From 32a360eca660c76c3620317b98e0b542ceaa6eae Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sat, 20 May 2017 15:26:21 +0200 Subject: [PATCH] Imported Upstream version 0.6.24+dfsg1 --- .gitignore | 38 + AUTHORS | 3 + COPYING | 340 + ChangeLog | 185 + INSTALL | 236 + Makefile.in | 183 + README | 10 + THANKS | 85 + config.guess | 1526 ++++ config.sub | 1658 ++++ configure | 7104 +++++++++++++++++ configure.ac | 313 + contrib/pnp4nagios-gearman.spec | 62 + contrib/pnp4nagios.spec | 128 + contrib/ssi/status-header.ssi.in | 9 + helpers/kohana-install.sh | 16 + helpers/wiki2html.sh | 42 + include/broker.h | 222 + include/common.h | 500 ++ include/config.h.in | 177 + include/global.h | 4 + include/locations.h | 43 + include/nagios.h | 812 ++ include/nebcallbacks.h | 88 + include/nebmodules.h | 102 + include/nebstructs.h | 533 ++ include/npcdmod.h | 41 + include/objects.h | 771 ++ include/pnp.h | 126 + install-sh | 323 + lib/Makefile.in | 305 + lib/kohana/system/config/cache.php | 32 + lib/kohana/system/config/cache_memcache.php | 20 + lib/kohana/system/config/cache_sqlite.php | 10 + lib/kohana/system/config/cache_xcache.php | 12 + lib/kohana/system/config/captcha.php | 29 + lib/kohana/system/config/cookie.php | 32 + lib/kohana/system/config/credit_cards.php | 60 + lib/kohana/system/config/database.php | 45 + lib/kohana/system/config/email.php | 22 + lib/kohana/system/config/encryption.php | 31 + lib/kohana/system/config/http.php | 19 + lib/kohana/system/config/image.php | 13 + lib/kohana/system/config/inflector.php | 58 + lib/kohana/system/config/locale.php | 16 + lib/kohana/system/config/mimes.php | 224 + lib/kohana/system/config/pagination.php | 25 + lib/kohana/system/config/profiler.php | 8 + lib/kohana/system/config/routes.php | 7 + lib/kohana/system/config/session.php | 47 + lib/kohana/system/config/sql_types.php | 58 + lib/kohana/system/config/upload.php | 17 + lib/kohana/system/config/user_agents.php | 112 + lib/kohana/system/config/view.php | 17 + lib/kohana/system/controllers/captcha.php | 23 + lib/kohana/system/controllers/template.php | 54 + lib/kohana/system/core/Benchmark.php | 125 + lib/kohana/system/core/Bootstrap.php | 58 + lib/kohana/system/core/Event.php | 232 + lib/kohana/system/core/Kohana.php | 1790 +++++ lib/kohana/system/core/utf8.php | 743 ++ lib/kohana/system/core/utf8/from_unicode.php | 68 + lib/kohana/system/core/utf8/ltrim.php | 22 + lib/kohana/system/core/utf8/ord.php | 88 + lib/kohana/system/core/utf8/rtrim.php | 22 + lib/kohana/system/core/utf8/str_ireplace.php | 70 + lib/kohana/system/core/utf8/str_pad.php | 54 + lib/kohana/system/core/utf8/str_split.php | 33 + lib/kohana/system/core/utf8/strcasecmp.php | 19 + lib/kohana/system/core/utf8/strcspn.php | 30 + lib/kohana/system/core/utf8/stristr.php | 28 + lib/kohana/system/core/utf8/strlen.php | 21 + lib/kohana/system/core/utf8/strpos.php | 30 + lib/kohana/system/core/utf8/strrev.php | 18 + lib/kohana/system/core/utf8/strrpos.php | 30 + lib/kohana/system/core/utf8/strspn.php | 30 + lib/kohana/system/core/utf8/strtolower.php | 84 + lib/kohana/system/core/utf8/strtoupper.php | 84 + lib/kohana/system/core/utf8/substr.php | 75 + .../system/core/utf8/substr_replace.php | 22 + lib/kohana/system/core/utf8/to_unicode.php | 141 + .../core/utf8/transliterate_to_ascii.php | 77 + lib/kohana/system/core/utf8/trim.php | 17 + lib/kohana/system/core/utf8/ucfirst.php | 18 + lib/kohana/system/core/utf8/ucwords.php | 26 + lib/kohana/system/fonts/DejaVuSerif.ttf | Bin 0 -> 305632 bytes lib/kohana/system/fonts/LICENSE | 99 + lib/kohana/system/helpers/arr.php | 312 + lib/kohana/system/helpers/cookie.php | 84 + lib/kohana/system/helpers/date.php | 405 + lib/kohana/system/helpers/download.php | 105 + lib/kohana/system/helpers/email.php | 181 + lib/kohana/system/helpers/expires.php | 111 + lib/kohana/system/helpers/feed.php | 122 + lib/kohana/system/helpers/file.php | 186 + lib/kohana/system/helpers/form.php | 542 ++ lib/kohana/system/helpers/format.php | 66 + lib/kohana/system/helpers/html.php | 446 ++ lib/kohana/system/helpers/inflector.php | 193 + lib/kohana/system/helpers/num.php | 26 + lib/kohana/system/helpers/remote.php | 66 + lib/kohana/system/helpers/request.php | 239 + lib/kohana/system/helpers/security.php | 47 + lib/kohana/system/helpers/text.php | 410 + lib/kohana/system/helpers/upload.php | 162 + lib/kohana/system/helpers/url.php | 252 + lib/kohana/system/helpers/valid.php | 330 + lib/kohana/system/i18n/de_DE/cache.php | 10 + lib/kohana/system/i18n/de_DE/calendar.php | 59 + lib/kohana/system/i18n/de_DE/captcha.php | 33 + lib/kohana/system/i18n/de_DE/core.php | 34 + lib/kohana/system/i18n/de_DE/database.php | 15 + lib/kohana/system/i18n/de_DE/encrypt.php | 8 + lib/kohana/system/i18n/de_DE/errors.php | 16 + lib/kohana/system/i18n/de_DE/event.php | 7 + lib/kohana/system/i18n/de_DE/image.php | 33 + lib/kohana/system/i18n/de_DE/orm.php | 3 + lib/kohana/system/i18n/de_DE/pagination.php | 15 + lib/kohana/system/i18n/de_DE/profiler.php | 15 + lib/kohana/system/i18n/de_DE/session.php | 6 + lib/kohana/system/i18n/de_DE/swift.php | 6 + lib/kohana/system/i18n/de_DE/upload.php | 6 + lib/kohana/system/i18n/de_DE/validation.php | 41 + lib/kohana/system/i18n/en_US/cache.php | 10 + lib/kohana/system/i18n/en_US/calendar.php | 59 + lib/kohana/system/i18n/en_US/captcha.php | 33 + lib/kohana/system/i18n/en_US/core.php | 34 + lib/kohana/system/i18n/en_US/database.php | 15 + lib/kohana/system/i18n/en_US/encrypt.php | 8 + lib/kohana/system/i18n/en_US/errors.php | 15 + lib/kohana/system/i18n/en_US/event.php | 7 + lib/kohana/system/i18n/en_US/image.php | 33 + lib/kohana/system/i18n/en_US/orm.php | 3 + lib/kohana/system/i18n/en_US/pagination.php | 15 + lib/kohana/system/i18n/en_US/profiler.php | 15 + lib/kohana/system/i18n/en_US/session.php | 6 + lib/kohana/system/i18n/en_US/swift.php | 6 + lib/kohana/system/i18n/en_US/upload.php | 6 + lib/kohana/system/i18n/en_US/validation.php | 41 + lib/kohana/system/i18n/es_ES/cache.php | 10 + lib/kohana/system/i18n/es_ES/calendar.php | 55 + lib/kohana/system/i18n/es_ES/captcha.php | 33 + lib/kohana/system/i18n/es_ES/core.php | 34 + lib/kohana/system/i18n/es_ES/database.php | 15 + lib/kohana/system/i18n/es_ES/encrypt.php | 8 + lib/kohana/system/i18n/es_ES/errors.php | 16 + lib/kohana/system/i18n/es_ES/event.php | 7 + lib/kohana/system/i18n/es_ES/image.php | 33 + lib/kohana/system/i18n/es_ES/orm.php | 3 + lib/kohana/system/i18n/es_ES/pagination.php | 15 + lib/kohana/system/i18n/es_ES/profiler.php | 15 + lib/kohana/system/i18n/es_ES/session.php | 6 + lib/kohana/system/i18n/es_ES/swift.php | 6 + lib/kohana/system/i18n/es_ES/upload.php | 6 + lib/kohana/system/i18n/es_ES/validation.php | 41 + lib/kohana/system/i18n/fr_FR/cache.php | 10 + lib/kohana/system/i18n/fr_FR/calendar.php | 59 + lib/kohana/system/i18n/fr_FR/captcha.php | 33 + lib/kohana/system/i18n/fr_FR/core.php | 34 + lib/kohana/system/i18n/fr_FR/database.php | 15 + lib/kohana/system/i18n/fr_FR/encrypt.php | 8 + lib/kohana/system/i18n/fr_FR/errors.php | 16 + lib/kohana/system/i18n/fr_FR/event.php | 7 + lib/kohana/system/i18n/fr_FR/image.php | 33 + lib/kohana/system/i18n/fr_FR/orm.php | 3 + lib/kohana/system/i18n/fr_FR/pagination.php | 15 + lib/kohana/system/i18n/fr_FR/profiler.php | 15 + lib/kohana/system/i18n/fr_FR/session.php | 6 + lib/kohana/system/i18n/fr_FR/swift.php | 6 + lib/kohana/system/i18n/fr_FR/upload.php | 6 + lib/kohana/system/i18n/fr_FR/validation.php | 41 + lib/kohana/system/i18n/it_IT/cache.php | 10 + lib/kohana/system/i18n/it_IT/calendar.php | 59 + lib/kohana/system/i18n/it_IT/captcha.php | 33 + lib/kohana/system/i18n/it_IT/core.php | 34 + lib/kohana/system/i18n/it_IT/database.php | 15 + lib/kohana/system/i18n/it_IT/encrypt.php | 8 + lib/kohana/system/i18n/it_IT/errors.php | 16 + lib/kohana/system/i18n/it_IT/event.php | 7 + lib/kohana/system/i18n/it_IT/image.php | 33 + lib/kohana/system/i18n/it_IT/orm.php | 3 + lib/kohana/system/i18n/it_IT/pagination.php | 15 + lib/kohana/system/i18n/it_IT/profiler.php | 15 + lib/kohana/system/i18n/it_IT/session.php | 6 + lib/kohana/system/i18n/it_IT/swift.php | 6 + lib/kohana/system/i18n/it_IT/upload.php | 6 + lib/kohana/system/i18n/it_IT/validation.php | 41 + lib/kohana/system/i18n/nl_NL/cache.php | 10 + lib/kohana/system/i18n/nl_NL/calendar.php | 59 + lib/kohana/system/i18n/nl_NL/captcha.php | 33 + lib/kohana/system/i18n/nl_NL/core.php | 34 + lib/kohana/system/i18n/nl_NL/database.php | 15 + lib/kohana/system/i18n/nl_NL/encrypt.php | 8 + lib/kohana/system/i18n/nl_NL/errors.php | 16 + lib/kohana/system/i18n/nl_NL/event.php | 7 + lib/kohana/system/i18n/nl_NL/image.php | 27 + lib/kohana/system/i18n/nl_NL/orm.php | 3 + lib/kohana/system/i18n/nl_NL/pagination.php | 15 + lib/kohana/system/i18n/nl_NL/profiler.php | 15 + lib/kohana/system/i18n/nl_NL/session.php | 6 + lib/kohana/system/i18n/nl_NL/swift.php | 6 + lib/kohana/system/i18n/nl_NL/upload.php | 6 + lib/kohana/system/i18n/nl_NL/validation.php | 39 + lib/kohana/system/i18n/ru_RU/cache.php | 10 + lib/kohana/system/i18n/ru_RU/calendar.php | 59 + lib/kohana/system/i18n/ru_RU/captcha.php | 33 + lib/kohana/system/i18n/ru_RU/core.php | 34 + lib/kohana/system/i18n/ru_RU/database.php | 15 + lib/kohana/system/i18n/ru_RU/encrypt.php | 8 + lib/kohana/system/i18n/ru_RU/errors.php | 16 + lib/kohana/system/i18n/ru_RU/event.php | 7 + lib/kohana/system/i18n/ru_RU/image.php | 28 + lib/kohana/system/i18n/ru_RU/orm.php | 3 + lib/kohana/system/i18n/ru_RU/pagination.php | 15 + lib/kohana/system/i18n/ru_RU/profiler.php | 15 + lib/kohana/system/i18n/ru_RU/session.php | 6 + lib/kohana/system/i18n/ru_RU/swift.php | 6 + lib/kohana/system/i18n/ru_RU/upload.php | 23 + lib/kohana/system/i18n/ru_RU/validation.php | 39 + lib/kohana/system/libraries/Cache.php | 208 + lib/kohana/system/libraries/Calendar.php | 362 + .../system/libraries/Calendar_Event.php | 307 + lib/kohana/system/libraries/Captcha.php | 279 + lib/kohana/system/libraries/Controller.php | 86 + lib/kohana/system/libraries/Database.php | 1444 ++++ .../system/libraries/Database_Expression.php | 26 + lib/kohana/system/libraries/Encrypt.php | 164 + .../system/libraries/Event_Observer.php | 70 + lib/kohana/system/libraries/Event_Subject.php | 67 + lib/kohana/system/libraries/Image.php | 431 + lib/kohana/system/libraries/Input.php | 452 ++ lib/kohana/system/libraries/Model.php | 31 + lib/kohana/system/libraries/ORM.php | 1431 ++++ lib/kohana/system/libraries/ORM_Iterator.php | 228 + lib/kohana/system/libraries/ORM_Tree.php | 76 + lib/kohana/system/libraries/ORM_Versioned.php | 143 + lib/kohana/system/libraries/Pagination.php | 236 + lib/kohana/system/libraries/Profiler.php | 271 + .../system/libraries/Profiler_Table.php | 69 + lib/kohana/system/libraries/Router.php | 304 + lib/kohana/system/libraries/Session.php | 457 ++ lib/kohana/system/libraries/Tagcloud.php | 130 + lib/kohana/system/libraries/URI.php | 279 + lib/kohana/system/libraries/Validation.php | 826 ++ lib/kohana/system/libraries/View.php | 309 + lib/kohana/system/libraries/drivers/Cache.php | 40 + .../system/libraries/drivers/Cache/Apc.php | 64 + .../libraries/drivers/Cache/Eaccelerator.php | 66 + .../system/libraries/drivers/Cache/File.php | 261 + .../libraries/drivers/Cache/Memcache.php | 191 + .../system/libraries/drivers/Cache/Sqlite.php | 257 + .../system/libraries/drivers/Cache/Xcache.php | 119 + .../system/libraries/drivers/Captcha.php | 227 + .../libraries/drivers/Captcha/Alpha.php | 92 + .../libraries/drivers/Captcha/Basic.php | 81 + .../libraries/drivers/Captcha/Black.php | 72 + .../system/libraries/drivers/Captcha/Math.php | 61 + .../libraries/drivers/Captcha/Riddle.php | 47 + .../system/libraries/drivers/Captcha/Word.php | 37 + .../system/libraries/drivers/Database.php | 636 ++ .../libraries/drivers/Database/Mssql.php | 462 ++ .../libraries/drivers/Database/Mysql.php | 496 ++ .../libraries/drivers/Database/Mysqli.php | 358 + .../libraries/drivers/Database/Pdosqlite.php | 486 ++ .../libraries/drivers/Database/Pgsql.php | 538 ++ lib/kohana/system/libraries/drivers/Image.php | 149 + .../system/libraries/drivers/Image/GD.php | 379 + .../drivers/Image/GraphicsMagick.php | 211 + .../libraries/drivers/Image/ImageMagick.php | 212 + .../system/libraries/drivers/Session.php | 70 + .../libraries/drivers/Session/Cache.php | 105 + .../libraries/drivers/Session/Cookie.php | 80 + .../libraries/drivers/Session/Database.php | 163 + lib/kohana/system/views/kohana/template.php | 36 + lib/kohana/system/views/kohana_calendar.php | 52 + .../system/views/kohana_error_disabled.php | 17 + lib/kohana/system/views/kohana_error_page.php | 27 + lib/kohana/system/views/kohana_errors.css | 21 + lib/kohana/system/views/kohana_profiler.php | 37 + .../system/views/kohana_profiler_table.css | 53 + .../system/views/kohana_profiler_table.php | 25 + .../system/views/pagination/classic.php | 39 + lib/kohana/system/views/pagination/digg.php | 83 + .../system/views/pagination/extended.php | 27 + lib/kohana/system/views/pagination/punbb.php | 37 + man/Makefile.in | 23 + man/npcd.8.in | 38 + sample-config/Makefile.in | 84 + sample-config/httpd.conf.in | 30 + sample-config/lighttpd.pnp4nagios.conf.in | 20 + sample-config/misccommands.cfg-sample.in | 44 + sample-config/nagios.cfg-sample.in | 42 + sample-config/nginx.pnp4nagios.conf.in | 34 + sample-config/pnp/background-letter.pdf | Bin 0 -> 237627 bytes sample-config/pnp/background.pdf | Bin 0 -> 29383 bytes .../check_all_local_disks.cfg-sample | 45 + .../pnp/check_commands/check_nrpe.cfg-sample | 46 + .../check_commands/check_nwstat.cfg-sample | 46 + sample-config/pnp/config.php.in | 275 + sample-config/pnp/npcd.cfg-sample.in | 195 + .../pnp/pages/web_traffic.cfg-sample | 23 + sample-config/pnp/pnp4nagios_release.in | 8 + .../pnp/process_perfdata.cfg-sample.in | 135 + sample-config/pnp/rra.cfg-sample | 36 + scripts/Makefile.in | 52 + scripts/check_pnp_rrds.pl.in | 298 + scripts/process_perfdata.pl.in | 1596 ++++ scripts/rc.npcd.in | 162 + scripts/rc.pnp_gearman_worker.in | 113 + scripts/rrd_convert.pl.in | 555 ++ scripts/rrd_modify.pl.in | 282 + scripts/verify_pnp_config_v2.pl | 1009 +++ share/Makefile.in | 172 + share/pnp/application/config/config.php | 142 + share/pnp/application/config/locale.php | 16 + share/pnp/application/config/routes.php | 7 + share/pnp/application/config/session.php | 47 + share/pnp/application/controllers/ajax.php | 148 + share/pnp/application/controllers/color.php | 26 + share/pnp/application/controllers/debug.php | 66 + share/pnp/application/controllers/docs.php | 80 + share/pnp/application/controllers/graph.php | 129 + share/pnp/application/controllers/image.php | 56 + share/pnp/application/controllers/json.php | 75 + share/pnp/application/controllers/mobile.php | 93 + share/pnp/application/controllers/page.php | 80 + share/pnp/application/controllers/pdf.php | 280 + share/pnp/application/controllers/popup.php | 41 + share/pnp/application/controllers/special.php | 52 + share/pnp/application/controllers/start.php | 21 + share/pnp/application/controllers/system.php | 210 + share/pnp/application/controllers/xml.php | 48 + share/pnp/application/controllers/xport.php | 74 + share/pnp/application/controllers/zoom.php | 80 + share/pnp/application/helpers/nagios.php | 58 + share/pnp/application/helpers/pnp.php | 150 + share/pnp/application/helpers/rrd.php | 459 ++ share/pnp/application/i18n/de_DE/common.php | 59 + share/pnp/application/i18n/de_DE/error.php | 32 + share/pnp/application/i18n/en_US/common.php | 59 + share/pnp/application/i18n/en_US/error.php | 32 + share/pnp/application/i18n/es_ES/common.php | 58 + share/pnp/application/i18n/es_ES/error.php | 32 + share/pnp/application/i18n/fr_FR/common.php | 59 + share/pnp/application/i18n/fr_FR/error.php | 32 + share/pnp/application/i18n/ru_RU/common.php | 59 + share/pnp/application/i18n/ru_RU/error.php | 32 + share/pnp/application/lib/json.php | 806 ++ share/pnp/application/lib/jsonwrapper.php | 6 + .../pnp/application/lib/jsonwrapper_inner.php | 23 + share/pnp/application/models/auth.php | 154 + .../pnp/application/models/auth_multisite.php | 111 + share/pnp/application/models/config.php | 88 + share/pnp/application/models/data.php | 1115 +++ share/pnp/application/models/rrdtool.php | 243 + share/pnp/application/models/system.php | 14 + .../vendor/fpdf/filters/FilterASCII85.php | 98 + .../fpdf/filters/FilterASCII85_FPDI.php | 33 + .../vendor/fpdf/filters/FilterLZW.php | 154 + .../vendor/fpdf/filters/FilterLZW_FPDI.php | 33 + .../application/vendor/fpdf/font/courier.php | 7 + .../vendor/fpdf/font/helvetica.php | 15 + .../vendor/fpdf/font/helveticab.php | 15 + .../vendor/fpdf/font/helveticabi.php | 15 + .../vendor/fpdf/font/helveticai.php | 15 + .../application/vendor/fpdf/font/symbol.php | 15 + .../application/vendor/fpdf/font/times.php | 15 + .../application/vendor/fpdf/font/timesb.php | 15 + .../application/vendor/fpdf/font/timesbi.php | 15 + .../application/vendor/fpdf/font/timesi.php | 15 + .../vendor/fpdf/font/zapfdingbats.php | 15 + share/pnp/application/vendor/fpdf/fpdf.php | 1732 ++++ .../pnp/application/vendor/fpdf/fpdf_tpl.php | 409 + share/pnp/application/vendor/fpdf/fpdi.php | 505 ++ .../vendor/fpdf/fpdi2tcpdf_bridge.php | 171 + .../vendor/fpdf/fpdi_pdf_parser.php | 384 + share/pnp/application/vendor/fpdf/license.txt | 6 + .../application/vendor/fpdf/pdf_context.php | 97 + .../application/vendor/fpdf/pdf_parser.php | 706 ++ share/pnp/application/views/basket_box.php | 32 + share/pnp/application/views/color.php | 38 + share/pnp/application/views/color_box.php | 15 + share/pnp/application/views/debug.php | 74 + share/pnp/application/views/docs.php | 31 + share/pnp/application/views/docs_box.php | 28 + share/pnp/application/views/graph.php | 56 + share/pnp/application/views/graph_content.php | 102 + .../views/graph_content_special.php | 53 + share/pnp/application/views/graph_tiny.php | 19 + share/pnp/application/views/header.php | 4 + share/pnp/application/views/host_box.php | 11 + share/pnp/application/views/icon_box.php | 39 + .../application/views/kohana_error_page.php | 77 + share/pnp/application/views/logo_box.php | 9 + share/pnp/application/views/mobile.php | 51 + share/pnp/application/views/mobile_about.php | 3 + share/pnp/application/views/mobile_graph.php | 43 + .../views/mobile_graph_special.php | 33 + share/pnp/application/views/mobile_home.php | 17 + share/pnp/application/views/mobile_host.php | 30 + .../pnp/application/views/mobile_overview.php | 14 + share/pnp/application/views/mobile_pages.php | 10 + share/pnp/application/views/mobile_search.php | 24 + .../pnp/application/views/mobile_special.php | 9 + share/pnp/application/views/multisite_box.php | 17 + share/pnp/application/views/page.php | 48 + share/pnp/application/views/pages_box.php | 29 + share/pnp/application/views/popup.php | 10 + share/pnp/application/views/search_box.php | 22 + share/pnp/application/views/service_box.php | 36 + .../views/special_templates_box.php | 31 + share/pnp/application/views/status_box.php | 19 + share/pnp/application/views/template.php | 221 + share/pnp/application/views/timerange_box.php | 26 + .../application/views/timerange_select.php | 37 + .../application/views/widget_graph.sample.php | 10 + .../application/views/widget_menu.sample.php | 10 + share/pnp/application/views/zoom.php | 129 + share/pnp/application/views/zoom_header.php | 4 + share/pnp/documents/_media/bulk-npcd.png | Bin 0 -> 82168 bytes share/pnp/documents/_media/bulk-npcdmod.png | Bin 0 -> 87067 bytes share/pnp/documents/_media/bulk.png | Bin 0 -> 66790 bytes share/pnp/documents/_media/gearman.png | Bin 0 -> 87928 bytes share/pnp/documents/_media/mobile-graphs.png | Bin 0 -> 281741 bytes share/pnp/documents/_media/mobile-home.png | Bin 0 -> 143788 bytes .../pnp/documents/_media/mobile-hostlist.png | Bin 0 -> 125986 bytes share/pnp/documents/_media/mobile-loading.png | Bin 0 -> 150565 bytes .../documents/_media/mobile-servicelist.png | Bin 0 -> 151081 bytes .../documents/_media/nagiospowered-72x72.png | Bin 0 -> 3954 bytes .../_media/pnp-preview-05-08-2009.png | Bin 0 -> 148576 bytes share/pnp/documents/_media/popup.png | Bin 0 -> 148775 bytes share/pnp/documents/_media/srv_info.png | Bin 0 -> 31102 bytes share/pnp/documents/_media/synchronous.png | Bin 0 -> 49349 bytes share/pnp/documents/de_DE/about.html | 186 + share/pnp/documents/de_DE/advanced.html | 81 + share/pnp/documents/de_DE/config.html | 423 + share/pnp/documents/de_DE/doc_complete.html | 3369 ++++++++ share/pnp/documents/de_DE/dwnld.html | 1 + share/pnp/documents/de_DE/install.html | 208 + share/pnp/documents/de_DE/mobile.html | 89 + share/pnp/documents/de_DE/modes.html | 152 + share/pnp/documents/de_DE/new-features.html | 67 + share/pnp/documents/de_DE/npcd.html | 323 + share/pnp/documents/de_DE/pages.html | 93 + .../pnp/documents/de_DE/perfdata_format.html | 62 + share/pnp/documents/de_DE/rrd_convert.html | 84 + share/pnp/documents/de_DE/rrdcached.html | 153 + share/pnp/documents/de_DE/start.html | 199 + share/pnp/documents/de_DE/timeranges.html | 96 + share/pnp/documents/de_DE/tpl.html | 243 + share/pnp/documents/de_DE/tpl_custom.html | 326 + share/pnp/documents/de_DE/tpl_helper.html | 246 + share/pnp/documents/de_DE/tpl_helper_pnp.html | 91 + share/pnp/documents/de_DE/tpl_special.html | 188 + share/pnp/documents/de_DE/upgrade.html | 218 + share/pnp/documents/de_DE/verify.html | 133 + .../documents/de_DE/verify_pnp_config.html | 153 + share/pnp/documents/de_DE/webfe.html | 149 + share/pnp/documents/de_DE/webfe_cfg.html | 142 + share/pnp/documents/de_DE/wrapper.html | 30 + share/pnp/documents/de_DE/xport.html | 43 + share/pnp/documents/en_US/about.html | 186 + share/pnp/documents/en_US/advanced.html | 73 + share/pnp/documents/en_US/config.html | 395 + share/pnp/documents/en_US/doc_complete.html | 3744 +++++++++ share/pnp/documents/en_US/dwnld.html | 478 ++ share/pnp/documents/en_US/install.html | 213 + share/pnp/documents/en_US/mobile.html | 89 + share/pnp/documents/en_US/modes.html | 145 + share/pnp/documents/en_US/new-features.html | 61 + share/pnp/documents/en_US/npcd.html | 323 + share/pnp/documents/en_US/pages.html | 91 + .../pnp/documents/en_US/perfdata_format.html | 61 + share/pnp/documents/en_US/rrd_convert.html | 88 + share/pnp/documents/en_US/rrdcached.html | 154 + share/pnp/documents/en_US/start.html | 194 + share/pnp/documents/en_US/timeranges.html | 87 + share/pnp/documents/en_US/tpl.html | 240 + share/pnp/documents/en_US/tpl_custom.html | 323 + share/pnp/documents/en_US/tpl_helper.html | 247 + share/pnp/documents/en_US/tpl_helper_pnp.html | 90 + share/pnp/documents/en_US/tpl_special.html | 187 + share/pnp/documents/en_US/upgrade.html | 220 + share/pnp/documents/en_US/verify.html | 115 + .../documents/en_US/verify_pnp_config.html | 132 + share/pnp/documents/en_US/webfe.html | 149 + share/pnp/documents/en_US/webfe_cfg.html | 136 + share/pnp/documents/en_US/wrapper.html | 30 + share/pnp/documents/en_US/xport.html | 44 + share/pnp/documents/images/smileys/delete.gif | Bin 0 -> 1421 bytes share/pnp/documents/images/smileys/fixme.gif | Bin 0 -> 1435 bytes .../documents/images/smileys/icon_arrow.gif | Bin 0 -> 170 bytes .../documents/images/smileys/icon_biggrin.gif | Bin 0 -> 172 bytes .../images/smileys/icon_confused.gif | Bin 0 -> 171 bytes .../documents/images/smileys/icon_cool.gif | Bin 0 -> 172 bytes .../pnp/documents/images/smileys/icon_cry.gif | Bin 0 -> 498 bytes .../documents/images/smileys/icon_doubt.gif | Bin 0 -> 990 bytes .../documents/images/smileys/icon_doubt2.gif | Bin 0 -> 992 bytes .../pnp/documents/images/smileys/icon_eek.gif | Bin 0 -> 170 bytes .../documents/images/smileys/icon_evil.gif | Bin 0 -> 236 bytes .../documents/images/smileys/icon_exclaim.gif | Bin 0 -> 236 bytes .../documents/images/smileys/icon_frown.gif | Bin 0 -> 171 bytes .../pnp/documents/images/smileys/icon_fun.gif | Bin 0 -> 590 bytes .../documents/images/smileys/icon_idea.gif | Bin 0 -> 176 bytes .../documents/images/smileys/icon_kaddi.gif | Bin 0 -> 991 bytes .../pnp/documents/images/smileys/icon_lol.gif | Bin 0 -> 336 bytes .../documents/images/smileys/icon_mrgreen.gif | Bin 0 -> 349 bytes .../documents/images/smileys/icon_neutral.gif | Bin 0 -> 171 bytes .../images/smileys/icon_question.gif | Bin 0 -> 248 bytes .../documents/images/smileys/icon_razz.gif | Bin 0 -> 176 bytes .../documents/images/smileys/icon_redface.gif | Bin 0 -> 650 bytes .../images/smileys/icon_rolleyes.gif | Bin 0 -> 485 bytes .../pnp/documents/images/smileys/icon_sad.gif | Bin 0 -> 171 bytes .../images/smileys/icon_silenced.gif | Bin 0 -> 231 bytes .../documents/images/smileys/icon_smile.gif | Bin 0 -> 174 bytes .../documents/images/smileys/icon_smile2.gif | Bin 0 -> 174 bytes .../images/smileys/icon_surprised.gif | Bin 0 -> 174 bytes .../documents/images/smileys/icon_twisted.gif | Bin 0 -> 238 bytes .../documents/images/smileys/icon_wink.gif | Bin 0 -> 170 bytes share/pnp/index.php.in | 148 + share/pnp/install.php.in | 211 + share/pnp/media/css/autocomplete.css | 6 + share/pnp/media/css/border-h.gif | Bin 0 -> 72 bytes share/pnp/media/css/border-v.gif | Bin 0 -> 72 bytes share/pnp/media/css/common.css | 206 + share/pnp/media/css/images/ajax-loader.png | Bin 0 -> 503 bytes .../media/css/images/icon-search-black.png | Bin 0 -> 1245 bytes share/pnp/media/css/images/icons-18-black.png | Bin 0 -> 2138 bytes share/pnp/media/css/images/icons-18-white.png | Bin 0 -> 2207 bytes share/pnp/media/css/images/icons-36-black.png | Bin 0 -> 4011 bytes share/pnp/media/css/images/icons-36-white.png | Bin 0 -> 4343 bytes share/pnp/media/css/imgareaselect-default.css | 41 + share/pnp/media/css/mobile.css | 10 + share/pnp/media/css/shadow.png | Bin 0 -> 3403 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../pnp/media/css/ui-lightness/jquery-ui.css | 563 ++ .../images/contentframe_background.jpg | Bin 0 -> 98551 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_6da1b8_40x100.png | Bin 0 -> 182 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_88b9ce_1x400.png | Bin 0 -> 125 bytes .../images/ui-bg_glass_75_6da1b8_1x400.png | Bin 0 -> 136 bytes .../images/ui-bg_glass_75_94cde6_1x400.png | Bin 0 -> 177 bytes .../ui-bg_highlight-soft_75_274554_1x100.png | Bin 0 -> 132 bytes .../ui-bg_highlight-soft_75_6da1b8_1x100.png | Bin 0 -> 130 bytes .../ui-bg_inset-soft_95_fef1ec_1x100.png | Bin 0 -> 123 bytes .../images/ui-icons_000000_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../pnp/media/css/ui-multisite/jquery-ui.css | 569 ++ .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes share/pnp/media/css/ui-redmond/jquery-ui.css | 563 ++ .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../pnp/media/css/ui-smoothness/jquery-ui.css | 563 ++ share/pnp/media/images/1x1.gif | Bin 0 -> 42 bytes share/pnp/media/images/add.png | Bin 0 -> 1447 bytes share/pnp/media/images/back.png | Bin 0 -> 6403 bytes share/pnp/media/images/calendar.png | Bin 0 -> 5411 bytes share/pnp/media/images/color.png | Bin 0 -> 11493 bytes share/pnp/media/images/de_DE.png | Bin 0 -> 3793 bytes share/pnp/media/images/docs.png | Bin 0 -> 5835 bytes share/pnp/media/images/en_US.png | Bin 0 -> 9270 bytes share/pnp/media/images/favicon.ico | Bin 0 -> 4286 bytes share/pnp/media/images/go-left.png | Bin 0 -> 1649 bytes share/pnp/media/images/go-now.png | Bin 0 -> 1660 bytes share/pnp/media/images/go-right.png | Bin 0 -> 1652 bytes share/pnp/media/images/graph.png | Bin 0 -> 18017 bytes share/pnp/media/images/home.png | Bin 0 -> 6263 bytes share/pnp/media/images/int.gif | Bin 0 -> 80 bytes share/pnp/media/images/int2.gif | Bin 0 -> 80 bytes share/pnp/media/images/loader.gif | Bin 0 -> 432 bytes share/pnp/media/images/notify.gif | Bin 0 -> 947 bytes share/pnp/media/images/pages.png | Bin 0 -> 7175 bytes share/pnp/media/images/pdf.png | Bin 0 -> 5949 bytes share/pnp/media/images/pnp.png | Bin 0 -> 272 bytes share/pnp/media/images/remove.png | Bin 0 -> 792 bytes share/pnp/media/images/rrdtool.png | Bin 0 -> 420 bytes share/pnp/media/images/special.png | Bin 0 -> 5575 bytes share/pnp/media/images/stats.png | Bin 0 -> 6736 bytes share/pnp/media/images/trends.gif | Bin 0 -> 870 bytes share/pnp/media/images/view-calendar.png | Bin 0 -> 1293 bytes share/pnp/media/images/xml.png | Bin 0 -> 6757 bytes share/pnp/media/images/zoom.png | Bin 0 -> 810 bytes .../media/js/jquery-ui-timepicker-addon.js | 1276 +++ share/pnp/media/js/jquery.cluetip.js | 558 ++ .../media/js/jquery.imgareaselect.Debian.txt | 14 + share/pnp/media/js/jquery.imgareaselect.js | 730 ++ share/pnp/templates.dist/check-host-alive.php | 1 + .../pnp/templates.dist/check_apachestatus.php | 117 + .../check_apachestatus_auto.php | 101 + .../check_dell_bladechassis.php | 140 + share/pnp/templates.dist/check_disk.php | 64 + share/pnp/templates.dist/check_dns.php | 24 + share/pnp/templates.dist/check_esx3.php | 105 + share/pnp/templates.dist/check_fping.php | 65 + share/pnp/templates.dist/check_gearman.php | 36 + .../templates.dist/check_hp_bladechassis.php | 42 + share/pnp/templates.dist/check_hpasm.php | 42 + share/pnp/templates.dist/check_http.php | 42 + share/pnp/templates.dist/check_icmp.php | 1 + .../check_iftraffic_counter.php | 17 + .../templates.dist/check_iftraffic_pct.php | 18 + .../check_jmx4perl_connector_errors.php | 21 + .../check_jmx4perl_connector_nr_requests.php | 21 + .../check_jmx4perl_connector_proc_time.php | 16 + .../check_jmx4perl_connector_received.php | 21 + .../check_jmx4perl_connector_sent.php | 21 + .../check_jmx4perl_connector_threads.php | 21 + .../check_jmx4perl_memory_gc_count.php | 21 + .../check_jmx4perl_memory_gc_time.php | 16 + .../check_jmx4perl_memory_heap.php | 21 + .../check_jmx4perl_thread_count.php | 21 + .../check_jmx4perl_thread_increase.php | 21 + share/pnp/templates.dist/check_load.php | 26 + share/pnp/templates.dist/check_local_disk.php | 1 + share/pnp/templates.dist/check_local_load.php | 1 + .../pnp/templates.dist/check_messpc_temp.php | 23 + .../pnp/templates.dist/check_mssql_health.php | 364 + share/pnp/templates.dist/check_multi.php | 23 + .../templates.dist/check_multi_nagiostats.php | 104 + .../pnp/templates.dist/check_mysql_health.php | 400 + share/pnp/templates.dist/check_nt_cpu.php | 24 + share/pnp/templates.dist/check_nt_disk.php | 24 + share/pnp/templates.dist/check_nt_mem.php | 20 + share/pnp/templates.dist/check_ntp_time.php | 25 + .../pnp/templates.dist/check_nwstat_CONNS.php | 34 + .../pnp/templates.dist/check_nwstat_LOAD.php | 34 + .../pnp/templates.dist/check_nwstat_LOAD1.php | 1 + .../templates.dist/check_nwstat_LOAD15.php | 1 + .../pnp/templates.dist/check_nwstat_LOAD5.php | 1 + .../templates.dist/check_nwstat_ofiles.php | 34 + share/pnp/templates.dist/check_openmanage.php | 545 ++ .../check_oracle_connection-time.php | 15 + .../templates.dist/check_oracle_health.php | 34 + .../check_oracle_health_connection-time.php | 15 + ...oracle_health_pga-in-memory-sort-ratio.php | 15 + .../check_oracle_health_redo-io-traffic.php | 15 + .../check_oracle_health_switch-interval.php | 15 + .../check_oracle_health_tablespace-usage.php | 33 + share/pnp/templates.dist/check_ping.php | 44 + share/pnp/templates.dist/check_ping_tick.php | 47 + share/pnp/templates.dist/check_pnp_rrds.php | 27 + share/pnp/templates.dist/check_smtp.php | 1 + .../templates.dist/check_snmp_int-bits.php | 24 + share/pnp/templates.dist/check_snmp_int.php | 20 + share/pnp/templates.dist/check_swap.php | 26 + share/pnp/templates.dist/check_tcp.php | 1 + share/pnp/templates.dist/check_users.php | 24 + share/pnp/templates.dist/default.php | 92 + share/pnp/templates.dist/integer.php | 26 + share/pnp/templates.dist/nagiostats.php | 62 + share/pnp/templates.dist/pnp-runtime.php | 42 + share/pnp/templates.dist/response.php | 15 + share/pnp/templates.special/README | 1 + .../advanced_loop.php-sample | 34 + share/pnp/templates.special/loop.php-sample | 28 + share/pnp/templates.special/static.php-sample | 19 + src/Makefile.in | 137 + src/config.c | 584 ++ src/logging.c | 93 + src/module/modpnpsender.c | 297 + src/npcd.c | 572 ++ src/npcdmod.c | 598 ++ src/pnpsender.c | 384 + src/utils.c | 228 + subst.in | 142 + summary.in | 86 + 705 files changed, 87250 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.in create mode 100644 README create mode 100644 THANKS create mode 100755 config.guess create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100644 contrib/pnp4nagios-gearman.spec create mode 100644 contrib/pnp4nagios.spec create mode 100644 contrib/ssi/status-header.ssi.in create mode 100755 helpers/kohana-install.sh create mode 100755 helpers/wiki2html.sh create mode 100644 include/broker.h create mode 100644 include/common.h create mode 100644 include/config.h.in create mode 100644 include/global.h create mode 100644 include/locations.h create mode 100644 include/nagios.h create mode 100644 include/nebcallbacks.h create mode 100644 include/nebmodules.h create mode 100644 include/nebstructs.h create mode 100644 include/npcdmod.h create mode 100644 include/objects.h create mode 100644 include/pnp.h create mode 100755 install-sh create mode 100644 lib/Makefile.in create mode 100644 lib/kohana/system/config/cache.php create mode 100644 lib/kohana/system/config/cache_memcache.php create mode 100644 lib/kohana/system/config/cache_sqlite.php create mode 100644 lib/kohana/system/config/cache_xcache.php create mode 100644 lib/kohana/system/config/captcha.php create mode 100644 lib/kohana/system/config/cookie.php create mode 100644 lib/kohana/system/config/credit_cards.php create mode 100644 lib/kohana/system/config/database.php create mode 100644 lib/kohana/system/config/email.php create mode 100644 lib/kohana/system/config/encryption.php create mode 100644 lib/kohana/system/config/http.php create mode 100644 lib/kohana/system/config/image.php create mode 100644 lib/kohana/system/config/inflector.php create mode 100644 lib/kohana/system/config/locale.php create mode 100644 lib/kohana/system/config/mimes.php create mode 100644 lib/kohana/system/config/pagination.php create mode 100644 lib/kohana/system/config/profiler.php create mode 100644 lib/kohana/system/config/routes.php create mode 100644 lib/kohana/system/config/session.php create mode 100644 lib/kohana/system/config/sql_types.php create mode 100644 lib/kohana/system/config/upload.php create mode 100644 lib/kohana/system/config/user_agents.php create mode 100644 lib/kohana/system/config/view.php create mode 100644 lib/kohana/system/controllers/captcha.php create mode 100644 lib/kohana/system/controllers/template.php create mode 100644 lib/kohana/system/core/Benchmark.php create mode 100644 lib/kohana/system/core/Bootstrap.php create mode 100644 lib/kohana/system/core/Event.php create mode 100644 lib/kohana/system/core/Kohana.php create mode 100644 lib/kohana/system/core/utf8.php create mode 100644 lib/kohana/system/core/utf8/from_unicode.php create mode 100644 lib/kohana/system/core/utf8/ltrim.php create mode 100644 lib/kohana/system/core/utf8/ord.php create mode 100644 lib/kohana/system/core/utf8/rtrim.php create mode 100644 lib/kohana/system/core/utf8/str_ireplace.php create mode 100644 lib/kohana/system/core/utf8/str_pad.php create mode 100644 lib/kohana/system/core/utf8/str_split.php create mode 100644 lib/kohana/system/core/utf8/strcasecmp.php create mode 100644 lib/kohana/system/core/utf8/strcspn.php create mode 100644 lib/kohana/system/core/utf8/stristr.php create mode 100644 lib/kohana/system/core/utf8/strlen.php create mode 100644 lib/kohana/system/core/utf8/strpos.php create mode 100644 lib/kohana/system/core/utf8/strrev.php create mode 100644 lib/kohana/system/core/utf8/strrpos.php create mode 100644 lib/kohana/system/core/utf8/strspn.php create mode 100644 lib/kohana/system/core/utf8/strtolower.php create mode 100644 lib/kohana/system/core/utf8/strtoupper.php create mode 100644 lib/kohana/system/core/utf8/substr.php create mode 100644 lib/kohana/system/core/utf8/substr_replace.php create mode 100644 lib/kohana/system/core/utf8/to_unicode.php create mode 100644 lib/kohana/system/core/utf8/transliterate_to_ascii.php create mode 100644 lib/kohana/system/core/utf8/trim.php create mode 100644 lib/kohana/system/core/utf8/ucfirst.php create mode 100644 lib/kohana/system/core/utf8/ucwords.php create mode 100644 lib/kohana/system/fonts/DejaVuSerif.ttf create mode 100644 lib/kohana/system/fonts/LICENSE create mode 100644 lib/kohana/system/helpers/arr.php create mode 100644 lib/kohana/system/helpers/cookie.php create mode 100644 lib/kohana/system/helpers/date.php create mode 100644 lib/kohana/system/helpers/download.php create mode 100644 lib/kohana/system/helpers/email.php create mode 100644 lib/kohana/system/helpers/expires.php create mode 100644 lib/kohana/system/helpers/feed.php create mode 100644 lib/kohana/system/helpers/file.php create mode 100644 lib/kohana/system/helpers/form.php create mode 100644 lib/kohana/system/helpers/format.php create mode 100644 lib/kohana/system/helpers/html.php create mode 100644 lib/kohana/system/helpers/inflector.php create mode 100644 lib/kohana/system/helpers/num.php create mode 100644 lib/kohana/system/helpers/remote.php create mode 100644 lib/kohana/system/helpers/request.php create mode 100644 lib/kohana/system/helpers/security.php create mode 100644 lib/kohana/system/helpers/text.php create mode 100644 lib/kohana/system/helpers/upload.php create mode 100644 lib/kohana/system/helpers/url.php create mode 100644 lib/kohana/system/helpers/valid.php create mode 100644 lib/kohana/system/i18n/de_DE/cache.php create mode 100644 lib/kohana/system/i18n/de_DE/calendar.php create mode 100644 lib/kohana/system/i18n/de_DE/captcha.php create mode 100644 lib/kohana/system/i18n/de_DE/core.php create mode 100644 lib/kohana/system/i18n/de_DE/database.php create mode 100644 lib/kohana/system/i18n/de_DE/encrypt.php create mode 100644 lib/kohana/system/i18n/de_DE/errors.php create mode 100644 lib/kohana/system/i18n/de_DE/event.php create mode 100644 lib/kohana/system/i18n/de_DE/image.php create mode 100644 lib/kohana/system/i18n/de_DE/orm.php create mode 100644 lib/kohana/system/i18n/de_DE/pagination.php create mode 100644 lib/kohana/system/i18n/de_DE/profiler.php create mode 100644 lib/kohana/system/i18n/de_DE/session.php create mode 100644 lib/kohana/system/i18n/de_DE/swift.php create mode 100644 lib/kohana/system/i18n/de_DE/upload.php create mode 100644 lib/kohana/system/i18n/de_DE/validation.php create mode 100644 lib/kohana/system/i18n/en_US/cache.php create mode 100644 lib/kohana/system/i18n/en_US/calendar.php create mode 100644 lib/kohana/system/i18n/en_US/captcha.php create mode 100644 lib/kohana/system/i18n/en_US/core.php create mode 100644 lib/kohana/system/i18n/en_US/database.php create mode 100644 lib/kohana/system/i18n/en_US/encrypt.php create mode 100644 lib/kohana/system/i18n/en_US/errors.php create mode 100644 lib/kohana/system/i18n/en_US/event.php create mode 100644 lib/kohana/system/i18n/en_US/image.php create mode 100644 lib/kohana/system/i18n/en_US/orm.php create mode 100644 lib/kohana/system/i18n/en_US/pagination.php create mode 100644 lib/kohana/system/i18n/en_US/profiler.php create mode 100644 lib/kohana/system/i18n/en_US/session.php create mode 100644 lib/kohana/system/i18n/en_US/swift.php create mode 100644 lib/kohana/system/i18n/en_US/upload.php create mode 100644 lib/kohana/system/i18n/en_US/validation.php create mode 100644 lib/kohana/system/i18n/es_ES/cache.php create mode 100644 lib/kohana/system/i18n/es_ES/calendar.php create mode 100644 lib/kohana/system/i18n/es_ES/captcha.php create mode 100644 lib/kohana/system/i18n/es_ES/core.php create mode 100644 lib/kohana/system/i18n/es_ES/database.php create mode 100644 lib/kohana/system/i18n/es_ES/encrypt.php create mode 100644 lib/kohana/system/i18n/es_ES/errors.php create mode 100644 lib/kohana/system/i18n/es_ES/event.php create mode 100644 lib/kohana/system/i18n/es_ES/image.php create mode 100644 lib/kohana/system/i18n/es_ES/orm.php create mode 100644 lib/kohana/system/i18n/es_ES/pagination.php create mode 100644 lib/kohana/system/i18n/es_ES/profiler.php create mode 100644 lib/kohana/system/i18n/es_ES/session.php create mode 100644 lib/kohana/system/i18n/es_ES/swift.php create mode 100644 lib/kohana/system/i18n/es_ES/upload.php create mode 100644 lib/kohana/system/i18n/es_ES/validation.php create mode 100644 lib/kohana/system/i18n/fr_FR/cache.php create mode 100644 lib/kohana/system/i18n/fr_FR/calendar.php create mode 100644 lib/kohana/system/i18n/fr_FR/captcha.php create mode 100644 lib/kohana/system/i18n/fr_FR/core.php create mode 100644 lib/kohana/system/i18n/fr_FR/database.php create mode 100644 lib/kohana/system/i18n/fr_FR/encrypt.php create mode 100644 lib/kohana/system/i18n/fr_FR/errors.php create mode 100644 lib/kohana/system/i18n/fr_FR/event.php create mode 100644 lib/kohana/system/i18n/fr_FR/image.php create mode 100644 lib/kohana/system/i18n/fr_FR/orm.php create mode 100644 lib/kohana/system/i18n/fr_FR/pagination.php create mode 100644 lib/kohana/system/i18n/fr_FR/profiler.php create mode 100644 lib/kohana/system/i18n/fr_FR/session.php create mode 100644 lib/kohana/system/i18n/fr_FR/swift.php create mode 100644 lib/kohana/system/i18n/fr_FR/upload.php create mode 100644 lib/kohana/system/i18n/fr_FR/validation.php create mode 100644 lib/kohana/system/i18n/it_IT/cache.php create mode 100644 lib/kohana/system/i18n/it_IT/calendar.php create mode 100644 lib/kohana/system/i18n/it_IT/captcha.php create mode 100644 lib/kohana/system/i18n/it_IT/core.php create mode 100644 lib/kohana/system/i18n/it_IT/database.php create mode 100644 lib/kohana/system/i18n/it_IT/encrypt.php create mode 100644 lib/kohana/system/i18n/it_IT/errors.php create mode 100644 lib/kohana/system/i18n/it_IT/event.php create mode 100644 lib/kohana/system/i18n/it_IT/image.php create mode 100644 lib/kohana/system/i18n/it_IT/orm.php create mode 100644 lib/kohana/system/i18n/it_IT/pagination.php create mode 100644 lib/kohana/system/i18n/it_IT/profiler.php create mode 100644 lib/kohana/system/i18n/it_IT/session.php create mode 100644 lib/kohana/system/i18n/it_IT/swift.php create mode 100644 lib/kohana/system/i18n/it_IT/upload.php create mode 100644 lib/kohana/system/i18n/it_IT/validation.php create mode 100644 lib/kohana/system/i18n/nl_NL/cache.php create mode 100644 lib/kohana/system/i18n/nl_NL/calendar.php create mode 100644 lib/kohana/system/i18n/nl_NL/captcha.php create mode 100644 lib/kohana/system/i18n/nl_NL/core.php create mode 100644 lib/kohana/system/i18n/nl_NL/database.php create mode 100644 lib/kohana/system/i18n/nl_NL/encrypt.php create mode 100644 lib/kohana/system/i18n/nl_NL/errors.php create mode 100644 lib/kohana/system/i18n/nl_NL/event.php create mode 100644 lib/kohana/system/i18n/nl_NL/image.php create mode 100644 lib/kohana/system/i18n/nl_NL/orm.php create mode 100644 lib/kohana/system/i18n/nl_NL/pagination.php create mode 100644 lib/kohana/system/i18n/nl_NL/profiler.php create mode 100644 lib/kohana/system/i18n/nl_NL/session.php create mode 100644 lib/kohana/system/i18n/nl_NL/swift.php create mode 100644 lib/kohana/system/i18n/nl_NL/upload.php create mode 100644 lib/kohana/system/i18n/nl_NL/validation.php create mode 100644 lib/kohana/system/i18n/ru_RU/cache.php create mode 100644 lib/kohana/system/i18n/ru_RU/calendar.php create mode 100644 lib/kohana/system/i18n/ru_RU/captcha.php create mode 100644 lib/kohana/system/i18n/ru_RU/core.php create mode 100644 lib/kohana/system/i18n/ru_RU/database.php create mode 100644 lib/kohana/system/i18n/ru_RU/encrypt.php create mode 100644 lib/kohana/system/i18n/ru_RU/errors.php create mode 100644 lib/kohana/system/i18n/ru_RU/event.php create mode 100644 lib/kohana/system/i18n/ru_RU/image.php create mode 100644 lib/kohana/system/i18n/ru_RU/orm.php create mode 100644 lib/kohana/system/i18n/ru_RU/pagination.php create mode 100644 lib/kohana/system/i18n/ru_RU/profiler.php create mode 100644 lib/kohana/system/i18n/ru_RU/session.php create mode 100644 lib/kohana/system/i18n/ru_RU/swift.php create mode 100644 lib/kohana/system/i18n/ru_RU/upload.php create mode 100644 lib/kohana/system/i18n/ru_RU/validation.php create mode 100644 lib/kohana/system/libraries/Cache.php create mode 100644 lib/kohana/system/libraries/Calendar.php create mode 100644 lib/kohana/system/libraries/Calendar_Event.php create mode 100644 lib/kohana/system/libraries/Captcha.php create mode 100644 lib/kohana/system/libraries/Controller.php create mode 100644 lib/kohana/system/libraries/Database.php create mode 100644 lib/kohana/system/libraries/Database_Expression.php create mode 100644 lib/kohana/system/libraries/Encrypt.php create mode 100644 lib/kohana/system/libraries/Event_Observer.php create mode 100644 lib/kohana/system/libraries/Event_Subject.php create mode 100644 lib/kohana/system/libraries/Image.php create mode 100644 lib/kohana/system/libraries/Input.php create mode 100644 lib/kohana/system/libraries/Model.php create mode 100644 lib/kohana/system/libraries/ORM.php create mode 100644 lib/kohana/system/libraries/ORM_Iterator.php create mode 100644 lib/kohana/system/libraries/ORM_Tree.php create mode 100644 lib/kohana/system/libraries/ORM_Versioned.php create mode 100644 lib/kohana/system/libraries/Pagination.php create mode 100644 lib/kohana/system/libraries/Profiler.php create mode 100644 lib/kohana/system/libraries/Profiler_Table.php create mode 100644 lib/kohana/system/libraries/Router.php create mode 100644 lib/kohana/system/libraries/Session.php create mode 100644 lib/kohana/system/libraries/Tagcloud.php create mode 100644 lib/kohana/system/libraries/URI.php create mode 100644 lib/kohana/system/libraries/Validation.php create mode 100644 lib/kohana/system/libraries/View.php create mode 100644 lib/kohana/system/libraries/drivers/Cache.php create mode 100644 lib/kohana/system/libraries/drivers/Cache/Apc.php create mode 100644 lib/kohana/system/libraries/drivers/Cache/Eaccelerator.php create mode 100644 lib/kohana/system/libraries/drivers/Cache/File.php create mode 100644 lib/kohana/system/libraries/drivers/Cache/Memcache.php create mode 100644 lib/kohana/system/libraries/drivers/Cache/Sqlite.php create mode 100644 lib/kohana/system/libraries/drivers/Cache/Xcache.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha/Alpha.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha/Basic.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha/Black.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha/Math.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha/Riddle.php create mode 100644 lib/kohana/system/libraries/drivers/Captcha/Word.php create mode 100644 lib/kohana/system/libraries/drivers/Database.php create mode 100644 lib/kohana/system/libraries/drivers/Database/Mssql.php create mode 100644 lib/kohana/system/libraries/drivers/Database/Mysql.php create mode 100644 lib/kohana/system/libraries/drivers/Database/Mysqli.php create mode 100644 lib/kohana/system/libraries/drivers/Database/Pdosqlite.php create mode 100644 lib/kohana/system/libraries/drivers/Database/Pgsql.php create mode 100644 lib/kohana/system/libraries/drivers/Image.php create mode 100644 lib/kohana/system/libraries/drivers/Image/GD.php create mode 100644 lib/kohana/system/libraries/drivers/Image/GraphicsMagick.php create mode 100644 lib/kohana/system/libraries/drivers/Image/ImageMagick.php create mode 100644 lib/kohana/system/libraries/drivers/Session.php create mode 100644 lib/kohana/system/libraries/drivers/Session/Cache.php create mode 100644 lib/kohana/system/libraries/drivers/Session/Cookie.php create mode 100644 lib/kohana/system/libraries/drivers/Session/Database.php create mode 100644 lib/kohana/system/views/kohana/template.php create mode 100644 lib/kohana/system/views/kohana_calendar.php create mode 100644 lib/kohana/system/views/kohana_error_disabled.php create mode 100644 lib/kohana/system/views/kohana_error_page.php create mode 100644 lib/kohana/system/views/kohana_errors.css create mode 100644 lib/kohana/system/views/kohana_profiler.php create mode 100644 lib/kohana/system/views/kohana_profiler_table.css create mode 100644 lib/kohana/system/views/kohana_profiler_table.php create mode 100644 lib/kohana/system/views/pagination/classic.php create mode 100644 lib/kohana/system/views/pagination/digg.php create mode 100644 lib/kohana/system/views/pagination/extended.php create mode 100644 lib/kohana/system/views/pagination/punbb.php create mode 100644 man/Makefile.in create mode 100644 man/npcd.8.in create mode 100644 sample-config/Makefile.in create mode 100644 sample-config/httpd.conf.in create mode 100644 sample-config/lighttpd.pnp4nagios.conf.in create mode 100644 sample-config/misccommands.cfg-sample.in create mode 100644 sample-config/nagios.cfg-sample.in create mode 100644 sample-config/nginx.pnp4nagios.conf.in create mode 100644 sample-config/pnp/background-letter.pdf create mode 100644 sample-config/pnp/background.pdf create mode 100644 sample-config/pnp/check_commands/check_all_local_disks.cfg-sample create mode 100644 sample-config/pnp/check_commands/check_nrpe.cfg-sample create mode 100644 sample-config/pnp/check_commands/check_nwstat.cfg-sample create mode 100644 sample-config/pnp/config.php.in create mode 100644 sample-config/pnp/npcd.cfg-sample.in create mode 100644 sample-config/pnp/pages/web_traffic.cfg-sample create mode 100644 sample-config/pnp/pnp4nagios_release.in create mode 100644 sample-config/pnp/process_perfdata.cfg-sample.in create mode 100644 sample-config/pnp/rra.cfg-sample create mode 100644 scripts/Makefile.in create mode 100644 scripts/check_pnp_rrds.pl.in create mode 100644 scripts/process_perfdata.pl.in create mode 100644 scripts/rc.npcd.in create mode 100644 scripts/rc.pnp_gearman_worker.in create mode 100644 scripts/rrd_convert.pl.in create mode 100644 scripts/rrd_modify.pl.in create mode 100755 scripts/verify_pnp_config_v2.pl create mode 100644 share/Makefile.in create mode 100644 share/pnp/application/config/config.php create mode 100644 share/pnp/application/config/locale.php create mode 100644 share/pnp/application/config/routes.php create mode 100644 share/pnp/application/config/session.php create mode 100644 share/pnp/application/controllers/ajax.php create mode 100644 share/pnp/application/controllers/color.php create mode 100644 share/pnp/application/controllers/debug.php create mode 100644 share/pnp/application/controllers/docs.php create mode 100644 share/pnp/application/controllers/graph.php create mode 100644 share/pnp/application/controllers/image.php create mode 100644 share/pnp/application/controllers/json.php create mode 100644 share/pnp/application/controllers/mobile.php create mode 100644 share/pnp/application/controllers/page.php create mode 100644 share/pnp/application/controllers/pdf.php create mode 100644 share/pnp/application/controllers/popup.php create mode 100644 share/pnp/application/controllers/special.php create mode 100644 share/pnp/application/controllers/start.php create mode 100644 share/pnp/application/controllers/system.php create mode 100644 share/pnp/application/controllers/xml.php create mode 100644 share/pnp/application/controllers/xport.php create mode 100644 share/pnp/application/controllers/zoom.php create mode 100644 share/pnp/application/helpers/nagios.php create mode 100644 share/pnp/application/helpers/pnp.php create mode 100644 share/pnp/application/helpers/rrd.php create mode 100644 share/pnp/application/i18n/de_DE/common.php create mode 100644 share/pnp/application/i18n/de_DE/error.php create mode 100644 share/pnp/application/i18n/en_US/common.php create mode 100644 share/pnp/application/i18n/en_US/error.php create mode 100644 share/pnp/application/i18n/es_ES/common.php create mode 100644 share/pnp/application/i18n/es_ES/error.php create mode 100644 share/pnp/application/i18n/fr_FR/common.php create mode 100644 share/pnp/application/i18n/fr_FR/error.php create mode 100644 share/pnp/application/i18n/ru_RU/common.php create mode 100644 share/pnp/application/i18n/ru_RU/error.php create mode 100644 share/pnp/application/lib/json.php create mode 100644 share/pnp/application/lib/jsonwrapper.php create mode 100644 share/pnp/application/lib/jsonwrapper_inner.php create mode 100644 share/pnp/application/models/auth.php create mode 100644 share/pnp/application/models/auth_multisite.php create mode 100644 share/pnp/application/models/config.php create mode 100644 share/pnp/application/models/data.php create mode 100644 share/pnp/application/models/rrdtool.php create mode 100644 share/pnp/application/models/system.php create mode 100644 share/pnp/application/vendor/fpdf/filters/FilterASCII85.php create mode 100644 share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php create mode 100644 share/pnp/application/vendor/fpdf/filters/FilterLZW.php create mode 100644 share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php create mode 100644 share/pnp/application/vendor/fpdf/font/courier.php create mode 100644 share/pnp/application/vendor/fpdf/font/helvetica.php create mode 100644 share/pnp/application/vendor/fpdf/font/helveticab.php create mode 100644 share/pnp/application/vendor/fpdf/font/helveticabi.php create mode 100644 share/pnp/application/vendor/fpdf/font/helveticai.php create mode 100644 share/pnp/application/vendor/fpdf/font/symbol.php create mode 100644 share/pnp/application/vendor/fpdf/font/times.php create mode 100644 share/pnp/application/vendor/fpdf/font/timesb.php create mode 100644 share/pnp/application/vendor/fpdf/font/timesbi.php create mode 100644 share/pnp/application/vendor/fpdf/font/timesi.php create mode 100644 share/pnp/application/vendor/fpdf/font/zapfdingbats.php create mode 100644 share/pnp/application/vendor/fpdf/fpdf.php create mode 100644 share/pnp/application/vendor/fpdf/fpdf_tpl.php create mode 100644 share/pnp/application/vendor/fpdf/fpdi.php create mode 100644 share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php create mode 100644 share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php create mode 100644 share/pnp/application/vendor/fpdf/license.txt create mode 100644 share/pnp/application/vendor/fpdf/pdf_context.php create mode 100644 share/pnp/application/vendor/fpdf/pdf_parser.php create mode 100644 share/pnp/application/views/basket_box.php create mode 100644 share/pnp/application/views/color.php create mode 100644 share/pnp/application/views/color_box.php create mode 100644 share/pnp/application/views/debug.php create mode 100644 share/pnp/application/views/docs.php create mode 100644 share/pnp/application/views/docs_box.php create mode 100644 share/pnp/application/views/graph.php create mode 100644 share/pnp/application/views/graph_content.php create mode 100644 share/pnp/application/views/graph_content_special.php create mode 100644 share/pnp/application/views/graph_tiny.php create mode 100644 share/pnp/application/views/header.php create mode 100644 share/pnp/application/views/host_box.php create mode 100644 share/pnp/application/views/icon_box.php create mode 100644 share/pnp/application/views/kohana_error_page.php create mode 100644 share/pnp/application/views/logo_box.php create mode 100644 share/pnp/application/views/mobile.php create mode 100644 share/pnp/application/views/mobile_about.php create mode 100644 share/pnp/application/views/mobile_graph.php create mode 100644 share/pnp/application/views/mobile_graph_special.php create mode 100644 share/pnp/application/views/mobile_home.php create mode 100644 share/pnp/application/views/mobile_host.php create mode 100644 share/pnp/application/views/mobile_overview.php create mode 100644 share/pnp/application/views/mobile_pages.php create mode 100644 share/pnp/application/views/mobile_search.php create mode 100644 share/pnp/application/views/mobile_special.php create mode 100644 share/pnp/application/views/multisite_box.php create mode 100644 share/pnp/application/views/page.php create mode 100644 share/pnp/application/views/pages_box.php create mode 100644 share/pnp/application/views/popup.php create mode 100644 share/pnp/application/views/search_box.php create mode 100644 share/pnp/application/views/service_box.php create mode 100644 share/pnp/application/views/special_templates_box.php create mode 100644 share/pnp/application/views/status_box.php create mode 100644 share/pnp/application/views/template.php create mode 100644 share/pnp/application/views/timerange_box.php create mode 100644 share/pnp/application/views/timerange_select.php create mode 100644 share/pnp/application/views/widget_graph.sample.php create mode 100644 share/pnp/application/views/widget_menu.sample.php create mode 100644 share/pnp/application/views/zoom.php create mode 100644 share/pnp/application/views/zoom_header.php create mode 100644 share/pnp/documents/_media/bulk-npcd.png create mode 100644 share/pnp/documents/_media/bulk-npcdmod.png create mode 100644 share/pnp/documents/_media/bulk.png create mode 100644 share/pnp/documents/_media/gearman.png create mode 100644 share/pnp/documents/_media/mobile-graphs.png create mode 100644 share/pnp/documents/_media/mobile-home.png create mode 100644 share/pnp/documents/_media/mobile-hostlist.png create mode 100644 share/pnp/documents/_media/mobile-loading.png create mode 100644 share/pnp/documents/_media/mobile-servicelist.png create mode 100644 share/pnp/documents/_media/nagiospowered-72x72.png create mode 100644 share/pnp/documents/_media/pnp-preview-05-08-2009.png create mode 100644 share/pnp/documents/_media/popup.png create mode 100644 share/pnp/documents/_media/srv_info.png create mode 100644 share/pnp/documents/_media/synchronous.png create mode 100644 share/pnp/documents/de_DE/about.html create mode 100644 share/pnp/documents/de_DE/advanced.html create mode 100644 share/pnp/documents/de_DE/config.html create mode 100644 share/pnp/documents/de_DE/doc_complete.html create mode 120000 share/pnp/documents/de_DE/dwnld.html create mode 100644 share/pnp/documents/de_DE/install.html create mode 100644 share/pnp/documents/de_DE/mobile.html create mode 100644 share/pnp/documents/de_DE/modes.html create mode 100644 share/pnp/documents/de_DE/new-features.html create mode 100644 share/pnp/documents/de_DE/npcd.html create mode 100644 share/pnp/documents/de_DE/pages.html create mode 100644 share/pnp/documents/de_DE/perfdata_format.html create mode 100644 share/pnp/documents/de_DE/rrd_convert.html create mode 100644 share/pnp/documents/de_DE/rrdcached.html create mode 100644 share/pnp/documents/de_DE/start.html create mode 100644 share/pnp/documents/de_DE/timeranges.html create mode 100644 share/pnp/documents/de_DE/tpl.html create mode 100644 share/pnp/documents/de_DE/tpl_custom.html create mode 100644 share/pnp/documents/de_DE/tpl_helper.html create mode 100644 share/pnp/documents/de_DE/tpl_helper_pnp.html create mode 100644 share/pnp/documents/de_DE/tpl_special.html create mode 100644 share/pnp/documents/de_DE/upgrade.html create mode 100644 share/pnp/documents/de_DE/verify.html create mode 100644 share/pnp/documents/de_DE/verify_pnp_config.html create mode 100644 share/pnp/documents/de_DE/webfe.html create mode 100644 share/pnp/documents/de_DE/webfe_cfg.html create mode 100644 share/pnp/documents/de_DE/wrapper.html create mode 100644 share/pnp/documents/de_DE/xport.html create mode 100644 share/pnp/documents/en_US/about.html create mode 100644 share/pnp/documents/en_US/advanced.html create mode 100644 share/pnp/documents/en_US/config.html create mode 100644 share/pnp/documents/en_US/doc_complete.html create mode 100644 share/pnp/documents/en_US/dwnld.html create mode 100644 share/pnp/documents/en_US/install.html create mode 100644 share/pnp/documents/en_US/mobile.html create mode 100644 share/pnp/documents/en_US/modes.html create mode 100644 share/pnp/documents/en_US/new-features.html create mode 100644 share/pnp/documents/en_US/npcd.html create mode 100644 share/pnp/documents/en_US/pages.html create mode 100644 share/pnp/documents/en_US/perfdata_format.html create mode 100644 share/pnp/documents/en_US/rrd_convert.html create mode 100644 share/pnp/documents/en_US/rrdcached.html create mode 100644 share/pnp/documents/en_US/start.html create mode 100644 share/pnp/documents/en_US/timeranges.html create mode 100644 share/pnp/documents/en_US/tpl.html create mode 100644 share/pnp/documents/en_US/tpl_custom.html create mode 100644 share/pnp/documents/en_US/tpl_helper.html create mode 100644 share/pnp/documents/en_US/tpl_helper_pnp.html create mode 100644 share/pnp/documents/en_US/tpl_special.html create mode 100644 share/pnp/documents/en_US/upgrade.html create mode 100644 share/pnp/documents/en_US/verify.html create mode 100644 share/pnp/documents/en_US/verify_pnp_config.html create mode 100644 share/pnp/documents/en_US/webfe.html create mode 100644 share/pnp/documents/en_US/webfe_cfg.html create mode 100644 share/pnp/documents/en_US/wrapper.html create mode 100644 share/pnp/documents/en_US/xport.html create mode 100644 share/pnp/documents/images/smileys/delete.gif create mode 100644 share/pnp/documents/images/smileys/fixme.gif create mode 100644 share/pnp/documents/images/smileys/icon_arrow.gif create mode 100644 share/pnp/documents/images/smileys/icon_biggrin.gif create mode 100644 share/pnp/documents/images/smileys/icon_confused.gif create mode 100644 share/pnp/documents/images/smileys/icon_cool.gif create mode 100644 share/pnp/documents/images/smileys/icon_cry.gif create mode 100644 share/pnp/documents/images/smileys/icon_doubt.gif create mode 100644 share/pnp/documents/images/smileys/icon_doubt2.gif create mode 100644 share/pnp/documents/images/smileys/icon_eek.gif create mode 100644 share/pnp/documents/images/smileys/icon_evil.gif create mode 100644 share/pnp/documents/images/smileys/icon_exclaim.gif create mode 100644 share/pnp/documents/images/smileys/icon_frown.gif create mode 100644 share/pnp/documents/images/smileys/icon_fun.gif create mode 100644 share/pnp/documents/images/smileys/icon_idea.gif create mode 100644 share/pnp/documents/images/smileys/icon_kaddi.gif create mode 100644 share/pnp/documents/images/smileys/icon_lol.gif create mode 100644 share/pnp/documents/images/smileys/icon_mrgreen.gif create mode 100644 share/pnp/documents/images/smileys/icon_neutral.gif create mode 100644 share/pnp/documents/images/smileys/icon_question.gif create mode 100644 share/pnp/documents/images/smileys/icon_razz.gif create mode 100644 share/pnp/documents/images/smileys/icon_redface.gif create mode 100644 share/pnp/documents/images/smileys/icon_rolleyes.gif create mode 100644 share/pnp/documents/images/smileys/icon_sad.gif create mode 100644 share/pnp/documents/images/smileys/icon_silenced.gif create mode 100644 share/pnp/documents/images/smileys/icon_smile.gif create mode 100644 share/pnp/documents/images/smileys/icon_smile2.gif create mode 100644 share/pnp/documents/images/smileys/icon_surprised.gif create mode 100644 share/pnp/documents/images/smileys/icon_twisted.gif create mode 100644 share/pnp/documents/images/smileys/icon_wink.gif create mode 100644 share/pnp/index.php.in create mode 100644 share/pnp/install.php.in create mode 100644 share/pnp/media/css/autocomplete.css create mode 100644 share/pnp/media/css/border-h.gif create mode 100644 share/pnp/media/css/border-v.gif create mode 100644 share/pnp/media/css/common.css create mode 100644 share/pnp/media/css/images/ajax-loader.png create mode 100644 share/pnp/media/css/images/icon-search-black.png create mode 100644 share/pnp/media/css/images/icons-18-black.png create mode 100644 share/pnp/media/css/images/icons-18-white.png create mode 100644 share/pnp/media/css/images/icons-36-black.png create mode 100644 share/pnp/media/css/images/icons-36-white.png create mode 100644 share/pnp/media/css/imgareaselect-default.css create mode 100644 share/pnp/media/css/mobile.css create mode 100644 share/pnp/media/css/shadow.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-icons_222222_256x240.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-icons_2e83ff_256x240.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-icons_454545_256x240.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-icons_888888_256x240.png create mode 100644 share/pnp/media/css/ui-lightness/images/ui-icons_cd0a0a_256x240.png create mode 100644 share/pnp/media/css/ui-lightness/jquery-ui.css create mode 100644 share/pnp/media/css/ui-multisite/images/contentframe_background.jpg create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_flat_75_6da1b8_40x100.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_glass_65_88b9ce_1x400.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_glass_75_6da1b8_1x400.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_glass_75_94cde6_1x400.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_highlight-soft_75_274554_1x100.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_highlight-soft_75_6da1b8_1x100.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-bg_inset-soft_95_fef1ec_1x100.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-icons_000000_256x240.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-icons_222222_256x240.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-icons_2e83ff_256x240.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-icons_454545_256x240.png create mode 100755 share/pnp/media/css/ui-multisite/images/ui-icons_cd0a0a_256x240.png create mode 100644 share/pnp/media/css/ui-multisite/jquery-ui.css create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-icons_222222_256x240.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-icons_2e83ff_256x240.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-icons_454545_256x240.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-icons_888888_256x240.png create mode 100644 share/pnp/media/css/ui-redmond/images/ui-icons_cd0a0a_256x240.png create mode 100644 share/pnp/media/css/ui-redmond/jquery-ui.css create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-icons_222222_256x240.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-icons_454545_256x240.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-icons_888888_256x240.png create mode 100644 share/pnp/media/css/ui-smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 share/pnp/media/css/ui-smoothness/jquery-ui.css create mode 100644 share/pnp/media/images/1x1.gif create mode 100644 share/pnp/media/images/add.png create mode 100644 share/pnp/media/images/back.png create mode 100644 share/pnp/media/images/calendar.png create mode 100644 share/pnp/media/images/color.png create mode 100755 share/pnp/media/images/de_DE.png create mode 100755 share/pnp/media/images/docs.png create mode 100755 share/pnp/media/images/en_US.png create mode 100644 share/pnp/media/images/favicon.ico create mode 100644 share/pnp/media/images/go-left.png create mode 100644 share/pnp/media/images/go-now.png create mode 100644 share/pnp/media/images/go-right.png create mode 100644 share/pnp/media/images/graph.png create mode 100755 share/pnp/media/images/home.png create mode 100644 share/pnp/media/images/int.gif create mode 100644 share/pnp/media/images/int2.gif create mode 100644 share/pnp/media/images/loader.gif create mode 100644 share/pnp/media/images/notify.gif create mode 100644 share/pnp/media/images/pages.png create mode 100644 share/pnp/media/images/pdf.png create mode 100644 share/pnp/media/images/pnp.png create mode 100644 share/pnp/media/images/remove.png create mode 100644 share/pnp/media/images/rrdtool.png create mode 100755 share/pnp/media/images/special.png create mode 100644 share/pnp/media/images/stats.png create mode 100644 share/pnp/media/images/trends.gif create mode 100644 share/pnp/media/images/view-calendar.png create mode 100644 share/pnp/media/images/xml.png create mode 100644 share/pnp/media/images/zoom.png create mode 100644 share/pnp/media/js/jquery-ui-timepicker-addon.js create mode 100644 share/pnp/media/js/jquery.cluetip.js create mode 100644 share/pnp/media/js/jquery.imgareaselect.Debian.txt create mode 100644 share/pnp/media/js/jquery.imgareaselect.js create mode 120000 share/pnp/templates.dist/check-host-alive.php create mode 100644 share/pnp/templates.dist/check_apachestatus.php create mode 100644 share/pnp/templates.dist/check_apachestatus_auto.php create mode 100644 share/pnp/templates.dist/check_dell_bladechassis.php create mode 100644 share/pnp/templates.dist/check_disk.php create mode 100644 share/pnp/templates.dist/check_dns.php create mode 100644 share/pnp/templates.dist/check_esx3.php create mode 100644 share/pnp/templates.dist/check_fping.php create mode 100644 share/pnp/templates.dist/check_gearman.php create mode 100644 share/pnp/templates.dist/check_hp_bladechassis.php create mode 100644 share/pnp/templates.dist/check_hpasm.php create mode 100644 share/pnp/templates.dist/check_http.php create mode 120000 share/pnp/templates.dist/check_icmp.php create mode 100644 share/pnp/templates.dist/check_iftraffic_counter.php create mode 100644 share/pnp/templates.dist/check_iftraffic_pct.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_connector_errors.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_connector_nr_requests.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_connector_proc_time.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_connector_received.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_connector_sent.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_connector_threads.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_memory_gc_count.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_memory_gc_time.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_memory_heap.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_thread_count.php create mode 100644 share/pnp/templates.dist/check_jmx4perl_thread_increase.php create mode 100644 share/pnp/templates.dist/check_load.php create mode 120000 share/pnp/templates.dist/check_local_disk.php create mode 120000 share/pnp/templates.dist/check_local_load.php create mode 100644 share/pnp/templates.dist/check_messpc_temp.php create mode 100644 share/pnp/templates.dist/check_mssql_health.php create mode 100644 share/pnp/templates.dist/check_multi.php create mode 100644 share/pnp/templates.dist/check_multi_nagiostats.php create mode 100644 share/pnp/templates.dist/check_mysql_health.php create mode 100644 share/pnp/templates.dist/check_nt_cpu.php create mode 100644 share/pnp/templates.dist/check_nt_disk.php create mode 100644 share/pnp/templates.dist/check_nt_mem.php create mode 100644 share/pnp/templates.dist/check_ntp_time.php create mode 100644 share/pnp/templates.dist/check_nwstat_CONNS.php create mode 100644 share/pnp/templates.dist/check_nwstat_LOAD.php create mode 120000 share/pnp/templates.dist/check_nwstat_LOAD1.php create mode 120000 share/pnp/templates.dist/check_nwstat_LOAD15.php create mode 120000 share/pnp/templates.dist/check_nwstat_LOAD5.php create mode 100644 share/pnp/templates.dist/check_nwstat_ofiles.php create mode 100644 share/pnp/templates.dist/check_openmanage.php create mode 100644 share/pnp/templates.dist/check_oracle_connection-time.php create mode 100644 share/pnp/templates.dist/check_oracle_health.php create mode 100644 share/pnp/templates.dist/check_oracle_health_connection-time.php create mode 100644 share/pnp/templates.dist/check_oracle_health_pga-in-memory-sort-ratio.php create mode 100644 share/pnp/templates.dist/check_oracle_health_redo-io-traffic.php create mode 100644 share/pnp/templates.dist/check_oracle_health_switch-interval.php create mode 100644 share/pnp/templates.dist/check_oracle_health_tablespace-usage.php create mode 100644 share/pnp/templates.dist/check_ping.php create mode 100644 share/pnp/templates.dist/check_ping_tick.php create mode 100644 share/pnp/templates.dist/check_pnp_rrds.php create mode 120000 share/pnp/templates.dist/check_smtp.php create mode 100644 share/pnp/templates.dist/check_snmp_int-bits.php create mode 100644 share/pnp/templates.dist/check_snmp_int.php create mode 100644 share/pnp/templates.dist/check_swap.php create mode 120000 share/pnp/templates.dist/check_tcp.php create mode 100644 share/pnp/templates.dist/check_users.php create mode 100644 share/pnp/templates.dist/default.php create mode 100644 share/pnp/templates.dist/integer.php create mode 100644 share/pnp/templates.dist/nagiostats.php create mode 100644 share/pnp/templates.dist/pnp-runtime.php create mode 100644 share/pnp/templates.dist/response.php create mode 100644 share/pnp/templates.special/README create mode 100644 share/pnp/templates.special/advanced_loop.php-sample create mode 100644 share/pnp/templates.special/loop.php-sample create mode 100644 share/pnp/templates.special/static.php-sample create mode 100644 src/Makefile.in create mode 100644 src/config.c create mode 100644 src/logging.c create mode 100644 src/module/modpnpsender.c create mode 100644 src/npcd.c create mode 100644 src/npcdmod.c create mode 100644 src/pnpsender.c create mode 100644 src/utils.c create mode 100755 subst.in create mode 100644 summary.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bf28ca2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +autom4te.cache +subst +summary +*Makefile +config.log +config.status +scripts/rc.npcd +scripts/rc.pnp_gearman_worker +scripts/check_pnp_rrds.pl +scripts/process_perfdata.pl +scripts/rrd_modify.pl +src/*.o +src/npcd +include/config.h +*~ + +sample-config/pnp/config.php +sample-config/pnp/pnp4nagios_release +sample-config/pnp/process_perfdata.cfg-sample +sample-config/pnp/npcd.cfg-sample +sample-config/misccommands.cfg-sample +sample-config/nagios.cfg-sample + +share/pnp/application/config/config.php +share/pnp/index.php +share/pnp/install.php +sample-config/httpd.conf +share/pnp/application/logs/* +contrib/ssi/status-header.ssi +helpers/w2h.pl +scripts/verify_pnp_config.pl +sample-config/lighttpd.pnp4nagios.conf +sample-config/nginx.pnp4nagios.conf +share/pnp/media/js/basket.js +scripts/rrd_convert.pl +scripts/rrd_converter.pl + +man/npcd.8 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..56e9fde --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Authors: +Jörg Linge pitchfork@pnp4nagios.org +Hendrik Bäcker andurin@process-zero.de diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..623b625 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + 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 Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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 Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..66dbda2 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,185 @@ +**pnp-0.6.?? ??/??/2013** + +**pnp-0.6.24 07/30/2013** + * Bugfix: Fixed some more XSS issues + * Bugfix: Fixed PHP issue while running on PHP 5.6 ( Reported by Sven Nierlein ) + +**pnp-0.6.22 06/04/2014** + * Bugfix: Fixed livestatus socket parsing ( Pekka Panula ) + * Bugfix: Update check_mssql_health.php ( Miriam Zenk ) + * Feature: Add "version=tiny" to got get a stripped down version of graph ( Ricardo Bartels ) + * feature: Add STDIN Mode to process_perfdata.pl ( Robert Steininger ) + * Bugfix: XSS issue fixed by Mikael Falkvidd. This issue was detected by Peter Österberg at Hexbit AB in a security assessment of op5 Monitor 6.3 on assignment by op5 AB. + +**pnp-0.6.21 03/24/2013** + * Feature: Helper functions rrd::alerter and rrd:alerter_gr both supports treshold detection (Martin Schirrmacher) + * Update: jQuery Mobile update to 1.3.0 ( was broken in 0.6.20 ) + +**pnp-0.6.20 03/03/2013** + * Feature: Support check_mk Multisite Cookie Auth ( Lars Michelsen ) + * Feature: Allow RRD unknown values ( Simon Meggle ) + * feature: Interactive delete mode added to check_rrds.pl ( Simon Meggle ) + * Bugfix: Allow multiple gearman servers ( Craig Barraclough ) + * Bugfix: Fixed Graph Search ( Stefan Triep ) + * Update: jQuery update to 1.8.1 + * Update: jQueryUI update to 1.8.23 + +**pnp-0.6.19 09/01/2012** + * Feature: Parameter "width" added to popup controller ( Andreas Doehler ) + * Fix: simplify/improve apache rules ( Christoph Anton Mitterer ) + * Fix: Check for missing PHP GD functions + * Bugfix: socketDOMAIN changed to AF_INET while using livstatus tcp socket ( Rene Koch ) + +**pnp-0.6.18 06/28/2012** + * Bugfix: Fixed STORAGE_TYPE and CUSTOM_TEMPLATE vars used in custom templates + * Bugfix: Blank screen on PHP 5.4 fixed + * Feature: Allow multiple gearman job servers + * Feature: New helper function rrd::debug() + * Feature: New templates check_jmx4perl_*.php + +**pnp-0.6.17 03/25/2012** + * Bugfix: Fixed rrd_convert.pl while running with --dry-run + * Bugfix: logging.c include missing header files ( Lars Vogdt ) + * Bugfix: Check if pnp4nagios/etc/rra.cfg is readable + * Bugfix: rrd_convert.pl use XML tag TEMPLATE instead of CHECKCOMMAND to selects RRDs ( Sven Velt ) + * Feature: npcdmod.o increase perfdata buffer and log discarded perfdata ( Birger Schmidt ) + * Feature: rrd_modify.pl to change number of data sources of an RRD file + * Feature: New template check_apachestatus_auto.php + * Feature: Implement etc/config.d to place config snippets ( Lars Michelsen ) + +**pnp-0.6.16 11/21/2011** + * Bugfix: Fixed single quoted check_multi labels (Reported by Matthias Flacke) + * Bugfix: Append missing slash to perfdata_spool_dir ( Reported by Juergen-Michael Radtke ) + * Bugfix: Fixed jQuery-ui multisite theme + * Feature: PDF margins are now adjustable via config.php ( Thomas Witzenrath ) + * Feature: Support for PDF size 'letter' added ( Robert Becht ) + +**pnp-0.6.15 09/15/2011** + * Bugfix: Fixed Overview link (reported by Stefan Triep) + * Bugfix: Fixed zoom popup (reported by Rudolf Labuschagne) + * Bugfix: Fixed double urlencode() (reported by Mathias Kettner) + * Feature: "Clear basket" button added (suggested by Stefan Triep) + * Feature: New helper function "rrd::alerter_gr()" ( committed by Stefan Trip ) + +**pnp-0.6.14 08/05/2011** + * Feature: Webinterface for mobile devices based on jQuery Mobile \\ ( http://jquerymobile.com/ ) + * Feature: Zoom based on jQuery plugin imgAreaSelect \\ ( http://odyniec.net/projects/imgareaselect/ ) + * Feature: New template check_mssql_health.php + * Bugfix: Fixed popups to work under nginx ( Joram Agten ) + * Bugfix: Helper rrd::vdef() fixed + * Update: jQuery update to 1.6.2 + * Update: jQuery-ui update to 1.8.14 + +**pnp-0.6.13 05/19/2011** + * Feature: New option --ignore-hosts added to check_pnp_rrds.pl ( by Jochen Bern ) + * Feature: New options zgraph_width and zgraph_height in config.php ( Mike Liebsch ) + * Bugfix: rrd_convert.pl: parse_xml_filename() regex fix + * Info: Version used by OMD-0.48 [[http://omdistro.org|OMD]] + +**pnp-0.6.12 04/22/2011** + * Feature: mod_gearman support added + * Feature: rrd_convert.pl is now able to convert all RRDs from RRD_STORAGE_TYPE=SINGLE to RRD_STORAGE_TYPE=MULTIPLE + * Feature: New template check_gearman.php + * Feature: Install process_perfdata.cfg and npcd.cfg by default + * Bugfix: rrd_convert.pl is now able to parse xml dumps created by rrdtool 1.4.x + * Bugfix: process_perfdata.pl default timeout value set to 15 seconds + +**pnp-0.6.11 01/15/2011** + * Bugfix: urldecoding fixed + * Bugfix: Zoom in/out is working again ( Reported by Thorben Soehl ) + * Featue: npcd.cfg - New option perfdata_file_processing_interval used by npcdmod + * Info: Version used by OMD-0.46 [[http://omdistro.org|OMD]] + +**pnp-0.6.10 12/15/2010** + + * Feature: Add RRDTool Option --only-graph if graph height is below 32px to create thumbnails + * Feature: RRDTool Option --width and --height is now allowed in templates + * Feature: RRDTool DS Type for UOM of "c" changed from COUNTER to DERIVE + * Feature: Pass query string from special controller to image controller ( Matthew Garrett ) + * Feature: Authorisation against [[http://mathias-kettner.de/checkmk_livestatus.html|mk_livestatus]] API added + * Feature: Sample nginx webserver config added ( by evax@users.sourceforge.net ) + * Feature: Kohana backport to support PHP 5.1.6 ( Kudos to Andreas Ericsson ) + * Bugfix: Sort list of special templates + * Bugfix: Urlencode hostname and service description ( Reported by Yannick ) + * Bugfix: corrected warning/critical thresholds in ticker/alerter functions + +**pnp-0.6.7 09/27/2010** + + * Bugfix: Page config parser fix (Beau Gunderson) + * Bugfix: Zoom window size fixed (Report by Rudolf Labuschagne) + * Bugfix: Fixed undefined offset while using 'ds_name' in templates (Reported by Vladimir Bilik) + * Bugfix: Npcdmod respects process_perf_data option used in hosts and services definitions ( Reported by Wolfgang Barth ) + * Template: New Template check_nagiostats.php used with check_nagiostats written by Jochen Bern + +**pnp-0.6.6 08/07/2010** + + * Bugfix: Fixed max amount of graphs per template + * Bugfix: Autodetect PNP base URL + * Bugfix: Too short npcdmod perfdata_template to take perfdata + overhead, increased +1024byte + * Bugfix: Ignore files in var/perfdata and check for empty directories + * Bugfix: Reducing memory usage while parsing page config (Laurent Freval) + +**pnp-0.6.5 07/09/2010** + + * Feature: Special Templates are back [[tpl_special]] + * Feature: New rrdtool helper functions makes template design easier [[tpl_helper]] + * Feature: config.php -> 'recursive_template_search' is enabled by default + * Feature: config.php -> 'template_dirs' is now an array of directorys to search for PNP templates + +**pnp-0.6.4 06/03/2010** + + * Update: jQuery Update to 1.4.2 + * Update: jQuery-ui Update to 1.8 + * Feature: New configure Option --with-base-url + * Template: New template check_ntp_time.php (Mathias Kettner) + * Feature: New i18n files for fr_FR (Yannig Parre) + * Feature: New jQuery Theme 'multisite' + +**pnp-0.6.3 03/16/2010** + + * Feature: New helper script libexec/rrd_convert.pl -> [[rrd_convert]] + * Bugfix: Ignore old XML files while building the service list + * Template: New template check_hpasm.php + * Bugfix: Installer now checks for json_decode() + * Workaround: Allow "trailing unfilled semicolons". Workaround for nsclient++ + * Template: Updates for check_openmanage.php, check_hp_bladecenter.php and check_dell_baldecenter.php ( Trond Hasle Amundsen )" + +**pnp-0.6.2 12/23/2009** + + * Feature: XML_WRITE_DELAY option added to process_perfdata.cfg as suggested by Mathias Kettner + * Feature: New template integer.php + * Update: FPDI update to 1.3.1 + * Feature: PNP will now work with [[http://http://www.lighttpd.net|lighttpd]] and php-cgi + * Template: check_mk-ps.perf.php added ( by Mathias Kettner ) + * Feature: PNP will now work without mod_rewrite -> [[webfe]] + * Bugfix: Wrong pdf link used on site 'pages' and 'basket' + * Bugfix: Incorrect group permissions on spool directory + +**pnp-0.6.1 11/22/2009** + + * Feature: RRD heartbeat per check_command -> [[tpl_custom]] + * Feature: New config.php option pdf_graph_opt + * Feature: Recognize the 'background_pdf' option in page definitions -> [[pages]] + * Feature: Recognize the 'source' option in page definitions -> [[pages]] + * Feature: Array $TIMERANGE now available for templates -> [[timeranges]] + * Bugfix: ./configure --sysconfdir no longer ignored + * Feature: Store internal runtime statistics on a per minute base + * Feature: Added two widgets views/widget_menu.php and views/widget_graph.php + +**pnp-0.6.0 10/30/2009** + + * Webfrontend based on [[http://www.kohanaphp.com|Kohana]] + * Webfrontend based on [[http://jqueryui.com/themeroller/|jQuery Themes]] + * Javascript-functions using [[http://jquery.com/|jQuery]] plugins + * process_perfdata.pl will be able to use one RRD database per datasource + * improved installer. Specification of directory layouts using --with-layout + * RRDtool errors are now displayed as images. no more missing images + * PNP templates cannot overwrite internal variables anymore + * PNP templates of version 0.4.x can still be used + * PDF functions recoded + * Template default.php optimized + * Export from RRD databases into XML, CSV and JSON format using the RRDtool "xport" function + * Page functions recoded + * Error pages links to online FAQ + * Mouseover Popup in Nagios frontend via jQuery.clueTip plugin + * Full support of rrdcached diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..23e5f25 --- /dev/null +++ b/INSTALL @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..5ac4d8e --- /dev/null +++ b/Makefile.in @@ -0,0 +1,183 @@ +############################### +# Makefile for PNP +# +# Last Modified: 12-10-2006 +############################### + + +# Source code directories +SRC_BASE=@srcdir@/src +SRC_SHARE=@srcdir@/share +SRC_LIB=@srcdir@/lib +SRC_SCRIPTS=@srcdir@/scripts +SRC_CONFIG=@srcdir@/sample-config +SRC_MAN=@srcdir@/man +SRC_CONTRIB=@srcdir@/contrib +SRC_HELPERS=@srcdir@/helpers + +CC=@CC@ +CFLAGS=@CFLAGS@ @DEFS@ +LDFLAGS=@LDFLAGS@ @LIBS@ + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +LOGDIR=@localstatedir@ +CFGDIR=@sysconfdir@ +BINDIR=@bindir@ +LIBEXECDIR=@libexecdir@ +LIBDIR=@libdir@ +KOHANA=@KOHANA@ +CGIDIR=@sbindir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +DATAROOTDIR=@datarootdir@ + +CP=@CP@ +PERL=@PERL@ + +none: + @echo "Please supply a command line argument (i.e. 'make all'). Other targets are:" + @echo " clean" + @echo " install install-init install-config install-processperfdata install-html fullinstall" + @echo " install-plugins" + +all: + cd $(SRC_BASE) && $(MAKE) + cd $(SRC_SHARE) && $(MAKE) + cd $(SRC_SCRIPTS) && $(MAKE) + chmod a+r $(SRC_CONTRIB)/ssi/status-header.ssi + + @echo "" + @echo "*** Compile finished ***" + @echo "" + @echo " make install" + @echo " - This installs the main program and HTML files" + @echo "" + @echo " make fullinstall" + @echo " - This installs the main program, runlevel scripts, config and HTML files" + @echo "" + @echo "Enjoy." + @echo "" + +scripts: + cd $(SRC_SCRIPTS) && $(MAKE) + +share: + cd $(SRC_SHARE) && $(MAKE) + +clean: + cd $(SRC_BASE) && $(MAKE) $@ + cd $(SRC_MAN) && $(MAKE) $@ + cd $(SRC_SHARE) && $(MAKE) $@ + cd $(SRC_LIB) && $(MAKE) $@ + cd $(SRC_SCRIPTS) && $(MAKE) $@ + cd $(SRC_CONFIG) && $(MAKE) $@ + -rm -f *.cfg core + -rm -f *~ *.*~ */*~ */*.*~ + -rm -f config.log config.status config.cache + +distclean: + cd $(SRC_BASE) && $(MAKE) $@ + cd $(SRC_MAN) && $(MAKE) $@ + cd $(SRC_SHARE) && $(MAKE) $@ + cd $(SRC_LIB) && $(MAKE) $@ + cd $(SRC_SCRIPTS) && $(MAKE) $@ + cd $(SRC_CONFIG) && $(MAKE) $@ + -rm -f *.cfg core + -rm -f *~ *.*~ */*~ */*.*~ + -rm -f config.log config.status config.cache + rm -f Makefile include/stamp-h1 include/config.h config.status config.log + rm -f subst summary + rm -f $(SRC_CONTRIB)/ssi/status-header.ssi + +devclean: distclean + +install-html: + cd $(SRC_SHARE) && $(MAKE) install + +install-base: + cd $(SRC_BASE) && $(MAKE) install + +install-man: + cd $(SRC_MAN) && $(MAKE) install + +install-processperfdata: + cd $(SRC_SCRIPTS) && $(MAKE) install + +install-init: + cd $(SRC_SCRIPTS) && $(MAKE) $@ + +install-config: + cd $(SRC_CONFIG) && $(MAKE) $@ + + @echo "" + @echo "*** PNP4Nagios sample config files installed ***" + @echo "" + @echo "Please run 'make install-init' if you want to use" + @echo "BULK Mode with NPCD" + @echo "" + @echo "" + @echo "" + +install-webconf: + cd $(SRC_CONFIG) && $(MAKE) $@ + + + @echo "" + @echo "*** Apache config file installed ***" + @echo "" + @echo "Restart your apache webserver to activete your changes." + @echo "" + @echo "Please run 'make install-config' to install sample" + @echo "configuration files" + @echo "" + @echo "Please run 'make install-init' if you want to use" + @echo "BULK Mode with NPCD" + @echo "" + @echo "" + @echo "" + +install-plugins: + cd $(SRC_SCRIPTS) && $(MAKE) $@ + +install: + cd $(SRC_BASE) && $(MAKE) $@ + cd $(SRC_MAN) && $(MAKE) $@ + cd $(SRC_SHARE) && $(MAKE) $@ + if [ x$(KOHANA) = xyes ]; then \ + cd $(SRC_LIB) && $(MAKE) $@; \ + fi + + cd $(SRC_SCRIPTS) && $(MAKE) $@ + cd $(SRC_CONFIG) && $(MAKE) $@ + + @echo "" + @echo "*** Main program, Scripts and HTML files installed ***" + @echo "" + @echo "Please run 'make install-webconf' to install the" + @echo "web configuration file" + @echo "" + @echo "Please run 'make install-config' to install sample" + @echo "configuration files" + @echo "" + @echo "Please run 'make install-init' if you want to use" + @echo "BULK Mode with NPCD" + @echo "" + @echo "" + @echo "" + +install-unstripped: + cd $(SRC_BASE) && $(MAKE) $@ + cd $(SRC_SHARE) && $(MAKE) $@ + cd $(SRC_SCRIPTS) && $(MAKE) $@ + $(MAKE) install-basic + +fullinstall: install install-webconf install-config install-init + + $(PERL) summary fullinstall + @echo "" + @echo "*** Main program, Scripts and HTML files installed ***" + @echo "" + @echo "Enjoy." + @echo "" + diff --git a/README b/README new file mode 100644 index 0000000..72010fd --- /dev/null +++ b/README @@ -0,0 +1,10 @@ +######################### +# # +# README # +# # +######################### + +See our online documentation at: + +http://pnp4nagios.sourceforge.net or: +http://docs.pnp4nagios.org/ diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..94b9a83 --- /dev/null +++ b/THANKS @@ -0,0 +1,85 @@ +########################################### +# PNP Thanks # +########################################### + +Olivier PLATHEY - For providing FPDF +Sven Nierlein - For providing mod_gearman +Michal Wojciechowski - For providing imgAreaSelect + +Hendrik Baecker - Testing, debugging and english Translation +Olaf Reiss - Testing +Andreas Koch - Testing +Christian Mies - check_nwstat Templates, Testing +Sebastian Schubert - Internal Design +Stephan von Gehlen - Testing and Feedback +Geoffrey Walton - Feedback and Translation +Frank J. Heym - process_perfdata.pl Patch for check_nrpe Templates +Rudolf Labuschagne - Testing PNP in distributed setups +Sven Velt - Multigraph Layout +Sonja Scholz - Documentation +Andrea Gabellini - +Matthias Flittener - Bugreport +Ton Kersten - Dutch Language +Matthias Flacke - check_multi development, npcd load patch +Markus Dorfer - +Christian Claus - Debugging 64bit Counter +Herbert Straub +Wolfgang Nieder - English translation, verify-script, nitpicking +Max Schubert - +Wolfgang Barth - +Ethan Galstad - Patches and Feedback +Jan Dreyer - Solaris debugging +Jean-Marie Le Borgne - French Translation +Steffen Waitz - ./configure Patch +Lars Michelsen - +Philipp Deneu - +Thomas Stolle - Debugging and testing +Benjamin Ritcey - Patches +Franky Van Liedekerke - Testing +Simon Meggle - Testing / Patches +Mattias Ryrlén - Patches +Nicolas Graziano - Patches +Joe Precious - Testing +Stefan Priebe - Patches +Carlos de Nova - i18n +Stefan Hoesl - Testing +Trond Hasle Amundsen - Template check_openmanage +Silvan Hunkirchen - Bugreport +Petr Maizner - Bugreport +Steve Finkelstein - Bugreport +Mathias Kettner - xml write delay +Yannig Parre - i18n fr_FR +Laurent Freval - Patches and feedback +Beau Gunderson - Patches and feedback +Thomas Sesselmann - Patches and feedback +Vladimir Bilik - Feedback +Matthew Garrett - +Thomas Charbonnel - nginx webserver config +Richard Allen - Patches and feedback +Falko Koglin - Patches +Jochen Bern - Patches +Mike Liebsch - Patches +Joram Agten - Patches +Juergen-Michael Radtke - Bugreport +Robert Becht - Feedback +Lars Vogdt - Patches +Birger Schmidt - Patches +Andreas Doehler - Patches +Christoph Anton Mitterer - Patches and feedback +Rene Koch - Patches +Craig Barraclough - Patches +Martin Schirrmacher - Patches +Pekka Panula - Bugreport +Dennis Lamers - Bugreport and Patches +Robert Steininger - Patches +Ricardo Bartels - Patches +Miriam Zenk - Patches + +########################################### +# NPCD Thanks # +########################################### + +Joerg Linge - for giving so much ideas what I have to do ;) +Ethan Galstad - for many useful code to learn from +Carsten Schlosser - for all the time I can disturb him to ask silly pointer questions +My Girlfriend Katrin (without 'h') - for spending so much time without me diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..d407b8c --- /dev/null +++ b/config.guess @@ -0,0 +1,1526 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-23' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..6759825 --- /dev/null +++ b/config.sub @@ -0,0 +1,1658 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-16' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..f0756a8 --- /dev/null +++ b/configure @@ -0,0 +1,7104 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.61 for pnp 0.6.24. +# +# Report bugs to . +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='pnp' +PACKAGE_TARNAME='pnp' +PACKAGE_VERSION='0.6.24' +PACKAGE_STRING='pnp 0.6.24' +PACKAGE_BUGREPORT='pnp4nagios-devel@lists.sourceforge.net' + +ac_unique_file="src/" +ac_default_prefix=/usr/local/pnp4nagios +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +PKG_NAME +PKG_VERSION +PKG_HOME_URL +PKG_REL_DATE +ac_configure_args +XML_STRUCTURE_VERSION +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +INSTALL +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +SET_MAKE +STRIP +CP +CPP +GREP +EGREP +LIBOBJS +KOHANA +KOHANA_SYSTEM +nagios_user +nagios_grp +INSTALL_OPTS +PERL +PERL_LIB_PATH +RRDTOOL +PERFDATA_LOG +PERFDATA_DIR +PERFDATA_SPOOL_DIR +DEBUG +HTTPD_CONF +BASE_URL +init_dir +pnpsender_name +npcd_name +pp_pl_name +MOD_CFLAGS +MOD_LDFLAGS +RRDS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures pnp 0.6.24 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/pnp] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of pnp 0.6.24:";; + esac + cat <<\_ACEOF + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-layout=\default,debian\ sets directory layout + --without-kohana does not install the kohana framework + --with-kohana_system= Points to an already installed kohana framework + --with-nagios-user= sets user name to run nagios + --with-nagios-group= sets group name to run nagios + --with-perl_lib_path= sets path to rrdtool RRDs perl modules. + --with-rrdtool= sets path to rrdtool + --with-perfdata-logfile= Tell me where I should store the 'process_perfdata.pl' Logfile + --with-perfdata-dir= Tell me where I should store the RRD Database Files + --with-perfdata-spool-dir= Tell me where I should store perfdata files for bulk mode with npcd + --with-debug Enable debuging for process_perfdata.pl + --with-httpd-conf= sets path to Apache conf.d directory + --with-base-url=/${PKG_NAME} + --with-init-dir= sets directory to place init script into + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +pnp configure 0.6.24 +generated by GNU Autoconf 2.61 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by pnp $as_me 0.6.24, which was +generated by GNU Autoconf 2.61. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_config_headers="$ac_config_headers include/config.h:include/config.h.in" + + + + +cat >>confdefs.h <<\_ACEOF +#define DEFAULT_NAGIOS_USER nagios +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define DEFAULT_NAGIOS_GROUP nagios +_ACEOF + + +PKG_NAME=pnp4nagios +PKG_VERSION="0.6.24" +PKG_HOME_URL="http://www.pnp4nagios.org/pnp/start" +PKG_REL_DATE="30-07-2014" + + + + + +XML_STRUCTURE_VERSION="4" + + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + +#dnl What OS are we running? +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } +set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + SET_MAKE= +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $STRIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_STRIP" && ac_cv_path_STRIP="true" + ;; +esac +fi +STRIP=$ac_cv_path_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + + + +# Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CP="$CP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +CP=$ac_cv_path_CP +if test -n "$CP"; then + { echo "$as_me:$LINENO: result: $CP" >&5 +echo "${ECHO_T}$CP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +# Checks for libraries. + +# Checks for header files. + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_sys_wait_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + +#AC_CHECK_HEADERS(netinet/in.h string.h sys/socket.h unistd.h stdio.h stdlib.h getopt.h signal.h) +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + + + + + + + + + + +for ac_header in dirent.h stdio.h errno.h unistd.h syslog.h signal.h stdlib.h dirent.h string.h pthread.h getopt.h grp.h pwd.h sys/mman.h sys/types.h sys/wait.h sys/stat.h sys/socket.h sys/loadavg.h netinet/in.h fcntl.h limits.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------------------------- ## +## Report this to pnp4nagios-devel@lists.sourceforge.net ## +## ----------------------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +{ echo "$as_me:$LINENO: checking for pid_t" >&5 +echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; } +if test "${ac_cv_type_pid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef pid_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_pid_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_pid_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +echo "${ECHO_T}$ac_cv_type_pid_t" >&6; } +if test $ac_cv_type_pid_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5 +echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; } +if test "${ac_cv_type_signal+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_signal=int +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_signal=void +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 +echo "${ECHO_T}$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +{ echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5 +echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6; } +if test "${ac_cv_type_uid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1; then + ac_cv_type_uid_t=yes +else + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5 +echo "${ECHO_T}$ac_cv_type_uid_t" >&6; } +if test $ac_cv_type_uid_t = no; then + +cat >>confdefs.h <<\_ACEOF +#define uid_t int +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define gid_t int +_ACEOF + +fi + + +# Checks for structure members +#AC_CHECK_MEMBER([struct dirent.d_type], [AC_MSG_RESULT([We successfully have a `dirent_d_type'!])], +# [AC_MSG_ERROR([We need `dirent.d_type'!])], +# [#include ]) + + + + { echo "$as_me:$LINENO: checking for struct dirent.d_type" >&5 +echo $ECHO_N "checking for struct dirent.d_type... $ECHO_C" >&6; } +if test "${ac_cv_member_struct_dirent_d_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#ifdef HAVE_DIRENT_H +# include +#else +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + + +int +main () +{ +static struct dirent ac_aggr; +if (ac_aggr.d_type) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_dirent_d_type=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#ifdef HAVE_DIRENT_H +# include +#else +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + + +int +main () +{ +static struct dirent ac_aggr; +if (sizeof ac_aggr.d_type) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_member_struct_dirent_d_type=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_member_struct_dirent_d_type=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_dirent_d_type" >&5 +echo "${ECHO_T}$ac_cv_member_struct_dirent_d_type" >&6; } +if test $ac_cv_member_struct_dirent_d_type = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_DIRENT_D_TYPE 1 +_ACEOF + + +fi + + + +# Checks for library functions. + +for ac_header in vfork.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------------------------- ## +## Report this to pnp4nagios-devel@lists.sourceforge.net ## +## ----------------------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_func in fork vfork +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test "x$ac_cv_func_fork" = xyes; then + { echo "$as_me:$LINENO: checking for working fork" >&5 +echo $ECHO_N "checking for working fork... $ECHO_C" >&6; } +if test "${ac_cv_func_fork_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_fork_works=cross +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* By Ruediger Kuhlmann. */ + return fork () < 0; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_fork_works=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_fork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_fork_works" >&5 +echo "${ECHO_T}$ac_cv_func_fork_works" >&6; } + +else + ac_cv_func_fork_works=$ac_cv_func_fork +fi +if test "x$ac_cv_func_fork_works" = xcross; then + case $host in + *-*-amigaos* | *-*-msdosdjgpp*) + # Override, as these systems have only a dummy fork() stub + ac_cv_func_fork_works=no + ;; + *) + ac_cv_func_fork_works=yes + ;; + esac + { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 +echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} +fi +ac_cv_func_vfork_works=$ac_cv_func_vfork +if test "x$ac_cv_func_vfork" = xyes; then + { echo "$as_me:$LINENO: checking for working vfork" >&5 +echo $ECHO_N "checking for working vfork... $ECHO_C" >&6; } +if test "${ac_cv_func_vfork_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_vfork_works=cross +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Thanks to Paul Eggert for this test. */ +$ac_includes_default +#include +#ifdef HAVE_VFORK_H +# include +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. The compiler + is told about this with #include , but some compilers + (e.g. gcc -O) don't grok . Test for this by using a + static variable whose address is put into a register that is + clobbered by the vfork. */ +static void +#ifdef __cplusplus +sparc_address_test (int arg) +# else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} + +int +main () +{ + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (0); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. This + test uses lots of local variables, at least as many local + variables as main has allocated so far including compiler + temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris + 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should + reuse the register of parent for one of the local variables, + since it will think that parent can't possibly be used any more + in this routine. Assigning to the local variable will thus + munge parent in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent + from child file descriptors. If the child closes a descriptor + before it execs or exits, this munges the parent's descriptor + as well. Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + return ( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_vfork_works=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_vfork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_vfork_works" >&5 +echo "${ECHO_T}$ac_cv_func_vfork_works" >&6; } + +fi; +if test "x$ac_cv_func_fork_works" = xcross; then + ac_cv_func_vfork_works=$ac_cv_func_vfork + { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 +echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} +fi + +if test "x$ac_cv_func_vfork_works" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WORKING_VFORK 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define vfork fork +_ACEOF + +fi +if test "x$ac_cv_func_fork_works" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WORKING_FORK 1 +_ACEOF + +fi + + + + + + + +for ac_func in bzero socket alarm strerror strspn getloadavg +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +for ac_header in stdlib.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------------------------- ## +## Report this to pnp4nagios-devel@lists.sourceforge.net ## +## ----------------------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5 +echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; } +if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_malloc_0_nonnull=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_malloc_0_nonnull=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5 +echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MALLOC 1 +_ACEOF + +else + cat >>confdefs.h <<\_ACEOF +#define HAVE_MALLOC 0 +_ACEOF + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<\_ACEOF +#define malloc rpl_malloc +_ACEOF + +fi + + + +{ echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5 +echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; } +if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f conftest.sym conftest.file +echo >conftest.file +if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then + if test "$cross_compiling" = yes; then + ac_cv_func_lstat_dereferences_slashed_symlink=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + /* Linux will dereference the symlink and fail. + That is better in the sense that it means we will not + have to compile and use the lstat wrapper. */ + return lstat ("conftest.sym/", &sbuf) == 0; + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_lstat_dereferences_slashed_symlink=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +else + # If the `ln -s' command failed, then we probably don't even + # have an lstat function. + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f conftest.sym conftest.file + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 +echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } + +test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && + +cat >>confdefs.h <<_ACEOF +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 +_ACEOF + + +if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then + case " $LIBOBJS " in + *" lstat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS lstat.$ac_objext" + ;; +esac + +fi + +{ echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5 +echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; } +if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_stat_empty_string_bug=yes +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + return stat ("", &sbuf) == 0; + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_stat_empty_string_bug=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_stat_empty_string_bug=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5 +echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; } +if test $ac_cv_func_stat_empty_string_bug = yes; then + case " $LIBOBJS " in + *" stat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS stat.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_STAT_EMPTY_STRING_BUG 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + +layout="default" + +# Check whether --with-layout was given. +if test "${with_layout+set}" = set; then + withval=$with_layout; layout=$withval +fi + + +case $layout in + debian) + prefix="/" + sysconfdir="/etc/${PKG_NAME}" + localstatedir="/var/log/${PKG_NAME}" + libexecdir="/usr/lib/${PKG_NAME}/libexec" + libdir="/usr/lib/${PKG_NAME}" + datarootdir="/usr/share/${PKG_NAME}/html" + PERFDATA_LOG="/var/log/${PKG_NAME}/perfdata.log" + PERFDATA_DIR="/var/lib/${PKG_NAME}/perfdata" + PERFDATA_SPOOL_DIR="/var/spool/${PKG_NAME}" + bindir="/usr/bin" + sbindir="/usr/sbin" + ;; + default-0.4) + prefix="/usr/local/nagios" + sysconfdir="\${prefix}/etc/pnp" + localstatedir="\${prefix}/var" + libexecdir="\${prefix}/libexec" + datarootdir="\${prefix}/share/pnp" + libdir="\${prefix}/lib/pnp" + PERFDATA_LOG="\${prefix}/var/perfdata.log" + PERFDATA_DIR="\${prefix}/share/perfdata" + PERFDATA_SPOOL_DIR="\${prefix}/var/spool/perfdata" + ;; + default) + PERFDATA_LOG="${localstatedir}/perfdata.log" + PERFDATA_DIR="${localstatedir}/perfdata" + PERFDATA_SPOOL_DIR="${localstatedir}/spool" + mandir="\${prefix}/man" + ;; +esac + + +# Check whether --with-kohana was given. +if test "${with_kohana+set}" = set; then + withval=$with_kohana; KOHANA=no +else + KOHANA=yes +fi + + + +# Check whether --with-kohana_system was given. +if test "${with_kohana_system+set}" = set; then + withval=$with_kohana_system; KOHANA_SYSTEM=$withval +else + KOHANA_SYSTEM=$libdir/kohana/system +fi + + + +# Check whether --with-nagios_user was given. +if test "${with_nagios_user+set}" = set; then + withval=$with_nagios_user; nagios_user=$withval +else + nagios_user=nagios +fi + + +# Check whether --with-nagios_group was given. +if test "${with_nagios_group+set}" = set; then + withval=$with_nagios_group; nagios_grp=$withval +else + nagios_grp=nagios +fi + + + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_NAGIOS_USER "$nagios_user" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_NAGIOS_GROUP "$nagios_grp" +_ACEOF + +INSTALL_OPTS="-o $nagios_user -g $nagios_grp" + + +# Checks for programs. +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PERL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { echo "$as_me:$LINENO: result: $PERL" >&5 +echo "${ECHO_T}$PERL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Check for Perl lib path +PERL_LIB_PATH=no + +# Check whether --with-perl_lib_path was given. +if test "${with_perl_lib_path+set}" = set; then + withval=$with_perl_lib_path; PERL_LIB_PATH=$withval +else + PERL_LIB_PATH=no +fi + + +# Check for rrdtool +RRDTOOL=no + +# Check whether --with-rrdtool was given. +if test "${with_rrdtool+set}" = set; then + withval=$with_rrdtool; RRDTOOL=$withval +else + RRDTOOL=no +fi + +if test RRDTOOL=no; then + # Extract the first word of "rrdtool", so it can be a program name with args. +set dummy rrdtool; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_RRDTOOL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RRDTOOL in + [\\/]* | ?:[\\/]*) + ac_cv_path_RRDTOOL="$RRDTOOL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_RRDTOOL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +RRDTOOL=$ac_cv_path_RRDTOOL +if test -n "$RRDTOOL"; then + { echo "$as_me:$LINENO: result: $RRDTOOL" >&5 +echo "${ECHO_T}$RRDTOOL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi + +{ echo "$as_me:$LINENO: checking rrdtool path $RRDTOOL" >&5 +echo $ECHO_N "checking rrdtool path $RRDTOOL... $ECHO_C" >&6; } +if test -d $RRDTOOL ;then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: $RRDTOOL is a directory! PNP needs the Path to the rrdtool binary!" >&5 +echo "$as_me: error: $RRDTOOL is a directory! PNP needs the Path to the rrdtool binary!" >&2;} + { (exit 1); exit 1; }; } +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +{ echo "$as_me:$LINENO: checking for executable Bit on $RRDTOOL" >&5 +echo $ECHO_N "checking for executable Bit on $RRDTOOL... $ECHO_C" >&6; } +if ! test -x $RRDTOOL ;then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: $RRDTOOL is not executable!" >&5 +echo "$as_me: error: $RRDTOOL is not executable!" >&2;} + { (exit 1); exit 1; }; } +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + + + + + +# Check whether --with-perfdata-logfile was given. +if test "${with_perfdata_logfile+set}" = set; then + withval=$with_perfdata_logfile; PERFDATA_LOG=$withval + +fi + + + + + +# Check whether --with-perfdata-dir was given. +if test "${with_perfdata_dir+set}" = set; then + withval=$with_perfdata_dir; PERFDATA_DIR=$withval + +fi + + + + +# Check whether --with-perfdata-spool-dir was given. +if test "${with_perfdata_spool_dir+set}" = set; then + withval=$with_perfdata_spool_dir; PERFDATA_SPOOL_DIR=$withval + +fi + + + + +# Check whether --with-debug was given. +if test "${with_debug+set}" = set; then + withval=$with_debug; DEBUG="2" +else + DEBUG="0" + +fi + + + +HTTP_CONF=no + +# Check whether --with-httpd_conf was given. +if test "${with_httpd_conf+set}" = set; then + withval=$with_httpd_conf; HTTPD_CONF=$withval +else + HTTPD_CONF=no +fi + +if test x$HTTPD_CONF = xno; then + if test -d /etc/httpd/conf.d; then + HTTPD_CONF="/etc/httpd/conf.d" + elif test -d /etc/apache2/conf.d; then + HTTPD_CONF="/etc/apache2/conf.d" + elif test -d /etc/apache/conf.d; then + HTTPD_CONF="/etc/apache/conf.d" + else + HTTPD_CONF="/etc/httpd/conf.d" + fi +fi + + +init_dir=/etc/rc.d/init.d +if test -d /etc/rc.d/init.d; then + init_dir="/etc/rc.d/init.d" +elif test -d /usr/local/etc/rc.d; then + init_dir="/usr/local/etc/rc.d" +elif test -d /etc/rc.d; then + init_dir="/etc/rc.d" +elif test -d /etc/init.d; then + init_dir="/etc/init.d" +elif test -d /sbin/init.d; then + init_dir="/sbin/init.d" +fi + +BASE_URL=${PKG_NAME} + +# Check whether --with-base-url was given. +if test "${with_base_url+set}" = set; then + withval=$with_base_url; BASE_URL=$withval +else + BASE_URL=/${PKG_NAME} +fi + + + + +# Check whether --with-init_dir was given. +if test "${with_init_dir+set}" = set; then + withval=$with_init_dir; init_dir=$withval +fi + + + +pnpsender_name=pnpsender + + +npcd_name=npcd + + +pp_pl_name=process_perfdata.pl + + +{ echo "$as_me:$LINENO: checking for linker flags for loadable modules" >&5 +echo $ECHO_N "checking for linker flags for loadable modules... $ECHO_C" >&6; } +case $host_os in + solaris2*|sysv4*) + MOD_LDFLAGS="-G" + ;; + aix4*|aix5*|aix6*|aix7*) + #MOD_LDFLAGS="-G -bnoentry -bexpall" + MOD_LDFLAGS="-shared -Wl,-G -Wl,-bM:SRE -Wl,-bnoentry -Wl,-bexpall" + ;; + freebsd2*) + # Non-ELF GNU linker + MOD_LDFLAGS="-Bshareable" + ;; + darwin*) + # Mach-O linker, a shared lib and a loadable + # object file is not the same thing. + MOD_LDFLAGS="-bundle -flat_namespace -undefined suppress" + MOD_CFLAGS="$MOD_CFLAGS -fno-common" + ;; + linux* | k*bsd*-gnu*) + # assume GNU linker and ELF + MOD_LDFLAGS="-shared" + MOD_CFLAGS="-fPIC" + ;; + *) + # assume GNU linker and ELF + MOD_LDFLAGS="-shared" + ;; +esac +{ echo "$as_me:$LINENO: result: $MOD_LDFLAGS" >&5 +echo "${ECHO_T}$MOD_LDFLAGS" >&6; } + + + +# +# Checking for Perl Modules +# +{ echo "$as_me:$LINENO: checking for Perl Module Time::HiRes" >&5 +echo $ECHO_N "checking for Perl Module Time::HiRes... $ECHO_C" >&6; } +$PERL -MTime::HiRes -e exit >/dev/null 2>&1 +if test $? -ne 0; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: Perl Module Time::HiRes not available" >&5 +echo "$as_me: error: Perl Module Time::HiRes not available" >&2;} + { (exit 1); exit 1; }; } +else + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +fi + +{ echo "$as_me:$LINENO: checking for Perl Module Getopt::Long" >&5 +echo $ECHO_N "checking for Perl Module Getopt::Long... $ECHO_C" >&6; } +$PERL -MGetopt::Long -e exit >/dev/null 2>&1 +if test $? -ne 0; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: Perl Module Getopt::Long not available" >&5 +echo "$as_me: error: Perl Module Getopt::Long not available" >&2;} + { (exit 1); exit 1; }; } +else + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +fi + +RRDS=0 +{ echo "$as_me:$LINENO: checking for optional Perl Module RRDs" >&5 +echo $ECHO_N "checking for optional Perl Module RRDs... $ECHO_C" >&6; } +$PERL -I${PERL_LIB_PATH} -MRRDs -e exit >/dev/null 2>&1 +if test $? -ne 0; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { echo "$as_me:$LINENO: WARNING: Perl Module RRDs not available" >&5 +echo "$as_me: WARNING: Perl Module RRDs not available" >&2;} + RRDS=0 +else + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + RRDS=1 +fi + + +ac_config_files="$ac_config_files subst Makefile share/Makefile lib/Makefile scripts/Makefile src/Makefile sample-config/Makefile man/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by pnp $as_me 0.6.24, which was +generated by GNU Autoconf 2.61. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +pnp config.status 0.6.24 +configured by $0, generated by GNU Autoconf 2.61, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h:include/config.h.in" ;; + "subst") CONFIG_FILES="$CONFIG_FILES subst" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "share/Makefile") CONFIG_FILES="$CONFIG_FILES share/Makefile" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "sample-config/Makefile") CONFIG_FILES="$CONFIG_FILES sample-config/Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +PKG_NAME!$PKG_NAME$ac_delim +PKG_VERSION!$PKG_VERSION$ac_delim +PKG_HOME_URL!$PKG_HOME_URL$ac_delim +PKG_REL_DATE!$PKG_REL_DATE$ac_delim +ac_configure_args!$ac_configure_args$ac_delim +XML_STRUCTURE_VERSION!$XML_STRUCTURE_VERSION$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +INSTALL!$INSTALL$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +SET_MAKE!$SET_MAKE$ac_delim +STRIP!$STRIP$ac_delim +CP!$CP$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +KOHANA!$KOHANA$ac_delim +KOHANA_SYSTEM!$KOHANA_SYSTEM$ac_delim +nagios_user!$nagios_user$ac_delim +nagios_grp!$nagios_grp$ac_delim +INSTALL_OPTS!$INSTALL_OPTS$ac_delim +PERL!$PERL$ac_delim +PERL_LIB_PATH!$PERL_LIB_PATH$ac_delim +RRDTOOL!$RRDTOOL$ac_delim +PERFDATA_LOG!$PERFDATA_LOG$ac_delim +PERFDATA_DIR!$PERFDATA_DIR$ac_delim +PERFDATA_SPOOL_DIR!$PERFDATA_SPOOL_DIR$ac_delim +DEBUG!$DEBUG$ac_delim +HTTPD_CONF!$HTTPD_CONF$ac_delim +BASE_URL!$BASE_URL$ac_delim +init_dir!$init_dir$ac_delim +pnpsender_name!$pnpsender_name$ac_delim +npcd_name!$npcd_name$ac_delim +pp_pl_name!$pp_pl_name$ac_delim +MOD_CFLAGS!$MOD_CFLAGS$ac_delim +MOD_LDFLAGS!$MOD_LDFLAGS$ac_delim +RRDS!$RRDS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 91; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + + esac + +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +$PERL subst summary +$PERL subst scripts/process_perfdata.pl +$PERL subst scripts/rrd_convert.pl +$PERL subst scripts/rrd_modify.pl +$PERL subst scripts/rc.npcd +$PERL subst scripts/rc.pnp_gearman_worker +$PERL subst scripts/check_pnp_rrds.pl +$PERL subst share/pnp/index.php +$PERL subst share/pnp/install.php +$PERL subst sample-config/httpd.conf +$PERL subst sample-config/lighttpd.pnp4nagios.conf +$PERL subst sample-config/nginx.pnp4nagios.conf +$PERL subst sample-config/nagios.cfg-sample +$PERL subst sample-config/misccommands.cfg-sample +$PERL subst sample-config/pnp/config.php +$PERL subst sample-config/pnp/npcd.cfg-sample +$PERL subst sample-config/pnp/process_perfdata.cfg-sample +$PERL subst sample-config/pnp/pnp4nagios_release +$PERL subst contrib/ssi/status-header.ssi +$PERL subst man/npcd.8 + +$PERL summary diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..3a4098d --- /dev/null +++ b/configure.ac @@ -0,0 +1,313 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.61) +AC_INIT(pnp, 0.6.24, pnp4nagios-devel@lists.sourceforge.net) +AC_CONFIG_SRCDIR(src/) +AC_CONFIG_HEADERS(include/config.h:include/config.h.in) +AC_PREFIX_DEFAULT(/usr/local/pnp4nagios) + +AC_DEFINE([DEFAULT_NAGIOS_USER], [nagios], [Default Nagios User]) +AC_DEFINE([DEFAULT_NAGIOS_GROUP], [nagios], [Default Nagios Group]) + +PKG_NAME=pnp4nagios +PKG_VERSION="0.6.24" +PKG_HOME_URL="http://www.pnp4nagios.org/pnp/start" +PKG_REL_DATE="30-07-2014" +AC_SUBST(PKG_NAME) +AC_SUBST(PKG_VERSION) +AC_SUBST(PKG_HOME_URL) +AC_SUBST(PKG_REL_DATE) +AC_SUBST(ac_configure_args) +XML_STRUCTURE_VERSION="4" +AC_SUBST(XML_STRUCTURE_VERSION) + +dnl Figure out how to invoke "install" and what install options to use. + +AC_PROG_INSTALL +AC_SUBST(INSTALL) + +#dnl What OS are we running? +AC_CANONICAL_HOST + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_MAKE_SET +AC_PATH_PROG([STRIP],[strip],[true]) + + + +AC_PATH_PROG(CP,cp) + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC +AC_HEADER_DIRENT +AC_HEADER_SYS_WAIT +#AC_CHECK_HEADERS(netinet/in.h string.h sys/socket.h unistd.h stdio.h stdlib.h getopt.h signal.h) +AC_CHECK_HEADERS(dirent.h stdio.h errno.h unistd.h syslog.h signal.h stdlib.h dirent.h string.h pthread.h getopt.h grp.h pwd.h sys/mman.h sys/types.h sys/wait.h sys/stat.h sys/socket.h sys/loadavg.h netinet/in.h fcntl.h limits.h) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_PID_T +AC_TYPE_SIGNAL +AC_TYPE_UID_T + +# Checks for structure members +#AC_CHECK_MEMBER([struct dirent.d_type], [AC_MSG_RESULT([We successfully have a `dirent_d_type'!])], +# [AC_MSG_ERROR([We need `dirent.d_type'!])], +# [#include ]) + +AC_STRUCT_DIRENT_D_TYPE + +# Checks for library functions. +AC_FUNC_FORK +AC_CHECK_FUNCS([bzero socket alarm strerror strspn getloadavg]) + +AC_FUNC_MALLOC +AC_FUNC_STAT + +AC_C_CONST + +dnl Layout Methods +layout="default" +AC_ARG_WITH(layout,[ --with-layout=\[default,debian\] sets directory layout],layout=$withval) + +case $layout in + debian) + prefix="/" + sysconfdir="/etc/${PKG_NAME}" + localstatedir="/var/log/${PKG_NAME}" + libexecdir="/usr/lib/${PKG_NAME}/libexec" + libdir="/usr/lib/${PKG_NAME}" + datarootdir="/usr/share/${PKG_NAME}/html" + PERFDATA_LOG="/var/log/${PKG_NAME}/perfdata.log" + PERFDATA_DIR="/var/lib/${PKG_NAME}/perfdata" + PERFDATA_SPOOL_DIR="/var/spool/${PKG_NAME}" + bindir="/usr/bin" + sbindir="/usr/sbin" + ;; + default-0.4) + prefix="/usr/local/nagios" + sysconfdir="\${prefix}/etc/pnp" + localstatedir="\${prefix}/var" + libexecdir="\${prefix}/libexec" + datarootdir="\${prefix}/share/pnp" + libdir="\${prefix}/lib/pnp" + PERFDATA_LOG="\${prefix}/var/perfdata.log" + PERFDATA_DIR="\${prefix}/share/perfdata" + PERFDATA_SPOOL_DIR="\${prefix}/var/spool/perfdata" + ;; + default) + PERFDATA_LOG="${localstatedir}/perfdata.log" + PERFDATA_DIR="${localstatedir}/perfdata" + PERFDATA_SPOOL_DIR="${localstatedir}/spool" + mandir="\${prefix}/man" + ;; +esac + +AC_ARG_WITH(kohana,[ --without-kohana does not install the kohana framework],KOHANA=no,KOHANA=yes) +AC_SUBST(KOHANA) +AC_ARG_WITH(kohana_system,[ --with-kohana_system= Points to an already installed kohana framework],KOHANA_SYSTEM=$withval,KOHANA_SYSTEM=$libdir/kohana/system) +AC_SUBST(KOHANA_SYSTEM) +AC_ARG_WITH(nagios_user,[ --with-nagios-user= sets user name to run nagios],nagios_user=$withval,nagios_user=nagios) +AC_ARG_WITH(nagios_group,[ --with-nagios-group= sets group name to run nagios],nagios_grp=$withval,nagios_grp=nagios) +AC_SUBST(nagios_user) +AC_SUBST(nagios_grp) +AC_DEFINE_UNQUOTED(DEFAULT_NAGIOS_USER,"$nagios_user") +AC_DEFINE_UNQUOTED(DEFAULT_NAGIOS_GROUP,"$nagios_grp") +INSTALL_OPTS="-o $nagios_user -g $nagios_grp" +AC_SUBST(INSTALL_OPTS) + +# Checks for programs. +AC_PATH_PROG(PERL,perl) +# Check for Perl lib path +PERL_LIB_PATH=no +AC_ARG_WITH(perl_lib_path,[ --with-perl_lib_path= sets path to rrdtool RRDs perl modules.],PERL_LIB_PATH=$withval,PERL_LIB_PATH=no) +AC_SUBST(PERL_LIB_PATH) +# Check for rrdtool +RRDTOOL=no +AC_ARG_WITH(rrdtool,[ --with-rrdtool= sets path to rrdtool],RRDTOOL=$withval,RRDTOOL=no) +if test RRDTOOL=no; then + AC_PATH_PROG(RRDTOOL,rrdtool) +fi + +AC_MSG_CHECKING(rrdtool path $RRDTOOL) +if [ test -d $RRDTOOL ];then + AC_MSG_RESULT(no) + AC_MSG_ERROR([$RRDTOOL is a directory! PNP needs the Path to the rrdtool binary!]) +fi +AC_MSG_RESULT(yes) +AC_MSG_CHECKING(for executable Bit on $RRDTOOL) +if [ ! test -x $RRDTOOL] ;then + AC_MSG_RESULT(no) + AC_MSG_ERROR([$RRDTOOL is not executable!]) +fi +AC_MSG_RESULT(yes) + +AC_SUBST(RRDTOOL) + + +AC_ARG_WITH(perfdata-logfile,[ --with-perfdata-logfile= Tell me where I should store the 'process_perfdata.pl' Logfile], + PERFDATA_LOG=$withval + ) +AC_SUBST(PERFDATA_LOG) + + +AC_ARG_WITH(perfdata-dir,[ --with-perfdata-dir= Tell me where I should store the RRD Database Files], + PERFDATA_DIR=$withval + ) +AC_SUBST(PERFDATA_DIR) + +AC_ARG_WITH(perfdata-spool-dir,[ --with-perfdata-spool-dir= Tell me where I should store perfdata files for bulk mode with npcd], + PERFDATA_SPOOL_DIR=$withval + ) +AC_SUBST(PERFDATA_SPOOL_DIR) + +AC_ARG_WITH(debug,[ --with-debug Enable debuging for process_perfdata.pl], + DEBUG="2", + DEBUG="0" + ) +AC_SUBST(DEBUG) + +dnl Check for location of Apache conf.d directory +HTTP_CONF=no +AC_ARG_WITH(httpd_conf,[ --with-httpd-conf= sets path to Apache conf.d directory],HTTPD_CONF=$withval,HTTPD_CONF=no) +if test x$HTTPD_CONF = xno; then + if test -d /etc/httpd/conf.d; then + HTTPD_CONF="/etc/httpd/conf.d" + elif test -d /etc/apache2/conf.d; then + HTTPD_CONF="/etc/apache2/conf.d" + elif test -d /etc/apache/conf.d; then + HTTPD_CONF="/etc/apache/conf.d" + else + HTTPD_CONF="/etc/httpd/conf.d" + fi +fi +AC_SUBST(HTTPD_CONF) + +dnl Check for location of init scripts +init_dir=/etc/rc.d/init.d +if test -d /etc/rc.d/init.d; then + init_dir="/etc/rc.d/init.d" +elif test -d /usr/local/etc/rc.d; then + init_dir="/usr/local/etc/rc.d" +elif test -d /etc/rc.d; then + init_dir="/etc/rc.d" +elif test -d /etc/init.d; then + init_dir="/etc/init.d" +elif test -d /sbin/init.d; then + init_dir="/sbin/init.d" +fi + +BASE_URL=${PKG_NAME} +AC_ARG_WITH(base-url,[ --with-base-url=/${PKG_NAME} ],BASE_URL=$withval,BASE_URL=/${PKG_NAME}) +AC_SUBST(BASE_URL) + +dnl User can override init script location +AC_ARG_WITH(init_dir,[ --with-init-dir= sets directory to place init script into],init_dir=$withval) +AC_SUBST(init_dir) + +pnpsender_name=pnpsender +AC_SUBST(pnpsender_name) + +npcd_name=npcd +AC_SUBST(npcd_name) + +pp_pl_name=process_perfdata.pl +AC_SUBST(pp_pl_name) + +dnl - Modified version from www.erlang.org +dnl - Some 12/15/05 mods made after reading http://xaxxon.slackworks.com/phuku/dl.html +AC_MSG_CHECKING(for linker flags for loadable modules) +case $host_os in + solaris2*|sysv4*) + MOD_LDFLAGS="-G" + ;; + aix4*|aix5*|aix6*|aix7*) + #MOD_LDFLAGS="-G -bnoentry -bexpall" + MOD_LDFLAGS="-shared -Wl,-G -Wl,-bM:SRE -Wl,-bnoentry -Wl,-bexpall" + ;; + freebsd2*) + # Non-ELF GNU linker + MOD_LDFLAGS="-Bshareable" + ;; + darwin*) + # Mach-O linker, a shared lib and a loadable + # object file is not the same thing. + MOD_LDFLAGS="-bundle -flat_namespace -undefined suppress" + MOD_CFLAGS="$MOD_CFLAGS -fno-common" + ;; + linux* | k*bsd*-gnu*) + # assume GNU linker and ELF + MOD_LDFLAGS="-shared" + MOD_CFLAGS="-fPIC" + ;; + *) + # assume GNU linker and ELF + MOD_LDFLAGS="-shared" + ;; +esac +AC_MSG_RESULT([$MOD_LDFLAGS]) +AC_SUBST(MOD_CFLAGS) +AC_SUBST(MOD_LDFLAGS) + +# +# Checking for Perl Modules +# +AC_MSG_CHECKING(for Perl Module Time::HiRes) +$PERL -MTime::HiRes -e exit >/dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_RESULT(no) + AC_MSG_ERROR(Perl Module Time::HiRes not available) +else + AC_MSG_RESULT(yes) +fi + +AC_MSG_CHECKING(for Perl Module Getopt::Long) +$PERL -MGetopt::Long -e exit >/dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_RESULT(no) + AC_MSG_ERROR(Perl Module Getopt::Long not available) +else + AC_MSG_RESULT(yes) +fi + +RRDS=0 +AC_MSG_CHECKING(for optional Perl Module RRDs) +$PERL -I${PERL_LIB_PATH} -MRRDs -e exit >/dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_RESULT(no) + AC_MSG_WARN(Perl Module RRDs not available) + RRDS=0 +else + AC_MSG_RESULT(yes) + RRDS=1 +fi +AC_SUBST(RRDS) + +AC_CONFIG_FILES( subst Makefile share/Makefile lib/Makefile scripts/Makefile src/Makefile sample-config/Makefile man/Makefile ) +AC_OUTPUT() + +$PERL subst summary +$PERL subst scripts/process_perfdata.pl +$PERL subst scripts/rrd_convert.pl +$PERL subst scripts/rrd_modify.pl +$PERL subst scripts/rc.npcd +$PERL subst scripts/rc.pnp_gearman_worker +$PERL subst scripts/check_pnp_rrds.pl +$PERL subst share/pnp/index.php +$PERL subst share/pnp/install.php +$PERL subst sample-config/httpd.conf +$PERL subst sample-config/lighttpd.pnp4nagios.conf +$PERL subst sample-config/nginx.pnp4nagios.conf +$PERL subst sample-config/nagios.cfg-sample +$PERL subst sample-config/misccommands.cfg-sample +$PERL subst sample-config/pnp/config.php +$PERL subst sample-config/pnp/npcd.cfg-sample +$PERL subst sample-config/pnp/process_perfdata.cfg-sample +$PERL subst sample-config/pnp/pnp4nagios_release +$PERL subst contrib/ssi/status-header.ssi +$PERL subst man/npcd.8 + +$PERL summary diff --git a/contrib/pnp4nagios-gearman.spec b/contrib/pnp4nagios-gearman.spec new file mode 100644 index 0000000..dbcee38 --- /dev/null +++ b/contrib/pnp4nagios-gearman.spec @@ -0,0 +1,62 @@ +Name: pnp4nagios +Version: 0.6.7 +Release: 1 +License: GNU Public License version 2 +Packager: Olivier Raginel +Vendor: PNP4nagios team +URL: http://pnp4nagios.org +Prefix: /opt/pnp4nagios +Source: http://github.com/Babar/pnp4nagios/tarball/%{name}-%{version}.tar.gz +Group: Applications/Monitoring +Requires: perl(Gearman::Worker), perl(Crypt::Rijndael) +BuildRoot: %{_tmppath}/%{name}-%{version}-root-%(%{__id_u} -n) +Summary: Gearman version of pnp4nagios +Provides: pnp4nagios + +%description +From the web page (http://docs.pnp4nagios.org/pnp-0.6/start): + +PNP is an addon to Nagios which analyzes performance data provided by plugins +and stores them automatically into RRD-databases (Round Robin Databases, see +RRD Tool). + +This is the version with support for Gearman, suitable to use with mod_gearman. + +%prep +%setup -q + +%build +./configure --with-nagios-user=nagios \ + --with-nagios-group=nagios \ + --prefix=%{_prefix} \ + --libdir=%{_libdir}/%{name} \ + --sysconfdir=%{_sysconfdir}/%{name} \ + --localstatedir=%{_localstatedir} \ + --with-init-dir=%{_initrddir} \ + --with-layout=debian + +%{__make} all + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/%{_prefix} + +%{__make} install fullinstall DESTDIR=$RPM_BUILD_ROOT INIT_OPTS= INSTALL_OPTS= + +%clean +rm -rf $RPM_BUILD_ROOT + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%defattr(-,root,root) +%docdir %{_defaultdocdir} +%{_prefix} +%{_sysconfdir} +%defattr(-,nagios,root) +%{_localstatedir} + +%changelog +* Wed Oct 21 2010 Olivier Raginel +- First build diff --git a/contrib/pnp4nagios.spec b/contrib/pnp4nagios.spec new file mode 100644 index 0000000..1216f9d --- /dev/null +++ b/contrib/pnp4nagios.spec @@ -0,0 +1,128 @@ +# $Id:$ +# Upstream: pnp4nagios-devel@lists.sourceforge.net +Name: pnp4nagios +Version: 0.6.16 +Release: 1 +Summary: PNP is not PerfParse. A Nagios/Icinga perfdata graphing solution + +Group: Applications/System +License: GPLv2 +URL: http://www.pnp4nagios.org/ +Source: http://downloads.sourceforge.net/pnp4nagios/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root + +BuildRequires: rrdtool-devel +BuildRequires: perl-rrdtool +Requires: rrdtool +Requires: perl-rrdtool +Obsoletes: pnp + +%description +PNP is an addon to Nagios/Icinga which analyzes performance data provided by plugins and stores them automatically into RRD-databases. + +%prep +%setup + + +%build +sed -i -e 's/INSTALL_OPTS="-o $nagios_user -g $nagios_grp"/INSTALL_OPTS=""/' configure +sed -i -e 's/INIT_OPTS=-o root -g root/INIT_OPTS=/' scripts/Makefile.in +# hardcode that until a proper fix is upstream +sed -i -e 's/MANDIR=@mandir@/MANDIR=\/usr\/share\/man/' man/Makefile.in +%configure --with-perfdata-logfile=%{_localstatedir}/log/nagios/perfdata.log \ + --sysconfdir=%{_sysconfdir}/%{name} \ + --datarootdir=%{_datadir}/%{name} \ + --with-perfdata-dir=%{_datadir}/%{name}/perfdata \ + --with-perfdata-spool-dir=%{_localstatedir}/spool/nagios \ + --mandir=%{_mandir} \ + --libdir=%{_libdir}/%{name} # only kohana is installed there and maybe we have a system wide kohana already +make %{?_smp_mflags} all + + +%install +rm -rf %{buildroot} +%{__mkdir} -p %{buildroot}%{_sysconfdir}/httpd/conf.d/ +make fullinstall DESTDIR=%{buildroot} +mv %{buildroot}%{_sysconfdir}/%{name}/check_commands/check_nwstat.cfg-sample %{buildroot}%{_sysconfdir}/%{name}/check_commands/check_nwstat.cfg +mv %{buildroot}%{_sysconfdir}/%{name}/pages/web_traffic.cfg-sample %{buildroot}%{_sysconfdir}/%{name}/pages/web_traffic.cfg +mv %{buildroot}%{_sysconfdir}/%{name}/rra.cfg-sample %{buildroot}%{_sysconfdir}/%{name}/rra.cfg + +sed -i -e 's*log_file = /var/npcd.log*log_file = /var/log/nagios/npcd.log*' %{buildroot}%{_sysconfdir}/%{name}/npcd.cfg + +# drop local versioning, we already provide our own upgrade safety +rm -f %{buildroot}%{_sysconfdir}/%{name}/config.php.%{version} +rm -f %{buildroot}%{_sysconfdir}/%{name}/config_local.php + + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%defattr(-,nagios,nagios,-) +%doc AUTHORS +%doc ChangeLog +%doc COPYING +%doc INSTALL +%doc README +%doc THANKS +%config(noreplace) %{_sysconfdir}/%{name}/check_commands/check_all_local_disks.cfg-sample +%config(noreplace) %{_sysconfdir}/%{name}/check_commands/check_nrpe.cfg-sample +%config(noreplace) %{_sysconfdir}/%{name}/check_commands/check_nwstat.cfg +%config(noreplace) %{_sysconfdir}/%{name}/npcd.cfg +%config(noreplace) %{_sysconfdir}/%{name}/pages/web_traffic.cfg +%config(noreplace) %{_sysconfdir}/%{name}/process_perfdata.cfg +%config(noreplace) %{_sysconfdir}/%{name}/rra.cfg +%config(noreplace) %{_sysconfdir}/httpd/conf.d/%{name}.conf +%{_sysconfdir}/%{name}/background.pdf +%{_sysconfdir}/%{name}/config.php +%{_sysconfdir}/%{name}/misccommands.cfg-sample +%{_sysconfdir}/%{name}/nagios.cfg-sample +%{_sysconfdir}/%{name}/pnp4nagios_release +%attr(755,root,root) %{_sysconfdir}/rc.d/init.d/npcd +%attr(755,root,root) %{_sysconfdir}/rc.d/init.d/pnp_gearman_worker +%{_bindir}/npcd +%{_libdir}/pnp4nagios/npcdmod.o +%{_libdir}/%{name} +%{_libexecdir}/check_pnp_rrds.pl +%{_libexecdir}/process_perfdata.pl +%{_libexecdir}/rrd_convert.pl +%{_datadir}/%{name} +%{_mandir}/man8/npcd.8.gz + + +%changelog +* Mon Feb 06 2012 Michael Friedrich - 0.6.16-1 +- Updated to version 0.6.16. +- drop (Build)Requires nagios, we can use other core(s) as well +- verify_pnp_config.pl => verify_pnp_config_v2.pl not installed anymore +- npcd.cfg and process_perfdata.cfg get now installed by make install w/o -sample suffix +- recognize new initscript for pnp_gearman_worker +- autoremove versionized config.php, we use config(noreplace) +- drop config_local.php which would override default settings +- fix npcd.8 man page prefix install + +* Tue Feb 15 2011 Christoph Maser - 0.6.11-1 +- Updated to version 0.6.11. + +* Tue Aug 31 2010 Christoph Maser - 0.6.6-1 +- Updated to version 0.6.6. + +* Thu Dec 24 2009 Christoph Maser - 0.6.2 - 2 +- add --with-perfdata-spool-dir and --with-perfdata--dir +- mark httpd-config snippet as config file + +* Thu Dec 24 2009 Christoph Maser - 0.6.2 - 1 +- Update to version 0.6.2 +- Rename to pnp4nagios + +* Mon Mar 23 2009 Christoph Maser - 0.4.14 - 2 +- Update to version 0.4.14 + +* Mon Mar 23 2009 Christoph Maser - 0.4.13 - 2 +- modify log path +- add documentation files + +* Mon Mar 23 2009 Christoph Maser - 0.4.13 - 1 +- Initial package (using brain ;) + diff --git a/contrib/ssi/status-header.ssi.in b/contrib/ssi/status-header.ssi.in new file mode 100644 index 0000000..19a0e0e --- /dev/null +++ b/contrib/ssi/status-header.ssi.in @@ -0,0 +1,9 @@ + + + + diff --git a/helpers/kohana-install.sh b/helpers/kohana-install.sh new file mode 100755 index 0000000..c2b70af --- /dev/null +++ b/helpers/kohana-install.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# +# PNP4Nagios Helper Script +# +DIR=`dirname $0` +cd $DIR/../lib/kohana +for D in `find . -type d -printf "%P\n"`;do + if [ "$D" != "" ];then + echo -e "\t\$(INSTALL) -m 755 \$(INSTALL_OPTS) -d \$(DESTDIR)\$(LIBDIR)/kohana/$D" + fi +done +for F in `find . -type f -printf "%P\n"`;do + if [ "$F" != "" ];then + echo -e "\t\$(INSTALL) -m 644 \$(INSTALL_OPTS) kohana/$F \$(DESTDIR)\$(LIBDIR)/kohana/$F" + fi +done diff --git a/helpers/wiki2html.sh b/helpers/wiki2html.sh new file mode 100755 index 0000000..81e1c4f --- /dev/null +++ b/helpers/wiki2html.sh @@ -0,0 +1,42 @@ +#!/bin/bash +#set -xv +LANG="de en" +LANG_TARGET=(de_DE en_US) +FILES=( about advanced config doc_complete dwnld install modes new-features npcd pages perfdata_format rrdcached rrd_convert start timeranges tpl_helper tpl_helper_pnp tpl_custom tpl upgrade verify verify_pnp_config webfe_cfg webfe wrapper xport mobile ) + + +DESTDIR="../share/pnp/documents" +URL="http://docs.pnp4nagios.org" + +cd $DESTDIR + +lindex=0 +for L in $LANG; do + if [ "$L" == "en" ];then + PART="pnp-0.6" + else + PART="$L/pnp-0.6" + fi + + T=${LANG_TARGET[$lindex]} + mkdir $T + index=0 + documents=${#FILES[@]} + + while [ "$index" -lt "$documents" ];do + F=${FILES[$index]} + echo "$L $F" + wget -nv -O "${T}/${F}.html" "${URL}/${PART}/${F}?do=export_xhtmlbody" + sed -i -e's/ü/\ü/g' "${T}/${F}.html" + sed -i -e's/Ü/\Ü/g' "${T}/${F}.html" + sed -i -e's/ä/\ä/g' "${T}/${F}.html" + sed -i -e's/Ä/\Ä/g' "${T}/${F}.html" + sed -i -e's/ö/\ö/g' "${T}/${F}.html" + sed -i -e's/Ö/\Ö/g' "${T}/${F}.html" + ((index++)) + + done + ((lindex++)) +done +rm de_DE/dwnld.html +ln -s en_US/dwnld.html de_DE/dwnld.html diff --git a/include/broker.h b/include/broker.h new file mode 100644 index 0000000..abc6b52 --- /dev/null +++ b/include/broker.h @@ -0,0 +1,222 @@ +/***************************************************************************** + * + * BROKER.H - Event broker includes for Nagios + * + * Copyright (c) 2002-2006 Ethan Galstad (nagios@nagios.org) + * Last Modified: 12-12-2006 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + +#ifndef _BROKER_H +#define _BROKER_H + +#include "config.h" +#include "nagios.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/*************** EVENT BROKER OPTIONS *****************/ + +#define BROKER_NOTHING 0 +#define BROKER_EVERYTHING 1048575 + +#define BROKER_PROGRAM_STATE 1 /* DONE */ +#define BROKER_TIMED_EVENTS 2 /* DONE */ +#define BROKER_SERVICE_CHECKS 4 /* DONE */ +#define BROKER_HOST_CHECKS 8 /* DONE */ +#define BROKER_EVENT_HANDLERS 16 /* DONE */ +#define BROKER_LOGGED_DATA 32 /* DONE */ +#define BROKER_NOTIFICATIONS 64 /* DONE */ +#define BROKER_FLAPPING_DATA 128 /* DONE */ +#define BROKER_COMMENT_DATA 256 /* DONE */ +#define BROKER_DOWNTIME_DATA 512 /* DONE */ +#define BROKER_SYSTEM_COMMANDS 1024 /* DONE */ +#define BROKER_OCP_DATA 2048 /* DONE */ +#define BROKER_STATUS_DATA 4096 /* DONE */ +#define BROKER_ADAPTIVE_DATA 8192 /* DONE */ +#define BROKER_EXTERNALCOMMAND_DATA 16384 /* DONE */ +#define BROKER_RETENTION_DATA 32768 /* DONE */ +#define BROKER_ACKNOWLEDGEMENT_DATA 65536 +#define BROKER_STATECHANGE_DATA 131072 +#define BROKER_RESERVED18 262144 +#define BROKER_RESERVED19 524288 + + +/****** EVENT TYPES ************************/ + +#define NEBTYPE_NONE 0 + +#define NEBTYPE_HELLO 1 +#define NEBTYPE_GOODBYE 2 +#define NEBTYPE_INFO 3 + +#define NEBTYPE_PROCESS_START 100 +#define NEBTYPE_PROCESS_DAEMONIZE 101 +#define NEBTYPE_PROCESS_RESTART 102 +#define NEBTYPE_PROCESS_SHUTDOWN 103 +#define NEBTYPE_PROCESS_PRELAUNCH 104 /* before objects are read or verified */ +#define NEBTYPE_PROCESS_EVENTLOOPSTART 105 +#define NEBTYPE_PROCESS_EVENTLOOPEND 106 + +#define NEBTYPE_TIMEDEVENT_ADD 200 +#define NEBTYPE_TIMEDEVENT_REMOVE 201 +#define NEBTYPE_TIMEDEVENT_EXECUTE 202 +#define NEBTYPE_TIMEDEVENT_DELAY 203 /* NOT IMPLEMENTED */ +#define NEBTYPE_TIMEDEVENT_SKIP 204 /* NOT IMPLEMENTED */ +#define NEBTYPE_TIMEDEVENT_SLEEP 205 + +#define NEBTYPE_LOG_DATA 300 +#define NEBTYPE_LOG_ROTATION 301 + +#define NEBTYPE_SYSTEM_COMMAND_START 400 +#define NEBTYPE_SYSTEM_COMMAND_END 401 + +#define NEBTYPE_EVENTHANDLER_START 500 +#define NEBTYPE_EVENTHANDLER_END 501 + +#define NEBTYPE_NOTIFICATION_START 600 +#define NEBTYPE_NOTIFICATION_END 601 +#define NEBTYPE_CONTACTNOTIFICATION_START 602 +#define NEBTYPE_CONTACTNOTIFICATION_END 603 +#define NEBTYPE_CONTACTNOTIFICATIONMETHOD_START 604 +#define NEBTYPE_CONTACTNOTIFICATIONMETHOD_END 605 + +#define NEBTYPE_SERVICECHECK_INITIATE 700 +#define NEBTYPE_SERVICECHECK_PROCESSED 701 +#define NEBTYPE_SERVICECHECK_RAW_START 702 /* NOT IMPLEMENTED */ +#define NEBTYPE_SERVICECHECK_RAW_END 703 /* NOT IMPLEMENTED */ +#define NEBTYPE_SERVICECHECK_ASYNC_PRECHECK 704 + +#define NEBTYPE_HOSTCHECK_INITIATE 800 /* a check of the route to the host has been initiated */ +#define NEBTYPE_HOSTCHECK_PROCESSED 801 /* the processed/final result of a host check */ +#define NEBTYPE_HOSTCHECK_RAW_START 802 /* the start of a "raw" host check */ +#define NEBTYPE_HOSTCHECK_RAW_END 803 /* a finished "raw" host check */ +#define NEBTYPE_HOSTCHECK_ASYNC_PRECHECK 804 +#define NEBTYPE_HOSTCHECK_SYNC_PRECHECK 805 + +#define NEBTYPE_COMMENT_ADD 900 +#define NEBTYPE_COMMENT_DELETE 901 +#define NEBTYPE_COMMENT_LOAD 902 + +#define NEBTYPE_FLAPPING_START 1000 +#define NEBTYPE_FLAPPING_STOP 1001 + +#define NEBTYPE_DOWNTIME_ADD 1100 +#define NEBTYPE_DOWNTIME_DELETE 1101 +#define NEBTYPE_DOWNTIME_LOAD 1102 +#define NEBTYPE_DOWNTIME_START 1103 +#define NEBTYPE_DOWNTIME_STOP 1104 + +#define NEBTYPE_PROGRAMSTATUS_UPDATE 1200 +#define NEBTYPE_HOSTSTATUS_UPDATE 1201 +#define NEBTYPE_SERVICESTATUS_UPDATE 1202 +#define NEBTYPE_CONTACTSTATUS_UPDATE 1203 + +#define NEBTYPE_ADAPTIVEPROGRAM_UPDATE 1300 +#define NEBTYPE_ADAPTIVEHOST_UPDATE 1301 +#define NEBTYPE_ADAPTIVESERVICE_UPDATE 1302 +#define NEBTYPE_ADAPTIVECONTACT_UPDATE 1303 + +#define NEBTYPE_EXTERNALCOMMAND_START 1400 +#define NEBTYPE_EXTERNALCOMMAND_END 1401 + +#define NEBTYPE_AGGREGATEDSTATUS_STARTDUMP 1500 +#define NEBTYPE_AGGREGATEDSTATUS_ENDDUMP 1501 + +#define NEBTYPE_RETENTIONDATA_STARTLOAD 1600 +#define NEBTYPE_RETENTIONDATA_ENDLOAD 1601 +#define NEBTYPE_RETENTIONDATA_STARTSAVE 1602 +#define NEBTYPE_RETENTIONDATA_ENDSAVE 1603 + +#define NEBTYPE_ACKNOWLEDGEMENT_ADD 1700 +#define NEBTYPE_ACKNOWLEDGEMENT_REMOVE 1701 /* NOT IMPLEMENTED */ +#define NEBTYPE_ACKNOWLEDGEMENT_LOAD 1702 /* NOT IMPLEMENTED */ + +#define NEBTYPE_STATECHANGE_START 1800 /* NOT IMPLEMENTED */ +#define NEBTYPE_STATECHANGE_END 1801 + + + +/****** EVENT FLAGS ************************/ + +#define NEBFLAG_NONE 0 +#define NEBFLAG_PROCESS_INITIATED 1 /* event was initiated by Nagios process */ +#define NEBFLAG_USER_INITIATED 2 /* event was initiated by a user request */ +#define NEBFLAG_MODULE_INITIATED 3 /* event was initiated by an event broker module */ + + + + +/****** EVENT ATTRIBUTES *******************/ + +#define NEBATTR_NONE 0 + +#define NEBATTR_SHUTDOWN_NORMAL 1 +#define NEBATTR_SHUTDOWN_ABNORMAL 2 +#define NEBATTR_RESTART_NORMAL 4 +#define NEBATTR_RESTART_ABNORMAL 8 + +#define NEBATTR_FLAPPING_STOP_NORMAL 1 +#define NEBATTR_FLAPPING_STOP_DISABLED 2 /* flapping stopped because flap detection was disabled */ + +#define NEBATTR_DOWNTIME_STOP_NORMAL 1 +#define NEBATTR_DOWNTIME_STOP_CANCELLED 2 + + + +/****** EVENT BROKER FUNCTIONS *************/ + +#ifdef USE_EVENT_BROKER +struct timeval get_broker_timestamp(struct timeval *); +void broker_program_state(int,int,int,struct timeval *); +void broker_timed_event(int,int,int,timed_event *,struct timeval *); +void broker_log_data(int,int,int,char *,unsigned long,time_t,struct timeval *); +void broker_event_handler(int,int,int,int,void *,int,int,struct timeval,struct timeval,double,int,int,int,char *,char *,char *,struct timeval *); +void broker_ocp_data(int,int,int,void *,int,int,double,int,int,struct timeval *); +void broker_system_command(int,int,int,struct timeval,struct timeval,double,int,int,int,char *,char *,struct timeval *); +int broker_host_check(int,int,int,host *,int,int,int,struct timeval,struct timeval,char *,double,double,int,int,int,char *,char *,char *,char *,struct timeval *); +int broker_service_check(int,int,int,service *,int,struct timeval,struct timeval,char *,double,double,int,int,int,char *,struct timeval *); +void broker_comment_data(int,int,int,int,int,char *,char *,time_t,char *,char *,int,int,int,time_t,unsigned long,struct timeval *); +void broker_downtime_data(int,int,int,int,char *,char *,time_t,char *,char *,time_t,time_t,int,unsigned long,unsigned long,unsigned long,struct timeval *); +void broker_flapping_data(int,int,int,int,void *,double,double,double,struct timeval *); +void broker_program_status(int,int,int,struct timeval *); +void broker_host_status(int,int,int,host *,struct timeval *); +void broker_service_status(int,int,int,service *,struct timeval *); +void broker_contact_status(int,int,int,contact *,struct timeval *); +void broker_notification_data(int,int,int,int,int,struct timeval,struct timeval,void *,char *,char *,int,int,struct timeval *); +void broker_contact_notification_data(int,int,int,int,int,struct timeval,struct timeval,void *,contact *,char *,char *,int,struct timeval *); +void broker_contact_notification_method_data(int,int,int,int,int,struct timeval,struct timeval,void *,contact *,char *,char *,char *,int,struct timeval *); +void broker_adaptive_program_data(int,int,int,int,unsigned long,unsigned long,unsigned long,unsigned long,struct timeval *); +void broker_adaptive_host_data(int,int,int,host *,int,unsigned long,unsigned long,struct timeval *); +void broker_adaptive_service_data(int,int,int,service *,int,unsigned long,unsigned long,struct timeval *); +void broker_adaptive_contact_data(int,int,int,contact *,int,unsigned long,unsigned long,unsigned long,unsigned long,unsigned long,unsigned long, struct timeval *); +void broker_external_command(int,int,int,int,time_t,char *,char *,struct timeval *); +void broker_aggregated_status_data(int,int,int,struct timeval *); +void broker_retention_data(int,int,int,struct timeval *); +void broker_acknowledgement_data(int,int,int,int,void *,char *,char *,int,int,int,struct timeval *); +void broker_statechange_data(int,int,int,int,void *,int,int,int,int,struct timeval *); +#endif + + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/include/common.h b/include/common.h new file mode 100644 index 0000000..1cf7628 --- /dev/null +++ b/include/common.h @@ -0,0 +1,500 @@ +/************************************************************************ + * + * Nagios Common Header File + * Written By: Ethan Galstad (nagios@nagios.org) + * Last Modified: 10-22-2007 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************/ + + +#define PROGRAM_VERSION "3.0" +#define PROGRAM_MODIFICATION_DATE "03-13-2008" + +/*#define DEBUG_CHECK_IPC 1 */ +/*#define DEBUG_CHECK_IPC2 1*/ + + + +/* daemon is thread safe */ +#ifdef NSCORE +#ifndef _REENTRANT +#define _REENTRANT +#endif +#ifndef _THREAD_SAFE +#define _THREAD_SAFE +#endif +#endif + +/* Experimental performance tweaks - use with caution */ +#undef USE_MEMORY_PERFORMANCE_TWEAKS + +/* my_free has been freed from bondage as a function */ +#define my_free(ptr) { if(ptr) { free(ptr); ptr = NULL; } } + + + +/***************************** COMMANDS *********************************/ + +#define CMD_NONE 0 + +#define CMD_ADD_HOST_COMMENT 1 +#define CMD_DEL_HOST_COMMENT 2 + +#define CMD_ADD_SVC_COMMENT 3 +#define CMD_DEL_SVC_COMMENT 4 + +#define CMD_ENABLE_SVC_CHECK 5 +#define CMD_DISABLE_SVC_CHECK 6 + +#define CMD_SCHEDULE_SVC_CHECK 7 + +#define CMD_DELAY_SVC_NOTIFICATION 9 + +#define CMD_DELAY_HOST_NOTIFICATION 10 + +#define CMD_DISABLE_NOTIFICATIONS 11 +#define CMD_ENABLE_NOTIFICATIONS 12 + +#define CMD_RESTART_PROCESS 13 +#define CMD_SHUTDOWN_PROCESS 14 + +#define CMD_ENABLE_HOST_SVC_CHECKS 15 +#define CMD_DISABLE_HOST_SVC_CHECKS 16 + +#define CMD_SCHEDULE_HOST_SVC_CHECKS 17 + +#define CMD_DELAY_HOST_SVC_NOTIFICATIONS 19 /* currently unimplemented */ + +#define CMD_DEL_ALL_HOST_COMMENTS 20 +#define CMD_DEL_ALL_SVC_COMMENTS 21 + +#define CMD_ENABLE_SVC_NOTIFICATIONS 22 +#define CMD_DISABLE_SVC_NOTIFICATIONS 23 +#define CMD_ENABLE_HOST_NOTIFICATIONS 24 +#define CMD_DISABLE_HOST_NOTIFICATIONS 25 +#define CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST 26 +#define CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST 27 +#define CMD_ENABLE_HOST_SVC_NOTIFICATIONS 28 +#define CMD_DISABLE_HOST_SVC_NOTIFICATIONS 29 + +#define CMD_PROCESS_SERVICE_CHECK_RESULT 30 + +#define CMD_SAVE_STATE_INFORMATION 31 +#define CMD_READ_STATE_INFORMATION 32 + +#define CMD_ACKNOWLEDGE_HOST_PROBLEM 33 +#define CMD_ACKNOWLEDGE_SVC_PROBLEM 34 + +#define CMD_START_EXECUTING_SVC_CHECKS 35 +#define CMD_STOP_EXECUTING_SVC_CHECKS 36 + +#define CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS 37 +#define CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS 38 + +#define CMD_ENABLE_PASSIVE_SVC_CHECKS 39 +#define CMD_DISABLE_PASSIVE_SVC_CHECKS 40 + +#define CMD_ENABLE_EVENT_HANDLERS 41 +#define CMD_DISABLE_EVENT_HANDLERS 42 + +#define CMD_ENABLE_HOST_EVENT_HANDLER 43 +#define CMD_DISABLE_HOST_EVENT_HANDLER 44 + +#define CMD_ENABLE_SVC_EVENT_HANDLER 45 +#define CMD_DISABLE_SVC_EVENT_HANDLER 46 + +#define CMD_ENABLE_HOST_CHECK 47 +#define CMD_DISABLE_HOST_CHECK 48 + +#define CMD_START_OBSESSING_OVER_SVC_CHECKS 49 +#define CMD_STOP_OBSESSING_OVER_SVC_CHECKS 50 + +#define CMD_REMOVE_HOST_ACKNOWLEDGEMENT 51 +#define CMD_REMOVE_SVC_ACKNOWLEDGEMENT 52 + +#define CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS 53 +#define CMD_SCHEDULE_FORCED_SVC_CHECK 54 + +#define CMD_SCHEDULE_HOST_DOWNTIME 55 +#define CMD_SCHEDULE_SVC_DOWNTIME 56 + +#define CMD_ENABLE_HOST_FLAP_DETECTION 57 +#define CMD_DISABLE_HOST_FLAP_DETECTION 58 + +#define CMD_ENABLE_SVC_FLAP_DETECTION 59 +#define CMD_DISABLE_SVC_FLAP_DETECTION 60 + +#define CMD_ENABLE_FLAP_DETECTION 61 +#define CMD_DISABLE_FLAP_DETECTION 62 + +#define CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS 63 +#define CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS 64 + +#define CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS 65 +#define CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS 66 + +#define CMD_ENABLE_HOSTGROUP_SVC_CHECKS 67 +#define CMD_DISABLE_HOSTGROUP_SVC_CHECKS 68 + +#define CMD_CANCEL_HOST_DOWNTIME 69 /* not internally implemented */ +#define CMD_CANCEL_SVC_DOWNTIME 70 /* not internally implemented */ + +#define CMD_CANCEL_ACTIVE_HOST_DOWNTIME 71 /* old - no longer used */ +#define CMD_CANCEL_PENDING_HOST_DOWNTIME 72 /* old - no longer used */ + +#define CMD_CANCEL_ACTIVE_SVC_DOWNTIME 73 /* old - no longer used */ +#define CMD_CANCEL_PENDING_SVC_DOWNTIME 74 /* old - no longer used */ + +#define CMD_CANCEL_ACTIVE_HOST_SVC_DOWNTIME 75 /* unimplemented */ +#define CMD_CANCEL_PENDING_HOST_SVC_DOWNTIME 76 /* unimplemented */ + +#define CMD_FLUSH_PENDING_COMMANDS 77 + +#define CMD_DEL_HOST_DOWNTIME 78 +#define CMD_DEL_SVC_DOWNTIME 79 + +#define CMD_ENABLE_FAILURE_PREDICTION 80 +#define CMD_DISABLE_FAILURE_PREDICTION 81 + +#define CMD_ENABLE_PERFORMANCE_DATA 82 +#define CMD_DISABLE_PERFORMANCE_DATA 83 + +#define CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME 84 +#define CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME 85 +#define CMD_SCHEDULE_HOST_SVC_DOWNTIME 86 + +/* new commands in Nagios 2.x found below... */ +#define CMD_PROCESS_HOST_CHECK_RESULT 87 + +#define CMD_START_EXECUTING_HOST_CHECKS 88 +#define CMD_STOP_EXECUTING_HOST_CHECKS 89 + +#define CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS 90 +#define CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS 91 + +#define CMD_ENABLE_PASSIVE_HOST_CHECKS 92 +#define CMD_DISABLE_PASSIVE_HOST_CHECKS 93 + +#define CMD_START_OBSESSING_OVER_HOST_CHECKS 94 +#define CMD_STOP_OBSESSING_OVER_HOST_CHECKS 95 + +#define CMD_SCHEDULE_HOST_CHECK 96 +#define CMD_SCHEDULE_FORCED_HOST_CHECK 98 + +#define CMD_START_OBSESSING_OVER_SVC 99 +#define CMD_STOP_OBSESSING_OVER_SVC 100 + +#define CMD_START_OBSESSING_OVER_HOST 101 +#define CMD_STOP_OBSESSING_OVER_HOST 102 + +#define CMD_ENABLE_HOSTGROUP_HOST_CHECKS 103 +#define CMD_DISABLE_HOSTGROUP_HOST_CHECKS 104 + +#define CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS 105 +#define CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS 106 + +#define CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS 107 +#define CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS 108 + +#define CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS 109 +#define CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS 110 + +#define CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS 111 +#define CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS 112 + +#define CMD_ENABLE_SERVICEGROUP_SVC_CHECKS 113 +#define CMD_DISABLE_SERVICEGROUP_SVC_CHECKS 114 + +#define CMD_ENABLE_SERVICEGROUP_HOST_CHECKS 115 +#define CMD_DISABLE_SERVICEGROUP_HOST_CHECKS 116 + +#define CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS 117 +#define CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS 118 + +#define CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS 119 +#define CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS 120 + +#define CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME 121 +#define CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME 122 + +#define CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER 123 +#define CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER 124 + +#define CMD_CHANGE_HOST_EVENT_HANDLER 125 +#define CMD_CHANGE_SVC_EVENT_HANDLER 126 + +#define CMD_CHANGE_HOST_CHECK_COMMAND 127 +#define CMD_CHANGE_SVC_CHECK_COMMAND 128 + +#define CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL 129 +#define CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL 130 +#define CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL 131 + +#define CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS 132 +#define CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS 133 + +#define CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME 134 + +#define CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS 135 +#define CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS 136 + +#define CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME 137 + +#define CMD_ENABLE_SERVICE_FRESHNESS_CHECKS 138 +#define CMD_DISABLE_SERVICE_FRESHNESS_CHECKS 139 + +#define CMD_ENABLE_HOST_FRESHNESS_CHECKS 140 +#define CMD_DISABLE_HOST_FRESHNESS_CHECKS 141 + +#define CMD_SET_HOST_NOTIFICATION_NUMBER 142 +#define CMD_SET_SVC_NOTIFICATION_NUMBER 143 + +/* new commands in Nagios 3.x found below... */ +#define CMD_CHANGE_HOST_CHECK_TIMEPERIOD 144 +#define CMD_CHANGE_SVC_CHECK_TIMEPERIOD 145 + +#define CMD_PROCESS_FILE 146 + +#define CMD_CHANGE_CUSTOM_HOST_VAR 147 +#define CMD_CHANGE_CUSTOM_SVC_VAR 148 +#define CMD_CHANGE_CUSTOM_CONTACT_VAR 149 + +#define CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS 150 +#define CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS 151 +#define CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS 152 +#define CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS 153 + +#define CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS 154 +#define CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS 155 +#define CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS 156 +#define CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS 157 + +#define CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL 158 + +#define CMD_SEND_CUSTOM_HOST_NOTIFICATION 159 +#define CMD_SEND_CUSTOM_SVC_NOTIFICATION 160 + +#define CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD 161 +#define CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD 162 +#define CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD 163 +#define CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD 164 + +#define CMD_CHANGE_HOST_MODATTR 165 +#define CMD_CHANGE_SVC_MODATTR 166 +#define CMD_CHANGE_CONTACT_MODATTR 167 +#define CMD_CHANGE_CONTACT_MODHATTR 168 +#define CMD_CHANGE_CONTACT_MODSATTR 169 + +/* custom command introduced in Nagios 3.x */ +#define CMD_CUSTOM_COMMAND 999 + + + +/************************ SERVICE CHECK TYPES ****************************/ + +#define SERVICE_CHECK_ACTIVE 0 /* Nagios performed the service check */ +#define SERVICE_CHECK_PASSIVE 1 /* the service check result was submitted by an external source */ + + +/************************** HOST CHECK TYPES *****************************/ + +#define HOST_CHECK_ACTIVE 0 /* Nagios performed the host check */ +#define HOST_CHECK_PASSIVE 1 /* the host check result was submitted by an external source */ + + +/************************ SERVICE STATE TYPES ****************************/ + +#define SOFT_STATE 0 +#define HARD_STATE 1 + + +/************************* SCHEDULED DOWNTIME TYPES **********************/ + +#define SERVICE_DOWNTIME 1 /* service downtime */ +#define HOST_DOWNTIME 2 /* host downtime */ +#define ANY_DOWNTIME 3 /* host or service downtime */ + + +/************************** NOTIFICATION OPTIONS *************************/ + +#define NOTIFICATION_OPTION_NONE 0 +#define NOTIFICATION_OPTION_BROADCAST 1 +#define NOTIFICATION_OPTION_FORCED 2 +#define NOTIFICATION_OPTION_INCREMENT 4 + + +/************************** ACKNOWLEDGEMENT TYPES ************************/ + +#define HOST_ACKNOWLEDGEMENT 0 +#define SERVICE_ACKNOWLEDGEMENT 1 + +#define ACKNOWLEDGEMENT_NONE 0 +#define ACKNOWLEDGEMENT_NORMAL 1 +#define ACKNOWLEDGEMENT_STICKY 2 + + +/**************************** DEPENDENCY TYPES ***************************/ + +#define NOTIFICATION_DEPENDENCY 1 +#define EXECUTION_DEPENDENCY 2 + + + +/********************** HOST/SERVICE CHECK OPTIONS ***********************/ + +#define CHECK_OPTION_NONE 0 /* no check options */ +#define CHECK_OPTION_FORCE_EXECUTION 1 /* force execution of a check (ignores disabled services/hosts, invalid timeperiods) */ +#define CHECK_OPTION_FRESHNESS_CHECK 2 /* this is a freshness check */ +#define CHECK_OPTION_ORPHAN_CHECK 4 /* this is an orphan check */ + + +/**************************** PROGRAM MODES ******************************/ + +#define STANDBY_MODE 0 +#define ACTIVE_MODE 1 + + +/************************** LOG ROTATION MODES ***************************/ + +#define LOG_ROTATION_NONE 0 +#define LOG_ROTATION_HOURLY 1 +#define LOG_ROTATION_DAILY 2 +#define LOG_ROTATION_WEEKLY 3 +#define LOG_ROTATION_MONTHLY 4 + + +/***************************** LOG VERSIONS ******************************/ + +#define LOG_VERSION_1 "1.0" +#define LOG_VERSION_2 "2.0" + + + +/*************************** CHECK STATISTICS ****************************/ + +#define ACTIVE_SCHEDULED_SERVICE_CHECK_STATS 0 +#define ACTIVE_ONDEMAND_SERVICE_CHECK_STATS 1 +#define PASSIVE_SERVICE_CHECK_STATS 2 +#define ACTIVE_SCHEDULED_HOST_CHECK_STATS 3 +#define ACTIVE_ONDEMAND_HOST_CHECK_STATS 4 +#define PASSIVE_HOST_CHECK_STATS 5 +#define ACTIVE_CACHED_HOST_CHECK_STATS 6 +#define ACTIVE_CACHED_SERVICE_CHECK_STATS 7 +#define EXTERNAL_COMMAND_STATS 8 +#define PARALLEL_HOST_CHECK_STATS 9 +#define SERIAL_HOST_CHECK_STATS 10 +#define MAX_CHECK_STATS_TYPES 11 + + +/************************* GENERAL DEFINITIONS **************************/ + +#define OK 0 +#define ERROR -2 /* value was changed from -1 so as to not interfere with STATUS_UNKNOWN plugin result */ + + +#ifndef TRUE +#define TRUE 1 +#elif (TRUE!=1) +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#elif (FALSE!=0) +#define FALSE 0 +#endif + + +/****************** HOST CONFIG FILE READING OPTIONS ********************/ + +#define READ_HOSTS 1 +#define READ_HOSTGROUPS 2 +#define READ_CONTACTS 4 +#define READ_CONTACTGROUPS 8 +#define READ_SERVICES 16 +#define READ_COMMANDS 32 +#define READ_TIMEPERIODS 64 +#define READ_SERVICEESCALATIONS 128 +#define READ_HOSTGROUPESCALATIONS 256 /* no longer implemented */ +#define READ_SERVICEDEPENDENCIES 512 +#define READ_HOSTDEPENDENCIES 1024 +#define READ_HOSTESCALATIONS 2048 +#define READ_HOSTEXTINFO 4096 +#define READ_SERVICEEXTINFO 8192 +#define READ_SERVICEGROUPS 16384 + +#define READ_ALL_OBJECT_DATA READ_HOSTS | READ_HOSTGROUPS | READ_CONTACTS | READ_CONTACTGROUPS | READ_SERVICES | READ_COMMANDS | READ_TIMEPERIODS | READ_SERVICEESCALATIONS | READ_SERVICEDEPENDENCIES | READ_HOSTDEPENDENCIES | READ_HOSTESCALATIONS | READ_HOSTEXTINFO | READ_SERVICEEXTINFO | READ_SERVICEGROUPS + + +/************************** DATE RANGE TYPES ****************************/ + +#define DATERANGE_CALENDAR_DATE 0 /* 2008-12-25 */ +#define DATERANGE_MONTH_DATE 1 /* july 4 (specific month) */ +#define DATERANGE_MONTH_DAY 2 /* day 21 (generic month) */ +#define DATERANGE_MONTH_WEEK_DAY 3 /* 3rd thursday (specific month) */ +#define DATERANGE_WEEK_DAY 4 /* 3rd thursday (generic month) */ +#define DATERANGE_TYPES 5 + + +/************************** DATE/TIME TYPES *****************************/ + +#define LONG_DATE_TIME 0 +#define SHORT_DATE_TIME 1 +#define SHORT_DATE 2 +#define SHORT_TIME 3 +#define HTTP_DATE_TIME 4 /* time formatted for use in HTTP headers */ + + +/**************************** DATE FORMATS ******************************/ + +#define DATE_FORMAT_US 0 /* U.S. (MM-DD-YYYY HH:MM:SS) */ +#define DATE_FORMAT_EURO 1 /* European (DD-MM-YYYY HH:MM:SS) */ +#define DATE_FORMAT_ISO8601 2 /* ISO8601 (YYYY-MM-DD HH:MM:SS) */ +#define DATE_FORMAT_STRICT_ISO8601 3 /* ISO8601 (YYYY-MM-DDTHH:MM:SS) */ + + +/************************** MISC DEFINITIONS ****************************/ + +#define MAX_FILENAME_LENGTH 256 /* max length of path/filename that Nagios will process */ +#define MAX_INPUT_BUFFER 1024 /* size in bytes of max. input buffer (for reading files, misc stuff) */ +#define MAX_COMMAND_BUFFER 8192 /* max length of raw or processed command line */ +#define MAX_EXTERNAL_COMMAND_LENGTH 8192 /* max length of an external command */ + +#define MAX_DATETIME_LENGTH 48 + + +/************************* MODIFIED ATTRIBUTES **************************/ + +#define MODATTR_NONE 0 +#define MODATTR_NOTIFICATIONS_ENABLED 1 +#define MODATTR_ACTIVE_CHECKS_ENABLED 2 +#define MODATTR_PASSIVE_CHECKS_ENABLED 4 +#define MODATTR_EVENT_HANDLER_ENABLED 8 +#define MODATTR_FLAP_DETECTION_ENABLED 16 +#define MODATTR_FAILURE_PREDICTION_ENABLED 32 +#define MODATTR_PERFORMANCE_DATA_ENABLED 64 +#define MODATTR_OBSESSIVE_HANDLER_ENABLED 128 +#define MODATTR_EVENT_HANDLER_COMMAND 256 +#define MODATTR_CHECK_COMMAND 512 +#define MODATTR_NORMAL_CHECK_INTERVAL 1024 +#define MODATTR_RETRY_CHECK_INTERVAL 2048 +#define MODATTR_MAX_CHECK_ATTEMPTS 4096 +#define MODATTR_FRESHNESS_CHECKS_ENABLED 8192 +#define MODATTR_CHECK_TIMEPERIOD 16384 +#define MODATTR_CUSTOM_VARIABLE 32768 +#define MODATTR_NOTIFICATION_TIMEPERIOD 65536 + + diff --git a/include/config.h.in b/include/config.h.in new file mode 100644 index 0000000..1af2340 --- /dev/null +++ b/include/config.h.in @@ -0,0 +1,177 @@ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +/* Default Nagios Group */ +#undef DEFAULT_NAGIOS_GROUP + +/* Default Nagios User */ +#undef DEFAULT_NAGIOS_USER + +/* Define to 1 if you have the `alarm' function. */ +#undef HAVE_ALARM + +/* Define to 1 if you have the `bzero' function. */ +#undef HAVE_BZERO + +/* Define to 1 if you have the `getloadavg' function. */ +#undef HAVE_GETLOADAVG + +/* Define to 1 if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_STAT_EMPTY_STRING_BUG + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strspn' function. */ +#undef HAVE_STRSPN + +/* Define to 1 if `d_type' is member of `struct dirent'. */ +#undef HAVE_STRUCT_DIRENT_D_TYPE + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork diff --git a/include/global.h b/include/global.h new file mode 100644 index 0000000..58c8279 --- /dev/null +++ b/include/global.h @@ -0,0 +1,4 @@ +#ifndef GLOBAL_H_ +#define GLOBAL_H_ + +#endif /*GLOBAL_H_*/ diff --git a/include/locations.h b/include/locations.h new file mode 100644 index 0000000..834e6c4 --- /dev/null +++ b/include/locations.h @@ -0,0 +1,43 @@ +/************************************************************************ + * + * Nagios Locations Header File + * Written By: Ethan Galstad (nagios@nagios.org) + * Last Modified: 04-30-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************/ + +#define DEFAULT_TEMP_FILE "/usr/local/nagios/var/tempfile" +#define DEFAULT_TEMP_PATH "/tmp" +#define DEFAULT_CHECK_RESULT_PATH "/usr/local/nagios/var/spool/checkresults" +#define DEFAULT_STATUS_FILE "/usr/local/nagios/var/status.dat" +#define DEFAULT_LOG_FILE "/usr/local/nagios/var/nagios.log" +#define DEFAULT_LOG_ARCHIVE_PATH "/usr/local/nagios/var/archives/" +#define DEFAULT_DEBUG_FILE "/usr/local/nagios/var/nagios.debug" +#define DEFAULT_COMMENT_FILE "/usr/local/nagios/var/comments.dat" +#define DEFAULT_DOWNTIME_FILE "/usr/local/nagios/var/downtime.dat" +#define DEFAULT_RETENTION_FILE "/usr/local/nagios/var/retention.dat" +#define DEFAULT_COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd" +#define DEFAULT_CONFIG_FILE "/usr/local/nagios/etc/nagios.cfg" +#define DEFAULT_PHYSICAL_HTML_PATH "/usr/local/nagios/share" +#define DEFAULT_URL_HTML_PATH "/nagios" +#define DEFAULT_PHYSICAL_CGIBIN_PATH "/usr/local/nagios/sbin" +#define DEFAULT_URL_CGIBIN_PATH "/nagios/cgi-bin" +#define DEFAULT_CGI_CONFIG_FILE "/usr/local/nagios/etc/cgi.cfg" +#define DEFAULT_LOCK_FILE "/usr/local/nagios/var/nagios.lock" +#define DEFAULT_OBJECT_CACHE_FILE "/usr/local/nagios/var/objects.cache" +#define DEFAULT_PRECACHED_OBJECT_FILE "/usr/local/nagios/var/objects.precache" +#define DEFAULT_EVENT_BROKER_FILE "/usr/local/nagios/var/broker.socket" +#define DEFAULT_P1_FILE "/usr/local/nagios/bin/p1.pl" /**** EMBEDDED PERL ****/ +#define DEFAULT_AUTH_FILE "" /**** EMBEDDED PERL - IS THIS USED? ****/ diff --git a/include/nagios.h b/include/nagios.h new file mode 100644 index 0000000..01eae70 --- /dev/null +++ b/include/nagios.h @@ -0,0 +1,812 @@ +/************************************************************************ + * + * Nagios Main Header File + * Written By: Ethan Galstad (nagios@nagios.org) + * Last Modified: 02-23-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************/ + +#ifndef _NAGIOS_H +#define _NAGIOS_H + +#ifndef __GNUC__ +# define __attribute__(x) /* nothing */ +#endif + +#include "config.h" + +//#include "pnp.h" +#include "common.h" +#include "locations.h" +#include "objects.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/************* MISC LENGTH/SIZE DEFINITIONS ***********/ + +/* + NOTE: Plugin length is artificially capped at 8k to prevent runaway plugins from returning MBs/GBs of data + back to Nagios. If you increase the 8k cap by modifying this value, make sure you also increase the value + of MAX_EXTERNAL_COMMAND_LENGTH in common.h to allow for passive checks results received through the external + command file. EG 10/19/07 +*/ +#define MAX_PLUGIN_OUTPUT_LENGTH 8192 /* max length of plugin output (including perf data) */ + + + +/******************* DEFAULT VALUES *******************/ + +#define DEFAULT_LOG_LEVEL 1 /* log all events to main log file */ +#define DEFAULT_USE_SYSLOG 1 /* log events to syslog? 1=yes, 0=no */ +#define DEFAULT_SYSLOG_LEVEL 2 /* log only severe events to syslog */ + +#define DEFAULT_NOTIFICATION_LOGGING 1 /* log notification events? 1=yes, 0=no */ + +#define DEFAULT_INTER_CHECK_DELAY 5.0 /* seconds between initial service check scheduling */ +#define DEFAULT_INTERLEAVE_FACTOR 1 /* default interleave to use when scheduling checks */ +#define DEFAULT_SLEEP_TIME 0.5 /* seconds between event run checks */ +#define DEFAULT_INTERVAL_LENGTH 60 /* seconds per interval unit for check scheduling */ +#define DEFAULT_RETRY_INTERVAL 30 /* services are retried in 30 seconds if they're not OK */ +#define DEFAULT_COMMAND_CHECK_INTERVAL -1 /* interval to check for external commands (default = as often as possible) */ +#define DEFAULT_CHECK_REAPER_INTERVAL 10 /* interval in seconds to reap host and service check results */ +#define DEFAULT_MAX_REAPER_TIME 30 /* maximum number of seconds to spend reaping service checks before we break out for a while */ +#define DEFAULT_MAX_CHECK_RESULT_AGE 3600 /* maximum number of seconds that a check result file is considered to be valid */ +#define DEFAULT_MAX_PARALLEL_SERVICE_CHECKS 0 /* maximum number of service checks we can have running at any given time (0=unlimited) */ +#define DEFAULT_RETENTION_UPDATE_INTERVAL 60 /* minutes between auto-save of retention data */ +#define DEFAULT_RETENTION_SCHEDULING_HORIZON 900 /* max seconds between program restarts that we will preserve scheduling information */ +#define DEFAULT_STATUS_UPDATE_INTERVAL 60 /* seconds between aggregated status data updates */ +#define DEFAULT_FRESHNESS_CHECK_INTERVAL 60 /* seconds between service result freshness checks */ +#define DEFAULT_AUTO_RESCHEDULING_INTERVAL 30 /* seconds between host and service check rescheduling events */ +#define DEFAULT_AUTO_RESCHEDULING_WINDOW 180 /* window of time (in seconds) for which we should reschedule host and service checks */ +#define DEFAULT_ORPHAN_CHECK_INTERVAL 60 /* seconds between checks for orphaned hosts and services */ + +#define DEFAULT_NOTIFICATION_TIMEOUT 30 /* max time in seconds to wait for notification commands to complete */ +#define DEFAULT_EVENT_HANDLER_TIMEOUT 30 /* max time in seconds to wait for event handler commands to complete */ +#define DEFAULT_HOST_CHECK_TIMEOUT 30 /* max time in seconds to wait for host check commands to complete */ +#define DEFAULT_SERVICE_CHECK_TIMEOUT 60 /* max time in seconds to wait for service check commands to complete */ +#define DEFAULT_OCSP_TIMEOUT 15 /* max time in seconds to wait for obsessive compulsive processing commands to complete */ +#define DEFAULT_OCHP_TIMEOUT 15 /* max time in seconds to wait for obsessive compulsive processing commands to complete */ +#define DEFAULT_PERFDATA_TIMEOUT 5 /* max time in seconds to wait for performance data commands to complete */ +#define DEFAULT_TIME_CHANGE_THRESHOLD 900 /* compensate for time changes of more than 15 minutes */ + +#define DEFAULT_LOG_HOST_RETRIES 0 /* don't log host retries */ +#define DEFAULT_LOG_SERVICE_RETRIES 0 /* don't log service retries */ +#define DEFAULT_LOG_EVENT_HANDLERS 1 /* log event handlers */ +#define DEFAULT_LOG_INITIAL_STATES 0 /* don't log initial service and host states */ +#define DEFAULT_LOG_EXTERNAL_COMMANDS 1 /* log external commands */ +#define DEFAULT_LOG_PASSIVE_CHECKS 1 /* log passive service checks */ + +#define DEFAULT_DEBUG_LEVEL 0 /* don't log any debugging information */ +#define DEFAULT_DEBUG_VERBOSITY 1 +#define DEFAULT_MAX_DEBUG_FILE_SIZE 1000000 /* max size of debug log */ + +#define DEFAULT_AGGRESSIVE_HOST_CHECKING 0 /* don't use "aggressive" host checking */ +#define DEFAULT_CHECK_EXTERNAL_COMMANDS 1 /* check for external commands */ +#define DEFAULT_CHECK_ORPHANED_SERVICES 1 /* check for orphaned services */ +#define DEFAULT_CHECK_ORPHANED_HOSTS 1 /* check for orphaned hosts */ +#define DEFAULT_ENABLE_FLAP_DETECTION 0 /* don't enable flap detection */ +#define DEFAULT_PROCESS_PERFORMANCE_DATA 0 /* don't process performance data */ +#define DEFAULT_CHECK_SERVICE_FRESHNESS 1 /* check service result freshness */ +#define DEFAULT_CHECK_HOST_FRESHNESS 0 /* don't check host result freshness */ +#define DEFAULT_AUTO_RESCHEDULE_CHECKS 0 /* don't auto-reschedule host and service checks */ +#define DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS 0 /* should we translate DOWN/UNREACHABLE passive host checks? */ +#define DEFAULT_PASSIVE_HOST_CHECKS_SOFT 0 /* passive host checks are treated as HARD by default */ + +#define DEFAULT_LOW_SERVICE_FLAP_THRESHOLD 20.0 /* low threshold for detection of service flapping */ +#define DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD 30.0 /* high threshold for detection of service flapping */ +#define DEFAULT_LOW_HOST_FLAP_THRESHOLD 20.0 /* low threshold for detection of host flapping */ +#define DEFAULT_HIGH_HOST_FLAP_THRESHOLD 30.0 /* high threshold for detection of host flapping */ + +#define DEFAULT_HOST_CHECK_SPREAD 30 /* max minutes to schedule all initial host checks */ +#define DEFAULT_SERVICE_CHECK_SPREAD 30 /* max minutes to schedule all initial service checks */ + +#define DEFAULT_CACHED_HOST_CHECK_HORIZON 15 /* max age in seconds that cached host checks can be used */ +#define DEFAULT_CACHED_SERVICE_CHECK_HORIZON 15 /* max age in seconds that cached service checks can be used */ +#define DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS 1 /* should we use predictive host dependency checks? */ +#define DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS 1 /* should we use predictive service dependency checks? */ + +#define DEFAULT_USE_LARGE_INSTALLATION_TWEAKS 0 /* don't use tweaks for large Nagios installations */ + +#define DEFAULT_ENABLE_EMBEDDED_PERL 1 /* enable embedded Perl interpreter (if compiled in) */ +#define DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY 1 /* by default, embedded Perl is used for Perl plugins that don't explicitly disable it */ + +#define DEFAULT_ADDITIONAL_FRESHNESS_LATENCY 15 /* seconds to be added to freshness thresholds when automatically calculated by Nagios */ + + + +/******************* LOGGING TYPES ********************/ + +#define NSLOG_RUNTIME_ERROR 1 +#define NSLOG_RUNTIME_WARNING 2 + +#define NSLOG_VERIFICATION_ERROR 4 +#define NSLOG_VERIFICATION_WARNING 8 + +#define NSLOG_CONFIG_ERROR 16 +#define NSLOG_CONFIG_WARNING 32 + +#define NSLOG_PROCESS_INFO 64 +#define NSLOG_EVENT_HANDLER 128 +/*#define NSLOG_NOTIFICATION 256*/ /* NOT USED ANYMORE - CAN BE REUSED */ +#define NSLOG_EXTERNAL_COMMAND 512 + +#define NSLOG_HOST_UP 1024 +#define NSLOG_HOST_DOWN 2048 +#define NSLOG_HOST_UNREACHABLE 4096 + +#define NSLOG_SERVICE_OK 8192 +#define NSLOG_SERVICE_UNKNOWN 16384 +#define NSLOG_SERVICE_WARNING 32768 +#define NSLOG_SERVICE_CRITICAL 65536 + +#define NSLOG_PASSIVE_CHECK 131072 + +#define NSLOG_INFO_MESSAGE 262144 + +#define NSLOG_HOST_NOTIFICATION 524288 +#define NSLOG_SERVICE_NOTIFICATION 1048576 + + +/***************** DEBUGGING LEVELS *******************/ + +#define DEBUGL_ALL -1 +#define DEBUGL_NONE 0 +#define DEBUGL_FUNCTIONS 1 +#define DEBUGL_CONFIG 2 +#define DEBUGL_PROCESS 4 +#define DEBUGL_STATUSDATA 4 +#define DEBUGL_RETENTIONDATA 4 +#define DEBUGL_EVENTS 8 +#define DEBUGL_CHECKS 16 +#define DEBUGL_IPC 16 +#define DEBUGL_FLAPPING 16 +#define DEBUGL_EVENTHANDLERS 16 +#define DEBUGL_PERFDATA 16 +#define DEBUGL_NOTIFICATIONS 32 +#define DEBUGL_EVENTBROKER 64 +#define DEBUGL_EXTERNALCOMMANDS 128 +#define DEBUGL_COMMANDS 256 +#define DEBUGL_DOWNTIME 512 +#define DEBUGL_COMMENTS 1024 +#define DEBUGL_MACROS 2048 + +#define DEBUGV_BASIC 0 +#define DEBUGV_MORE 1 +#define DEBUGV_MOST 2 + + +/******************** HOST STATUS *********************/ + +#define HOST_UP 0 +#define HOST_DOWN 1 +#define HOST_UNREACHABLE 2 + + + +/******************* STATE LOGGING TYPES **************/ + +#define INITIAL_STATES 1 +#define CURRENT_STATES 2 + + + +/************ SERVICE DEPENDENCY VALUES ***************/ + +#define DEPENDENCIES_OK 0 +#define DEPENDENCIES_FAILED 1 + + + +/*********** ROUTE CHECK PROPAGATION TYPES ************/ + +#define PROPAGATE_TO_PARENT_HOSTS 1 +#define PROPAGATE_TO_CHILD_HOSTS 2 + + + +/****************** SERVICE STATES ********************/ + +#define STATE_OK 0 +#define STATE_WARNING 1 +#define STATE_CRITICAL 2 +#define STATE_UNKNOWN 3 /* changed from -1 on 02/24/2001 */ + + + +/****************** FLAPPING TYPES ********************/ + +#define HOST_FLAPPING 0 +#define SERVICE_FLAPPING 1 + + + +/**************** NOTIFICATION TYPES ******************/ + +#define HOST_NOTIFICATION 0 +#define SERVICE_NOTIFICATION 1 + + + +/************* NOTIFICATION REASON TYPES ***************/ + +#define NOTIFICATION_NORMAL 0 +#define NOTIFICATION_ACKNOWLEDGEMENT 1 +#define NOTIFICATION_FLAPPINGSTART 2 +#define NOTIFICATION_FLAPPINGSTOP 3 +#define NOTIFICATION_FLAPPINGDISABLED 4 +#define NOTIFICATION_DOWNTIMESTART 5 +#define NOTIFICATION_DOWNTIMEEND 6 +#define NOTIFICATION_DOWNTIMECANCELLED 7 +#define NOTIFICATION_CUSTOM 99 + + + +/**************** EVENT HANDLER TYPES *****************/ + +#define HOST_EVENTHANDLER 0 +#define SERVICE_EVENTHANDLER 1 +#define GLOBAL_HOST_EVENTHANDLER 2 +#define GLOBAL_SERVICE_EVENTHANDLER 3 + + + +/***************** STATE CHANGE TYPES *****************/ + +#define HOST_STATECHANGE 0 +#define SERVICE_STATECHANGE 1 + + + +/***************** OBJECT CHECK TYPES *****************/ +#define SERVICE_CHECK 0 +#define HOST_CHECK 1 + + + +/******************* EVENT TYPES **********************/ + +#define EVENT_SERVICE_CHECK 0 /* active service check */ +#define EVENT_COMMAND_CHECK 1 /* external command check */ +#define EVENT_LOG_ROTATION 2 /* log file rotation */ +#define EVENT_PROGRAM_SHUTDOWN 3 /* program shutdown */ +#define EVENT_PROGRAM_RESTART 4 /* program restart */ +#define EVENT_CHECK_REAPER 5 /* reaps results from host and service checks */ +#define EVENT_ORPHAN_CHECK 6 /* checks for orphaned hosts and services */ +#define EVENT_RETENTION_SAVE 7 /* save (dump) retention data */ +#define EVENT_STATUS_SAVE 8 /* save (dump) status data */ +#define EVENT_SCHEDULED_DOWNTIME 9 /* scheduled host or service downtime */ +#define EVENT_SFRESHNESS_CHECK 10 /* checks service result "freshness" */ +#define EVENT_EXPIRE_DOWNTIME 11 /* checks for (and removes) expired scheduled downtime */ +#define EVENT_HOST_CHECK 12 /* active host check */ +#define EVENT_HFRESHNESS_CHECK 13 /* checks host result "freshness" */ +#define EVENT_RESCHEDULE_CHECKS 14 /* adjust scheduling of host and service checks */ +#define EVENT_EXPIRE_COMMENT 15 /* removes expired comments */ +#define EVENT_SLEEP 98 /* asynchronous sleep event that occurs when event queues are empty */ +#define EVENT_USER_FUNCTION 99 /* USER-defined function (modules) */ + + + +/******* INTER-CHECK DELAY CALCULATION TYPES **********/ + +#define ICD_NONE 0 /* no inter-check delay */ +#define ICD_DUMB 1 /* dumb delay of 1 second */ +#define ICD_SMART 2 /* smart delay */ +#define ICD_USER 3 /* user-specified delay */ + + + +/******* INTERLEAVE FACTOR CALCULATION TYPES **********/ + +#define ILF_USER 0 /* user-specified interleave factor */ +#define ILF_SMART 1 /* smart interleave */ + + + +/************ SCHEDULED DOWNTIME TYPES ****************/ + +#define ACTIVE_DOWNTIME 0 /* active downtime - currently in effect */ +#define PENDING_DOWNTIME 1 /* pending downtime - scheduled for the future */ + + + +/****************** DATA STRUCTURES *******************/ + +/* TIMED_EVENT structure */ +typedef struct timed_event_struct{ + int event_type; + time_t run_time; + int recurring; + unsigned long event_interval; + int compensate_for_time_change; + void *timing_func; + void *event_data; + void *event_args; + int event_options; + struct timed_event_struct *next; + struct timed_event_struct *prev; + }timed_event; + + +/* NOTIFY_LIST structure */ +typedef struct notify_list_struct{ + contact *contact; + struct notify_list_struct *next; + }notification; + + +/* CHECK_RESULT structure */ +typedef struct check_result_struct{ + int object_check_type; /* is this a service or a host check? */ + char *host_name; /* host name */ + char *service_description; /* service description */ + int check_type; /* was this an active or passive service check? */ + int check_options; + int scheduled_check; /* was this a scheduled or an on-demand check? */ + int reschedule_check; /* should we reschedule the next check */ + char *output_file; /* what file is the output stored in? */ + FILE *output_file_fp; + int output_file_fd; + double latency; + struct timeval start_time; /* time the service check was initiated */ + struct timeval finish_time; /* time the service check was completed */ + int early_timeout; /* did the service check timeout? */ + int exited_ok; /* did the plugin check return okay? */ + int return_code; /* plugin return code */ + char *output; /* plugin output */ + struct check_result_struct *next; + }check_result; + + +/* SCHED_INFO structure */ +typedef struct sched_info_struct{ + int total_services; + int total_scheduled_services; + int total_hosts; + int total_scheduled_hosts; + double average_services_per_host; + double average_scheduled_services_per_host; + unsigned long service_check_interval_total; + unsigned long host_check_interval_total; + double average_service_execution_time; + double average_service_check_interval; + double average_host_check_interval; + double average_service_inter_check_delay; + double average_host_inter_check_delay; + double service_inter_check_delay; + double host_inter_check_delay; + int service_interleave_factor; + int max_service_check_spread; + int max_host_check_spread; + time_t first_service_check; + time_t last_service_check; + time_t first_host_check; + time_t last_host_check; + }sched_info; + + +/* PASSIVE_CHECK_RESULT structure */ +typedef struct passive_check_result_struct{ + int object_check_type; + char *host_name; + char *service_description; + int return_code; + char *output; + time_t check_time; + double latency; + struct passive_check_result_struct *next; + }passive_check_result; + + +/* CIRCULAR_BUFFER structure - used by worker threads */ +typedef struct circular_buffer_struct{ + void **buffer; + int tail; + int head; + int items; + int high; /* highest number of items that has ever been stored in buffer */ + unsigned long overflow; + pthread_mutex_t buffer_lock; + }circular_buffer; + + +/* MMAPFILE structure - used for reading files via mmap() */ +typedef struct mmapfile_struct{ + char *path; + int mode; + int fd; + unsigned long file_size; + unsigned long current_position; + unsigned long current_line; + void *mmap_buf; + }mmapfile; + + +/* DBUF structure - dynamic string storage */ +typedef struct dbuf_struct{ + char *buf; + unsigned long used_size; + unsigned long allocated_size; + unsigned long chunk_size; + }dbuf; + + +#define CHECK_STATS_BUCKETS 15 + +/* used for tracking host and service check statistics */ +typedef struct check_stats_struct{ + int current_bucket; + int bucket[CHECK_STATS_BUCKETS]; + int overflow_bucket; + int minute_stats[3]; + time_t last_update; + }check_stats; + + +/******************* THREAD STUFF ********************/ + +/* slots in circular buffers */ +#define DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS 4096 + +/* worker threads */ +#define TOTAL_WORKER_THREADS 1 + +#define COMMAND_WORKER_THREAD 0 + + + +/******************** FUNCTIONS **********************/ + +/**** Configuration Functions ****/ +int read_main_config_file(char *); /* reads the main config file (nagios.cfg) */ +int read_resource_file(char *); /* processes macros in resource file */ +int read_all_object_data(char *); /* reads all object config data */ + + +/**** Setup Functions ****/ +int pre_flight_check(void); /* try and verify the configuration data */ +int pre_flight_object_check(int *,int *); /* verify object relationships and settings */ +int pre_flight_circular_check(int *,int *); /* detects circular dependencies and paths */ +void init_timing_loop(void); /* setup the initial scheduling queue */ +void setup_sighandler(void); /* trap signals */ +void reset_sighandler(void); /* reset signals to default action */ +int daemon_init(void); /* switches to daemon mode */ +int drop_privileges(char *,char *); /* drops privileges before startup */ +void display_scheduling_info(void); /* displays service check scheduling information */ + + +/**** Event Queue Functions ****/ +int schedule_new_event(int,int,time_t,int,unsigned long,void *,int,void *,void *,int); /* schedules a new timed event */ +void reschedule_event(timed_event *,timed_event **,timed_event **); /* reschedules an event */ +void add_event(timed_event *,timed_event **,timed_event **); /* adds an event to the execution queue */ +void remove_event(timed_event *,timed_event **,timed_event **); /* remove an event from the execution queue */ +int event_execution_loop(void); /* main monitoring/event handler loop */ +int handle_timed_event(timed_event *); /* top level handler for timed events */ +void adjust_check_scheduling(void); /* auto-adjusts scheduling of host and service checks */ +void compensate_for_system_time_change(unsigned long,unsigned long); /* attempts to compensate for a change in the system time */ +void adjust_timestamp_for_time_change(time_t,time_t,unsigned long,time_t *); /* adjusts a timestamp variable for a system time change */ +void resort_event_list(timed_event **,timed_event **); /* resorts event list by event run time for system time changes */ + + +/**** IPC Functions ****/ +int move_check_result_to_queue(char *); +int process_check_result_queue(char *); +int process_check_result_file(char *); +int add_check_result_to_list(check_result *); +check_result *read_check_result(void); /* reads a host/service check result from the list in memory */ +int delete_check_result_file(char *); +int free_check_result_list(void); +int init_check_result(check_result *); +int free_check_result(check_result *); /* frees memory associated with a host/service check result */ +int parse_check_output(char *,char **,char **,char **,int,int); +int open_command_file(void); /* creates the external command file as a named pipe (FIFO) and opens it for reading */ +int close_command_file(void); /* closes and deletes the external command file (FIFO) */ + + +/**** Monitoring/Event Handler Functions ****/ +int check_service_dependencies(service *,int); /* checks service dependencies */ +int check_host_dependencies(host *,int); /* checks host dependencies */ +void check_for_orphaned_services(void); /* checks for orphaned services */ +void check_for_orphaned_hosts(void); /* checks for orphaned hosts */ +void check_service_result_freshness(void); /* checks the "freshness" of service check results */ +int is_service_result_fresh(service *,time_t,int); /* determines if a service's check results are fresh */ +void check_host_result_freshness(void); /* checks the "freshness" of host check results */ +int is_host_result_fresh(host *,time_t,int); /* determines if a host's check results are fresh */ +int my_system(char *,int,int *,double *,char **,int); /* executes a command via popen(), but also protects against timeouts */ + + +/**** Flap Detection Functions ****/ +void check_for_service_flapping(service *,int,int); /* determines whether or not a service is "flapping" between states */ +void check_for_host_flapping(host *,int,int,int); /* determines whether or not a host is "flapping" between states */ +void set_service_flap(service *,double,double,double,int); /* handles a service that is flapping */ +void clear_service_flap(service *,double,double,double); /* handles a service that has stopped flapping */ +void set_host_flap(host *,double,double,double,int); /* handles a host that is flapping */ +void clear_host_flap(host *,double,double,double); /* handles a host that has stopped flapping */ +void enable_flap_detection_routines(void); /* enables flap detection on a program-wide basis */ +void disable_flap_detection_routines(void); /* disables flap detection on a program-wide basis */ +void enable_host_flap_detection(host *); /* enables flap detection for a particular host */ +void disable_host_flap_detection(host *); /* disables flap detection for a particular host */ +void enable_service_flap_detection(service *); /* enables flap detection for a particular service */ +void disable_service_flap_detection(service *); /* disables flap detection for a particular service */ +void handle_host_flap_detection_disabled(host *); /* handles the details when flap detection is disabled globally or on a per-host basis */ +void handle_service_flap_detection_disabled(service *); /* handles the details when flap detection is disabled globally or on a per-service basis */ + + +/**** Route/Host Check Functions ****/ +int perform_on_demand_host_check(host *,int *,int,int,unsigned long); +int perform_scheduled_host_check(host *,int,double); +int check_host_check_viability_3x(host *,int,int *,time_t *); +int adjust_host_check_attempt_3x(host *,int); +int determine_host_reachability(host *); +int process_host_check_result_3x(host *,int,char *,int,int,int,unsigned long); +int perform_on_demand_host_check_3x(host *,int *,int,int,unsigned long); +int run_sync_host_check_3x(host *,int *,int,int,unsigned long); +int execute_sync_host_check_3x(host *); +int run_scheduled_host_check_3x(host *,int,double); +int run_async_host_check_3x(host *,int,double,int,int,int *,time_t *); +int handle_async_host_check_result_3x(host *,check_result *); + + +/**** Service Check Functions ****/ +int check_service_check_viability(service *,int,int *,time_t *); +int run_scheduled_service_check(service *,int,double); +int run_async_service_check(service *,int,double,int,int,int *,time_t *); +int handle_async_service_check_result(service *,check_result *); + + +/**** Event Handler Functions ****/ +int handle_host_state(host *); /* top level host state handler */ + + + +/**** Common Check Fucntions *****/ +int reap_check_results(void); + + +/**** Check Statistics Functions ****/ +int init_check_stats(void); +int update_check_stats(int,time_t); +int generate_check_stats(void); + + + +/**** Event Handler Functions ****/ +int obsessive_compulsive_service_check_processor(service *); /* distributed monitoring craziness... */ +int obsessive_compulsive_host_check_processor(host *); /* distributed monitoring craziness... */ +int handle_service_event(service *); /* top level service event logic */ +int run_service_event_handler(service *); /* runs the event handler for a specific service */ +int run_global_service_event_handler(service *); /* runs the global service event handler */ +int handle_host_event(host *); /* top level host event logic */ +int run_host_event_handler(host *); /* runs the event handler for a specific host */ +int run_global_host_event_handler(host *); /* runs the global host event handler */ + + +/**** Notification Functions ****/ +int check_service_notification_viability(service *,int,int); /* checks viability of notifying all contacts about a service */ +int is_valid_escalation_for_service_notification(service *,serviceescalation *,int); /* checks if an escalation entry is valid for a particular service notification */ +int should_service_notification_be_escalated(service *); /* checks if a service notification should be escalated */ +int service_notification(service *,int,char *,char *,int); /* notify all contacts about a service (problem or recovery) */ +int check_contact_service_notification_viability(contact *,service *,int,int); /* checks viability of notifying a contact about a service */ +int notify_contact_of_service(contact *,service *,int,char *,char *,int,int); /* notify a single contact about a service */ +int check_host_notification_viability(host *,int,int); /* checks viability of notifying all contacts about a host */ +int is_valid_escalation_for_host_notification(host *,hostescalation *,int); /* checks if an escalation entry is valid for a particular host notification */ +int should_host_notification_be_escalated(host *); /* checks if a host notification should be escalated */ +int host_notification(host *,int,char *,char *,int); /* notify all contacts about a host (problem or recovery) */ +int check_contact_host_notification_viability(contact *,host *,int,int); /* checks viability of notifying a contact about a host */ +int notify_contact_of_host(contact *,host *,int,char *,char *,int,int); /* notify a single contact about a host */ +int create_notification_list_from_host(host *,int,int *); /* given a host, create list of contacts to be notified (remove duplicates) */ +int create_notification_list_from_service(service *,int,int *); /* given a service, create list of contacts to be notified (remove duplicates) */ +int add_notification(contact *); /* adds a notification instance */ +notification *find_notification(contact *); /* finds a notification object */ +time_t get_next_host_notification_time(host *,time_t); /* calculates nex acceptable re-notification time for a host */ +time_t get_next_service_notification_time(service *,time_t); /* calculates nex acceptable re-notification time for a service */ + + +/**** Logging Functions ****/ +void logit(int,int,const char *, ...) + __attribute__((__format__(__printf__, 3, 4))); +int write_to_logs_and_console(char *,unsigned long,int); /* writes a string to screen and logs */ +int write_to_console(char *); /* writes a string to screen */ +int write_to_all_logs(char *,unsigned long); /* writes a string to main log file and syslog facility */ +int write_to_all_logs_with_timestamp(char *,unsigned long,time_t *); /* writes a string to main log file and syslog facility */ +int write_to_log(char *,unsigned long,time_t *); /* write a string to the main log file */ +int write_to_syslog(char *,unsigned long); /* write a string to the syslog facility */ +int log_service_event(service *); /* logs a service event */ +int log_host_event(host *); /* logs a host event */ +int log_host_states(int,time_t *); /* logs initial/current host states */ +int log_service_states(int,time_t *); /* logs initial/current service states */ +int rotate_log_file(time_t); /* rotates the main log file */ +int write_log_file_info(time_t *); /* records log file/version info */ +int open_debug_log(void); +int log_debug_info(int,int,const char *,...) + __attribute__((__format__(__printf__, 3, 4))); +int close_debug_log(void); + + +/**** Cleanup Functions ****/ +void cleanup(void); /* cleanup after ourselves (before quitting or restarting) */ +void free_memory(void); /* free memory allocated to all linked lists in memory */ +int reset_variables(void); /* reset all global variables */ +void free_notification_list(void); /* frees all memory allocated to the notification list */ + + +/**** Hash Functions ****/ +int hashfunc(const char *name1, const char *name2, int hashslots); +int compare_hashdata(const char *,const char *,const char *,const char *); + + +/**** Miscellaneous Functions ****/ +void sighandler(int); /* handles signals */ +void service_check_sighandler(int); /* handles timeouts when executing service checks */ +void host_check_sighandler(int); /* handles timeouts when executing host checks */ +void my_system_sighandler(int); /* handles timeouts when executing commands via my_system() */ +void file_lock_sighandler(int); /* handles timeouts while waiting for file locks */ +void strip(char *); /* strips whitespace from string */ +char *my_strtok(char *,char *); /* my replacement for strtok() function (doesn't skip consecutive tokens) */ +char *my_strsep(char **,const char *); /* Solaris doesn't have strsep(), so I took this from the glibc source code */ +#ifdef REMOVED_10182007 +int my_free(void **); /* my wrapper for free() */ +#endif +int compare_strings(char *,char *); /* compares two strings for equality */ +char *escape_newlines(char *); +int contains_illegal_object_chars(char *); /* tests whether or not an object name (host, service, etc.) contains illegal characters */ +int my_rename(char *,char *); /* renames a file - works across filesystems */ +int my_fcopy(char *,char *); /* copies a file - works across filesystems */ +int get_raw_command_line(command *,char *,char **,int); /* given a raw command line, determine the actual command to run */ +int check_time_against_period(time_t,timeperiod *); /* check to see if a specific time is covered by a time period */ +int is_daterange_single_day(daterange *); +time_t calculate_time_from_weekday_of_month(int,int,int,int); /* calculates midnight time of specific (3rd, last, etc.) weekday of a particular month */ +time_t calculate_time_from_day_of_month(int,int,int); /* calculates midnight time of specific (1st, last, etc.) day of a particular month */ +void get_next_valid_time(time_t, time_t *,timeperiod *); /* get the next valid time in a time period */ +void get_datetime_string(time_t *,char *,int,int); /* get a date/time string for use in output */ +void get_time_breakdown(unsigned long,int *,int *,int *, int *); +time_t get_next_log_rotation_time(void); /* determine the next time to schedule a log rotation */ +int init_embedded_perl(char **); /* initialized embedded perl interpreter */ +int deinit_embedded_perl(void); /* cleans up embedded perl */ +int file_uses_embedded_perl(char *); /* tests whether or not the embedded perl interpreter should be used on a file */ +int dbuf_init(dbuf *,int); +int dbuf_free(dbuf *); +int dbuf_strcat(dbuf *,char *); +int set_environment_var(char *,char *,int); /* sets/clears and environment variable */ + + +/**** External Command Functions ****/ +int check_for_external_commands(void); /* checks for any external commands */ +int process_external_command1(char *); /* top-level external command processor */ +int process_external_command2(int,time_t,char *); /* process an external command */ +int process_external_commands_from_file(char *,int); /* process external commands in a file */ +int process_host_command(int,time_t,char *); /* process an external host command */ +int process_hostgroup_command(int,time_t,char *); /* process an external hostgroup command */ +int process_service_command(int,time_t,char *); /* process an external service command */ +int process_servicegroup_command(int,time_t,char *); /* process an external servicegroup command */ +int process_contact_command(int,time_t,char *); /* process an external contact command */ +int process_contactgroup_command(int,time_t,char *); /* process an external contactgroup command */ + + +/**** External Command Implementations ****/ +int cmd_add_comment(int,time_t,char *); /* add a service or host comment */ +int cmd_delete_comment(int,char *); /* delete a service or host comment */ +int cmd_delete_all_comments(int,char *); /* delete all comments associated with a host or service */ +int cmd_delay_notification(int,char *); /* delay a service or host notification */ +int cmd_schedule_service_check(int,char *,int); /* schedule an immediate or delayed service check */ +int cmd_schedule_check(int,char *); /* schedule an immediate or delayed host check */ +int cmd_schedule_host_service_checks(int,char *,int); /* schedule an immediate or delayed checks of all services on a host */ +int cmd_signal_process(int,char *); /* schedules a program shutdown or restart */ +int cmd_process_service_check_result(int,time_t,char *); /* processes a passive service check */ +int cmd_process_host_check_result(int,time_t,char *); /* processes a passive host check */ +int cmd_acknowledge_problem(int,char *); /* acknowledges a host or service problem */ +int cmd_remove_acknowledgement(int,char *); /* removes a host or service acknowledgement */ +int cmd_schedule_downtime(int,time_t,char *); /* schedules host or service downtime */ +int cmd_delete_downtime(int,char *); /* cancels active/pending host or service scheduled downtime */ +int cmd_change_object_int_var(int,char *); /* changes host/svc (int) variable */ +int cmd_change_object_char_var(int,char *); /* changes host/svc (char) variable */ +int cmd_change_object_custom_var(int,char *); /* changes host/svc custom variable */ +int cmd_process_external_commands_from_file(int,char *); /* process external commands from a file */ + +int process_passive_service_check(time_t,char *,char *,int,char *); +int process_passive_host_check(time_t,char *,int,char *); + + +/**** Internal Command Implementations ****/ +void disable_service_checks(service *); /* disables a service check */ +void enable_service_checks(service *); /* enables a service check */ +void schedule_service_check(service *,time_t,int); /* schedules an immediate or delayed service check */ +void schedule_host_check(host *,time_t,int); /* schedules an immediate or delayed host check */ +void enable_all_notifications(void); /* enables notifications on a program-wide basis */ +void disable_all_notifications(void); /* disables notifications on a program-wide basis */ +void enable_service_notifications(service *); /* enables service notifications */ +void disable_service_notifications(service *); /* disables service notifications */ +void enable_host_notifications(host *); /* enables host notifications */ +void disable_host_notifications(host *); /* disables host notifications */ +void enable_and_propagate_notifications(host *,int,int,int,int); /* enables notifications for all hosts and services beyond a given host */ +void disable_and_propagate_notifications(host *,int,int,int,int); /* disables notifications for all hosts and services beyond a given host */ +void schedule_and_propagate_downtime(host *,time_t,char *,char *,time_t,time_t,int,unsigned long,unsigned long); /* schedules downtime for all hosts beyond a given host */ +void acknowledge_host_problem(host *,char *,char *,int,int,int); /* acknowledges a host problem */ +void acknowledge_service_problem(service *,char *,char *,int,int,int); /* acknowledges a service problem */ +void remove_host_acknowledgement(host *); /* removes a host acknowledgement */ +void remove_service_acknowledgement(service *); /* removes a service acknowledgement */ +void start_executing_service_checks(void); /* starts executing service checks */ +void stop_executing_service_checks(void); /* stops executing service checks */ +void start_accepting_passive_service_checks(void); /* starts accepting passive service check results */ +void stop_accepting_passive_service_checks(void); /* stops accepting passive service check results */ +void enable_passive_service_checks(service *); /* enables passive service checks for a particular service */ +void disable_passive_service_checks(service *); /* disables passive service checks for a particular service */ +void start_using_event_handlers(void); /* enables event handlers on a program-wide basis */ +void stop_using_event_handlers(void); /* disables event handlers on a program-wide basis */ +void enable_service_event_handler(service *); /* enables the event handler for a particular service */ +void disable_service_event_handler(service *); /* disables the event handler for a particular service */ +void enable_host_event_handler(host *); /* enables the event handler for a particular host */ +void disable_host_event_handler(host *); /* disables the event handler for a particular host */ +void enable_host_checks(host *); /* enables checks of a particular host */ +void disable_host_checks(host *); /* disables checks of a particular host */ +void start_obsessing_over_service_checks(void); /* start obsessing about service check results */ +void stop_obsessing_over_service_checks(void); /* stop obsessing about service check results */ +void start_obsessing_over_host_checks(void); /* start obsessing about host check results */ +void stop_obsessing_over_host_checks(void); /* stop obsessing about host check results */ +void enable_service_freshness_checks(void); /* enable service freshness checks */ +void disable_service_freshness_checks(void); /* disable service freshness checks */ +void enable_host_freshness_checks(void); /* enable host freshness checks */ +void disable_host_freshness_checks(void); /* disable host freshness checks */ +void process_passive_checks(void); /* processes passive host and service check results */ +void enable_all_failure_prediction(void); /* enables failure prediction on a program-wide basis */ +void disable_all_failure_prediction(void); /* disables failure prediction on a program-wide basis */ +void enable_performance_data(void); /* enables processing of performance data on a program-wide basis */ +void disable_performance_data(void); /* disables processing of performance data on a program-wide basis */ +void start_executing_host_checks(void); /* starts executing host checks */ +void stop_executing_host_checks(void); /* stops executing host checks */ +void start_accepting_passive_host_checks(void); /* starts accepting passive host check results */ +void stop_accepting_passive_host_checks(void); /* stops accepting passive host check results */ +void enable_passive_host_checks(host *); /* enables passive host checks for a particular host */ +void disable_passive_host_checks(host *); /* disables passive host checks for a particular host */ +void start_obsessing_over_service(service *); /* start obsessing about specific service check results */ +void stop_obsessing_over_service(service *); /* stop obsessing about specific service check results */ +void start_obsessing_over_host(host *); /* start obsessing about specific host check results */ +void stop_obsessing_over_host(host *); /* stop obsessing about specific host check results */ +void set_host_notification_number(host *,int); /* sets current notification number for a specific host */ +void set_service_notification_number(service *,int); /* sets current notification number for a specific service */ +void enable_contact_host_notifications(contact *); /* enables host notifications for a specific contact */ +void disable_contact_host_notifications(contact *); /* disables host notifications for a specific contact */ +void enable_contact_service_notifications(contact *); /* enables service notifications for a specific contact */ +void disable_contact_service_notifications(contact *); /* disables service notifications for a specific contact */ + +int init_check_result_worker_thread(void); +int shutdown_check_result_worker_thread(void); +void * check_result_worker_thread(void *); +void cleanup_check_result_worker_thread(void *); + +int init_command_file_worker_thread(void); +int shutdown_command_file_worker_thread(void); +void * command_file_worker_thread(void *); +void cleanup_command_file_worker_thread(void *); + +int submit_external_command(char *,int *); +int submit_raw_external_command(char *,time_t *,int *); + +char *get_program_version(void); +char *get_program_modification_date(void); + +mmapfile *mmap_fopen(char *); /* open a file read-only via mmap() */ +int mmap_fclose(mmapfile *); +char *mmap_fgets(mmapfile *); +char *mmap_fgets_multiline(mmapfile *); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/include/nebcallbacks.h b/include/nebcallbacks.h new file mode 100644 index 0000000..a0fc3d5 --- /dev/null +++ b/include/nebcallbacks.h @@ -0,0 +1,88 @@ +/***************************************************************************** + * + * NEBCALLBACKS.H - Include file for event broker modules + * + * Copyright (c) 2002-2007 Ethan Galstad (nagios@nagios.org) + * Last Modified: 01-06-2007 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + +#ifndef _NEBCALLBACKS_H +#define _NEBCALLBACKS_H + +#include "config.h" +#include "nebmodules.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +/***** CALLBACK TYPES *****/ + +#define NEBCALLBACK_NUMITEMS 33 /* total number of callback types we have */ + +#define NEBCALLBACK_RESERVED0 0 /* reserved for future use */ +#define NEBCALLBACK_RESERVED1 1 +#define NEBCALLBACK_RESERVED2 2 +#define NEBCALLBACK_RESERVED3 3 +#define NEBCALLBACK_RESERVED4 4 + +#define NEBCALLBACK_RAW_DATA 5 +#define NEBCALLBACK_NEB_DATA 6 + +#define NEBCALLBACK_PROCESS_DATA 7 +#define NEBCALLBACK_TIMED_EVENT_DATA 8 +#define NEBCALLBACK_LOG_DATA 9 +#define NEBCALLBACK_SYSTEM_COMMAND_DATA 10 +#define NEBCALLBACK_EVENT_HANDLER_DATA 11 +#define NEBCALLBACK_NOTIFICATION_DATA 12 +#define NEBCALLBACK_SERVICE_CHECK_DATA 13 +#define NEBCALLBACK_HOST_CHECK_DATA 14 +#define NEBCALLBACK_COMMENT_DATA 15 +#define NEBCALLBACK_DOWNTIME_DATA 16 +#define NEBCALLBACK_FLAPPING_DATA 17 +#define NEBCALLBACK_PROGRAM_STATUS_DATA 18 +#define NEBCALLBACK_HOST_STATUS_DATA 19 +#define NEBCALLBACK_SERVICE_STATUS_DATA 20 +#define NEBCALLBACK_ADAPTIVE_PROGRAM_DATA 21 +#define NEBCALLBACK_ADAPTIVE_HOST_DATA 22 +#define NEBCALLBACK_ADAPTIVE_SERVICE_DATA 23 +#define NEBCALLBACK_EXTERNAL_COMMAND_DATA 24 +#define NEBCALLBACK_AGGREGATED_STATUS_DATA 25 +#define NEBCALLBACK_RETENTION_DATA 26 +#define NEBCALLBACK_CONTACT_NOTIFICATION_DATA 27 +#define NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA 28 +#define NEBCALLBACK_ACKNOWLEDGEMENT_DATA 29 +#define NEBCALLBACK_STATE_CHANGE_DATA 30 +#define NEBCALLBACK_CONTACT_STATUS_DATA 31 +#define NEBCALLBACK_ADAPTIVE_CONTACT_DATA 32 + + +/***** CALLBACK FUNCTIONS *****/ + +int neb_register_callback(int callback_type, void *mod_handle, int priority, int (*callback_func)(int,void *)); +int neb_deregister_callback(int callback_type, int (*callback_func)(int,void *)); +int neb_deregister_module_callbacks(nebmodule *); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/nebmodules.h b/include/nebmodules.h new file mode 100644 index 0000000..bb279e8 --- /dev/null +++ b/include/nebmodules.h @@ -0,0 +1,102 @@ +/***************************************************************************** + * + * NEBMODULES.H - Include file for event broker modules + * + * Copyright (c) 2002-2006 Ethan Galstad (nagios@nagios.org) + * Last Modified: 02-27-2006 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + +#ifndef _NEBMODULES_H +#define _NEBMODULES_H + +#ifdef __cplusplus + extern "C" { +#endif + +/***** MODULE VERSION INFORMATION *****/ + +#define NEB_API_VERSION(x) int __neb_api_version = x; +#define CURRENT_NEB_API_VERSION 3 + + + +/***** MODULE INFORMATION *****/ + +#define NEBMODULE_MODINFO_NUMITEMS 6 +#define NEBMODULE_MODINFO_TITLE 0 +#define NEBMODULE_MODINFO_AUTHOR 1 +#define NEBMODULE_MODINFO_COPYRIGHT 2 +#define NEBMODULE_MODINFO_VERSION 3 +#define NEBMODULE_MODINFO_LICENSE 4 +#define NEBMODULE_MODINFO_DESC 5 + + + +/***** MODULE LOAD/UNLOAD OPTIONS *****/ + +#define NEBMODULE_NORMAL_LOAD 0 /* module is being loaded normally */ +#define NEBMODULE_REQUEST_UNLOAD 0 /* request module to unload (but don't force it) */ +#define NEBMODULE_FORCE_UNLOAD 1 /* force module to unload */ + + + +/***** MODULES UNLOAD REASONS *****/ + +#define NEBMODULE_NEB_SHUTDOWN 1 /* event broker is shutting down */ +#define NEBMODULE_NEB_RESTART 2 /* event broker is restarting */ +#define NEBMODULE_ERROR_NO_INIT 3 /* _module_init() function was not found in module */ +#define NEBMODULE_ERROR_BAD_INIT 4 /* _module_init() function returned a bad code */ +#define NEBMODULE_ERROR_API_VERSION 5 /* module version is incompatible with current api */ + + + +/***** MODULE STRUCTURES *****/ + +/* NEB module structure */ +typedef struct nebmodule_struct{ + char *filename; + char *args; + char *info[NEBMODULE_MODINFO_NUMITEMS]; + int should_be_loaded; + int is_currently_loaded; +#ifdef USE_LTDL + lt_dlhandle module_handle; + lt_ptr init_func; + lt_ptr deinit_func; +#else + void *module_handle; + void *init_func; + void *deinit_func; +#endif +#ifdef HAVE_PTHREAD_H + pthread_t thread_id; +#endif + struct nebmodule_struct *next; + }nebmodule; + + + +/***** MODULE FUNCTIONS *****/ +int neb_set_module_info(void *,int,char *); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/include/nebstructs.h b/include/nebstructs.h new file mode 100644 index 0000000..dfb5a16 --- /dev/null +++ b/include/nebstructs.h @@ -0,0 +1,533 @@ +/***************************************************************************** + * + * NEBSTRUCTS.H - Event broker includes for Nagios + * + * Copyright (c) 2003-2007 Ethan Galstad (nagios@nagios.org) + * Last Modified: 10-28-2007 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + +#ifndef _NEBSTRUCTS_H +#define _NEBSTRUCTS_H + +#include "config.h" +#include "pnp.h" +#include "objects.h" +#include "nagios.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/****** STRUCTURES *************************/ + +/* process data structure */ +typedef struct nebstruct_process_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + }nebstruct_process_data; + + +/* timed event data structure */ +typedef struct nebstruct_timed_event_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int event_type; + int recurring; + time_t run_time; + void *event_data; + + void *event_ptr; + }nebstruct_timed_event_data; + + +/* log data structure */ +typedef struct nebstruct_log_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + time_t entry_time; + int data_type; + char *data; + }nebstruct_log_data; + + +/* system command structure */ +typedef struct nebstruct_system_command_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + struct timeval start_time; + struct timeval end_time; + int timeout; + char *command_line; + int early_timeout; + double execution_time; + int return_code; + char *output; + }nebstruct_system_command_data; + + +/* event handler structure */ +typedef struct nebstruct_event_handler_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int eventhandler_type; + char *host_name; + char *service_description; + int state_type; + int state; + int timeout; + char *command_name; + char *command_args; + char *command_line; + struct timeval start_time; + struct timeval end_time; + int early_timeout; + double execution_time; + int return_code; + char *output; + + void *object_ptr; + }nebstruct_event_handler_data; + + +/* host check structure */ +typedef struct nebstruct_host_check_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + char *host_name; + int current_attempt; + int check_type; + int max_attempts; + int state_type; + int state; + int timeout; + char *command_name; + char *command_args; + char *command_line; + struct timeval start_time; + struct timeval end_time; + int early_timeout; + double execution_time; + double latency; + int return_code; + char *output; + char *long_output; + char *perf_data; + + void *object_ptr; + }nebstruct_host_check_data; + + +/* service check structure */ +typedef struct nebstruct_service_check_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + char *host_name; + char *service_description; + int check_type; + int current_attempt; + int max_attempts; + int state_type; + int state; + int timeout; + char *command_name; + char *command_args; + char *command_line; + struct timeval start_time; + struct timeval end_time; + int early_timeout; + double execution_time; + double latency; + int return_code; + char *output; + char *long_output; + char *perf_data; + + void *object_ptr; + }nebstruct_service_check_data; + + +/* comment data structure */ +typedef struct nebstruct_comment_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int comment_type; + char *host_name; + char *service_description; + time_t entry_time; + char *author_name; + char *comment_data; + int persistent; + int source; + int entry_type; + int expires; + time_t expire_time; + unsigned long comment_id; + + void *object_ptr; /* not implemented yet */ + }nebstruct_comment_data; + + +/* downtime data structure */ +typedef struct nebstruct_downtime_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int downtime_type; + char *host_name; + char *service_description; + time_t entry_time; + char *author_name; + char *comment_data; + time_t start_time; + time_t end_time; + int fixed; + unsigned long duration; + unsigned long triggered_by; + unsigned long downtime_id; + + void *object_ptr; /* not implemented yet */ + }nebstruct_downtime_data; + + +/* flapping data structure */ +typedef struct nebstruct_flapping_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int flapping_type; + char *host_name; + char *service_description; + double percent_change; + double high_threshold; + double low_threshold; + unsigned long comment_id; + + void *object_ptr; + }nebstruct_flapping_data; + + +/* program status structure */ +typedef struct nebstruct_program_status_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + time_t program_start; + int pid; + int daemon_mode; + time_t last_command_check; + time_t last_log_rotation; + int notifications_enabled; + int active_service_checks_enabled; + int passive_service_checks_enabled; + int active_host_checks_enabled; + int passive_host_checks_enabled; + int event_handlers_enabled; + int flap_detection_enabled; + int failure_prediction_enabled; + int process_performance_data; + int obsess_over_hosts; + int obsess_over_services; + unsigned long modified_host_attributes; + unsigned long modified_service_attributes; + char *global_host_event_handler; + char *global_service_event_handler; + }nebstruct_program_status_data; + + +/* host status structure */ +typedef struct nebstruct_host_status_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + void *object_ptr; + }nebstruct_host_status_data; + + +/* service status structure */ +typedef struct nebstruct_service_status_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + void *object_ptr; + }nebstruct_service_status_data; + + +/* contact status structure */ +typedef struct nebstruct_contact_status_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + void *object_ptr; + }nebstruct_contact_status_data; + + +/* notification data structure */ +typedef struct nebstruct_notification_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int notification_type; + struct timeval start_time; + struct timeval end_time; + char *host_name; + char *service_description; + int reason_type; + int state; + char *output; + char *ack_author; + char *ack_data; + int escalated; + int contacts_notified; + + void *object_ptr; + }nebstruct_notification_data; + + +/* contact notification data structure */ +typedef struct nebstruct_contact_notification_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int notification_type; + struct timeval start_time; + struct timeval end_time; + char *host_name; + char *service_description; + char *contact_name; + int reason_type; + int state; + char *output; + char *ack_author; + char *ack_data; + int escalated; + + void *object_ptr; + void *contact_ptr; + }nebstruct_contact_notification_data; + + +/* contact notification method data structure */ +typedef struct nebstruct_contact_notification_method_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int notification_type; + struct timeval start_time; + struct timeval end_time; + char *host_name; + char *service_description; + char *contact_name; + char *command_name; + char *command_args; + int reason_type; + int state; + char *output; + char *ack_author; + char *ack_data; + int escalated; + + void *object_ptr; + void *contact_ptr; + }nebstruct_contact_notification_method_data; + + +/* adaptive program data structure */ +typedef struct nebstruct_adaptive_program_data_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int command_type; + unsigned long modified_host_attribute; + unsigned long modified_host_attributes; + unsigned long modified_service_attribute; + unsigned long modified_service_attributes; + }nebstruct_adaptive_program_data; + + +/* adaptive host data structure */ +typedef struct nebstruct_adaptive_host_data_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int command_type; + unsigned long modified_attribute; + unsigned long modified_attributes; + + void *object_ptr; + }nebstruct_adaptive_host_data; + + +/* adaptive service data structure */ +typedef struct nebstruct_adaptive_service_data_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int command_type; + unsigned long modified_attribute; + unsigned long modified_attributes; + + void *object_ptr; + }nebstruct_adaptive_service_data; + + +/* adaptive contact data structure */ +typedef struct nebstruct_adaptive_contact_data_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int command_type; + unsigned long modified_attribute; + unsigned long modified_attributes; + unsigned long modified_host_attribute; + unsigned long modified_host_attributes; + unsigned long modified_service_attribute; + unsigned long modified_service_attributes; + + void *object_ptr; + }nebstruct_adaptive_contact_data; + + +/* external command data structure */ +typedef struct nebstruct_external_command_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int command_type; + time_t entry_time; + char *command_string; + char *command_args; + }nebstruct_external_command_data; + + +/* aggregated status data structure */ +typedef struct nebstruct_aggregated_status_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + }nebstruct_aggregated_status_data; + + +/* retention data structure */ +typedef struct nebstruct_retention_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + }nebstruct_retention_data; + + +/* acknowledgement structure */ +typedef struct nebstruct_acknowledgement_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int acknowledgement_type; + char *host_name; + char *service_description; + int state; + char *author_name; + char *comment_data; + int is_sticky; + int persistent_comment; + int notify_contacts; + + void *object_ptr; + }nebstruct_acknowledgement_data; + + +/* state change structure */ +typedef struct nebstruct_statechange_struct{ + int type; + int flags; + int attr; + struct timeval timestamp; + + int statechange_type; + char *host_name; + char *service_description; + int state; + int state_type; + int current_attempt; + int max_attempts; + char *output; + + void *object_ptr; + }nebstruct_statechange_data; + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/include/npcdmod.h b/include/npcdmod.h new file mode 100644 index 0000000..f72d9d3 --- /dev/null +++ b/include/npcdmod.h @@ -0,0 +1,41 @@ +/***************************************************************************** + * + * NPCDMOD.H + * + * Copyright (c) 2008 Hendrik Baecker (http://www.pnp4nagios.org) + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Last Modified: 11-18-2008 + * + *****************************************************************************/ + +#define PERFDATA_BUFFER 65536 + + +/* MMAPFILE structure - used for reading files via mmap() */ +typedef struct pnp_mmapfile_struct { + char *path; + int mode; + int fd; + unsigned long file_size; + unsigned long current_position; + unsigned long current_line; + void *mmap_buf; +} pnp_mmapfile; + +pnp_mmapfile *pnp_mmap_fopen(char *); /* open a file read-only via mmap() */ +int pnp_mmap_fclose(pnp_mmapfile *); +char *pnp_mmap_fgets(pnp_mmapfile *); +char *pnp_mmap_fgets_multiline(pnp_mmapfile *); +extern void pnp_strip(char *); diff --git a/include/objects.h b/include/objects.h new file mode 100644 index 0000000..f82e39f --- /dev/null +++ b/include/objects.h @@ -0,0 +1,771 @@ +/***************************************************************************** + * + * OBJECTS.H - Header file for object addition/search functions + * + * Copyright (c) 1999-2007 Ethan Galstad (nagios@nagios.org) + * Last Modified: 11-10-2007 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + + +#ifndef _OBJECTS_H +#define _OBJECTS_H + +#include "config.h" +#include "common.h" + +#ifdef __cplusplus + extern "C" { +#endif + + + +/*************** CURRENT OBJECT REVISION **************/ + +#define CURRENT_OBJECT_STRUCTURE_VERSION 307 /* increment when changes are made to data structures... */ + /* Nagios 3 starts at 300, Nagios 4 at 400, etc. */ + + + +/***************** OBJECT SIZE LIMITS *****************/ + +#define MAX_STATE_HISTORY_ENTRIES 21 /* max number of old states to keep track of for flap detection */ +#define MAX_CONTACT_ADDRESSES 6 /* max number of custom addresses a contact can have */ + + + +/***************** SKIP LISTS ****************/ + +#define NUM_OBJECT_SKIPLISTS 13 + +#define HOST_SKIPLIST 1 +#define SERVICE_SKIPLIST 2 +#define COMMAND_SKIPLIST 3 +#define TIMEPERIOD_SKIPLIST 4 +#define CONTACT_SKIPLIST 5 +#define CONTACTGROUP_SKIPLIST 6 +#define HOSTGROUP_SKIPLIST 7 +#define SERVICEGROUP_SKIPLIST 8 +#define HOSTDEPENDENCY_SKIPLIST 9 +#define SERVICEDEPENDENCY_SKIPLIST 10 +#define HOSTESCALATION_SKIPLIST 11 +#define SERVICEESCALATION_SKIPLIST 12 + + +/****************** DATA STRUCTURES *******************/ + +typedef struct host_struct host; +typedef struct service_struct service; +typedef struct contact_struct contact; + +/* OBJECT LIST STRUCTURE */ +typedef struct objectlist_struct{ + void *object_ptr; + struct objectlist_struct *next; + }objectlist; + + +/* TIMERANGE structure */ +typedef struct timerange_struct{ + unsigned long range_start; + unsigned long range_end; + struct timerange_struct *next; + }timerange; + + +/* DATERANGE structure */ +typedef struct daterange_struct{ + int type; + int syear; /* start year */ + int smon; /* start month */ + int smday; /* start day of month (may 3rd, last day in feb) */ + int swday; /* start day of week (thursday) */ + int swday_offset; /* start weekday offset (3rd thursday, last monday in jan) */ + int eyear; + int emon; + int emday; + int ewday; + int ewday_offset; + int skip_interval; + timerange *times; + struct daterange_struct *next; + }daterange; + + +/* TIMEPERIODEXCLUSION structure */ +typedef struct timeperiodexclusion_struct{ + char *timeperiod_name; + struct timeperiod_struct *timeperiod_ptr; + struct timeperiodexclusion_struct *next; + }timeperiodexclusion; + + +/* TIMEPERIOD structure */ +typedef struct timeperiod_struct{ + char *name; + char *alias; + timerange *days[7]; + daterange *exceptions[DATERANGE_TYPES]; + timeperiodexclusion *exclusions; + struct timeperiod_struct *next; + struct timeperiod_struct *nexthash; + }timeperiod; + + +/* CONTACTSMEMBER structure */ +typedef struct contactsmember_struct{ + char *contact_name; +#ifdef NSCORE + contact *contact_ptr; +#endif + struct contactsmember_struct *next; + }contactsmember; + + +/* CONTACTGROUP structure */ +typedef struct contactgroup_struct{ + char *group_name; + char *alias; + contactsmember *members; + struct contactgroup_struct *next; + struct contactgroup_struct *nexthash; + }contactgroup; + + +/* CONTACTGROUPSMEMBER structure */ +typedef struct contactgroupsmember_struct{ + char *group_name; +#ifdef NSCORE + contactgroup *group_ptr; +#endif + struct contactgroupsmember_struct *next; + }contactgroupsmember; + + +/* CUSTOMVARIABLESMEMBER structure */ +typedef struct customvariablesmember_struct{ + char *variable_name; + char *variable_value; + int has_been_modified; + struct customvariablesmember_struct *next; + }customvariablesmember; + + +/* COMMAND structure */ +typedef struct command_struct{ + char *name; + char *command_line; + struct command_struct *next; + struct command_struct *nexthash; + }command; + + +/* COMMANDSMEMBER structure */ +typedef struct commandsmember_struct{ + char *command; +#ifdef NSCORE + command *command_ptr; +#endif + struct commandsmember_struct *next; + }commandsmember; + + +/* CONTACT structure */ +struct contact_struct{ + char *name; + char *alias; + char *email; + char *pager; + char *address[MAX_CONTACT_ADDRESSES]; + commandsmember *host_notification_commands; + commandsmember *service_notification_commands; + int notify_on_service_unknown; + int notify_on_service_warning; + int notify_on_service_critical; + int notify_on_service_recovery; + int notify_on_service_flapping; + int notify_on_service_downtime; + int notify_on_host_down; + int notify_on_host_unreachable; + int notify_on_host_recovery; + int notify_on_host_flapping; + int notify_on_host_downtime; + char *host_notification_period; + char *service_notification_period; + int host_notifications_enabled; + int service_notifications_enabled; + int can_submit_commands; + int retain_status_information; + int retain_nonstatus_information; + customvariablesmember *custom_variables; +#ifdef NSCORE + time_t last_host_notification; + time_t last_service_notification; + unsigned long modified_attributes; + unsigned long modified_host_attributes; + unsigned long modified_service_attributes; + + timeperiod *host_notification_period_ptr; + timeperiod *service_notification_period_ptr; + objectlist *contactgroups_ptr; +#endif + struct contact_struct *next; + struct contact_struct *nexthash; + }; + + +/* SERVICESMEMBER structure */ +typedef struct servicesmember_struct{ + char *host_name; + char *service_description; +#ifdef NSCORE + service *service_ptr; +#endif + struct servicesmember_struct *next; + }servicesmember; + + +/* HOSTSMEMBER structure */ +typedef struct hostsmember_struct{ + char *host_name; +#ifdef NSCORE + host *host_ptr; +#endif + struct hostsmember_struct *next; + }hostsmember; + + +/* HOSTGROUP structure */ +typedef struct hostgroup_struct{ + char *group_name; + char *alias; + hostsmember *members; + char *notes; + char *notes_url; + char *action_url; + struct hostgroup_struct *next; + struct hostgroup_struct *nexthash; + }hostgroup; + + +/* HOST structure */ +struct host_struct{ + char *name; + char *display_name; + char *alias; + char *address; + hostsmember *parent_hosts; + hostsmember *child_hosts; + servicesmember *services; + char *host_check_command; + int initial_state; + double check_interval; + double retry_interval; + int max_attempts; + char *event_handler; + contactgroupsmember *contact_groups; + contactsmember *contacts; + double notification_interval; + double first_notification_delay; + int notify_on_down; + int notify_on_unreachable; + int notify_on_recovery; + int notify_on_flapping; + int notify_on_downtime; + char *notification_period; + char *check_period; + int flap_detection_enabled; + double low_flap_threshold; + double high_flap_threshold; + int flap_detection_on_up; + int flap_detection_on_down; + int flap_detection_on_unreachable; + int stalk_on_up; + int stalk_on_down; + int stalk_on_unreachable; + int check_freshness; + int freshness_threshold; + int process_performance_data; + int checks_enabled; + int accept_passive_host_checks; + int event_handler_enabled; + int retain_status_information; + int retain_nonstatus_information; + int failure_prediction_enabled; + char *failure_prediction_options; + int obsess_over_host; + char *notes; + char *notes_url; + char *action_url; + char *icon_image; + char *icon_image_alt; + char *vrml_image; + char *statusmap_image; + int have_2d_coords; + int x_2d; + int y_2d; + int have_3d_coords; + double x_3d; + double y_3d; + double z_3d; + int should_be_drawn; + customvariablesmember *custom_variables; +#ifdef NSCORE + int problem_has_been_acknowledged; + int acknowledgement_type; + int check_type; + int current_state; + int last_state; + int last_hard_state; + char *plugin_output; + char *long_plugin_output; + char *perf_data; + int state_type; + int current_attempt; + unsigned long current_event_id; + unsigned long last_event_id; + unsigned long current_problem_id; + unsigned long last_problem_id; + double latency; + double execution_time; + int is_executing; + int check_options; + int notifications_enabled; + time_t last_host_notification; + time_t next_host_notification; + time_t next_check; + int should_be_scheduled; + time_t last_check; + time_t last_state_change; + time_t last_hard_state_change; + time_t last_time_up; + time_t last_time_down; + time_t last_time_unreachable; + int has_been_checked; + int is_being_freshened; + int notified_on_down; + int notified_on_unreachable; + int current_notification_number; + int no_more_notifications; + unsigned long current_notification_id; + int check_flapping_recovery_notification; + int scheduled_downtime_depth; + int pending_flex_downtime; + int state_history[MAX_STATE_HISTORY_ENTRIES]; /* flap detection */ + int state_history_index; + time_t last_state_history_update; + int is_flapping; + unsigned long flapping_comment_id; + double percent_state_change; + int total_services; + unsigned long total_service_check_interval; + unsigned long modified_attributes; + int circular_path_checked; + int contains_circular_path; + + command *event_handler_ptr; + command *check_command_ptr; + timeperiod *check_period_ptr; + timeperiod *notification_period_ptr; + objectlist *hostgroups_ptr; +#endif + struct host_struct *next; + struct host_struct *nexthash; + }; + + +/* SERVICEGROUP structure */ +typedef struct servicegroup_struct{ + char *group_name; + char *alias; + servicesmember *members; + char *notes; + char *notes_url; + char *action_url; + struct servicegroup_struct *next; + struct servicegroup_struct *nexthash; + }servicegroup; + + +/* SERVICE structure */ +struct service_struct{ + char *host_name; + char *description; + char *display_name; + char *service_check_command; + char *event_handler; + int initial_state; + double check_interval; + double retry_interval; + int max_attempts; + int parallelize; + contactgroupsmember *contact_groups; + contactsmember *contacts; + double notification_interval; + double first_notification_delay; + int notify_on_unknown; + int notify_on_warning; + int notify_on_critical; + int notify_on_recovery; + int notify_on_flapping; + int notify_on_downtime; + int stalk_on_ok; + int stalk_on_warning; + int stalk_on_unknown; + int stalk_on_critical; + int is_volatile; + char *notification_period; + char *check_period; + int flap_detection_enabled; + double low_flap_threshold; + double high_flap_threshold; + int flap_detection_on_ok; + int flap_detection_on_warning; + int flap_detection_on_unknown; + int flap_detection_on_critical; + int process_performance_data; + int check_freshness; + int freshness_threshold; + int accept_passive_service_checks; + int event_handler_enabled; + int checks_enabled; + int retain_status_information; + int retain_nonstatus_information; + int notifications_enabled; + int obsess_over_service; + int failure_prediction_enabled; + char *failure_prediction_options; + char *notes; + char *notes_url; + char *action_url; + char *icon_image; + char *icon_image_alt; + customvariablesmember *custom_variables; +#ifdef NSCORE + int problem_has_been_acknowledged; + int acknowledgement_type; + int host_problem_at_last_check; + int check_type; + int current_state; + int last_state; + int last_hard_state; + char *plugin_output; + char *long_plugin_output; + char *perf_data; + int state_type; + time_t next_check; + int should_be_scheduled; + time_t last_check; + int current_attempt; + unsigned long current_event_id; + unsigned long last_event_id; + unsigned long current_problem_id; + unsigned long last_problem_id; + time_t last_notification; + time_t next_notification; + int no_more_notifications; + int check_flapping_recovery_notification; + time_t last_state_change; + time_t last_hard_state_change; + time_t last_time_ok; + time_t last_time_warning; + time_t last_time_unknown; + time_t last_time_critical; + int has_been_checked; + int is_being_freshened; + int notified_on_unknown; + int notified_on_warning; + int notified_on_critical; + int current_notification_number; + unsigned long current_notification_id; + double latency; + double execution_time; + int is_executing; + int check_options; + int scheduled_downtime_depth; + int pending_flex_downtime; + int state_history[MAX_STATE_HISTORY_ENTRIES]; /* flap detection */ + int state_history_index; + int is_flapping; + unsigned long flapping_comment_id; + double percent_state_change; + unsigned long modified_attributes; + + host *host_ptr; + command *event_handler_ptr; + char *event_handler_args; + command *check_command_ptr; + char *check_command_args; + timeperiod *check_period_ptr; + timeperiod *notification_period_ptr; + objectlist *servicegroups_ptr; +#endif + struct service_struct *next; + struct service_struct *nexthash; + }; + + +/* SERVICE ESCALATION structure */ +typedef struct serviceescalation_struct{ + char *host_name; + char *description; + int first_notification; + int last_notification; + double notification_interval; + char *escalation_period; + int escalate_on_recovery; + int escalate_on_warning; + int escalate_on_unknown; + int escalate_on_critical; + contactgroupsmember *contact_groups; + contactsmember *contacts; +#ifdef NSCORE + service *service_ptr; + timeperiod *escalation_period_ptr; +#endif + struct serviceescalation_struct *next; + struct serviceescalation_struct *nexthash; + }serviceescalation; + + +/* SERVICE DEPENDENCY structure */ +typedef struct servicedependency_struct{ + int dependency_type; + char *dependent_host_name; + char *dependent_service_description; + char *host_name; + char *service_description; + char *dependency_period; + int inherits_parent; + int fail_on_ok; + int fail_on_warning; + int fail_on_unknown; + int fail_on_critical; + int fail_on_pending; +#ifdef NSCORE + int circular_path_checked; + int contains_circular_path; + + service *master_service_ptr; + service *dependent_service_ptr; + timeperiod *dependency_period_ptr; +#endif + struct servicedependency_struct *next; + struct servicedependency_struct *nexthash; + }servicedependency; + + +/* HOST ESCALATION structure */ +typedef struct hostescalation_struct{ + char *host_name; + int first_notification; + int last_notification; + double notification_interval; + char *escalation_period; + int escalate_on_recovery; + int escalate_on_down; + int escalate_on_unreachable; + contactgroupsmember *contact_groups; + contactsmember *contacts; +#ifdef NSCORE + host *host_ptr; + timeperiod *escalation_period_ptr; +#endif + struct hostescalation_struct *next; + struct hostescalation_struct *nexthash; + }hostescalation; + + +/* HOST DEPENDENCY structure */ +typedef struct hostdependency_struct{ + int dependency_type; + char *dependent_host_name; + char *host_name; + char *dependency_period; + int inherits_parent; + int fail_on_up; + int fail_on_down; + int fail_on_unreachable; + int fail_on_pending; +#ifdef NSCORE + int circular_path_checked; + int contains_circular_path; + + host *master_host_ptr; + host *dependent_host_ptr; + timeperiod *dependency_period_ptr; +#endif + struct hostdependency_struct *next; + struct hostdependency_struct *nexthash; + }hostdependency; + + + + +/****************** HASH STRUCTURES ********************/ + +typedef struct host_cursor_struct{ + int host_hashchain_iterator; + host *current_host_pointer; + }host_cursor; + + + + + +/********************* FUNCTIONS **********************/ + +/**** Top-level input functions ****/ +int read_object_config_data(char *,int,int,int); /* reads all external configuration data of specific types */ + + +/**** Object Creation Functions ****/ +contact *add_contact(char *,char *,char *,char *,char **,char *,char *,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int); /* adds a contact definition */ +commandsmember *add_service_notification_command_to_contact(contact *,char *); /* adds a service notification command to a contact definition */ +commandsmember *add_host_notification_command_to_contact(contact *,char *); /* adds a host notification command to a contact definition */ +customvariablesmember *add_custom_variable_to_contact(contact *,char *,char *); /* adds a custom variable to a service definition */ +host *add_host(char *,char *,char *,char *,char *,int,double,double,int,int,int,int,int,int,double,double,char *,int,char *,int,int,char *,int,int,double,double,int,int,int,int,int,int,int,int,char *,int,int,char *,char *,char *,char *,char *,char *,char *,int,int,int,double,double,double,int,int,int,int,int); /* adds a host definition */ +hostsmember *add_parent_host_to_host(host *,char *); /* adds a parent host to a host definition */ +hostsmember *add_child_link_to_host(host *,host *); /* adds a child host to a host definition */ +contactgroupsmember *add_contactgroup_to_host(host *,char *); /* adds a contactgroup to a host definition */ +contactsmember *add_contact_to_host(host *,char *); /* adds a contact to a host definition */ +customvariablesmember *add_custom_variable_to_host(host *,char *,char *); /* adds a custom variable to a host definition */ +timeperiod *add_timeperiod(char *,char *); /* adds a timeperiod definition */ +timeperiodexclusion *add_exclusion_to_timeperiod(timeperiod *,char *); /* adds an exclusion to a timeperiod */ +timerange *add_timerange_to_timeperiod(timeperiod *,int,unsigned long,unsigned long); /* adds a timerange to a timeperiod definition */ +daterange *add_exception_to_timeperiod(timeperiod *,int,int,int,int,int,int,int,int,int,int,int,int); +timerange *add_timerange_to_daterange(daterange *,unsigned long,unsigned long); +hostgroup *add_hostgroup(char *,char *,char *,char *,char *); /* adds a hostgroup definition */ +hostsmember *add_host_to_hostgroup(hostgroup *, char *); /* adds a host to a hostgroup definition */ +servicegroup *add_servicegroup(char *,char *,char *,char *,char *); /* adds a servicegroup definition */ +servicesmember *add_service_to_servicegroup(servicegroup *,char *,char *); /* adds a service to a servicegroup definition */ +contactgroup *add_contactgroup(char *,char *); /* adds a contactgroup definition */ +contactsmember *add_contact_to_contactgroup(contactgroup *,char *); /* adds a contact to a contact group definition */ +command *add_command(char *,char *); /* adds a command definition */ +service *add_service(char *,char *,char *,char *,int,int,int,int,double,double,double,double,char *,int,int,int,int,int,int,int,int,char *,int,char *,int,int,double,double,int,int,int,int,int,int,int,int,int,int,char *,int,int,char *,char *,char *,char *,char *,int,int,int); /* adds a service definition */ +contactgroupsmember *add_contactgroup_to_service(service *,char *); /* adds a contact group to a service definition */ +contactsmember *add_contact_to_service(service *,char *); /* adds a contact to a host definition */ +serviceescalation *add_serviceescalation(char *,char *,int,int,double,char *,int,int,int,int); /* adds a service escalation definition */ +contactgroupsmember *add_contactgroup_to_serviceescalation(serviceescalation *,char *); /* adds a contact group to a service escalation definition */ +contactsmember *add_contact_to_serviceescalation(serviceescalation *,char *); /* adds a contact to a service escalation definition */ +customvariablesmember *add_custom_variable_to_service(service *,char *,char *); /* adds a custom variable to a service definition */ +servicedependency *add_service_dependency(char *,char *,char *,char *,int,int,int,int,int,int,int,char *); /* adds a service dependency definition */ +hostdependency *add_host_dependency(char *,char *,int,int,int,int,int,int,char *); /* adds a host dependency definition */ +hostescalation *add_hostescalation(char *,int,int,double,char *,int,int,int); /* adds a host escalation definition */ +contactsmember *add_contact_to_hostescalation(hostescalation *,char *); /* adds a contact to a host escalation definition */ +contactgroupsmember *add_contactgroup_to_hostescalation(hostescalation *,char *); /* adds a contact group to a host escalation definition */ + +contactsmember *add_contact_to_object(contactsmember **,char *); /* adds a contact to an object */ +customvariablesmember *add_custom_variable_to_object(customvariablesmember **,char *,char *); /* adds a custom variable to an object */ + + +servicesmember *add_service_link_to_host(host *,service *); + + +/*** Object Skiplist Functions ****/ +int init_object_skiplists(void); +int free_object_skiplists(void); +int skiplist_compare_text(const char *val1a, const char *val1b, const char *val2a, const char *val2b); +int skiplist_compare_host(void *a, void *b); +int skiplist_compare_service(void *a, void *b); +int skiplist_compare_command(void *a, void *b); +int skiplist_compare_timeperiod(void *a, void *b); +int skiplist_compare_contact(void *a, void *b); +int skiplist_compare_contactgroup(void *a, void *b); +int skiplist_compare_hostgroup(void *a, void *b); +int skiplist_compare_servicegroup(void *a, void *b); +int skiplist_compare_hostescalation(void *a, void *b); +int skiplist_compare_serviceescalation(void *a, void *b); +int skiplist_compare_hostdependency(void *a, void *b); +int skiplist_compare_servicedependency(void *a, void *b); + +int get_host_count(void); +int get_service_count(void); + + + +/**** Object Hash Functions ****/ +int add_servicedependency_to_hashlist(servicedependency *); + + +/**** Object Search Functions ****/ +timeperiod * find_timeperiod(char *); /* finds a timeperiod object */ +host * find_host(char *); /* finds a host object */ +hostgroup * find_hostgroup(char *); /* finds a hostgroup object */ +servicegroup * find_servicegroup(char *); /* finds a servicegroup object */ +contact * find_contact(char *); /* finds a contact object */ +contactgroup * find_contactgroup(char *); /* finds a contactgroup object */ +command * find_command(char *); /* finds a command object */ +service * find_service(char *,char *); /* finds a service object */ + + +/**** Object Traversal Functions ****/ +hostescalation *get_first_hostescalation_by_host(char *, void **); +hostescalation *get_next_hostescalation_by_host(char *,void **); +serviceescalation *get_first_serviceescalation_by_service(char *,char *, void **); +serviceescalation *get_next_serviceescalation_by_service(char *,char *,void **); +hostdependency *get_first_hostdependency_by_dependent_host(char *, void **); +hostdependency *get_next_hostdependency_by_dependent_host(char *, void **); +servicedependency *get_first_servicedependency_by_dependent_service(char *,char *, void **); +servicedependency *get_next_servicedependency_by_dependent_service(char *,char *,void **); + +#ifdef NSCORE +int add_object_to_objectlist(objectlist **,void *); +int free_objectlist(objectlist **); +#endif + + +/**** Object Query Functions ****/ +int is_host_immediate_child_of_host(host *,host *); /* checks if a host is an immediate child of another host */ +int is_host_primary_immediate_child_of_host(host *,host *); /* checks if a host is an immediate child (and primary child) of another host */ +int is_host_immediate_parent_of_host(host *,host *); /* checks if a host is an immediate child of another host */ +int is_host_member_of_hostgroup(hostgroup *,host *); /* tests whether or not a host is a member of a specific hostgroup */ +int is_host_member_of_servicegroup(servicegroup *,host *); /* tests whether or not a service is a member of a specific servicegroup */ +int is_service_member_of_servicegroup(servicegroup *,service *); /* tests whether or not a service is a member of a specific servicegroup */ +int is_contact_member_of_contactgroup(contactgroup *, contact *); /* tests whether or not a contact is a member of a specific contact group */ +int is_contact_for_hostgroup(hostgroup *,contact *); /* tests whether or not a contact is a member of a specific hostgroup */ +int is_contact_for_servicegroup(servicegroup *,contact *); /* tests whether or not a contact is a member of a specific servicegroup */ +int is_contact_for_host(host *,contact *); /* tests whether or not a contact is a contact member for a specific host */ +int is_escalated_contact_for_host(host *,contact *); /* checks whether or not a contact is an escalated contact for a specific host */ +int is_contact_for_service(service *,contact *); /* tests whether or not a contact is a contact member for a specific service */ +int is_escalated_contact_for_service(service *,contact *); /* checks whether or not a contact is an escalated contact for a specific service */ +int is_host_immediate_parent_of_host(host *,host *); /* tests whether or not a host is an immediate parent of another host */ + +int number_of_immediate_child_hosts(host *); /* counts the number of immediate child hosts for a particular host */ +int number_of_total_child_hosts(host *); /* counts the number of total child hosts for a particular host */ +int number_of_immediate_parent_hosts(host *); /* counts the number of immediate parents hosts for a particular host */ +int number_of_total_parent_hosts(host *); /* counts the number of total parents hosts for a particular host */ + +#ifdef NSCORE +int check_for_circular_host_path(host *,host *); /* checks if a circular path exists for a given host */ +int check_for_circular_servicedependency_path(servicedependency *,servicedependency *,int); /* checks if a circular dependency exists for a given service */ +int check_for_circular_hostdependency_path(hostdependency *,hostdependency *,int); /* checks if a circular dependency exists for a given host */ +#endif + + +/**** Object Cleanup Functions ****/ +int free_object_data(void); /* frees all allocated memory for the object definitions */ + + + + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/include/pnp.h b/include/pnp.h new file mode 100644 index 0000000..a37da06 --- /dev/null +++ b/include/pnp.h @@ -0,0 +1,126 @@ +/* #include "../include/global.h" */ + +/************************************* + * General Header Files + *************************************/ + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYSLOG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef HAVE_SIGNAL_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_DIRENT_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_PTHREAD_H +#include +#endif + +#ifdef HAVE_GETOPT_H +#include +#endif + +#ifdef HAVE_GRP_H +#include +#endif + +#ifdef HAVE_PWD_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_LIMITS_H +#include +#endif + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +/************************************* + Default defines + **************************************/ +extern int do_log(char*); + + +#define LOG(level, msg) (loglevel >= level || loglevel == -1) ? (do_log(msg)) : (0) + +#define TRUE 1 +#define FALSE 0 + +#define OK 0 +#define ERROR -2 + +#define MAX_FILENAME_LENGTH 256 +#define MAX_VARIABLE_LENGTH 256 +#define MAX_VALUE_LENGTH 256 +#define MAX_COMMANDLINE_LENGTH 512 + +#define MAX_BUFFER_SIZE 1024 +#define MAX_LOGMESSAGE_SIZE 768 + +#define CONFIG_OPT_COUNT 15 + +#define CONFIG_OPT_LOGTYPE 0 +#define CONFIG_OPT_LOGFILE 1 +#define CONFIG_OPT_LOGFILESIZE 2 +#define CONFIG_OPT_LOGLEVEL 3 +#define CONFIG_OPT_SCANDIR 4 +#define CONFIG_OPT_RUNCMD 5 +#define CONFIG_OPT_RUNCMD_ARG 6 +#define CONFIG_OPT_MAXTHREADS 7 +#define CONFIG_OPT_USER 8 +#define CONFIG_OPT_GROUP 9 +#define CONFIG_OPT_PIDFILE 10 +#define CONFIG_OPT_USELOAD 11 +#define CONFIG_OPT_LOAD 12 +#define CONFIG_OPT_SLEEPTIME 13 +#define CONFIG_OPT_IDENTMYSELF 14 + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..4d4a951 --- /dev/null +++ b/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..b103bc8 --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,305 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +LOGDIR=@localstatedir@ +CFGDIR=@sysconfdir@ +BINDIR=@bindir@ +CGIDIR=@sbindir@ +LIBDIR=@libdir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +DATAROOTDIR=@datarootdir@ + +CP=@CP@ + +all html: + +clean: + +distclean: clean + -rm -f Makefile + +devclean: distclean + +install: + + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/controllers + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/helpers + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Image + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Session + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/config + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/core + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8 + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/views + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/views/pagination + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR)/kohana/system/fonts + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/controllers/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/controllers/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/controllers/template.php $(DESTDIR)$(LIBDIR)/kohana/system/controllers/template.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/de_DE/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/de_DE/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/nl_NL/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/nl_NL/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/es_ES/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/es_ES/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/ru_RU/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/ru_RU/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/en_US/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/en_US/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/fr_FR/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/fr_FR/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/validation.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/core.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/core.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/orm.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/orm.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/image.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/session.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/database.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/event.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/errors.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/errors.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/i18n/it_IT/swift.php $(DESTDIR)$(LIBDIR)/kohana/system/i18n/it_IT/swift.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/remote.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/remote.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/url.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/url.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/feed.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/feed.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/expires.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/expires.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/text.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/text.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/email.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/email.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/download.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/download.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/format.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/format.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/form.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/form.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/arr.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/arr.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/html.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/html.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/valid.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/valid.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/date.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/date.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/file.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/file.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/request.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/request.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/cookie.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/cookie.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/security.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/security.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/num.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/num.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/helpers/inflector.php $(DESTDIR)$(LIBDIR)/kohana/system/helpers/inflector.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/ORM_Tree.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/ORM_Tree.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Encrypt.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Encrypt.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Database_Expression.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Database_Expression.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Event_Observer.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Event_Observer.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Event_Subject.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Event_Subject.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Cache.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Session.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Database/Mssql.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database/Mssql.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Database/Pdosqlite.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database/Pdosqlite.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Database/Mysqli.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database/Mysqli.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Database/Pgsql.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database/Pgsql.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Database/Mysql.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database/Mysql.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha/Alpha.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha/Alpha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha/Math.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha/Math.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha/Word.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha/Word.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha/Riddle.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha/Riddle.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha/Basic.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha/Basic.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha/Black.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha/Black.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Session.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Image.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache/Eaccelerator.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache/Eaccelerator.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache/Apc.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache/Apc.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache/Memcache.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache/Memcache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache/Xcache.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache/Xcache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache/File.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache/File.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Cache/Sqlite.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Cache/Sqlite.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Image/GraphicsMagick.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Image/GraphicsMagick.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Image/GD.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Image/GD.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Image/ImageMagick.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Image/ImageMagick.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Session/Cookie.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Session/Cookie.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Session/Cache.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Session/Cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Session/Database.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Session/Database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/drivers/Database.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/drivers/Database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Image.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Validation.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Validation.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/ORM_Versioned.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/ORM_Versioned.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Controller.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Controller.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Model.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Model.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/View.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/View.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Router.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Router.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/ORM_Iterator.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/ORM_Iterator.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Profiler_Table.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Profiler_Table.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/URI.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/URI.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/ORM.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/ORM.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Calendar_Event.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Calendar_Event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Tagcloud.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Tagcloud.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Input.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Input.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/libraries/Database.php $(DESTDIR)$(LIBDIR)/kohana/system/libraries/Database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/locale.php $(DESTDIR)$(LIBDIR)/kohana/system/config/locale.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/routes.php $(DESTDIR)$(LIBDIR)/kohana/system/config/routes.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/pagination.php $(DESTDIR)$(LIBDIR)/kohana/system/config/pagination.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/sql_types.php $(DESTDIR)$(LIBDIR)/kohana/system/config/sql_types.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/captcha.php $(DESTDIR)$(LIBDIR)/kohana/system/config/captcha.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/email.php $(DESTDIR)$(LIBDIR)/kohana/system/config/email.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/image.php $(DESTDIR)$(LIBDIR)/kohana/system/config/image.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/cache_sqlite.php $(DESTDIR)$(LIBDIR)/kohana/system/config/cache_sqlite.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/cache_memcache.php $(DESTDIR)$(LIBDIR)/kohana/system/config/cache_memcache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/session.php $(DESTDIR)$(LIBDIR)/kohana/system/config/session.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/database.php $(DESTDIR)$(LIBDIR)/kohana/system/config/database.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/credit_cards.php $(DESTDIR)$(LIBDIR)/kohana/system/config/credit_cards.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/http.php $(DESTDIR)$(LIBDIR)/kohana/system/config/http.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/mimes.php $(DESTDIR)$(LIBDIR)/kohana/system/config/mimes.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/config/profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/view.php $(DESTDIR)$(LIBDIR)/kohana/system/config/view.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/cache.php $(DESTDIR)$(LIBDIR)/kohana/system/config/cache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/encryption.php $(DESTDIR)$(LIBDIR)/kohana/system/config/encryption.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/upload.php $(DESTDIR)$(LIBDIR)/kohana/system/config/upload.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/cookie.php $(DESTDIR)$(LIBDIR)/kohana/system/config/cookie.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/user_agents.php $(DESTDIR)$(LIBDIR)/kohana/system/config/user_agents.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/inflector.php $(DESTDIR)$(LIBDIR)/kohana/system/config/inflector.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/config/cache_xcache.php $(DESTDIR)$(LIBDIR)/kohana/system/config/cache_xcache.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/Event.php $(DESTDIR)$(LIBDIR)/kohana/system/core/Event.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/transliterate_to_ascii.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/transliterate_to_ascii.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/ucfirst.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/ucfirst.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/ord.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/ord.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strrpos.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strrpos.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strtolower.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strtolower.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/substr.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/substr.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/str_pad.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/str_pad.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strcspn.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strcspn.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/trim.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/trim.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/rtrim.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/rtrim.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strcasecmp.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strcasecmp.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strtoupper.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strtoupper.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/str_split.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/str_split.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strpos.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strpos.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/stristr.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/stristr.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/ucwords.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/ucwords.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/str_ireplace.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/str_ireplace.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strlen.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strlen.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/to_unicode.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/to_unicode.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/substr_replace.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/substr_replace.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/from_unicode.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/from_unicode.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strrev.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strrev.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/strspn.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/strspn.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8/ltrim.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8/ltrim.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/Benchmark.php $(DESTDIR)$(LIBDIR)/kohana/system/core/Benchmark.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/Bootstrap.php $(DESTDIR)$(LIBDIR)/kohana/system/core/Bootstrap.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/Kohana.php $(DESTDIR)$(LIBDIR)/kohana/system/core/Kohana.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/core/utf8.php $(DESTDIR)$(LIBDIR)/kohana/system/core/utf8.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_profiler_table.php $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_profiler_table.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana/template.php $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana/template.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_error_page.php $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_error_page.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_calendar.php $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_calendar.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/pagination/digg.php $(DESTDIR)$(LIBDIR)/kohana/system/views/pagination/digg.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/pagination/punbb.php $(DESTDIR)$(LIBDIR)/kohana/system/views/pagination/punbb.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/pagination/extended.php $(DESTDIR)$(LIBDIR)/kohana/system/views/pagination/extended.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/pagination/classic.php $(DESTDIR)$(LIBDIR)/kohana/system/views/pagination/classic.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_profiler_table.css $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_profiler_table.css + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_profiler.php $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_profiler.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_error_disabled.php $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_error_disabled.php + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/views/kohana_errors.css $(DESTDIR)$(LIBDIR)/kohana/system/views/kohana_errors.css + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/fonts/LICENSE $(DESTDIR)$(LIBDIR)/kohana/system/fonts/LICENSE + $(INSTALL) -m 644 $(INSTALL_OPTS) kohana/system/fonts/DejaVuSerif.ttf $(DESTDIR)$(LIBDIR)/kohana/system/fonts/DejaVuSerif.ttf diff --git a/lib/kohana/system/config/cache.php b/lib/kohana/system/config/cache.php new file mode 100644 index 0000000..ccd3da4 --- /dev/null +++ b/lib/kohana/system/config/cache.php @@ -0,0 +1,32 @@ + File cache is fast and reliable, but requires many filesystem lookups. + * > Database cache can be used to cache items remotely, but is slower. + * > Memcache is very high performance, but prevents cache tags from being used. + * + * params - Driver parameters, specific to each driver. + * + * lifetime - Default lifetime of caches in seconds. By default caches are stored for + * thirty minutes. Specific lifetime can also be set when creating a new cache. + * Setting this to 0 will never automatically delete caches. + * + * requests - Average number of cache requests that will processed before all expired + * caches are deleted. This is commonly referred to as "garbage collection". + * Setting this to 0 or a negative number will disable automatic garbage collection. + */ +$config['default'] = array +( + 'driver' => 'file', + 'params' => APPPATH.'cache', + 'lifetime' => 1800, + 'requests' => 1000 +); diff --git a/lib/kohana/system/config/cache_memcache.php b/lib/kohana/system/config/cache_memcache.php new file mode 100644 index 0000000..43d8f20 --- /dev/null +++ b/lib/kohana/system/config/cache_memcache.php @@ -0,0 +1,20 @@ + '127.0.0.1', + 'port' => 11211, + 'persistent' => FALSE, + ) +); + +/** + * Enable cache data compression. + */ +$config['compression'] = FALSE; diff --git a/lib/kohana/system/config/cache_sqlite.php b/lib/kohana/system/config/cache_sqlite.php new file mode 100644 index 0000000..818b893 --- /dev/null +++ b/lib/kohana/system/config/cache_sqlite.php @@ -0,0 +1,10 @@ + 'basic', + 'width' => 150, + 'height' => 50, + 'complexity' => 4, + 'background' => '', + 'fontpath' => SYSPATH.'fonts/', + 'fonts' => array('DejaVuSerif.ttf'), + 'promote' => FALSE, +); \ No newline at end of file diff --git a/lib/kohana/system/config/cookie.php b/lib/kohana/system/config/cookie.php new file mode 100644 index 0000000..b6ddfe4 --- /dev/null +++ b/lib/kohana/system/config/cookie.php @@ -0,0 +1,32 @@ + array + ( + 'length' => '13,14,15,16,17,18,19', + 'prefix' => '', + 'luhn' => TRUE + ), + 'american express' => array + ( + 'length' => '15', + 'prefix' => '3[47]', + 'luhn' => TRUE + ), + 'diners club' => array + ( + 'length' => '14,16', + 'prefix' => '36|55|30[0-5]', + 'luhn' => TRUE + ), + 'discover' => array + ( + 'length' => '16', + 'prefix' => '6(?:5|011)', + 'luhn' => TRUE, + ), + 'jcb' => array + ( + 'length' => '15,16', + 'prefix' => '3|1800|2131', + 'luhn' => TRUE + ), + 'maestro' => array + ( + 'length' => '16,18', + 'prefix' => '50(?:20|38)|6(?:304|759)', + 'luhn' => TRUE + ), + 'mastercard' => array + ( + 'length' => '16', + 'prefix' => '5[1-5]', + 'luhn' => TRUE + ), + 'visa' => array + ( + 'length' => '13,16', + 'prefix' => '4', + 'luhn' => TRUE + ), +); \ No newline at end of file diff --git a/lib/kohana/system/config/database.php b/lib/kohana/system/config/database.php new file mode 100644 index 0000000..6519156 --- /dev/null +++ b/lib/kohana/system/config/database.php @@ -0,0 +1,45 @@ + 'mysql://dbuser:secret@localhost/kohana' + * character_set - Database character set + * table_prefix - Database table prefix + * object - Enable or disable object results + * cache - Enable or disable query caching + * escape - Enable automatic query builder escaping + */ +$config['default'] = array +( + 'benchmark' => TRUE, + 'persistent' => FALSE, + 'connection' => array + ( + 'type' => 'mysql', + 'user' => 'dbuser', + 'pass' => 'p@ssw0rd', + 'host' => 'localhost', + 'port' => FALSE, + 'socket' => FALSE, + 'database' => 'kohana' + ), + 'character_set' => 'utf8', + 'table_prefix' => '', + 'object' => TRUE, + 'cache' => FALSE, + 'escape' => TRUE +); \ No newline at end of file diff --git a/lib/kohana/system/config/email.php b/lib/kohana/system/config/email.php new file mode 100644 index 0000000..c768367 --- /dev/null +++ b/lib/kohana/system/config/email.php @@ -0,0 +1,22 @@ + 'K0H@NA+PHP_7hE-SW!FtFraM3w0R|<', + 'mode' => MCRYPT_MODE_NOFB, + 'cipher' => MCRYPT_RIJNDAEL_128 +); diff --git a/lib/kohana/system/config/http.php b/lib/kohana/system/config/http.php new file mode 100644 index 0000000..3c4a86a --- /dev/null +++ b/lib/kohana/system/config/http.php @@ -0,0 +1,19 @@ + 'children', + 'clothes' => 'clothing', + 'man' => 'men', + 'movie' => 'movies', + 'person' => 'people', + 'woman' => 'women', + 'mouse' => 'mice', + 'goose' => 'geese', + 'ox' => 'oxen', + 'leaf' => 'leaves', + 'course' => 'courses', + 'size' => 'sizes', +); diff --git a/lib/kohana/system/config/locale.php b/lib/kohana/system/config/locale.php new file mode 100644 index 0000000..3a26882 --- /dev/null +++ b/lib/kohana/system/config/locale.php @@ -0,0 +1,16 @@ + array('text/h323'), + '7z' => array('application/x-7z-compressed'), + 'abw' => array('application/x-abiword'), + 'acx' => array('application/internet-property-stream'), + 'ai' => array('application/postscript'), + 'aif' => array('audio/x-aiff'), + 'aifc' => array('audio/x-aiff'), + 'aiff' => array('audio/x-aiff'), + 'asf' => array('video/x-ms-asf'), + 'asr' => array('video/x-ms-asf'), + 'asx' => array('video/x-ms-asf'), + 'atom' => array('application/atom+xml'), + 'avi' => array('video/avi', 'video/msvideo', 'video/x-msvideo'), + 'bin' => array('application/octet-stream','application/macbinary'), + 'bmp' => array('image/bmp'), + 'c' => array('text/x-csrc'), + 'c++' => array('text/x-c++src'), + 'cab' => array('application/x-cab'), + 'cc' => array('text/x-c++src'), + 'cda' => array('application/x-cdf'), + 'class' => array('application/octet-stream'), + 'cpp' => array('text/x-c++src'), + 'cpt' => array('application/mac-compactpro'), + 'csh' => array('text/x-csh'), + 'css' => array('text/css'), + 'csv' => array('text/x-comma-separated-values', 'application/vnd.ms-excel', 'text/comma-separated-values', 'text/csv'), + 'dbk' => array('application/docbook+xml'), + 'dcr' => array('application/x-director'), + 'deb' => array('application/x-debian-package'), + 'diff' => array('text/x-diff'), + 'dir' => array('application/x-director'), + 'divx' => array('video/divx'), + 'dll' => array('application/octet-stream', 'application/x-msdos-program'), + 'dmg' => array('application/x-apple-diskimage'), + 'dms' => array('application/octet-stream'), + 'doc' => array('application/msword'), + 'dvi' => array('application/x-dvi'), + 'dxr' => array('application/x-director'), + 'eml' => array('message/rfc822'), + 'eps' => array('application/postscript'), + 'evy' => array('application/envoy'), + 'exe' => array('application/x-msdos-program', 'application/octet-stream'), + 'fla' => array('application/octet-stream'), + 'flac' => array('application/x-flac'), + 'flc' => array('video/flc'), + 'fli' => array('video/fli'), + 'flv' => array('video/x-flv'), + 'gif' => array('image/gif'), + 'gtar' => array('application/x-gtar'), + 'gz' => array('application/x-gzip'), + 'h' => array('text/x-chdr'), + 'h++' => array('text/x-c++hdr'), + 'hh' => array('text/x-c++hdr'), + 'hpp' => array('text/x-c++hdr'), + 'hqx' => array('application/mac-binhex40'), + 'hs' => array('text/x-haskell'), + 'htm' => array('text/html'), + 'html' => array('text/html'), + 'ico' => array('image/x-icon'), + 'ics' => array('text/calendar'), + 'iii' => array('application/x-iphone'), + 'ins' => array('application/x-internet-signup'), + 'iso' => array('application/x-iso9660-image'), + 'isp' => array('application/x-internet-signup'), + 'jar' => array('application/java-archive'), + 'java' => array('application/x-java-applet'), + 'jpe' => array('image/jpeg', 'image/pjpeg'), + 'jpeg' => array('image/jpeg', 'image/pjpeg'), + 'jpg' => array('image/jpeg', 'image/pjpeg'), + 'js' => array('application/x-javascript'), + 'json' => array('application/json'), + 'latex' => array('application/x-latex'), + 'lha' => array('application/octet-stream'), + 'log' => array('text/plain', 'text/x-log'), + 'lzh' => array('application/octet-stream'), + 'm4a' => array('audio/mpeg'), + 'm4p' => array('video/mp4v-es'), + 'm4v' => array('video/mp4'), + 'man' => array('application/x-troff-man'), + 'mdb' => array('application/x-msaccess'), + 'midi' => array('audio/midi'), + 'mid' => array('audio/midi'), + 'mif' => array('application/vnd.mif'), + 'mka' => array('audio/x-matroska'), + 'mkv' => array('video/x-matroska'), + 'mov' => array('video/quicktime'), + 'movie' => array('video/x-sgi-movie'), + 'mp2' => array('audio/mpeg'), + 'mp3' => array('audio/mpeg'), + 'mp4' => array('application/mp4','audio/mp4','video/mp4'), + 'mpa' => array('video/mpeg'), + 'mpe' => array('video/mpeg'), + 'mpeg' => array('video/mpeg'), + 'mpg' => array('video/mpeg'), + 'mpg4' => array('video/mp4'), + 'mpga' => array('audio/mpeg'), + 'mpp' => array('application/vnd.ms-project'), + 'mpv' => array('video/x-matroska'), + 'mpv2' => array('video/mpeg'), + 'ms' => array('application/x-troff-ms'), + 'msg' => array('application/msoutlook','application/x-msg'), + 'msi' => array('application/x-msi'), + 'nws' => array('message/rfc822'), + 'oda' => array('application/oda'), + 'odb' => array('application/vnd.oasis.opendocument.database'), + 'odc' => array('application/vnd.oasis.opendocument.chart'), + 'odf' => array('application/vnd.oasis.opendocument.forumla'), + 'odg' => array('application/vnd.oasis.opendocument.graphics'), + 'odi' => array('application/vnd.oasis.opendocument.image'), + 'odm' => array('application/vnd.oasis.opendocument.text-master'), + 'odp' => array('application/vnd.oasis.opendocument.presentation'), + 'ods' => array('application/vnd.oasis.opendocument.spreadsheet'), + 'odt' => array('application/vnd.oasis.opendocument.text'), + 'oga' => array('audio/ogg'), + 'ogg' => array('application/ogg'), + 'ogv' => array('video/ogg'), + 'otg' => array('application/vnd.oasis.opendocument.graphics-template'), + 'oth' => array('application/vnd.oasis.opendocument.web'), + 'otp' => array('application/vnd.oasis.opendocument.presentation-template'), + 'ots' => array('application/vnd.oasis.opendocument.spreadsheet-template'), + 'ott' => array('application/vnd.oasis.opendocument.template'), + 'p' => array('text/x-pascal'), + 'pas' => array('text/x-pascal'), + 'patch' => array('text/x-diff'), + 'pbm' => array('image/x-portable-bitmap'), + 'pdf' => array('application/pdf', 'application/x-download'), + 'php' => array('application/x-httpd-php'), + 'php3' => array('application/x-httpd-php'), + 'php4' => array('application/x-httpd-php'), + 'php5' => array('application/x-httpd-php'), + 'phps' => array('application/x-httpd-php-source'), + 'phtml' => array('application/x-httpd-php'), + 'pl' => array('text/x-perl'), + 'pm' => array('text/x-perl'), + 'png' => array('image/png', 'image/x-png'), + 'po' => array('text/x-gettext-translation'), + 'pot' => array('application/vnd.ms-powerpoint'), + 'pps' => array('application/vnd.ms-powerpoint'), + 'ppt' => array('application/powerpoint'), + 'ps' => array('application/postscript'), + 'psd' => array('application/x-photoshop', 'image/x-photoshop'), + 'pub' => array('application/x-mspublisher'), + 'py' => array('text/x-python'), + 'qt' => array('video/quicktime'), + 'ra' => array('audio/x-realaudio'), + 'ram' => array('audio/x-realaudio', 'audio/x-pn-realaudio'), + 'rar' => array('application/rar'), + 'rgb' => array('image/x-rgb'), + 'rm' => array('audio/x-pn-realaudio'), + 'rpm' => array('audio/x-pn-realaudio-plugin', 'application/x-redhat-package-manager'), + 'rss' => array('application/rss+xml'), + 'rtf' => array('text/rtf'), + 'rtx' => array('text/richtext'), + 'rv' => array('video/vnd.rn-realvideo'), + 'sea' => array('application/octet-stream'), + 'sh' => array('text/x-sh'), + 'shtml' => array('text/html'), + 'sit' => array('application/x-stuffit'), + 'smi' => array('application/smil'), + 'smil' => array('application/smil'), + 'so' => array('application/octet-stream'), + 'src' => array('application/x-wais-source'), + 'svg' => array('image/svg+xml'), + 'swf' => array('application/x-shockwave-flash'), + 't' => array('application/x-troff'), + 'tar' => array('application/x-tar'), + 'tcl' => array('text/x-tcl'), + 'tex' => array('application/x-tex'), + 'text' => array('text/plain'), + 'texti' => array('application/x-texinfo'), + 'textinfo' => array('application/x-texinfo'), + 'tgz' => array('application/x-tar'), + 'tif' => array('image/tiff'), + 'tiff' => array('image/tiff'), + 'torrent' => array('application/x-bittorrent'), + 'tr' => array('application/x-troff'), + 'tsv' => array('text/tab-separated-values'), + 'txt' => array('text/plain'), + 'wav' => array('audio/x-wav'), + 'wax' => array('audio/x-ms-wax'), + 'wbxml' => array('application/wbxml'), + 'wm' => array('video/x-ms-wm'), + 'wma' => array('audio/x-ms-wma'), + 'wmd' => array('application/x-ms-wmd'), + 'wmlc' => array('application/wmlc'), + 'wmv' => array('video/x-ms-wmv', 'application/octet-stream'), + 'wmx' => array('video/x-ms-wmx'), + 'wmz' => array('application/x-ms-wmz'), + 'word' => array('application/msword', 'application/octet-stream'), + 'wp5' => array('application/wordperfect5.1'), + 'wpd' => array('application/vnd.wordperfect'), + 'wvx' => array('video/x-ms-wvx'), + 'xbm' => array('image/x-xbitmap'), + 'xcf' => array('image/xcf'), + 'xhtml' => array('application/xhtml+xml'), + 'xht' => array('application/xhtml+xml'), + 'xl' => array('application/excel', 'application/vnd.ms-excel'), + 'xla' => array('application/excel', 'application/vnd.ms-excel'), + 'xlc' => array('application/excel', 'application/vnd.ms-excel'), + 'xlm' => array('application/excel', 'application/vnd.ms-excel'), + 'xls' => array('application/excel', 'application/vnd.ms-excel'), + 'xlt' => array('application/excel', 'application/vnd.ms-excel'), + 'xml' => array('text/xml'), + 'xof' => array('x-world/x-vrml'), + 'xpm' => array('image/x-xpixmap'), + 'xsl' => array('text/xml'), + 'xvid' => array('video/x-xvid'), + 'xwd' => array('image/x-xwindowdump'), + 'z' => array('application/x-compress'), + 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed') +); diff --git a/lib/kohana/system/config/pagination.php b/lib/kohana/system/config/pagination.php new file mode 100644 index 0000000..808fc31 --- /dev/null +++ b/lib/kohana/system/config/pagination.php @@ -0,0 +1,25 @@ + 'pagination', + 'style' => 'classic', + 'uri_segment' => 3, + 'query_string' => '', + 'items_per_page' => 20, + 'auto_hide' => FALSE, +); diff --git a/lib/kohana/system/config/profiler.php b/lib/kohana/system/config/profiler.php new file mode 100644 index 0000000..98ab5a4 --- /dev/null +++ b/lib/kohana/system/config/profiler.php @@ -0,0 +1,8 @@ + array('type' => 'int', 'max' => 127), + 'smallint' => array('type' => 'int', 'max' => 32767), + 'mediumint' => array('type' => 'int', 'max' => 8388607), + 'int' => array('type' => 'int', 'max' => 2147483647), + 'integer' => array('type' => 'int', 'max' => 2147483647), + 'bigint' => array('type' => 'int', 'max' => 9223372036854775807), + 'float' => array('type' => 'float'), + 'float unsigned' => array('type' => 'float', 'min' => 0), + 'boolean' => array('type' => 'boolean'), + 'time' => array('type' => 'string', 'format' => '00:00:00'), + 'time with time zone' => array('type' => 'string'), + 'date' => array('type' => 'string', 'format' => '0000-00-00'), + 'year' => array('type' => 'string', 'format' => '0000'), + 'datetime' => array('type' => 'string', 'format' => '0000-00-00 00:00:00'), + 'timestamp with time zone' => array('type' => 'string'), + 'char' => array('type' => 'string', 'exact' => TRUE), + 'binary' => array('type' => 'string', 'binary' => TRUE, 'exact' => TRUE), + 'varchar' => array('type' => 'string'), + 'varbinary' => array('type' => 'string', 'binary' => TRUE), + 'blob' => array('type' => 'string', 'binary' => TRUE), + 'text' => array('type' => 'string') +); + +// DOUBLE +$config['double'] = $config['double precision'] = $config['decimal'] = $config['real'] = $config['numeric'] = $config['float']; +$config['double unsigned'] = $config['float unsigned']; + +// BIT +$config['bit'] = $config['boolean']; + +// TIMESTAMP +$config['timestamp'] = $config['timestamp without time zone'] = $config['datetime']; + +// ENUM +$config['enum'] = $config['set'] = $config['varchar']; + +// TEXT +$config['tinytext'] = $config['mediumtext'] = $config['longtext'] = $config['text']; + +// BLOB +$config['tsvector'] = $config['tinyblob'] = $config['mediumblob'] = $config['longblob'] = $config['clob'] = $config['bytea'] = $config['blob']; + +// CHARACTER +$config['character'] = $config['char']; +$config['character varying'] = $config['varchar']; + +// TIME +$config['time without time zone'] = $config['time']; diff --git a/lib/kohana/system/config/upload.php b/lib/kohana/system/config/upload.php new file mode 100644 index 0000000..df26a2d --- /dev/null +++ b/lib/kohana/system/config/upload.php @@ -0,0 +1,17 @@ + 'Windows Vista', + 'windows nt 5.2' => 'Windows 2003', + 'windows nt 5.0' => 'Windows 2000', + 'windows nt 5.1' => 'Windows XP', + 'windows nt 4.0' => 'Windows NT', + 'winnt4.0' => 'Windows NT', + 'winnt 4.0' => 'Windows NT', + 'winnt' => 'Windows NT', + 'windows 98' => 'Windows 98', + 'win98' => 'Windows 98', + 'windows 95' => 'Windows 95', + 'win95' => 'Windows 95', + 'windows' => 'Unknown Windows OS', + 'os x' => 'Mac OS X', + 'intel mac' => 'Intel Mac', + 'ppc mac' => 'PowerPC Mac', + 'powerpc' => 'PowerPC', + 'ppc' => 'PowerPC', + 'cygwin' => 'Cygwin', + 'linux' => 'Linux', + 'debian' => 'Debian', + 'openvms' => 'OpenVMS', + 'sunos' => 'Sun Solaris', + 'amiga' => 'Amiga', + 'beos' => 'BeOS', + 'apachebench' => 'ApacheBench', + 'freebsd' => 'FreeBSD', + 'netbsd' => 'NetBSD', + 'bsdi' => 'BSDi', + 'openbsd' => 'OpenBSD', + 'os/2' => 'OS/2', + 'warp' => 'OS/2', + 'aix' => 'AIX', + 'irix' => 'Irix', + 'osf' => 'DEC OSF', + 'hp-ux' => 'HP-UX', + 'hurd' => 'GNU/Hurd', + 'unix' => 'Unknown Unix OS', +); + +// The order of this array should NOT be changed. Many browsers return +// multiple browser types so we want to identify the sub-type first. +$config['browser'] = array +( + 'Opera' => 'Opera', + 'MSIE' => 'Internet Explorer', + 'Internet Explorer' => 'Internet Explorer', + 'Shiira' => 'Shiira', + 'Firefox' => 'Firefox', + 'Chimera' => 'Chimera', + 'Phoenix' => 'Phoenix', + 'Firebird' => 'Firebird', + 'Camino' => 'Camino', + 'Netscape' => 'Netscape', + 'OmniWeb' => 'OmniWeb', + 'Chrome' => 'Chrome', + 'Safari' => 'Safari', + 'Konqueror' => 'Konqueror', + 'Epiphany' => 'Epiphany', + 'Galeon' => 'Galeon', + 'Mozilla' => 'Mozilla', + 'icab' => 'iCab', + 'lynx' => 'Lynx', + 'links' => 'Links', + 'hotjava' => 'HotJava', + 'amaya' => 'Amaya', + 'IBrowse' => 'IBrowse', +); + +$config['mobile'] = array +( + 'mobileexplorer' => 'Mobile Explorer', + 'openwave' => 'Open Wave', + 'opera mini' => 'Opera Mini', + 'operamini' => 'Opera Mini', + 'elaine' => 'Palm', + 'palmsource' => 'Palm', + 'digital paths' => 'Palm', + 'avantgo' => 'Avantgo', + 'xiino' => 'Xiino', + 'palmscape' => 'Palmscape', + 'nokia' => 'Nokia', + 'ericsson' => 'Ericsson', + 'blackBerry' => 'BlackBerry', + 'motorola' => 'Motorola', + 'iphone' => 'iPhone', + 'android' => 'Android', +); + +// There are hundreds of bots but these are the most common. +$config['robot'] = array +( + 'googlebot' => 'Googlebot', + 'msnbot' => 'MSNBot', + 'slurp' => 'Inktomi Slurp', + 'yahoo' => 'Yahoo', + 'askjeeves' => 'AskJeeves', + 'fastcrawler' => 'FastCrawler', + 'infoseek' => 'InfoSeek Robot 1.0', + 'lycos' => 'Lycos', +); \ No newline at end of file diff --git a/lib/kohana/system/config/view.php b/lib/kohana/system/config/view.php new file mode 100644 index 0000000..6bed22e --- /dev/null +++ b/lib/kohana/system/config/view.php @@ -0,0 +1,17 @@ +" /> + * + * $Id: captcha.php 3769 2008-12-15 00:48:56Z zombor $ + * + * @package Captcha + * @author Kohana Team + * @copyright (c) 2007-2008 Kohana Team + * @license http://kohanaphp.com/license.html + */ +class Captcha_Controller extends Controller { + + public function __call($method, $args) + { + // Output the Captcha challenge resource (no html) + // Pull the config group name from the URL + Captcha::factory($this->uri->segment(2))->render(FALSE); + } + +} // End Captcha_Controller \ No newline at end of file diff --git a/lib/kohana/system/controllers/template.php b/lib/kohana/system/controllers/template.php new file mode 100644 index 0000000..34d1a22 --- /dev/null +++ b/lib/kohana/system/controllers/template.php @@ -0,0 +1,54 @@ +template = new View($this->template); + + if ($this->auto_render == TRUE) + { + // Render the template immediately after the controller method + Event::add('system.post_controller', array($this, '_render')); + } + } + + /** + * Render the loaded template. + */ + public function _render() + { + if ($this->auto_render == TRUE) + { + // Render the template when the class is destroyed + $this->template->render(TRUE); + } + } + +} // End Template_Controller \ No newline at end of file diff --git a/lib/kohana/system/core/Benchmark.php b/lib/kohana/system/core/Benchmark.php new file mode 100644 index 0000000..ce230f1 --- /dev/null +++ b/lib/kohana/system/core/Benchmark.php @@ -0,0 +1,125 @@ + microtime(TRUE), + 'stop' => FALSE, + 'memory_start' => self::memory_usage(), + 'memory_stop' => FALSE + ); + + array_unshift(self::$marks[$name], $mark); + } + + /** + * Set a benchmark stop point. + * + * @param string benchmark name + * @return void + */ + public static function stop($name) + { + if (isset(self::$marks[$name]) AND self::$marks[$name][0]['stop'] === FALSE) + { + self::$marks[$name][0]['stop'] = microtime(TRUE); + self::$marks[$name][0]['memory_stop'] = self::memory_usage(); + } + } + + /** + * Get the elapsed time between a start and stop. + * + * @param string benchmark name, TRUE for all + * @param integer number of decimal places to count to + * @return array + */ + public static function get($name, $decimals = 4) + { + if ($name === TRUE) + { + $times = array(); + $names = array_keys(self::$marks); + + foreach ($names as $name) + { + // Get each mark recursively + $times[$name] = self::get($name, $decimals); + } + + // Return the array + return $times; + } + + if ( ! isset(self::$marks[$name])) + return FALSE; + + if (self::$marks[$name][0]['stop'] === FALSE) + { + // Stop the benchmark to prevent mis-matched results + self::stop($name); + } + + // Return a string version of the time between the start and stop points + // Properly reading a float requires using number_format or sprintf + $time = $memory = 0; + for ($i = 0; $i < count(self::$marks[$name]); $i++) + { + $time += self::$marks[$name][$i]['stop'] - self::$marks[$name][$i]['start']; + $memory += self::$marks[$name][$i]['memory_stop'] - self::$marks[$name][$i]['memory_start']; + } + + return array + ( + 'time' => number_format($time, $decimals), + 'memory' => $memory, + 'count' => count(self::$marks[$name]) + ); + } + + /** + * Returns the current memory usage. This is only possible if the + * memory_get_usage function is supported in PHP. + * + * @return integer + */ + private static function memory_usage() + { + static $func; + + if ($func === NULL) + { + // Test if memory usage can be seen + $func = function_exists('memory_get_usage'); + } + + return $func ? memory_get_usage() : 0; + } + +} // End Benchmark diff --git a/lib/kohana/system/core/Bootstrap.php b/lib/kohana/system/core/Bootstrap.php new file mode 100644 index 0000000..1334190 --- /dev/null +++ b/lib/kohana/system/core/Bootstrap.php @@ -0,0 +1,58 @@ + $event_callback) + { + if ($callback === $event_callback) + { + unset(self::$events[$name][$i]); + } + } + } + } + + /** + * Execute all of the callbacks attached to an event. + * + * @param string event name + * @param array data can be processed as Event::$data by the callbacks + * @return void + */ + public static function run($name, & $data = NULL) + { + if ( ! empty(self::$events[$name])) + { + // So callbacks can access Event::$data + self::$data =& $data; + $callbacks = self::get($name); + + foreach ($callbacks as $callback) + { + call_user_func($callback); + } + + // Do this to prevent data from getting 'stuck' + $clear_data = ''; + self::$data =& $clear_data; + } + + // The event has been run! + self::$has_run[$name] = $name; + } + + /** + * Check if a given event has been run. + * + * @param string event name + * @return boolean + */ + public static function has_run($name) + { + return isset(self::$has_run[$name]); + } + +} // End Event \ No newline at end of file diff --git a/lib/kohana/system/core/Kohana.php b/lib/kohana/system/core/Kohana.php new file mode 100644 index 0000000..c79e30b --- /dev/null +++ b/lib/kohana/system/core/Kohana.php @@ -0,0 +1,1790 @@ + 1, + 'alert' => 2, + 'info' => 3, + 'debug' => 4, + ); + + // Internal caches and write status + private static $internal_cache = array(); + private static $write_cache; + private static $internal_cache_path; + private static $internal_cache_key; + private static $internal_cache_encrypt; + + /** + * Sets up the PHP environment. Adds error/exception handling, output + * buffering, and adds an auto-loading method for loading classes. + * + * This method is run immediately when this file is loaded, and is + * benchmarked as environment_setup. + * + * For security, this function also destroys the $_REQUEST global variable. + * Using the proper global (GET, POST, COOKIE, etc) is inherently more secure. + * The recommended way to fetch a global variable is using the Input library. + * @see http://www.php.net/globals + * + * @return void + */ + public static function setup() + { + static $run; + + // This function can only be run once + if ($run === TRUE) + return; + + // Start the environment setup benchmark + Benchmark::start(SYSTEM_BENCHMARK.'_environment_setup'); + + // Define Kohana error constant + define('E_KOHANA', 42); + + // Define 404 error constant + define('E_PAGE_NOT_FOUND', 43); + + // Define database error constant + define('E_DATABASE_ERROR', 44); + + if (self::$cache_lifetime = self::config('core.internal_cache')) + { + // Are we using encryption for caches? + self::$internal_cache_encrypt = self::config('core.internal_cache_encrypt'); + + if(self::$internal_cache_encrypt===TRUE) + { + self::$internal_cache_key = self::config('core.internal_cache_key'); + + // Be sure the key is of acceptable length for the mcrypt algorithm used + self::$internal_cache_key = substr(self::$internal_cache_key, 0, 24); + } + + // Set the directory to be used for the internal cache + if ( ! self::$internal_cache_path = self::config('core.internal_cache_path')) + { + self::$internal_cache_path = APPPATH.'cache/'; + } + + // Load cached configuration and language files + self::$internal_cache['configuration'] = self::cache('configuration', self::$cache_lifetime); + self::$internal_cache['language'] = self::cache('language', self::$cache_lifetime); + + // Load cached file paths + self::$internal_cache['find_file_paths'] = self::cache('find_file_paths', self::$cache_lifetime); + + // Enable cache saving + Event::add('system.shutdown', array(__CLASS__, 'internal_cache_save')); + } + + // Disable notices and "strict" errors + $ER = error_reporting(~E_NOTICE & ~E_STRICT); + + // Set the user agent + self::$user_agent = ( ! empty($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : ''); + + if (function_exists('date_default_timezone_set')) + { + $timezone = self::config('locale.timezone'); + + // Set default timezone, due to increased validation of date settings + // which cause massive amounts of E_NOTICEs to be generated in PHP 5.2+ + date_default_timezone_set(empty($timezone) ? date_default_timezone_get() : $timezone); + } + + // Restore error reporting + error_reporting($ER); + + // Start output buffering + ob_start(array(__CLASS__, 'output_buffer')); + + // Save buffering level + self::$buffer_level = ob_get_level(); + + // Set autoloader + spl_autoload_register(array('Kohana', 'auto_load')); + + // Set error handler + set_error_handler(array('Kohana', 'exception_handler')); + + // Set exception handler + set_exception_handler(array('Kohana', 'exception_handler')); + + // Send default text/html UTF-8 header + header('Content-Type: text/html; charset=UTF-8'); + + // Load locales + $locales = self::config('locale.language'); + + // Make first locale UTF-8 + $locales[0] .= '.UTF-8'; + + // Set locale information + self::$locale = setlocale(LC_ALL, $locales); + + if (self::$configuration['core']['log_threshold'] > 0) + { + // Set the log directory + self::log_directory(self::$configuration['core']['log_directory']); + + // Enable log writing at shutdown + register_shutdown_function(array(__CLASS__, 'log_save')); + } + + // Enable Kohana routing + Event::add('system.routing', array('Router', 'find_uri')); + Event::add('system.routing', array('Router', 'setup')); + + // Enable Kohana controller initialization + Event::add('system.execute', array('Kohana', 'instance')); + + // Enable Kohana 404 pages + Event::add('system.404', array('Kohana', 'show_404')); + + // Enable Kohana output handling + Event::add('system.shutdown', array('Kohana', 'shutdown')); + + if (self::config('core.enable_hooks') === TRUE) + { + // Find all the hook files + $hooks = self::list_files('hooks', TRUE); + + foreach ($hooks as $file) + { + // Load the hook + include $file; + } + } + + // Setup is complete, prevent it from being run again + $run = TRUE; + + // Stop the environment setup routine + Benchmark::stop(SYSTEM_BENCHMARK.'_environment_setup'); + } + + /** + * Loads the controller and initializes it. Runs the pre_controller, + * post_controller_constructor, and post_controller events. Triggers + * a system.404 event when the route cannot be mapped to a controller. + * + * This method is benchmarked as controller_setup and controller_execution. + * + * @return object instance of controller + */ + public static function & instance() + { + if (self::$instance === NULL) + { + Benchmark::start(SYSTEM_BENCHMARK.'_controller_setup'); + + // Include the Controller file + require Router::$controller_path; + + try + { + // Start validation of the controller + $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller'); + } + catch (ReflectionException $e) + { + // Controller does not exist + Event::run('system.404'); + } + + if ($class->isAbstract() OR (IN_PRODUCTION AND $class->getConstant('ALLOW_PRODUCTION') == FALSE)) + { + // Controller is not allowed to run in production + Event::run('system.404'); + } + + // Run system.pre_controller + Event::run('system.pre_controller'); + + // Create a new controller instance + $controller = $class->newInstance(); + + // Controller constructor has been executed + Event::run('system.post_controller_constructor'); + + try + { + // Load the controller method + $method = $class->getMethod(Router::$method); + + // Method exists + if (Router::$method[0] === '_') + { + // Do not allow access to hidden methods + Event::run('system.404'); + } + + if ($method->isProtected() or $method->isPrivate()) + { + // Do not attempt to invoke protected methods + throw new ReflectionException('protected controller method'); + } + + // Default arguments + $arguments = Router::$arguments; + } + catch (ReflectionException $e) + { + // Use __call instead + $method = $class->getMethod('__call'); + + // Use arguments in __call format + $arguments = array(Router::$method, Router::$arguments); + } + + // Stop the controller setup benchmark + Benchmark::stop(SYSTEM_BENCHMARK.'_controller_setup'); + + // Start the controller execution benchmark + Benchmark::start(SYSTEM_BENCHMARK.'_controller_execution'); + + // Execute the controller method + $method->invokeArgs($controller, $arguments); + + // Controller method has been executed + Event::run('system.post_controller'); + + // Stop the controller execution benchmark + Benchmark::stop(SYSTEM_BENCHMARK.'_controller_execution'); + } + + return self::$instance; + } + + /** + * Get all include paths. APPPATH is the first path, followed by module + * paths in the order they are configured, follow by the SYSPATH. + * + * @param boolean re-process the include paths + * @return array + */ + public static function include_paths($process = FALSE) + { + if ($process === TRUE) + { + // Add APPPATH as the first path + self::$include_paths = array(APPPATH); + + foreach (self::$configuration['core']['modules'] as $path) + { + if ($path = str_replace('\\', '/', realpath($path))) + { + // Add a valid path + self::$include_paths[] = $path.'/'; + } + } + + // Add SYSPATH as the last path + self::$include_paths[] = SYSPATH; + } + + return self::$include_paths; + } + + /** + * Get a config item or group. + * + * @param string item name + * @param boolean force a forward slash (/) at the end of the item + * @param boolean is the item required? + * @return mixed + */ + public static function config($key, $slash = FALSE, $required = TRUE) + { + if (self::$configuration === NULL) + { + // Load core configuration + self::$configuration['core'] = self::config_load('core'); + + // Re-parse the include paths + self::include_paths(TRUE); + } + + // Get the group name from the key + $group = explode('.', $key, 2); + $group = $group[0]; + + if ( ! isset(self::$configuration[$group])) + { + // Load the configuration group + self::$configuration[$group] = self::config_load($group, $required); + } + + // Get the value of the key string + $value = self::key_string(self::$configuration, $key); + + if ($slash === TRUE AND is_string($value) AND $value !== '') + { + // Force the value to end with "/" + $value = rtrim($value, '/').'/'; + } + + return $value; + } + + /** + * Sets a configuration item, if allowed. + * + * @param string config key string + * @param string config value + * @return boolean + */ + public static function config_set($key, $value) + { + // Do this to make sure that the config array is already loaded + self::config($key); + + if (substr($key, 0, 7) === 'routes.') + { + // Routes cannot contain sub keys due to possible dots in regex + $keys = explode('.', $key, 2); + } + else + { + // Convert dot-noted key string to an array + $keys = explode('.', $key); + } + + // Used for recursion + $conf =& self::$configuration; + $last = count($keys) - 1; + + foreach ($keys as $i => $k) + { + if ($i === $last) + { + $conf[$k] = $value; + } + else + { + $conf =& $conf[$k]; + } + } + + if ($key === 'core.modules') + { + // Reprocess the include paths + self::include_paths(TRUE); + } + + return TRUE; + } + + /** + * Load a config file. + * + * @param string config filename, without extension + * @param boolean is the file required? + * @return array + */ + public static function config_load($name, $required = TRUE) + { + if ($name === 'core') + { + // Load the application configuration file + require APPPATH.'config/config'.EXT; + + if ( ! isset($config['site_domain'])) + { + // Invalid config file + die('Your Kohana application configuration file is not valid.'); + } + + return $config; + } + + if (isset(self::$internal_cache['configuration'][$name])) + return self::$internal_cache['configuration'][$name]; + + // Load matching configs + $configuration = array(); + + if ($files = self::find_file('config', $name, $required)) + { + foreach ($files as $file) + { + require $file; + + if (isset($config) AND is_array($config)) + { + // Merge in configuration + $configuration = array_merge($configuration, $config); + } + } + } + + if ( ! isset(self::$write_cache['configuration'])) + { + // Cache has changed + self::$write_cache['configuration'] = TRUE; + } + + return self::$internal_cache['configuration'][$name] = $configuration; + } + + /** + * Clears a config group from the cached configuration. + * + * @param string config group + * @return void + */ + public static function config_clear($group) + { + // Remove the group from config + unset(self::$configuration[$group], self::$internal_cache['configuration'][$group]); + + if ( ! isset(self::$write_cache['configuration'])) + { + // Cache has changed + self::$write_cache['configuration'] = TRUE; + } + } + + /** + * Add a new message to the log. + * + * @param string type of message + * @param string message text + * @return void + */ + public static function log($type, $message) + { + if (self::$log_levels[$type] <= self::$configuration['core']['log_threshold']) + { + $message = array(date('Y-m-d H:i:s P'), $type, $message); + + // Run the system.log event + Event::run('system.log', $message); + + self::$log[] = $message; + } + } + + /** + * Save all currently logged messages. + * + * @return void + */ + public static function log_save() + { + if (empty(self::$log) OR self::$configuration['core']['log_threshold'] < 1) + return; + + // Filename of the log + $filename = self::log_directory().date('Y-m-d').'.log'.EXT; + + if ( ! is_file($filename)) + { + // Write the SYSPATH checking header + file_put_contents($filename, + ''.PHP_EOL.PHP_EOL); + + // Prevent external writes + chmod($filename, 0644); + } + + // Messages to write + $messages = array(); + + do + { + // Load the next mess + list ($date, $type, $text) = array_shift(self::$log); + + // Add a new message line + $messages[] = $date.' --- '.$type.': '.$text; + } + while ( ! empty(self::$log)); + + // Write messages to log file + file_put_contents($filename, implode(PHP_EOL, $messages).PHP_EOL, FILE_APPEND); + } + + /** + * Get or set the logging directory. + * + * @param string new log directory + * @return string + */ + public static function log_directory($dir = NULL) + { + static $directory; + + if ( ! empty($dir)) + { + // Get the directory path + $dir = realpath($dir); + + if (is_dir($dir) AND is_writable($dir)) + { + // Change the log directory + $directory = str_replace('\\', '/', $dir).'/'; + } + else + { + // Log directory is invalid + throw new Kohana_Exception('core.log_dir_unwritable', $dir); + } + } + + return $directory; + } + + /** + * Load data from a simple cache file. This should only be used internally, + * and is NOT a replacement for the Cache library. + * + * @param string unique name of cache + * @param integer expiration in seconds + * @return mixed + */ + public static function cache($name, $lifetime) + { + if ($lifetime > 0) + { + $path = self::$internal_cache_path.'kohana_'.$name; + + if (is_file($path)) + { + // Check the file modification time + if ((time() - filemtime($path)) < $lifetime) + { + // Cache is valid! Now, do we need to decrypt it? + if(self::$internal_cache_encrypt===TRUE) + { + $data = file_get_contents($path); + + $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); + $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); + + $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, self::$internal_cache_key, $data, MCRYPT_MODE_ECB, $iv); + + $cache = unserialize($decrypted_text); + + // If the key changed, delete the cache file + if(!$cache) + unlink($path); + + // If cache is false (as above) return NULL, otherwise, return the cache + return ($cache ? $cache : NULL); + } + else + { + return unserialize(file_get_contents($path)); + } + } + else + { + // Cache is invalid, delete it + unlink($path); + } + } + } + + // No cache found + return NULL; + } + + /** + * Save data to a simple cache file. This should only be used internally, and + * is NOT a replacement for the Cache library. + * + * @param string cache name + * @param mixed data to cache + * @param integer expiration in seconds + * @return boolean + */ + public static function cache_save($name, $data, $lifetime) + { + if ($lifetime < 1) + return FALSE; + + $path = self::$internal_cache_path.'kohana_'.$name; + + if ($data === NULL) + { + // Delete cache + return (is_file($path) and unlink($path)); + } + else + { + // Using encryption? Encrypt the data when we write it + if(self::$internal_cache_encrypt===TRUE) + { + // Encrypt and write data to cache file + $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); + $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); + + // Serialize and encrypt! + $encrypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, self::$internal_cache_key, serialize($data), MCRYPT_MODE_ECB, $iv); + + return (bool) file_put_contents($path, $encrypted_text); + } + else + { + // Write data to cache file + return (bool) file_put_contents($path, serialize($data)); + } + } + } + + /** + * Kohana output handler. Called during ob_clean, ob_flush, and their variants. + * + * @param string current output buffer + * @return string + */ + public static function output_buffer($output) + { + // Could be flushing, so send headers first + if ( ! Event::has_run('system.send_headers')) + { + // Run the send_headers event + Event::run('system.send_headers'); + } + + self::$output = $output; + + // Set and return the final output + return self::$output; + } + + /** + * Closes all open output buffers, either by flushing or cleaning, and stores the Kohana + * output buffer for display during shutdown. + * + * @param boolean disable to clear buffers, rather than flushing + * @return void + */ + public static function close_buffers($flush = TRUE) + { + if (ob_get_level() >= self::$buffer_level) + { + // Set the close function + $close = ($flush === TRUE) ? 'ob_end_flush' : 'ob_end_clean'; + + while (ob_get_level() > self::$buffer_level) + { + // Flush or clean the buffer + $close(); + } + + // Store the Kohana output buffer + if ( version_compare(PHP_VERSION, '5.4', '<') ) { + ob_end_clean(); + } + } + } + + /** + * Triggers the shutdown of Kohana by closing the output buffer, runs the system.display event. + * + * @return void + */ + public static function shutdown() + { + // Close output buffers + self::close_buffers(TRUE); + + // Run the output event + Event::run('system.display', self::$output); + + // Render the final output + self::render(self::$output); + } + + /** + * Inserts global Kohana variables into the generated output and prints it. + * + * @param string final output that will displayed + * @return void + */ + public static function render($output) + { + if (self::config('core.render_stats') === TRUE) + { + // Fetch memory usage in MB + $memory = function_exists('memory_get_usage') ? (memory_get_usage() / 1024 / 1024) : 0; + + // Fetch benchmark for page execution time + $benchmark = Benchmark::get(SYSTEM_BENCHMARK.'_total_execution'); + + // Replace the global template variables + $output = str_replace( + array + ( + '{kohana_version}', + '{kohana_codename}', + '{execution_time}', + '{memory_usage}', + '{included_files}', + ), + array + ( + KOHANA_VERSION, + KOHANA_CODENAME, + $benchmark['time'], + number_format($memory, 2).'MB', + count(get_included_files()), + ), + $output + ); + } + + if ($level = self::config('core.output_compression') AND ini_get('output_handler') !== 'ob_gzhandler' AND (int) ini_get('zlib.output_compression') === 0) + { + if ($level < 1 OR $level > 9) + { + // Normalize the level to be an integer between 1 and 9. This + // step must be done to prevent gzencode from triggering an error + $level = max(1, min($level, 9)); + } + + if (stripos(@$_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) + { + $compress = 'gzip'; + } + elseif (stripos(@$_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== FALSE) + { + $compress = 'deflate'; + } + } + + if (isset($compress) AND $level > 0) + { + switch ($compress) + { + case 'gzip': + // Compress output using gzip + $output = gzencode($output, $level); + break; + case 'deflate': + // Compress output using zlib (HTTP deflate) + $output = gzdeflate($output, $level); + break; + } + + // This header must be sent with compressed content to prevent + // browser caches from breaking + header('Vary: Accept-Encoding'); + + // Send the content encoding header + header('Content-Encoding: '.$compress); + + // Sending Content-Length in CGI can result in unexpected behavior + if (stripos(PHP_SAPI, 'cgi') === FALSE) + { + header('Content-Length: '.strlen($output)); + } + } + + echo $output; + } + + /** + * Displays a 404 page. + * + * @throws Kohana_404_Exception + * @param string URI of page + * @param string custom template + * @return void + */ + public static function show_404($page = FALSE, $template = FALSE) + { + throw new Kohana_404_Exception($page, $template); + } + + /** + * Dual-purpose PHP error and exception handler. Uses the kohana_error_page + * view to display the message. + * + * @param integer|object exception object or error code + * @param string error message + * @param string filename + * @param integer line number + * @return void + */ + public static function exception_handler($exception, $message = NULL, $file = NULL, $line = NULL) + { + try + { + // PHP errors have 5 args, always + $PHP_ERROR = (func_num_args() === 5); + + // Test to see if errors should be displayed + if ($PHP_ERROR AND (error_reporting() & $exception) === 0) + return; + + // This is useful for hooks to determine if a page has an error + self::$has_error = TRUE; + + // Error handling will use exactly 5 args, every time + if ($PHP_ERROR) + { + $code = $exception; + $type = 'PHP Error'; + $template = 'kohana_error_page'; + } + else + { + $code = $exception->getCode(); + $type = get_class($exception); + $message = $exception->getMessage(); + $file = $exception->getFile(); + $line = $exception->getLine(); + $template = ($exception instanceof Kohana_Exception) ? $exception->getTemplate() : 'kohana_error_page'; + } + + if (is_numeric($code)) + { + $codes = self::lang('errors'); + + if ( ! empty($codes[$code])) + { + list($level, $error, $description) = $codes[$code]; + } + else + { + $level = 1; + $error = $PHP_ERROR ? 'Unknown Error' : get_class($exception); + $description = ''; + } + } + else + { + // Custom error message, this will never be logged + $level = 5; + $error = $code; + $description = ''; + } + + // Remove the DOCROOT from the path, as a security precaution + $file = str_replace('\\', '/', realpath($file)); + $file = preg_replace('|^'.preg_quote(DOCROOT).'|', '', $file); + + if ($level <= self::$configuration['core']['log_threshold']) + { + // Log the error + self::log('error', self::lang('core.uncaught_exception', $type, $message, $file, $line)); + } + + if ($PHP_ERROR) + { + //$description = self::lang('errors.'.E_RECOVERABLE_ERROR); + $description = is_array($description) ? $description[2] : ''; + + if ( ! headers_sent()) + { + // Send the 500 header + header('HTTP/1.1 500 Internal Server Error'); + } + } + else + { + if (method_exists($exception, 'sendHeaders') AND ! headers_sent()) + { + // Send the headers if they have not already been sent + $exception->sendHeaders(); + } + } + + // Close all output buffers except for Kohana + while (ob_get_level() > self::$buffer_level) + { + ob_end_clean(); + } + + // Test if display_errors is on + if (self::$configuration['core']['display_errors'] === TRUE) + { + if ( ! IN_PRODUCTION AND $line != FALSE) + { + // Remove the first entry of debug_backtrace(), it is the exception_handler call + $trace = $PHP_ERROR ? array_slice(debug_backtrace(), 1) : $exception->getTrace(); + + // Beautify backtrace + $trace = self::backtrace($trace); + } + + // Load the error + require self::find_file('views', empty($template) ? 'kohana_error_page' : $template); + } + else + { + // Get the i18n messages + $error = self::lang('core.generic_error'); + $message = self::lang('core.errors_disabled', url::site(), url::site(Router::$current_uri)); + + // Load the errors_disabled view + require self::find_file('views', 'kohana_error_disabled'); + } + + if ( ! Event::has_run('system.shutdown')) + { + // Run the shutdown even to ensure a clean exit + Event::run('system.shutdown'); + } + + // Turn off error reporting + error_reporting(0); + exit; + } + catch (Exception $e) + { + if (IN_PRODUCTION) + { + die('Fatal Error'); + } + else + { + die('Fatal Error: '.$e->getMessage().' File: '.$e->getFile().' Line: '.$e->getLine()); + } + } + } + + /** + * Provides class auto-loading. + * + * @throws Kohana_Exception + * @param string name of class + * @return bool + */ + public static function auto_load($class) + { + if (class_exists($class, FALSE)) + return TRUE; + + if (($suffix = strrpos($class, '_')) > 0) + { + // Find the class suffix + $suffix = substr($class, $suffix + 1); + } + else + { + // No suffix + $suffix = FALSE; + } + + if ($suffix === 'Core') + { + $type = 'libraries'; + $file = substr($class, 0, -5); + } + elseif ($suffix === 'Controller') + { + $type = 'controllers'; + // Lowercase filename + $file = strtolower(substr($class, 0, -11)); + } + elseif ($suffix === 'Model') + { + $type = 'models'; + // Lowercase filename + $file = strtolower(substr($class, 0, -6)); + } + elseif ($suffix === 'Driver') + { + $type = 'libraries/drivers'; + $file = str_replace('_', '/', substr($class, 0, -7)); + } + else + { + // This could be either a library or a helper, but libraries must + // always be capitalized, so we check if the first character is + // uppercase. If it is, we are loading a library, not a helper. + $type = ($class[0] < 'a') ? 'libraries' : 'helpers'; + $file = $class; + } + + if ($filename = self::find_file($type, $file)) + { + // Load the class + require $filename; + } + else + { + // The class could not be found + return FALSE; + } + + if ($filename = self::find_file($type, self::$configuration['core']['extension_prefix'].$class)) + { + // Load the class extension + require $filename; + } + elseif ($suffix !== 'Core' AND class_exists($class.'_Core', FALSE)) + { + // Class extension to be evaluated + $extension = 'class '.$class.' extends '.$class.'_Core { }'; + + // Start class analysis + $core = new ReflectionClass($class.'_Core'); + + if ($core->isAbstract()) + { + // Make the extension abstract + $extension = 'abstract '.$extension; + } + + // Transparent class extensions are handled using eval. This is + // a disgusting hack, but it gets the job done. + eval($extension); + } + + return TRUE; + } + + /** + * Find a resource file in a given directory. Files will be located according + * to the order of the include paths. Configuration and i18n files will be + * returned in reverse order. + * + * @throws Kohana_Exception if file is required and not found + * @param string directory to search in + * @param string filename to look for (without extension) + * @param boolean file required + * @param string file extension + * @return array if the type is config, i18n or l10n + * @return string if the file is found + * @return FALSE if the file is not found + */ + public static function find_file($directory, $filename, $required = FALSE, $ext = FALSE) + { + // NOTE: This test MUST be not be a strict comparison (===), or empty + // extensions will be allowed! + if ($ext == '') + { + // Use the default extension + $ext = EXT; + } + else + { + // Add a period before the extension + $ext = '.'.$ext; + } + + // Search path + $search = $directory.'/'.$filename.$ext; + + if (isset(self::$internal_cache['find_file_paths'][$search])) + return self::$internal_cache['find_file_paths'][$search]; + + // Load include paths + $paths = self::$include_paths; + + // Nothing found, yet + $found = NULL; + + if ($directory === 'config' OR $directory === 'i18n') + { + // Search in reverse, for merging + $paths = array_reverse($paths); + + foreach ($paths as $path) + { + if (is_file($path.$search)) + { + // A matching file has been found + $found[] = $path.$search; + } + } + } + else + { + foreach ($paths as $path) + { + if (is_file($path.$search)) + { + // A matching file has been found + $found = $path.$search; + + // Stop searching + break; + } + } + } + + if ($found === NULL) + { + if ($required === TRUE) + { + // Directory i18n key + $directory = 'core.'.inflector::singular($directory); + + // If the file is required, throw an exception + throw new Kohana_Exception('core.resource_not_found', self::lang($directory), $filename); + } + else + { + // Nothing was found, return FALSE + $found = FALSE; + } + } + + if ( ! isset(self::$write_cache['find_file_paths'])) + { + // Write cache at shutdown + self::$write_cache['find_file_paths'] = TRUE; + } + + return self::$internal_cache['find_file_paths'][$search] = $found; + } + + /** + * Lists all files and directories in a resource path. + * + * @param string directory to search + * @param boolean list all files to the maximum depth? + * @param string full path to search (used for recursion, *never* set this manually) + * @return array filenames and directories + */ + public static function list_files($directory, $recursive = FALSE, $path = FALSE) + { + $files = array(); + + if ($path === FALSE) + { + $paths = array_reverse(self::include_paths()); + + foreach ($paths as $path) + { + // Recursively get and merge all files + $files = array_merge($files, self::list_files($directory, $recursive, $path.$directory)); + } + } + else + { + $path = rtrim($path, '/').'/'; + + if (is_readable($path)) + { + $items = (array) glob($path.'*'); + + if ( ! empty($items)) + { + foreach ($items as $index => $item) + { + $files[] = $item = str_replace('\\', '/', $item); + + // Handle recursion + if (is_dir($item) AND $recursive == TRUE) + { + // Filename should only be the basename + $item = pathinfo($item, PATHINFO_BASENAME); + + // Append sub-directory search + $files = array_merge($files, self::list_files($directory, TRUE, $path.$item)); + } + } + } + } + } + + return $files; + } + + /** + * Fetch an i18n language item. + * + * @param string language key to fetch + * @param array additional information to insert into the line + * @return string i18n language string, or the requested key if the i18n item is not found + */ + public static function lang($key, $args = array()) + { + // Extract the main group from the key + $group = explode('.', $key, 2); + $group = $group[0]; + + // Get locale name + $locale = self::config('locale.language.0'); + + if ( ! isset(self::$internal_cache['language'][$locale][$group])) + { + // Messages for this group + $messages = array(); + + if ($files = self::find_file('i18n', $locale.'/'.$group)) + { + foreach ($files as $file) + { + include $file; + + // Merge in configuration + if ( ! empty($lang) AND is_array($lang)) + { + foreach ($lang as $k => $v) + { + $messages[$k] = $v; + } + } + } + } + + if ( ! isset(self::$write_cache['language'])) + { + // Write language cache + self::$write_cache['language'] = TRUE; + } + + self::$internal_cache['language'][$locale][$group] = $messages; + } + + // Get the line from cache + $line = self::key_string(self::$internal_cache['language'][$locale], $key); + + if ($line === NULL) + { + self::log('error', 'Missing i18n entry '.$key.' for language '.$locale); + + // Return the key string as fallback + return $key; + } + + if (is_string($line) AND func_num_args() > 1) + { + $args = array_slice(func_get_args(), 1); + + // Add the arguments into the line + $line = vsprintf($line, is_array($args[0]) ? $args[0] : $args); + } + + return $line; + } + + /** + * Returns the value of a key, defined by a 'dot-noted' string, from an array. + * + * @param array array to search + * @param string dot-noted string: foo.bar.baz + * @return string if the key is found + * @return void if the key is not found + */ + public static function key_string($array, $keys) + { + if (empty($array)) + return NULL; + + // Prepare for loop + $keys = explode('.', $keys); + + do + { + // Get the next key + $key = array_shift($keys); + + if (isset($array[$key])) + { + if (is_array($array[$key]) AND ! empty($keys)) + { + // Dig down to prepare the next loop + $array = $array[$key]; + } + else + { + // Requested key was found + return $array[$key]; + } + } + else + { + // Requested key is not set + break; + } + } + while ( ! empty($keys)); + + return NULL; + } + + /** + * Sets values in an array by using a 'dot-noted' string. + * + * @param array array to set keys in (reference) + * @param string dot-noted string: foo.bar.baz + * @return mixed fill value for the key + * @return void + */ + public static function key_string_set( & $array, $keys, $fill = NULL) + { + if (is_object($array) AND ($array instanceof ArrayObject)) + { + // Copy the array + $array_copy = $array->getArrayCopy(); + + // Is an object + $array_object = TRUE; + } + else + { + if ( ! is_array($array)) + { + // Must always be an array + $array = (array) $array; + } + + // Copy is a reference to the array + $array_copy =& $array; + } + + if (empty($keys)) + return $array; + + // Create keys + $keys = explode('.', $keys); + + // Create reference to the array + $row =& $array_copy; + + for ($i = 0, $end = count($keys) - 1; $i <= $end; $i++) + { + // Get the current key + $key = $keys[$i]; + + if ( ! isset($row[$key])) + { + if (isset($keys[$i + 1])) + { + // Make the value an array + $row[$key] = array(); + } + else + { + // Add the fill key + $row[$key] = $fill; + } + } + elseif (isset($keys[$i + 1])) + { + // Make the value an array + $row[$key] = (array) $row[$key]; + } + + // Go down a level, creating a new row reference + $row =& $row[$key]; + } + + if (isset($array_object)) + { + // Swap the array back in + $array->exchangeArray($array_copy); + } + } + + /** + * Retrieves current user agent information: + * keys: browser, version, platform, mobile, robot, referrer, languages, charsets + * tests: is_browser, is_mobile, is_robot, accept_lang, accept_charset + * + * @param string key or test name + * @param string used with "accept" tests: user_agent(accept_lang, en) + * @return array languages and charsets + * @return string all other keys + * @return boolean all tests + */ + public static function user_agent($key = 'agent', $compare = NULL) + { + static $info; + + // Return the raw string + if ($key === 'agent') + return self::$user_agent; + + if ($info === NULL) + { + // Parse the user agent and extract basic information + $agents = self::config('user_agents'); + + foreach ($agents as $type => $data) + { + foreach ($data as $agent => $name) + { + if (stripos(self::$user_agent, $agent) !== FALSE) + { + if ($type === 'browser' AND preg_match('|'.preg_quote($agent).'[^0-9.]*+([0-9.][0-9.a-z]*)|i', self::$user_agent, $match)) + { + // Set the browser version + $info['version'] = $match[1]; + } + + // Set the agent name + $info[$type] = $name; + break; + } + } + } + } + + if (empty($info[$key])) + { + switch ($key) + { + case 'is_robot': + case 'is_browser': + case 'is_mobile': + // A boolean result + $return = ! empty($info[substr($key, 3)]); + break; + case 'languages': + $return = array(); + if ( ! empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + { + if (preg_match_all('/[-a-z]{2,}/', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE'])), $matches)) + { + // Found a result + $return = $matches[0]; + } + } + break; + case 'charsets': + $return = array(); + if ( ! empty($_SERVER['HTTP_ACCEPT_CHARSET'])) + { + if (preg_match_all('/[-a-z0-9]{2,}/', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET'])), $matches)) + { + // Found a result + $return = $matches[0]; + } + } + break; + case 'referrer': + if ( ! empty($_SERVER['HTTP_REFERER'])) + { + // Found a result + $return = trim($_SERVER['HTTP_REFERER']); + } + break; + } + + // Cache the return value + isset($return) and $info[$key] = $return; + } + + if ( ! empty($compare)) + { + // The comparison must always be lowercase + $compare = strtolower($compare); + + switch ($key) + { + case 'accept_lang': + // Check if the lange is accepted + return in_array($compare, self::user_agent('languages')); + break; + case 'accept_charset': + // Check if the charset is accepted + return in_array($compare, self::user_agent('charsets')); + break; + default: + // Invalid comparison + return FALSE; + break; + } + } + + // Return the key, if set + return isset($info[$key]) ? $info[$key] : NULL; + } + + /** + * Quick debugging of any variable. Any number of parameters can be set. + * + * @return string + */ + public static function debug() + { + if (func_num_args() === 0) + return; + + // Get params + $params = func_get_args(); + $output = array(); + + foreach ($params as $var) + { + $output[] = '
('.gettype($var).') '.html::specialchars(print_r($var, TRUE)).'
'; + } + + return implode("\n", $output); + } + + /** + * Displays nice backtrace information. + * @see http://php.net/debug_backtrace + * + * @param array backtrace generated by an exception or debug_backtrace + * @return string + */ + public static function backtrace($trace) + { + if ( ! is_array($trace)) + return; + + // Final output + $output = array(); + + foreach ($trace as $entry) + { + $temp = '
  • '; + + if (isset($entry['file'])) + { + $temp .= self::lang('core.error_file_line', preg_replace('!^'.preg_quote(DOCROOT).'!', '', $entry['file']), $entry['line']); + } + + $temp .= '
    ';
    +
    +			if (isset($entry['class']))
    +			{
    +				// Add class and call type
    +				$temp .= $entry['class'].$entry['type'];
    +			}
    +
    +			// Add function
    +			$temp .= $entry['function'].'( ';
    +
    +			// Add function args
    +			if (isset($entry['args']) AND is_array($entry['args']))
    +			{
    +				// Separator starts as nothing
    +				$sep = '';
    +
    +				while ($arg = array_shift($entry['args']))
    +				{
    +					if (is_string($arg) AND is_file($arg))
    +					{
    +						// Remove docroot from filename
    +						$arg = preg_replace('!^'.preg_quote(DOCROOT).'!', '', $arg);
    +					}
    +
    +					$temp .= $sep.html::specialchars(print_r($arg, TRUE));
    +
    +					// Change separator to a comma
    +					$sep = ', ';
    +				}
    +			}
    +
    +			$temp .= ' )
  • '; + + $output[] = $temp; + } + + return '
      '.implode("\n", $output).'
    '; + } + + /** + * Saves the internal caches: configuration, include paths, etc. + * + * @return boolean + */ + public static function internal_cache_save() + { + if ( ! is_array(self::$write_cache)) + return FALSE; + + // Get internal cache names + $caches = array_keys(self::$write_cache); + + // Nothing written + $written = FALSE; + + foreach ($caches as $cache) + { + if (isset(self::$internal_cache[$cache])) + { + // Write the cache file + self::cache_save($cache, self::$internal_cache[$cache], self::$configuration['core']['internal_cache']); + + // A cache has been written + $written = TRUE; + } + } + + return $written; + } + +} // End Kohana + +/** + * Creates a generic i18n exception. + */ +class Kohana_Exception extends Exception { + + // Template file + protected $template = 'kohana_error_page'; + + // Header + protected $header = FALSE; + + // Error code + protected $code = E_KOHANA; + + /** + * Set exception message. + * + * @param string i18n language key for the message + * @param array addition line parameters + */ + public function __construct($error) + { + $args = array_slice(func_get_args(), 1); + + // Fetch the error message + $message = Kohana::lang($error, $args); + + if ($message === $error OR empty($message)) + { + // Unable to locate the message for the error + $message = 'Unknown Exception: '.$error; + } + + // Sets $this->message the proper way + parent::__construct($message); + } + + /** + * Magic method for converting an object to a string. + * + * @return string i18n message + */ + public function __toString() + { + return (string) $this->message; + } + + /** + * Fetch the template name. + * + * @return string + */ + public function getTemplate() + { + return $this->template; + } + + /** + * Sends an Internal Server Error header. + * + * @return void + */ + public function sendHeaders() + { + // Send the 500 header + header('HTTP/1.1 500 Internal Server Error'); + } + +} // End Kohana Exception + +/** + * Creates a custom exception. + */ +class Kohana_User_Exception extends Kohana_Exception { + + /** + * Set exception title and message. + * + * @param string exception title string + * @param string exception message string + * @param string custom error template + */ + public function __construct($title, $message, $template = FALSE) + { + Exception::__construct($message); + + $this->code = $title; + + if ($template !== FALSE) + { + $this->template = $template; + } + } + +} // End Kohana PHP Exception + +/** + * Creates a Page Not Found exception. + */ +class Kohana_404_Exception extends Kohana_Exception { + + protected $code = E_PAGE_NOT_FOUND; + + /** + * Set internal properties. + * + * @param string URL of page + * @param string custom error template + */ + public function __construct($page = FALSE, $template = FALSE) + { + if ($page === FALSE) + { + // Construct the page URI using Router properties + $page = Router::$current_uri.Router::$url_suffix.Router::$query_string; + } + + Exception::__construct(Kohana::lang('core.page_not_found', $page)); + + $this->template = $template; + } + + /** + * Sends "File Not Found" headers, to emulate server behavior. + * + * @return void + */ + public function sendHeaders() + { + // Send the 404 header + header('HTTP/1.1 404 File Not Found'); + } + +} // End Kohana 404 Exception diff --git a/lib/kohana/system/core/utf8.php b/lib/kohana/system/core/utf8.php new file mode 100644 index 0000000..9f20f42 --- /dev/null +++ b/lib/kohana/system/core/utf8.php @@ -0,0 +1,743 @@ +PCRE has not been compiled with UTF-8 support. '. + 'See PCRE Pattern Modifiers '. + 'for more information. This application cannot be run without UTF-8 support.', + E_USER_ERROR + ); +} + +if ( ! extension_loaded('iconv')) +{ + trigger_error + ( + 'The iconv extension is not loaded. '. + 'Without iconv, strings cannot be properly translated to UTF-8 from user input. '. + 'This application cannot be run without UTF-8 support.', + E_USER_ERROR + ); +} + +if (extension_loaded('mbstring') AND (ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING)) +{ + trigger_error + ( + 'The mbstring extension is overloading PHP\'s native string functions. '. + 'Disable this by setting mbstring.func_overload to 0, 1, 4 or 5 in php.ini or a .htaccess file.'. + 'This application cannot be run without UTF-8 support.', + E_USER_ERROR + ); +} + +// Check PCRE support for Unicode properties such as \p and \X. +$ER = error_reporting(0); +define('PCRE_UNICODE_PROPERTIES', (bool) preg_match('/^\pL$/u', 'ñ')); +error_reporting($ER); + +// SERVER_UTF8 ? use mb_* functions : use non-native functions +if (extension_loaded('mbstring')) +{ + mb_internal_encoding('UTF-8'); + define('SERVER_UTF8', TRUE); +} +else +{ + define('SERVER_UTF8', FALSE); +} + +// Convert all global variables to UTF-8. +$_GET = utf8::clean($_GET); +$_POST = utf8::clean($_POST); +$_COOKIE = utf8::clean($_COOKIE); +$_SERVER = utf8::clean($_SERVER); + +if (PHP_SAPI == 'cli') +{ + // Convert command line arguments + $_SERVER['argv'] = utf8::clean($_SERVER['argv']); +} + +final class utf8 { + + // Called methods + static $called = array(); + + /** + * Recursively cleans arrays, objects, and strings. Removes ASCII control + * codes and converts to UTF-8 while silently discarding incompatible + * UTF-8 characters. + * + * @param string string to clean + * @return string + */ + public static function clean($str) + { + if (is_array($str) OR is_object($str)) + { + foreach ($str as $key => $val) + { + // Recursion! + $str[self::clean($key)] = self::clean($val); + } + } + elseif (is_string($str) AND $str !== '') + { + // Remove control characters + $str = self::strip_ascii_ctrl($str); + + if ( ! self::is_ascii($str)) + { + // Disable notices + $ER = error_reporting(~E_NOTICE); + + // iconv is expensive, so it is only used when needed + $str = iconv('UTF-8', 'UTF-8//IGNORE', $str); + + // Turn notices back on + error_reporting($ER); + } + } + + return $str; + } + + /** + * Tests whether a string contains only 7bit ASCII bytes. This is used to + * determine when to use native functions or UTF-8 functions. + * + * @param string string to check + * @return bool + */ + public static function is_ascii($str) + { + return ! preg_match('/[^\x00-\x7F]/S', $str); + } + + /** + * Strips out device control codes in the ASCII range. + * + * @param string string to clean + * @return string + */ + public static function strip_ascii_ctrl($str) + { + return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $str); + } + + /** + * Strips out all non-7bit ASCII bytes. + * + * @param string string to clean + * @return string + */ + public static function strip_non_ascii($str) + { + return preg_replace('/[^\x00-\x7F]+/S', '', $str); + } + + /** + * Replaces special/accented UTF-8 characters by ASCII-7 'equivalents'. + * + * @author Andreas Gohr + * + * @param string string to transliterate + * @param integer -1 lowercase only, +1 uppercase only, 0 both cases + * @return string + */ + public static function transliterate_to_ascii($str, $case = 0) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _transliterate_to_ascii($str, $case); + } + + /** + * Returns the length of the given string. + * @see http://php.net/strlen + * + * @param string string being measured for length + * @return integer + */ + public static function strlen($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strlen($str); + } + + /** + * Finds position of first occurrence of a UTF-8 string. + * @see http://php.net/strlen + * + * @author Harry Fuecks + * + * @param string haystack + * @param string needle + * @param integer offset from which character in haystack to start searching + * @return integer position of needle + * @return boolean FALSE if the needle is not found + */ + public static function strpos($str, $search, $offset = 0) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strpos($str, $search, $offset); + } + + /** + * Finds position of last occurrence of a char in a UTF-8 string. + * @see http://php.net/strrpos + * + * @author Harry Fuecks + * + * @param string haystack + * @param string needle + * @param integer offset from which character in haystack to start searching + * @return integer position of needle + * @return boolean FALSE if the needle is not found + */ + public static function strrpos($str, $search, $offset = 0) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strrpos($str, $search, $offset); + } + + /** + * Returns part of a UTF-8 string. + * @see http://php.net/substr + * + * @author Chris Smith + * + * @param string input string + * @param integer offset + * @param integer length limit + * @return string + */ + public static function substr($str, $offset, $length = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _substr($str, $offset, $length); + } + + /** + * Replaces text within a portion of a UTF-8 string. + * @see http://php.net/substr_replace + * + * @author Harry Fuecks + * + * @param string input string + * @param string replacement string + * @param integer offset + * @return string + */ + public static function substr_replace($str, $replacement, $offset, $length = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _substr_replace($str, $replacement, $offset, $length); + } + + /** + * Makes a UTF-8 string lowercase. + * @see http://php.net/strtolower + * + * @author Andreas Gohr + * + * @param string mixed case string + * @return string + */ + public static function strtolower($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strtolower($str); + } + + /** + * Makes a UTF-8 string uppercase. + * @see http://php.net/strtoupper + * + * @author Andreas Gohr + * + * @param string mixed case string + * @return string + */ + public static function strtoupper($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strtoupper($str); + } + + /** + * Makes a UTF-8 string's first character uppercase. + * @see http://php.net/ucfirst + * + * @author Harry Fuecks + * + * @param string mixed case string + * @return string + */ + public static function ucfirst($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _ucfirst($str); + } + + /** + * Makes the first character of every word in a UTF-8 string uppercase. + * @see http://php.net/ucwords + * + * @author Harry Fuecks + * + * @param string mixed case string + * @return string + */ + public static function ucwords($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _ucwords($str); + } + + /** + * Case-insensitive UTF-8 string comparison. + * @see http://php.net/strcasecmp + * + * @author Harry Fuecks + * + * @param string string to compare + * @param string string to compare + * @return integer less than 0 if str1 is less than str2 + * @return integer greater than 0 if str1 is greater than str2 + * @return integer 0 if they are equal + */ + public static function strcasecmp($str1, $str2) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strcasecmp($str1, $str2); + } + + /** + * Returns a string or an array with all occurrences of search in subject (ignoring case). + * replaced with the given replace value. + * @see http://php.net/str_ireplace + * + * @note It's not fast and gets slower if $search and/or $replace are arrays. + * @author Harry Fuecks + * + * @param string input string + * @param string needle + * @return string matched substring if found + * @return boolean FALSE if the substring was not found + */ + public static function stristr($str, $search) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _stristr($str, $search); + } + + /** + * Finds the length of the initial segment matching mask. + * @see http://php.net/strspn + * + * @author Harry Fuecks + * + * @param string input string + * @param string mask for search + * @param integer start position of the string to examine + * @param integer length of the string to examine + * @return integer length of the initial segment that contains characters in the mask + */ + public static function strspn($str, $mask, $offset = NULL, $length = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strspn($str, $mask, $offset, $length); + } + + /** + * Finds the length of the initial segment not matching mask. + * @see http://php.net/strcspn + * + * @author Harry Fuecks + * + * @param string input string + * @param string mask for search + * @param integer start position of the string to examine + * @param integer length of the string to examine + * @return integer length of the initial segment that contains characters not in the mask + */ + public static function strcspn($str, $mask, $offset = NULL, $length = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strcspn($str, $mask, $offset, $length); + } + + /** + * Pads a UTF-8 string to a certain length with another string. + * @see http://php.net/str_pad + * + * @author Harry Fuecks + * + * @param string input string + * @param integer desired string length after padding + * @param string string to use as padding + * @param string padding type: STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH + * @return string + */ + public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _str_pad($str, $final_str_length, $pad_str, $pad_type); + } + + /** + * Converts a UTF-8 string to an array. + * @see http://php.net/str_split + * + * @author Harry Fuecks + * + * @param string input string + * @param integer maximum length of each chunk + * @return array + */ + public static function str_split($str, $split_length = 1) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _str_split($str, $split_length); + } + + /** + * Reverses a UTF-8 string. + * @see http://php.net/strrev + * + * @author Harry Fuecks + * + * @param string string to be reversed + * @return string + */ + public static function strrev($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _strrev($str); + } + + /** + * Strips whitespace (or other UTF-8 characters) from the beginning and + * end of a string. + * @see http://php.net/trim + * + * @author Andreas Gohr + * + * @param string input string + * @param string string of characters to remove + * @return string + */ + public static function trim($str, $charlist = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _trim($str, $charlist); + } + + /** + * Strips whitespace (or other UTF-8 characters) from the beginning of a string. + * @see http://php.net/ltrim + * + * @author Andreas Gohr + * + * @param string input string + * @param string string of characters to remove + * @return string + */ + public static function ltrim($str, $charlist = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _ltrim($str, $charlist); + } + + /** + * Strips whitespace (or other UTF-8 characters) from the end of a string. + * @see http://php.net/rtrim + * + * @author Andreas Gohr + * + * @param string input string + * @param string string of characters to remove + * @return string + */ + public static function rtrim($str, $charlist = NULL) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _rtrim($str, $charlist); + } + + /** + * Returns the unicode ordinal for a character. + * @see http://php.net/ord + * + * @author Harry Fuecks + * + * @param string UTF-8 encoded character + * @return integer + */ + public static function ord($chr) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _ord($chr); + } + + /** + * Takes an UTF-8 string and returns an array of ints representing the Unicode characters. + * Astral planes are supported i.e. the ints in the output can be > 0xFFFF. + * Occurrances of the BOM are ignored. Surrogates are not allowed. + * + * The Original Code is Mozilla Communicator client code. + * The Initial Developer of the Original Code is Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer. + * Ported to PHP by Henri Sivonen , see http://hsivonen.iki.fi/php-utf8/. + * Slight modifications to fit with phputf8 library by Harry Fuecks . + * + * @param string UTF-8 encoded string + * @return array unicode code points + * @return boolean FALSE if the string is invalid + */ + public static function to_unicode($str) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _to_unicode($str); + } + + /** + * Takes an array of ints representing the Unicode characters and returns a UTF-8 string. + * Astral planes are supported i.e. the ints in the input can be > 0xFFFF. + * Occurrances of the BOM are ignored. Surrogates are not allowed. + * + * The Original Code is Mozilla Communicator client code. + * The Initial Developer of the Original Code is Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer. + * Ported to PHP by Henri Sivonen , see http://hsivonen.iki.fi/php-utf8/. + * Slight modifications to fit with phputf8 library by Harry Fuecks . + * + * @param array unicode code points representing a string + * @return string utf8 string of characters + * @return boolean FALSE if a code point cannot be found + */ + public static function from_unicode($arr) + { + if ( ! isset(self::$called[__FUNCTION__])) + { + require SYSPATH.'core/utf8/'.__FUNCTION__.EXT; + + // Function has been called + self::$called[__FUNCTION__] = TRUE; + } + + return _from_unicode($arr); + } + +} // End utf8 \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/from_unicode.php b/lib/kohana/system/core/utf8/from_unicode.php new file mode 100644 index 0000000..66c6742 --- /dev/null +++ b/lib/kohana/system/core/utf8/from_unicode.php @@ -0,0 +1,68 @@ += 0) AND ($arr[$k] <= 0x007f)) + { + echo chr($arr[$k]); + } + // 2 byte sequence + elseif ($arr[$k] <= 0x07ff) + { + echo chr(0xc0 | ($arr[$k] >> 6)); + echo chr(0x80 | ($arr[$k] & 0x003f)); + } + // Byte order mark (skip) + elseif ($arr[$k] == 0xFEFF) + { + // nop -- zap the BOM + } + // Test for illegal surrogates + elseif ($arr[$k] >= 0xD800 AND $arr[$k] <= 0xDFFF) + { + // Found a surrogate + trigger_error('utf8::from_unicode: Illegal surrogate at index: '.$k.', value: '.$arr[$k], E_USER_WARNING); + return FALSE; + } + // 3 byte sequence + elseif ($arr[$k] <= 0xffff) + { + echo chr(0xe0 | ($arr[$k] >> 12)); + echo chr(0x80 | (($arr[$k] >> 6) & 0x003f)); + echo chr(0x80 | ($arr[$k] & 0x003f)); + } + // 4 byte sequence + elseif ($arr[$k] <= 0x10ffff) + { + echo chr(0xf0 | ($arr[$k] >> 18)); + echo chr(0x80 | (($arr[$k] >> 12) & 0x3f)); + echo chr(0x80 | (($arr[$k] >> 6) & 0x3f)); + echo chr(0x80 | ($arr[$k] & 0x3f)); + } + // Out of range + else + { + trigger_error('utf8::from_unicode: Codepoint out of Unicode range at index: '.$k.', value: '.$arr[$k], E_USER_WARNING); + return FALSE; + } + } + + $result = ob_get_contents(); + ob_end_clean(); + return $result; +} diff --git a/lib/kohana/system/core/utf8/ltrim.php b/lib/kohana/system/core/utf8/ltrim.php new file mode 100644 index 0000000..556fe07 --- /dev/null +++ b/lib/kohana/system/core/utf8/ltrim.php @@ -0,0 +1,22 @@ += 0 AND $ord0 <= 127) + { + return $ord0; + } + + if ( ! isset($chr[1])) + { + trigger_error('Short sequence - at least 2 bytes expected, only 1 seen', E_USER_WARNING); + return FALSE; + } + + $ord1 = ord($chr[1]); + + if ($ord0 >= 192 AND $ord0 <= 223) + { + return ($ord0 - 192) * 64 + ($ord1 - 128); + } + + if ( ! isset($chr[2])) + { + trigger_error('Short sequence - at least 3 bytes expected, only 2 seen', E_USER_WARNING); + return FALSE; + } + + $ord2 = ord($chr[2]); + + if ($ord0 >= 224 AND $ord0 <= 239) + { + return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128); + } + + if ( ! isset($chr[3])) + { + trigger_error('Short sequence - at least 4 bytes expected, only 3 seen', E_USER_WARNING); + return FALSE; + } + + $ord3 = ord($chr[3]); + + if ($ord0 >= 240 AND $ord0 <= 247) + { + return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2-128) * 64 + ($ord3 - 128); + } + + if ( ! isset($chr[4])) + { + trigger_error('Short sequence - at least 5 bytes expected, only 4 seen', E_USER_WARNING); + return FALSE; + } + + $ord4 = ord($chr[4]); + + if ($ord0 >= 248 AND $ord0 <= 251) + { + return ($ord0 - 248) * 16777216 + ($ord1-128) * 262144 + ($ord2 - 128) * 4096 + ($ord3 - 128) * 64 + ($ord4 - 128); + } + + if ( ! isset($chr[5])) + { + trigger_error('Short sequence - at least 6 bytes expected, only 5 seen', E_USER_WARNING); + return FALSE; + } + + if ($ord0 >= 252 AND $ord0 <= 253) + { + return ($ord0 - 252) * 1073741824 + ($ord1 - 128) * 16777216 + ($ord2 - 128) * 262144 + ($ord3 - 128) * 4096 + ($ord4 - 128) * 64 + (ord($chr[5]) - 128); + } + + if ($ord0 >= 254 AND $ord0 <= 255) + { + trigger_error('Invalid UTF-8 with surrogate ordinal '.$ord0, E_USER_WARNING); + return FALSE; + } +} \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/rtrim.php b/lib/kohana/system/core/utf8/rtrim.php new file mode 100644 index 0000000..efa0e19 --- /dev/null +++ b/lib/kohana/system/core/utf8/rtrim.php @@ -0,0 +1,22 @@ + $val) + { + $str[$key] = utf8::str_ireplace($search, $replace, $val, $count); + } + return $str; + } + + if (is_array($search)) + { + $keys = array_keys($search); + + foreach ($keys as $k) + { + if (is_array($replace)) + { + if (array_key_exists($k, $replace)) + { + $str = utf8::str_ireplace($search[$k], $replace[$k], $str, $count); + } + else + { + $str = utf8::str_ireplace($search[$k], '', $str, $count); + } + } + else + { + $str = utf8::str_ireplace($search[$k], $replace, $str, $count); + } + } + return $str; + } + + $search = utf8::strtolower($search); + $str_lower = utf8::strtolower($str); + + $total_matched_strlen = 0; + $i = 0; + + while (preg_match('/(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches)) + { + $matched_strlen = strlen($matches[0]); + $str_lower = substr($str_lower, $matched_strlen); + + $offset = $total_matched_strlen + strlen($matches[1]) + ($i * (strlen($replace) - 1)); + $str = substr_replace($str, $replace, $offset, strlen($search)); + + $total_matched_strlen += $matched_strlen; + $i++; + } + + $count += $i; + return $str; +} diff --git a/lib/kohana/system/core/utf8/str_pad.php b/lib/kohana/system/core/utf8/str_pad.php new file mode 100644 index 0000000..aab4ccc --- /dev/null +++ b/lib/kohana/system/core/utf8/str_pad.php @@ -0,0 +1,54 @@ +0x0061, 0x03A6=>0x03C6, 0x0162=>0x0163, 0x00C5=>0x00E5, 0x0042=>0x0062, + 0x0139=>0x013A, 0x00C1=>0x00E1, 0x0141=>0x0142, 0x038E=>0x03CD, 0x0100=>0x0101, + 0x0490=>0x0491, 0x0394=>0x03B4, 0x015A=>0x015B, 0x0044=>0x0064, 0x0393=>0x03B3, + 0x00D4=>0x00F4, 0x042A=>0x044A, 0x0419=>0x0439, 0x0112=>0x0113, 0x041C=>0x043C, + 0x015E=>0x015F, 0x0143=>0x0144, 0x00CE=>0x00EE, 0x040E=>0x045E, 0x042F=>0x044F, + 0x039A=>0x03BA, 0x0154=>0x0155, 0x0049=>0x0069, 0x0053=>0x0073, 0x1E1E=>0x1E1F, + 0x0134=>0x0135, 0x0427=>0x0447, 0x03A0=>0x03C0, 0x0418=>0x0438, 0x00D3=>0x00F3, + 0x0420=>0x0440, 0x0404=>0x0454, 0x0415=>0x0435, 0x0429=>0x0449, 0x014A=>0x014B, + 0x0411=>0x0431, 0x0409=>0x0459, 0x1E02=>0x1E03, 0x00D6=>0x00F6, 0x00D9=>0x00F9, + 0x004E=>0x006E, 0x0401=>0x0451, 0x03A4=>0x03C4, 0x0423=>0x0443, 0x015C=>0x015D, + 0x0403=>0x0453, 0x03A8=>0x03C8, 0x0158=>0x0159, 0x0047=>0x0067, 0x00C4=>0x00E4, + 0x0386=>0x03AC, 0x0389=>0x03AE, 0x0166=>0x0167, 0x039E=>0x03BE, 0x0164=>0x0165, + 0x0116=>0x0117, 0x0108=>0x0109, 0x0056=>0x0076, 0x00DE=>0x00FE, 0x0156=>0x0157, + 0x00DA=>0x00FA, 0x1E60=>0x1E61, 0x1E82=>0x1E83, 0x00C2=>0x00E2, 0x0118=>0x0119, + 0x0145=>0x0146, 0x0050=>0x0070, 0x0150=>0x0151, 0x042E=>0x044E, 0x0128=>0x0129, + 0x03A7=>0x03C7, 0x013D=>0x013E, 0x0422=>0x0442, 0x005A=>0x007A, 0x0428=>0x0448, + 0x03A1=>0x03C1, 0x1E80=>0x1E81, 0x016C=>0x016D, 0x00D5=>0x00F5, 0x0055=>0x0075, + 0x0176=>0x0177, 0x00DC=>0x00FC, 0x1E56=>0x1E57, 0x03A3=>0x03C3, 0x041A=>0x043A, + 0x004D=>0x006D, 0x016A=>0x016B, 0x0170=>0x0171, 0x0424=>0x0444, 0x00CC=>0x00EC, + 0x0168=>0x0169, 0x039F=>0x03BF, 0x004B=>0x006B, 0x00D2=>0x00F2, 0x00C0=>0x00E0, + 0x0414=>0x0434, 0x03A9=>0x03C9, 0x1E6A=>0x1E6B, 0x00C3=>0x00E3, 0x042D=>0x044D, + 0x0416=>0x0436, 0x01A0=>0x01A1, 0x010C=>0x010D, 0x011C=>0x011D, 0x00D0=>0x00F0, + 0x013B=>0x013C, 0x040F=>0x045F, 0x040A=>0x045A, 0x00C8=>0x00E8, 0x03A5=>0x03C5, + 0x0046=>0x0066, 0x00DD=>0x00FD, 0x0043=>0x0063, 0x021A=>0x021B, 0x00CA=>0x00EA, + 0x0399=>0x03B9, 0x0179=>0x017A, 0x00CF=>0x00EF, 0x01AF=>0x01B0, 0x0045=>0x0065, + 0x039B=>0x03BB, 0x0398=>0x03B8, 0x039C=>0x03BC, 0x040C=>0x045C, 0x041F=>0x043F, + 0x042C=>0x044C, 0x00DE=>0x00FE, 0x00D0=>0x00F0, 0x1EF2=>0x1EF3, 0x0048=>0x0068, + 0x00CB=>0x00EB, 0x0110=>0x0111, 0x0413=>0x0433, 0x012E=>0x012F, 0x00C6=>0x00E6, + 0x0058=>0x0078, 0x0160=>0x0161, 0x016E=>0x016F, 0x0391=>0x03B1, 0x0407=>0x0457, + 0x0172=>0x0173, 0x0178=>0x00FF, 0x004F=>0x006F, 0x041B=>0x043B, 0x0395=>0x03B5, + 0x0425=>0x0445, 0x0120=>0x0121, 0x017D=>0x017E, 0x017B=>0x017C, 0x0396=>0x03B6, + 0x0392=>0x03B2, 0x0388=>0x03AD, 0x1E84=>0x1E85, 0x0174=>0x0175, 0x0051=>0x0071, + 0x0417=>0x0437, 0x1E0A=>0x1E0B, 0x0147=>0x0148, 0x0104=>0x0105, 0x0408=>0x0458, + 0x014C=>0x014D, 0x00CD=>0x00ED, 0x0059=>0x0079, 0x010A=>0x010B, 0x038F=>0x03CE, + 0x0052=>0x0072, 0x0410=>0x0430, 0x0405=>0x0455, 0x0402=>0x0452, 0x0126=>0x0127, + 0x0136=>0x0137, 0x012A=>0x012B, 0x038A=>0x03AF, 0x042B=>0x044B, 0x004C=>0x006C, + 0x0397=>0x03B7, 0x0124=>0x0125, 0x0218=>0x0219, 0x00DB=>0x00FB, 0x011E=>0x011F, + 0x041E=>0x043E, 0x1E40=>0x1E41, 0x039D=>0x03BD, 0x0106=>0x0107, 0x03AB=>0x03CB, + 0x0426=>0x0446, 0x00DE=>0x00FE, 0x00C7=>0x00E7, 0x03AA=>0x03CA, 0x0421=>0x0441, + 0x0412=>0x0432, 0x010E=>0x010F, 0x00D8=>0x00F8, 0x0057=>0x0077, 0x011A=>0x011B, + 0x0054=>0x0074, 0x004A=>0x006A, 0x040B=>0x045B, 0x0406=>0x0456, 0x0102=>0x0103, + 0x039B=>0x03BB, 0x00D1=>0x00F1, 0x041D=>0x043D, 0x038C=>0x03CC, 0x00C9=>0x00E9, + 0x00D0=>0x00F0, 0x0407=>0x0457, 0x0122=>0x0123, + ); + } + + $uni = utf8::to_unicode($str); + + if ($uni === FALSE) + return FALSE; + + for ($i = 0, $c = count($uni); $i < $c; $i++) + { + if (isset($UTF8_UPPER_TO_LOWER[$uni[$i]])) + { + $uni[$i] = $UTF8_UPPER_TO_LOWER[$uni[$i]]; + } + } + + return utf8::from_unicode($uni); +} \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/strtoupper.php b/lib/kohana/system/core/utf8/strtoupper.php new file mode 100644 index 0000000..f3ded73 --- /dev/null +++ b/lib/kohana/system/core/utf8/strtoupper.php @@ -0,0 +1,84 @@ +0x0041, 0x03C6=>0x03A6, 0x0163=>0x0162, 0x00E5=>0x00C5, 0x0062=>0x0042, + 0x013A=>0x0139, 0x00E1=>0x00C1, 0x0142=>0x0141, 0x03CD=>0x038E, 0x0101=>0x0100, + 0x0491=>0x0490, 0x03B4=>0x0394, 0x015B=>0x015A, 0x0064=>0x0044, 0x03B3=>0x0393, + 0x00F4=>0x00D4, 0x044A=>0x042A, 0x0439=>0x0419, 0x0113=>0x0112, 0x043C=>0x041C, + 0x015F=>0x015E, 0x0144=>0x0143, 0x00EE=>0x00CE, 0x045E=>0x040E, 0x044F=>0x042F, + 0x03BA=>0x039A, 0x0155=>0x0154, 0x0069=>0x0049, 0x0073=>0x0053, 0x1E1F=>0x1E1E, + 0x0135=>0x0134, 0x0447=>0x0427, 0x03C0=>0x03A0, 0x0438=>0x0418, 0x00F3=>0x00D3, + 0x0440=>0x0420, 0x0454=>0x0404, 0x0435=>0x0415, 0x0449=>0x0429, 0x014B=>0x014A, + 0x0431=>0x0411, 0x0459=>0x0409, 0x1E03=>0x1E02, 0x00F6=>0x00D6, 0x00F9=>0x00D9, + 0x006E=>0x004E, 0x0451=>0x0401, 0x03C4=>0x03A4, 0x0443=>0x0423, 0x015D=>0x015C, + 0x0453=>0x0403, 0x03C8=>0x03A8, 0x0159=>0x0158, 0x0067=>0x0047, 0x00E4=>0x00C4, + 0x03AC=>0x0386, 0x03AE=>0x0389, 0x0167=>0x0166, 0x03BE=>0x039E, 0x0165=>0x0164, + 0x0117=>0x0116, 0x0109=>0x0108, 0x0076=>0x0056, 0x00FE=>0x00DE, 0x0157=>0x0156, + 0x00FA=>0x00DA, 0x1E61=>0x1E60, 0x1E83=>0x1E82, 0x00E2=>0x00C2, 0x0119=>0x0118, + 0x0146=>0x0145, 0x0070=>0x0050, 0x0151=>0x0150, 0x044E=>0x042E, 0x0129=>0x0128, + 0x03C7=>0x03A7, 0x013E=>0x013D, 0x0442=>0x0422, 0x007A=>0x005A, 0x0448=>0x0428, + 0x03C1=>0x03A1, 0x1E81=>0x1E80, 0x016D=>0x016C, 0x00F5=>0x00D5, 0x0075=>0x0055, + 0x0177=>0x0176, 0x00FC=>0x00DC, 0x1E57=>0x1E56, 0x03C3=>0x03A3, 0x043A=>0x041A, + 0x006D=>0x004D, 0x016B=>0x016A, 0x0171=>0x0170, 0x0444=>0x0424, 0x00EC=>0x00CC, + 0x0169=>0x0168, 0x03BF=>0x039F, 0x006B=>0x004B, 0x00F2=>0x00D2, 0x00E0=>0x00C0, + 0x0434=>0x0414, 0x03C9=>0x03A9, 0x1E6B=>0x1E6A, 0x00E3=>0x00C3, 0x044D=>0x042D, + 0x0436=>0x0416, 0x01A1=>0x01A0, 0x010D=>0x010C, 0x011D=>0x011C, 0x00F0=>0x00D0, + 0x013C=>0x013B, 0x045F=>0x040F, 0x045A=>0x040A, 0x00E8=>0x00C8, 0x03C5=>0x03A5, + 0x0066=>0x0046, 0x00FD=>0x00DD, 0x0063=>0x0043, 0x021B=>0x021A, 0x00EA=>0x00CA, + 0x03B9=>0x0399, 0x017A=>0x0179, 0x00EF=>0x00CF, 0x01B0=>0x01AF, 0x0065=>0x0045, + 0x03BB=>0x039B, 0x03B8=>0x0398, 0x03BC=>0x039C, 0x045C=>0x040C, 0x043F=>0x041F, + 0x044C=>0x042C, 0x00FE=>0x00DE, 0x00F0=>0x00D0, 0x1EF3=>0x1EF2, 0x0068=>0x0048, + 0x00EB=>0x00CB, 0x0111=>0x0110, 0x0433=>0x0413, 0x012F=>0x012E, 0x00E6=>0x00C6, + 0x0078=>0x0058, 0x0161=>0x0160, 0x016F=>0x016E, 0x03B1=>0x0391, 0x0457=>0x0407, + 0x0173=>0x0172, 0x00FF=>0x0178, 0x006F=>0x004F, 0x043B=>0x041B, 0x03B5=>0x0395, + 0x0445=>0x0425, 0x0121=>0x0120, 0x017E=>0x017D, 0x017C=>0x017B, 0x03B6=>0x0396, + 0x03B2=>0x0392, 0x03AD=>0x0388, 0x1E85=>0x1E84, 0x0175=>0x0174, 0x0071=>0x0051, + 0x0437=>0x0417, 0x1E0B=>0x1E0A, 0x0148=>0x0147, 0x0105=>0x0104, 0x0458=>0x0408, + 0x014D=>0x014C, 0x00ED=>0x00CD, 0x0079=>0x0059, 0x010B=>0x010A, 0x03CE=>0x038F, + 0x0072=>0x0052, 0x0430=>0x0410, 0x0455=>0x0405, 0x0452=>0x0402, 0x0127=>0x0126, + 0x0137=>0x0136, 0x012B=>0x012A, 0x03AF=>0x038A, 0x044B=>0x042B, 0x006C=>0x004C, + 0x03B7=>0x0397, 0x0125=>0x0124, 0x0219=>0x0218, 0x00FB=>0x00DB, 0x011F=>0x011E, + 0x043E=>0x041E, 0x1E41=>0x1E40, 0x03BD=>0x039D, 0x0107=>0x0106, 0x03CB=>0x03AB, + 0x0446=>0x0426, 0x00FE=>0x00DE, 0x00E7=>0x00C7, 0x03CA=>0x03AA, 0x0441=>0x0421, + 0x0432=>0x0412, 0x010F=>0x010E, 0x00F8=>0x00D8, 0x0077=>0x0057, 0x011B=>0x011A, + 0x0074=>0x0054, 0x006A=>0x004A, 0x045B=>0x040B, 0x0456=>0x0406, 0x0103=>0x0102, + 0x03BB=>0x039B, 0x00F1=>0x00D1, 0x043D=>0x041D, 0x03CC=>0x038C, 0x00E9=>0x00C9, + 0x00F0=>0x00D0, 0x0457=>0x0407, 0x0123=>0x0122, + ); + } + + $uni = utf8::to_unicode($str); + + if ($uni === FALSE) + return FALSE; + + for ($i = 0, $c = count($uni); $i < $c; $i++) + { + if (isset($UTF8_LOWER_TO_UPPER[$uni[$i]])) + { + $uni[$i] = $UTF8_LOWER_TO_UPPER[$uni[$i]]; + } + } + + return utf8::from_unicode($uni); +} \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/substr.php b/lib/kohana/system/core/utf8/substr.php new file mode 100644 index 0000000..daf66b8 --- /dev/null +++ b/lib/kohana/system/core/utf8/substr.php @@ -0,0 +1,75 @@ += $strlen OR ($length < 0 AND $length <= $offset - $strlen)) + return ''; + + // Whole string + if ($offset == 0 AND ($length === NULL OR $length >= $strlen)) + return $str; + + // Build regex + $regex = '^'; + + // Create an offset expression + if ($offset > 0) + { + // PCRE repeating quantifiers must be less than 65536, so repeat when necessary + $x = (int) ($offset / 65535); + $y = (int) ($offset % 65535); + $regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}'; + $regex .= ($y == 0) ? '' : '.{'.$y.'}'; + } + + // Create a length expression + if ($length === NULL) + { + $regex .= '(.*)'; // No length set, grab it all + } + // Find length from the left (positive length) + elseif ($length > 0) + { + // Reduce length so that it can't go beyond the end of the string + $length = min($strlen - $offset, $length); + + $x = (int) ($length / 65535); + $y = (int) ($length % 65535); + $regex .= '('; + $regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}'; + $regex .= '.{'.$y.'})'; + } + // Find length from the right (negative length) + else + { + $x = (int) (-$length / 65535); + $y = (int) (-$length % 65535); + $regex .= '(.*)'; + $regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}'; + $regex .= '.{'.$y.'}'; + } + + preg_match('/'.$regex.'/us', $str, $matches); + return $matches[1]; +} \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/substr_replace.php b/lib/kohana/system/core/utf8/substr_replace.php new file mode 100644 index 0000000..45e2d2a --- /dev/null +++ b/lib/kohana/system/core/utf8/substr_replace.php @@ -0,0 +1,22 @@ + 0x10FFFF)) + { + trigger_error('utf8::to_unicode: Illegal sequence or codepoint in UTF-8 at byte '.$i, E_USER_WARNING); + return FALSE; + } + + if (0xFEFF != $mUcs4) + { + // BOM is legal but we don't want to output it + $out[] = $mUcs4; + } + + // Initialize UTF-8 cache + $mState = 0; + $mUcs4 = 0; + $mBytes = 1; + } + } + else + { + // ((0xC0 & (*in) != 0x80) AND (mState != 0)) + // Incomplete multi-octet sequence + trigger_error('utf8::to_unicode: Incomplete multi-octet sequence in UTF-8 at byte '.$i, E_USER_WARNING); + return FALSE; + } + } + } + + return $out; +} \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/transliterate_to_ascii.php b/lib/kohana/system/core/utf8/transliterate_to_ascii.php new file mode 100644 index 0000000..07461fb --- /dev/null +++ b/lib/kohana/system/core/utf8/transliterate_to_ascii.php @@ -0,0 +1,77 @@ + 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o', + 'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k', + 'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o', + 'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o', + 'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c', + 'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't', + 'ū' => 'u', 'č' => 'c', 'ö' => 'o', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l', + 'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z', + 'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't', + 'ŗ' => 'r', 'ä' => 'a', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'u', 'ò' => 'o', + 'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j', + 'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o', + 'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g', + 'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a', + 'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e', + ); + } + + $str = str_replace( + array_keys($UTF8_LOWER_ACCENTS), + array_values($UTF8_LOWER_ACCENTS), + $str + ); + } + + if ($case >= 0) + { + if ($UTF8_UPPER_ACCENTS === NULL) + { + $UTF8_UPPER_ACCENTS = array( + 'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O', + 'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K', 'Ĕ' => 'E', + 'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O', + 'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O', + 'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C', + 'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T', + 'Ū' => 'U', 'Č' => 'C', 'Ö' => 'O', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L', + 'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z', + 'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T', + 'Ŗ' => 'R', 'Ä' => 'A', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'U', 'Ò' => 'O', + 'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J', + 'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O', + 'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G', + 'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A', + 'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', + ); + } + + $str = str_replace( + array_keys($UTF8_UPPER_ACCENTS), + array_values($UTF8_UPPER_ACCENTS), + $str + ); + } + + return $str; +} \ No newline at end of file diff --git a/lib/kohana/system/core/utf8/trim.php b/lib/kohana/system/core/utf8/trim.php new file mode 100644 index 0000000..7434102 --- /dev/null +++ b/lib/kohana/system/core/utf8/trim.php @@ -0,0 +1,17 @@ +)Tt-1e7&nrj4#POgFbGNC_g8gqAnG{J_dU;i&%A$pw{p5pS65e` zI(6#QsZ-S*LJ1)r9AuK)qsNf`{ob&>MF{PP)FwTJz>9qv;9~eJo##EvqkltRLTgOkDJ8pq<*G`-V z3A^digwio3f6eNYPT0nHTyHx83HFyfFX4P3&eJDMo;fFOWY6z#K9i6ZO(&L4pE9br zwkgrS@@z9UPT#fk^E8tFm zL_CB^4-hIXl{Nu;TzVY%6Vg+_w@6O|e@5B{{5k1);M=90z+aGd0e?|C0Q{hI2>6@Q zQQ+_CUlOW+rGG`3{!2Yx_Pn7dj=cx>$Fc7XBlvMpUw#xR{lsyAI1cVR80murKI8^|?+}sm zXHR3i9f^1HnCTNq;^c{wCz4={MqV>sHx7)LKxI5p#d*A_50#b(4p5&;DD{$B9NVH* zl1O{fiF6}<$UxM5Bq=5n$P_Y@RFXyHUb2)tMAniGWHZ@Hs>p8g3VEHpP2MNR2sMaW zB97z4(fg}o&tIjy&r>u!ANNM@iXJD4l;|;lW&zv*P)H z7I~YzQ{E%*mk-JB$REm|$fxD6DuL`)n+5UUAt3TqAk}}YwNU4INzde({^fmwEfy4?H%ny z4YH^~7B$GC23gb~i`oV4vWb{flhx!l#hX%0=_W{?Dc1zKGj%j|G4(PHFbx4d0#F1P z2bcty4wwU20Js})KVT(b4FKbe=?TCyfad|b0DA!k0fzxc0UrTA1$+*u27Cwj9&iy* zM~GPhm;iQw7mx@D0x|(PfIL8ZKqo*qKp((Bz)-+QKrvtfV2XLBxzfDIe6M+_`62UK z^9H1C25dD~nRlCCF~4qp+x))ynE5mFm*!gYIr9(ZOJ+ltbzOJre!YpFsyEeJ>TUE6 zdRXtF_tOXI!}MGA61`lXs?XMM*YDJq=*#uh`Z|4+zD3`r@6`9``}ITmJNk$EC;DlO zPT%O~^$YrC3$dsctHo`Jx1?CoEzK;smbR9T7^Qky23UqzMp%k0<1CXb(=Br>3oLhA z?zgP8tg)=OJYjjp^1Nl2Wv}I+<*?Hf0ZEPKEVOtMdKieSNFx#!R z5?i@#s%^IIcH5n{CAQ_Z)wXrEO|~tzZML1ZJ+}R}L$-Gav3+R!#CF>Dwe1_=kTu%{ z0%azhQC{Xpfu9xlS&p;oInJ*CWx8}u5b|xr|@(+MWmk;`A-V`ae+TB@FN00BJe^PT3IUOIPIl! zs-pQPi1Z1tZ74e-(nTKWR*`-4?D@rVNn_ei87-!H_*fHdXuNqUc4Mh(9cc?ylFID&|??(qMsvYp`agqANhNU z^g#meBJeI8XB8Z06~9cEI*L3UMfom)yF{KpX%kV}DQyP0y+iPPhbSi|Z#+Ni%=5&K zjoO{vBhoj>uq4?AqM)2u?f6|(P#EQyBsd_SQeMDQPDL)`C~+EOQJ1Ujg*KA@#A%31 zd#to*FW4j6dPDRmD2z(@c;yY;CCZP=o)nd|DBq%z_PBBod7>PM%1o34EktQ8L}{X4 z4ZTTlsgZ<4>k@5oDSB@sS(QEz{QN-hvymJ!A5UjKkuKV_fj=UDj8_8pMvo$Aj=-VC zL33mLm`Fdy(;L$hlgXjtYOG~Nt2J&Z(VDTo|ELxZsx(peFT_#k5ILqLIIm*bAj*>{ z|EmR`mnxWXu7)xBmo9Le9uw)ueubY9=_f?`Zh`L>_a=#Z zlLVe8@H~!_2**i8^0X3pG8)x)nMhwI z=n*|J$_M%vk*AQ;EE6uhym-zfkw1guaz~Ngk>ic&ks6JajEekJ z+`)1A4z9gfqx7GR-NOWLg)Kq5@%+&-QCcg~*NQSf7U|D&TzWvHKOpd~Je>;LL)s$J zxA1z!%K4G!q4RkgMf1=ZqPG>_bqmm~KS=EhKldJJ=oMUbckYM;5aO*fMe-dx$+mma>Q0!(^M74HpxZuO!Bz8McqPntM91qkeAf=)c439 z^+WX|^0InN{e--teyV;-4q#UL9XY5U*H4i*^@yc8Ig0s7SMrmkyQLSog7z~B-yIQN zJD>2^B?wPlity2;3h!JC;X5f1zLU1(28cf&)T{tE0Cx6o_&5k!m+-Nk4gd@RV9rU4 z0OJ6Y0Mh|;01F^ z2f(*P>(GlNfC*kBJ7O;&5fB7qA`RAxlm}=J=mfx=Q^K56!kklrT`ghGDHQ`I0Hy$D z0xAKE0QU-S3VI5>IR7h0ND_b6^lL}nTMZokZ$HNP6Qw-LE8y@#{X6(3CA8-rQEw-I z8-~{rZ{FtpBs)wNeF_!Ri0Z4^PkJ6#VjcjlN%A z`8S{cjMx9>vj2^@jof=|LwhziTn=qLGDi?u_MA?x_{BKY3V9pnM)}ux z_{$<(26f7=C&QKw_}JUnIp_3yW(hId&Zu}@r7UA_nQe+`Sm5^l1OW8 zlm0r>zexF?>C0a|y^uu1zj$KfOIN)>jT8S{I3IB_k9>&~{#Ro!q%&r7{I?z?k-^wo z>BPEQI)X$p5Ew?@O!ySD5ERlBL4{{A8@qR#A(%)D1T$%gpo{r~g|tSnk~{<($w#nb z1*8pekOBlJX^Y?@?GW5p6KRhfvz)75tc-LZKCFyfNBmeB=}6+RigG>ndGB#{FMDdZqRh`ff7f<2ngl#ZgTzHsX)2DHG?S#$T$+o0-R)>Ql0iGr4kV6t zrkzQ=R3?>?Om&8eJt5e&R|$N9x`1S1|K1|f6nlx!kOb@wy$*CrWD#1&fmY{jFQIi@ zX!T^&RTgrf2nkR{duyV-O`>(pqAhjNmKM>LR?(I=(Ux}6mJZRDPOOG?L#aIw+@vRh zhx9`5iq`dE&8!bn`XTs9e}p)4BSJiO?fwpJ&s#kak~tXdF$BRAlYpVnKgr}~gcLFi zApn^ej#eCj5E7D+DkLKfD{-Sx6D}W$kdF)@AF7ZBvycX}kOr%e1}Av}A(K3bkcHjB zPXm7jp()nvo`vLZMQBF;fY2QKVxI%P3n7QRh|mK2i1z^J($kXc!(Q1|LWXjM^yCWZ zX-(ch$P+Tun!JgSCnTvgc?%&=$dgKrAY==v(u7oLLaJ2q0YWx8j*w4IAmo#i2>Ij` zLO%HuLUZytf+nO*!>-(~fmb7F)K2XQzvx-cTpE`H+2K|P!Dh}e`e~#YGfNB ze+5GF3WVh8G(9B zs4gVei$37ftMwYlE+yk2`{~eknP~H-;BYgvWlOYPYqUr{^j86-y&ZBELb|VmR9_F- z9RSI^Nob;5AZd4!yU5+-9!S{|$k+Yk0gQ;tpnFz9&K@Rf#47MQ$k}@GduX1G&^S9G zH!nhBUV_Z*g`6COl)MhPI1Cwh2d(}-G{{HL9bZCYM4&4ebc7eWAr3kr2`!Qej^~1} z9cX8%41K*4^;@K$L9fOt7(gcmR+4}HF2E4+E~~(@n*nO@n%4Ycr&0xycsZ6ycsZ6ycsZ6ycsZ6ycsZ6 zyctj;-V9hUoTh0NNx$8^yfPj%O3;RU{{a)4m65&(Oq5H7PGykNwMbb< z9>M&LIC5K%3Ejhl z?qNdrFrj-G-pRoGI^-Mz!y5wUar_>EiP}=~0|LWa0~c_-h``7t1V*mFE@V`r8jgH? zWYmgvb|y3#6FQ6u?Zt%NVq)B6G@iyI4<9!fZ9<#in1U5~MuQaZ7YXgfgx+F8V=>y4 zHbr_f+6>1WnuB9Y+7d^u!x+t@c{sMAZE)n8j0qja(Ce-Pemw=Z#hAAxT~LD zjq`rEDkCL|HRR_xb@T{+4R1I>f;sk043n^%@7Xz66>jJ+3O>@B|m zd3E%UWzuqKh4hfLN?I*FBCVAki{3$gq(AWe9hUC&2Z8sn;Jq6>jrX*_fvf$%!PRVy zd=|Y2eO6AyZVTuFj3STXG$k6d6J(r(ogI>@GQ5EyNir%E8AN`%qRS+R`^dm?-AhQA z1S1jEYk288Z8AMmM99W3PVlSvas9%z3iep=Hc?7I1%9?kNaYx04pi}US;77b+6Rdm zGz}pO=*x6Jy(lF~A*qYhU3yu1jkmq@vGj@bx%91co^@tj*^StjGltD#mDpW#KU>Nk zXYaGGWmmElLncOk?mgLgp zImz>q?@4|s`9MmGl)forQyxosGUe5j4^mF1oK5*D;0q)Nx(E6PZVn6&+!7cSm><{` zI28Cea4PWEz=ePj^aV46t%Dtcor1lCCBbRI<-yg#Ex~QU?ZF+v7eg#$4%tKgP+}-K zlp0D8WrdoDdWZUk?oK7Ca;iDin(9jprnX4EKDBFVuhg4T$E22~E>7K^`evGxW=V6U zC8UMYGSZr+%};wi?Su3*OiDUt_RJigS&{X4)|Xk|W-rYCb2EFhR?QQ0Cgt4LGQMTY zi*H{1(wE>Rxys9#f|qxL zm&@6c>_hgwT#Pq%rprs^mGTC8tGrh}D8D7YD}UhJ>%xMSV!X@@H4AkFF9(NKrb?-5swLHt z8kd@u+CH@lcsVe&D77T@&eWxXm!>plT6|itF)v~Cw9o9ES(I5Oc==7%_u!=!yd*i} zb7nQ-B{4|kC(g^rnaJyr*CGca2O_UV_C;QfY>zx2*&2B!@>Jx>$P`i9} zp6zkA``Pf>HfQtC=AF$sn{+neth4q??d96NwR>uJ)mGJRtKD3?zIJu({k4l~D{JS} z&aRzVJH2*V?bO;T5TTq){n^zmE zZBm<9n@}59^KQ-Inm1}*t=U)ea?Oi1yJ}vj*-`U&&8C`1YnIn6t65s}K+SzMOKR?| zxxHpi&CHs~HDhbW)O4@8p(dyL`|3YepRN9?`c(C&)t^+~Sv{ya@5~ox*w;tDe&_3* zU+?&8(N|r*y6&rjFW>oc>zDU`vG?;SpN~6z`1B5MlGo|AJI+|YvvB?V|Ns779Kh~7 zyjNw46}J^}5U>Ei_3kF<)Rz%s{~Fx~*blfJa1d}2um}Kelaz!Q-WDkZ5CVP*aXO$2 z@GlT|j{@IlCJh9jOp5*>p-kyDKpEgL0DBFjseq#~;Ctmh1Yl)L!fKcFNet#9{uJ;z zfbXUI67VhH4gmab0<7dl{T9UVEhh(nk3yUS;B_rRoD1j(d@SNl0OXaYA_gCl!3TLc z;@bdofIozIUKHfji0_Gl{4nCj052iW8pM#PhtFQ7mhzA1j zOa=8ynE=53N<3oJHwEpa^h3N2@G5Yg7c!Xwz9^t8E7qfA0v4LA#Y3gRCC;G2TB zLRCq?2OP2zK)C_bUs;Jb2Fkew#L5ybvz)R(I#KWVYyo30bC@5&30C>ki zIf@wa5||GhavN9#*aiF?Vzhk#?W=|mgXREaQ_V&E3E&iP@Hp@%z+ZuPLkyY&7l7m0 zfr|hGINA@A z1o)$f%K_7XZ$vy3fVNeiMhw0L(Vi;m9^4WI^)1BUKL_<~#M`5w9zl$EvpA^WPZ0GE zz6c!r2}uA396Sj@9yzFJvycs72mT>q)G6c#{t@B?KqByCh?AqBf={8;D5xh8r$+%h zpGgQj2xTGvNyOkos5x-(G=#c`czwaw5af%4`e($00e1sOyM$0j6ic)e#Go@(2EGEZ z3ILtjLx?Q^D{$~F)d2vl+FHcme<~V81K(2904;z&i?}`Ddf?zeY8OCP;Cm56t~h9r ztJHyjn}ENHxCk%?_#24PCaLIO+M9^)1S|#)o~JGafY%y$n98pKw7(IO2AVl&ke4(Q z0JLg9B6b2?!2f|5a-IgBYCjPcQg2y*%{CiIQW=Z1Q-w8jkpX@0UT|d^>`G_pegIi zD40_be*^dydGL&^?+M9X2pkW}M*DHlAzRJRCe0u}`fkLnqM*M_;3fp1Y#lt$!83Cv z0Y8p-7T`AEkd2n$2?zai#4V$se?iE_H>03~mWzLk0=`s1Esc}hWP5GUm&;{Kkf}uFo)HM2`d~r z{4-Xp8rb0}cfyzLh9BBXe8dlLbv(S(i3I+6!oB7J5`_Obm8AW`p9ph0=2Oi57hc6q z*tH$TI|W@xSNP1k!(-kPp7P$93-%SW)&ZDnbHDf?_``?5`#2QyEog&8`cAYG<_o5)~ zdKZ4Vz2G}az_`chA0#~ZT~K--aQ!5`i)^OHv5LBk%z$Em89;UAIA|#+#maFJzK5Tg zKbfbME5}tYXemcMUjb#Cqvem=oONnyhi$HeN-z|wfT@o ziOgg9be)lSlcZ-$Uy{H?~ z1`opn@W+$!wC>$74Dpsi%VS2%c)g4@@;GHPaE&B}t*|fEx2Q=OCCQ}Kp=0M-6X&sW z$Ij(?Tp?FR$Q2qVle!r!sjkLYquDS0FkQ_Cx8ovbq!8N70u3=a>~^p*<|1pc+fJP} z73#z3b{;x*sP2&SJW8v+P5c8!K z(71ku?FI~JSJ+RcQnz^%+7B4ezTJTS%2Rdk*43fDN7z=W2DC=&Yf-37icPXgB$M;l z>0?Jh;f0Pz^Kz*x4K+@4(Fq%+CL5LG^~a^=90d0^pvT53`%y-K+#GJ3Y*xmSIFDnj zlw`q2KN4(`&lN~%l9U(+%BUh)<2^2?-DWkLG*xEArn~icDd@a#^pGpA5Pw)K>UbzG z?-)Ng&qpDb!gpk$Ax}Po%R@jKDhMbD36R}J?GT#WaU4w?zpae6F`gPkI~bdQ8#NQQ zjx*k+BL^9W=-3JD9%Cn4Y>c5BjWO$tosSyDbOVP+>40@~BkIG*^Tx;WWb`T(n!Ys| z7cNw7-b^{IoKP@BD@{sHY?V`#m#PO_CVH4=CQjYX)SxLlC!-1cc&a^4 z%5z>gbnZ}G-m&U)&hyT{#GyL8$$8bzht>J zs4G8(#<^M|t!+D3zKfrvwWL`<(7GC0q9v7fPP=XP^pf$@%cdH|ljOB)YWJQ#R8qQc z_+;z-voF5+&BrB0?|0Luj2=2CAU&p)4I5YmVGa4LNoH&FBxY@GY2&p4A}N;D{%mrg<8j(|3oBEggE(*s*NK&0|Z3 z4lN#g(}unKe!pq&zSOmKBi1HucxB(ljW6$2R&9BB)iY18Uj1}^+A|NYdiv>AtDhZl zdf&cNr}n*aO8WArA646_eXo9Y>Xp5xgj%na-4W*`DXNwdWFZjB^HoOGY7QSo9b>LH9Uceet}3 z9G{%e!zJ*v5WgrJ?SDZJ(wwn~GgY9&Q!}t!5@oCs%Cgh6AmO4V1Pm%eNLQL*eH`sX z+octRd}(&7#pTO`>i6D!bM3ZqFG?>M759~$zuz#7j~;z2Key)1t}o1(W?wXA{Gx7? zB)R*I`Yw8Mn``XgZGS#1l@54u+?KC;KKbCVq15#CJ!ea=pW9{QzSLC1m^gLXi0kK0 ztN(J~%ViTM-uZRWOWaC>9-3KGM1Lm zlaq_fjfKXO#%5z-Ihq`0KZvsDi?Wl#R*e$VG`q#65!voMb|{ale^Iojpsm~Gl(Gu^ zJbG~5;>GJOT)JeuR$NZ+pd;xhdPjNjWFyO1Z~WfK66J=l%J2nb$whjHn>%e5-K@zN z0d=d1DK4wM%#F`4S#`y%xf}{!_r@pLWQ*CRxt&}Mo(4cQLQQ~x3phWNhgQzTOT$`* zC(WZ|wV>@3md`TS7sgz=xSz2ZU#l@T_oIuAx&7!!oY0Z-@!c=aK55)V=bxPY(w^H+ z;*ILNPDbmDNI3;Bf`x>_4x+K?W~!KEVwH5&%Aa4?@eqXWSVzQY3+P`y7!-tD7&=wECJzlhx%4|em88Fj`3aY*wNXsU3%4Dppu~w)LZ=RzueRc%;>qifeb%Hc=juhjM91?n`u=P!#7#**VeqsrK3JZDsmrEBqq zcm-W+OfVia9x^5feqF{ucL6l$WKOt=T!IxXR-!8XnJQC7Ei=&>1fqyuXhD0yRzdrp z%e!#M1yv)eCquEwTwC|8(uWLt6>JZq^WfW0k%R4B?b;6yn}Z}sTbWzw@+jo7h&+*l z(L5w9@^BGS3NrE`Q8bOp#>aHh{S?b9pS^L{xyzNY{`dfVT?0U86Vg8%vU-WbMrKMS ziKR-J?KYR!W{o2{jZ;l_-AUb+WONR0o;lBRjmQV+M@e*Kj3K^(5_F*Z-8ht^!V|B0GGt*rfR~m3+&m^Up zr3`~X^I(cOIW1c!X(~RqX7%dCEj1T<|0?NRkkIyZ=bVRyqA$$#aB8__r*R8F4y9&h zaT6grPBy0nQ3SMWX>ZLsaqFpzTi5S-*Enljn)St$srvI99^J9KYINTA?JE~Ae%Llu zS(DT9)n^vJ7)(6zhd+LimrqkyuHLb(>cw#nK6KXuixxme;g683P!GNnY-2b>DlzM3 zTB7Ub{#3V;8FmQw484p=+*Wkin8RX{+|CP77F=7nIPa_LIv(qIE-xl9ke2B9zO$8? z(owsE=AbQTXHntkTV)+`OW!IRKRAZm0(o)^S#e{69hH@Eyah}7?P+f+tCC-8s<)Ne z>pi7jx`u6C)MajHK`u-oSHASFA+g={!@jSdDJ?%tlZ`Xq)5|QeuGUb?X~txBp-!J@ zz_mfi^JuTR=+go6TsVWN$#W7*Rp(4cskaoxZ;?VCWAt-l&O? z@t;ncW`1(jhON(T9C2U4Q04e$V@P_sap9Z482{j{zkJPyZ@m6NxT{!dAoqbMYtZ%< zxU0s7;m%V_9i-F;b7pQ@X;PW5C^M+1_?hbVSyi(VZ^;BppsyM<7NnM&dgyW)W~51D7p|#6CVs;C_ib# zvbAfMtyr`6im)=U3(C1T9E|!)Xp9$T!4YGX~+T28@hm#p!dzTocq(26O+q7benJK(JI-E#m z-YcUsk_+b=1o^6=%G(;EY8EYQhLsoa=-lo`4Xwv{U+-&Mco zVW~y^fLZK>QgQh~rS%><67(^_|7C*zaoBs-DV&-f&q{sf(iBH&v$B+;-1K;>TgkF2 zEr^=rQ`M}HC6^O=p+S8#3>=@F=T?x=Xi>|LHNvBMBrP?)u^9;c!uD=lxpE_i?E7z@ z_rL@5Zohxh*8RrCOaCzbzW)!8Jbvlq$xDyZwVQVA*!1|09c=cJwQHB$w|4E3xc4@G zbmq)Q8{dmd+P-Ah2OsQOvYn50cR-eST@oNmqr&MVF<8nxliYLTN*ye*)C_f)>DApt zO;fDCWYz6gxinRyE)b$1I;uU}#N{=(pB-@m_fD3*># zfsfptI)i7K;66zWJGn*W9%Ge#X5vuX%m-^nI4Af#>;1-dm8a3OVm4N1{zwiD#+Gbp z-+w?mq@gFAB)2N3ET zp-8OGxW`z$mHu%Hg)^Abe3Fh+PO%M;XpJO??b39jPM1vzjh9KB34R5^o~SzoTAK%W z-*{1%4Ypy^rA=Hv|BN0ODfo)5Of^;FWq_WJ=dRM@DZqx+0xF7-?W}IA(Q1p)YAc;9 zXn7!VhMg6CDwT8$2mNTQcwfkxQtES*nTyh3F(xIteU!wxL)0pz2_+w$h6yR;lQQS~ zPUFqo#x542tYAW@8ai}?@t~#A3H_r!m;Qe$KQQETO8@l5yd5t*v|##!zA+8CeYSnns_WKoeWhF1a^r&+MpO-b=gX4OlWFtk z?)b8(V3KkE$(M{5=HGG8y^9vo;je!}$K2L$fU(!8r7LF4UA&}n`tnPI23|gLU)@7{EL^Z;%lhKl+l>px z5p1$6oB!DM4I8)r9kvt>sx^~FohHo= zuvjIV(`3^6ORBwsI5An1E7W40xttEW%>w_Gf(~Nyn3)HCBIdfPJ_m;nrZ^35jkr7w zLk1r;Ou_^Lilo@d@YJ16-LQwkem=lE><)+ARB5U6iu9MP@^Yy*%lDyAIzE$;KZJA%cbpB>3Svq_rxm=le`Qh?%e2sFCu%Q{e-Pltm z#yb~QBf5vPQnU)Q&sh;y>>(BA1#YLV(fE{fh1l##GPY;A)6K-?4Q24|4rdjH6;w^w z)8{Y=I0r8lq$Ly`v_X|6kxDPq=DW5$^`ddy*!;*Nn+@Z({rjb_zOLE$ z=>9j2Z;TV=>$g7pSowk__sze&rd%NtU*2=i26y}$n?L^ueSwl0ku%C>^x0(6KAe;| zg)rwrM~QcewTu;|xEzkm%VVZarVr8HmDIa&TE-Vg{(AA^U!VRomp<^v6D4D&(&Sy3(*GfR zgYnEOJ29bp$=G8&w{Zg`iSzY>;H!^ZA5O4p74~8s9M!1L0gr*(W=R_wb$zkp$~R-S@wl1TGe6qIyqPgw63s2* zY5VufJLlC8qTkM&XT(YS=kdlgcKy+??lYYG>R0^H!18XCwsxS+M|y;_eomQ(R>TPN z>L!O>Z6J*EjuQq|%-yAYN_RdFlR80J?mwd^-^ZyrJg>eJH9(E@*Pqj}AU3b$vh@aJ zD~0rgh3higDjeo1Ua~N`giT2-^A-h&BiU|sC1*O}$ju0F5v#uHvgZ>sVd56%?hXcX zgEs~lL=BP^#1tL&2VAy%atqmuHY683C6M;{VYtqyYD{~7lyR0;-($SD-FV(8!~A^s zBI;Tv$L)K;*oA5POUCo<+tWKH)_>f;KYbdXdMl<+UDwfon_ciwy$?K0BDaQH#w{{C zEE;1KHl;Yh=VBDS84HrubUjf`H@WTUe%<8+E8|UQ<0cJl41U4~jX!V`BSBo=#f~_@ zM!}>#d1~^avawapDzH zUM}5P&p9pVmG*#M3uzbj>S~1vuDuG$Owltmmac@Xu=eum1T8|h~-P7z?b(xuaEd*_WI6TKN_`fl^xTy=%f@^qB&xg zK8xCyZ3|)y63Z^zrn6zgZoBmxY1;n7r+cn4*8O?xm^Gg%g%c-UKJbszsWG0Y37|Kg zHVt=kmbjdlTU#xXUgB^%yqFt_B_5y8+u!FjW0$+mTiB`;`(5b2M7LR(+o`(a)O4Q- z9-4G1lpuK6u{!S%M)c_V$+^5d*hX=}O(@*!v9Sj(_UPb)foEzWA9$Y7%zksaIm_AB z+{4_Qr6vy3gjb`y76k-|hGKyv_6sONKSm zmTAv&G<9~++uGXNxt9gL7HinrgMUif9=3OJgk52G*c0}K69?18AbPRJ2 zbCp@jtfjV6`#49jtH@pCDe}&>EVRtEF0{_J&9={W%yrInb;We|nlw@&jAlL>Vv&S* zc1VMC*Aw*nXX+P9?`<`ns_z(+#&@Lx$mDzV`Q_4^^-uARAJstt@ZLsp!-*EN#?_*E z5v?HTFuKDEe)7HoN3u}a&T64?E}qYW7Q99Sm&e$Hw+dZ1@rvuR0aq1&gNSHHMB948 zJv}9`CEO)2Abd_3QC_E}sr`K(wX(aoS{$N*mzXt^+u=^o;@tsv zQ+F$OwkO-$-rd<<=qdE})_S>bbocS}@eb35xktN4ct&{3v%`jl&xz>=s?i-P`= zBS+{$w(xDqdSq^0w3#&+XHW4Ez=A~$N9y!awbo?1NC7-~HEg7H;F@mP=; zvuU_)GGWHvH5?)pzPp576Q@V*8aX~KX4?3gu_i7aZ`xfn>@u_<|RdGZU+f^J&ATJyowoo{&wsf*3N|4>a0ElKl=OJ zY~4LNy&`>6I(VvpcUPH+*-Hw&j{2~|+Q`?=ii~HC@~g}=jv1HQJ~lbQG<#$Pq^+3_BwO;7GNHhtT5YVj8z z*KbCH{r$7QJXc>yvmRNw@)6^tRO7j2kkP%Ip1S{c^}EF2{NaIhJ2F?SStI=7+u#SP zf$V3~tZ)}t;OQYJ{!2tkKuQietyW8ai!~UM{d6H8y0iQXeIOrlUFghjXKQXEJD40y%>rC&xuLOsIVp2Jh%D4=2M$5 zYOe6{J?4(>Tjdo#*=E8Fz-#RdKG~T~^=u1wS7ryYgV~|%)b{2=y@RELwS%qDUYOD$ z&>`3%RG8X6t+(FW(#P7{)+^9E*gMoab+|s=XIXZ&Seq!(6%wm!LR z@uZpUuDjv&XZL^9qPg+FB*Av+n@CwBNXF97g!NQa*8FU7hju*I&~V21~i_8{-dfb~K^bWeYp@9C*+7 z;@HVU;X-VXlDPRm@s=122I0#U`7Mtu%Z;mD!9y){uulJ~Ms)?E;naQ%rjCUrbcykk56MIvsnXQ@Krr~AEEQ)2C zQD#Y07Q;1<={UTRw&xkT`@#A@Z>vB5uoP6vuiPtFV!&I&Ybj(&$39m+7xmIL;agY< z`aAcyptnm-CfV#Z>a^Q!SlPs+o_OsgHtbLJTAWsktbi0rcPfh9-)=!IJq|NdDqL2r zm=P~`y;v=}DY}Ks;Z|YS!ym~lq6-~=X7e`Kx(&`2ZuvI&VWM0B4+4HZO7RsLwDT`5 z{P1TsNw+BWL$u%{yKAm@C{#=+jju+C zc7;I=oQt!Xu-VvZY~5_kT`h(7;>GeIPtXyxa2tJomAwB-7v8#8cF23L6v`uG?TkHu z`0r8}*XWPo@eo^D0&|R%BoUaq#EChT-u8w&9Tg}&b7_6FMz--gvf+F3tjWv^E~st zbA7Y?a}wqx&PtjNAre!uf(Ge{2~jLj+G4DF&2U3@jDDM>fmJk2dmp6VK4Z+HCpOhr z?UWYQ{~6AL8Pc+e6O91<3e&aM>N}T5^?C$*+VTI)xc+Dr?ryV6mJ)1#)UgtcDYEXg z=-hHLVUdm-PdddCG`zDmwb+f}%IdOs?C@-veVRn!Bh&Gq8cs$?)etJZ^Xhz zg6Bafj(?>q9b8ZBMC);7Ar}6A=`cWgY0Qbch_%WBV6P3IqWvwq?t_? zW@WZSEz#t(I&ICgW~NsD4q69OJ9B%zv!&45*;;7pZ0pRoe>!`Zds~K@hg)v3-eN1W zOt4m1C)g@%MgG~^Y|&nGY%BcPyklehZ0Offwao|7yABxnOQq(|<6i~LdWP;?W^_JK zj(-4f7F^#fp)=R#)E_H{4S-chr8D?$gFhwB?8GJ)$!Rj1`diGhv`EEt8UMCSXBwu< z%%NBb-x|f&xHwyRhdh4~?zuw^?(c@VsDs;HiB^1hUQ+Ro3-LC@we9qd8yz~R&M%0r zjQYfC{z&#jUEMr+eci3BUu7@F{RJJ->+*TwN(7Bn#t+gR*r%nD^srl=p<6)6SUvKpOAsA&hGLO%^JVfA{0+N;h|oiESGVTORsWIr-)X*Kge*hFKJV$D*K^ zImJgI>`;pr4n;xVGrGxB{d`LN@9`YUXABsB|e=y--B9@j%(Sqpq1Q>cAF-fvFES80$ zt6o}K0pGdcXRZEn-@Qv_&RDi*v$6U5O%r!~c>W}nR^2n@PUq;N7l;1oEFJLG?8=He zm(y43KPsQmr^hRsp4#1e?mZ>NC$h7#BZb%dI@Eg)fmCwWB*yVdLTAiyF4r4+zwjS_UU%*=U=B2DC$=<@6NW6(^ zvm`zzKN|IK)Nulh>fD_bO+Z_0<(_-a8&7b!A6-t)`n>8J*vN_Bl)ha$(YNfbhu1!` z=C3s`P+= zT9Iw3@N^e2v zXDgp_ewDG7GxDcPZ-SA}({X!NEnWWLgUi9l@+~E!X}impY1`2yQg->3cgqgE^W~pT ze|_XC-Tc3QdEp@#5KfUyzDif=Cn9T5rDEfi)f$xJP%yQv|i7v~w!(Pj)yCgKMSYUBi9$I(yi4Aif z3#`uh%WK~nHPrw0->7s^f|#Ke1!)tNUN(a!T>O3Sra0 z=O$!YI1~TT)2&xxyQjP&VVcug={2pln{BiOv01b%($?dEq~>CS9^BMmGZu5i$a_AI z`--p&UhHJf-MJ!#%R}EPAGgMng}zC~`d?Jvyi`PrsMI-yVyvKIAx}+4#rOm<>b1y^ ztzNTfW9Z-;#}A>|#))(F+p4OnUVfqLy;nWe0~9x$m9-#3R=vi%u}sHb@qGrS6uRpE5JQm{9c6p%vGJY|BJr zX-vcpHnf?H;RZad20J-8vlFJ;a;#a9H&-rJ5BcH}*E!g}3Pa#1BrL9xg!u)Hu*qXIHr_46 zonp~-r?e>QY=#4-0x~tP@?WRGu+FcmJ?kwaZfi4UWi`!^6`8WFfW|L#1(*YCEzR_$pdAyR_ z*9os7IXc-LnA7$5J4~3*n=37Hr8+I%i^+YZWj$WVRG1kn&{kb_`8Br-FOgS;;I8HHXPU|EF#An$ep8|& z(VuC`c4Yf8Rq_|c^>Pd~-Ru}|8t)kIpAdJOX^DT0W49?@Hfy?O!M{(&k`}?DmdRuB zYJRubqkAwl_t@NaCziL8yz!WoH8nTYn_4n4A8X-k=4$3{?#=OK`&%Wowen@ILT7=e z(APPshq)Uj>fP+!J;Tkzu()-zW2kGWd#GoEd7O2eZM?nIG2S`GHO5`+DfN!?7bVRx z&(Y^tDxGs&bKJ8%mA(f&4|wnM-REDCw8pW<`LcPhzSpwHKLi>sn?|MYsv$4rk!sl8 z+NZv53r1^t@KO5J?*GHyd&gCErTwFO?R^TT0H@M>JJJL}K$LRChS(4ku^}p=fCdmt zM6pIq>`9DKgC&k*jL8@^%``NL>BVspV=}3em||Whlg!U#CQ-Kc`>eeW9MsJF{(kq~ z&;94d=z+yz?X}l>*0Y}aeUR0(eOKp|o$^a}AEG03&BXRVoB9OeMLm0Ry{yDiU|+>D z>?@)Y-8NmTPqPLolDPa_dMQPlZd4A6dQ5OgOkRh?$cfJgF-&2@-40oH@M!0yIwt%gI&%PdttAXq$pQhNbt z%2(33x)tma~kN7r#}%D+(;oM-m$-d zp72e?G>db#-+%x1?f37zm!!YoOP5%%{O!>1FJ8QK>EgxjXF?j0S%&;B0xI6Yy#|?C zu0X}~!3eyJ6~?<$m|zW;d^Oucd|UlvB3h%2+Z~%is-sr>x5q`M2>Ot~tZ2WKaEsvb zO^@pmoyi~Qxx8TyR^{g>R>U8RCxfseK`G+Ci?nK@1&=hX+-K~dM`k|RLz<>zA{N)F zLi3Xi5Cc8Jv>Xa68gw1ZpJb2#%)i{79ILknNasU;nOXq0qAQ9^N5H zxDQ5UgI&u6|5mG@4cLUs!P*X+Ep$^$ip|GmPVq~ps0AEuT!Cl6cM#SizX~zXf|v{n z_3a1O0BqhC$wJ}dPD_9#&=Qmu;uhS@ExIK)%DN7Ax&z#S?jR=~EmG$w7A5LP*i}z| zFhBjl@C&H=suKOB^U%6y4+Et4>b0Xs+mSHOeL{UJC7-EOQ@XLy0XkIOkU zPE7R|hTPhXbq&!eTuJTe#!~b6PDF7pR;4S_73GR{#kgW887G-0nJ4*9ikuWRDSA>& zW$e1hby4f0*Tt-h-4VGXYDe^rm>sc)A`e9!iar!`C^p=kydwEA$79aN0v-!|EaQ?5J#E+8yOw_N z!nkK=)@$xuxM1<5_4nMr_S?5+pBeD)#fzp+99q#QHRX=ldk&=}eK&hSS=pemNvUa@ z8}I*93XU$;6#A~@(l�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 K1-t#GoBj`&Wgve5 literal 0 HcmV?d00001 diff --git a/lib/kohana/system/fonts/LICENSE b/lib/kohana/system/fonts/LICENSE new file mode 100644 index 0000000..254e2cc --- /dev/null +++ b/lib/kohana/system/fonts/LICENSE @@ -0,0 +1,99 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + +$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ diff --git a/lib/kohana/system/helpers/arr.php b/lib/kohana/system/helpers/arr.php new file mode 100644 index 0000000..9570c4b --- /dev/null +++ b/lib/kohana/system/helpers/arr.php @@ -0,0 +1,312 @@ + $value) + { + $value = ($keep_keys === TRUE) ? $value : array_values($value); + foreach ($value as $k => $v) + { + $new_array[$k][$key] = $v; + } + } + + return $new_array; + } + + /** + * Removes a key from an array and returns the value. + * + * @param string key to return + * @param array array to work on + * @return mixed value of the requested array key + */ + public static function remove($key, & $array) + { + if ( ! array_key_exists($key, $array)) + return NULL; + + $val = $array[$key]; + unset($array[$key]); + + return $val; + } + + + /** + * Extract one or more keys from an array. Each key given after the first + * argument (the array) will be extracted. Keys that do not exist in the + * search array will be NULL in the extracted data. + * + * @param array array to search + * @param string key name + * @return array + */ + public static function extract(array $search, $keys) + { + // Get the keys, removing the $search array + $keys = array_slice(func_get_args(), 1); + + $found = array(); + foreach ($keys as $key) + { + if (isset($search[$key])) + { + $found[$key] = $search[$key]; + } + else + { + $found[$key] = NULL; + } + } + + return $found; + } + + /** + * Because PHP does not have this function. + * + * @param array array to unshift + * @param string key to unshift + * @param mixed value to unshift + * @return array + */ + public static function unshift_assoc( array & $array, $key, $val) + { + $array = array_reverse($array, TRUE); + $array[$key] = $val; + $array = array_reverse($array, TRUE); + + return $array; + } + + /** + * Because PHP does not have this function, and array_walk_recursive creates + * references in arrays and is not truly recursive. + * + * @param mixed callback to apply to each member of the array + * @param array array to map to + * @return array + */ + public static function map_recursive($callback, array $array) + { + foreach ($array as $key => $val) + { + // Map the callback to the key + $array[$key] = is_array($val) ? arr::map_recursive($callback, $val) : call_user_func($callback, $val); + } + + return $array; + } + + /** + * @param mixed $needle the value to search for + * @param array $haystack an array of values to search in + * @param boolean $sort sort the array now + * @return integer|FALSE the index of the match or FALSE when not found + */ + public static function binary_search($needle, $haystack, $sort = FALSE) + { + if ($sort) + { + sort($haystack); + } + + $high = count($haystack) - 1; + $low = 0; + + while ($low <= $high) + { + $mid = ($low + $high) >> 1; + + if ($haystack[$mid] < $needle) + { + $low = $mid + 1; + } + elseif ($haystack[$mid] > $needle) + { + $high = $mid - 1; + } + else + { + return $mid; + } + } + + return FALSE; + } + + + /** + * Emulates array_merge_recursive, but appends numeric keys and replaces + * associative keys, instead of appending all keys. + * + * @param array any number of arrays + * @return array + */ + public static function merge() + { + $total = func_num_args(); + + $result = array(); + for ($i = 0; $i < $total; $i++) + { + foreach (func_get_arg($i) as $key => $val) + { + if (isset($result[$key])) + { + if (is_array($val)) + { + // Arrays are merged recursively + $result[$key] = arr::merge($result[$key], $val); + } + elseif (is_int($key)) + { + // Indexed arrays are appended + array_push($result, $val); + } + else + { + // Associative arrays are replaced + $result[$key] = $val; + } + } + else + { + // New values are added + $result[$key] = $val; + } + } + } + + return $result; + } + + /** + * Overwrites an array with values from input array(s). + * Non-existing keys will not be appended! + * + * @param array key array + * @param array input array(s) that will overwrite key array values + * @return array + */ + public static function overwrite($array1, $array2) + { + foreach (array_intersect_key($array2, $array1) as $key => $value) + { + $array1[$key] = $value; + } + + if (func_num_args() > 2) + { + foreach (array_slice(func_get_args(), 2) as $array2) + { + foreach (array_intersect_key($array2, $array1) as $key => $value) + { + $array1[$key] = $value; + } + } + } + + return $array1; + } + + /** + * Fill an array with a range of numbers. + * + * @param integer stepping + * @param integer ending number + * @return array + */ + public static function range($step = 10, $max = 100) + { + if ($step < 1) + return array(); + + $array = array(); + for ($i = $step; $i <= $max; $i += $step) + { + $array[$i] = $i; + } + + return $array; + } + + /** + * Recursively convert an array to an object. + * + * @param array array to convert + * @return object + */ + public static function to_object(array $array, $class = 'stdClass') + { + $object = new $class; + + foreach ($array as $key => $value) + { + if (is_array($value)) + { + // Convert the array to an object + $value = arr::to_object($value, $class); + } + + // Add the value to the object + $object->{$key} = $value; + } + + return $object; + } + +} // End arr diff --git a/lib/kohana/system/helpers/cookie.php b/lib/kohana/system/helpers/cookie.php new file mode 100644 index 0000000..d58c25d --- /dev/null +++ b/lib/kohana/system/helpers/cookie.php @@ -0,0 +1,84 @@ +cookie($name, $default, $xss_clean); + } + + /** + * Nullify and unset a cookie. + * + * @param string cookie name + * @param string URL path + * @param string URL domain + * @return boolean + */ + public static function delete($name, $path = NULL, $domain = NULL) + { + if ( ! isset($_COOKIE[$name])) + return FALSE; + + // Delete the cookie from globals + unset($_COOKIE[$name]); + + // Sets the cookie value to an empty string, and the expiration to 24 hours ago + return cookie::set($name, '', -86400, $path, $domain, FALSE, FALSE); + } + +} // End cookie diff --git a/lib/kohana/system/helpers/date.php b/lib/kohana/system/helpers/date.php new file mode 100644 index 0000000..7d5a9ab --- /dev/null +++ b/lib/kohana/system/helpers/date.php @@ -0,0 +1,405 @@ +> 1); + } + + /** + * Converts a DOS timestamp to UNIX format. + * + * @param integer DOS timestamp + * @return integer + */ + public static function dos2unix($timestamp = FALSE) + { + $sec = 2 * ($timestamp & 0x1f); + $min = ($timestamp >> 5) & 0x3f; + $hrs = ($timestamp >> 11) & 0x1f; + $day = ($timestamp >> 16) & 0x1f; + $mon = ($timestamp >> 21) & 0x0f; + $year = ($timestamp >> 25) & 0x7f; + + return mktime($hrs, $min, $sec, $mon, $day, $year + 1980); + } + + /** + * Returns the offset (in seconds) between two time zones. + * @see http://php.net/timezones + * + * @param string timezone that to find the offset of + * @param string|boolean timezone used as the baseline + * @return integer + */ + public static function offset($remote, $local = TRUE) + { + static $offsets; + + // Default values + $remote = (string) $remote; + $local = ($local === TRUE) ? date_default_timezone_get() : (string) $local; + + // Cache key name + $cache = $remote.$local; + + if (empty($offsets[$cache])) + { + // Create timezone objects + $remote = new DateTimeZone($remote); + $local = new DateTimeZone($local); + + // Create date objects from timezones + $time_there = new DateTime('now', $remote); + $time_here = new DateTime('now', $local); + + // Find the offset + $offsets[$cache] = $remote->getOffset($time_there) - $local->getOffset($time_here); + } + + return $offsets[$cache]; + } + + /** + * Number of seconds in a minute, incrementing by a step. + * + * @param integer amount to increment each step by, 1 to 30 + * @param integer start value + * @param integer end value + * @return array A mirrored (foo => foo) array from 1-60. + */ + public static function seconds($step = 1, $start = 0, $end = 60) + { + // Always integer + $step = (int) $step; + + $seconds = array(); + + for ($i = $start; $i < $end; $i += $step) + { + $seconds[$i] = ($i < 10) ? '0'.$i : $i; + } + + return $seconds; + } + + /** + * Number of minutes in an hour, incrementing by a step. + * + * @param integer amount to increment each step by, 1 to 30 + * @return array A mirrored (foo => foo) array from 1-60. + */ + public static function minutes($step = 5) + { + // Because there are the same number of minutes as seconds in this set, + // we choose to re-use seconds(), rather than creating an entirely new + // function. Shhhh, it's cheating! ;) There are several more of these + // in the following methods. + return date::seconds($step); + } + + /** + * Number of hours in a day. + * + * @param integer amount to increment each step by + * @param boolean use 24-hour time + * @param integer the hour to start at + * @return array A mirrored (foo => foo) array from start-12 or start-23. + */ + public static function hours($step = 1, $long = FALSE, $start = NULL) + { + // Default values + $step = (int) $step; + $long = (bool) $long; + $hours = array(); + + // Set the default start if none was specified. + if ($start === NULL) + { + $start = ($long === FALSE) ? 1 : 0; + } + + $hours = array(); + + // 24-hour time has 24 hours, instead of 12 + $size = ($long === TRUE) ? 23 : 12; + + for ($i = $start; $i <= $size; $i += $step) + { + $hours[$i] = $i; + } + + return $hours; + } + + /** + * Returns AM or PM, based on a given hour. + * + * @param integer number of the hour + * @return string + */ + public static function ampm($hour) + { + // Always integer + $hour = (int) $hour; + + return ($hour > 11) ? 'PM' : 'AM'; + } + + /** + * Adjusts a non-24-hour number into a 24-hour number. + * + * @param integer hour to adjust + * @param string AM or PM + * @return string + */ + public static function adjust($hour, $ampm) + { + $hour = (int) $hour; + $ampm = strtolower($ampm); + + switch ($ampm) + { + case 'am': + if ($hour == 12) + $hour = 0; + break; + case 'pm': + if ($hour < 12) + $hour += 12; + break; + } + + return sprintf('%02s', $hour); + } + + /** + * Number of days in month. + * + * @param integer number of month + * @param integer number of year to check month, defaults to the current year + * @return array A mirrored (foo => foo) array of the days. + */ + public static function days($month, $year = FALSE) + { + static $months; + + // Always integers + $month = (int) $month; + $year = (int) $year; + + // Use the current year by default + $year = ($year == FALSE) ? date('Y') : $year; + + // We use caching for months, because time functions are used + if (empty($months[$year][$month])) + { + $months[$year][$month] = array(); + + // Use date to find the number of days in the given month + $total = date('t', mktime(1, 0, 0, $month, 1, $year)) + 1; + + for ($i = 1; $i < $total; $i++) + { + $months[$year][$month][$i] = $i; + } + } + + return $months[$year][$month]; + } + + /** + * Number of months in a year + * + * @return array A mirrored (foo => foo) array from 1-12. + */ + public static function months() + { + return date::hours(); + } + + /** + * Returns an array of years between a starting and ending year. + * Uses the current year +/- 5 as the max/min. + * + * @param integer starting year + * @param integer ending year + * @return array + */ + public static function years($start = FALSE, $end = FALSE) + { + // Default values + $start = ($start === FALSE) ? date('Y') - 5 : (int) $start; + $end = ($end === FALSE) ? date('Y') + 5 : (int) $end; + + $years = array(); + + // Add one, so that "less than" works + $end += 1; + + for ($i = $start; $i < $end; $i++) + { + $years[$i] = $i; + } + + return $years; + } + + /** + * Returns time difference between two timestamps, in human readable format. + * + * @param integer timestamp + * @param integer timestamp, defaults to the current time + * @param string formatting string + * @return string|array + */ + public static function timespan($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds') + { + // Array with the output formats + $output = preg_split('/[^a-z]+/', strtolower((string) $output)); + + // Invalid output + if (empty($output)) + return FALSE; + + // Make the output values into keys + extract(array_flip($output), EXTR_SKIP); + + // Default values + $time1 = max(0, (int) $time1); + $time2 = empty($time2) ? time() : max(0, (int) $time2); + + // Calculate timespan (seconds) + $timespan = abs($time1 - $time2); + + // All values found using Google Calculator. + // Years and months do not match the formula exactly, due to leap years. + + // Years ago, 60 * 60 * 24 * 365 + isset($years) and $timespan -= 31556926 * ($years = (int) floor($timespan / 31556926)); + + // Months ago, 60 * 60 * 24 * 30 + isset($months) and $timespan -= 2629744 * ($months = (int) floor($timespan / 2629743.83)); + + // Weeks ago, 60 * 60 * 24 * 7 + isset($weeks) and $timespan -= 604800 * ($weeks = (int) floor($timespan / 604800)); + + // Days ago, 60 * 60 * 24 + isset($days) and $timespan -= 86400 * ($days = (int) floor($timespan / 86400)); + + // Hours ago, 60 * 60 + isset($hours) and $timespan -= 3600 * ($hours = (int) floor($timespan / 3600)); + + // Minutes ago, 60 + isset($minutes) and $timespan -= 60 * ($minutes = (int) floor($timespan / 60)); + + // Seconds ago, 1 + isset($seconds) and $seconds = $timespan; + + // Remove the variables that cannot be accessed + unset($timespan, $time1, $time2); + + // Deny access to these variables + $deny = array_flip(array('deny', 'key', 'difference', 'output')); + + // Return the difference + $difference = array(); + foreach ($output as $key) + { + if (isset($$key) AND ! isset($deny[$key])) + { + // Add requested key to the output + $difference[$key] = $$key; + } + } + + // Invalid output formats string + if (empty($difference)) + return FALSE; + + // If only one output format was asked, don't put it in an array + if (count($difference) === 1) + return current($difference); + + // Return array + return $difference; + } + + /** + * Returns time difference between two timestamps, in the format: + * N year, N months, N weeks, N days, N hours, N minutes, and N seconds ago + * + * @param integer timestamp + * @param integer timestamp, defaults to the current time + * @param string formatting string + * @return string + */ + public static function timespan_string($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds') + { + if ($difference = date::timespan($time1, $time2, $output) AND is_array($difference)) + { + // Determine the key of the last item in the array + $last = end($difference); + $last = key($difference); + + $span = array(); + foreach ($difference as $name => $amount) + { + if ($amount === 0) + { + // Skip empty amounts + continue; + } + + // Add the amount to the span + $span[] = ($name === $last ? ' and ' : ', ').$amount.' '.($amount === 1 ? inflector::singular($name) : $name); + } + + // If the difference is less than 60 seconds, remove the preceding and. + if (count($span) === 1) + { + $span[0] = ltrim($span[0], 'and '); + } + + // Replace difference by making the span into a string + $difference = trim(implode('', $span), ','); + } + elseif (is_int($difference)) + { + // Single-value return + $difference = $difference.' '.($difference === 1 ? inflector::singular($output) : $output); + } + + return $difference; + } + +} // End date \ No newline at end of file diff --git a/lib/kohana/system/helpers/download.php b/lib/kohana/system/helpers/download.php new file mode 100644 index 0000000..49fed42 --- /dev/null +++ b/lib/kohana/system/helpers/download.php @@ -0,0 +1,105 @@ +setUsername($config['options']['username']); + empty($config['options']['password']) or $connection->setPassword($config['options']['password']); + + if ( ! empty($config['options']['auth'])) + { + // Get the class name and params + list ($class, $params) = arr::callback_string($config['options']['auth']); + + if ($class === 'PopB4Smtp') + { + // Load the PopB4Smtp class manually, due to its odd filename + require Kohana::find_file('vendor', 'swift/Swift/Authenticator/$PopB4Smtp$'); + } + + // Prepare the class name for auto-loading + $class = 'Swift_Authenticator_'.$class; + + // Attach the authenticator + $connection->attachAuthenticator(($params === NULL) ? new $class : new $class($params[0])); + } + + // Set the timeout to 5 seconds + $connection->setTimeout(empty($config['options']['timeout']) ? 5 : (int) $config['options']['timeout']); + break; + case 'sendmail': + // Create a sendmail connection + $connection = new Swift_Connection_Sendmail + ( + empty($config['options']) ? Swift_Connection_Sendmail::AUTO_DETECT : $config['options'] + ); + + // Set the timeout to 5 seconds + $connection->setTimeout(5); + break; + default: + // Use the native connection + $connection = new Swift_Connection_NativeMail($config['options']); + break; + } + + // Create the SwiftMailer instance + return email::$mail = new Swift($connection); + } + + /** + * Send an email message. + * + * @param string|array recipient email (and name), or an array of To, Cc, Bcc names + * @param string|array sender email (and name) + * @param string message subject + * @param string message body + * @param boolean send email as HTML + * @return integer number of emails sent + */ + public static function send($to, $from, $subject, $message, $html = FALSE) + { + // Connect to SwiftMailer + (email::$mail === NULL) and email::connect(); + + // Determine the message type + $html = ($html === TRUE) ? 'text/html' : 'text/plain'; + + // Create the message + $message = new Swift_Message($subject, $message, $html, '8bit', 'utf-8'); + + if (is_string($to)) + { + // Single recipient + $recipients = new Swift_Address($to); + } + elseif (is_array($to)) + { + if (isset($to[0]) AND isset($to[1])) + { + // Create To: address set + $to = array('to' => $to); + } + + // Create a list of recipients + $recipients = new Swift_RecipientList; + + foreach ($to as $method => $set) + { + if ( ! in_array($method, array('to', 'cc', 'bcc'))) + { + // Use To: by default + $method = 'to'; + } + + // Create method name + $method = 'add'.ucfirst($method); + + if (is_array($set)) + { + // Add a recipient with name + $recipients->$method($set[0], $set[1]); + } + else + { + // Add a recipient without name + $recipients->$method($set); + } + } + } + + if (is_string($from)) + { + // From without a name + $from = new Swift_Address($from); + } + elseif (is_array($from)) + { + // From with a name + $from = new Swift_Address($from[0], $from[1]); + } + + return email::$mail->send($message, $recipients, $from); + } + +} // End email \ No newline at end of file diff --git a/lib/kohana/system/helpers/expires.php b/lib/kohana/system/helpers/expires.php new file mode 100644 index 0000000..c43cc0c --- /dev/null +++ b/lib/kohana/system/helpers/expires.php @@ -0,0 +1,111 @@ + 0) + { + // Re-send headers + header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $mod_time)); + header('Expires: '.gmdate('D, d M Y H:i:s T', time() + $mod_time_diff)); + header('Cache-Control: max-age='.$mod_time_diff); + header('Status: 304 Not Modified', TRUE, 304); + + // Prevent any output + Event::add('system.display', array('expires', 'prevent_output')); + + // Exit to prevent other output + exit; + } + } + + return FALSE; + } + + /** + * Check headers already created to not step on download or Img_lib's feet + * + * @return boolean + */ + public static function check_headers() + { + foreach (headers_list() as $header) + { + if ((session_cache_limiter() == '' AND stripos($header, 'Last-Modified:') === 0) + OR stripos($header, 'Expires:') === 0) + { + return FALSE; + } + } + + return TRUE; + } + + /** + * Prevent any output from being displayed. Executed during system.display. + * + * @return void + */ + public static function prevent_output() + { + Kohana::$output = ''; + } + +} // End expires \ No newline at end of file diff --git a/lib/kohana/system/helpers/feed.php b/lib/kohana/system/helpers/feed.php new file mode 100644 index 0000000..74bb2f6 --- /dev/null +++ b/lib/kohana/system/helpers/feed.php @@ -0,0 +1,122 @@ +channel) ? $feed->xpath('//item') : $feed->entry; + + $i = 0; + $items = array(); + + foreach ($feed as $item) + { + if ($limit > 0 AND $i++ === $limit) + break; + + $items[] = (array) $item; + } + + return $items; + } + + /** + * Creates a feed from the given parameters. + * + * @param array feed information + * @param array items to add to the feed + * @param string define which format to use + * @param string define which encoding to use + * @return string + */ + public static function create($info, $items, $format = 'rss2', $encoding = 'UTF-8') + { + $info += array('title' => 'Generated Feed', 'link' => '', 'generator' => 'KohanaPHP'); + + $feed = ''; + $feed = simplexml_load_string($feed); + + foreach ($info as $name => $value) + { + if (($name === 'pubDate' OR $name === 'lastBuildDate') AND (is_int($value) OR ctype_digit($value))) + { + // Convert timestamps to RFC 822 formatted dates + $value = date(DATE_RFC822, $value); + } + elseif (($name === 'link' OR $name === 'docs') AND strpos($value, '://') === FALSE) + { + // Convert URIs to URLs + $value = url::site($value, 'http'); + } + + // Add the info to the channel + $feed->channel->addChild($name, $value); + } + + foreach ($items as $item) + { + // Add the item to the channel + $row = $feed->channel->addChild('item'); + + foreach ($item as $name => $value) + { + if ($name === 'pubDate' AND (is_int($value) OR ctype_digit($value))) + { + // Convert timestamps to RFC 822 formatted dates + $value = date(DATE_RFC822, $value); + } + elseif (($name === 'link' OR $name === 'guid') AND strpos($value, '://') === FALSE) + { + // Convert URIs to URLs + $value = url::site($value, 'http'); + } + + // Add the info to the row + $row->addChild($name, $value); + } + } + + return $feed->asXML(); + } + +} // End feed \ No newline at end of file diff --git a/lib/kohana/system/helpers/file.php b/lib/kohana/system/helpers/file.php new file mode 100644 index 0000000..b1b7174 --- /dev/null +++ b/lib/kohana/system/helpers/file.php @@ -0,0 +1,186 @@ +'."\n"; + + // Add hidden fields immediate after opening tag + empty($hidden) or $form .= form::hidden($hidden); + + return $form; + } + + /** + * Generates an opening HTML form tag that can be used for uploading files. + * + * @param string form action attribute + * @param array extra attributes + * @param array hidden fields to be created immediately after the form tag + * @return string + */ + public static function open_multipart($action = NULL, $attr = array(), $hidden = array()) + { + // Set multi-part form type + $attr['enctype'] = 'multipart/form-data'; + + return form::open($action, $attr, $hidden); + } + + /** + * Generates a fieldset opening tag. + * + * @param array html attributes + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function open_fieldset($data = NULL, $extra = '') + { + return ''."\n"; + } + + /** + * Generates a fieldset closing tag. + * + * @return string + */ + public static function close_fieldset() + { + return ''."\n"; + } + + /** + * Generates a legend tag for use with a fieldset. + * + * @param string legend text + * @param array HTML attributes + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function legend($text = '', $data = NULL, $extra = '') + { + return ''.$text.''."\n"; + } + + /** + * Generates hidden form fields. + * You can pass a simple key/value string or an associative array with multiple values. + * + * @param string|array input name (string) or key/value pairs (array) + * @param string input value, if using an input name + * @return string + */ + public static function hidden($data, $value = '') + { + if ( ! is_array($data)) + { + $data = array + ( + $data => $value + ); + } + + $input = ''; + foreach ($data as $name => $value) + { + $attr = array + ( + 'type' => 'hidden', + 'name' => $name, + 'value' => $value + ); + + $input .= form::input($attr)."\n"; + } + + return $input; + } + + /** + * Creates an HTML form input tag. Defaults to a text type. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function input($data, $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + // Type and value are required attributes + $data += array + ( + 'type' => 'text', + 'value' => $value + ); + + return ''; + } + + /** + * Creates a HTML form password input tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function password($data, $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'password'; + + return form::input($data, $value, $extra); + } + + /** + * Creates an HTML form upload input tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function upload($data, $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'file'; + + return form::input($data, $value, $extra); + } + + /** + * Creates an HTML form textarea tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param string a string to be attached to the end of the attributes + * @param boolean encode existing entities + * @return string + */ + public static function textarea($data, $value = '', $extra = '', $double_encode = TRUE) + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + // Use the value from $data if possible, or use $value + $value = isset($data['value']) ? $data['value'] : $value; + + // Value is not part of the attributes + unset($data['value']); + + return ''.html::specialchars($value, $double_encode).''; + } + + /** + * Creates an HTML form select tag, or "dropdown menu". + * + * @param string|array input name or an array of HTML attributes + * @param array select options, when using a name + * @param string|array option key(s) that should be selected by default + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function dropdown($data, $options = NULL, $selected = NULL, $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + else + { + if (isset($data['options'])) + { + // Use data options + $options = $data['options']; + } + + if (isset($data['selected'])) + { + // Use data selected + $selected = $data['selected']; + } + } + + if (is_array($selected)) + { + // Multi-select box + $data['multiple'] = 'multiple'; + } + else + { + // Single selection (but converted to an array) + $selected = array($selected); + } + + $input = ''."\n"; + foreach ((array) $options as $key => $val) + { + // Key should always be a string + $key = (string) $key; + + if (is_array($val)) + { + $input .= ''."\n"; + foreach ($val as $inner_key => $inner_val) + { + // Inner key should always be a string + $inner_key = (string) $inner_key; + + $sel = in_array($inner_key, $selected) ? ' selected="selected"' : ''; + $input .= ''."\n"; + } + $input .= ''."\n"; + } + else + { + $sel = in_array($key, $selected) ? ' selected="selected"' : ''; + $input .= ''."\n"; + } + } + $input .= ''; + + return $input; + } + + /** + * Creates an HTML form checkbox input tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param boolean make the checkbox checked by default + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function checkbox($data, $value = '', $checked = FALSE, $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'checkbox'; + + if ($checked == TRUE OR (isset($data['checked']) AND $data['checked'] == TRUE)) + { + $data['checked'] = 'checked'; + } + else + { + unset($data['checked']); + } + + return form::input($data, $value, $extra); + } + + /** + * Creates an HTML form radio input tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param boolean make the radio selected by default + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function radio($data = '', $value = '', $checked = FALSE, $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'radio'; + + if ($checked == TRUE OR (isset($data['checked']) AND $data['checked'] == TRUE)) + { + $data['checked'] = 'checked'; + } + else + { + unset($data['checked']); + } + + return form::input($data, $value, $extra); + } + + /** + * Creates an HTML form submit input tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function submit($data = '', $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + if (empty($data['name'])) + { + // Remove the name if it is empty + unset($data['name']); + } + + $data['type'] = 'submit'; + + return form::input($data, $value, $extra); + } + + /** + * Creates an HTML form button input tag. + * + * @param string|array input name or an array of HTML attributes + * @param string input value, when using a name + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function button($data = '', $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + if (empty($data['name'])) + { + // Remove the name if it is empty + unset($data['name']); + } + + if (isset($data['value']) AND empty($value)) + { + $value = arr::remove('value', $data); + } + + return ''.$value.''; + } + + /** + * Closes an open form tag. + * + * @param string string to be attached after the closing tag + * @return string + */ + public static function close($extra = '') + { + return ''."\n".$extra; + } + + /** + * Creates an HTML form label tag. + * + * @param string|array label "for" name or an array of HTML attributes + * @param string label text or HTML + * @param string a string to be attached to the end of the attributes + * @return string + */ + public static function label($data = '', $text = NULL, $extra = '') + { + if ( ! is_array($data)) + { + if (is_string($data)) + { + // Specify the input this label is for + $data = array('for' => $data); + } + else + { + // No input specified + $data = array(); + } + } + + if ($text === NULL AND isset($data['for'])) + { + // Make the text the human-readable input name + $text = ucwords(inflector::humanize($data['for'])); + } + + return ''.$text.''; + } + + /** + * Sorts a key/value array of HTML attributes, putting form attributes first, + * and returns an attribute string. + * + * @param array HTML attributes array + * @return string + */ + public static function attributes($attr, $type = NULL) + { + if (empty($attr)) + return ''; + + if (isset($attr['name']) AND empty($attr['id']) AND strpos($attr['name'], '[') === FALSE) + { + if ($type === NULL AND ! empty($attr['type'])) + { + // Set the type by the attributes + $type = $attr['type']; + } + + switch ($type) + { + case 'text': + case 'textarea': + case 'password': + case 'select': + case 'checkbox': + case 'file': + case 'image': + case 'button': + case 'submit': + // Only specific types of inputs use name to id matching + $attr['id'] = $attr['name']; + break; + } + } + + $order = array + ( + 'action', + 'method', + 'type', + 'id', + 'name', + 'value', + 'src', + 'size', + 'maxlength', + 'rows', + 'cols', + 'accept', + 'tabindex', + 'accesskey', + 'align', + 'alt', + 'title', + 'class', + 'style', + 'selected', + 'checked', + 'readonly', + 'disabled' + ); + + $sorted = array(); + foreach ($order as $key) + { + if (isset($attr[$key])) + { + // Move the attribute to the sorted array + $sorted[$key] = $attr[$key]; + + // Remove the attribute from unsorted array + unset($attr[$key]); + } + } + + // Combine the sorted and unsorted attributes and create an HTML string + return html::attributes(array_merge($sorted, $attr)); + } + +} // End form \ No newline at end of file diff --git a/lib/kohana/system/helpers/format.php b/lib/kohana/system/helpers/format.php new file mode 100644 index 0000000..fb8a029 --- /dev/null +++ b/lib/kohana/system/helpers/format.php @@ -0,0 +1,66 @@ +=')) + { + $str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8', FALSE); + } + else + { + $str = preg_replace('/&(?!(?:#\d++|[a-z]++);)/ui', '&', $str); + $str = str_replace(array('<', '>', '\'', '"'), array('<', '>', ''', '"'), $str); + } + } + + return $str; + } + + /** + * Perform a html::specialchars() with additional URL specific encoding. + * + * @param string string to convert + * @param boolean encode existing entities + * @return string + */ + public static function specialurlencode($str, $double_encode = TRUE) + { + return str_replace(' ', '%20', html::specialchars($str, $double_encode)); + } + + /** + * Create HTML link anchors. + * + * @param string URL or URI string + * @param string link text + * @param array HTML anchor attributes + * @param string non-default protocol, eg: https + * @param boolean option to escape the title that is output + * @return string + */ + public static function anchor($uri, $title = NULL, $attributes = NULL, $protocol = NULL, $escape_title = FALSE) + { + if ($uri === '') + { + $site_url = url::base(FALSE); + } + elseif (strpos($uri, '#') === 0) + { + // This is an id target link, not a URL + $site_url = $uri; + } + elseif (strpos($uri, '://') === FALSE) + { + $site_url = url::site($uri, $protocol); + } + else + { + if (html::$windowed_urls === TRUE AND empty($attributes['target'])) + { + $attributes['target'] = '_blank'; + } + + $site_url = $uri; + } + + return + // Parsed URL + '' + // Title empty? Use the parsed URL + .($escape_title ? html::specialchars((($title === NULL) ? $site_url : $title), FALSE) : (($title === NULL) ? $site_url : $title)).''; + } + + /** + * Creates an HTML anchor to a file. + * + * @param string name of file to link to + * @param string link text + * @param array HTML anchor attributes + * @param string non-default protocol, eg: ftp + * @return string + */ + public static function file_anchor($file, $title = NULL, $attributes = NULL, $protocol = NULL) + { + return + // Base URL + URI = full URL + '' + // Title empty? Use the filename part of the URI + .(($title === NULL) ? end(explode('/', $file)) : $title) .''; + } + + /** + * Similar to anchor, but with the protocol parameter first. + * + * @param string link protocol + * @param string URI or URL to link to + * @param string link text + * @param array HTML anchor attributes + * @return string + */ + public static function panchor($protocol, $uri, $title = NULL, $attributes = FALSE) + { + return html::anchor($uri, $title, $attributes, $protocol); + } + + /** + * Create an array of anchors from an array of link/title pairs. + * + * @param array link/title pairs + * @return array + */ + public static function anchor_array(array $array) + { + $anchors = array(); + foreach ($array as $link => $title) + { + // Create list of anchors + $anchors[] = html::anchor($link, $title); + } + return $anchors; + } + + /** + * Generates an obfuscated version of an email address. + * + * @param string email address + * @return string + */ + public static function email($email) + { + $safe = ''; + foreach (str_split($email) as $letter) + { + switch (($letter === '@') ? rand(1, 2) : rand(1, 3)) + { + // HTML entity code + case 1: $safe .= '&#'.ord($letter).';'; break; + // Hex character code + case 2: $safe .= '&#x'.dechex(ord($letter)).';'; break; + // Raw (no) encoding + case 3: $safe .= $letter; + } + } + + return $safe; + } + + /** + * Creates an email anchor. + * + * @param string email address to send to + * @param string link text + * @param array HTML anchor attributes + * @return string + */ + public static function mailto($email, $title = NULL, $attributes = NULL) + { + if (empty($email)) + return $title; + + // Remove the subject or other parameters that do not need to be encoded + if (strpos($email, '?') !== FALSE) + { + // Extract the parameters from the email address + list ($email, $params) = explode('?', $email, 2); + + // Make the params into a query string, replacing spaces + $params = '?'.str_replace(' ', '%20', $params); + } + else + { + // No parameters + $params = ''; + } + + // Obfuscate email address + $safe = html::email($email); + + // Title defaults to the encoded email address + empty($title) and $title = $safe; + + // Parse attributes + empty($attributes) or $attributes = html::attributes($attributes); + + // Encoded start of the href="" is a static encoded version of 'mailto:' + return ''.$title.''; + } + + /** + * Generate a "breadcrumb" list of anchors representing the URI. + * + * @param array segments to use as breadcrumbs, defaults to using Router::$segments + * @return string + */ + public static function breadcrumb($segments = NULL) + { + empty($segments) and $segments = Router::$segments; + + $array = array(); + while ($segment = array_pop($segments)) + { + $array[] = html::anchor + ( + // Complete URI for the URL + implode('/', $segments).'/'.$segment, + // Title for the current segment + ucwords(inflector::humanize($segment)) + ); + } + + // Retrun the array of all the segments + return array_reverse($array); + } + + /** + * Creates a meta tag. + * + * @param string|array tag name, or an array of tags + * @param string tag "content" value + * @return string + */ + public static function meta($tag, $value = NULL) + { + if (is_array($tag)) + { + $tags = array(); + foreach ($tag as $t => $v) + { + // Build each tag and add it to the array + $tags[] = html::meta($t, $v); + } + + // Return all of the tags as a string + return implode("\n", $tags); + } + + // Set the meta attribute value + $attr = in_array(strtolower($tag), Kohana::config('http.meta_equiv')) ? 'http-equiv' : 'name'; + + return ''; + } + + /** + * Creates a stylesheet link. + * + * @param string|array filename, or array of filenames to match to array of medias + * @param string|array media type of stylesheet, or array to match filenames + * @param boolean include the index_page in the link + * @return string + */ + public static function stylesheet($style, $media = FALSE, $index = FALSE) + { + return html::link($style, 'stylesheet', 'text/css', '.css', $media, $index); + } + + /** + * Creates a link tag. + * + * @param string|array filename + * @param string|array relationship + * @param string|array mimetype + * @param string specifies suffix of the file + * @param string|array specifies on what device the document will be displayed + * @param boolean include the index_page in the link + * @return string + */ + public static function link($href, $rel, $type, $suffix = FALSE, $media = FALSE, $index = FALSE) + { + $compiled = ''; + + if (is_array($href)) + { + foreach ($href as $_href) + { + $_rel = is_array($rel) ? array_shift($rel) : $rel; + $_type = is_array($type) ? array_shift($type) : $type; + $_media = is_array($media) ? array_shift($media) : $media; + + $compiled .= html::link($_href, $_rel, $_type, $suffix, $_media, $index); + } + } + else + { + if (strpos($href, '://') === FALSE) + { + // Make the URL absolute + $href = url::base($index).$href; + } + + $length = strlen($suffix); + + if ( $length > 0 AND substr_compare($href, $suffix, -$length, $length, FALSE) !== 0) + { + // Add the defined suffix + $href .= $suffix; + } + + $attr = array + ( + 'rel' => $rel, + 'type' => $type, + 'href' => $href, + ); + + if ( ! empty($media)) + { + // Add the media type to the attributes + $attr['media'] = $media; + } + + $compiled = ''; + } + + return $compiled."\n"; + } + + /** + * Creates a script link. + * + * @param string|array filename + * @param boolean include the index_page in the link + * @return string + */ + public static function script($script, $index = FALSE) + { + $compiled = ''; + + if (is_array($script)) + { + foreach ($script as $name) + { + $compiled .= html::script($name, $index); + } + } + else + { + if (strpos($script, '://') === FALSE) + { + // Add the suffix only when it's not already present + $script = url::base((bool) $index).$script; + } + + if (substr_compare($script, '.js', -3, 3, FALSE) !== 0) + { + // Add the javascript suffix + $script .= '.js'; + } + + $compiled = ''; + } + + return $compiled."\n"; + } + + /** + * Creates a image link. + * + * @param string image source, or an array of attributes + * @param string|array image alt attribute, or an array of attributes + * @param boolean include the index_page in the link + * @return string + */ + public static function image($src = NULL, $alt = NULL, $index = FALSE) + { + // Create attribute list + $attributes = is_array($src) ? $src : array('src' => $src); + + if (is_array($alt)) + { + $attributes += $alt; + } + elseif ( ! empty($alt)) + { + // Add alt to attributes + $attributes['alt'] = $alt; + } + + if (strpos($attributes['src'], '://') === FALSE) + { + // Make the src attribute into an absolute URL + $attributes['src'] = url::base($index).$attributes['src']; + } + + return ''; + } + + /** + * Compiles an array of HTML attributes into an attribute string. + * + * @param string|array array of attributes + * @return string + */ + public static function attributes($attrs) + { + if (empty($attrs)) + return ''; + + if (is_string($attrs)) + return ' '.$attrs; + + $compiled = ''; + foreach ($attrs as $key => $val) + { + $compiled .= ' '.$key.'="'.html::specialchars($val).'"'; + } + + return $compiled; + } + +} // End html diff --git a/lib/kohana/system/helpers/inflector.php b/lib/kohana/system/helpers/inflector.php new file mode 100644 index 0000000..1e4fee2 --- /dev/null +++ b/lib/kohana/system/helpers/inflector.php @@ -0,0 +1,193 @@ + 1) + return $str; + + // Cache key name + $key = 'singular_'.$str.$count; + + if (isset(inflector::$cache[$key])) + return inflector::$cache[$key]; + + if (inflector::uncountable($str)) + return inflector::$cache[$key] = $str; + + if (empty(inflector::$irregular)) + { + // Cache irregular words + inflector::$irregular = Kohana::config('inflector.irregular'); + } + + if ($irregular = array_search($str, inflector::$irregular)) + { + $str = $irregular; + } + elseif (preg_match('/[sxz]es$/', $str) OR preg_match('/[^aeioudgkprt]hes$/', $str)) + { + // Remove "es" + $str = substr($str, 0, -2); + } + elseif (preg_match('/[^aeiou]ies$/', $str)) + { + $str = substr($str, 0, -3).'y'; + } + elseif (substr($str, -1) === 's' AND substr($str, -2) !== 'ss') + { + $str = substr($str, 0, -1); + } + + return inflector::$cache[$key] = $str; + } + + /** + * Makes a singular word plural. + * + * @param string word to pluralize + * @return string + */ + public static function plural($str, $count = NULL) + { + // Remove garbage + $str = strtolower(trim($str)); + + if (is_string($count)) + { + // Convert to integer when using a digit string + $count = (int) $count; + } + + // Do nothing with singular + if ($count === 1) + return $str; + + // Cache key name + $key = 'plural_'.$str.$count; + + if (isset(inflector::$cache[$key])) + return inflector::$cache[$key]; + + if (inflector::uncountable($str)) + return inflector::$cache[$key] = $str; + + if (empty(inflector::$irregular)) + { + // Cache irregular words + inflector::$irregular = Kohana::config('inflector.irregular'); + } + + if (isset(inflector::$irregular[$str])) + { + $str = inflector::$irregular[$str]; + } + elseif (preg_match('/[sxz]$/', $str) OR preg_match('/[^aeioudgkprt]h$/', $str)) + { + $str .= 'es'; + } + elseif (preg_match('/[^aeiou]y$/', $str)) + { + // Change "y" to "ies" + $str = substr_replace($str, 'ies', -1); + } + else + { + $str .= 's'; + } + + // Set the cache and return + return inflector::$cache[$key] = $str; + } + + /** + * Makes a phrase camel case. + * + * @param string phrase to camelize + * @return string + */ + public static function camelize($str) + { + $str = 'x'.strtolower(trim($str)); + $str = ucwords(preg_replace('/[\s_]+/', ' ', $str)); + + return substr(str_replace(' ', '', $str), 1); + } + + /** + * Makes a phrase underscored instead of spaced. + * + * @param string phrase to underscore + * @return string + */ + public static function underscore($str) + { + return preg_replace('/\s+/', '_', trim($str)); + } + + /** + * Makes an underscored or dashed phrase human-reable. + * + * @param string phrase to make human-reable + * @return string + */ + public static function humanize($str) + { + return preg_replace('/[_-]+/', ' ', trim($str)); + } + +} // End inflector \ No newline at end of file diff --git a/lib/kohana/system/helpers/num.php b/lib/kohana/system/helpers/num.php new file mode 100644 index 0000000..3eb5d5a --- /dev/null +++ b/lib/kohana/system/helpers/num.php @@ -0,0 +1,26 @@ + 0); + } + + /** + * Compare the q values for given array of content types and return the one with the highest value. + * If items are found to have the same q value, the first one encountered in the given array wins. + * If all items in the given array have a q value of 0, FALSE is returned. + * + * @param array content types + * @param boolean set to TRUE to disable wildcard checking + * @return mixed string mime type with highest q value, FALSE if none of the given types are accepted + */ + public static function preferred_accept($types, $explicit_check = FALSE) + { + // Initialize + $mime_types = array(); + $max_q = 0; + $preferred = FALSE; + + // Load q values for all given content types + foreach (array_unique($types) as $type) + { + $mime_types[$type] = request::accepts_at_quality($type, $explicit_check); + } + + // Look for the highest q value + foreach ($mime_types as $type => $q) + { + if ($q > $max_q) + { + $max_q = $q; + $preferred = $type; + } + } + + return $preferred; + } + + /** + * Returns quality factor at which the client accepts content type. + * + * @param string content type (e.g. "image/jpg", "jpg") + * @param boolean set to TRUE to disable wildcard checking + * @return integer|float + */ + public static function accepts_at_quality($type = NULL, $explicit_check = FALSE) + { + request::parse_accept_header(); + + // Normalize type + $type = strtolower((string) $type); + + // General content type (e.g. "jpg") + if (strpos($type, '/') === FALSE) + { + // Don't accept anything by default + $q = 0; + + // Look up relevant mime types + foreach ((array) Kohana::config('mimes.'.$type) as $type) + { + $q2 = request::accepts_at_quality($type, $explicit_check); + $q = ($q2 > $q) ? $q2 : $q; + } + + return $q; + } + + // Content type with subtype given (e.g. "image/jpg") + $type = explode('/', $type, 2); + + // Exact match + if (isset(request::$accept_types[$type[0]][$type[1]])) + return request::$accept_types[$type[0]][$type[1]]; + + // Wildcard match (if not checking explicitly) + if ($explicit_check === FALSE AND isset(request::$accept_types[$type[0]]['*'])) + return request::$accept_types[$type[0]]['*']; + + // Catch-all wildcard match (if not checking explicitly) + if ($explicit_check === FALSE AND isset(request::$accept_types['*']['*'])) + return request::$accept_types['*']['*']; + + // Content type not accepted + return 0; + } + + /** + * Parses client's HTTP Accept request header, and builds array structure representing it. + * + * @return void + */ + protected static function parse_accept_header() + { + // Run this function just once + if (request::$accept_types !== NULL) + return; + + // Initialize accept_types array + request::$accept_types = array(); + + // No HTTP Accept header found + if (empty($_SERVER['HTTP_ACCEPT'])) + { + // Accept everything + request::$accept_types['*']['*'] = 1; + return; + } + + // Remove linebreaks and parse the HTTP Accept header + foreach (explode(',', str_replace(array("\r", "\n"), '', $_SERVER['HTTP_ACCEPT'])) as $accept_entry) + { + // Explode each entry in content type and possible quality factor + $accept_entry = explode(';', trim($accept_entry), 2); + + // Explode each content type (e.g. "text/html") + $type = explode('/', $accept_entry[0], 2); + + // Skip invalid content types + if ( ! isset($type[1])) + continue; + + // Assume a default quality factor of 1 if no custom q value found + $q = (isset($accept_entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $accept_entry[1], $match)) ? (float) $match[1] : 1; + + // Populate accept_types array + if ( ! isset(request::$accept_types[$type[0]][$type[1]]) OR $q > request::$accept_types[$type[0]][$type[1]]) + { + request::$accept_types[$type[0]][$type[1]] = $q; + } + } + } + +} // End request \ No newline at end of file diff --git a/lib/kohana/system/helpers/security.php b/lib/kohana/system/helpers/security.php new file mode 100644 index 0000000..cd48d2e --- /dev/null +++ b/lib/kohana/system/helpers/security.php @@ -0,0 +1,47 @@ +xss_clean($str); + } + + /** + * Remove image tags from a string. + * + * @param string string to sanitize + * @return string + */ + public static function strip_image_tags($str) + { + return preg_replace('#\s]*)["\']?[^>]*)?>#is', '$1', $str); + } + + /** + * Remove PHP tags from a string. + * + * @param string string to sanitize + * @return string + */ + public static function encode_php_tags($str) + { + return str_replace(array(''), array('<?', '?>'), $str); + } + +} // End security \ No newline at end of file diff --git a/lib/kohana/system/helpers/text.php b/lib/kohana/system/helpers/text.php new file mode 100644 index 0000000..d0e573e --- /dev/null +++ b/lib/kohana/system/helpers/text.php @@ -0,0 +1,410 @@ + 1) + { + if (ctype_alpha($str)) + { + // Add a random digit + $str[mt_rand(0, $length - 1)] = chr(mt_rand(48, 57)); + } + elseif (ctype_digit($str)) + { + // Add a random letter + $str[mt_rand(0, $length - 1)] = chr(mt_rand(65, 90)); + } + } + + return $str; + } + + /** + * Reduces multiple slashes in a string to single slashes. + * + * @param string string to reduce slashes of + * @return string + */ + public static function reduce_slashes($str) + { + return preg_replace('#(? $badword) + { + $badwords[$key] = str_replace('\*', '\S*?', preg_quote((string) $badword)); + } + + $regex = '('.implode('|', $badwords).')'; + + if ($replace_partial_words == TRUE) + { + // Just using \b isn't sufficient when we need to replace a badword that already contains word boundaries itself + $regex = '(?<=\b|\s|^)'.$regex.'(?=\b|\s|$)'; + } + + $regex = '!'.$regex.'!ui'; + + if (utf8::strlen($replacement) == 1) + { + $regex .= 'e'; + return preg_replace($regex, 'str_repeat($replacement, utf8::strlen(\'$1\'))', $str); + } + + return preg_replace($regex, $replacement, $str); + } + + /** + * Finds the text that is similar between a set of words. + * + * @param array words to find similar text of + * @return string + */ + public static function similar(array $words) + { + // First word is the word to match against + $word = current($words); + + for ($i = 0, $max = strlen($word); $i < $max; ++$i) + { + foreach ($words as $w) + { + // Once a difference is found, break out of the loops + if ( ! isset($w[$i]) OR $w[$i] !== $word[$i]) + break 2; + } + } + + // Return the similar text + return substr($word, 0, $i); + } + + /** + * Converts text email addresses and anchors into links. + * + * @param string text to auto link + * @return string + */ + public static function auto_link($text) + { + // Auto link emails first to prevent problems with "www.domain.com@example.com" + return text::auto_link_urls(text::auto_link_emails($text)); + } + + /** + * Converts text anchors into links. + * + * @param string text to auto link + * @return string + */ + public static function auto_link_urls($text) + { + // Finds all http/https/ftp/ftps links that are not part of an existing html anchor + if (preg_match_all('~\b(?)(?:ht|f)tps?://\S+(?:/|\b)~i', $text, $matches)) + { + foreach ($matches[0] as $match) + { + // Replace each link with an anchor + $text = str_replace($match, html::anchor($match), $text); + } + } + + // Find all naked www.links.com (without http://) + if (preg_match_all('~\b(?|58;)(?!\.)[-+_a-z0-9.]++(? and
    markup to text. Basically nl2br() on steroids. + * + * @param string subject + * @return string + */ + public static function auto_p($str) + { + // Trim whitespace + if (($str = trim($str)) === '') + return ''; + + // Standardize newlines + $str = str_replace(array("\r\n", "\r"), "\n", $str); + + // Trim whitespace on each line + $str = preg_replace('~^[ \t]+~m', '', $str); + $str = preg_replace('~[ \t]+$~m', '', $str); + + // The following regexes only need to be executed if the string contains html + if ($html_found = (strpos($str, '<') !== FALSE)) + { + // Elements that should not be surrounded by p tags + $no_p = '(?:p|div|h[1-6r]|ul|ol|li|blockquote|d[dlt]|pre|t[dhr]|t(?:able|body|foot|head)|c(?:aption|olgroup)|form|s(?:elect|tyle)|a(?:ddress|rea)|ma(?:p|th))'; + + // Put at least two linebreaks before and after $no_p elements + $str = preg_replace('~^<'.$no_p.'[^>]*+>~im', "\n$0", $str); + $str = preg_replace('~$~im', "$0\n", $str); + } + + // Do the

    magic! + $str = '

    '.trim($str).'

    '; + $str = preg_replace('~\n{2,}~', "

    \n\n

    ", $str); + + // The following regexes only need to be executed if the string contains html + if ($html_found !== FALSE) + { + // Remove p tags around $no_p elements + $str = preg_replace('~

    (?=]*+>)~i', '', $str); + $str = preg_replace('~(]*+>)

    ~i', '$1', $str); + } + + // Convert single linebreaks to
    + $str = preg_replace('~(?\n", $str); + + return $str; + } + + /** + * Returns human readable sizes. + * @see Based on original functions written by: + * @see Aidan Lister: http://aidanlister.com/repos/v/function.size_readable.php + * @see Quentin Zervaas: http://www.phpriot.com/d/code/strings/filesize-format/ + * + * @param integer size in bytes + * @param string a definitive unit + * @param string the return string format + * @param boolean whether to use SI prefixes or IEC + * @return string + */ + public static function bytes($bytes, $force_unit = NULL, $format = NULL, $si = TRUE) + { + // Format string + $format = ($format === NULL) ? '%01.2f %s' : (string) $format; + + // IEC prefixes (binary) + if ($si == FALSE OR strpos($force_unit, 'i') !== FALSE) + { + $units = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'); + $mod = 1024; + } + // SI prefixes (decimal) + else + { + $units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB'); + $mod = 1000; + } + + // Determine unit to use + if (($power = array_search((string) $force_unit, $units)) === FALSE) + { + $power = ($bytes > 0) ? floor(log($bytes, $mod)) : 0; + } + + return sprintf($format, $bytes / pow($mod, $power), $units[$power]); + } + + /** + * Prevents widow words by inserting a non-breaking space between the last two words. + * @see http://www.shauninman.com/archive/2006/08/22/widont_wordpress_plugin + * + * @param string string to remove widows from + * @return string + */ + public static function widont($str) + { + $str = rtrim($str); + $space = strrpos($str, ' '); + + if ($space !== FALSE) + { + $str = substr($str, 0, $space).' '.substr($str, $space + 1); + } + + return $str; + } + +} // End text \ No newline at end of file diff --git a/lib/kohana/system/helpers/upload.php b/lib/kohana/system/helpers/upload.php new file mode 100644 index 0000000..422e9e8 --- /dev/null +++ b/lib/kohana/system/helpers/upload.php @@ -0,0 +1,162 @@ + 'Refresh', + '300' => 'Multiple Choices', + '301' => 'Moved Permanently', + '302' => 'Found', + '303' => 'See Other', + '304' => 'Not Modified', + '305' => 'Use Proxy', + '307' => 'Temporary Redirect' + ); + + // Validate the method and default to 302 + $method = isset($codes[$method]) ? (string) $method : '302'; + + if ($method === '300') + { + $uri = (array) $uri; + + $output = '
      '; + foreach ($uri as $link) + { + $output .= '
    • '.html::anchor($link).'
    • '; + } + $output .= '
    '; + + // The first URI will be used for the Location header + $uri = $uri[0]; + } + else + { + $output = '

    '.html::anchor($uri).'

    '; + } + + // Run the redirect event + Event::run('system.redirect', $uri); + + if (strpos($uri, '://') === FALSE) + { + // HTTP headers expect absolute URLs + $uri = url::site($uri, request::protocol()); + } + + if ($method === 'refresh') + { + header('Refresh: 0; url='.$uri); + } + else + { + header('HTTP/1.1 '.$method.' '.$codes[$method]); + header('Location: '.$uri); + } + + // We are about to exit, so run the send_headers event + Event::run('system.send_headers'); + + exit('

    '.$method.' - '.$codes[$method].'

    '.$output); + } + +} // End url \ No newline at end of file diff --git a/lib/kohana/system/helpers/valid.php b/lib/kohana/system/helpers/valid.php new file mode 100644 index 0000000..74517c0 --- /dev/null +++ b/lib/kohana/system/helpers/valid.php @@ -0,0 +1,330 @@ += 0; $i -= 2) + { + // Add up every 2nd digit, starting from the right + $checksum += $number[$i]; + } + + for ($i = $length - 2; $i >= 0; $i -= 2) + { + // Add up every 2nd digit doubled, starting from the right + $double = $number[$i] * 2; + + // Subtract 9 from the double where value is greater than 10 + $checksum += ($double >= 10) ? $double - 9 : $double; + } + + // If the checksum is a multiple of 10, the number is valid + return ($checksum % 10 === 0); + } + + /** + * Checks if a phone number is valid. + * + * @param string phone number to check + * @return boolean + */ + public static function phone($number, $lengths = NULL) + { + if ( ! is_array($lengths)) + { + $lengths = array(7,10,11); + } + + // Remove all non-digit characters from the number + $number = preg_replace('/\D+/', '', $number); + + // Check if the number is within range + return in_array(strlen($number), $lengths); + } + + /** + * Tests if a string is a valid date string. + * + * @param string date to check + * @return boolean + */ + public static function date($str) + { + return (strtotime($str) !== FALSE); + } + + /** + * Checks whether a string consists of alphabetical characters only. + * + * @param string input string + * @param boolean trigger UTF-8 compatibility + * @return boolean + */ + public static function alpha($str, $utf8 = FALSE) + { + return ($utf8 === TRUE) + ? (bool) preg_match('/^\pL++$/uD', (string) $str) + : ctype_alpha((string) $str); + } + + /** + * Checks whether a string consists of alphabetical characters and numbers only. + * + * @param string input string + * @param boolean trigger UTF-8 compatibility + * @return boolean + */ + public static function alpha_numeric($str, $utf8 = FALSE) + { + return ($utf8 === TRUE) + ? (bool) preg_match('/^[\pL\pN]++$/uD', (string) $str) + : ctype_alnum((string) $str); + } + + /** + * Checks whether a string consists of alphabetical characters, numbers, underscores and dashes only. + * + * @param string input string + * @param boolean trigger UTF-8 compatibility + * @return boolean + */ + public static function alpha_dash($str, $utf8 = FALSE) + { + return ($utf8 === TRUE) + ? (bool) preg_match('/^[-\pL\pN_]++$/uD', (string) $str) + : (bool) preg_match('/^[-a-z0-9_]++$/iD', (string) $str); + } + + /** + * Checks whether a string consists of digits only (no dots or dashes). + * + * @param string input string + * @param boolean trigger UTF-8 compatibility + * @return boolean + */ + public static function digit($str, $utf8 = FALSE) + { + return ($utf8 === TRUE) + ? (bool) preg_match('/^\pN++$/uD', (string) $str) + : ctype_digit((string) $str); + } + + /** + * Checks whether a string is a valid number (negative and decimal numbers allowed). + * + * @see Uses locale conversion to allow decimal point to be locale specific. + * @see http://www.php.net/manual/en/function.localeconv.php + * + * @param string input string + * @return boolean + */ + public static function numeric($str) + { + // Use localeconv to set the decimal_point value: Usually a comma or period. + $locale = localeconv(); + return (bool) preg_match('/^-?[0-9'.$locale['decimal_point'].']++$/D', (string) $str); + } + + /** + * Checks whether a string is a valid text. Letters, numbers, whitespace, + * dashes, periods, and underscores are allowed. + * + * @param string text to check + * @return boolean + */ + public static function standard_text($str) + { + // pL matches letters + // pN matches numbers + // pZ matches whitespace + // pPc matches underscores + // pPd matches dashes + // pPo matches normal puncuation + return (bool) preg_match('/^[\pL\pN\pZ\p{Pc}\p{Pd}\p{Po}]++$/uD', (string) $str); + } + + /** + * Checks if a string is a proper decimal format. The format array can be + * used to specify a decimal length, or a number and decimal length, eg: + * array(2) would force the number to have 2 decimal places, array(4,2) + * would force the number to have 4 digits and 2 decimal places. + * + * @param string input string + * @param array decimal format: y or x,y + * @return boolean + */ + public static function decimal($str, $format = NULL) + { + // Create the pattern + $pattern = '/^[0-9]%s\.[0-9]%s$/'; + + if ( ! empty($format)) + { + if (count($format) > 1) + { + // Use the format for number and decimal length + $pattern = sprintf($pattern, '{'.$format[0].'}', '{'.$format[1].'}'); + } + elseif (count($format) > 0) + { + // Use the format as decimal length + $pattern = sprintf($pattern, '+', '{'.$format[0].'}'); + } + } + else + { + // No format + $pattern = sprintf($pattern, '+', '+'); + } + + return (bool) preg_match($pattern, (string) $str); + } + +} // End valid diff --git a/lib/kohana/system/i18n/de_DE/cache.php b/lib/kohana/system/i18n/de_DE/cache.php new file mode 100644 index 0000000..53f32aa --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/cache.php @@ -0,0 +1,10 @@ + 'Die Gruppe %s ist in Ihrer Konfiguration nicht definiert.', + 'extension_not_loaded' => 'Die PHP-Erweiterung %s muss geladen sein, um diesen Treiber benutzen zu können.', + 'unwritable' => 'Der eingestellte Speicherort %s ist nicht beschreibbar.', + 'resources' => 'Das Cachen von Ressourcen ist nicht möglich, da diese nicht serialisiert werden können.', + 'driver_error' => '%s' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/calendar.php b/lib/kohana/system/i18n/de_DE/calendar.php new file mode 100644 index 0000000..d95f54b --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/calendar.php @@ -0,0 +1,59 @@ + 'So', + 'mo' => 'Mo', + 'tu' => 'Di', + 'we' => 'Mi', + 'th' => 'Do', + 'fr' => 'Fr', + 'sa' => 'Sa', + + // Short day names + 'sun' => 'Son', + 'mon' => 'Mon', + 'tue' => 'Die', + 'wed' => 'Mit', + 'thu' => 'Don', + 'fri' => 'Fre', + 'sat' => 'Sam', + + // Long day names + 'sunday' => 'Sonntag', + 'monday' => 'Montag', + 'tuesday' => 'Dienstag', + 'wednesday' => 'Mittwoch', + 'thursday' => 'Donnerstag', + 'friday' => 'Freitag', + 'saturday' => 'Samstag', + + // Short month names + 'jan' => 'Jan', + 'feb' => 'Feb', + 'mar' => 'Mär', + 'apr' => 'Apr', + 'may' => 'Mai', + 'jun' => 'Jun', + 'jul' => 'Jul', + 'aug' => 'Aug', + 'sep' => 'Sep', + 'oct' => 'Okt', + 'nov' => 'Nov', + 'dec' => 'Dez', + + // Long month names + 'january' => 'Januar', + 'february' => 'Februar', + 'march' => 'März', + 'april' => 'April', + 'mayl' => 'Mai', + 'june' => 'Juni', + 'july' => 'Juli', + 'august' => 'August', + 'september' => 'September', + 'october' => 'Oktober', + 'november' => 'November', + 'december' => 'Dezember' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/captcha.php b/lib/kohana/system/i18n/de_DE/captcha.php new file mode 100644 index 0000000..0a5ce5e --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/captcha.php @@ -0,0 +1,33 @@ + 'Die eingestellte Datei %s konnte nicht gefunden werden. Kontrollieren Sie bitte, bevor Sie Dateien benutzen, ob diese existieren. Sie können dafür die Funktion file_exists() benutzen.', + 'requires_GD2' => 'Die Captcha-Bibliothek erfordert GD2 mit FreeType-Unterstützung. Sehen Sie sich die Seite http://php.net/gd_info an, um weitere Informationen zu erhalten.', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'it', 'to', 'be', 'or', + 'sun', 'car', 'dog', 'bed', 'kid', 'egg', + 'bike', 'tree', 'bath', 'roof', 'road', 'hair', + 'hello', 'world', 'earth', 'beard', 'chess', 'water', + 'barber', 'bakery', 'banana', 'market', 'purple', 'writer', + 'america', 'release', 'playing', 'working', 'foreign', 'general', + 'aircraft', 'computer', 'laughter', 'alphabet', 'kangaroo', 'spelling', + 'architect', 'president', 'cockroach', 'encounter', 'terrorism', 'cylinders', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('Hasst du Spam? (ja oder nein)', 'ja'), + array('Bist du ein Roboter? (ja oder nein)', 'nein'), + array('Feuer ist ... (heiß or kalt)', 'heiß'), + array('Die Jahreszeit, die nach Herbst kommt ist ...', 'Winter'), + array('Welcher Wochentag ist heute?', strftime('%A')), + array('In welchem Monat befinden wir uns gerade?', strftime('%B')), + ), +); diff --git a/lib/kohana/system/i18n/de_DE/core.php b/lib/kohana/system/i18n/de_DE/core.php new file mode 100644 index 0000000..a47ded2 --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/core.php @@ -0,0 +1,34 @@ + 'Pro Seitenaufruf kann es nur eine Instanz von Kohana geben', + 'uncaught_exception' => 'Unerwarteter Fehler vom Typ %s: %s in %s in Zeile %s', + 'invalid_method' => 'Ungültige Methode %s aufgerufen in %s', + 'invalid_property' => '%s ist keine Eigenschaft der Klasse %s.', + 'log_dir_unwritable' => 'Das Log-Verzeichnis ist nicht beschreibbar: %s', + 'resource_not_found' => '%s %s konnte nicht gefunden werden', + 'invalid_filetype' => 'Die Dateiendung .%s ist in Ihrer View-Konfiguration nicht vorhanden', + 'view_set_filename' => 'Sie müssen den Dateinamen der Ansicht festlegen, bevor render aufgerufen wird', + 'no_default_route' => 'Erstellen Sie bitte eine Standardroute config/routes.php', + 'no_controller' => 'Kohana gelang es nicht einen Controller zu finden, um diesen Aufruf zu verarbeiten: %s', + 'page_not_found' => 'Die Seite %s konnte nicht gefunden werden.', + 'stats_footer' => 'Seite geladen in {execution_time} Sekunden bei {memory_usage} Speichernutzung. Generiert von Kohana v{kohana_version}.', + 'error_file_line' => '%s [%s]:', + 'stack_trace' => 'Stack Trace', + 'generic_error' => 'Die Abfrage konnte nicht abgeschlossen werden', + 'errors_disabled' => 'Sie können zur Startseite zurück kehren oder es erneut versuchen.', + + // Drivers + 'driver_implements' => 'Der Treiber %s für die Bibliothek %s muss das Interface %s implementieren', + 'driver_not_found' => 'Der Treiber %s für die Bibliothek %s konnte nicht gefunden werden', + + // Resource names + 'config' => 'Die Konfigurationsdatei', + 'controller' => 'Der Controller', + 'helper' => 'Der Helfer', + 'library' => 'Die Bibliothek', + 'driver' => 'Der Treiber', + 'model' => 'Das Modell', + 'view' => 'Die Ansicht', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/database.php b/lib/kohana/system/i18n/de_DE/database.php new file mode 100644 index 0000000..58edf3b --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/database.php @@ -0,0 +1,15 @@ + 'Die Gruppe %s ist in Ihrer Konfiguration nicht definiert worden.', + 'error' => 'Es gab einen SQL-Fehler: %s', + 'connection' => 'Es gab einen Fehler bei der Verbindung mit der Datenbank: %s', + 'invalid_dsn' => 'Die von Ihnen angegebene DSN ist ungültig: %s', + 'must_use_set' => 'Sie müssen SET in Ihrem Query benutzen.', + 'must_use_where' => 'Sie müssen WHERE in Ihrem Query benutzen.', + 'must_use_table' => 'Sie müssen eine Tabelle für Ihren Query angeben.', + 'table_not_found' => 'Die Tabelle %s konnte in der Datenbank nicht gefunden werden.', + 'not_implemented' => 'Die Methode %s wird von diesem Datenbanktreiber nicht unterstützt.', + 'result_read_only' => 'Ergebnisse der Anfrage können nur gelesen werden.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/encrypt.php b/lib/kohana/system/i18n/de_DE/encrypt.php new file mode 100644 index 0000000..1933969 --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/encrypt.php @@ -0,0 +1,8 @@ + 'Die Gruppe %s ist nicht in Ihrer Konfiguration enthalten.', + 'requires_mcrypt' => 'Um die Bibliothek Encrypt zu benutzen, muss mcrypt in Ihrer PHP-Installation aktiviert werden', + 'no_encryption_key' => 'Um die Bibliothek Encrypt zu benutzen, müssen Sie einen Schlüssel in Ihrer Konfiguration eintragen' +); diff --git a/lib/kohana/system/i18n/de_DE/errors.php b/lib/kohana/system/i18n/de_DE/errors.php new file mode 100644 index 0000000..92e281c --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/errors.php @@ -0,0 +1,16 @@ + array( 1, 'Framework-Fehler', 'Lesen Sie bitte in der Kohana-Dokumentation, um mehr über den folgenden Fehler zu erfahren.'), + E_PAGE_NOT_FOUND => array( 1, 'Seite Nicht Gefunden', 'Die aufgerufene Seite wurde nicht gefunden. Sie wurde entweder verschoben, gelöscht oder archiviert.'), + E_DATABASE_ERROR => array( 1, 'Datenbank-Fehler', 'Ein Datenbankfehler ist während des Aufrufs aufgetreten. Überprüfen Sie bitte den unten stehenden Fehler für mehr Informationen.'), + E_RECOVERABLE_ERROR => array( 1, 'Behebbarer Fehler', 'Es ist ein Fehler aufgetreten, der das Laden der Seite verhindert hat. Wenn der Fehler weiterhin besteht, kontaktieren Sie bitte den Administrator der Seite.'), + E_ERROR => array( 1, 'Fataler Fehler', ''), + E_USER_ERROR => array( 1, 'Fataler Fehler', ''), + E_PARSE => array( 1, 'Syntax-Fehler', ''), + E_WARNING => array( 1, 'Warnung', ''), + E_USER_WARNING => array( 1, 'Warnung', ''), + E_STRICT => array( 2, 'Strict Mode Error', ''), + E_NOTICE => array( 2, 'Laufzeitfehler', ''), +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/event.php b/lib/kohana/system/i18n/de_DE/event.php new file mode 100644 index 0000000..e299e05 --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/event.php @@ -0,0 +1,7 @@ + 'Der Versuch, das ungültige Subjekt %s an %s anzuhängen, ist fehlgeschlagen. Subjekte müssen die Klasse Event_Subject erweitern.', + 'invalid_observer' => 'Der Versuch, den ungültigen Beobachter %s an %s anzuhängen, ist fehlgeschlagen. Beobachter müssen die Klasse Event_Observer erweitern.', +); diff --git a/lib/kohana/system/i18n/de_DE/image.php b/lib/kohana/system/i18n/de_DE/image.php new file mode 100644 index 0000000..b12b13c --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/image.php @@ -0,0 +1,33 @@ + 'Die Bildbibliothek versucht die PHP-Funktion getimagesize() zu benutzen, die aber nicht Bestandteil ihrer PHP-Installation ist.', + 'unsupported_method' => 'Der Bildtreiber, den Sie benutzen, unterstützt nicht die %s-Bildtransformation.', + 'file_not_found' => 'Das angegebene Bild %s konnte nicht gefunden werden. Stellen Sie bitte sicher, dass das Bild existiert. Benutzen Sie hierzu die Funktion file_exists().', + 'type_not_allowed' => 'Das angegebene Bild %s ist kein erlaubter Bildtyp.', + 'invalid_width' => 'Die von Ihnen festgelegte Bildbreite, %s, ist ungültig.', + 'invalid_height' => 'Die von Ihnen festgelegte Bildhöhe, %s, ist ungültig.', + 'invalid_dimensions' => 'Das festgelegte Format für %s ist ungültig.', + 'invalid_master' => 'Die festgelegte Master-Dimension ist ungültig.', + 'invalid_flip' => 'Die festgelegte Richtung der Spiegelung ist ungültig.', + 'directory_unwritable' => 'Das Verzeichnis %s ist nicht beschreibbar.', + + // ImageMagick specific messages + 'imagemagick' => array + ( + 'not_found' => 'Das festgelegte ImageMagic-Verzeichnis enthält nicht das benötigte Programm %s.', + ), + + // GraphicsMagick specific messages + 'graphicsmagick' => array + ( + 'not_found' => 'Das festgelegte GraphicsMagick-Verzeichnis enthält nicht das benötigte Programm %s.', + ), + + // GD specific messages + 'gd' => array + ( + 'requires_v2' => 'Die Bildbibliothek erfordert GD2. Sehen Sie sich die Seite http://php.net/gd_info an, um weitere Informationen zu erhalten.', + ), +); diff --git a/lib/kohana/system/i18n/de_DE/orm.php b/lib/kohana/system/i18n/de_DE/orm.php new file mode 100644 index 0000000..b03df5b --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/orm.php @@ -0,0 +1,3 @@ + 'Die Gruppe %s ist nicht in der Pagination-Konfiguration definiert worden.', + 'page' => 'Seite', + 'pages' => 'Seiten', + 'item' => 'Element', + 'items' => 'Elemente', + 'of' => 'von', + 'first' => 'Erste', + 'last' => 'Letzte', + 'previous' => 'Vorherige', + 'next' => 'Nächste', +); diff --git a/lib/kohana/system/i18n/de_DE/profiler.php b/lib/kohana/system/i18n/de_DE/profiler.php new file mode 100644 index 0000000..1b16433 --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/profiler.php @@ -0,0 +1,15 @@ + 'Benchmark-Tests', + 'post_data' => 'POST-Daten:', + 'no_post' => 'Keine POST-Daten', + 'session_data' => 'Session-Daten', + 'no_session' => 'Keine Session-Daten', + 'queries' => 'Datenbank-Anfragen', + 'no_queries' => 'Keine Anfragen', + 'no_database' => 'Datenbank nicht geladen', + 'cookie_data' => 'Cookie-Daten', + 'no_cookie' => 'Keine Cookie-Daten', +); diff --git a/lib/kohana/system/i18n/de_DE/session.php b/lib/kohana/system/i18n/de_DE/session.php new file mode 100644 index 0000000..abbd912 --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/session.php @@ -0,0 +1,6 @@ + 'Der Sessionname %s ist ungültig. Dieser darf nur aus alphanumerischen Zeichen und mindestens einem Buchstaben bestehen.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/swift.php b/lib/kohana/system/i18n/de_DE/swift.php new file mode 100644 index 0000000..88b112b --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/swift.php @@ -0,0 +1,6 @@ + 'Fehler beim Senden einer E-Mail aufgetreten.' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/upload.php b/lib/kohana/system/i18n/de_DE/upload.php new file mode 100644 index 0000000..181d389 --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/upload.php @@ -0,0 +1,6 @@ + 'Das Verzeichnis für hochgeladene Dateien, %s, ist nicht beschreibbar.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/de_DE/validation.php b/lib/kohana/system/i18n/de_DE/validation.php new file mode 100644 index 0000000..d1797da --- /dev/null +++ b/lib/kohana/system/i18n/de_DE/validation.php @@ -0,0 +1,41 @@ + 'Ungültige Validierungsregel benutzt: %s', + 'i18n_array' => 'Der i18n-Schlüssel %s muss ein Array sein, um diesen in der in_array-Regel benutzen zu können', + 'not_callable' => 'Die Callback-Funktion %s, die zur Validierung benutzt wird, ist nicht aufrufbar', + + // General errors + 'unknown_error' => 'Unbekannter Fehler bei der Validierungsregel von dem Feld %s aufgetreten.', + 'required' => 'Das Feld %s ist erforderlich.', + 'min_length' => 'Das Feld %s muss mindestens %d Zeichen lang sein.', + 'max_length' => 'Das Feld %s darf höchstens %d Zeichen lang sein.', + 'exact_length' => 'Das Feld %s muss genau %d Zeichen enthalten.', + 'in_array' => 'Das Feld %s muss ausgewählt werden.', + 'matches' => 'Das Feld %s muss mit dem Feld %s übereinstimmen.', + 'valid_url' => 'Das Feld %s muss eine gültige URL beinhalten.', + 'valid_email' => 'Das Feld %s muss eine gültige E-Mailadresse beinhalten.', + 'valid_ip' => 'Das Feld %s muss eine gültige IP-Adresse beinhalten.', + 'valid_type' => 'Das Feld %s darf nur %s beinhalten.', + 'range' => 'Das Feld %s muss zwischen festgelegten Bereichen sein.', + 'regex' => 'Das Feld %s entspricht nicht einer akzeptierten Eingabe.', + 'depends_on' => 'Das Feld %s hängt vom Feld %s ab.', + + // Upload errors + 'user_aborted' => 'Das Hochladen der Datei %s wurde abgebrochen.', + 'invalid_type' => 'Die Datei %s entspricht nicht den erlaubten Dateitypen.', + 'max_size' => 'Die Datei %s ist zu groß. Die maximale Größe beträgt %s.', + 'max_width' => 'Die Datei %s ist zu groß. Die maximal erlaubte Breite betägt %spx.', + 'max_height' => 'Die Datei %s ist zu groß. Die maximal erlaubte Höhe betägt %spx.', + 'min_width' => 'Die Datei %s ist zu klein. Die minimal erlaubte Breite betägt %spx.', + 'min_height' => 'Die Datei %s ist zu klein. Die minimal erlaubte Höhe betägt %spx.', + + // Field types + 'alpha' => 'alphabetische Zeichen', + 'alpha_numeric' => 'alphabetische und numerische Zeichen', + 'alpha_dash' => 'alphabetische Zeichen, Trennstriche und Unterstriche', + 'digit' => 'Zahlen', + 'numeric' => 'Nummern', +); diff --git a/lib/kohana/system/i18n/en_US/cache.php b/lib/kohana/system/i18n/en_US/cache.php new file mode 100644 index 0000000..bef0279 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/cache.php @@ -0,0 +1,10 @@ + 'The %s group is not defined in your configuration.', + 'extension_not_loaded' => 'The %s PHP extension must be loaded to use this driver.', + 'unwritable' => 'The configured storage location, %s, is not writable.', + 'resources' => 'Caching of resources is impossible, because resources cannot be serialized.', + 'driver_error' => '%s', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/en_US/calendar.php b/lib/kohana/system/i18n/en_US/calendar.php new file mode 100644 index 0000000..21dad22 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/calendar.php @@ -0,0 +1,59 @@ + 'Su', + 'mo' => 'Mo', + 'tu' => 'Tu', + 'we' => 'We', + 'th' => 'Th', + 'fr' => 'Fr', + 'sa' => 'Sa', + + // Short day names + 'sun' => 'Sun', + 'mon' => 'Mon', + 'tue' => 'Tue', + 'wed' => 'Wed', + 'thu' => 'Thu', + 'fri' => 'Fri', + 'sat' => 'Sat', + + // Long day names + 'sunday' => 'Sunday', + 'monday' => 'Monday', + 'tuesday' => 'Tuesday', + 'wednesday' => 'Wednesday', + 'thursday' => 'Thursday', + 'friday' => 'Friday', + 'saturday' => 'Saturday', + + // Short month names + 'jan' => 'Jan', + 'feb' => 'Feb', + 'mar' => 'Mar', + 'apr' => 'Apr', + 'may' => 'May', + 'jun' => 'Jun', + 'jul' => 'Jul', + 'aug' => 'Aug', + 'sep' => 'Sep', + 'oct' => 'Oct', + 'nov' => 'Nov', + 'dec' => 'Dec', + + // Long month names + 'january' => 'January', + 'february' => 'February', + 'march' => 'March', + 'april' => 'April', + 'mayl' => 'May', + 'june' => 'June', + 'july' => 'July', + 'august' => 'August', + 'september' => 'September', + 'october' => 'October', + 'november' => 'November', + 'december' => 'December' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/en_US/captcha.php b/lib/kohana/system/i18n/en_US/captcha.php new file mode 100644 index 0000000..6040471 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/captcha.php @@ -0,0 +1,33 @@ + 'The specified file, %s, was not found. Please verify that files exist by using file_exists() before using them.', + 'requires_GD2' => 'The Captcha library requires GD2 with FreeType support. Please see http://php.net/gd_info for more information.', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'it', 'to', 'be', 'or', + 'sun', 'car', 'dog', 'bed', 'kid', 'egg', + 'bike', 'tree', 'bath', 'roof', 'road', 'hair', + 'hello', 'world', 'earth', 'beard', 'chess', 'water', + 'barber', 'bakery', 'banana', 'market', 'purple', 'writer', + 'america', 'release', 'playing', 'working', 'foreign', 'general', + 'aircraft', 'computer', 'laughter', 'alphabet', 'kangaroo', 'spelling', + 'architect', 'president', 'cockroach', 'encounter', 'terrorism', 'cylinders', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('Do you hate spam? (yes or no)', 'yes'), + array('Are you a robot? (yes or no)', 'no'), + array('Fire is... (hot or cold)', 'hot'), + array('The season after fall is...', 'winter'), + array('Which day of the week is it today?', strftime('%A')), + array('Which month of the year are we in?', strftime('%B')), + ), +); diff --git a/lib/kohana/system/i18n/en_US/core.php b/lib/kohana/system/i18n/en_US/core.php new file mode 100644 index 0000000..9711b7c --- /dev/null +++ b/lib/kohana/system/i18n/en_US/core.php @@ -0,0 +1,34 @@ + 'There can be only one instance of Kohana per page request', + 'uncaught_exception' => 'Uncaught %s: %s in file %s on line %s', + 'invalid_method' => 'Invalid method %s called in %s', + 'invalid_property' => 'The %s property does not exist in the %s class.', + 'log_dir_unwritable' => 'The log directory is not writable: %s', + 'resource_not_found' => 'The requested %s, %s, could not be found', + 'invalid_filetype' => 'The requested filetype, .%s, is not allowed in your view configuration file', + 'view_set_filename' => 'You must set the the view filename before calling render', + 'no_default_route' => 'Please set a default route in config/routes.php', + 'no_controller' => 'Kohana was not able to determine a controller to process this request: %s', + 'page_not_found' => 'The page you requested, %s, could not be found.', + 'stats_footer' => 'Loaded in {execution_time} seconds, using {memory_usage} of memory. Generated by Kohana v{kohana_version}.', + 'error_file_line' => '%s [%s]:', + 'stack_trace' => 'Stack Trace', + 'generic_error' => 'Unable to Complete Request', + 'errors_disabled' => 'You can go to the home page or try again.', + + // Drivers + 'driver_implements' => 'The %s driver for the %s library must implement the %s interface', + 'driver_not_found' => 'The %s driver for the %s library could not be found', + + // Resource names + 'config' => 'config file', + 'controller' => 'controller', + 'helper' => 'helper', + 'library' => 'library', + 'driver' => 'driver', + 'model' => 'model', + 'view' => 'view', +); diff --git a/lib/kohana/system/i18n/en_US/database.php b/lib/kohana/system/i18n/en_US/database.php new file mode 100644 index 0000000..172e5c9 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/database.php @@ -0,0 +1,15 @@ + 'The %s group is not defined in your configuration.', + 'error' => 'There was an SQL error: %s', + 'connection' => 'There was an error connecting to the database: %s', + 'invalid_dsn' => 'The DSN you supplied is not valid: %s', + 'must_use_set' => 'You must set a SET clause for your query.', + 'must_use_where' => 'You must set a WHERE clause for your query.', + 'must_use_table' => 'You must set a database table for your query.', + 'table_not_found' => 'Table %s does not exist in your database.', + 'not_implemented' => 'The method you called, %s, is not supported by this driver.', + 'result_read_only' => 'Query results are read only.' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/en_US/encrypt.php b/lib/kohana/system/i18n/en_US/encrypt.php new file mode 100644 index 0000000..9afd620 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/encrypt.php @@ -0,0 +1,8 @@ + 'The %s group is not defined in your configuration.', + 'requires_mcrypt' => 'To use the Encrypt library, mcrypt must be enabled in your PHP installation', + 'no_encryption_key' => 'To use the Encrypt library, you must set an encryption key in your config file' +); diff --git a/lib/kohana/system/i18n/en_US/errors.php b/lib/kohana/system/i18n/en_US/errors.php new file mode 100644 index 0000000..10f44ff --- /dev/null +++ b/lib/kohana/system/i18n/en_US/errors.php @@ -0,0 +1,15 @@ + array( 1, 'Framework Error', 'Please check the Kohana documentation for information about the following error.'), + E_PAGE_NOT_FOUND => array( 1, 'Page Not Found', 'The requested page was not found. It may have moved, been deleted, or archived.'), + E_DATABASE_ERROR => array( 1, 'Database Error', 'A database error occurred while performing the requested procedure. Please review the database error below for more information.'), + E_ERROR => array( 1, 'Fatal Error', ''), + E_USER_ERROR => array( 1, 'Fatal Error', ''), + E_PARSE => array( 1, 'Syntax Error', ''), + E_WARNING => array( 1, 'Warning Message', ''), + E_USER_WARNING => array( 1, 'Warning Message', ''), + E_STRICT => array( 2, 'Strict Mode Error', ''), + E_NOTICE => array( 2, 'Runtime Message', ''), +); diff --git a/lib/kohana/system/i18n/en_US/event.php b/lib/kohana/system/i18n/en_US/event.php new file mode 100644 index 0000000..282a0a2 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/event.php @@ -0,0 +1,7 @@ + 'Attempt to attach invalid subject %s to %s failed: Subjects must extend the Event_Subject class', + 'invalid_observer' => 'Attempt to attach invalid observer %s to %s failed: Observers must extend the Event_Observer class', +); diff --git a/lib/kohana/system/i18n/en_US/image.php b/lib/kohana/system/i18n/en_US/image.php new file mode 100644 index 0000000..9f18493 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/image.php @@ -0,0 +1,33 @@ + 'The Image library requires the getimagesize() PHP function, which is not available in your installation.', + 'unsupported_method' => 'Your configured driver does not support the %s image transformation.', + 'file_not_found' => 'The specified image, %s, was not found. Please verify that images exist by using file_exists() before manipulating them.', + 'type_not_allowed' => 'The specified image, %s, is not an allowed image type.', + 'invalid_width' => 'The width you specified, %s, is not valid.', + 'invalid_height' => 'The height you specified, %s, is not valid.', + 'invalid_dimensions' => 'The dimensions specified for %s are not valid.', + 'invalid_master' => 'The master dimension specified is not valid.', + 'invalid_flip' => 'The flip direction specified is not valid.', + 'directory_unwritable' => 'The specified directory, %s, is not writable.', + + // ImageMagick specific messages + 'imagemagick' => array + ( + 'not_found' => 'The ImageMagick directory specified does not contain a required program, %s.', + ), + + // GraphicsMagick specific messages + 'graphicsmagick' => array + ( + 'not_found' => 'The GraphicsMagick directory specified does not contain a required program, %s.', + ), + + // GD specific messages + 'gd' => array + ( + 'requires_v2' => 'The Image library requires GD2. Please see http://php.net/gd_info for more information.', + ), +); diff --git a/lib/kohana/system/i18n/en_US/orm.php b/lib/kohana/system/i18n/en_US/orm.php new file mode 100644 index 0000000..3c5720b --- /dev/null +++ b/lib/kohana/system/i18n/en_US/orm.php @@ -0,0 +1,3 @@ + 'The %s group is not defined in your pagination configuration.', + 'page' => 'page', + 'pages' => 'pages', + 'item' => 'item', + 'items' => 'items', + 'of' => 'of', + 'first' => 'first', + 'last' => 'last', + 'previous' => 'previous', + 'next' => 'next', +); diff --git a/lib/kohana/system/i18n/en_US/profiler.php b/lib/kohana/system/i18n/en_US/profiler.php new file mode 100644 index 0000000..a39c2f5 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/profiler.php @@ -0,0 +1,15 @@ + 'Benchmarks', + 'post_data' => 'Post Data', + 'no_post' => 'No post data', + 'session_data' => 'Session Data', + 'no_session' => 'No session data', + 'queries' => 'Database Queries', + 'no_queries' => 'No queries', + 'no_database' => 'Database not loaded', + 'cookie_data' => 'Cookie Data', + 'no_cookie' => 'No cookie data', +); diff --git a/lib/kohana/system/i18n/en_US/session.php b/lib/kohana/system/i18n/en_US/session.php new file mode 100644 index 0000000..ee781c6 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/session.php @@ -0,0 +1,6 @@ + 'The session_name, %s, is invalid. It must contain only alphanumeric characters and underscores. Also at least one letter must be present.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/en_US/swift.php b/lib/kohana/system/i18n/en_US/swift.php new file mode 100644 index 0000000..249c4a8 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/swift.php @@ -0,0 +1,6 @@ + 'An error occurred while sending the email message.' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/en_US/upload.php b/lib/kohana/system/i18n/en_US/upload.php new file mode 100644 index 0000000..7f6e216 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/upload.php @@ -0,0 +1,6 @@ + 'The upload destination folder, %s, does not appear to be writable.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/en_US/validation.php b/lib/kohana/system/i18n/en_US/validation.php new file mode 100644 index 0000000..d98e548 --- /dev/null +++ b/lib/kohana/system/i18n/en_US/validation.php @@ -0,0 +1,41 @@ + 'Invalid validation rule used: %s', + 'i18n_array' => 'The %s i18n key must be an array to be used with the in_lang rule', + 'not_callable' => 'Callback %s used for Validation is not callable', + + // General errors + 'unknown_error' => 'Unknown validation error while validating the %s field.', + 'required' => 'The %s field is required.', + 'min_length' => 'The %s field must be at least %d characters long.', + 'max_length' => 'The %s field must be %d characters or fewer.', + 'exact_length' => 'The %s field must be exactly %d characters.', + 'in_array' => 'The %s field must be selected from the options listed.', + 'matches' => 'The %s field must match the %s field.', + 'valid_url' => 'The %s field must contain a valid URL.', + 'valid_email' => 'The %s field must contain a valid email address.', + 'valid_ip' => 'The %s field must contain a valid IP address.', + 'valid_type' => 'The %s field must only contain %s characters.', + 'range' => 'The %s field must be between specified ranges.', + 'regex' => 'The %s field does not match accepted input.', + 'depends_on' => 'The %s field depends on the %s field.', + + // Upload errors + 'user_aborted' => 'The %s file was aborted during upload.', + 'invalid_type' => 'The %s file is not an allowed file type.', + 'max_size' => 'The %s file you uploaded was too large. The maximum size allowed is %s.', + 'max_width' => 'The %s file you uploaded was too big. The maximum allowed width is %spx.', + 'max_height' => 'The %s file you uploaded was too big. The maximum allowed height is %spx.', + 'min_width' => 'The %s file you uploaded was too small. The minimum allowed width is %spx.', + 'min_height' => 'The %s file you uploaded was too small. The minimum allowed height is %spx.', + + // Field types + 'alpha' => 'alphabetical', + 'alpha_numeric' => 'alphabetical and numeric', + 'alpha_dash' => 'alphabetical, dash, and underscore', + 'digit' => 'digit', + 'numeric' => 'numeric', +); diff --git a/lib/kohana/system/i18n/es_ES/cache.php b/lib/kohana/system/i18n/es_ES/cache.php new file mode 100644 index 0000000..c05e4cb --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/cache.php @@ -0,0 +1,10 @@ + 'El grupo %s no esta definido en la configuracion.', + 'extension_not_loaded' => 'La extensión PHP %s tiene que estar cargada para poder utilizar este driver.', + 'unwritable' => 'El directorio seleccionado, %s, no tiene permisos de escritura.', + 'resources' => 'No es posible guardar el contenido en la cache, el contenido no es serializable.', + 'driver_error' => '%s', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/calendar.php b/lib/kohana/system/i18n/es_ES/calendar.php new file mode 100644 index 0000000..961b223 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/calendar.php @@ -0,0 +1,55 @@ + 'Do', + 'mo' => 'Lu', + 'tu' => 'Ma', + 'we' => 'Mi', + 'th' => 'Ju', + 'fr' => 'Vi', + 'sa' => 'Sa', + // Short day names + 'sun' => 'Dom', + 'mon' => 'Lun', + 'tue' => 'Mar', + 'wed' => 'Mie', + 'thu' => 'Jue', + 'fri' => 'Vie', + 'sat' => 'Sab', + // Long day names + 'sunday' => 'Domingo', + 'monday' => 'Lunes', + 'tuesday' => 'Martes', + 'wednesday' => 'Miércoles', + 'thursday' => 'Jueves', + 'friday' => 'Viernes', + 'saturday' => 'Sábado', + // Short month names + 'jan' => 'Ene', + 'feb' => 'Feb', + 'mar' => 'Mar', + 'apr' => 'Abr', + 'may' => 'May', + 'jun' => 'Jun', + 'jul' => 'Jul', + 'aug' => 'Ago', + 'sep' => 'Sep', + 'oct' => 'Oct', + 'nov' => 'Nov', + 'dec' => 'Dic', + // Long month names + 'january' => 'Enero', + 'february' => 'Febrero', + 'march' => 'Marzo', + 'april' => 'Abril', + 'mayl' => 'Mayo', + 'june' => 'Junio', + 'july' => 'Julio', + 'august' => 'Agosto', + 'september' => 'Septiembre', + 'october' => 'Octubre', + 'november' => 'Noviembre', + 'december' => 'Diciembre', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/captcha.php b/lib/kohana/system/i18n/es_ES/captcha.php new file mode 100644 index 0000000..6c2cd15 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/captcha.php @@ -0,0 +1,33 @@ + 'El archivo especificado, %s, no ha sido encontrado. Por favor, verifica que el fichero existe utilizando file_exists() antes de intentar utilizarlo.', + 'requires_GD2' => 'La libreria Captcha requiere GD2 con soporte FreeType. Lea lo siguiente http://php.net/gd_info para ampliar la informacion.', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'it', 'to', 'be', 'or', + 'sun', 'car', 'dog', 'bed', 'kid', 'egg', + 'bike', 'tree', 'bath', 'roof', 'road', 'hair', + 'hello', 'world', 'earth', 'beard', 'chess', 'water', + 'barber', 'bakery', 'banana', 'market', 'purple', 'writer', + 'america', 'release', 'playing', 'working', 'foreign', 'general', + 'aircraft', 'computer', 'laughter', 'alphabet', 'kangaroo', 'spelling', + 'architect', 'president', 'cockroach', 'encounter', 'terrorism', 'cylinders', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('¿Odias el spam? (si o no)', 'si'), + array('¿Eres un robot? (si o no)', 'no'), + array('El fuego es... (caliente o frio)', 'caliente'), + array('La estación que viene despues del otoño es...', 'invierno'), + array('¿Qué día de la semana es hoy?', strftime('%A')), + array('¿En qué mes del año estamos?', strftime('%B')), + ), +); diff --git a/lib/kohana/system/i18n/es_ES/core.php b/lib/kohana/system/i18n/es_ES/core.php new file mode 100644 index 0000000..6cbe5e9 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/core.php @@ -0,0 +1,34 @@ + 'Solo puede haber una instancia de Kohana por cada página.', + 'uncaught_exception' => '%s no capturada: %s en el archivo %s, linea %s', + 'invalid_method' => 'Método inválido %s llamado en %s.', + 'invalid_property' => 'La propiedad %s no existe en la clase %s.', + 'log_dir_unwritable' => 'Tu configuración del &8220;log.directory&8221; no apunta a un directorio con permiso de escritura.', + 'resource_not_found' => 'El fichero de %s con nombre %s, no pudo ser encontrado.', + 'invalid_filetype' => 'El tipo de fichero solicitado, .%s, no esta permitido en la configuración de tus vistas.', + 'view_set_filename' => 'Tienes que definir el nombre de la vista antes de llamar al metodo render', + 'no_default_route' => 'Por favor, especifica la ruta en config/routes.php.', + 'no_controller' => 'Kohana no pudo determinar un controlador para procesar: %s', + 'page_not_found' => 'La página que solicitase, %s, no se encuentra.', + 'stats_footer' => 'Cargado en {execution_time} segundos, usando {memory_usage} de memoria. Generado con Kohana v{kohana_version}.', + 'error_file_line' => '%s [%s]:', + 'stack_trace' => 'Stack Trace', + 'generic_error' => 'Imposible completar la solicitud', + 'errors_disabled' => 'Puedes volver a la página de inico o volver a intentarlo.', + + // Drivers + 'driver_implements' => 'El driver %s para la libreria %s debe implementar el interface %s', + 'driver_not_found' => 'No se ha encontrado el driver %s para la libreria %s', + + // Resource names + 'config' => 'fichero de configuración', + 'controller' => 'controlador', + 'helper' => 'helper', + 'library' => 'librería', + 'driver' => 'driver', + 'model' => 'modelo', + 'view' => 'vista', +); diff --git a/lib/kohana/system/i18n/es_ES/database.php b/lib/kohana/system/i18n/es_ES/database.php new file mode 100644 index 0000000..ebfea71 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/database.php @@ -0,0 +1,15 @@ + 'El grupo %s no esta definido en tu configuración.', + 'error' => 'Ocurrió un error de SQL: %s', + 'connection' => 'Ocurrió un error conectando a la base de datos: %s', + 'invalid_dsn' => 'El DSN que pusiste no es válido: %s', + 'must_use_set' => 'Necesitas una clausula SET para tu consulta.', + 'must_use_where' => 'Necesitas una clausula WHERE para tu consulta.', + 'must_use_table' => 'Necesitas especificar la tabla para tu consulta.', + 'table_not_found' => 'La tabla %s no existe en tu base de datos.', + 'not_implemented' => 'El método requerido, %s, no esta soportado por este driver.', + 'result_read_only' => 'Los resultados del query son de solo lectura.' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/encrypt.php b/lib/kohana/system/i18n/es_ES/encrypt.php new file mode 100644 index 0000000..80e32c2 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/encrypt.php @@ -0,0 +1,8 @@ + 'El grupo %s no esta definidp en la configuración.', + 'requires_mcrypt' => 'Para usar la librería de Encriptación, mcrypt debe estar habilitado.', + 'no_encryption_key' => 'Para usar la librería de Encriptación, tienes que especificar una llave de encriptación en tu archivo de configuración.', +); diff --git a/lib/kohana/system/i18n/es_ES/errors.php b/lib/kohana/system/i18n/es_ES/errors.php new file mode 100644 index 0000000..cc22414 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/errors.php @@ -0,0 +1,16 @@ + array( 1, 'Error del Framework', 'Revisa la documentación de Kohana para información sobre el siguiente error.'), + E_PAGE_NOT_FOUND => array( 1, 'No se encuentra la página', 'No se encontró la página solicitada. Puede ser que haya sido movida, borrada o archivada.'), + E_DATABASE_ERROR => array( 1, 'Error de Base de Datos', 'Ocurrió un error en la base de datos mientras se ejecutaba el procedimiento requerido. Para más información, revisa el error que aparece más abajo.'), + E_RECOVERABLE_ERROR => array( 1, 'Error Recuperable', 'Se detectó un error que evitó que esta página cargara. Si el problema persiste, contacta con el administrador de la web.'), + E_ERROR => array( 1, 'Error Fatal', ''), + E_USER_ERROR => array( 1, 'Error Fatal', ''), + E_PARSE => array( 1, 'Error de Syntaxis', ''), + E_WARNING => array( 1, 'Advertencia', ''), + E_USER_WARNING => array( 1, 'Advertencia', ''), + E_STRICT => array( 2, 'Strict Mode Error', ''), + E_NOTICE => array( 2, 'Runtime Message', ''), +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/event.php b/lib/kohana/system/i18n/es_ES/event.php new file mode 100644 index 0000000..c990771 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/event.php @@ -0,0 +1,7 @@ + 'Fallo el intento de añadir el sujeto %s a %s. Los sujetos deben extender la clase Event_Subject.', + 'invalid_observer' => 'Fallo el intento de añadir el observador %s a %s. Los observadores deben extender la clase Event_Observer.', +); diff --git a/lib/kohana/system/i18n/es_ES/image.php b/lib/kohana/system/i18n/es_ES/image.php new file mode 100644 index 0000000..2b8f6a6 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/image.php @@ -0,0 +1,33 @@ + 'La librería &8220;Image&8221; requiere la función PHP getimagesize, que no parece estar disponible en tu instalación.', + 'unsupported_method' => 'El driver que has elegido en la configuración no soporta el tipo de transformación %s.', + 'file_not_found' => 'La imagen especificada, %s no se ha encontrado. Por favor, verifica que existe utilizando file_exists() antes de manipularla.', + 'type_not_allowed' => 'El tipo de imagen especificado, %s, no es un tipo de imagen permitido.', + 'invalid_width' => 'El ancho que has especificado, %s, no es valido.', + 'invalid_height' => 'El alto que has especificado, %s, no es valido.', + 'invalid_dimensions' => 'Las dimensiones que has especificado para %s no son validas.', + 'invalid_master' => 'The master dim specified is not valid.', + 'invalid_flip' => 'La dirección de rotación especificada no es valida.', + 'directory_unwritable' => 'El directorio especificado, %s, no tiene permisos de escritura.', + + // ImageMagick specific messages + 'imagemagick' => array + ( + 'not_found' => 'El directorio de ImageMagick especificado, no contiene el programa requerido, %s.', + ), + + // GraphicsMagick specific messages + 'graphicsmagick' => array + ( + 'not_found' => 'El directorio de GraphicsMagick especificado, no contiene el programa requerido, %s.', + ), + + // GD specific messages + 'gd' => array + ( + 'requires_v2' => 'La librería &8220;Image&8221; requiere GD2. Por favor, lee http://php.net/gd_info para más información.', + ), +); diff --git a/lib/kohana/system/i18n/es_ES/orm.php b/lib/kohana/system/i18n/es_ES/orm.php new file mode 100644 index 0000000..24070e9 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/orm.php @@ -0,0 +1,3 @@ + 'El grupo %s no esta definido en la configuracion de la paginacion.', + 'page' => 'página', + 'pages' => 'páginas', + 'item' => 'elemento', + 'items' => 'elementos', + 'of' => 'de', + 'first' => 'primero', + 'last' => 'último', + 'previous' => 'anterior', + 'next' => 'siguiente', +); diff --git a/lib/kohana/system/i18n/es_ES/profiler.php b/lib/kohana/system/i18n/es_ES/profiler.php new file mode 100644 index 0000000..506cf65 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/profiler.php @@ -0,0 +1,15 @@ + 'Benchmarks', + 'post_data' => 'Datos Posteados', + 'no_post' => 'No hay datos posteados', + 'session_data' => 'Datos de sesión', + 'no_session' => 'No hay datos de sesión', + 'queries' => 'Consultas a la base de datos', + 'no_queries' => 'No hay consultas a la base de datos', + 'no_database' => 'No se encuentra la base de datos', + 'cookie_data' => 'Datos de la cookie', + 'no_cookie' => 'No se encuentran los datos de la cookie', +); diff --git a/lib/kohana/system/i18n/es_ES/session.php b/lib/kohana/system/i18n/es_ES/session.php new file mode 100644 index 0000000..2f503c2 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/session.php @@ -0,0 +1,6 @@ + 'El parametro session_name, %s, no es valido. Solo debe contener caracteres alfanumericos y guiones bajos. Tambien al menos uno debe de ser una letra.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/swift.php b/lib/kohana/system/i18n/es_ES/swift.php new file mode 100644 index 0000000..79fa6f4 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/swift.php @@ -0,0 +1,6 @@ + 'Ocurrió un error mientras se realizaba el envio del mensaje de correo.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/upload.php b/lib/kohana/system/i18n/es_ES/upload.php new file mode 100644 index 0000000..57bbec4 --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/upload.php @@ -0,0 +1,6 @@ + 'El directorio seleccionado, %s, no tiene permisos de escritura.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/es_ES/validation.php b/lib/kohana/system/i18n/es_ES/validation.php new file mode 100644 index 0000000..9cb114a --- /dev/null +++ b/lib/kohana/system/i18n/es_ES/validation.php @@ -0,0 +1,41 @@ + 'La regla de validación usada es invalida: %s', + 'i18n_array' => 'La clave %s i18n debe de ser un array para ser utilizado en la regla in_lang', + 'not_callable' => 'La llamada de retorno %s utilizada para la validación no puede ser llamada', + + // General errors + 'unknown_error' => 'Error de validación desconocido al comprobar el campo %s.', + 'required' => 'El campo %s es obligatorio.', + 'min_length' => 'El campo %s debe tener un mínimo de %d caracteres.', + 'max_length' => 'El campo %s debe tener un máximo de %d caracteres.', + 'exact_length' => 'El campo %s debe tener exactamente %d caracteres.', + 'in_array' => 'El campo %s debe ser seleccionado de las opciones listadas.', + 'matches' => 'El campo %s debe conincidir con el campo %s.', + 'valid_url' => 'El campo %s debe contener una url valida, empezando con %s://.', + 'valid_email' => 'El campo %s debe contener una dirección de email valida.', + 'valid_ip' => 'El campo %s debe contener una dirección IP valida.', + 'valid_type' => 'El campo %s debe contener unicamente %s.', + 'range' => 'El campo %s debe estar entre los rangos especificados.', + 'regex' => 'El campo %s no coincide con los datos aceptados.', + 'depends_on' => 'El campo %s depende del campo %s.', + + // Upload errors + 'user_aborted' => 'El envio del archivo %s fue abortado antes de completarse.', + 'invalid_type' => 'El archivo %s no es un tipo de archivo permitido.', + 'max_size' => 'El archivo %s que estas enviando es muy grande. El tamaño máximo es de %s.', + 'max_width' => 'El archivo %s debe tener como ancho máximo %s, y tiene %spx.', + 'max_height' => 'El archivo %s debe tener como alto máximo %s, y tiene %spx.', + 'min_width' => 'El archivo %s que estas enviando es muy pequeño. El ancho mínimo permitido es de %spx.', + 'min_height' => 'El archivo %s que estas enviando es muy pequeño. El alto mínimo permitido es de %spx.', + + // Field types + 'alpha' => 'caracteres del alfabeto', + 'alpha_numeric' => 'caracteres del alfabeto y numericos', + 'alpha_dash' => 'caracteres del alfabeto, guiones y subrayado', + 'digit' => 'digitos', + 'numeric' => 'caracteres numéricos', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/fr_FR/cache.php b/lib/kohana/system/i18n/fr_FR/cache.php new file mode 100644 index 0000000..f6ae08d --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/cache.php @@ -0,0 +1,10 @@ + 'Le groupe %s n\'est pas défini dans votre configuration.', + 'extension_not_loaded' => 'l\'extension PHP %s doit être chargée pour utiliser ce driver.', + 'unwritable' => 'Le chemin %s configuré pour le cache n\'est pas accessible en écriture.', + 'resources' => 'La mise en cache des ressources est impossible car elles n\'ont pas pu être sérialisées.', + 'driver_error' => '%s' +); diff --git a/lib/kohana/system/i18n/fr_FR/calendar.php b/lib/kohana/system/i18n/fr_FR/calendar.php new file mode 100644 index 0000000..bf1d52c --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/calendar.php @@ -0,0 +1,59 @@ + 'Di', + 'mo' => 'Lu', + 'tu' => 'Ma', + 'we' => 'Me', + 'th' => 'Je', + 'fr' => 'Ve', + 'sa' => 'Sa', + + // Short day names + 'sun' => 'Dim', + 'mon' => 'Lun', + 'tue' => 'Mar', + 'wed' => 'Mer', + 'thu' => 'Jeu', + 'fri' => 'Ven', + 'sat' => 'Sam', + + // Long day names + 'sunday' => 'Dimanche', + 'monday' => 'Lundi', + 'tuesday' => 'Mardi', + 'wednesday' => 'Mercredi', + 'thursday' => 'Jeudi', + 'friday' => 'Vendredi', + 'saturday' => 'Samedi', + + // Short month names + 'jan' => 'Jan', + 'feb' => 'Fév', + 'mar' => 'Mar', + 'apr' => 'Avr', + 'may' => 'Mai', + 'jun' => 'Jui', + 'jul' => 'Juil', + 'aug' => 'Aoû', + 'sep' => 'Sep', + 'oct' => 'Oct', + 'nov' => 'Nov', + 'dec' => 'Déc', + + // Long month names + 'january' => 'Janvier', + 'february' => 'Février', + 'march' => 'Mars', + 'april' => 'Avril', + 'mayl' => 'Mai', + 'june' => 'Juin', + 'july' => 'Juillet', + 'august' => 'Août', + 'september' => 'Septembre', + 'october' => 'Octobre', + 'november' => 'Novembre', + 'december' => 'Décembre' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/fr_FR/captcha.php b/lib/kohana/system/i18n/fr_FR/captcha.php new file mode 100644 index 0000000..2b1af29 --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/captcha.php @@ -0,0 +1,33 @@ + 'Le fichier spécifié, %s, est introuvable. Merci de vérifier que les fichiers existent, grâce à la fontion file_exists, avant de les utiliser.', + 'requires_GD2' => 'La librairie Captcha requiert GD2 avec le support FreeType installé. Voir http://php.net/gd_info pour de plus amples renseignements, merci.', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'le', 'il', 'ou', 'an', + 'moi', 'age', 'coq', 'ici', 'bob', 'eau', + 'cake', 'agir', 'bain', 'dodo', 'elle', 'faux', + 'hello', 'monde', 'terre', 'adore', 'baton', 'chats', + 'absent', 'cendre', 'banane', 'cirque', 'violet', 'disque', + 'abricot', 'billets', 'cendres', 'frisson', 'nations', 'respect', + 'accepter', 'batterie', 'collines', 'desserts', 'feuilles', 'sandwich', + 'acheteurs', 'tellement', 'renverser', 'histoires', 'dimanches', 'cinquante', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('Détestez-vous le spam? (oui ou non)', 'oui'), + array('Etes vous un robot? (oui ou non)', 'non'), + array('Le feu est... (chaud ou froid)', 'chaud'), + array('La saison après l\'automne est l\'...', 'hiver'), + array('Quel jour est-il?', strftime('%A')), + array('Quel est le mois en cours?', strftime('%B')), + ) +); diff --git a/lib/kohana/system/i18n/fr_FR/core.php b/lib/kohana/system/i18n/fr_FR/core.php new file mode 100644 index 0000000..53d88be --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/core.php @@ -0,0 +1,34 @@ + 'Il ne peut y avoir qu\'une instance de Kohana par page.', + 'uncaught_exception' => 'Uncaught %s: %s dans le fichier %s à la ligne %s', + 'invalid_method' => 'La méthode %s appelée dans %s est invalide.', + 'invalid_property' => 'La propriété %s n\'existe pas dans la classe %s.', + 'log_dir_unwritable' => 'Le répertoire spécifié dans votre fichier de configuration pour le fichier de log ne pointe pas vers un répertoire accessible en écriture.', + 'resource_not_found' => 'La ressource %s, %s, n\'a pas été trouvée.', + 'invalid_filetype' => 'Le type de ficher demandé, .%s, n\'est pas autorisé dans le fichier de configuration des vues (view configuration file).', + 'view_set_filename' => 'Vous devez renseigner le nom de la vue avant d\'appeller la méthode render', + 'no_default_route' => 'Aucune route par défaut n\a été définie. Veuillez la spécifer dans le fichier config/routes.php.', + 'no_controller' => 'Kohana n\'a pu déterminer aucun controlleur pour effectuer la requête: %s.', + 'page_not_found' => 'La page demandée %s n\'a pu être trouvée.', + 'stats_footer' => 'Chargé en {execution_time} secondes, {memory_usage} de mémoire utilisée. Généré par Kohana v{kohana_version}.', + 'error_file_line' => '%s [%s]:', + 'stack_trace' => 'Stack Trace', + 'generic_error' => 'Impossible de terminer la requête.', + 'errors_disabled' => 'Vous pouvez aller sur la page d\'accueil ou essayer encore.', + + // Drivers + 'driver_implements' => 'Le driver %s de la librairie %s doit implémenter l\'interface %s.', + 'driver_not_found' => 'Le driver %s de la librairie %s est introuvable.', + + // Resource names + 'config' => 'fichier de configuration', + 'controller' => 'contrôleur', + 'helper' => 'helper', + 'library' => 'librairie', + 'driver' => 'driver', + 'model' => 'modèle', + 'view' => 'vue', +); diff --git a/lib/kohana/system/i18n/fr_FR/database.php b/lib/kohana/system/i18n/fr_FR/database.php new file mode 100644 index 0000000..643a4fe --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/database.php @@ -0,0 +1,15 @@ + 'Le groupe de base de données %s n\'existe pas dans votre fichier de configuration.', + 'error' => 'L\'erreur SQL suivante est survenue: %s', + 'connection' => 'Il y a eu une erreur lors de la connexion à la base de données: %s', + 'invalid_dsn' => 'Le DSN que vous avez spécifié n\'est pas valide: %s', + 'must_use_set' => 'Vous devez spécifier une clause SET pour votre requête.', + 'must_use_where' => 'Vous devez spécifier une clause WHERE pour votre requête.', + 'must_use_table' => 'Vous devez spécifier une table de la base de données pour votre requête.', + 'table_not_found' => 'La table %s n\'existe pas dans votre base de données.', + 'not_implemented' => 'La méthode %s que vous avez appelée n\'est pas supportée par le driver de base de données.', + 'result_read_only' => 'Les résultats de la requête sont en lecture seule.' +); diff --git a/lib/kohana/system/i18n/fr_FR/encrypt.php b/lib/kohana/system/i18n/fr_FR/encrypt.php new file mode 100644 index 0000000..0ca75d5 --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/encrypt.php @@ -0,0 +1,8 @@ + 'Le groupe %s n\'est pas défini dans votre configuration.', + 'requires_mcrypt' => 'Afin de pouvoir utiliser la librairie de chiffrement (Encrypt library), mcrypt doit être activé dans votre installation PHP.', + 'no_encryption_key' => 'Afin de pouvoir utiliser la librairie de chiffrement (Encrypt library), vous devez définir une clé de chiffrement dans votre fichier de configuration.' +); diff --git a/lib/kohana/system/i18n/fr_FR/errors.php b/lib/kohana/system/i18n/fr_FR/errors.php new file mode 100644 index 0000000..4f4385b --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/errors.php @@ -0,0 +1,16 @@ + array( 1, 'Framework Error', 'Veuillez vous référer à la documentation de Kohana pour plus d\'informations sur l\'erreur suivante.'), + E_PAGE_NOT_FOUND => array( 1, 'Page Not Found', 'La page demandée n\'a pas été trouvée. Elle a peut-être été déplacée, supprimée, ou archivée.'), + E_DATABASE_ERROR => array( 1, 'Database Error', 'Une erreur de base de données est survenue lors de l\'exécution de la procèdure demandée. Veuillez vous référer à l\'erreur renvoyée ci-dessous pour plus d\'informations.'), + E_RECOVERABLE_ERROR => array( 1, 'Recoverable Error', 'Une erreur a empêché le chargement de la page. Si le problème persiste, veuillez contacter l\'administrateur du site.'), + E_ERROR => array( 1, 'Fatal Error', ''), + E_USER_ERROR => array( 1, 'Fatal Error', ''), + E_PARSE => array( 1, 'Syntax Error', ''), + E_WARNING => array( 1, 'Warning Message', ''), + E_USER_WARNING => array( 1, 'Warning Message', ''), + E_STRICT => array( 2, 'Strict Mode Error', ''), + E_NOTICE => array( 2, 'Runtime Message', ''), +); diff --git a/lib/kohana/system/i18n/fr_FR/event.php b/lib/kohana/system/i18n/fr_FR/event.php new file mode 100644 index 0000000..65dec21 --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/event.php @@ -0,0 +1,7 @@ + 'Le sujet %s n\'a pas pu peut être attaché à %s. Les sujets doivent étendre la classe Event_Subject.', + 'invalid_observer' => 'L\'observeur %s n\'a pas pu peut être attaché à %s. Les observeurs doivent étendre la classe Event_Observer.', +); diff --git a/lib/kohana/system/i18n/fr_FR/image.php b/lib/kohana/system/i18n/fr_FR/image.php new file mode 100644 index 0000000..aa1c4ad --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/image.php @@ -0,0 +1,33 @@ + 'Le répertoire %s spécifié n\'est pas accessible en écriture.', + 'getimagesize_missing' => 'La librairie d\'image requiert la function PHP getimagesize. Celle-ci n\'est pas disponible dans votre installation.', + 'unsupported_method' => 'Le pilote configuré ne supporte pas la transformation d\'image %s.', + 'file_not_found' => 'L\'image spécifié %s n\'a pas été trouvée. Merci de vérifier que l\'image existe bien avec la fonction file_exists avant sa manipulation.', + 'type_not_allowed' => 'L\'image spécifié %s n\'est pas d\'un type autorisé.', + 'invalid_width' => 'La largeur que vous avez spécifiée, %s, est invalide.', + 'invalid_height' => 'La hauteur que vous avez spécifiée, %s, est invalide.', + 'invalid_dimensions' => 'Les dimensions spécifiées pour %s ne sont pas valides.', + 'invalid_master' => 'La dimension principale (master dim) n\'est pas valide.', + 'invalid_flip' => 'La direction de rotation spécifiée n\'est pas valide.', + + // ImageMagick specific messages + 'imagemagick' => array + ( + 'not_found' => 'Le répertoire ImageMagick spécifié ne contient pas le programme requis %s.', + ), + + // GraphicsMagick specific messages + 'graphicsmagick' => array + ( + 'not_found' => 'Le répertoire GraphicsMagick spécifié ne contient pas le programme requis %s.', + ), + + // GD specific messages + 'gd' => array + ( + 'requires_v2' => 'La librairie d\'image requiert GD2. Veuillez consulter http://php.net/gd_info pour de plus amples informations.', + ), +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/fr_FR/orm.php b/lib/kohana/system/i18n/fr_FR/orm.php new file mode 100644 index 0000000..9c9d234 --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/orm.php @@ -0,0 +1,3 @@ + 'Le groupe %s n\'est pas défini dans votre configuration de la pagination.', + 'page' => 'page', + 'pages' => 'pages', + 'item' => 'résultat', + 'items' => 'résultats', + 'of' => 'sur', + 'first' => 'premier', + 'last' => 'dernier', + 'previous' => 'précédent', + 'next' => 'suivant', +); diff --git a/lib/kohana/system/i18n/fr_FR/profiler.php b/lib/kohana/system/i18n/fr_FR/profiler.php new file mode 100644 index 0000000..02a95d1 --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/profiler.php @@ -0,0 +1,15 @@ + 'Benchmarks', + 'post_data' => 'Données POST', + 'no_post' => 'Aucune donnée POST', + 'session_data' => 'Données de session', + 'no_session' => 'Aucune donnée de session', + 'queries' => 'Requêtes', + 'no_queries' => 'Aucune requête', + 'no_database' => 'Base de données non chargée', + 'cookie_data' => 'Données du Cookie', + 'no_cookie' => 'Aucune donnée de Cookie', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/fr_FR/session.php b/lib/kohana/system/i18n/fr_FR/session.php new file mode 100644 index 0000000..70700a6 --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/session.php @@ -0,0 +1,6 @@ + 'Le nom de session "session_name", %s, est invalide. Il doit contenir uniquement des caractères alphanumériques et au moins une lettre doit être présente.', +); diff --git a/lib/kohana/system/i18n/fr_FR/swift.php b/lib/kohana/system/i18n/fr_FR/swift.php new file mode 100644 index 0000000..5f31f9d --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/swift.php @@ -0,0 +1,6 @@ + 'Une erreur est survenue lors de l\'envoi du message.' +); diff --git a/lib/kohana/system/i18n/fr_FR/upload.php b/lib/kohana/system/i18n/fr_FR/upload.php new file mode 100644 index 0000000..3cace0e --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/upload.php @@ -0,0 +1,6 @@ + 'Le répertoire de destination pour l\'upload, %s, ne semble pas être accessible en écriture.', +); diff --git a/lib/kohana/system/i18n/fr_FR/validation.php b/lib/kohana/system/i18n/fr_FR/validation.php new file mode 100644 index 0000000..9cb17be --- /dev/null +++ b/lib/kohana/system/i18n/fr_FR/validation.php @@ -0,0 +1,41 @@ + 'La règle de validation %s utilisée est invalide', + 'i18n_array' => 'La clé i18n %s doit être un tableau pour pouvoir être utilisée avec la règle in_lang', + 'not_callable' => 'La callback %s utilisé pour la Validation n\'est pas appellable', + + // General errors + 'unknown_error' => 'Erreur de validation inconnue lors de la validation du champ %s.', + 'required' => 'Le champ %s est requis.', + 'min_length' => 'Le champ %s doit contenir au minimum %d caractères.', + 'max_length' => 'Le champ %s ne peut contenir plus de %d caractères.', + 'exact_length' => 'Le champ %s doit contenir exactement %d caractères.', + 'in_array' => 'Le champ %s doit être sélectionné dans parmi les options listées.', + 'matches' => 'Le champ %s doit correspondre au champ %s.', + 'valid_url' => 'Le champ %s doit contenir une URL valide.', + 'valid_email' => 'Le champ %s doit contenir une adresse email valide.', + 'valid_ip' => 'Le champ %s doit contenir une adresse IP valide.', + 'valid_type' => 'Le champ %s doit contenir uniquement %s caractères', + 'range' => 'Le champ %s doit être situé dans la plage de valeurs spécifiée.', + 'regex' => 'Le champ %s ne correspond pas aux valeurs acceptées.', + 'depends_on' => 'Le champ %s est dépendant du champ %s.', + + // Upload errors + 'user_aborted' => 'L\'envoi du fichier %s sur le serveur a échoué.', + 'invalid_type' => 'Le type du fichier %s n\'est pas autorisé.', + 'max_size' => 'La taille du fichier %s que vous tentez d\'envoyer est trop volumineuse. La taille maximale autorisée est de %s', + 'max_width' => 'La largeur de l\'image %s que vous envoyez est trop grande. La largeur maximale autorisée est de %spx', + 'max_height' => 'La hauteur de l\'image %s que vous envoyez est trop grande. La hauteur maximale autorisée est de %spx', + 'min_width' => 'La largeur de l\'image %s que vous envoyez n\'est pas assez grande. La largeur minimale demandée est de %spx', + 'min_height' => 'La hauteur de l\'image %s que vous envoyez n\'est pas assez grande. La hauteur minimale demandée est de %spx', + + // Field types + 'alpha' => 'alphabétiques', + 'alpha_numeric' => 'alphabétiques et numériques', + 'alpha_dash' => 'alphabétiques, tirets haut ou tirets bas (underscore)', + 'digit' => 'digitaux', + 'numeric' => 'numériques', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/it_IT/cache.php b/lib/kohana/system/i18n/it_IT/cache.php new file mode 100644 index 0000000..c2e9687 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/cache.php @@ -0,0 +1,10 @@ + 'Il gruppo %s non è stato definito in configurazione.', + 'extension_not_loaded' => 'L\'estensione di PHP %s deve essere caricata per poter usare questo driver.', + 'unwritable' => 'La cartella di deposito, %s, non ha i permessi in scrittura.', + 'resources' => 'Risorsa non serializzabile. Impossibile immagazzinare.', + 'driver_error' => '%s', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/it_IT/calendar.php b/lib/kohana/system/i18n/it_IT/calendar.php new file mode 100644 index 0000000..98e61dd --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/calendar.php @@ -0,0 +1,59 @@ + 'Do', + 'mo' => 'Lu', + 'tu' => 'Ma', + 'we' => 'Me', + 'th' => 'Gi', + 'fr' => 'Ve', + 'sa' => 'Sa', + + // Short day names + 'sun' => 'Dom', + 'mon' => 'Lun', + 'tue' => 'Mar', + 'wed' => 'Mer', + 'thu' => 'Gio', + 'fri' => 'Ven', + 'sat' => 'Sab', + + // Long day names + 'sunday' => 'Domenica', + 'monday' => 'Lunedì', + 'tuesday' => 'Martedì', + 'wednesday' => 'Mercoledì', + 'thursday' => 'Giovedì', + 'friday' => 'Venerdì', + 'saturday' => 'Sabato', + + // Short month names + 'jan' => 'Gen', + 'feb' => 'Feb', + 'mar' => 'Mar', + 'apr' => 'Apr', + 'may' => 'Mag', + 'jun' => 'Giu', + 'jul' => 'Lug', + 'aug' => 'Ago', + 'sep' => 'Set', + 'oct' => 'Ott', + 'nov' => 'Nov', + 'dec' => 'Dic', + + // Long month names + 'january' => 'Gennaio', + 'february' => 'Febbraio', + 'march' => 'Marzo', + 'april' => 'Aprile', + 'mayl' => 'Maggio', + 'june' => 'Giugno', + 'july' => 'Luglio', + 'august' => 'Agosto', + 'september' => 'Settembre', + 'october' => 'Ottobre', + 'november' => 'Novembre', + 'december' => 'Dicembre' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/it_IT/captcha.php b/lib/kohana/system/i18n/it_IT/captcha.php new file mode 100644 index 0000000..57faa35 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/captcha.php @@ -0,0 +1,33 @@ + 'Il file specificato, %s, non è stato trovato. Verificarne l\'esistenza con file_exists prima di usarlo.', + 'requires_GD2' => 'La libreria Captcha richiede GD2 con supporto FreeType. Leggere http://php.net/gd_info per maggiori informazioni.', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'it', 'to', 'be', 'or', + 'sun', 'car', 'dog', 'bed', 'kid', 'egg', + 'bike', 'tree', 'bath', 'roof', 'road', 'hair', + 'hello', 'world', 'earth', 'beard', 'chess', 'water', + 'barber', 'bakery', 'banana', 'market', 'purple', 'writer', + 'america', 'release', 'playing', 'working', 'foreign', 'general', + 'aircraft', 'computer', 'laughter', 'alphabet', 'kangaroo', 'spelling', + 'architect', 'president', 'cockroach', 'encounter', 'terrorism', 'cylinders', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('Detesti lo spam? (si o no)', 'si'), + array('Sei un robot? (si o no)', 'no'), + array('Il fuoco è... (caldo o freddo)', 'caldo'), + array('La stagione che viene dopo l\'autunno è...', 'inverno'), + array('Che giorno della settimana è oggi?', strftime('%A')), + array('In quale mese dell\'anno siamo?', strftime('%B')), + ), +); diff --git a/lib/kohana/system/i18n/it_IT/core.php b/lib/kohana/system/i18n/it_IT/core.php new file mode 100644 index 0000000..662092d --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/core.php @@ -0,0 +1,34 @@ + 'Ci può essere una sola istanza di Kohana per ogni pagina richiesta.', + 'uncaught_exception' => 'Uncaught %s: %s in %s, linea %s', + 'invalid_method' => 'Metodo non valido %s chiamato in %s.', + 'invalid_property' => 'La proprietà %s non esiste nella classe %s.', + 'log_dir_unwritable' => 'Il parametro di configurazione log.directory non punta ad una cartella con permesso di scrittura.', + 'resource_not_found' => 'Il %s richiesto, %s, non è stato trovato.', + 'invalid_filetype' => 'Il tipo di file richiesto, .%s, non è presente nel file di configurazione.', + 'view_set_filename' => 'Bisogna definire il nome di una vista prima di chiamare il metodo render', + 'no_default_route' => 'Non è stato definito il default route in config/routes.php.', + 'no_controller' => 'Kohana non è in grado di determinare a quale controller inoltrare la richiesta: %s', + 'page_not_found' => 'La pagina richiesta, %s, non è stata trovata.', + 'stats_footer' => 'Caricato in {execution_time} secondi, usando {memory_usage} di memoria. Generato da Kohana v{kohana_version}.', + 'error_file_line' => 'Errore in %s linea: %s.', + 'stack_trace' => 'Tracciato', + 'generic_error' => 'Impossibile completare la richiesta', + 'errors_disabled' => 'Puoi andare alla pagina iniziale o ritentare.', + + // Drivers + 'driver_implements' => 'Il driver %s per la libreria %s non implementa l\'interfaccia %s', + 'driver_not_found' => 'Il driver %s per la libreria %s non è stato trovato', + + // Resource names + 'config' => 'file di configurazione', + 'controller' => 'controller', + 'helper' => 'helper', + 'library' => 'libreria', + 'driver' => 'driver', + 'model' => 'modello', + 'view' => 'vista', +); diff --git a/lib/kohana/system/i18n/it_IT/database.php b/lib/kohana/system/i18n/it_IT/database.php new file mode 100644 index 0000000..acd77ad --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/database.php @@ -0,0 +1,15 @@ + 'Il gruppo %s non è stato definito nel file di configurazione.', + 'error' => 'Si è verificato un errore SQL: %s', + 'connection' => 'Si è verificato un errore durante la connessione al database: %s', + 'invalid_dsn' => 'Il DSN fornito non è valido: %s', + 'must_use_set' => 'È necessario definire una clausola SET per la query.', + 'must_use_where' => 'È necessario definire una clausola WHERE per la query.', + 'must_use_table' => 'È necessario definire una tabella per la query.', + 'table_not_found' => 'La tabella %s non esiste nella base di dati.', + 'not_implemented' => 'Il metodo chiamato, %s, non è supportato da questo driver.', + 'result_read_only' => 'Il risultato della query è in sola lettura.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/it_IT/encrypt.php b/lib/kohana/system/i18n/it_IT/encrypt.php new file mode 100644 index 0000000..8f2b63d --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/encrypt.php @@ -0,0 +1,8 @@ + 'Il gruppo %s non è definito nel file di configurazione.', + 'requires_mcrypt' => 'L\'uso della libreria Encrypt richiede l\'abilitazione di mcrypt.', + 'no_encryption_key' => 'Per usare la libreria Encrypt bisogna definire una chiave di codifica nel file di configurazione.' +); diff --git a/lib/kohana/system/i18n/it_IT/errors.php b/lib/kohana/system/i18n/it_IT/errors.php new file mode 100644 index 0000000..1df3e7a --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/errors.php @@ -0,0 +1,16 @@ + array( 1, 'Errore del Framework', 'Controlla la documentazione di Kohana per informazioni circa il seguente errore.'), + E_PAGE_NOT_FOUND => array( 1, 'Pagina non trovata', 'La pagina richiesta non è stata trovata. Potrebbe essere stata spostata, rimossa o archiviata.'), + E_DATABASE_ERROR => array( 1, 'Errore del Database', 'Si è verificato un errore durante l\'esecuzione della procedura richiesta. Per maggiori informazioni fare riferimento al messaggio sottostante.'), + E_RECOVERABLE_ERROR => array( 1, 'Errore Recuperabile', 'Un errore ha impedito il caricamento della pagina. Se l\'errore persiste contattare l\'amministratore del sito.'), + E_ERROR => array( 1, 'Errore Fatale', ''), + E_USER_ERROR => array( 1, 'Errore Fatale', ''), + E_PARSE => array( 1, 'Errore di Sintassi', ''), + E_WARNING => array( 1, 'Avviso', ''), + E_USER_WARNING => array( 1, 'Avviso', ''), + E_STRICT => array( 2, 'Strict Mode Error', ''), + E_NOTICE => array( 2, 'Runtime Message', ''), +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/it_IT/event.php b/lib/kohana/system/i18n/it_IT/event.php new file mode 100644 index 0000000..13c5374 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/event.php @@ -0,0 +1,7 @@ + 'Fallito il tentativo di aggiungere il soggetto %s a %s. I soggetti devono estendere la classe Event_Subject.', + 'invalid_observer' => 'Fallito il tentativo di aggiungere l\'observer %s a %s. Gli observer devono estendere la classe Event_Observer.', +); diff --git a/lib/kohana/system/i18n/it_IT/image.php b/lib/kohana/system/i18n/it_IT/image.php new file mode 100644 index 0000000..493b027 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/image.php @@ -0,0 +1,33 @@ + 'La libreria Image richiede la funzione PHP getimagesize, che non è disponibile nella tua intallazione.', + 'unsupported_method' => 'Il driver impostato in configurazione non supporta il tipo di trasformazione %s.', + 'file_not_found' => 'L\'immagine specificata, %s, non è stata trovata. Verificarne l\'esistenza con file_exists prima di manipolarla.', + 'type_not_allowed' => 'Il tipo d\'immagine specificato, %s, non è permesso.', + 'invalid_width' => 'La larghezza specificata, %s, non è valida.', + 'invalid_height' => 'L\'altezza specificata, %s, non è valida.', + 'invalid_dimensions' => 'Le dimensioni specificate per %s non sono valide.', + 'invalid_master' => 'Master dimension specificato non valido.', + 'invalid_flip' => 'La direzione di rotazione specificata non è valida.', + 'directory_unwritable' => 'La directory specificata, %s, non consente la scrittura.', + + // Messaggi specifici per ImageMagick + 'imagemagick' => array + ( + 'not_found' => 'La cartella di ImageMagick specificata non contiene il programma richiesto, %s.', + ), + + // Messaggi specifici per GraphicsMagick + 'graphicsmagick' => array + ( + 'not_found' => 'La cartella di GraphicsMagick specificata non contiene il programma richiesto, %s.', + ), + + // Messaggi specifici per GD + 'gd' => array + ( + 'requires_v2' => 'La libreria Image richiede GD2. Leggere http://php.net/gd_info per maggiori informazioni.', + ), +); diff --git a/lib/kohana/system/i18n/it_IT/orm.php b/lib/kohana/system/i18n/it_IT/orm.php new file mode 100644 index 0000000..09e3a79 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/orm.php @@ -0,0 +1,3 @@ + 'Il gruppo %s non è stato definito nel file di configurazione per la paginazione.', + 'page' => 'pagina', + 'pages' => 'pagine', + 'item' => 'elemento', + 'items' => 'elementi', + 'of' => 'di', + 'first' => 'primo', + 'last' => 'ultimo', + 'previous' => 'precedente', + 'next' => 'successivo', +); diff --git a/lib/kohana/system/i18n/it_IT/profiler.php b/lib/kohana/system/i18n/it_IT/profiler.php new file mode 100644 index 0000000..5cdd502 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/profiler.php @@ -0,0 +1,15 @@ + 'Benchmarks', + 'post_data' => 'Dati postati', + 'no_post' => 'Non ci sono dati postati', + 'session_data' => 'Dati di sessione', + 'no_session' => 'Non ci sono dati di sessione', + 'queries' => 'Query al database', + 'no_queries' => 'Non ci sono query al database', + 'no_database' => 'Database non caricato', + 'cookie_data' => 'Dati del cookie', + 'no_cookie' => 'I dati del cookie non sono stati trovati', +); diff --git a/lib/kohana/system/i18n/it_IT/session.php b/lib/kohana/system/i18n/it_IT/session.php new file mode 100644 index 0000000..d831894 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/session.php @@ -0,0 +1,6 @@ + 'Il parametro session_name, %s, non è valido. Può contenere solo caratteri alfanumerici o il trattino basso. Almeno una lettera deve essere presente.', +); diff --git a/lib/kohana/system/i18n/it_IT/swift.php b/lib/kohana/system/i18n/it_IT/swift.php new file mode 100644 index 0000000..9f83b40 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/swift.php @@ -0,0 +1,6 @@ + 'Si è verificato un errore durante l\'invio del messaggio di posta elettronica.' +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/it_IT/upload.php b/lib/kohana/system/i18n/it_IT/upload.php new file mode 100644 index 0000000..9ea084f --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/upload.php @@ -0,0 +1,6 @@ + 'La cartella di destinazione, %s, non sembra avere i permessi in scrittura.', +); diff --git a/lib/kohana/system/i18n/it_IT/validation.php b/lib/kohana/system/i18n/it_IT/validation.php new file mode 100644 index 0000000..472a2e5 --- /dev/null +++ b/lib/kohana/system/i18n/it_IT/validation.php @@ -0,0 +1,41 @@ + 'Regola di validazione usata non valida: %s', + 'i18n_array' => 'Il parametro i18n %s deve essere un array per essere utilizzato con la regola in_lang', + 'not_callable' => 'La callback %s usata per la Validation non puo essere richiamata', + + // Errori generici + 'unknown_error' => 'Errore sconosciuto durante la validazione del campo %s.', + 'required' => 'Il campo %s è obbligatorio.', + 'min_length' => 'Il campo %s deve essere lungo almeno %d caratteri.', + 'max_length' => 'Il campo %s non deve superare i %d caratteri.', + 'exact_length' => 'Il campo %s deve contenere esattamente %d caratteri.', + 'in_array' => 'Il campo %s deve essere selezionato dalla lista delle opzioni.', + 'matches' => 'Il campo %s deve coincidere con il campo %s.', + 'valid_url' => 'Il campo %s deve contenere un URL valido.', + 'valid_email' => 'Il campo %s deve contenere un indirizzo email valido.', + 'valid_ip' => 'Il campo %s deve contenere un indirizzo IP valido.', + 'valid_type' => 'Il campo %s deve contenere solo i caratteri %s.', + 'range' => 'Il campo %s deve trovarsi negli intervalli specificati.', + 'regex' => 'Il campo %s non coincide con i dati accettati.', + 'depends_on' => 'Il campo %s dipende dal campo %s.', + + // Errori di upload + 'user_aborted' => 'Il caricamento del file %s è stato interrotto.', + 'invalid_type' => 'Il file %s non è un tipo di file permesso.', + 'max_size' => 'Il file %s inviato è troppo grande. La dimensone massima consentita è %s.', + 'max_width' => 'Il file %s inviato è troppo grande. La larghezza massima consentita è %spx.', + 'max_height' => 'Il file %s inviato è troppo grande. L\'altezza massima consentita è %spx.', + 'min_width' => 'Il file %s inviato è troppo piccolo. La larghezza minima consentita è %spx.', + 'min_height' => 'Il file %s inviato è troppo piccolo. L\'altezza minima consentita è %spx.', + + // Tipi di valore dei campi + 'alpha' => 'alfabetico', + 'alpha_numeric' => 'alfanumerico', + 'alpha_dash' => 'alfabetico, trattino e sottolineato', + 'digit' => 'cifra', + 'numeric' => 'numerico', +); diff --git a/lib/kohana/system/i18n/nl_NL/cache.php b/lib/kohana/system/i18n/nl_NL/cache.php new file mode 100644 index 0000000..b6f1631 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/cache.php @@ -0,0 +1,10 @@ + 'De %s groep is niet gedefinieerd in uw configuratie.', + 'extension_not_loaded' => 'De %s PHP extensie moet geladen zijn om deze driver te gebruiken.', + 'unwritable' => 'De geconfigureerde opslaglocatie, %s, is niet schrijfbaar.', + 'resources' => 'Het cachen van resources is onmogelijk omdat resources niet geserialized kunnen worden.', + 'driver_error' => '%s', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/calendar.php b/lib/kohana/system/i18n/nl_NL/calendar.php new file mode 100644 index 0000000..ce8fa88 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/calendar.php @@ -0,0 +1,59 @@ + 'zo', + 'mo' => 'ma', + 'tu' => 'di', + 'we' => 'wo', + 'th' => 'do', + 'fr' => 'vr', + 'sa' => 'za', + + // Short day names + 'sun' => 'zon', + 'mon' => 'maa', + 'tue' => 'din', + 'wed' => 'woe', + 'thu' => 'don', + 'fri' => 'vri', + 'sat' => 'zat', + + // Long day names + 'sunday' => 'zondag', + 'monday' => 'maandag', + 'tuesday' => 'dinsdag', + 'wednesday' => 'woensdag', + 'thursday' => 'donderdag', + 'friday' => 'vrijdag', + 'saturday' => 'zaterdag', + + // Short month names + 'jan' => 'jan', + 'feb' => 'feb', + 'mar' => 'maa', + 'apr' => 'apr', + 'may' => 'mei', + 'jun' => 'jun', + 'jul' => 'jul', + 'aug' => 'aug', + 'sep' => 'sep', + 'oct' => 'okt', + 'nov' => 'nov', + 'dec' => 'dec', + + // Long month names + 'january' => 'januari', + 'february' => 'februari', + 'march' => 'maart', + 'april' => 'april', + 'mayl' => 'mei', + 'june' => 'juni', + 'july' => 'juli', + 'august' => 'augustus', + 'september' => 'september', + 'october' => 'oktober', + 'november' => 'november', + 'december' => 'december', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/captcha.php b/lib/kohana/system/i18n/nl_NL/captcha.php new file mode 100644 index 0000000..842d5fb --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/captcha.php @@ -0,0 +1,33 @@ + 'Het opgegeven bestand, %s, werd niet gevonden. Controleer met file_exists() of bestanden bestaan, voordat je ze gebruikt.', + 'requires_GD2' => 'De Captcha library vereist GD2 met FreeType ondersteuning. Zie http://php.net/gd_info voor meer informatie.', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'ok', 'pc', 'nu', 'ik', + 'zon', 'kar', 'kat', 'bed', 'tof', 'hoi', + 'puin', 'hoop', 'mens', 'roof', 'auto', 'haar', + 'water', 'beter', 'aarde', 'appel', 'mango', 'liter', + 'ananas', 'bakker', 'wekker', 'kroket', 'zingen', 'dansen', + 'fietsen', 'zwemmen', 'kolonel', 'potlood', 'kookpot', 'voetbal', + 'barbecue', 'computer', 'generaal', 'koelkast', 'fietsers', 'spelling', + 'appelmoes', 'president', 'kangoeroe', 'frankrijk', 'luxemburg', 'apartheid', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('Haat jij spam? (ja of nee)', 'ja'), + array('Ben jij een robot? (ja of nee)', 'nee'), + array('Vuur is... (heet of koud)', 'heet'), + array('Het seizoen na herfst is...', 'winter'), + array('Welke dag van de week is het vandaag?', strftime('%A')), + array('In welke maand van het jaar zijn we?', strftime('%B')), + ), +); diff --git a/lib/kohana/system/i18n/nl_NL/core.php b/lib/kohana/system/i18n/nl_NL/core.php new file mode 100644 index 0000000..e3668af --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/core.php @@ -0,0 +1,34 @@ + 'Er kan maar één instantie van Kohana zijn per pagina oproep.', + 'uncaught_exception' => 'Uncaught %s: %s in bestand %s op lijn %s', + 'invalid_method' => 'Ongeldige method %s opgeroepen in %s.', + 'invalid_property' => 'De %s property bestaat niet in de %s class.', + 'log_dir_unwritable' => 'De log directory is niet schrijfbaar: %s', + 'resource_not_found' => 'De opgevraagde %s, %s, kon niet gevonden worden.', + 'invalid_filetype' => 'Het opgevraagde bestandstype, .%s, wordt niet toegestaan door het view configuratiebestand.', + 'view_set_filename' => 'Je moet de view bestandsnaam opgeven voordat je render aanroept.', + 'no_default_route' => 'Zet een default route in config/routes.php.', + 'no_controller' => 'Kohana kon geen controller aanduiden om deze pagina te verwerken: %s', + 'page_not_found' => 'De opgevraagde pagina, %s, kon niet gevonden worden.', + 'stats_footer' => 'Geladen in {execution_time} seconden, met een geheugengebruik van {memory_usage}. Aangedreven door Kohana v{kohana_version}.', + 'error_file_line' => '%s [%s]:', + 'stack_trace' => 'Stack Trace', + 'generic_error' => 'Oproep kon niet afgewerkt worden', + 'errors_disabled' => 'Ga naar de homepage of probeer opnieuw.', + + // Drivers + 'driver_implements' => 'De %s driver voor de %s library moet de %s interface implementeren.', + 'driver_not_found' => 'De %s driver voor de %s library werd niet gevonden.', + + // Resource names + 'config' => 'configuratiebestand', + 'controller' => 'controller', + 'helper' => 'helper', + 'library' => 'library', + 'driver' => 'driver', + 'model' => 'model', + 'view' => 'view', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/database.php b/lib/kohana/system/i18n/nl_NL/database.php new file mode 100644 index 0000000..b520283 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/database.php @@ -0,0 +1,15 @@ + 'De %s groep is niet opgegeven in je configuratie.', + 'error' => 'Er was een SQL fout: %s', + 'connection' => 'Fout bij het verbinden met de database: %s', + 'invalid_dsn' => 'De DSN die je opgaf is ongeldig: %s', + 'must_use_set' => 'Je moet een SET clause opgeven voor je query.', + 'must_use_where' => 'Je moet een WHERE clause opgeven voor je query.', + 'must_use_table' => 'Je moet een database tabel opgeven voor je query.', + 'table_not_found' => 'De tabel %s bestaat niet in je database.', + 'not_implemented' => 'De method die je opriep, %s, wordt niet ondersteund door deze driver.', + 'result_read_only' => 'Query resultaten kunnen alleen maar gelezen worden.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/encrypt.php b/lib/kohana/system/i18n/nl_NL/encrypt.php new file mode 100644 index 0000000..980cdb1 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/encrypt.php @@ -0,0 +1,8 @@ + 'De %s groep is niet gedefinieerd in je configuratie.', + 'requires_mcrypt' => 'Om de Encrypt library te gebruiken, moet mcrypt ingeschakeld zijn in je PHP installatie.', + 'no_encryption_key' => 'Om de Encrypt library te gebruiken, moet je een encryption key zetten in je config bestand.', +); diff --git a/lib/kohana/system/i18n/nl_NL/errors.php b/lib/kohana/system/i18n/nl_NL/errors.php new file mode 100644 index 0000000..2d4dc94 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/errors.php @@ -0,0 +1,16 @@ + array( 1, 'Framework Error', 'Bekijk de Kohana documentatie voor meer informatie over deze fout.'), + E_PAGE_NOT_FOUND => array( 1, 'Pagina Niet Gevonden', 'De opgevraagde pagina werd niet gevonden. Mogelijk werd deze verplaatst of verwijderd.'), + E_DATABASE_ERROR => array( 1, 'Database Error', 'Er vond een database fout plaats bij het verwerken van de opgeroepen procedure. Bekijk het errorbericht hieronder voor meer informatie.'), + E_RECOVERABLE_ERROR => array( 1, 'Recoverable Error', 'Er vond een fout plaats waardoor deze pagina niet geladen kon worden. Als dit probleem aanhoudt, contacteer dan a.u.b. de website beheerder.'), + E_ERROR => array( 1, 'Fatal Error', ''), + E_USER_ERROR => array( 1, 'Fatal Error', ''), + E_PARSE => array( 1, 'Syntax Error', ''), + E_WARNING => array( 1, 'Warning Message', ''), + E_USER_WARNING => array( 1, 'Warning Message', ''), + E_STRICT => array( 2, 'Strict Mode Error', ''), + E_NOTICE => array( 2, 'Runtime Message', ''), +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/event.php b/lib/kohana/system/i18n/nl_NL/event.php new file mode 100644 index 0000000..2909e3f --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/event.php @@ -0,0 +1,7 @@ + 'Poging om ongeldig subject %s te binden aan %s mislukt. Subjects moeten de Event_Subject class extenden.', + 'invalid_observer' => 'Poging om ongeldige observer %s te binden aan %s mislukt. Observers moeten de Event_Subject class extenden.', +); diff --git a/lib/kohana/system/i18n/nl_NL/image.php b/lib/kohana/system/i18n/nl_NL/image.php new file mode 100644 index 0000000..e7c3cd7 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/image.php @@ -0,0 +1,27 @@ + 'De Image library vereist de getimagesize() functie en die is niet beschikbaar op dit systeem.', + 'unsupported_method' => 'De huidige Image driver ondersteunt volgende transformatie niet: %s.', + 'file_not_found' => 'De opgegeven afbeelding, %s, werd niet gevonden. Controleer a.u.b. eerst of afbeeldingen bestaan via de file_exists() functie voordat je ze begint te bewerken.', + 'type_not_allowed' => 'De opgegeven afbeelding, %s, is geen toegestaan afbeeldingstype.', + 'invalid_width' => 'De breedte die je opgaf, %s, is ongeldig.', + 'invalid_height' => 'De hoogte die je opgaf, %s, is ongeldig.', + 'invalid_dimensions' => 'De afmetingen die je opgaf voor %s zijn ongeldig.', + 'invalid_master' => 'De master afmeting die je opgaf, is ongeldig.', + 'invalid_flip' => 'De spiegelrichting die je opgaf, is ongeldig.', + 'directory_unwritable' => 'De opgegeven directory, %s, is niet schrijfbaar.', + + // ImageMagick specific messages + 'imagemagick' => array + ( + 'not_found' => 'De opgegeven ImageMagick directory bevat een vereist programma niet: %s.', + ), + + // GD specific messages + 'gd' => array + ( + 'requires_v2' => 'De Image library vereist GD2. Kijk op http://php.net/gd_info voor meer informatie.', + ), +); diff --git a/lib/kohana/system/i18n/nl_NL/orm.php b/lib/kohana/system/i18n/nl_NL/orm.php new file mode 100644 index 0000000..bea9238 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/orm.php @@ -0,0 +1,3 @@ + 'De %s groep werd niet gedefinieerd in uw pagination configuratie.', + 'page' => 'pagina', + 'pages' => 'pagina\'s', + 'item' => 'item', + 'items' => 'items', + 'of' => 'van', + 'first' => 'eerste', + 'last' => 'laatste', + 'previous' => 'vorige', + 'next' => 'volgende', +); diff --git a/lib/kohana/system/i18n/nl_NL/profiler.php b/lib/kohana/system/i18n/nl_NL/profiler.php new file mode 100644 index 0000000..03d0f84 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/profiler.php @@ -0,0 +1,15 @@ + 'Benchmarks', + 'post_data' => 'Post Data', + 'no_post' => 'Geen post data', + 'session_data' => 'Session Data', + 'no_session' => 'Geen session data', + 'queries' => 'Database Queries', + 'no_queries' => 'Geen queries', + 'no_database' => 'Database niet geladen', + 'cookie_data' => 'Cookie Data', + 'no_cookie' => 'Geen cookie data', +); diff --git a/lib/kohana/system/i18n/nl_NL/session.php b/lib/kohana/system/i18n/nl_NL/session.php new file mode 100644 index 0000000..391a46d --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/session.php @@ -0,0 +1,6 @@ + 'De sessienaam, %s, is ongeldig. Hij mag alleen maar bestaan uit alfanumerieke tekens en underscores. Hij moet ook minstens één letter bevatten.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/swift.php b/lib/kohana/system/i18n/nl_NL/swift.php new file mode 100644 index 0000000..bdd2af7 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/swift.php @@ -0,0 +1,6 @@ + 'Er vond een fout plaats bij het verzenden van de e-mail.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/upload.php b/lib/kohana/system/i18n/nl_NL/upload.php new file mode 100644 index 0000000..4a6549f --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/upload.php @@ -0,0 +1,6 @@ + 'De upload doelmap, %s, is niet schrijfbaar.', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/nl_NL/validation.php b/lib/kohana/system/i18n/nl_NL/validation.php new file mode 100644 index 0000000..4eb6c60 --- /dev/null +++ b/lib/kohana/system/i18n/nl_NL/validation.php @@ -0,0 +1,39 @@ + 'Ongeldige validatieregel gebruikt: %s', + + // Algemene errors + 'unknown_error' => 'Onbekende validatiefout bij het valideren van het %s veld.', + 'required' => 'Het %s veld is verplicht.', + 'min_length' => 'Het %s veld moet minstens %s karakters lang zijn.', + 'max_length' => 'Het %s veld mag maximum %s karakters lang zijn.', + 'exact_length' => 'Het %s veld moet exact %s karakters lang zijn.', + 'in_array' => 'Het %s veld moet geselecteerd worden uit de gegeven opties.', + 'matches' => 'Het %s veld moet overeenkomen met het %s veld.', + 'valid_url' => 'Het %s veld moet een geldige URL zijn.', + 'valid_email' => 'Het %s veld moet een geldig e-mailadres zijn.', + 'valid_ip' => 'Het %s veld moet een geldig IP-adres zijn.', + 'valid_type' => 'Het %s veld mag alleen maar %s karakters bevatten.', + 'range' => 'Het %s veld moet tussen bepaalde waardes liggen.', + 'regex' => 'Het %s veld valideert niet als geldige invoer.', + 'depends_on' => 'Het %s veld is afhankelijk van het %s veld.', + + // Upload errors + 'user_aborted' => 'Het uploaden van het %s bestand werd afgebroken.', + 'invalid_type' => 'Het bestandstype van het %s bestand is niet toegestaan.', + 'max_size' => 'Het %s bestand dat je wilde uploaden is te groot. De maximum toegelaten grootte is %s.', + 'max_width' => 'Het %s upgeloade bestand is te groot: maximum toegelaten breedte is %spx.', + 'max_height' => 'Het %s upgeloade bestand is te groot: maximum toegelaten hoogte is %spx.', + 'min_width' => 'Het %s upgeloade bestand is te klein: minimum toegelaten breedte is %spx.', + 'min_height' => 'Het %s upgeloade bestand is te klein: minimum toegelaten breedte is %spx.', + + // Field types + 'alpha' => 'alfabetisch', + 'alpha_numeric' => 'alfanumeriek', + 'alpha_dash' => 'alfabetisch, streepje, en underscore', + 'digit' => 'cijfers', + 'numeric' => 'getal', +); \ No newline at end of file diff --git a/lib/kohana/system/i18n/ru_RU/cache.php b/lib/kohana/system/i18n/ru_RU/cache.php new file mode 100644 index 0000000..855e834 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/cache.php @@ -0,0 +1,10 @@ + 'Группа "%s" не определена Вашей конфигурацией.', + 'extension_not_loaded' => 'Расширение PHP "%s" должно быть загружено для использования этого драйвера.', + 'unwritable' => 'Целевая директория хранения кеша, %s, не доступна для записи.', + 'resources' => 'Кеширование ресурсов невозможно, так как ресурсы не могут быть сериализованы.', + 'driver_error' => '%s', +); diff --git a/lib/kohana/system/i18n/ru_RU/calendar.php b/lib/kohana/system/i18n/ru_RU/calendar.php new file mode 100644 index 0000000..a78ad34 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/calendar.php @@ -0,0 +1,59 @@ + 'Пн', + 'tu' => 'Вт', + 'we' => 'Ср', + 'th' => 'Чт', + 'fr' => 'Пт', + 'sa' => 'Сб', + 'su' => 'Вс', + + // Short day names + 'mon' => 'Пнд', + 'tue' => 'Втр', + 'wed' => 'Срд', + 'thu' => 'Чтв', + 'fri' => 'Птн', + 'sat' => 'Сбт', + 'sun' => 'Вск', + + // Long day names + 'monday' => 'Понедельник', + 'tuesday' => 'Вторник', + 'wednesday' => 'Среда', + 'thursday' => 'Четверг', + 'friday' => 'Пятница', + 'saturday' => 'Суббота', + 'sunday' => 'Воскресенье', + + // Short month names + 'jan' => 'Янв', + 'feb' => 'Фев', + 'mar' => 'Мар', + 'apr' => 'Апр', + 'may' => 'Май', + 'jun' => 'Июн', + 'jul' => 'Июл', + 'aug' => 'Авг', + 'sep' => 'Сен', + 'oct' => 'Окт', + 'nov' => 'Ноя', + 'dec' => 'Дек', + + // Long month names + 'january' => 'Январь', + 'february' => 'Февраль', + 'march' => 'Март', + 'april' => 'Апрель', + 'mayl' => 'Май', + 'june' => 'Июнь', + 'july' => 'Июль', + 'august' => 'Август', + 'september' => 'Сентябрь', + 'october' => 'Октябрь', + 'november' => 'Ноябрь', + 'december' => 'Декабрь' +); diff --git a/lib/kohana/system/i18n/ru_RU/captcha.php b/lib/kohana/system/i18n/ru_RU/captcha.php new file mode 100644 index 0000000..98dd5d1 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/captcha.php @@ -0,0 +1,33 @@ + 'Файл "%s" не найден. Убедитесь в наличии файлов функцией file_exists() перед их использованием.', + 'requires_GD2' => 'Библиотека Captcha нуждается в расширении GD2 с поддержкой FreeType. Подробности на http://php.net/gd_info .', + + // Words of varying length for the Captcha_Word_Driver to pick from + // Note: use only alphanumeric characters + 'words' => array + ( + 'cd', 'tv', 'it', 'to', 'be', 'or', + 'sun', 'car', 'dog', 'bed', 'kid', 'egg', + 'bike', 'tree', 'bath', 'roof', 'road', 'hair', + 'hello', 'world', 'earth', 'beard', 'chess', 'water', + 'barber', 'bakery', 'banana', 'market', 'purple', 'writer', + 'america', 'release', 'playing', 'working', 'foreign', 'general', + 'aircraft', 'computer', 'laughter', 'alphabet', 'kangaroo', 'spelling', + 'architect', 'president', 'cockroach', 'encounter', 'terrorism', 'cylinders', + ), + + // Riddles for the Captcha_Riddle_Driver to pick from + // Note: use only alphanumeric characters + 'riddles' => array + ( + array('Do you hate spam? (yes or no)', 'yes'), + array('Are you a robot? (yes or no)', 'no'), + array('Fire is... (hot or cold)', 'hot'), + array('The season after fall is...', 'winter'), + array('Which day of the week is it today?', strftime('%A')), + array('Which month of the year are we in?', strftime('%B')), + ), +); diff --git a/lib/kohana/system/i18n/ru_RU/core.php b/lib/kohana/system/i18n/ru_RU/core.php new file mode 100644 index 0000000..45840eb --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/core.php @@ -0,0 +1,34 @@ + 'Наличие более, чем одного экземпляра Kohana, в пределах одного запроса страницы, невозможно', + 'uncaught_exception' => 'Не пойманное %s: %s в файле %s, на строке %s', + 'invalid_method' => 'Вызов метода %s из файла %s невозможен', + 'invalid_property' => 'Свойство %s не входит в состав класса %s.', + 'log_dir_unwritable' => 'Директория для хранения журналов, %s, не доступна для записи', + 'resource_not_found' => 'Запрошенный %s, %s, не найден', + 'invalid_filetype' => 'Запрошенный тип файла, .%s, не разрешён конфигурацией видов', + 'view_set_filename' => 'Необходимо задать файл вида перед вызовом render()', + 'no_default_route' => 'Установите путь по умолчанию в файле config/routes.php.', + 'no_controller' => 'Kohana не удалось найти контроллер для обработки этого запроса: %s', + 'page_not_found' => 'Запрошенная страница, %s, не найдена.', + 'stats_footer' => 'Загружено за {execution_time} секунд, используя {memory_usage} памяти. Сгенерировано Kohana v{kohana_version}.', + 'error_file_line' => '%s [%s]:', + 'stack_trace' => 'Стек вызовов', + 'generic_error' => 'Не удалось обработать запрос', + 'errors_disabled' => 'Вы можете вернуться на начальную страницу или повторить попытку.', + + // Drivers + 'driver_implements' => 'Драйвер %s библиотеки %s не реализует интерфейс %s', + 'driver_not_found' => 'Драйвер %s библиотеки %s не найден', + + // Resource names + 'config' => 'конфигурация', + 'controller' => 'контроллер', + 'helper' => 'помощник', + 'library' => 'библиотека', + 'driver' => 'драйвер', + 'model' => 'модель', + 'view' => 'вид', +); diff --git a/lib/kohana/system/i18n/ru_RU/database.php b/lib/kohana/system/i18n/ru_RU/database.php new file mode 100644 index 0000000..ab13b9f --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/database.php @@ -0,0 +1,15 @@ + 'Группа %s не определена Вашей конфигурацией.', + 'error' => 'Ошибка SQL: %s', + 'connection' => 'Не удалось подключиться к базе данных: %s', + 'invalid_dsn' => 'Переданный DSN некорректен: %s', + 'must_use_set' => 'Необходимо использовать оператор SET в этом запросе.', + 'must_use_where' => 'Необходимо использовать оператор WHERE в этом запросе.', + 'must_use_table' => 'Необходимо указать таблицу базы данных в этом запросе.', + 'table_not_found' => 'Таблица %s не существует в Вашей базе данных.', + 'not_implemented' => 'Запрошенный метод, %s, не поддерживается этим драйвером.', + 'result_read_only' => 'Результат запроса доступен только для чтения.' +); diff --git a/lib/kohana/system/i18n/ru_RU/encrypt.php b/lib/kohana/system/i18n/ru_RU/encrypt.php new file mode 100644 index 0000000..49f1237 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/encrypt.php @@ -0,0 +1,8 @@ + 'Группа %s не определена вашей конфигурацией.', + 'requires_mcrypt' => 'Для использования библиотеки Encrypt необходимо включить расширение "mcrypt" в конфигурации PHP.', + 'no_encryption_key' => 'Для использования библиотеки Encrypt необходимо задать ключ шифрования в конфигурационном файле.' +); diff --git a/lib/kohana/system/i18n/ru_RU/errors.php b/lib/kohana/system/i18n/ru_RU/errors.php new file mode 100644 index 0000000..ca6c6b8 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/errors.php @@ -0,0 +1,16 @@ + array( 1, 'Ошибка фреймворка', 'Информация об этой ошибке доступна в документации Kohana.'), + E_PAGE_NOT_FOUND => array( 1, 'Page Not Found', 'Запрошенная страница не найдена. Возможно, она была перемещена, удалена, или архивирована.'), + E_DATABASE_ERROR => array( 1, 'Database Error', 'При обработке запроса произошла ошибка в базе данных. Пожалуйста, уточните причину ошибки ниже'), + E_RECOVERABLE_ERROR => array( 1, 'Recoverable Error', 'Обнаружена ошибка, препятствующая загрузке этой страницы. Если это повторится, пожалуйста, уведомите администрацию сайта.'), + E_ERROR => array( 1, 'Фатальная ошибка', ''), + E_USER_ERROR => array( 1, 'Фатальная ошибка', ''), + E_PARSE => array( 1, 'Синтаксическая ошибка', ''), + E_WARNING => array( 1, 'Предупреждение', ''), + E_USER_WARNING => array( 1, 'Предупреждение', ''), + E_STRICT => array( 2, 'Стилистическая ошибка', ''), + E_NOTICE => array( 2, 'Уведомление', ''), +); diff --git a/lib/kohana/system/i18n/ru_RU/event.php b/lib/kohana/system/i18n/ru_RU/event.php new file mode 100644 index 0000000..92b091b --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/event.php @@ -0,0 +1,7 @@ + 'Попытка привязать некорректный субъект %s к %s не удалась: Субъект должен быть наследником класса Event_Subject', + 'invalid_observer' => 'Попытка привязать некорректный наблюдатель %s к %s не удалась: Наблюдатель должен быть наследником класса Event_Observer', +); diff --git a/lib/kohana/system/i18n/ru_RU/image.php b/lib/kohana/system/i18n/ru_RU/image.php new file mode 100644 index 0000000..e00757e --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/image.php @@ -0,0 +1,28 @@ + 'Библиотеке Image необходима функция getimagesize(), недоступная в вашей инсталляции PHP.', + 'unsupported_method' => 'Указанный драйвер не поддерживает операцию %s.', + 'file_not_found' => 'Заданное изображение, %s, не найдено. Удостоверьтесь в наличии изображения функцией file_exists() перед его обработкой.', + 'type_not_allowed' => 'Заданное изображение, %s, не является разрешённым типом изображений.', + 'invalid_width' => 'Заданная ширина, %s, некорректна.', + 'invalid_height' => 'Заданная высота, %s, некорректна.', + 'invalid_dimensions' => 'Заданный размер для %s некорректен.', + 'invalid_master' => 'Заданная основная сторона некорректна.', + 'invalid_flip' => 'Направление разворота некорректно.', + + 'directory_unwritable' => 'Заданная директория, %s, недоступна для записи.', + + // ImageMagick specific messages + 'imagemagick' => array + ( + 'not_found' => 'Директория ImageMagick не содержит запрошенную программу, %s.', + ), + + // GD specific messages + 'gd' => array + ( + 'requires_v2' => 'Библиотеке Image необходимо расширение GD2. Подробности на http://php.net/gd_info .', + ), +); diff --git a/lib/kohana/system/i18n/ru_RU/orm.php b/lib/kohana/system/i18n/ru_RU/orm.php new file mode 100644 index 0000000..2c9a382 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/orm.php @@ -0,0 +1,3 @@ + 'Группа %s не определена конфигурацией нумератора страниц.', + 'page' => 'страница', + 'pages' => 'страницы', + 'item' => 'пункт', + 'items' => 'пунктов', + 'of' => 'из', + 'first' => 'первая', + 'last' => 'последняя', + 'previous' => 'предыдущая', + 'next' => 'следующая', +); diff --git a/lib/kohana/system/i18n/ru_RU/profiler.php b/lib/kohana/system/i18n/ru_RU/profiler.php new file mode 100644 index 0000000..2d45e7e --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/profiler.php @@ -0,0 +1,15 @@ + 'Производительность', + 'post_data' => 'Данные POST', + 'no_post' => 'Нет данных POST', + 'session_data' => 'Данные сессии', + 'no_session' => 'Нет данных сессии', + 'queries' => 'Запросов к БД', + 'no_queries' => 'Нет запросов к БД', + 'no_database' => 'БД не загружена', + 'cookie_data' => 'Данные cookie', + 'no_cookie' => 'Нет данных cookie', +); diff --git a/lib/kohana/system/i18n/ru_RU/session.php b/lib/kohana/system/i18n/ru_RU/session.php new file mode 100644 index 0000000..882fb27 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/session.php @@ -0,0 +1,6 @@ + 'Имя сессии, %s, некорректно. Оно должно состоять только из буквенно-цифровых символов, и, как минимум, одной буквы.', +); diff --git a/lib/kohana/system/i18n/ru_RU/swift.php b/lib/kohana/system/i18n/ru_RU/swift.php new file mode 100644 index 0000000..9033d0c --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/swift.php @@ -0,0 +1,6 @@ + 'Отправка письма не удалась.' +); diff --git a/lib/kohana/system/i18n/ru_RU/upload.php b/lib/kohana/system/i18n/ru_RU/upload.php new file mode 100644 index 0000000..1363ee2 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/upload.php @@ -0,0 +1,23 @@ + 'POST-переменная %s не найдена.', + 'file_exceeds_limit' => 'Размер закачанного файла превышает максимальный разрешённый конфигурацией PHP', + 'file_partial' => 'Файл закачан не полностью', + 'no_file_selected' => 'Вы не выбрали файл для закачивания', + 'invalid_filetype' => 'Тип файла, который вы пытаетесь закачать, не разрешён.', + 'invalid_filesize' => 'Размер файла, который вы пытаетесь закачать, превышает максимальный разрешённый (%s)', + 'invalid_dimensions' => 'Разрешение картинки, которую вы пытаетесь закачать, превышает максимальное разрешённое (%s)', + 'destination_error' => 'Не удалось переместить закачанный файл в пункт назначения.', + 'no_filepath' => 'Путь для закачивания некорректен.', + 'no_file_types' => 'Вы не разрешили ни один тип файлов.', + 'bad_filename' => 'Файл с таким именем уже существует на сервере.', + 'not_writable' => 'Запись в целевой каталог, %s, не возможна.', + 'error_on_file' => 'Ошибка при закачивании %s:', + // Error code responses + 'set_allowed' => 'В целях безопасности, установите разрешённые для закачивания типы файлов.', + 'max_file_size' => 'В целях безопасности, не используйте MAX_FILE_SIZE для ограничения размера закачиваемых файлов.', + 'no_tmp_dir' => 'Временная директория для закачивания файлов не найдена.', + 'tmp_unwritable' => 'Нет прав записи во временную директорию для закачивания файлов, %s.' +); diff --git a/lib/kohana/system/i18n/ru_RU/validation.php b/lib/kohana/system/i18n/ru_RU/validation.php new file mode 100644 index 0000000..edf6a02 --- /dev/null +++ b/lib/kohana/system/i18n/ru_RU/validation.php @@ -0,0 +1,39 @@ + 'Некорректное правило валидации: %s', + + // General errors + 'unknown_error' => 'Неизвестная ошибка при валидации поля %s.', + 'required' => 'Поле %s обязательно для заполнения.', + 'min_length' => 'Поле %s должно быть не короче %d символов.', + 'max_length' => 'Поле %s должно быть не длиннее %d символов.', + 'exact_length' => 'Поле %s должно быть длиной в %d символов.', + 'in_array' => 'Поле %s должно содержать одно из перечисленных значений.', + 'matches' => 'Поле %s должно совпадать с полем %s.', + 'valid_url' => 'Поле %s должно содержать корректный URL.', + 'valid_email' => 'Поле %s должно содержать корректный email.', + 'valid_ip' => 'Поле %s должно содержать корректный IP-адрес.', + 'valid_type' => 'Поле %s должно содержать только символы %s.', + 'range' => 'Поле %s должно сожержать значение из заданных пределов.', + 'regex' => 'Поле %s не является принимаемым значением.', + 'depends_on' => 'Поле %s зависит от поля %s.', + + // Upload errors + 'user_aborted' => 'Загрузка файла %s отменена пользователем.', + 'invalid_type' => 'Загруженный файл, %s, не является файлом разрешённого типа.', + 'max_size' => 'Загруженный файл, %s, слишком велик. Максимальный разрешённый размер файла: %s.', + 'max_width' => 'Загруженный файл, %s, слишком велик. Максимальная разрешённая ширина: %s пикселей.', + 'max_height' => 'Загруженный файл, %s, слишком велик. Максимальная разрешённая высота: %s пикселей.', + 'min_width' => 'Загруженный файл, %s, слишком мал. Минимальная разрешённая ширина: %s пикселей.', + 'min_height' => 'Загруженный файл, %s, слишком мал. Минимальная разрешённая высота: %s пикселей.', + + // Field types + 'alpha' => 'буквенное', + 'alpha_numeric' => 'буквенно-цифровое', + 'alpha_dash' => 'буквенное, c дефисом и символом подчёркивания', + 'digit' => 'цифровое', + 'numeric' => 'числовое', +); diff --git a/lib/kohana/system/libraries/Cache.php b/lib/kohana/system/libraries/Cache.php new file mode 100644 index 0000000..8a02a90 --- /dev/null +++ b/lib/kohana/system/libraries/Cache.php @@ -0,0 +1,208 @@ +config = $config; + + // Set driver name + $driver = 'Cache_'.ucfirst($this->config['driver']).'_Driver'; + + // Load the driver + if ( ! Kohana::auto_load($driver)) + throw new Kohana_Exception('core.driver_not_found', $this->config['driver'], get_class($this)); + + // Initialize the driver + $this->driver = new $driver($this->config['params']); + + // Validate the driver + if ( ! ($this->driver instanceof Cache_Driver)) + throw new Kohana_Exception('core.driver_implements', $this->config['driver'], get_class($this), 'Cache_Driver'); + + Kohana::log('debug', 'Cache Library initialized'); + + if (Cache::$loaded !== TRUE) + { + $this->config['requests'] = (int) $this->config['requests']; + + if ($this->config['requests'] > 0 AND mt_rand(1, $this->config['requests']) === 1) + { + // Do garbage collection + $this->driver->delete_expired(); + + Kohana::log('debug', 'Cache: Expired caches deleted.'); + } + + // Cache has been loaded once + Cache::$loaded = TRUE; + } + } + + /** + * Fetches a cache by id. NULL is returned when a cache item is not found. + * + * @param string cache id + * @return mixed cached data or NULL + */ + public function get($id) + { + // Sanitize the ID + $id = $this->sanitize_id($id); + + return $this->driver->get($id); + } + + /** + * Fetches all of the caches for a given tag. An empty array will be + * returned when no matching caches are found. + * + * @param string cache tag + * @return array all cache items matching the tag + */ + public function find($tag) + { + return $this->driver->find($tag); + } + + /** + * Set a cache item by id. Tags may also be added and a custom lifetime + * can be set. Non-string data is automatically serialized. + * + * @param string unique cache id + * @param mixed data to cache + * @param array|string tags for this item + * @param integer number of seconds until the cache expires + * @return boolean + */ + function set($id, $data, $tags = NULL, $lifetime = NULL) + { + if (is_resource($data)) + throw new Kohana_Exception('cache.resources'); + + // Sanitize the ID + $id = $this->sanitize_id($id); + + if ($lifetime === NULL) + { + // Get the default lifetime + $lifetime = $this->config['lifetime']; + } + + return $this->driver->set($id, $data, (array) $tags, $lifetime); + } + + /** + * Delete a cache item by id. + * + * @param string cache id + * @return boolean + */ + public function delete($id) + { + // Sanitize the ID + $id = $this->sanitize_id($id); + + return $this->driver->delete($id); + } + + /** + * Delete all cache items with a given tag. + * + * @param string cache tag name + * @return boolean + */ + public function delete_tag($tag) + { + return $this->driver->delete($tag, TRUE); + } + + /** + * Delete ALL cache items items. + * + * @return boolean + */ + public function delete_all() + { + return $this->driver->delete(TRUE); + } + + /** + * Replaces troublesome characters with underscores. + * + * @param string cache id + * @return string + */ + protected function sanitize_id($id) + { + // Change slashes and spaces to underscores + return str_replace(array('/', '\\', ' '), '_', $id); + } + +} // End Cache diff --git a/lib/kohana/system/libraries/Calendar.php b/lib/kohana/system/libraries/Calendar.php new file mode 100644 index 0000000..193a6fb --- /dev/null +++ b/lib/kohana/system/libraries/Calendar.php @@ -0,0 +1,362 @@ + 3) ? '%A' : '%a'; + + // Days of the week + $days = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); + + if (Calendar::$start_monday === TRUE) + { + // Push Sunday to the end of the days + array_push($days, array_shift($days)); + } + + if (strpos(Kohana::config('locale.language.0'), 'en') !== 0) + { + // This is a bit awkward, but it works properly and is reliable + foreach ($days as $i => $day) + { + // Convert the English names to i18n names + $days[$i] = strftime($format, strtotime($day)); + } + } + + if (is_int($length) OR ctype_digit($length)) + { + foreach ($days as $i => $day) + { + // Shorten the days to the expected length + $days[$i] = utf8::substr($day, 0, $length); + } + } + + return $days; + } + + /** + * Create a new Calendar instance. A month and year can be specified. + * By default, the current month and year are used. + * + * @param integer month number + * @param integer year number + * @return object + */ + public static function factory($month = NULL, $year = NULL) + { + return new Calendar($month, $year); + } + + /** + * Create a new Calendar instance. A month and year can be specified. + * By default, the current month and year are used. + * + * @param integer month number + * @param integer year number + * @return void + */ + public function __construct($month = NULL, $year = NULL) + { + empty($month) and $month = date('n'); // Current month + empty($year) and $year = date('Y'); // Current year + + // Set the month and year + $this->month = (int) $month; + $this->year = (int) $year; + + if (Calendar::$start_monday === TRUE) + { + // Week starts on Monday + $this->week_start = 1; + } + } + + /** + * Allows fetching the current month and year. + * + * @param string key to get + * @return mixed + */ + public function __get($key) + { + if ($key === 'month' OR $key === 'year') + { + return $this->$key; + } + } + + /** + * Calendar_Event factory method. + * + * @param string unique name for the event + * @return object Calendar_Event + */ + public function event($name = NULL) + { + return new Calendar_Event($this); + } + + /** + * Calendar_Event factory method. + * + * @chainable + * @param string standard event type + * @return object + */ + public function standard($name) + { + switch ($name) + { + case 'today': + // Add an event for the current day + $this->attach($this->event()->condition('timestamp', strtotime('today'))->add_class('today')); + break; + case 'prev-next': + // Add an event for padding days + $this->attach($this->event()->condition('current', FALSE)->add_class('prev-next')); + break; + case 'holidays': + // Base event + $event = $this->event()->condition('current', TRUE)->add_class('holiday'); + + // Attach New Years + $holiday = clone $event; + $this->attach($holiday->condition('month', 1)->condition('day', 1)); + + // Attach Valentine's Day + $holiday = clone $event; + $this->attach($holiday->condition('month', 2)->condition('day', 14)); + + // Attach St. Patrick's Day + $holiday = clone $event; + $this->attach($holiday->condition('month', 3)->condition('day', 17)); + + // Attach Easter + $holiday = clone $event; + $this->attach($holiday->condition('easter', TRUE)); + + // Attach Memorial Day + $holiday = clone $event; + $this->attach($holiday->condition('month', 5)->condition('day_of_week', 1)->condition('last_occurrence', TRUE)); + + // Attach Independance Day + $holiday = clone $event; + $this->attach($holiday->condition('month', 7)->condition('day', 4)); + + // Attach Labor Day + $holiday = clone $event; + $this->attach($holiday->condition('month', 9)->condition('day_of_week', 1)->condition('occurrence', 1)); + + // Attach Halloween + $holiday = clone $event; + $this->attach($holiday->condition('month', 10)->condition('day', 31)); + + // Attach Thanksgiving + $holiday = clone $event; + $this->attach($holiday->condition('month', 11)->condition('day_of_week', 4)->condition('occurrence', 4)); + + // Attach Christmas + $holiday = clone $event; + $this->attach($holiday->condition('month', 12)->condition('day', 25)); + break; + case 'weekends': + // Weekend events + $this->attach($this->event()->condition('weekend', TRUE)->add_class('weekend')); + break; + } + + return $this; + } + + /** + * Returns an array for use with a view. The array contains an array for + * each week. Each week contains 7 arrays, with a day number and status: + * TRUE if the day is in the month, FALSE if it is padding. + * + * @return array + */ + public function weeks() + { + // First day of the month as a timestamp + $first = mktime(1, 0, 0, $this->month, 1, $this->year); + + // Total number of days in this month + $total = (int) date('t', $first); + + // Last day of the month as a timestamp + $last = mktime(1, 0, 0, $this->month, $total, $this->year); + + // Make the month and week empty arrays + $month = $week = array(); + + // Number of days added. When this reaches 7, start a new week + $days = 0; + $week_number = 1; + + if (($w = (int) date('w', $first) - $this->week_start) < 0) + { + $w = 6; + } + + if ($w > 0) + { + // Number of days in the previous month + $n = (int) date('t', mktime(1, 0, 0, $this->month - 1, 1, $this->year)); + + // i = number of day, t = number of days to pad + for ($i = $n - $w + 1, $t = $w; $t > 0; $t--, $i++) + { + // Notify the listeners + $this->notify(array($this->month - 1, $i, $this->year, $week_number, FALSE)); + + // Add previous month padding days + $week[] = array($i, FALSE, $this->observed_data); + $days++; + } + } + + // i = number of day + for ($i = 1; $i <= $total; $i++) + { + if ($days % 7 === 0) + { + // Start a new week + $month[] = $week; + $week = array(); + + $week_number++; + } + + // Notify the listeners + $this->notify(array($this->month, $i, $this->year, $week_number, TRUE)); + + // Add days to this month + $week[] = array($i, TRUE, $this->observed_data); + $days++; + } + + if (($w = (int) date('w', $last) - $this->week_start) < 0) + { + $w = 6; + } + + if ($w >= 0) + { + // i = number of day, t = number of days to pad + for ($i = 1, $t = 6 - $w; $t > 0; $t--, $i++) + { + // Notify the listeners + $this->notify(array($this->month + 1, $i, $this->year, $week_number, FALSE)); + + // Add next month padding days + $week[] = array($i, FALSE, $this->observed_data); + } + } + + if ( ! empty($week)) + { + // Append the remaining days + $month[] = $week; + } + + return $month; + } + + /** + * Adds new data from an observer. All event data contains and array of CSS + * classes and an array of output messages. + * + * @param array observer data. + * @return void + */ + public function add_data(array $data) + { + // Add new classes + $this->observed_data['classes'] += $data['classes']; + + if ( ! empty($data['output'])) + { + // Only add output if it's not empty + $this->observed_data['output'][] = $data['output']; + } + } + + /** + * Resets the observed data and sends a notify to all attached events. + * + * @param array UNIX timestamp + * @return void + */ + public function notify($data) + { + // Reset observed data + $this->observed_data = array + ( + 'classes' => array(), + 'output' => array(), + ); + + // Send a notify + parent::notify($data); + } + + /** + * Convert the calendar to HTML using the kohana_calendar view. + * + * @return string + */ + public function render() + { + $view = new View('kohana_calendar', array + ( + 'month' => $this->month, + 'year' => $this->year, + 'weeks' => $this->weeks(), + )); + + return $view->render(); + } + + /** + * Magically convert this object to a string, the rendered calendar. + * + * @return string + */ + public function __toString() + { + return $this->render(); + } + +} // End Calendar \ No newline at end of file diff --git a/lib/kohana/system/libraries/Calendar_Event.php b/lib/kohana/system/libraries/Calendar_Event.php new file mode 100644 index 0000000..ba9b5ad --- /dev/null +++ b/lib/kohana/system/libraries/Calendar_Event.php @@ -0,0 +1,307 @@ +conditions[$key]); + } + else + { + if ($key === 'callback') + { + // Do nothing + } + elseif (in_array($key, $this->booleans)) + { + // Make the value boolean + $value = (bool) $value; + } + else + { + // Make the value an int + $value = (int) $value; + } + + $this->conditions[$key] = $value; + } + + return $this; + } + + /** + * Add a CSS class for this event. This can be called multiple times. + * + * @chainable + * @param string CSS class name + * @return object + */ + public function add_class($class) + { + $this->classes[$class] = $class; + + return $this; + } + + /** + * Remove a CSS class for this event. This can be called multiple times. + * + * @chainable + * @param string CSS class name + * @return object + */ + public function remove_class($class) + { + unset($this->classes[$class]); + + return $this; + } + + /** + * Set HTML output for this event. + * + * @chainable + * @param string HTML output + * @return object + */ + public function output($str) + { + $this->output = $str; + + return $this; + } + + /** + * Add a CSS class for this event. This can be called multiple times. + * + * @chainable + * @param string CSS class name + * @return object + */ + public function notify($data) + { + // Split the date and current status + list ($month, $day, $year, $week, $current) = $data; + + // Get a timestamp for the day + $timestamp = mktime(0, 0, 0, $month, $day, $year); + + // Date conditionals + $condition = array + ( + 'timestamp' => (int) $timestamp, + 'day' => (int) date('j', $timestamp), + 'week' => (int) $week, + 'month' => (int) date('n', $timestamp), + 'year' => (int) date('Y', $timestamp), + 'day_of_week' => (int) date('w', $timestamp), + 'current' => (bool) $current, + ); + + // Tested conditions + $tested = array(); + + foreach ($condition as $key => $value) + { + // Timestamps need to be handled carefully + if($key === 'timestamp' AND isset($this->conditions['timestamp'])) + { + // This adds 23 hours, 59 minutes and 59 seconds to today's timestamp, as 24 hours + // is classed as a new day + $next_day = $timestamp + 86399; + + if($this->conditions['timestamp'] < $timestamp OR $this->conditions['timestamp'] > $next_day) + return FALSE; + } + // Test basic conditions first + elseif (isset($this->conditions[$key]) AND $this->conditions[$key] !== $value) + return FALSE; + + // Condition has been tested + $tested[$key] = TRUE; + } + + if (isset($this->conditions['weekend'])) + { + // Weekday vs Weekend + $condition['weekend'] = ($condition['day_of_week'] === 0 OR $condition['day_of_week'] === 6); + } + + if (isset($this->conditions['first_day'])) + { + // First day of month + $condition['first_day'] = ($condition['day'] === 1); + } + + if (isset($this->conditions['last_day'])) + { + // Last day of month + $condition['last_day'] = ($condition['day'] === (int) date('t', $timestamp)); + } + + if (isset($this->conditions['occurrence'])) + { + // Get the occurance of the current day + $condition['occurrence'] = $this->day_occurrence($timestamp); + } + + if (isset($this->conditions['last_occurrence'])) + { + // Test if the next occurance of this date is next month + $condition['last_occurrence'] = ((int) date('n', $timestamp + 604800) !== $condition['month']); + } + + if (isset($this->conditions['easter'])) + { + if ($condition['month'] === 3 OR $condition['month'] === 4) + { + // This algorithm is from Practical Astronomy With Your Calculator, 2nd Edition by Peter + // Duffett-Smith. It was originally from Butcher's Ecclesiastical Calendar, published in + // 1876. This algorithm has also been published in the 1922 book General Astronomy by + // Spencer Jones; in The Journal of the British Astronomical Association (Vol.88, page + // 91, December 1977); and in Astronomical Algorithms (1991) by Jean Meeus. + + $a = $condition['year'] % 19; + $b = (int) ($condition['year'] / 100); + $c = $condition['year'] % 100; + $d = (int) ($b / 4); + $e = $b % 4; + $f = (int) (($b + 8) / 25); + $g = (int) (($b - $f + 1) / 3); + $h = (19 * $a + $b - $d - $g + 15) % 30; + $i = (int) ($c / 4); + $k = $c % 4; + $l = (32 + 2 * $e + 2 * $i - $h - $k) % 7; + $m = (int) (($a + 11 * $h + 22 * $l) / 451); + $p = ($h + $l - 7 * $m + 114) % 31; + + $month = (int) (($h + $l - 7 * $m + 114) / 31); + $day = $p + 1; + + $condition['easter'] = ($condition['month'] === $month AND $condition['day'] === $day); + } + else + { + // Easter can only happen in March or April + $condition['easter'] = FALSE; + } + } + + if (isset($this->conditions['callback'])) + { + // Use a callback to determine validity + $condition['callback'] = call_user_func($this->conditions['callback'], $condition, $this); + } + + $conditions = array_diff_key($this->conditions, $tested); + + foreach ($conditions as $key => $value) + { + if ($key === 'callback') + { + // Callbacks are tested on a TRUE/FALSE basis + $value = TRUE; + } + + // Test advanced conditions + if ($condition[$key] !== $value) + return FALSE; + } + + $this->caller->add_data(array + ( + 'classes' => $this->classes, + 'output' => $this->output, + )); + } + + /** + * Find the week day occurrence for a specific timestamp. The occurrence is + * relative to the current month. For example, the second Saturday of any + * given month will return "2" as the occurrence. This is used in combination + * with the "occurrence" condition. + * + * @param integer UNIX timestamp + * @return integer + */ + protected function day_occurrence($timestamp) + { + // Get the current month for the timestamp + $month = date('m', $timestamp); + + // Default occurrence is one + $occurrence = 1; + + // Reduce the timestamp by one week for each loop. This has the added + // benefit of preventing an infinite loop. + while ($timestamp -= 604800) + { + if (date('m', $timestamp) !== $month) + { + // Once the timestamp has gone into the previous month, the + // proper occurrence has been found. + return $occurrence; + } + + // Increment the occurrence + $occurrence++; + } + } + +} // End Calendar Event diff --git a/lib/kohana/system/libraries/Captcha.php b/lib/kohana/system/libraries/Captcha.php new file mode 100644 index 0000000..f5f2b46 --- /dev/null +++ b/lib/kohana/system/libraries/Captcha.php @@ -0,0 +1,279 @@ + 'basic', + 'width' => 150, + 'height' => 50, + 'complexity' => 4, + 'background' => '', + 'fontpath' => '', + 'fonts' => array(), + 'promote' => FALSE, + ); + + /** + * Singleton instance of Captcha. + * + * @return object + */ + public static function instance() + { + // Create the instance if it does not exist + empty(Captcha::$instance) and new Captcha; + + return Captcha::$instance; + } + + /** + * Constructs and returns a new Captcha object. + * + * @param string config group name + * @return object + */ + public static function factory($group = NULL) + { + return new Captcha($group); + } + + /** + * Constructs a new Captcha object. + * + * @throws Kohana_Exception + * @param string config group name + * @return void + */ + public function __construct($group = NULL) + { + // Create a singleton instance once + empty(Captcha::$instance) and Captcha::$instance = $this; + + // No config group name given + if ( ! is_string($group)) + { + $group = 'default'; + } + + // Load and validate config group + if ( ! is_array($config = Kohana::config('captcha.'.$group))) + throw new Kohana_Exception('captcha.undefined_group', $group); + + // All captcha config groups inherit default config group + if ($group !== 'default') + { + // Load and validate default config group + if ( ! is_array($default = Kohana::config('captcha.default'))) + throw new Kohana_Exception('captcha.undefined_group', 'default'); + + // Merge config group with default config group + $config += $default; + } + + // Assign config values to the object + foreach ($config as $key => $value) + { + if (array_key_exists($key, Captcha::$config)) + { + Captcha::$config[$key] = $value; + } + } + + // Store the config group name as well, so the drivers can access it + Captcha::$config['group'] = $group; + + // If using a background image, check if it exists + if ( ! empty($config['background'])) + { + Captcha::$config['background'] = str_replace('\\', '/', realpath($config['background'])); + + if ( ! is_file(Captcha::$config['background'])) + throw new Kohana_Exception('captcha.file_not_found', Captcha::$config['background']); + } + + // If using any fonts, check if they exist + if ( ! empty($config['fonts'])) + { + Captcha::$config['fontpath'] = str_replace('\\', '/', realpath($config['fontpath'])).'/'; + + foreach ($config['fonts'] as $font) + { + if ( ! is_file(Captcha::$config['fontpath'].$font)) + throw new Kohana_Exception('captcha.file_not_found', Captcha::$config['fontpath'].$font); + } + } + + // Set driver name + $driver = 'Captcha_'.ucfirst($config['style']).'_Driver'; + + // Load the driver + if ( ! Kohana::auto_load($driver)) + throw new Kohana_Exception('core.driver_not_found', $config['style'], get_class($this)); + + // Initialize the driver + $this->driver = new $driver; + + // Validate the driver + if ( ! ($this->driver instanceof Captcha_Driver)) + throw new Kohana_Exception('core.driver_implements', $config['style'], get_class($this), 'Captcha_Driver'); + + Kohana::log('debug', 'Captcha Library initialized'); + } + + /** + * Validates a Captcha response and updates response counter. + * + * @param string captcha response + * @return boolean + */ + public static function valid($response) + { + // Maximum one count per page load + static $counted; + + // User has been promoted, always TRUE and don't count anymore + if (Captcha::instance()->promoted()) + return TRUE; + + // Challenge result + $result = (bool) Captcha::instance()->driver->valid($response); + + // Increment response counter + if ($counted !== TRUE) + { + $counted = TRUE; + + // Valid response + if ($result === TRUE) + { + Captcha::instance()->valid_count(Session::instance()->get('captcha_valid_count') + 1); + } + // Invalid response + else + { + Captcha::instance()->invalid_count(Session::instance()->get('captcha_invalid_count') + 1); + } + } + + return $result; + } + + /** + * Gets or sets the number of valid Captcha responses for this session. + * + * @param integer new counter value + * @param boolean trigger invalid counter (for internal use only) + * @return integer counter value + */ + public function valid_count($new_count = NULL, $invalid = FALSE) + { + // Pick the right session to use + $session = ($invalid === TRUE) ? 'captcha_invalid_count' : 'captcha_valid_count'; + + // Update counter + if ($new_count !== NULL) + { + $new_count = (int) $new_count; + + // Reset counter = delete session + if ($new_count < 1) + { + Session::instance()->delete($session); + } + // Set counter to new value + else + { + Session::instance()->set($session, (int) $new_count); + } + + // Return new count + return (int) $new_count; + } + + // Return current count + return (int) Session::instance()->get($session); + } + + /** + * Gets or sets the number of invalid Captcha responses for this session. + * + * @param integer new counter value + * @return integer counter value + */ + public function invalid_count($new_count = NULL) + { + return $this->valid_count($new_count, TRUE); + } + + /** + * Resets the Captcha response counters and removes the count sessions. + * + * @return void + */ + public function reset_count() + { + $this->valid_count(0); + $this->valid_count(0, TRUE); + } + + /** + * Checks whether user has been promoted after having given enough valid responses. + * + * @param integer valid response count threshold + * @return boolean + */ + public function promoted($threshold = NULL) + { + // Promotion has been disabled + if (Captcha::$config['promote'] === FALSE) + return FALSE; + + // Use the config threshold + if ($threshold === NULL) + { + $threshold = Captcha::$config['promote']; + } + + // Compare the valid response count to the threshold + return ($this->valid_count() >= $threshold); + } + + /** + * Returns or outputs the Captcha challenge. + * + * @param boolean TRUE to output html, e.g. + * @return mixed html string or void + */ + public function render($html = TRUE) + { + return $this->driver->render($html); + } + + /** + * Magically outputs the Captcha challenge. + * + * @return mixed + */ + public function __toString() + { + return $this->render(); + } + +} // End Captcha Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/Controller.php b/lib/kohana/system/libraries/Controller.php new file mode 100644 index 0000000..2f64c21 --- /dev/null +++ b/lib/kohana/system/libraries/Controller.php @@ -0,0 +1,86 @@ +uri = URI::instance(); + + // Input should always be available + $this->input = Input::instance(); + } + + /** + * Handles methods that do not exist. + * + * @param string method name + * @param array arguments + * @return void + */ + public function __call($method, $args) + { + // Default to showing a 404 page + Event::run('system.404'); + } + + /** + * Includes a View within the controller scope. + * + * @param string view filename + * @param array array of view variables + * @return string + */ + public function _kohana_load_view($kohana_view_filename, $kohana_input_data) + { + if ($kohana_view_filename == '') + return; + + // Buffering on + ob_start(); + + // Import the view variables to local namespace + extract($kohana_input_data, EXTR_SKIP); + + // Views are straight HTML pages with embedded PHP, so importing them + // this way insures that $this can be accessed as if the user was in + // the controller, which gives the easiest access to libraries in views + try + { + include $kohana_view_filename; + } + catch (Exception $e) + { + ob_end_clean(); + throw $e; + } + + // Fetch the output and close the buffer + return ob_get_clean(); + } + +} // End Controller Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/Database.php b/lib/kohana/system/libraries/Database.php new file mode 100644 index 0000000..6267f63 --- /dev/null +++ b/lib/kohana/system/libraries/Database.php @@ -0,0 +1,1444 @@ + TRUE, + 'persistent' => FALSE, + 'connection' => '', + 'character_set' => 'utf8', + 'table_prefix' => '', + 'object' => TRUE, + 'cache' => FALSE, + 'escape' => TRUE, + ); + + // Database driver object + protected $driver; + protected $link; + + // Un-compiled parts of the SQL query + protected $select = array(); + protected $set = array(); + protected $from = array(); + protected $join = array(); + protected $where = array(); + protected $orderby = array(); + protected $order = array(); + protected $groupby = array(); + protected $having = array(); + protected $distinct = FALSE; + protected $limit = FALSE; + protected $offset = FALSE; + protected $last_query = ''; + + // Stack of queries for push/pop + protected $query_history = array(); + + /** + * Returns a singleton instance of Database. + * + * @param mixed configuration array or DSN + * @return Database_Core + */ + public static function & instance($name = 'default', $config = NULL) + { + if ( ! isset(Database::$instances[$name])) + { + // Create a new instance + Database::$instances[$name] = new Database($config === NULL ? $name : $config); + } + + return Database::$instances[$name]; + } + + /** + * Returns the name of a given database instance. + * + * @param Database instance of Database + * @return string + */ + public static function instance_name(Database $db) + { + return array_search($db, Database::$instances, TRUE); + } + + /** + * Sets up the database configuration, loads the Database_Driver. + * + * @throws Kohana_Database_Exception + */ + public function __construct($config = array()) + { + if (empty($config)) + { + // Load the default group + $config = Kohana::config('database.default'); + } + elseif (is_array($config) AND count($config) > 0) + { + if ( ! array_key_exists('connection', $config)) + { + $config = array('connection' => $config); + } + } + elseif (is_string($config)) + { + // The config is a DSN string + if (strpos($config, '://') !== FALSE) + { + $config = array('connection' => $config); + } + // The config is a group name + else + { + $name = $config; + + // Test the config group name + if (($config = Kohana::config('database.'.$config)) === NULL) + throw new Kohana_Database_Exception('database.undefined_group', $name); + } + } + + // Merge the default config with the passed config + $this->config = array_merge($this->config, $config); + + if (is_string($this->config['connection'])) + { + // Make sure the connection is valid + if (strpos($this->config['connection'], '://') === FALSE) + throw new Kohana_Database_Exception('database.invalid_dsn', $this->config['connection']); + + // Parse the DSN, creating an array to hold the connection parameters + $db = array + ( + 'type' => FALSE, + 'user' => FALSE, + 'pass' => FALSE, + 'host' => FALSE, + 'port' => FALSE, + 'socket' => FALSE, + 'database' => FALSE + ); + + // Get the protocol and arguments + list ($db['type'], $connection) = explode('://', $this->config['connection'], 2); + + if (strpos($connection, '@') !== FALSE) + { + // Get the username and password + list ($db['pass'], $connection) = explode('@', $connection, 2); + // Check if a password is supplied + $logindata = explode(':', $db['pass'], 2); + $db['pass'] = (count($logindata) > 1) ? $logindata[1] : ''; + $db['user'] = $logindata[0]; + + // Prepare for finding the database + $connection = explode('/', $connection); + + // Find the database name + $db['database'] = array_pop($connection); + + // Reset connection string + $connection = implode('/', $connection); + + // Find the socket + if (preg_match('/^unix\([^)]++\)/', $connection)) + { + // This one is a little hairy: we explode based on the end of + // the socket, removing the 'unix(' from the connection string + list ($db['socket'], $connection) = explode(')', substr($connection, 5), 2); + } + elseif (strpos($connection, ':') !== FALSE) + { + // Fetch the host and port name + list ($db['host'], $db['port']) = explode(':', $connection, 2); + } + else + { + $db['host'] = $connection; + } + } + else + { + // File connection + $connection = explode('/', $connection); + + // Find database file name + $db['database'] = array_pop($connection); + + // Find database directory name + $db['socket'] = implode('/', $connection).'/'; + } + + // Reset the connection array to the database config + $this->config['connection'] = $db; + } + // Set driver name + $driver = 'Database_'.ucfirst($this->config['connection']['type']).'_Driver'; + + // Load the driver + if ( ! Kohana::auto_load($driver)) + throw new Kohana_Database_Exception('core.driver_not_found', $this->config['connection']['type'], get_class($this)); + + // Initialize the driver + $this->driver = new $driver($this->config); + + // Validate the driver + if ( ! ($this->driver instanceof Database_Driver)) + throw new Kohana_Database_Exception('core.driver_implements', $this->config['connection']['type'], get_class($this), 'Database_Driver'); + + Kohana::log('debug', 'Database Library initialized'); + } + + /** + * Simple connect method to get the database queries up and running. + * + * @return void + */ + public function connect() + { + // A link can be a resource or an object + if ( ! is_resource($this->link) AND ! is_object($this->link)) + { + $this->link = $this->driver->connect(); + if ( ! is_resource($this->link) AND ! is_object($this->link)) + throw new Kohana_Database_Exception('database.connection', $this->driver->show_error()); + + // Clear password after successful connect + $this->config['connection']['pass'] = NULL; + } + } + + /** + * Runs a query into the driver and returns the result. + * + * @param string SQL query to execute + * @return Database_Result + */ + public function query($sql = '') + { + if ($sql == '') return FALSE; + + // No link? Connect! + $this->link or $this->connect(); + + // Start the benchmark + $start = microtime(TRUE); + + if (func_num_args() > 1) //if we have more than one argument ($sql) + { + $argv = func_get_args(); + $binds = (is_array(next($argv))) ? current($argv) : array_slice($argv, 1); + } + + // Compile binds if needed + if (isset($binds)) + { + $sql = $this->compile_binds($sql, $binds); + } + + // Fetch the result + $result = $this->driver->query($this->last_query = $sql); + + // Stop the benchmark + $stop = microtime(TRUE); + + if ($this->config['benchmark'] == TRUE) + { + // Benchmark the query + Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result)); + } + + return $result; + } + + /** + * Selects the column names for a database query. + * + * @param string string or array of column names to select + * @return Database_Core This Database object. + */ + public function select($sql = '*') + { + if (func_num_args() > 1) + { + $sql = func_get_args(); + } + elseif (is_string($sql)) + { + $sql = explode(',', $sql); + } + else + { + $sql = (array) $sql; + } + + foreach ($sql as $val) + { + if (($val = trim($val)) === '') continue; + + if (strpos($val, '(') === FALSE AND $val !== '*') + { + if (preg_match('/^DISTINCT\s++(.+)$/i', $val, $matches)) + { + // Only prepend with table prefix if table name is specified + $val = (strpos($matches[1], '.') !== FALSE) ? $this->config['table_prefix'].$matches[1] : $matches[1]; + + $this->distinct = TRUE; + } + else + { + $val = (strpos($val, '.') !== FALSE) ? $this->config['table_prefix'].$val : $val; + } + + $val = $this->driver->escape_column($val); + } + + $this->select[] = $val; + } + + return $this; + } + + /** + * Selects the from table(s) for a database query. + * + * @param string string or array of tables to select + * @return Database_Core This Database object. + */ + public function from($sql) + { + if (func_num_args() > 1) + { + $sql = func_get_args(); + } + elseif (is_string($sql)) + { + $sql = explode(',', $sql); + } + else + { + $sql = array($sql); + } + + foreach ($sql as $val) + { + if (is_string($val)) + { + if (($val = trim($val)) === '') continue; + + // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice) + if (stripos($val, ' AS ') !== FALSE) + { + $val = str_ireplace(' AS ', ' AS ', $val); + + list($table, $alias) = explode(' AS ', $val); + + // Attach prefix to both sides of the AS + $val = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias; + } + else + { + $val = $this->config['table_prefix'].$val; + } + } + + $this->from[] = $val; + } + + return $this; + } + + /** + * Generates the JOIN portion of the query. + * + * @param string table name + * @param string|array where key or array of key => value pairs + * @param string where value + * @param string type of join + * @return Database_Core This Database object. + */ + public function join($table, $key, $value = NULL, $type = '') + { + $join = array(); + + if ( ! empty($type)) + { + $type = strtoupper(trim($type)); + + if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE)) + { + $type = ''; + } + else + { + $type .= ' '; + } + } + + $cond = array(); + $keys = is_array($key) ? $key : array($key => $value); + foreach ($keys as $key => $value) + { + $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key; + + if (is_string($value)) + { + // Only escape if it's a string + $value = $this->driver->escape_column($this->config['table_prefix'].$value); + } + + $cond[] = $this->driver->where($key, $value, 'AND ', count($cond), FALSE); + } + + if ( ! is_array($this->join)) + { + $this->join = array(); + } + + if ( ! is_array($table)) + { + $table = array($table); + } + + foreach ($table as $t) + { + if (is_string($t)) + { + // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice) + if (stripos($t, ' AS ') !== FALSE) + { + $t = str_ireplace(' AS ', ' AS ', $t); + + list($table, $alias) = explode(' AS ', $t); + + // Attach prefix to both sides of the AS + $t = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias; + } + else + { + $t = $this->config['table_prefix'].$t; + } + } + + $join['tables'][] = $this->driver->escape_column($t); + } + + $join['conditions'] = '('.trim(implode(' ', $cond)).')'; + $join['type'] = $type; + + $this->join[] = $join; + + return $this; + } + + + /** + * Selects the where(s) for a database query. + * + * @param string|array key name or array of key => value pairs + * @param string value to match with key + * @param boolean disable quoting of WHERE clause + * @return Database_Core This Database object. + */ + public function where($key, $value = NULL, $quote = TRUE) + { + $quote = (func_num_args() < 2 AND ! is_array($key)) ? -1 : $quote; + if (is_object($key)) + { + $keys = array((string) $key => ''); + } + elseif ( ! is_array($key)) + { + $keys = array($key => $value); + } + else + { + $keys = $key; + } + + foreach ($keys as $key => $value) + { + $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key; + $this->where[] = $this->driver->where($key, $value, 'AND ', count($this->where), $quote); + } + + return $this; + } + + /** + * Selects the or where(s) for a database query. + * + * @param string|array key name or array of key => value pairs + * @param string value to match with key + * @param boolean disable quoting of WHERE clause + * @return Database_Core This Database object. + */ + public function orwhere($key, $value = NULL, $quote = TRUE) + { + $quote = (func_num_args() < 2 AND ! is_array($key)) ? -1 : $quote; + if (is_object($key)) + { + $keys = array((string) $key => ''); + } + elseif ( ! is_array($key)) + { + $keys = array($key => $value); + } + else + { + $keys = $key; + } + + foreach ($keys as $key => $value) + { + $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key; + $this->where[] = $this->driver->where($key, $value, 'OR ', count($this->where), $quote); + } + + return $this; + } + + /** + * Selects the like(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string like value to match with field + * @param boolean automatically add starting and ending wildcards + * @return Database_Core This Database object. + */ + public function like($field, $match = '', $auto = TRUE) + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->like($field, $match, $auto, 'AND ', count($this->where)); + } + + return $this; + } + + /** + * Selects the or like(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string like value to match with field + * @param boolean automatically add starting and ending wildcards + * @return Database_Core This Database object. + */ + public function orlike($field, $match = '', $auto = TRUE) + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->like($field, $match, $auto, 'OR ', count($this->where)); + } + + return $this; + } + + /** + * Selects the not like(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string like value to match with field + * @param boolean automatically add starting and ending wildcards + * @return Database_Core This Database object. + */ + public function notlike($field, $match = '', $auto = TRUE) + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->notlike($field, $match, $auto, 'AND ', count($this->where)); + } + + return $this; + } + + /** + * Selects the or not like(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string like value to match with field + * @return Database_Core This Database object. + */ + public function ornotlike($field, $match = '', $auto = TRUE) + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->notlike($field, $match, $auto, 'OR ', count($this->where)); + } + + return $this; + } + + /** + * Selects the like(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string like value to match with field + * @return Database_Core This Database object. + */ + public function regex($field, $match = '') + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->regex($field, $match, 'AND ', count($this->where)); + } + + return $this; + } + + /** + * Selects the or like(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string like value to match with field + * @return Database_Core This Database object. + */ + public function orregex($field, $match = '') + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->regex($field, $match, 'OR ', count($this->where)); + } + + return $this; + } + + /** + * Selects the not regex(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string regex value to match with field + * @return Database_Core This Database object. + */ + public function notregex($field, $match = '') + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->notregex($field, $match, 'AND ', count($this->where)); + } + + return $this; + } + + /** + * Selects the or not regex(s) for a database query. + * + * @param string|array field name or array of field => match pairs + * @param string regex value to match with field + * @return Database_Core This Database object. + */ + public function ornotregex($field, $match = '') + { + $fields = is_array($field) ? $field : array($field => $match); + + foreach ($fields as $field => $match) + { + $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; + $this->where[] = $this->driver->notregex($field, $match, 'OR ', count($this->where)); + } + + return $this; + } + + /** + * Chooses the column to group by in a select query. + * + * @param string column name to group by + * @return Database_Core This Database object. + */ + public function groupby($by) + { + if ( ! is_array($by)) + { + $by = explode(',', (string) $by); + } + + foreach ($by as $val) + { + $val = trim($val); + + if ($val != '') + { + // Add the table prefix if we are using table.column names + if(strpos($val, '.')) + { + $val = $this->config['table_prefix'].$val; + } + + $this->groupby[] = $this->driver->escape_column($val); + } + } + + return $this; + } + + /** + * Selects the having(s) for a database query. + * + * @param string|array key name or array of key => value pairs + * @param string value to match with key + * @param boolean disable quoting of WHERE clause + * @return Database_Core This Database object. + */ + public function having($key, $value = '', $quote = TRUE) + { + $this->having[] = $this->driver->where($key, $value, 'AND', count($this->having), TRUE); + return $this; + } + + /** + * Selects the or having(s) for a database query. + * + * @param string|array key name or array of key => value pairs + * @param string value to match with key + * @param boolean disable quoting of WHERE clause + * @return Database_Core This Database object. + */ + public function orhaving($key, $value = '', $quote = TRUE) + { + $this->having[] = $this->driver->where($key, $value, 'OR', count($this->having), TRUE); + return $this; + } + + /** + * Chooses which column(s) to order the select query by. + * + * @param string|array column(s) to order on, can be an array, single column, or comma seperated list of columns + * @param string direction of the order + * @return Database_Core This Database object. + */ + public function orderby($orderby, $direction = NULL) + { + if ( ! is_array($orderby)) + { + $orderby = array($orderby => $direction); + } + + foreach ($orderby as $column => $direction) + { + $direction = strtoupper(trim($direction)); + + // Add a direction if the provided one isn't valid + if ( ! in_array($direction, array('ASC', 'DESC', 'RAND()', 'RANDOM()', 'NULL'))) + { + $direction = 'ASC'; + } + + // Add the table prefix if a table.column was passed + if (strpos($column, '.')) + { + $column = $this->config['table_prefix'].$column; + } + + $this->orderby[] = $this->driver->escape_column($column).' '.$direction; + } + + return $this; + } + + /** + * Selects the limit section of a query. + * + * @param integer number of rows to limit result to + * @param integer offset in result to start returning rows from + * @return Database_Core This Database object. + */ + public function limit($limit, $offset = NULL) + { + $this->limit = (int) $limit; + + if ($offset !== NULL OR ! is_int($this->offset)) + { + $this->offset($offset); + } + + return $this; + } + + /** + * Sets the offset portion of a query. + * + * @param integer offset value + * @return Database_Core This Database object. + */ + public function offset($value) + { + $this->offset = (int) $value; + + return $this; + } + + /** + * Allows key/value pairs to be set for inserting or updating. + * + * @param string|array key name or array of key => value pairs + * @param string value to match with key + * @return Database_Core This Database object. + */ + public function set($key, $value = '') + { + if ( ! is_array($key)) + { + $key = array($key => $value); + } + + foreach ($key as $k => $v) + { + // Add a table prefix if the column includes the table. + if (strpos($k, '.')) + $k = $this->config['table_prefix'].$k; + + $this->set[$k] = $this->driver->escape($v); + } + + return $this; + } + + /** + * Compiles the select statement based on the other functions called and runs the query. + * + * @param string table name + * @param string limit clause + * @param string offset clause + * @return Database_Result + */ + public function get($table = '', $limit = NULL, $offset = NULL) + { + if ($table != '') + { + $this->from($table); + } + + if ( ! is_null($limit)) + { + $this->limit($limit, $offset); + } + + $sql = $this->driver->compile_select(get_object_vars($this)); + + $this->reset_select(); + + $result = $this->query($sql); + + $this->last_query = $sql; + + return $result; + } + + /** + * Compiles the select statement based on the other functions called and runs the query. + * + * @param string table name + * @param array where clause + * @param string limit clause + * @param string offset clause + * @return Database_Core This Database object. + */ + public function getwhere($table = '', $where = NULL, $limit = NULL, $offset = NULL) + { + if ($table != '') + { + $this->from($table); + } + + if ( ! is_null($where)) + { + $this->where($where); + } + + if ( ! is_null($limit)) + { + $this->limit($limit, $offset); + } + + $sql = $this->driver->compile_select(get_object_vars($this)); + + $this->reset_select(); + + $result = $this->query($sql); + + return $result; + } + + /** + * Compiles the select statement based on the other functions called and returns the query string. + * + * @param string table name + * @param string limit clause + * @param string offset clause + * @return string sql string + */ + public function compile($table = '', $limit = NULL, $offset = NULL) + { + if ($table != '') + { + $this->from($table); + } + + if ( ! is_null($limit)) + { + $this->limit($limit, $offset); + } + + $sql = $this->driver->compile_select(get_object_vars($this)); + + $this->reset_select(); + + return $sql; + } + + /** + * Compiles an insert string and runs the query. + * + * @param string table name + * @param array array of key/value pairs to insert + * @return Database_Result Query result + */ + public function insert($table = '', $set = NULL) + { + if ( ! is_null($set)) + { + $this->set($set); + } + + if ($this->set == NULL) + throw new Kohana_Database_Exception('database.must_use_set'); + + if ($table == '') + { + if ( ! isset($this->from[0])) + throw new Kohana_Database_Exception('database.must_use_table'); + + $table = $this->from[0]; + } + + // If caching is enabled, clear the cache before inserting + ($this->config['cache'] === TRUE) and $this->clear_cache(); + + $sql = $this->driver->insert($this->config['table_prefix'].$table, array_keys($this->set), array_values($this->set)); + + $this->reset_write(); + + return $this->query($sql); + } + + /** + * Adds an "IN" condition to the where clause + * + * @param string Name of the column being examined + * @param mixed An array or string to match against + * @param bool Generate a NOT IN clause instead + * @return Database_Core This Database object. + */ + public function in($field, $values, $not = FALSE) + { + if (is_array($values)) + { + $escaped_values = array(); + foreach ($values as $v) + { + if (is_numeric($v)) + { + $escaped_values[] = $v; + } + else + { + $escaped_values[] = "'".$this->driver->escape_str($v)."'"; + } + } + $values = implode(",", $escaped_values); + } + + $where = $this->driver->escape_column(((strpos($field,'.') !== FALSE) ? $this->config['table_prefix'] : ''). $field).' '.($not === TRUE ? 'NOT ' : '').'IN ('.$values.')'; + $this->where[] = $this->driver->where($where, '', 'AND ', count($this->where), -1); + + return $this; + } + + /** + * Adds a "NOT IN" condition to the where clause + * + * @param string Name of the column being examined + * @param mixed An array or string to match against + * @return Database_Core This Database object. + */ + public function notin($field, $values) + { + return $this->in($field, $values, TRUE); + } + + /** + * Compiles a merge string and runs the query. + * + * @param string table name + * @param array array of key/value pairs to merge + * @return Database_Result Query result + */ + public function merge($table = '', $set = NULL) + { + if ( ! is_null($set)) + { + $this->set($set); + } + + if ($this->set == NULL) + throw new Kohana_Database_Exception('database.must_use_set'); + + if ($table == '') + { + if ( ! isset($this->from[0])) + throw new Kohana_Database_Exception('database.must_use_table'); + + $table = $this->from[0]; + } + + $sql = $this->driver->merge($this->config['table_prefix'].$table, array_keys($this->set), array_values($this->set)); + + $this->reset_write(); + return $this->query($sql); + } + + /** + * Compiles an update string and runs the query. + * + * @param string table name + * @param array associative array of update values + * @param array where clause + * @return Database_Result Query result + */ + public function update($table = '', $set = NULL, $where = NULL) + { + if ( is_array($set)) + { + $this->set($set); + } + + if ( ! is_null($where)) + { + $this->where($where); + } + + if ($this->set == FALSE) + throw new Kohana_Database_Exception('database.must_use_set'); + + if ($table == '') + { + if ( ! isset($this->from[0])) + throw new Kohana_Database_Exception('database.must_use_table'); + + $table = $this->from[0]; + } + + $sql = $this->driver->update($this->config['table_prefix'].$table, $this->set, $this->where); + + $this->reset_write(); + return $this->query($sql); + } + + /** + * Compiles a delete string and runs the query. + * + * @param string table name + * @param array where clause + * @return Database_Result Query result + */ + public function delete($table = '', $where = NULL) + { + if ($table == '') + { + if ( ! isset($this->from[0])) + throw new Kohana_Database_Exception('database.must_use_table'); + + $table = $this->from[0]; + } + else + { + $table = $this->config['table_prefix'].$table; + } + + if (! is_null($where)) + { + $this->where($where); + } + + if (count($this->where) < 1) + throw new Kohana_Database_Exception('database.must_use_where'); + + $sql = $this->driver->delete($table, $this->where); + + $this->reset_write(); + return $this->query($sql); + } + + /** + * Returns the last query run. + * + * @return string SQL + */ + public function last_query() + { + return $this->last_query; + } + + /** + * Count query records. + * + * @param string table name + * @param array where clause + * @return integer + */ + public function count_records($table = FALSE, $where = NULL) + { + if (count($this->from) < 1) + { + if ($table == FALSE) + throw new Kohana_Database_Exception('database.must_use_table'); + + $this->from($table); + } + + if ($where !== NULL) + { + $this->where($where); + } + + $query = $this->select('COUNT(*) AS '.$this->escape_column('records_found'))->get()->result(TRUE); + + return (int) $query->current()->records_found; + } + + /** + * Resets all private select variables. + * + * @return void + */ + protected function reset_select() + { + $this->select = array(); + $this->from = array(); + $this->join = array(); + $this->where = array(); + $this->orderby = array(); + $this->groupby = array(); + $this->having = array(); + $this->distinct = FALSE; + $this->limit = FALSE; + $this->offset = FALSE; + } + + /** + * Resets all private insert and update variables. + * + * @return void + */ + protected function reset_write() + { + $this->set = array(); + $this->from = array(); + $this->where = array(); + } + + /** + * Lists all the tables in the current database. + * + * @return array + */ + public function list_tables() + { + $this->link or $this->connect(); + + return $this->driver->list_tables(); + } + + /** + * See if a table exists in the database. + * + * @param string table name + * @param boolean True to attach table prefix + * @return boolean + */ + public function table_exists($table_name, $prefix = TRUE) + { + if ($prefix) + return in_array($this->config['table_prefix'].$table_name, $this->list_tables()); + else + return in_array($table_name, $this->list_tables()); + } + + /** + * Combine a SQL statement with the bind values. Used for safe queries. + * + * @param string query to bind to the values + * @param array array of values to bind to the query + * @return string + */ + public function compile_binds($sql, $binds) + { + foreach ((array) $binds as $val) + { + // If the SQL contains no more bind marks ("?"), we're done. + if (($next_bind_pos = strpos($sql, '?')) === FALSE) + break; + + // Properly escape the bind value. + $val = $this->driver->escape($val); + + // Temporarily replace possible bind marks ("?"), in the bind value itself, with a placeholder. + $val = str_replace('?', '{%B%}', $val); + + // Replace the first bind mark ("?") with its corresponding value. + $sql = substr($sql, 0, $next_bind_pos).$val.substr($sql, $next_bind_pos + 1); + } + + // Restore placeholders. + return str_replace('{%B%}', '?', $sql); + } + + /** + * Get the field data for a database table, along with the field's attributes. + * + * @param string table name + * @return array + */ + public function field_data($table = '') + { + $this->link or $this->connect(); + + return $this->driver->field_data($this->config['table_prefix'].$table); + } + + /** + * Get the field data for a database table, along with the field's attributes. + * + * @param string table name + * @return array + */ + public function list_fields($table = '') + { + $this->link or $this->connect(); + + return $this->driver->list_fields($this->config['table_prefix'].$table); + } + + /** + * Escapes a value for a query. + * + * @param mixed value to escape + * @return string + */ + public function escape($value) + { + return $this->driver->escape($value); + } + + /** + * Escapes a string for a query. + * + * @param string string to escape + * @return string + */ + public function escape_str($str) + { + return $this->driver->escape_str($str); + } + + /** + * Escapes a table name for a query. + * + * @param string string to escape + * @return string + */ + public function escape_table($table) + { + return $this->driver->escape_table($table); + } + + /** + * Escapes a column name for a query. + * + * @param string string to escape + * @return string + */ + public function escape_column($table) + { + return $this->driver->escape_column($table); + } + + /** + * Returns table prefix of current configuration. + * + * @return string + */ + public function table_prefix() + { + return $this->config['table_prefix']; + } + + /** + * Clears the query cache. + * + * @param string|TRUE clear cache by SQL statement or TRUE for last query + * @return Database_Core This Database object. + */ + public function clear_cache($sql = NULL) + { + if ($sql === TRUE) + { + $this->driver->clear_cache($this->last_query); + } + elseif (is_string($sql)) + { + $this->driver->clear_cache($sql); + } + else + { + $this->driver->clear_cache(); + } + + return $this; + } + + /** + * Pushes existing query space onto the query stack. Use push + * and pop to prevent queries from clashing before they are + * executed + * + * @return Database_Core This Databaes object + */ + public function push() + { + array_push($this->query_history, array( + $this->select, + $this->from, + $this->join, + $this->where, + $this->orderby, + $this->order, + $this->groupby, + $this->having, + $this->distinct, + $this->limit, + $this->offset + )); + + $this->reset_select(); + + return $this; + } + + /** + * Pops from query stack into the current query space. + * + * @return Database_Core This Databaes object + */ + public function pop() + { + if (count($this->query_history) == 0) + { + // No history + return $this; + } + + list( + $this->select, + $this->from, + $this->join, + $this->where, + $this->orderby, + $this->order, + $this->groupby, + $this->having, + $this->distinct, + $this->limit, + $this->offset + ) = array_pop($this->query_history); + + return $this; + } + + /** + * Count the number of records in the last query, without LIMIT or OFFSET applied. + * + * @return integer + */ + public function count_last_query() + { + if ($sql = $this->last_query()) + { + if (stripos($sql, 'LIMIT') !== FALSE) + { + // Remove LIMIT from the SQL + $sql = preg_replace('/\sLIMIT\s+[^a-z]+/i', ' ', $sql); + } + + if (stripos($sql, 'OFFSET') !== FALSE) + { + // Remove OFFSET from the SQL + $sql = preg_replace('/\sOFFSET\s+\d+/i', '', $sql); + } + + // Get the total rows from the last query executed + $result = $this->query + ( + 'SELECT COUNT(*) AS '.$this->escape_column('total_rows').' '. + 'FROM ('.trim($sql).') AS '.$this->escape_table('counted_results') + ); + + // Return the total number of rows from the query + return (int) $result->current()->total_rows; + } + + return FALSE; + } + +} // End Database Class + + +/** + * Sets the code for a Database exception. + */ +class Kohana_Database_Exception extends Kohana_Exception { + + protected $code = E_DATABASE_ERROR; + +} // End Kohana Database Exception diff --git a/lib/kohana/system/libraries/Database_Expression.php b/lib/kohana/system/libraries/Database_Expression.php new file mode 100644 index 0000000..940a636 --- /dev/null +++ b/lib/kohana/system/libraries/Database_Expression.php @@ -0,0 +1,26 @@ +expression = $expression; + } + + public function __toString() + { + return (string) $this->expression; + } + +} // End Database Expr Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/Encrypt.php b/lib/kohana/system/libraries/Encrypt.php new file mode 100644 index 0000000..3d564f9 --- /dev/null +++ b/lib/kohana/system/libraries/Encrypt.php @@ -0,0 +1,164 @@ + $size) + { + // Shorten the key to the maximum size + $config['key'] = substr($config['key'], 0, $size); + } + + // Find the initialization vector size + $config['iv_size'] = mcrypt_get_iv_size($config['cipher'], $config['mode']); + + // Cache the config in the object + $this->config = $config; + + Kohana::log('debug', 'Encrypt Library initialized'); + } + + /** + * Encrypts a string and returns an encrypted string that can be decoded. + * + * @param string data to be encrypted + * @return string encrypted data + */ + public function encode($data) + { + // Set the rand type if it has not already been set + if (Encrypt::$rand === NULL) + { + if (KOHANA_IS_WIN) + { + // Windows only supports the system random number generator + Encrypt::$rand = MCRYPT_RAND; + } + else + { + if (defined('MCRYPT_DEV_URANDOM')) + { + // Use /dev/urandom + Encrypt::$rand = MCRYPT_DEV_URANDOM; + } + elseif (defined('MCRYPT_DEV_RANDOM')) + { + // Use /dev/random + Encrypt::$rand = MCRYPT_DEV_RANDOM; + } + else + { + // Use the system random number generator + Encrypt::$rand = MCRYPT_RAND; + } + } + } + + if (Encrypt::$rand === MCRYPT_RAND) + { + // The system random number generator must always be seeded each + // time it is used, or it will not produce true random results + mt_srand(); + } + + // Create a random initialization vector of the proper size for the current cipher + $iv = mcrypt_create_iv($this->config['iv_size'], Encrypt::$rand); + + // Encrypt the data using the configured options and generated iv + $data = mcrypt_encrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv); + + // Use base64 encoding to convert to a string + return base64_encode($iv.$data); + } + + /** + * Decrypts an encoded string back to its original value. + * + * @param string encoded string to be decrypted + * @return string decrypted data + */ + public function decode($data) + { + // Convert the data back to binary + $data = base64_decode($data); + + // Extract the initialization vector from the data + $iv = substr($data, 0, $this->config['iv_size']); + + // Remove the iv from the data + $data = substr($data, $this->config['iv_size']); + + // Return the decrypted data, trimming the \0 padding bytes from the end of the data + return rtrim(mcrypt_decrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv), "\0"); + } + +} // End Encrypt diff --git a/lib/kohana/system/libraries/Event_Observer.php b/lib/kohana/system/libraries/Event_Observer.php new file mode 100644 index 0000000..086c8a2 --- /dev/null +++ b/lib/kohana/system/libraries/Event_Observer.php @@ -0,0 +1,70 @@ +update($caller); + } + + /** + * Updates the observer subject with a new caller. + * + * @chainable + * @param object Event_Subject + * @return object + */ + public function update(SplSubject $caller) + { + if ( ! ($caller instanceof Event_Subject)) + throw new Kohana_Exception('event.invalid_subject', get_class($caller), get_class($this)); + + // Update the caller + $this->caller = $caller; + + return $this; + } + + /** + * Detaches this observer from the subject. + * + * @chainable + * @return object + */ + public function remove() + { + // Detach this observer from the caller + $this->caller->detach($this); + + return $this; + } + + /** + * Notify the observer of a new message. This function must be defined in + * all observers and must take exactly one parameter of any type. + * + * @param mixed message string, object, or array + * @return void + */ + abstract public function notify($message); + +} // End Event Observer \ No newline at end of file diff --git a/lib/kohana/system/libraries/Event_Subject.php b/lib/kohana/system/libraries/Event_Subject.php new file mode 100644 index 0000000..d1ccc54 --- /dev/null +++ b/lib/kohana/system/libraries/Event_Subject.php @@ -0,0 +1,67 @@ +listeners[spl_object_hash($obj)] = $obj; + + return $this; + } + + /** + * Detach an observer from the object. + * + * @chainable + * @param object Event_Observer + * @return object + */ + public function detach(SplObserver $obj) + { + // Remove the listener + unset($this->listeners[spl_object_hash($obj)]); + + return $this; + } + + /** + * Notify all attached observers of a new message. + * + * @chainable + * @param mixed message string, object, or array + * @return object + */ + public function notify($message) + { + foreach ($this->listeners as $obj) + { + $obj->notify($message); + } + + return $this; + } + +} // End Event Subject \ No newline at end of file diff --git a/lib/kohana/system/libraries/Image.php b/lib/kohana/system/libraries/Image.php new file mode 100644 index 0000000..2de0658 --- /dev/null +++ b/lib/kohana/system/libraries/Image.php @@ -0,0 +1,431 @@ + 'gif', + IMAGETYPE_JPEG => 'jpg', + IMAGETYPE_PNG => 'png', + IMAGETYPE_TIFF_II => 'tiff', + IMAGETYPE_TIFF_MM => 'tiff', + ); + + // Driver instance + protected $driver; + + // Driver actions + protected $actions = array(); + + // Reference to the current image filename + protected $image = ''; + + /** + * Creates a new Image instance and returns it. + * + * @param string filename of image + * @param array non-default configurations + * @return object + */ + public static function factory($image, $config = NULL) + { + return new Image($image, $config); + } + + /** + * Creates a new image editor instance. + * + * @throws Kohana_Exception + * @param string filename of image + * @param array non-default configurations + * @return void + */ + public function __construct($image, $config = NULL) + { + static $check; + + // Make the check exactly once + ($check === NULL) and $check = function_exists('getimagesize'); + + if ($check === FALSE) + throw new Kohana_Exception('image.getimagesize_missing'); + + // Check to make sure the image exists + if ( ! is_file($image)) + throw new Kohana_Exception('image.file_not_found', $image); + + // Disable error reporting, to prevent PHP warnings + $ER = error_reporting(0); + + // Fetch the image size and mime type + $image_info = getimagesize($image); + + // Turn on error reporting again + error_reporting($ER); + + // Make sure that the image is readable and valid + if ( ! is_array($image_info) OR count($image_info) < 3) + throw new Kohana_Exception('image.file_unreadable', $image); + + // Check to make sure the image type is allowed + if ( ! isset(Image::$allowed_types[$image_info[2]])) + throw new Kohana_Exception('image.type_not_allowed', $image); + + // Image has been validated, load it + $this->image = array + ( + 'file' => str_replace('\\', '/', realpath($image)), + 'width' => $image_info[0], + 'height' => $image_info[1], + 'type' => $image_info[2], + 'ext' => Image::$allowed_types[$image_info[2]], + 'mime' => $image_info['mime'] + ); + + // Load configuration + $this->config = (array) $config + Kohana::config('image'); + + // Set driver class name + $driver = 'Image_'.ucfirst($this->config['driver']).'_Driver'; + + // Load the driver + if ( ! Kohana::auto_load($driver)) + throw new Kohana_Exception('core.driver_not_found', $this->config['driver'], get_class($this)); + + // Initialize the driver + $this->driver = new $driver($this->config['params']); + + // Validate the driver + if ( ! ($this->driver instanceof Image_Driver)) + throw new Kohana_Exception('core.driver_implements', $this->config['driver'], get_class($this), 'Image_Driver'); + } + + /** + * Handles retrieval of pre-save image properties + * + * @param string property name + * @return mixed + */ + public function __get($property) + { + if (isset($this->image[$property])) + { + return $this->image[$property]; + } + else + { + throw new Kohana_Exception('core.invalid_property', $property, get_class($this)); + } + } + + /** + * Resize an image to a specific width and height. By default, Kohana will + * maintain the aspect ratio using the width as the master dimension. If you + * wish to use height as master dim, set $image->master_dim = Image::HEIGHT + * This method is chainable. + * + * @throws Kohana_Exception + * @param integer width + * @param integer height + * @param integer one of: Image::NONE, Image::AUTO, Image::WIDTH, Image::HEIGHT + * @return object + */ + public function resize($width, $height, $master = NULL) + { + if ( ! $this->valid_size('width', $width)) + throw new Kohana_Exception('image.invalid_width', $width); + + if ( ! $this->valid_size('height', $height)) + throw new Kohana_Exception('image.invalid_height', $height); + + if (empty($width) AND empty($height)) + throw new Kohana_Exception('image.invalid_dimensions', __FUNCTION__); + + if ($master === NULL) + { + // Maintain the aspect ratio by default + $master = Image::AUTO; + } + elseif ( ! $this->valid_size('master', $master)) + throw new Kohana_Exception('image.invalid_master'); + + $this->actions['resize'] = array + ( + 'width' => $width, + 'height' => $height, + 'master' => $master, + ); + + return $this; + } + + /** + * Crop an image to a specific width and height. You may also set the top + * and left offset. + * This method is chainable. + * + * @throws Kohana_Exception + * @param integer width + * @param integer height + * @param integer top offset, pixel value or one of: top, center, bottom + * @param integer left offset, pixel value or one of: left, center, right + * @return object + */ + public function crop($width, $height, $top = 'center', $left = 'center') + { + if ( ! $this->valid_size('width', $width)) + throw new Kohana_Exception('image.invalid_width', $width); + + if ( ! $this->valid_size('height', $height)) + throw new Kohana_Exception('image.invalid_height', $height); + + if ( ! $this->valid_size('top', $top)) + throw new Kohana_Exception('image.invalid_top', $top); + + if ( ! $this->valid_size('left', $left)) + throw new Kohana_Exception('image.invalid_left', $left); + + if (empty($width) AND empty($height)) + throw new Kohana_Exception('image.invalid_dimensions', __FUNCTION__); + + $this->actions['crop'] = array + ( + 'width' => $width, + 'height' => $height, + 'top' => $top, + 'left' => $left, + ); + + return $this; + } + + /** + * Allows rotation of an image by 180 degrees clockwise or counter clockwise. + * + * @param integer degrees + * @return object + */ + public function rotate($degrees) + { + $degrees = (int) $degrees; + + if ($degrees > 180) + { + do + { + // Keep subtracting full circles until the degrees have normalized + $degrees -= 360; + } + while($degrees > 180); + } + + if ($degrees < -180) + { + do + { + // Keep adding full circles until the degrees have normalized + $degrees += 360; + } + while($degrees < -180); + } + + $this->actions['rotate'] = $degrees; + + return $this; + } + + /** + * Flip an image horizontally or vertically. + * + * @throws Kohana_Exception + * @param integer direction + * @return object + */ + public function flip($direction) + { + if ($direction !== Image::HORIZONTAL AND $direction !== Image::VERTICAL) + throw new Kohana_Exception('image.invalid_flip'); + + $this->actions['flip'] = $direction; + + return $this; + } + + /** + * Change the quality of an image. + * + * @param integer quality as a percentage + * @return object + */ + public function quality($amount) + { + $this->actions['quality'] = max(1, min($amount, 100)); + + return $this; + } + + /** + * Sharpen an image. + * + * @param integer amount to sharpen, usually ~20 is ideal + * @return object + */ + public function sharpen($amount) + { + $this->actions['sharpen'] = max(1, min($amount, 100)); + + return $this; + } + + /** + * Save the image to a new image or overwrite this image. + * + * @throws Kohana_Exception + * @param string new image filename + * @param integer permissions for new image + * @param boolean keep or discard image process actions + * @return object + */ + public function save($new_image = FALSE, $chmod = 0644, $keep_actions = FALSE) + { + // If no new image is defined, use the current image + empty($new_image) and $new_image = $this->image['file']; + + // Separate the directory and filename + $dir = pathinfo($new_image, PATHINFO_DIRNAME); + $file = pathinfo($new_image, PATHINFO_BASENAME); + + // Normalize the path + $dir = str_replace('\\', '/', realpath($dir)).'/'; + + if ( ! is_writable($dir)) + throw new Kohana_Exception('image.directory_unwritable', $dir); + + if ($status = $this->driver->process($this->image, $this->actions, $dir, $file)) + { + if ($chmod !== FALSE) + { + // Set permissions + chmod($new_image, $chmod); + } + } + + // Reset actions. Subsequent save() or render() will not apply previous actions. + if ($keep_actions === FALSE) + $this->actions = array(); + + return $status; + } + + /** + * Output the image to the browser. + * + * @param boolean keep or discard image process actions + * @return object + */ + public function render($keep_actions = FALSE) + { + $new_image = $this->image['file']; + + // Separate the directory and filename + $dir = pathinfo($new_image, PATHINFO_DIRNAME); + $file = pathinfo($new_image, PATHINFO_BASENAME); + + // Normalize the path + $dir = str_replace('\\', '/', realpath($dir)).'/'; + + // Process the image with the driver + $status = $this->driver->process($this->image, $this->actions, $dir, $file, $render = TRUE); + + // Reset actions. Subsequent save() or render() will not apply previous actions. + if ($keep_actions === FALSE) + $this->actions = array(); + + return $status; + } + + /** + * Sanitize a given value type. + * + * @param string type of property + * @param mixed property value + * @return boolean + */ + protected function valid_size($type, & $value) + { + if (is_null($value)) + return TRUE; + + if ( ! is_scalar($value)) + return FALSE; + + switch ($type) + { + case 'width': + case 'height': + if (is_string($value) AND ! ctype_digit($value)) + { + // Only numbers and percent signs + if ( ! preg_match('/^[0-9]++%$/D', $value)) + return FALSE; + } + else + { + $value = (int) $value; + } + break; + case 'top': + if (is_string($value) AND ! ctype_digit($value)) + { + if ( ! in_array($value, array('top', 'bottom', 'center'))) + return FALSE; + } + else + { + $value = (int) $value; + } + break; + case 'left': + if (is_string($value) AND ! ctype_digit($value)) + { + if ( ! in_array($value, array('left', 'right', 'center'))) + return FALSE; + } + else + { + $value = (int) $value; + } + break; + case 'master': + if ($value !== Image::NONE AND + $value !== Image::AUTO AND + $value !== Image::WIDTH AND + $value !== Image::HEIGHT) + return FALSE; + break; + } + + return TRUE; + } + +} // End Image \ No newline at end of file diff --git a/lib/kohana/system/libraries/Input.php b/lib/kohana/system/libraries/Input.php new file mode 100644 index 0000000..0e23c80 --- /dev/null +++ b/lib/kohana/system/libraries/Input.php @@ -0,0 +1,452 @@ +use_xss_clean = (bool) Kohana::config('core.global_xss_filtering'); + + if (Input::$instance === NULL) + { + // magic_quotes_runtime is enabled + if (get_magic_quotes_runtime()) + { + set_magic_quotes_runtime(0); + Kohana::log('debug', 'Disable magic_quotes_runtime! It is evil and deprecated: http://php.net/magic_quotes'); + } + + // magic_quotes_gpc is enabled + if (get_magic_quotes_gpc()) + { + $this->magic_quotes_gpc = TRUE; + Kohana::log('debug', 'Disable magic_quotes_gpc! It is evil and deprecated: http://php.net/magic_quotes'); + } + + // register_globals is enabled + if (ini_get('register_globals')) + { + if (isset($_REQUEST['GLOBALS'])) + { + // Prevent GLOBALS override attacks + exit('Global variable overload attack.'); + } + + // Destroy the REQUEST global + $_REQUEST = array(); + + // These globals are standard and should not be removed + $preserve = array('GLOBALS', '_REQUEST', '_GET', '_POST', '_FILES', '_COOKIE', '_SERVER', '_ENV', '_SESSION'); + + // This loop has the same effect as disabling register_globals + foreach (array_diff(array_keys($GLOBALS), $preserve) as $key) + { + global $$key; + $$key = NULL; + + // Unset the global variable + unset($GLOBALS[$key], $$key); + } + + // Warn the developer about register globals + Kohana::log('debug', 'Disable register_globals! It is evil and deprecated: http://php.net/register_globals'); + } + + if (is_array($_GET)) + { + foreach ($_GET as $key => $val) + { + // Sanitize $_GET + $_GET[$this->clean_input_keys($key)] = $this->clean_input_data($val); + } + } + else + { + $_GET = array(); + } + + if (is_array($_POST)) + { + foreach ($_POST as $key => $val) + { + // Sanitize $_POST + $_POST[$this->clean_input_keys($key)] = $this->clean_input_data($val); + } + } + else + { + $_POST = array(); + } + + if (is_array($_COOKIE)) + { + foreach ($_COOKIE as $key => $val) + { + // Ignore special attributes in RFC2109 compliant cookies + if ($key == '$Version' OR $key == '$Path' OR $key == '$Domain') + continue; + + // Sanitize $_COOKIE + $_COOKIE[$this->clean_input_keys($key)] = $this->clean_input_data($val); + } + } + else + { + $_COOKIE = array(); + } + + // Create a singleton + Input::$instance = $this; + + Kohana::log('debug', 'Global GET, POST and COOKIE data sanitized'); + } + } + + /** + * Fetch an item from the $_GET array. + * + * @param string key to find + * @param mixed default value + * @param boolean XSS clean the value + * @return mixed + */ + public function get($key = array(), $default = NULL, $xss_clean = FALSE) + { + return $this->search_array($_GET, $key, $default, $xss_clean); + } + + /** + * Fetch an item from the $_POST array. + * + * @param string key to find + * @param mixed default value + * @param boolean XSS clean the value + * @return mixed + */ + public function post($key = array(), $default = NULL, $xss_clean = FALSE) + { + return $this->search_array($_POST, $key, $default, $xss_clean); + } + + /** + * Fetch an item from the $_COOKIE array. + * + * @param string key to find + * @param mixed default value + * @param boolean XSS clean the value + * @return mixed + */ + public function cookie($key = array(), $default = NULL, $xss_clean = FALSE) + { + return $this->search_array($_COOKIE, $key, $default, $xss_clean); + } + + /** + * Fetch an item from the $_SERVER array. + * + * @param string key to find + * @param mixed default value + * @param boolean XSS clean the value + * @return mixed + */ + public function server($key = array(), $default = NULL, $xss_clean = FALSE) + { + return $this->search_array($_SERVER, $key, $default, $xss_clean); + } + + /** + * Fetch an item from a global array. + * + * @param array array to search + * @param string key to find + * @param mixed default value + * @param boolean XSS clean the value + * @return mixed + */ + protected function search_array($array, $key, $default = NULL, $xss_clean = FALSE) + { + if ($key === array()) + return $array; + + if ( ! isset($array[$key])) + return $default; + + // Get the value + $value = $array[$key]; + + if ($this->use_xss_clean === FALSE AND $xss_clean === TRUE) + { + // XSS clean the value + $value = $this->xss_clean($value); + } + + return $value; + } + + /** + * Fetch the IP Address. + * + * @return string + */ + public function ip_address() + { + if ($this->ip_address !== NULL) + return $this->ip_address; + + // Server keys that could contain the client IP address + $keys = array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'); + + foreach ($keys as $key) + { + if ($ip = $this->server($key)) + { + $this->ip_address = $ip; + + // An IP address has been found + break; + } + } + + if ($comma = strrpos($this->ip_address, ',') !== FALSE) + { + $this->ip_address = substr($this->ip_address, $comma + 1); + } + + if ( ! valid::ip($this->ip_address)) + { + // Use an empty IP + $this->ip_address = '0.0.0.0'; + } + + return $this->ip_address; + } + + /** + * Clean cross site scripting exploits from string. + * HTMLPurifier may be used if installed, otherwise defaults to built in method. + * Note - This function should only be used to deal with data upon submission. + * It's not something that should be used for general runtime processing + * since it requires a fair amount of processing overhead. + * + * @param string data to clean + * @param string xss_clean method to use ('htmlpurifier' or defaults to built-in method) + * @return string + */ + public function xss_clean($data, $tool = NULL) + { + if ($tool === NULL) + { + // Use the default tool + $tool = Kohana::config('core.global_xss_filtering'); + } + + if (is_array($data)) + { + foreach ($data as $key => $val) + { + $data[$key] = $this->xss_clean($val, $tool); + } + + return $data; + } + + // Do not clean empty strings + if (trim($data) === '') + return $data; + + if ($tool === TRUE) + { + // NOTE: This is necessary because switch is NOT type-sensative! + $tool = 'default'; + } + + switch ($tool) + { + case 'htmlpurifier': + /** + * @todo License should go here, http://htmlpurifier.org/ + */ + if ( ! class_exists('HTMLPurifier_Config', FALSE)) + { + // Load HTMLPurifier + require Kohana::find_file('vendor', 'htmlpurifier/HTMLPurifier.auto', TRUE); + require 'HTMLPurifier.func.php'; + } + + // Set configuration + $config = HTMLPurifier_Config::createDefault(); + $config->set('HTML', 'TidyLevel', 'none'); // Only XSS cleaning now + + // Run HTMLPurifier + $data = HTMLPurifier($data, $config); + break; + default: + // http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php + // +----------------------------------------------------------------------+ + // | Copyright (c) 2001-2006 Bitflux GmbH | + // +----------------------------------------------------------------------+ + // | Licensed under the Apache License, Version 2.0 (the "License"); | + // | you may not use this file except in compliance with the License. | + // | You may obtain a copy of the License at | + // | http://www.apache.org/licenses/LICENSE-2.0 | + // | Unless required by applicable law or agreed to in writing, software | + // | distributed under the License is distributed on an "AS IS" BASIS, | + // | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | + // | implied. See the License for the specific language governing | + // | permissions and limitations under the License. | + // +----------------------------------------------------------------------+ + // | Author: Christian Stocker | + // +----------------------------------------------------------------------+ + // + // Kohana Modifications: + // * Changed double quotes to single quotes, changed indenting and spacing + // * Removed magic_quotes stuff + // * Increased regex readability: + // * Used delimeters that aren't found in the pattern + // * Removed all unneeded escapes + // * Deleted U modifiers and swapped greediness where needed + // * Increased regex speed: + // * Made capturing parentheses non-capturing where possible + // * Removed parentheses where possible + // * Split up alternation alternatives + // * Made some quantifiers possessive + + // Fix &entity\n; + $data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data); + $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data); + $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data); + $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8'); + + // Remove any attribute starting with "on" or xmlns + $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data); + + // Remove javascript: and vbscript: protocols + $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data); + $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data); + $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data); + + // Only works in IE: + $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data); + $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data); + $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data); + + // Remove namespaced elements (we do not need them) + $data = preg_replace('#]*+>#i', '', $data); + + do + { + // Remove really unwanted tags + $old_data = $data; + $data = preg_replace('#]*+>#i', '', $data); + } + while ($old_data !== $data); + break; + } + + return $data; + } + + /** + * This is a helper method. It enforces W3C specifications for allowed + * key name strings, to prevent malicious exploitation. + * + * @param string string to clean + * @return string + */ + public function clean_input_keys($str) + { + $chars = PCRE_UNICODE_PROPERTIES ? '\pL' : 'a-zA-Z'; + + if ( ! preg_match('#^['.$chars.'0-9:_.-]++$#uD', $str)) + { + exit('Disallowed key characters in global data.'); + } + + return $str; + } + + /** + * This is a helper method. It escapes data and forces all newline + * characters to "\n". + * + * @param unknown_type string to clean + * @return string + */ + public function clean_input_data($str) + { + if (is_array($str)) + { + $new_array = array(); + foreach ($str as $key => $val) + { + // Recursion! + $new_array[$this->clean_input_keys($key)] = $this->clean_input_data($val); + } + return $new_array; + } + + if ($this->magic_quotes_gpc === TRUE) + { + // Remove annoying magic quotes + $str = stripslashes($str); + } + + if ($this->use_xss_clean === TRUE) + { + $str = $this->xss_clean($str); + } + + if (strpos($str, "\r") !== FALSE) + { + // Standardize newlines + $str = str_replace(array("\r\n", "\r"), "\n", $str); + } + + return $str; + } + +} // End Input Class diff --git a/lib/kohana/system/libraries/Model.php b/lib/kohana/system/libraries/Model.php new file mode 100644 index 0000000..0c9fd8d --- /dev/null +++ b/lib/kohana/system/libraries/Model.php @@ -0,0 +1,31 @@ +db)) + { + // Load the default database + $this->db = Database::instance($this->db); + } + } + +} // End Model \ No newline at end of file diff --git a/lib/kohana/system/libraries/ORM.php b/lib/kohana/system/libraries/ORM.php new file mode 100644 index 0000000..c104860 --- /dev/null +++ b/lib/kohana/system/libraries/ORM.php @@ -0,0 +1,1431 @@ +object_name = strtolower(substr(get_class($this), 0, -6)); + $this->object_plural = inflector::plural($this->object_name); + + if (!isset($this->sorting)) + { + // Default sorting + $this->sorting = array($this->primary_key => 'asc'); + } + + // Initialize database + $this->__initialize(); + + // Clear the object + $this->clear(); + + if (is_object($id)) + { + // Load an object + $this->load_values((array) $id); + } + elseif (!empty($id)) + { + // Find an object + $this->find($id); + } + } + + /** + * Prepares the model database connection, determines the table name, + * and loads column information. + * + * @return void + */ + public function __initialize() + { + if ( ! is_object($this->db)) + { + // Get database instance + $this->db = Database::instance($this->db); + } + + if (empty($this->table_name)) + { + // Table name is the same as the object name + $this->table_name = $this->object_name; + + if ($this->table_names_plural === TRUE) + { + // Make the table name plural + $this->table_name = inflector::plural($this->table_name); + } + } + + if (is_array($this->ignored_columns)) + { + // Make the ignored columns mirrored = mirrored + $this->ignored_columns = array_combine($this->ignored_columns, $this->ignored_columns); + } + + // Load column information + $this->reload_columns(); + } + + /** + * Allows serialization of only the object data and state, to prevent + * "stale" objects being unserialized, which also requires less memory. + * + * @return array + */ + public function __sleep() + { + // Store only information about the object + return array('object_name', 'object', 'changed', 'loaded', 'saved', 'sorting'); + } + + /** + * Prepares the database connection and reloads the object. + * + * @return void + */ + public function __wakeup() + { + // Initialize database + $this->__initialize(); + + if ($this->reload_on_wakeup === TRUE) + { + // Reload the object + $this->reload(); + } + } + + /** + * Handles pass-through to database methods. Calls to query methods + * (query, get, insert, update) are not allowed. Query builder methods + * are chainable. + * + * @param string method name + * @param array method arguments + * @return mixed + */ + public function __call($method, array $args) + { + if (method_exists($this->db, $method)) + { + if (in_array($method, array('query', 'get', 'insert', 'update', 'delete'))) + throw new Kohana_Exception('orm.query_methods_not_allowed'); + + // Method has been applied to the database + $this->db_applied[$method] = $method; + + // Number of arguments passed + $num_args = count($args); + + if ($method === 'select' AND $num_args > 3) + { + // Call select() manually to avoid call_user_func_array + $this->db->select($args); + } + else + { + // We use switch here to manually call the database methods. This is + // done for speed: call_user_func_array can take over 300% longer to + // make calls. Most database methods are 4 arguments or less, so this + // avoids almost any calls to call_user_func_array. + + switch ($num_args) + { + case 0: + if (in_array($method, array('open_paren', 'close_paren', 'enable_cache', 'disable_cache'))) + { + // Should return ORM, not Database + $this->db->$method(); + } + else + { + // Support for things like reset_select, reset_write, list_tables + return $this->db->$method(); + } + break; + case 1: + $this->db->$method($args[0]); + break; + case 2: + $this->db->$method($args[0], $args[1]); + break; + case 3: + $this->db->$method($args[0], $args[1], $args[2]); + break; + case 4: + $this->db->$method($args[0], $args[1], $args[2], $args[3]); + break; + default: + // Here comes the snail... + call_user_func_array(array($this->db, $method), $args); + break; + } + } + + return $this; + } + else + { + throw new Kohana_Exception('core.invalid_method', $method, get_class($this)); + } + } + + /** + * Handles retrieval of all model values, relationships, and metadata. + * + * @param string column name + * @return mixed + */ + public function __get($column) + { + if (array_key_exists($column, $this->object)) + { + return $this->object[$column]; + } + elseif (isset($this->related[$column])) + { + return $this->related[$column]; + } + elseif ($column === 'primary_key_value') + { + return $this->object[$this->primary_key]; + } + elseif ($model = $this->related_object($column)) + { + // This handles the has_one and belongs_to relationships + + if (in_array($model->object_name, $this->belongs_to) OR ! array_key_exists($this->foreign_key($column), $model->object)) + { + // Foreign key lies in this table (this model belongs_to target model) OR an invalid has_one relationship + $where = array($model->table_name.'.'.$model->primary_key => $this->object[$this->foreign_key($column)]); + } + else + { + // Foreign key lies in the target table (this model has_one target model) + $where = array($this->foreign_key($column, $model->table_name) => $this->primary_key_value); + } + + // one<>alias:one relationship + return $this->related[$column] = $model->find($where); + } + elseif (isset($this->has_many[$column])) + { + // Load the "middle" model + $through = ORM::factory(inflector::singular($this->has_many[$column])); + + // Load the "end" model + $model = ORM::factory(inflector::singular($column)); + + // Join ON target model's primary key set to 'through' model's foreign key + // User-defined foreign keys must be defined in the 'through' model + $join_table = $through->table_name; + $join_col1 = $through->foreign_key($model->object_name, $join_table); + $join_col2 = $model->table_name.'.'.$model->primary_key; + + // one<>alias:many relationship + return $this->related[$column] = $model + ->join($join_table, $join_col1, $join_col2) + ->where($through->foreign_key($this->object_name, $join_table), $this->object[$this->primary_key]) + ->find_all(); + } + elseif (in_array($column, $this->has_many)) + { + // one<>many relationship + $model = ORM::factory(inflector::singular($column)); + return $this->related[$column] = $model + ->where($this->foreign_key($column, $model->table_name), $this->object[$this->primary_key]) + ->find_all(); + } + elseif (in_array($column, $this->has_and_belongs_to_many)) + { + // Load the remote model, always singular + $model = ORM::factory(inflector::singular($column)); + + if ($this->has($model, TRUE)) + { + // many<>many relationship + return $this->related[$column] = $model + ->in($model->table_name.'.'.$model->primary_key, $this->changed_relations[$column]) + ->find_all(); + } + else + { + // empty many<>many relationship + return $this->related[$column] = $model + ->where($model->table_name.'.'.$model->primary_key, NULL) + ->find_all(); + } + } + elseif (isset($this->ignored_columns[$column])) + { + return NULL; + } + elseif (in_array($column, array + ( + 'object_name', 'object_plural', // Object + 'primary_key', 'primary_val', 'table_name', 'table_columns', // Table + 'loaded', 'saved', // Status + 'has_one', 'belongs_to', 'has_many', 'has_and_belongs_to_many', 'load_with' // Relationships + ))) + { + // Model meta information + return $this->$column; + } + else + { + throw new Kohana_Exception('core.invalid_property', $column, get_class($this)); + } + } + + /** + * Handles setting of all model values, and tracks changes between values. + * + * @param string column name + * @param mixed column value + * @return void + */ + public function __set($column, $value) + { + if (isset($this->ignored_columns[$column])) + { + return NULL; + } + elseif (isset($this->object[$column]) OR array_key_exists($column, $this->object)) + { + if (isset($this->table_columns[$column])) + { + // Data has changed + $this->changed[$column] = $column; + + // Object is no longer saved + $this->saved = FALSE; + } + + $this->object[$column] = $this->load_type($column, $value); + } + elseif (in_array($column, $this->has_and_belongs_to_many) AND is_array($value)) + { + // Load relations + $model = ORM::factory(inflector::singular($column)); + + if ( ! isset($this->object_relations[$column])) + { + // Load relations + $this->has($model); + } + + // Change the relationships + $this->changed_relations[$column] = $value; + + if (isset($this->related[$column])) + { + // Force a reload of the relationships + unset($this->related[$column]); + } + } + else + { + throw new Kohana_Exception('core.invalid_property', $column, get_class($this)); + } + } + + /** + * Checks if object data is set. + * + * @param string column name + * @return boolean + */ + public function __isset($column) + { + return (isset($this->object[$column]) OR isset($this->related[$column])); + } + + /** + * Unsets object data. + * + * @param string column name + * @return void + */ + public function __unset($column) + { + unset($this->object[$column], $this->changed[$column], $this->related[$column]); + } + + /** + * Displays the primary key of a model when it is converted to a string. + * + * @return string + */ + public function __toString() + { + return (string) $this->object[$this->primary_key]; + } + + /** + * Returns the values of this object as an array. + * + * @return array + */ + public function as_array() + { + $object = array(); + + foreach ($this->object as $key => $val) + { + // Reconstruct the array (calls __get) + $object[$key] = $this->$key; + } + + return $object; + } + + /** + * Binds another one-to-one object to this model. One-to-one objects + * can be nested using 'object1:object2' syntax + * + * @param string $target_path + * @return void + */ + public function with($target_path) + { + if (isset($this->with_applied[$target_path])) + { + // Don't join anything already joined + return $this; + } + + // Split object parts + $objects = explode(':', $target_path); + $target = $this; + foreach ($objects as $object) + { + // Go down the line of objects to find the given target + $parent = $target; + $target = $parent->related_object($object); + + if ( ! $target) + { + // Can't find related object + return $this; + } + } + + $target_name = $object; + + // Pop-off top object to get the parent object (user:photo:tag becomes user:photo - the parent table prefix) + array_pop($objects); + $parent_path = implode(':', $objects); + + if (empty($parent_path)) + { + // Use this table name itself for the parent object + $parent_path = $this->table_name; + } + else + { + if( ! isset($this->with_applied[$parent_path])) + { + // If the parent object hasn't been joined yet, do it first (otherwise LEFT JOINs fail) + $this->with($parent_path); + } + } + + // Add to with_applied to prevent duplicate joins + $this->with_applied[$target_path] = TRUE; + + // Use the keys of the empty object to determine the columns + $select = array_keys($target->object); + foreach ($select as $i => $column) + { + // Add the prefix so that load_result can determine the relationship + $select[$i] = $target_path.'.'.$column.' AS '.$target_path.':'.$column; + } + + + // Select all of the prefixed keys in the object + $this->db->select($select); + + if (in_array($target->object_name, $parent->belongs_to) OR ! isset($target->object[$parent->foreign_key($target_name)])) + { + // Parent belongs_to target, use target's primary key as join column + $join_col1 = $target->foreign_key(TRUE, $target_path); + $join_col2 = $parent->foreign_key($target_name, $parent_path); + } + else + { + // Parent has_one target, use parent's primary key as join column + $join_col2 = $parent->foreign_key(TRUE, $parent_path); + $join_col1 = $parent->foreign_key($target_name, $target_path); + } + + // This allows for models to use different table prefixes (sharing the same database) + $join_table = new Database_Expression($target->db->table_prefix().$target->table_name.' AS '.$this->db->table_prefix().$target_path); + + // Join the related object into the result + $this->db->join($join_table, $join_col1, $join_col2, 'LEFT'); + + return $this; + } + + /** + * Finds and loads a single database row into the object. + * + * @chainable + * @param mixed primary key or an array of clauses + * @return ORM + */ + public function find($id = NULL) + { + if ($id !== NULL) + { + if (is_array($id)) + { + // Search for all clauses + $this->db->where($id); + } + else + { + // Search for a specific column + $this->db->where($this->table_name.'.'.$this->unique_key($id), $id); + } + } + + return $this->load_result(); + } + + /** + * Finds multiple database rows and returns an iterator of the rows found. + * + * @chainable + * @param integer SQL limit + * @param integer SQL offset + * @return ORM_Iterator + */ + public function find_all($limit = NULL, $offset = NULL) + { + if ($limit !== NULL AND ! isset($this->db_applied['limit'])) + { + // Set limit + $this->limit($limit); + } + + if ($offset !== NULL AND ! isset($this->db_applied['offset'])) + { + // Set offset + $this->offset($offset); + } + + return $this->load_result(TRUE); + } + + /** + * Creates a key/value array from all of the objects available. Uses find_all + * to find the objects. + * + * @param string key column + * @param string value column + * @return array + */ + public function select_list($key = NULL, $val = NULL) + { + if ($key === NULL) + { + $key = $this->primary_key; + } + + if ($val === NULL) + { + $val = $this->primary_val; + } + + // Return a select list from the results + return $this->select($key, $val)->find_all()->select_list($key, $val); + } + + /** + * Validates the current object. This method should generally be called + * via the model, after the $_POST Validation object has been created. + * + * @param object Validation array + * @return boolean + */ + public function validate(Validation $array, $save = FALSE) + { + $safe_array = $array->safe_array(); + + if ( ! $array->submitted()) + { + foreach ($safe_array as $key => $value) + { + // Get the value from this object + $value = $this->$key; + + if (is_object($value) AND $value instanceof ORM_Iterator) + { + // Convert the value to an array of primary keys + $value = $value->primary_key_array(); + } + + // Pre-fill data + $array[$key] = $value; + } + } + + // Validate the array + if ($status = $array->validate()) + { + // Grab only set fields (excludes missing data, unlike safe_array) + $fields = $array->as_array(); + + foreach ($fields as $key => $value) + { + if (isset($safe_array[$key])) + { + // Set new data, ignoring any missing fields or fields without rules + $this->$key = $value; + } + } + + if ($save === TRUE OR is_string($save)) + { + // Save this object + $this->save(); + + if (is_string($save)) + { + // Redirect to the saved page + url::redirect($save); + } + } + } + + // Return validation status + return $status; + } + + /** + * Saves the current object. + * + * @chainable + * @return ORM + */ + public function save() + { + if ( ! empty($this->changed)) + { + $data = array(); + foreach ($this->changed as $column) + { + // Compile changed data + $data[$column] = $this->object[$column]; + } + + if ($this->loaded === TRUE) + { + $query = $this->db + ->where($this->primary_key, $this->object[$this->primary_key]) + ->update($this->table_name, $data); + + // Object has been saved + $this->saved = TRUE; + } + else + { + $query = $this->db + ->insert($this->table_name, $data); + + if ($query->count() > 0) + { + if (empty($this->object[$this->primary_key])) + { + // Load the insert id as the primary key + $this->object[$this->primary_key] = $query->insert_id(); + } + + // Object is now loaded and saved + $this->loaded = $this->saved = TRUE; + } + } + + if ($this->saved === TRUE) + { + // All changes have been saved + $this->changed = array(); + } + } + + if ($this->saved === TRUE AND ! empty($this->changed_relations)) + { + foreach ($this->changed_relations as $column => $values) + { + // All values that were added + $added = array_diff($values, $this->object_relations[$column]); + + // All values that were saved + $removed = array_diff($this->object_relations[$column], $values); + + if (empty($added) AND empty($removed)) + { + // No need to bother + continue; + } + + // Clear related columns + unset($this->related[$column]); + + // Load the model + $model = ORM::factory(inflector::singular($column)); + + if (($join_table = array_search($column, $this->has_and_belongs_to_many)) === FALSE) + continue; + + if (is_int($join_table)) + { + // No "through" table, load the default JOIN table + $join_table = $model->join_table($this->table_name); + } + + // Foreign keys for the join table + $object_fk = $this->foreign_key(NULL); + $related_fk = $model->foreign_key(NULL); + + if ( ! empty($added)) + { + foreach ($added as $id) + { + // Insert the new relationship + $this->db->insert($join_table, array + ( + $object_fk => $this->object[$this->primary_key], + $related_fk => $id, + )); + } + } + + if ( ! empty($removed)) + { + $this->db + ->where($object_fk, $this->object[$this->primary_key]) + ->in($related_fk, $removed) + ->delete($join_table); + } + + // Clear all relations for this column + unset($this->object_relations[$column], $this->changed_relations[$column]); + } + } + + return $this; + } + + /** + * Deletes the current object from the database. This does NOT destroy + * relationships that have been created with other objects. + * + * @chainable + * @return ORM + */ + public function delete($id = NULL) + { + if ($id === NULL AND $this->loaded) + { + // Use the the primary key value + $id = $this->object[$this->primary_key]; + } + + // Delete this object + $this->db->where($this->primary_key, $id)->delete($this->table_name); + + return $this->clear(); + } + + /** + * Delete all objects in the associated table. This does NOT destroy + * relationships that have been created with other objects. + * + * @chainable + * @param array ids to delete + * @return ORM + */ + public function delete_all($ids = NULL) + { + if (is_array($ids)) + { + // Delete only given ids + $this->db->in($this->primary_key, $ids); + } + elseif (is_null($ids)) + { + // Delete all records + $this->db->where('1=1'); + } + else + { + // Do nothing - safeguard + return $this; + } + + // Delete all objects + $this->db->delete($this->table_name); + + return $this->clear(); + } + + /** + * Unloads the current object and clears the status. + * + * @chainable + * @return ORM + */ + public function clear() + { + // Create an array with all the columns set to NULL + $columns = array_keys($this->table_columns); + $values = array_combine($columns, array_fill(0, count($columns), NULL)); + + // Replace the current object with an empty one + $this->load_values($values); + + return $this; + } + + /** + * Reloads the current object from the database. + * + * @chainable + * @return ORM + */ + public function reload() + { + return $this->find($this->object[$this->primary_key]); + } + + /** + * Reload column definitions. + * + * @chainable + * @param boolean force reloading + * @return ORM + */ + public function reload_columns($force = FALSE) + { + if ($force === TRUE OR empty($this->table_columns)) + { + if (isset(ORM::$column_cache[$this->object_name])) + { + // Use cached column information + $this->table_columns = ORM::$column_cache[$this->object_name]; + } + else + { + // Load table columns + ORM::$column_cache[$this->object_name] = $this->table_columns = $this->list_fields(); + } + } + + return $this; + } + + /** + * Tests if this object has a relationship to a different model. + * + * @param object related ORM model + * @param boolean check for any relations to given model + * @return boolean + */ + public function has(ORM $model, $any = FALSE) + { + // Determine plural or singular relation name + $related = ($model->table_names_plural === TRUE) ? $model->object_plural : $model->object_name; + + if (($join_table = array_search($related, $this->has_and_belongs_to_many)) === FALSE) + return FALSE; + + if (is_int($join_table)) + { + // No "through" table, load the default JOIN table + $join_table = $model->join_table($this->table_name); + } + + if ( ! isset($this->object_relations[$related])) + { + // Load the object relationships + $this->changed_relations[$related] = $this->object_relations[$related] = $this->load_relations($join_table, $model); + } + + if ( ! $model->empty_primary_key()) + { + // Check if a specific object exists + return in_array($model->primary_key_value, $this->changed_relations[$related]); + } + elseif ($any) + { + // Check if any relations to given model exist + return ! empty($this->changed_relations[$related]); + } + else + { + return FALSE; + } + } + + /** + * Adds a new relationship to between this model and another. + * + * @param object related ORM model + * @return boolean + */ + public function add(ORM $model) + { + if ($this->has($model)) + return TRUE; + + // Get the faked column name + $column = $model->object_plural; + + // Add the new relation to the update + $this->changed_relations[$column][] = $model->primary_key_value; + + if (isset($this->related[$column])) + { + // Force a reload of the relationships + unset($this->related[$column]); + } + + return TRUE; + } + + /** + * Adds a new relationship to between this model and another. + * + * @param object related ORM model + * @return boolean + */ + public function remove(ORM $model) + { + if ( ! $this->has($model)) + return FALSE; + + // Get the faked column name + $column = $model->object_plural; + + if (($key = array_search($model->primary_key_value, $this->changed_relations[$column])) === FALSE) + return FALSE; + + // Remove the relationship + unset($this->changed_relations[$column][$key]); + + if (isset($this->related[$column])) + { + // Force a reload of the relationships + unset($this->related[$column]); + } + + return TRUE; + } + + /** + * Count the number of records in the table. + * + * @return integer + */ + public function count_all() + { + // Return the total number of records in a table + return $this->db->count_records($this->table_name); + } + + /** + * Proxy method to Database list_fields. + * + * @param string table name or NULL to use this table + * @return array + */ + public function list_fields($table = NULL) + { + if ($table === NULL) + { + $table = $this->table_name; + } + + // Proxy to database + return $this->db->list_fields($table); + } + + /** + * Proxy method to Database field_data. + * + * @param string table name + * @return array + */ + public function field_data($table) + { + // Proxy to database + return $this->db->field_data($table); + } + + /** + * Proxy method to Database field_data. + * + * @chainable + * @param string SQL query to clear + * @return ORM + */ + public function clear_cache($sql = NULL) + { + // Proxy to database + $this->db->clear_cache($sql); + + ORM::$column_cache = array(); + + return $this; + } + + /** + * Returns the unique key for a specific value. This method is expected + * to be overloaded in models if the model has other unique columns. + * + * @param mixed unique value + * @return string + */ + public function unique_key($id) + { + return $this->primary_key; + } + + /** + * Determines the name of a foreign key for a specific table. + * + * @param string related table name + * @param string prefix table name (used for JOINs) + * @return string + */ + public function foreign_key($table = NULL, $prefix_table = NULL) + { + if ($table === TRUE) + { + if (is_string($prefix_table)) + { + // Use prefix table name and this table's PK + return $prefix_table.'.'.$this->primary_key; + } + else + { + // Return the name of this table's PK + return $this->table_name.'.'.$this->primary_key; + } + } + + if (is_string($prefix_table)) + { + // Add a period for prefix_table.column support + $prefix_table .= '.'; + } + + if (isset($this->foreign_key[$table])) + { + // Use the defined foreign key name, no magic here! + $foreign_key = $this->foreign_key[$table]; + } + else + { + if ( ! is_string($table) OR ! array_key_exists($table.'_'.$this->primary_key, $this->object)) + { + // Use this table + $table = $this->table_name; + + if (strpos($table, '.') !== FALSE) + { + // Hack around support for PostgreSQL schemas + list ($schema, $table) = explode('.', $table, 2); + } + + if ($this->table_names_plural === TRUE) + { + // Make the key name singular + $table = inflector::singular($table); + } + } + + $foreign_key = $table.'_'.$this->primary_key; + } + + return $prefix_table.$foreign_key; + } + + /** + * This uses alphabetical comparison to choose the name of the table. + * + * Example: The joining table of users and roles would be roles_users, + * because "r" comes before "u". Joining products and categories would + * result in categories_products, because "c" comes before "p". + * + * Example: zoo > zebra > robber > ocean > angel > aardvark + * + * @param string table name + * @return string + */ + public function join_table($table) + { + if ($this->table_name > $table) + { + $table = $table.'_'.$this->table_name; + } + else + { + $table = $this->table_name.'_'.$table; + } + + return $table; + } + + /** + * Returns an ORM model for the given object name; + * + * @param string object name + * @return ORM + */ + protected function related_object($object) + { + if (isset($this->has_one[$object])) + { + $object = ORM::factory($this->has_one[$object]); + } + elseif (isset($this->belongs_to[$object])) + { + $object = ORM::factory($this->belongs_to[$object]); + } + elseif (in_array($object, $this->has_one) OR in_array($object, $this->belongs_to)) + { + $object = ORM::factory($object); + } + else + { + return FALSE; + } + + return $object; + } + + /** + * Loads an array of values into into the current object. + * + * @chainable + * @param array values to load + * @return ORM + */ + public function load_values(array $values) + { + if (array_key_exists($this->primary_key, $values)) + { + // Replace the object and reset the object status + $this->object = $this->changed = $this->related = array(); + + // Set the loaded and saved object status based on the primary key + $this->loaded = $this->saved = ($values[$this->primary_key] !== NULL); + } + + // Related objects + $related = array(); + + foreach ($values as $column => $value) + { + if (strpos($column, ':') === FALSE) + { + if (isset($this->table_columns[$column])) + { + // The type of the value can be determined, convert the value + $value = $this->load_type($column, $value); + } + + $this->object[$column] = $value; + } + else + { + list ($prefix, $column) = explode(':', $column, 2); + + $related[$prefix][$column] = $value; + } + } + + if ( ! empty($related)) + { + foreach ($related as $object => $values) + { + // Load the related objects with the values in the result + $this->related[$object] = $this->related_object($object)->load_values($values); + } + } + + return $this; + } + + /** + * Loads a value according to the types defined by the column metadata. + * + * @param string column name + * @param mixed value to load + * @return mixed + */ + protected function load_type($column, $value) + { + $type = gettype($value); + if ($type == 'object' OR $type == 'array' OR ! isset($this->table_columns[$column])) + return $value; + + // Load column data + $column = $this->table_columns[$column]; + + if ($value === NULL AND ! empty($column['null'])) + return $value; + + if ( ! empty($column['binary']) AND ! empty($column['exact']) AND (int) $column['length'] === 1) + { + // Use boolean for BINARY(1) fields + $column['type'] = 'boolean'; + } + + switch ($column['type']) + { + case 'int': + if ($value === '' AND ! empty($column['null'])) + { + // Forms will only submit strings, so empty integer values must be null + $value = NULL; + } + elseif ((float) $value > PHP_INT_MAX) + { + // This number cannot be represented by a PHP integer, so we convert it to a string + $value = (string) $value; + } + else + { + $value = (int) $value; + } + break; + case 'float': + $value = (float) $value; + break; + case 'boolean': + $value = (bool) $value; + break; + case 'string': + $value = (string) $value; + break; + } + + return $value; + } + + /** + * Loads a database result, either as a new object for this model, or as + * an iterator for multiple rows. + * + * @chainable + * @param boolean return an iterator or load a single row + * @return ORM for single rows + * @return ORM_Iterator for multiple rows + */ + protected function load_result($array = FALSE) + { + if ($array === FALSE) + { + // Only fetch 1 record + $this->db->limit(1); + } + + if ( ! isset($this->db_applied['select'])) + { + // Select all columns by default + $this->db->select($this->table_name.'.*'); + } + + if ( ! empty($this->load_with)) + { + foreach ($this->load_with as $alias => $object) + { + // Join each object into the results + if (is_string($alias)) + { + // Use alias + $this->with($alias); + } + else + { + // Use object + $this->with($object); + } + } + } + + if ( ! isset($this->db_applied['orderby']) AND ! empty($this->sorting)) + { + $sorting = array(); + foreach ($this->sorting as $column => $direction) + { + if (strpos($column, '.') === FALSE) + { + // Keeps sorting working properly when using JOINs on + // tables with columns of the same name + $column = $this->table_name.'.'.$column; + } + + $sorting[$column] = $direction; + } + + // Apply the user-defined sorting + $this->db->orderby($sorting); + } + + // Load the result + $result = $this->db->get($this->table_name); + + if ($array === TRUE) + { + // Return an iterated result + return new ORM_Iterator($this, $result); + } + + if ($result->count() === 1) + { + // Load object values + $this->load_values($result->result(FALSE)->current()); + } + else + { + // Clear the object, nothing was found + $this->clear(); + } + + return $this; + } + + /** + * Return an array of all the primary keys of the related table. + * + * @param string table name + * @param object ORM model to find relations of + * @return array + */ + protected function load_relations($table, ORM $model) + { + // Save the current query chain (otherwise the next call will clash) + $this->db->push(); + + $query = $this->db + ->select($model->foreign_key(NULL).' AS id') + ->from($table) + ->where($this->foreign_key(NULL, $table), $this->object[$this->primary_key]) + ->get() + ->result(TRUE); + + $this->db->pop(); + + $relations = array(); + foreach ($query as $row) + { + $relations[] = $row->id; + } + + return $relations; + } + + /** + * Returns whether or not primary key is empty + * + * @return bool + */ + protected function empty_primary_key() + { + return (empty($this->object[$this->primary_key]) AND $this->object[$this->primary_key] !== '0'); + } + +} // End ORM diff --git a/lib/kohana/system/libraries/ORM_Iterator.php b/lib/kohana/system/libraries/ORM_Iterator.php new file mode 100644 index 0000000..41aa806 --- /dev/null +++ b/lib/kohana/system/libraries/ORM_Iterator.php @@ -0,0 +1,228 @@ +class_name = get_class($model); + $this->primary_key = $model->primary_key; + $this->primary_val = $model->primary_val; + + // Database result + $this->result = $result->result(TRUE); + } + + /** + * Returns an array of the results as ORM objects. + * + * @return array + */ + public function as_array() + { + $array = array(); + + if ($results = $this->result->result_array()) + { + // Import class name + $class = $this->class_name; + + foreach ($results as $obj) + { + $array[] = new $class($obj); + } + } + + return $array; + } + + /** + * Return an array of all of the primary keys for this object. + * + * @return array + */ + public function primary_key_array() + { + $ids = array(); + foreach ($this->result as $row) + { + $ids[] = $row->{$this->primary_key}; + } + return $ids; + } + + /** + * Create a key/value array from the results. + * + * @param string key column + * @param string value column + * @return array + */ + public function select_list($key = NULL, $val = NULL) + { + if ($key === NULL) + { + // Use the default key + $key = $this->primary_key; + } + + if ($val === NULL) + { + // Use the default value + $val = $this->primary_val; + } + + $array = array(); + foreach ($this->result->result_array() as $row) + { + $array[$row->$key] = $row->$val; + } + return $array; + } + + /** + * Return a range of offsets. + * + * @param integer start + * @param integer end + * @return array + */ + public function range($start, $end) + { + // Array of objects + $array = array(); + + if ($this->result->offsetExists($start)) + { + // Import the class name + $class = $this->class_name; + + // Set the end offset + $end = $this->result->offsetExists($end) ? $end : $this->count(); + + for ($i = $start; $i < $end; $i++) + { + // Insert each object in the range + $array[] = new $class($this->result->offsetGet($i)); + } + } + + return $array; + } + + /** + * Countable: count + */ + public function count() + { + return $this->result->count(); + } + + /** + * Iterator: current + */ + public function current() + { + if ($row = $this->result->current()) + { + // Import class name + $class = $this->class_name; + + $row = new $class($row); + } + + return $row; + } + + /** + * Iterator: key + */ + public function key() + { + return $this->result->key(); + } + + /** + * Iterator: next + */ + public function next() + { + return $this->result->next(); + } + + /** + * Iterator: rewind + */ + public function rewind() + { + $this->result->rewind(); + } + + /** + * Iterator: valid + */ + public function valid() + { + return $this->result->valid(); + } + + /** + * ArrayAccess: offsetExists + */ + public function offsetExists($offset) + { + return $this->result->offsetExists($offset); + } + + /** + * ArrayAccess: offsetGet + */ + public function offsetGet($offset) + { + if ($this->result->offsetExists($offset)) + { + // Import class name + $class = $this->class_name; + + return new $class($this->result->offsetGet($offset)); + } + } + + /** + * ArrayAccess: offsetSet + * + * @throws Kohana_Database_Exception + */ + public function offsetSet($offset, $value) + { + throw new Kohana_Database_Exception('database.result_read_only'); + } + + /** + * ArrayAccess: offsetUnset + * + * @throws Kohana_Database_Exception + */ + public function offsetUnset($offset) + { + throw new Kohana_Database_Exception('database.result_read_only'); + } + +} // End ORM Iterator \ No newline at end of file diff --git a/lib/kohana/system/libraries/ORM_Tree.php b/lib/kohana/system/libraries/ORM_Tree.php new file mode 100644 index 0000000..cdb09fd --- /dev/null +++ b/lib/kohana/system/libraries/ORM_Tree.php @@ -0,0 +1,76 @@ +related[$column])) + { + // Load child model + $model = ORM::factory(inflector::singular($this->ORM_Tree_children)); + + if (array_key_exists($this->ORM_Tree_parent_key, $this->object)) + { + // Find children of this parent + $model->where($model->primary_key, $this->object[$this->ORM_Tree_parent_key])->find(); + } + + $this->related[$column] = $model; + } + + return $this->related[$column]; + } + elseif ($column === 'children') + { + if (empty($this->related[$column])) + { + $model = ORM::factory(inflector::singular($this->ORM_Tree_children)); + + if ($this->ORM_Tree_children === $this->table_name) + { + // Load children within this table + $this->related[$column] = $model + ->where($this->ORM_Tree_parent_key, $this->object[$this->primary_key]) + ->find_all(); + } + else + { + // Find first selection of children + $this->related[$column] = $model + ->where($this->foreign_key(), $this->object[$this->primary_key]) + ->where($this->ORM_Tree_parent_key, NULL) + ->find_all(); + } + } + + return $this->related[$column]; + } + + return parent::__get($column); + } + +} // End ORM Tree \ No newline at end of file diff --git a/lib/kohana/system/libraries/ORM_Versioned.php b/lib/kohana/system/libraries/ORM_Versioned.php new file mode 100644 index 0000000..7c3ee5d --- /dev/null +++ b/lib/kohana/system/libraries/ORM_Versioned.php @@ -0,0 +1,143 @@ +last_version = 1 + ($this->last_version === NULL ? $this->object['version'] : $this->last_version); + $this->__set('version', $this->last_version); + + parent::save(); + + if ($this->saved) + { + $data = array(); + foreach ($this->object as $key => $value) + { + if ($key === 'id') + continue; + + $data[$key] = $value; + } + $data[$this->foreign_key()] = $this->id; + + $this->db->insert($this->table_name.'_versions', $data); + } + + return $this; + } + + /** + * Loads previous version from current object + * + * @chainable + * @return ORM + */ + public function previous() + { + if ( ! $this->loaded) + return $this; + + $this->last_version = ($this->last_version === NULL) ? $this->object['version'] : $this->last_version; + $version = $this->last_version - 1; + + $query = $this->db + ->where($this->foreign_key(), $this->object[$this->primary_key]) + ->where('version', $version) + ->limit(1) + ->get($this->table_name.'_versions'); + + if ($query->count()) + { + $this->load_values($query->result(FALSE)->current()); + } + + return $this; + } + + /** + * Restores the object with data from stored version + * + * @param integer version number you want to restore + * @return ORM + */ + public function restore($version) + { + if ( ! $this->loaded) + return $this; + + $query = $this->db + ->where($this->foreign_key(), $this->object[$this->primary_key]) + ->where('version', $version) + ->limit(1) + ->get($this->table_name.'_versions'); + + if ($query->count()) + { + $row = $query->result(FALSE)->current(); + + foreach ($row as $key => $value) + { + if ($key === $this->primary_key OR $key === $this->foreign_key()) + { + // Do not overwrite the primary key + continue; + } + + if ($key === 'version') + { + // Always use the current version + $value = $this->version; + } + + $this->__set($key, $value); + } + + $this->save(); + } + + return $this; + } + + /** + * Overloads ORM::delete() to delete all versioned entries of current object + * and the object itself + * + * @param integer id of the object you want to delete + * @return ORM + */ + public function delete($id = NULL) + { + if ($id === NULL) + { + // Use the current object id + $id = $this->object[$this->primary_key]; + } + + if ($status = parent::delete($id)) + { + $this->db->where($this->foreign_key(), $id)->delete($this->table_name.'_versions'); + } + + return $status; + } + +} \ No newline at end of file diff --git a/lib/kohana/system/libraries/Pagination.php b/lib/kohana/system/libraries/Pagination.php new file mode 100644 index 0000000..a8f7bb1 --- /dev/null +++ b/lib/kohana/system/libraries/Pagination.php @@ -0,0 +1,236 @@ +initialize($config); + + Kohana::log('debug', 'Pagination Library initialized'); + } + + /** + * Sets config values. + * + * @throws Kohana_Exception + * @param array configuration settings + * @return void + */ + public function initialize($config = array()) + { + // Load config group + if (isset($config['group'])) + { + // Load and validate config group + if ( ! is_array($group_config = Kohana::config('pagination.'.$config['group']))) + throw new Kohana_Exception('pagination.undefined_group', $config['group']); + + // All pagination config groups inherit default config group + if ($config['group'] !== 'default') + { + // Load and validate default config group + if ( ! is_array($default_config = Kohana::config('pagination.default'))) + throw new Kohana_Exception('pagination.undefined_group', 'default'); + + // Merge config group with default config group + $group_config += $default_config; + } + + // Merge custom config items with config group + $config += $group_config; + } + + // Assign config values to the object + foreach ($config as $key => $value) + { + if (property_exists($this, $key)) + { + $this->$key = $value; + } + } + + // Clean view directory + $this->directory = trim($this->directory, '/').'/'; + + // Build generic URL with page in query string + if ($this->query_string !== '') + { + // Extract current page + $this->current_page = isset($_GET[$this->query_string]) ? (int) $_GET[$this->query_string] : 1; + + // Insert {page} placeholder + $_GET[$this->query_string] = '{page}'; + + // Create full URL + $base_url = ($this->base_url === '') ? Router::$current_uri : $this->base_url; + $this->url = url::site($base_url).'?'.str_replace('%7Bpage%7D', '{page}', http_build_query($_GET)); + + // Reset page number + $_GET[$this->query_string] = $this->current_page; + } + + // Build generic URL with page as URI segment + else + { + // Use current URI if no base_url set + $this->url = ($this->base_url === '') ? Router::$segments : explode('/', trim($this->base_url, '/')); + + // Convert uri 'label' to corresponding integer if needed + if (is_string($this->uri_segment)) + { + if (($key = array_search($this->uri_segment, $this->url)) === FALSE) + { + // If uri 'label' is not found, auto add it to base_url + $this->url[] = $this->uri_segment; + $this->uri_segment = count($this->url) + 1; + } + else + { + $this->uri_segment = $key + 2; + } + } + + // Insert {page} placeholder + $this->url[$this->uri_segment - 1] = '{page}'; + + // Create full URL + $this->url = url::site(implode('/', $this->url)).Router::$query_string; + + // Extract current page + $this->current_page = URI::instance()->segment($this->uri_segment); + } + + // Core pagination values + $this->total_items = (int) max(0, $this->total_items); + $this->items_per_page = (int) max(1, $this->items_per_page); + $this->total_pages = (int) ceil($this->total_items / $this->items_per_page); + $this->current_page = (int) min(max(1, $this->current_page), max(1, $this->total_pages)); + $this->current_first_item = (int) min((($this->current_page - 1) * $this->items_per_page) + 1, $this->total_items); + $this->current_last_item = (int) min($this->current_first_item + $this->items_per_page - 1, $this->total_items); + + // If there is no first/last/previous/next page, relative to the + // current page, value is set to FALSE. Valid page number otherwise. + $this->first_page = ($this->current_page === 1) ? FALSE : 1; + $this->last_page = ($this->current_page >= $this->total_pages) ? FALSE : $this->total_pages; + $this->previous_page = ($this->current_page > 1) ? $this->current_page - 1 : FALSE; + $this->next_page = ($this->current_page < $this->total_pages) ? $this->current_page + 1 : FALSE; + + // SQL values + $this->sql_offset = (int) ($this->current_page - 1) * $this->items_per_page; + $this->sql_limit = sprintf(' LIMIT %d OFFSET %d ', $this->items_per_page, $this->sql_offset); + } + + /** + * Generates the HTML for the chosen pagination style. + * + * @param string pagination style + * @return string pagination html + */ + public function render($style = NULL) + { + // Hide single page pagination + if ($this->auto_hide === TRUE AND $this->total_pages <= 1) + return ''; + + if ($style === NULL) + { + // Use default style + $style = $this->style; + } + + // Return rendered pagination view + return View::factory($this->directory.$style, get_object_vars($this))->render(); + } + + /** + * Magically converts Pagination object to string. + * + * @return string pagination html + */ + public function __toString() + { + return $this->render(); + } + + /** + * Magically gets a pagination variable. + * + * @param string variable key + * @return mixed variable value if the key is found + * @return void if the key is not found + */ + public function __get($key) + { + if (isset($this->$key)) + return $this->$key; + } + + /** + * Adds a secondary interface for accessing properties, e.g. $pagination->total_pages(). + * Note that $pagination->total_pages is the recommended way to access properties. + * + * @param string function name + * @return string + */ + public function __call($func, $args = NULL) + { + return $this->__get($func); + } + +} // End Pagination Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/Profiler.php b/lib/kohana/system/libraries/Profiler.php new file mode 100644 index 0000000..9da053f --- /dev/null +++ b/lib/kohana/system/libraries/Profiler.php @@ -0,0 +1,271 @@ +show OR (is_array($this->show) AND ! in_array($args[0], $this->show))) + return FALSE; + + // Class name + $class = 'Profiler_'.ucfirst($method); + + $class = new $class(); + + $this->profiles[$args[0]] = $class; + + return $class; + } + + /** + * Disables the profiler for this page only. + * Best used when profiler is autoloaded. + * + * @return void + */ + public function disable() + { + // Removes itself from the event queue + Event::clear('system.display', array($this, 'render')); + } + + /** + * Render the profiler. Output is added to the bottom of the page by default. + * + * @param boolean return the output if TRUE + * @return void|string + */ + public function render($return = FALSE) + { + $start = microtime(TRUE); + + $get = isset($_GET['profiler']) ? explode(',', $_GET['profiler']) : array(); + $this->show = empty($get) ? Kohana::config('profiler.show') : $get; + + Event::run('profiler.run', $this); + + $styles = ''; + foreach ($this->profiles as $profile) + { + $styles .= $profile->styles(); + } + + // Don't display if there's no profiles + if (empty($this->profiles)) + return; + + // Load the profiler view + $data = array + ( + 'profiles' => $this->profiles, + 'styles' => $styles, + 'execution_time' => microtime(TRUE) - $start + ); + $view = new View('kohana_profiler', $data); + + // Return rendered view if $return is TRUE + if ($return === TRUE) + return $view->render(); + + // Add profiler data to the output + if (stripos(Kohana::$output, '') !== FALSE) + { + // Closing body tag was found, insert the profiler data before it + Kohana::$output = str_ireplace('', $view->render().'', Kohana::$output); + } + else + { + // Append the profiler data to the output + Kohana::$output .= $view->render(); + } + } + + /** + * Benchmark times and memory usage from the Benchmark library. + * + * @return void + */ + public function benchmarks() + { + if ( ! $table = $this->table('benchmarks')) + return; + + $table->add_column(); + $table->add_column('kp-column kp-data'); + $table->add_column('kp-column kp-data'); + $table->add_column('kp-column kp-data'); + $table->add_row(array('Benchmarks', 'Time', 'Count', 'Memory'), 'kp-title', 'background-color: #FFE0E0'); + + $benchmarks = Benchmark::get(TRUE); + + // Moves the first benchmark (total execution time) to the end of the array + $benchmarks = array_slice($benchmarks, 1) + array_slice($benchmarks, 0, 1); + + text::alternate(); + foreach ($benchmarks as $name => $benchmark) + { + // Clean unique id from system benchmark names + $name = ucwords(str_replace(array('_', '-'), ' ', str_replace(SYSTEM_BENCHMARK.'_', '', $name))); + + $data = array($name, number_format($benchmark['time'], 3), $benchmark['count'], number_format($benchmark['memory'] / 1024 / 1024, 2).'MB'); + $class = text::alternate('', 'kp-altrow'); + + if ($name == 'Total Execution') + $class = 'kp-totalrow'; + + $table->add_row($data, $class); + } + } + + /** + * Database query benchmarks. + * + * @return void + */ + public function database() + { + if ( ! $table = $this->table('database')) + return; + + $table->add_column(); + $table->add_column('kp-column kp-data'); + $table->add_column('kp-column kp-data'); + $table->add_row(array('Queries', 'Time', 'Rows'), 'kp-title', 'background-color: #E0FFE0'); + + $queries = Database::$benchmarks; + + text::alternate(); + $total_time = $total_rows = 0; + foreach ($queries as $query) + { + $data = array($query['query'], number_format($query['time'], 3), $query['rows']); + $class = text::alternate('', 'kp-altrow'); + $table->add_row($data, $class); + $total_time += $query['time']; + $total_rows += $query['rows']; + } + + $data = array('Total: ' . count($queries), number_format($total_time, 3), $total_rows); + $table->add_row($data, 'kp-totalrow'); + } + + /** + * Session data. + * + * @return void + */ + public function session() + { + if (empty($_SESSION)) return; + + if ( ! $table = $this->table('session')) + return; + + $table->add_column('kp-name'); + $table->add_column(); + $table->add_row(array('Session', 'Value'), 'kp-title', 'background-color: #CCE8FB'); + + text::alternate(); + foreach($_SESSION as $name => $value) + { + if (is_object($value)) + { + $value = get_class($value).' [object]'; + } + + $data = array($name, $value); + $class = text::alternate('', 'kp-altrow'); + $table->add_row($data, $class); + } + } + + /** + * POST data. + * + * @return void + */ + public function post() + { + if (empty($_POST)) return; + + if ( ! $table = $this->table('post')) + return; + + $table->add_column('kp-name'); + $table->add_column(); + $table->add_row(array('POST', 'Value'), 'kp-title', 'background-color: #E0E0FF'); + + text::alternate(); + foreach($_POST as $name => $value) + { + $data = array($name, $value); + $class = text::alternate('', 'kp-altrow'); + $table->add_row($data, $class); + } + } + + /** + * Cookie data. + * + * @return void + */ + public function cookies() + { + if (empty($_COOKIE)) return; + + if ( ! $table = $this->table('cookies')) + return; + + $table->add_column('kp-name'); + $table->add_column(); + $table->add_row(array('Cookies', 'Value'), 'kp-title', 'background-color: #FFF4D7'); + + text::alternate(); + foreach($_COOKIE as $name => $value) + { + $data = array($name, $value); + $class = text::alternate('', 'kp-altrow'); + $table->add_row($data, $class); + } + } +} \ No newline at end of file diff --git a/lib/kohana/system/libraries/Profiler_Table.php b/lib/kohana/system/libraries/Profiler_Table.php new file mode 100644 index 0000000..a0058a5 --- /dev/null +++ b/lib/kohana/system/libraries/Profiler_Table.php @@ -0,0 +1,69 @@ +columns[] = array('class' => $class, 'style' => $style); + } + + /** + * Add row to table. + * + * @param array data to go in table cells + * @param string CSS class + * @param string CSS style + */ + public function add_row($data, $class = '', $style = '') + { + $this->rows[] = array('data' => $data, 'class' => $class, 'style' => $style); + } + + /** + * Render table. + * + * @return string + */ + public function render() + { + $data['rows'] = $this->rows; + $data['columns'] = $this->columns; + return View::factory('kohana_profiler_table', $data)->render(); + } +} \ No newline at end of file diff --git a/lib/kohana/system/libraries/Router.php b/lib/kohana/system/libraries/Router.php new file mode 100644 index 0000000..ef0e1e4 --- /dev/null +++ b/lib/kohana/system/libraries/Router.php @@ -0,0 +1,304 @@ + 1) + { + // Custom routing + Router::$rsegments = Router::routed_uri(Router::$current_uri); + } + + // The routed URI is now complete + Router::$routed_uri = Router::$rsegments; + + // Routed segments will never be empty + Router::$rsegments = explode('/', Router::$rsegments); + + // Prepare to find the controller + $controller_path = ''; + $method_segment = NULL; + + // Paths to search + $paths = Kohana::include_paths(); + + foreach (Router::$rsegments as $key => $segment) + { + // Add the segment to the search path + $controller_path .= $segment; + + $found = FALSE; + foreach ($paths as $dir) + { + // Search within controllers only + $dir .= 'controllers/'; + + if (is_dir($dir.$controller_path) OR is_file($dir.$controller_path.EXT)) + { + // Valid path + $found = TRUE; + + // The controller must be a file that exists with the search path + if ($c = str_replace('\\', '/', realpath($dir.$controller_path.EXT)) + AND is_file($c) AND strpos($c, $dir) === 0) + { + // Set controller name + Router::$controller = $segment; + + // Change controller path + Router::$controller_path = $c; + + // Set the method segment + $method_segment = $key + 1; + + // Stop searching + break; + } + } + } + + if ($found === FALSE) + { + // Maximum depth has been reached, stop searching + break; + } + + // Add another slash + $controller_path .= '/'; + } + + if ($method_segment !== NULL AND isset(Router::$rsegments[$method_segment])) + { + // Set method + Router::$method = Router::$rsegments[$method_segment]; + + if (isset(Router::$rsegments[$method_segment + 1])) + { + // Set arguments + Router::$arguments = array_slice(Router::$rsegments, $method_segment + 1); + } + } + + // Last chance to set routing before a 404 is triggered + Event::run('system.post_routing'); + + if (Router::$controller === NULL) + { + // No controller was found, so no page can be rendered + Event::run('system.404'); + } + } + + /** + * Attempts to determine the current URI using CLI, GET, PATH_INFO, ORIG_PATH_INFO, or PHP_SELF. + * + * @return void + */ + public static function find_uri() + { + if (PHP_SAPI === 'cli') + { + // Command line requires a bit of hacking + if (isset($_SERVER['argv'][1])) + { + Router::$current_uri = $_SERVER['argv'][1]; + + // Remove GET string from segments + if (($query = strpos(Router::$current_uri, '?')) !== FALSE) + { + list (Router::$current_uri, $query) = explode('?', Router::$current_uri, 2); + + // Parse the query string into $_GET + parse_str($query, $_GET); + + // Convert $_GET to UTF-8 + $_GET = utf8::clean($_GET); + } + } + } + elseif (isset($_GET['kohana_uri'])) + { + // Use the URI defined in the query string + Router::$current_uri = $_GET['kohana_uri']; + + // Remove the URI from $_GET + unset($_GET['kohana_uri']); + + // Remove the URI from $_SERVER['QUERY_STRING'] + $_SERVER['QUERY_STRING'] = preg_replace('~\bkohana_uri\b[^&]*+&?~', '', $_SERVER['QUERY_STRING']); + } + elseif (isset($_SERVER['PATH_INFO']) AND $_SERVER['PATH_INFO']) + { + Router::$current_uri = $_SERVER['PATH_INFO']; + } + elseif (isset($_SERVER['ORIG_PATH_INFO']) AND $_SERVER['ORIG_PATH_INFO']) + { + Router::$current_uri = $_SERVER['ORIG_PATH_INFO']; + } + elseif (isset($_SERVER['PHP_SELF']) AND $_SERVER['PHP_SELF']) + { + Router::$current_uri = $_SERVER['PHP_SELF']; + } + + if (($strpos_fc = strpos(Router::$current_uri, KOHANA)) !== FALSE) + { + // Remove the front controller from the current uri + Router::$current_uri = (string) substr(Router::$current_uri, $strpos_fc + strlen(KOHANA)); + } + + // Remove slashes from the start and end of the URI + Router::$current_uri = trim(Router::$current_uri, '/'); + + if (Router::$current_uri !== '') + { + if ($suffix = Kohana::config('core.url_suffix') AND strpos(Router::$current_uri, $suffix) !== FALSE) + { + // Remove the URL suffix + Router::$current_uri = preg_replace('#'.preg_quote($suffix).'$#u', '', Router::$current_uri); + + // Set the URL suffix + Router::$url_suffix = $suffix; + } + + // Reduce multiple slashes into single slashes + Router::$current_uri = preg_replace('#//+#', '/', Router::$current_uri); + } + } + + /** + * Generates routed URI from given URI. + * + * @param string URI to convert + * @return string Routed uri + */ + public static function routed_uri($uri) + { + if (Router::$routes === NULL) + { + // Load routes + Router::$routes = Kohana::config('routes'); + } + + // Prepare variables + $routed_uri = $uri = trim($uri, '/'); + + if (isset(Router::$routes[$uri])) + { + // Literal match, no need for regex + $routed_uri = Router::$routes[$uri]; + } + else + { + // Loop through the routes and see if anything matches + foreach (Router::$routes as $key => $val) + { + if ($key === '_default') continue; + + // Trim slashes + $key = trim($key, '/'); + $val = trim($val, '/'); + + if (preg_match('#^'.$key.'$#u', $uri)) + { + if (strpos($val, '$') !== FALSE) + { + // Use regex routing + $routed_uri = preg_replace('#^'.$key.'$#u', $val, $uri); + } + else + { + // Standard routing + $routed_uri = $val; + } + + // A valid route has been found + break; + } + } + } + + if (isset(Router::$routes[$routed_uri])) + { + // Check for double routing (without regex) + $routed_uri = Router::$routes[$routed_uri]; + } + + return trim($routed_uri, '/'); + } + +} // End Router \ No newline at end of file diff --git a/lib/kohana/system/libraries/Session.php b/lib/kohana/system/libraries/Session.php new file mode 100644 index 0000000..7ae79cf --- /dev/null +++ b/lib/kohana/system/libraries/Session.php @@ -0,0 +1,457 @@ +input = Input::instance(); + + // This part only needs to be run once + if (Session::$instance === NULL) + { + // Load config + Session::$config = Kohana::config('session'); + + // Makes a mirrored array, eg: foo=foo + Session::$protect = array_combine(Session::$protect, Session::$protect); + + // Configure garbage collection + ini_set('session.gc_probability', (int) Session::$config['gc_probability']); + ini_set('session.gc_divisor', 100); + ini_set('session.gc_maxlifetime', (Session::$config['expiration'] == 0) ? 86400 : Session::$config['expiration']); + + // Create a new session + $this->create(); + + if (Session::$config['regenerate'] > 0 AND ($_SESSION['total_hits'] % Session::$config['regenerate']) === 0) + { + // Regenerate session id and update session cookie + $this->regenerate(); + } + else + { + // Always update session cookie to keep the session alive + cookie::set(Session::$config['name'], $_SESSION['session_id'], Session::$config['expiration']); + } + + // Close the session just before sending the headers, so that + // the session cookie(s) can be written. + Event::add('system.send_headers', array($this, 'write_close')); + + // Make sure that sessions are closed before exiting + register_shutdown_function(array($this, 'write_close')); + + // Singleton instance + Session::$instance = $this; + } + + Kohana::log('debug', 'Session Library initialized'); + } + + /** + * Get the session id. + * + * @return string + */ + public function id() + { + return $_SESSION['session_id']; + } + + /** + * Create a new session. + * + * @param array variables to set after creation + * @return void + */ + public function create($vars = NULL) + { + // Destroy any current sessions + $this->destroy(); + + if (Session::$config['driver'] !== 'native') + { + // Set driver name + $driver = 'Session_'.ucfirst(Session::$config['driver']).'_Driver'; + + // Load the driver + if ( ! Kohana::auto_load($driver)) + throw new Kohana_Exception('core.driver_not_found', Session::$config['driver'], get_class($this)); + + // Initialize the driver + Session::$driver = new $driver(); + + // Validate the driver + if ( ! (Session::$driver instanceof Session_Driver)) + throw new Kohana_Exception('core.driver_implements', Session::$config['driver'], get_class($this), 'Session_Driver'); + + // Register non-native driver as the session handler + session_set_save_handler + ( + array(Session::$driver, 'open'), + array(Session::$driver, 'close'), + array(Session::$driver, 'read'), + array(Session::$driver, 'write'), + array(Session::$driver, 'destroy'), + array(Session::$driver, 'gc') + ); + } + + // Validate the session name + if ( ! preg_match('~^(?=.*[a-z])[a-z0-9_]++$~iD', Session::$config['name'])) + throw new Kohana_Exception('session.invalid_session_name', Session::$config['name']); + + // Name the session, this will also be the name of the cookie + session_name(Session::$config['name']); + + // Set the session cookie parameters + session_set_cookie_params + ( + Session::$config['expiration'], + Kohana::config('cookie.path'), + Kohana::config('cookie.domain'), + Kohana::config('cookie.secure') + ); + + // Start the session! + session_start(); + + // Put session_id in the session variable + $_SESSION['session_id'] = session_id(); + + // Set defaults + if ( ! isset($_SESSION['_kf_flash_'])) + { + $_SESSION['total_hits'] = 0; + $_SESSION['_kf_flash_'] = array(); + + $_SESSION['user_agent'] = Kohana::$user_agent; + $_SESSION['ip_address'] = $this->input->ip_address(); + } + + // Set up flash variables + Session::$flash =& $_SESSION['_kf_flash_']; + + // Increase total hits + $_SESSION['total_hits'] += 1; + + // Validate data only on hits after one + if ($_SESSION['total_hits'] > 1) + { + // Validate the session + foreach (Session::$config['validate'] as $valid) + { + switch ($valid) + { + // Check user agent for consistency + case 'user_agent': + if ($_SESSION[$valid] !== Kohana::$user_agent) + return $this->create(); + break; + + // Check ip address for consistency + case 'ip_address': + if ($_SESSION[$valid] !== $this->input->$valid()) + return $this->create(); + break; + + // Check expiration time to prevent users from manually modifying it + case 'expiration': + if (time() - $_SESSION['last_activity'] > ini_get('session.gc_maxlifetime')) + return $this->create(); + break; + } + } + } + + // Expire flash keys + $this->expire_flash(); + + // Update last activity + $_SESSION['last_activity'] = time(); + + // Set the new data + Session::set($vars); + } + + /** + * Regenerates the global session id. + * + * @return void + */ + public function regenerate() + { + if (Session::$config['driver'] === 'native') + { + // Generate a new session id + // Note: also sets a new session cookie with the updated id + session_regenerate_id(TRUE); + + // Update session with new id + $_SESSION['session_id'] = session_id(); + } + else + { + // Pass the regenerating off to the driver in case it wants to do anything special + $_SESSION['session_id'] = Session::$driver->regenerate(); + } + + // Get the session name + $name = session_name(); + + if (isset($_COOKIE[$name])) + { + // Change the cookie value to match the new session id to prevent "lag" + $_COOKIE[$name] = $_SESSION['session_id']; + } + } + + /** + * Destroys the current session. + * + * @return void + */ + public function destroy() + { + if (session_id() !== '') + { + // Get the session name + $name = session_name(); + + // Destroy the session + session_destroy(); + + // Re-initialize the array + $_SESSION = array(); + + // Delete the session cookie + cookie::delete($name); + } + } + + /** + * Runs the system.session_write event, then calls session_write_close. + * + * @return void + */ + public function write_close() + { + static $run; + + if ($run === NULL) + { + $run = TRUE; + + // Run the events that depend on the session being open + Event::run('system.session_write'); + + // Expire flash keys + $this->expire_flash(); + + // Close the session + session_write_close(); + } + } + + /** + * Set a session variable. + * + * @param string|array key, or array of values + * @param mixed value (if keys is not an array) + * @return void + */ + public function set($keys, $val = FALSE) + { + if (empty($keys)) + return FALSE; + + if ( ! is_array($keys)) + { + $keys = array($keys => $val); + } + + foreach ($keys as $key => $val) + { + if (isset(Session::$protect[$key])) + continue; + + // Set the key + $_SESSION[$key] = $val; + } + } + + /** + * Set a flash variable. + * + * @param string|array key, or array of values + * @param mixed value (if keys is not an array) + * @return void + */ + public function set_flash($keys, $val = FALSE) + { + if (empty($keys)) + return FALSE; + + if ( ! is_array($keys)) + { + $keys = array($keys => $val); + } + + foreach ($keys as $key => $val) + { + if ($key == FALSE) + continue; + + Session::$flash[$key] = 'new'; + Session::set($key, $val); + } + } + + /** + * Freshen one, multiple or all flash variables. + * + * @param string variable key(s) + * @return void + */ + public function keep_flash($keys = NULL) + { + $keys = ($keys === NULL) ? array_keys(Session::$flash) : func_get_args(); + + foreach ($keys as $key) + { + if (isset(Session::$flash[$key])) + { + Session::$flash[$key] = 'new'; + } + } + } + + /** + * Expires old flash data and removes it from the session. + * + * @return void + */ + public function expire_flash() + { + static $run; + + // Method can only be run once + if ($run === TRUE) + return; + + if ( ! empty(Session::$flash)) + { + foreach (Session::$flash as $key => $state) + { + if ($state === 'old') + { + // Flash has expired + unset(Session::$flash[$key], $_SESSION[$key]); + } + else + { + // Flash will expire + Session::$flash[$key] = 'old'; + } + } + } + + // Method has been run + $run = TRUE; + } + + /** + * Get a variable. Access to sub-arrays is supported with key.subkey. + * + * @param string variable key + * @param mixed default value returned if variable does not exist + * @return mixed Variable data if key specified, otherwise array containing all session data. + */ + public function get($key = FALSE, $default = FALSE) + { + if (empty($key)) + return $_SESSION; + + $result = isset($_SESSION[$key]) ? $_SESSION[$key] : Kohana::key_string($_SESSION, $key); + + return ($result === NULL) ? $default : $result; + } + + /** + * Get a variable, and delete it. + * + * @param string variable key + * @param mixed default value returned if variable does not exist + * @return mixed + */ + public function get_once($key, $default = FALSE) + { + $return = Session::get($key, $default); + Session::delete($key); + + return $return; + } + + /** + * Delete one or more variables. + * + * @param string variable key(s) + * @return void + */ + public function delete($keys) + { + $args = func_get_args(); + + foreach ($args as $key) + { + if (isset(Session::$protect[$key])) + continue; + + // Unset the key + unset($_SESSION[$key]); + } + } + +} // End Session Class diff --git a/lib/kohana/system/libraries/Tagcloud.php b/lib/kohana/system/libraries/Tagcloud.php new file mode 100644 index 0000000..8fd7bfc --- /dev/null +++ b/lib/kohana/system/libraries/Tagcloud.php @@ -0,0 +1,130 @@ + 'tag'); + public $shuffle = FALSE; + + // Tag elements, biggest and smallest values + protected $elements; + protected $biggest; + protected $smallest; + + /** + * Construct a new tagcloud. The elements must be passed in as an array, + * with each entry in the array having a "title" ,"link", and "count" key. + * Font sizes will be applied via the "style" attribute as a percentage. + * + * @param array elements of the tagcloud + * @param integer minimum font size + * @param integer maximum font size + * @return void + */ + public function __construct(array $elements, $min_size = NULL, $max_size = NULL, $shuffle = FALSE) + { + $this->elements = $elements; + + if($shuffle !== FALSE) + { + $this->shuffle = TRUE; + } + + $counts = array(); + foreach ($elements as $data) + { + $counts[] = $data['count']; + } + + // Find the biggest and smallest values of the elements + $this->biggest = max($counts); + $this->smallest = min($counts); + + if ($min_size !== NULL) + { + $this->min_size = $min_size; + } + + if ($max_size !== NULL) + { + $this->max_size = $max_size; + } + } + + /** + * Magic __toString method. Returns all of the links as a single string. + * + * @return string + */ + public function __toString() + { + return implode("\n", $this->render()); + } + + /** + * Renders the elements of the tagcloud into an array of links. + * + * @return array + */ + public function render() + { + if ($this->shuffle === TRUE) + { + shuffle($this->elements); + } + + // Minimum values must be 1 to prevent divide by zero errors + $range = max($this->biggest - $this->smallest, 1); + $scale = max($this->max_size - $this->min_size, 1); + + // Import the attributes locally to prevent overwrites + $attr = $this->attributes; + + $output = array(); + foreach ($this->elements as $data) + { + if (strpos($data['title'], ' ') !== FALSE) + { + // Replace spaces with non-breaking spaces to prevent line wrapping + // in the middle of a link + $data['title'] = str_replace(' ', ' ', $data['title']); + } + + // Determine the size based on the min/max scale and the smallest/biggest range + $size = ((($data['count'] - $this->smallest) * $scale) / $range) + $this->min_size; + + $attr['style'] = 'font-size: '.round($size, 0).'%'; + + $output[] = html::anchor($data['link'], $data['title'], $attr)."\n"; + } + + return $output; + } + +} // End Tagcloud \ No newline at end of file diff --git a/lib/kohana/system/libraries/URI.php b/lib/kohana/system/libraries/URI.php new file mode 100644 index 0000000..d9ccdcf --- /dev/null +++ b/lib/kohana/system/libraries/URI.php @@ -0,0 +1,279 @@ +build_array(URI::$segments, $offset, $associative); + } + + /** + * Returns an array containing all the re-routed URI segments. + * + * @param integer rsegment offset + * @param boolean return an associative array + * @return array + */ + public function rsegment_array($offset = 0, $associative = FALSE) + { + return $this->build_array(URI::$rsegments, $offset, $associative); + } + + /** + * Returns an array containing all the URI arguments. + * + * @param integer segment offset + * @param boolean return an associative array + * @return array + */ + public function argument_array($offset = 0, $associative = FALSE) + { + return $this->build_array(URI::$arguments, $offset, $associative); + } + + /** + * Creates a simple or associative array from an array and an offset. + * Used as a helper for (r)segment_array and argument_array. + * + * @param array array to rebuild + * @param integer offset to start from + * @param boolean create an associative array + * @return array + */ + public function build_array($array, $offset = 0, $associative = FALSE) + { + // Prevent the keys from being improperly indexed + array_unshift($array, 0); + + // Slice the array, preserving the keys + $array = array_slice($array, $offset + 1, count($array) - 1, TRUE); + + if ($associative === FALSE) + return $array; + + $associative = array(); + $pairs = array_chunk($array, 2); + + foreach ($pairs as $pair) + { + // Add the key/value pair to the associative array + $associative[$pair[0]] = isset($pair[1]) ? $pair[1] : ''; + } + + return $associative; + } + + /** + * Returns the complete URI as a string. + * + * @return string + */ + public function string() + { + return URI::$current_uri; + } + + /** + * Magic method for converting an object to a string. + * + * @return string + */ + public function __toString() + { + return URI::$current_uri; + } + + /** + * Returns the total number of URI segments. + * + * @return integer + */ + public function total_segments() + { + return count(URI::$segments); + } + + /** + * Returns the total number of re-routed URI segments. + * + * @return integer + */ + public function total_rsegments() + { + return count(URI::$rsegments); + } + + /** + * Returns the total number of URI arguments. + * + * @return integer + */ + public function total_arguments() + { + return count(URI::$arguments); + } + + /** + * Returns the last URI segment. + * + * @param mixed default value returned if segment does not exist + * @return string + */ + public function last_segment($default = FALSE) + { + if (($end = $this->total_segments()) < 1) + return $default; + + return URI::$segments[$end - 1]; + } + + /** + * Returns the last re-routed URI segment. + * + * @param mixed default value returned if segment does not exist + * @return string + */ + public function last_rsegment($default = FALSE) + { + if (($end = $this->total_segments()) < 1) + return $default; + + return URI::$rsegments[$end - 1]; + } + + /** + * Returns the path to the current controller (not including the actual + * controller), as a web path. + * + * @param boolean return a full url, or only the path specifically + * @return string + */ + public function controller_path($full = TRUE) + { + return ($full) ? url::site(URI::$controller_path) : URI::$controller_path; + } + + /** + * Returns the current controller, as a web path. + * + * @param boolean return a full url, or only the controller specifically + * @return string + */ + public function controller($full = TRUE) + { + return ($full) ? url::site(URI::$controller_path.URI::$controller) : URI::$controller; + } + + /** + * Returns the current method, as a web path. + * + * @param boolean return a full url, or only the method specifically + * @return string + */ + public function method($full = TRUE) + { + return ($full) ? url::site(URI::$controller_path.URI::$controller.'/'.URI::$method) : URI::$method; + } + +} // End URI Class diff --git a/lib/kohana/system/libraries/Validation.php b/lib/kohana/system/libraries/Validation.php new file mode 100644 index 0000000..5a48bfc --- /dev/null +++ b/lib/kohana/system/libraries/Validation.php @@ -0,0 +1,826 @@ +submitted = ! empty($array); + + parent::__construct($array, ArrayObject::ARRAY_AS_PROPS | ArrayObject::STD_PROP_LIST); + } + + /** + * Magic clone method, clears errors and messages. + * + * @return void + */ + public function __clone() + { + $this->errors = array(); + $this->messages = array(); + } + + /** + * Create a copy of the current validation rules and change the array. + * + * @chainable + * @param array new array to validate + * @return Validation + */ + public function copy(array $array) + { + $copy = clone $this; + + $copy->exchangeArray($array); + + return $copy; + } + + /** + * Test if the data has been submitted. + * + * @return boolean + */ + public function submitted($value = NULL) + { + if (is_bool($value)) + { + $this->submitted = $value; + } + + return $this->submitted; + } + + /** + * Returns an array of all the field names that have filters, rules, or callbacks. + * + * @return array + */ + public function field_names() + { + // All the fields that are being validated + $fields = array_keys(array_merge + ( + $this->pre_filters, + $this->rules, + $this->callbacks, + $this->post_filters + )); + + // Remove wildcard fields + $fields = array_diff($fields, array('*')); + + return $fields; + } + + /** + * Returns the array values of the current object. + * + * @return array + */ + public function as_array() + { + return $this->getArrayCopy(); + } + + /** + * Returns the ArrayObject values, removing all inputs without rules. + * To choose specific inputs, list the field name as arguments. + * + * @param boolean return only fields with filters, rules, and callbacks + * @return array + */ + public function safe_array() + { + // Load choices + $choices = func_get_args(); + $choices = empty($choices) ? NULL : array_combine($choices, $choices); + + // Get field names + $fields = $this->field_names(); + + $safe = array(); + foreach ($fields as $field) + { + if ($choices === NULL OR isset($choices[$field])) + { + if (isset($this[$field])) + { + $value = $this[$field]; + + if (is_object($value)) + { + // Convert the value back into an array + $value = $value->getArrayCopy(); + } + } + else + { + // Even if the field is not in this array, it must be set + $value = NULL; + } + + // Add the field to the array + $safe[$field] = $value; + } + } + + return $safe; + } + + /** + * Add additional rules that will forced, even for empty fields. All arguments + * passed will be appended to the list. + * + * @chainable + * @param string rule name + * @return object + */ + public function allow_empty_rules($rules) + { + // Any number of args are supported + $rules = func_get_args(); + + // Merge the allowed rules + $this->empty_rules = array_merge($this->empty_rules, $rules); + + return $this; + } + + /** + * Converts a filter, rule, or callback into a fully-qualified callback array. + * + * @return mixed + */ + protected function callback($callback) + { + if (is_string($callback)) + { + if (strpos($callback, '::') !== FALSE) + { + $callback = explode('::', $callback); + } + elseif (function_exists($callback)) + { + // No need to check if the callback is a method + $callback = $callback; + } + elseif (method_exists($this, $callback)) + { + // The callback exists in Validation + $callback = array($this, $callback); + } + elseif (method_exists('valid', $callback)) + { + // The callback exists in valid:: + $callback = array('valid', $callback); + } + } + + if ( ! is_callable($callback, FALSE)) + { + if (is_array($callback)) + { + if (is_object($callback[0])) + { + // Object instance syntax + $name = get_class($callback[0]).'->'.$callback[1]; + } + else + { + // Static class syntax + $name = $callback[0].'::'.$callback[1]; + } + } + else + { + // Function syntax + $name = $callback; + } + + throw new Kohana_Exception('validation.not_callable', $name); + } + + return $callback; + } + + /** + * Add a pre-filter to one or more inputs. Pre-filters are applied before + * rules or callbacks are executed. + * + * @chainable + * @param callback filter + * @param string fields to apply filter to, use TRUE for all fields + * @return object + */ + public function pre_filter($filter, $field = TRUE) + { + if ($field === TRUE OR $field === '*') + { + // Use wildcard + $fields = array('*'); + } + else + { + // Add the filter to specific inputs + $fields = func_get_args(); + $fields = array_slice($fields, 1); + } + + // Convert to a proper callback + $filter = $this->callback($filter); + + foreach ($fields as $field) + { + // Add the filter to specified field + $this->pre_filters[$field][] = $filter; + } + + return $this; + } + + /** + * Add a post-filter to one or more inputs. Post-filters are applied after + * rules and callbacks have been executed. + * + * @chainable + * @param callback filter + * @param string fields to apply filter to, use TRUE for all fields + * @return object + */ + public function post_filter($filter, $field = TRUE) + { + if ($field === TRUE) + { + // Use wildcard + $fields = array('*'); + } + else + { + // Add the filter to specific inputs + $fields = func_get_args(); + $fields = array_slice($fields, 1); + } + + // Convert to a proper callback + $filter = $this->callback($filter); + + foreach ($fields as $field) + { + // Add the filter to specified field + $this->post_filters[$field][] = $filter; + } + + return $this; + } + + /** + * Add rules to a field. Validation rules may only return TRUE or FALSE and + * can not manipulate the value of a field. + * + * @chainable + * @param string field name + * @param callback rules (one or more arguments) + * @return object + */ + public function add_rules($field, $rules) + { + // Get the rules + $rules = func_get_args(); + $rules = array_slice($rules, 1); + + if ($field === TRUE) + { + // Use wildcard + $field = '*'; + } + + foreach ($rules as $rule) + { + // Arguments for rule + $args = NULL; + + if (is_string($rule)) + { + if (preg_match('/^([^\[]++)\[(.+)\]$/', $rule, $matches)) + { + // Split the rule into the function and args + $rule = $matches[1]; + $args = preg_split('/(?array_fields[$field] = $field; + } + + // Convert to a proper callback + $rule = $this->callback($rule); + + // Add the rule, with args, to the field + $this->rules[$field][] = array($rule, $args); + } + + return $this; + } + + /** + * Add callbacks to a field. Callbacks must accept the Validation object + * and the input name. Callback returns are not processed. + * + * @chainable + * @param string field name + * @param callbacks callbacks (unlimited number) + * @return object + */ + public function add_callbacks($field, $callbacks) + { + // Get all callbacks as an array + $callbacks = func_get_args(); + $callbacks = array_slice($callbacks, 1); + + if ($field === TRUE) + { + // Use wildcard + $field = '*'; + } + + foreach ($callbacks as $callback) + { + // Convert to a proper callback + $callback = $this->callback($callback); + + // Add the callback to specified field + $this->callbacks[$field][] = $callback; + } + + return $this; + } + + /** + * Validate by processing pre-filters, rules, callbacks, and post-filters. + * All fields that have filters, rules, or callbacks will be initialized if + * they are undefined. Validation will only be run if there is data already + * in the array. + * + * @param object Validation object, used only for recursion + * @param object name of field for errors + * @return bool + */ + public function validate($object = NULL, $field_name = NULL) + { + if ($object === NULL) + { + // Use the current object + $object = $this; + } + + // Get all field names + $fields = $this->field_names(); + + // Copy the array from the object, to optimize multiple sets + $array = $this->getArrayCopy(); + + foreach ($fields as $field) + { + if ($field === '*') + { + // Ignore wildcard + continue; + } + + if ( ! isset($array[$field])) + { + if (isset($this->array_fields[$field])) + { + // This field must be an array + $array[$field] = array(); + } + else + { + $array[$field] = NULL; + } + } + } + + // Swap the array back into the object + $this->exchangeArray($array); + + // Get all defined field names + $fields = array_keys($array); + + foreach ($this->pre_filters as $field => $callbacks) + { + foreach ($callbacks as $callback) + { + if ($field === '*') + { + foreach ($fields as $f) + { + $this[$f] = is_array($this[$f]) ? array_map($callback, $this[$f]) : call_user_func($callback, $this[$f]); + } + } + else + { + $this[$field] = is_array($this[$field]) ? array_map($callback, $this[$field]) : call_user_func($callback, $this[$field]); + } + } + } + + if ($this->submitted === FALSE) + return FALSE; + + foreach ($this->rules as $field => $callbacks) + { + foreach ($callbacks as $callback) + { + // Separate the callback and arguments + list ($callback, $args) = $callback; + + // Function or method name of the rule + $rule = is_array($callback) ? $callback[1] : $callback; + + if ($field === '*') + { + foreach ($fields as $f) + { + // Note that continue, instead of break, is used when + // applying rules using a wildcard, so that all fields + // will be validated. + + if (isset($this->errors[$f])) + { + // Prevent other rules from being evaluated if an error has occurred + continue; + } + + if (empty($this[$f]) AND ! in_array($rule, $this->empty_rules)) + { + // This rule does not need to be processed on empty fields + continue; + } + + if ($args === NULL) + { + if ( ! call_user_func($callback, $this[$f])) + { + $this->errors[$f] = $rule; + + // Stop validating this field when an error is found + continue; + } + } + else + { + if ( ! call_user_func($callback, $this[$f], $args)) + { + $this->errors[$f] = $rule; + + // Stop validating this field when an error is found + continue; + } + } + } + } + else + { + if (isset($this->errors[$field])) + { + // Prevent other rules from being evaluated if an error has occurred + break; + } + + if ( ! in_array($rule, $this->empty_rules) AND ! $this->required($this[$field])) + { + // This rule does not need to be processed on empty fields + continue; + } + + if ($args === NULL) + { + if ( ! call_user_func($callback, $this[$field])) + { + $this->errors[$field] = $rule; + + // Stop validating this field when an error is found + break; + } + } + else + { + if ( ! call_user_func($callback, $this[$field], $args)) + { + $this->errors[$field] = $rule; + + // Stop validating this field when an error is found + break; + } + } + } + } + } + + foreach ($this->callbacks as $field => $callbacks) + { + foreach ($callbacks as $callback) + { + if ($field === '*') + { + foreach ($fields as $f) + { + // Note that continue, instead of break, is used when + // applying rules using a wildcard, so that all fields + // will be validated. + + if (isset($this->errors[$f])) + { + // Stop validating this field when an error is found + continue; + } + + call_user_func($callback, $this, $f); + } + } + else + { + if (isset($this->errors[$field])) + { + // Stop validating this field when an error is found + break; + } + + call_user_func($callback, $this, $field); + } + } + } + + foreach ($this->post_filters as $field => $callbacks) + { + foreach ($callbacks as $callback) + { + if ($field === '*') + { + foreach ($fields as $f) + { + $this[$f] = is_array($this[$f]) ? array_map($callback, $this[$f]) : call_user_func($callback, $this[$f]); + } + } + else + { + $this[$field] = is_array($this[$field]) ? array_map($callback, $this[$field]) : call_user_func($callback, $this[$field]); + } + } + } + + // Return TRUE if there are no errors + return $this->errors === array(); + } + + /** + * Add an error to an input. + * + * @chainable + * @param string input name + * @param string unique error name + * @return object + */ + public function add_error($field, $name) + { + $this->errors[$field] = $name; + + return $this; + } + + /** + * Sets or returns the message for an input. + * + * @chainable + * @param string input key + * @param string message to set + * @return string|object + */ + public function message($input = NULL, $message = NULL) + { + if ($message === NULL) + { + if ($input === NULL) + { + $messages = array(); + $keys = array_keys($this->messages); + + foreach ($keys as $input) + { + $messages[] = $this->message($input); + } + + return implode("\n", $messages); + } + + // Return nothing if no message exists + if (empty($this->messages[$input])) + return ''; + + // Return the HTML message string + return $this->messages[$input]; + } + else + { + $this->messages[$input] = $message; + } + + return $this; + } + + /** + * Return the errors array. + * + * @param boolean load errors from a lang file + * @return array + */ + public function errors($file = NULL) + { + if ($file === NULL) + { + return $this->errors; + } + else + { + + $errors = array(); + foreach ($this->errors as $input => $error) + { + // Key for this input error + $key = "$file.$input.$error"; + + if (($errors[$input] = Kohana::lang($key)) === $key) + { + // Get the default error message + $errors[$input] = Kohana::lang("$file.$input.default"); + } + } + + return $errors; + } + } + + /** + * Rule: required. Generates an error if the field has an empty value. + * + * @param mixed input value + * @return bool + */ + public function required($str) + { + if (is_object($str) AND $str instanceof ArrayObject) + { + // Get the array from the ArrayObject + $str = $str->getArrayCopy(); + } + + if (is_array($str)) + { + return ! empty($str); + } + else + { + return ! ($str === '' OR $str === NULL OR $str === FALSE); + } + } + + /** + * Rule: matches. Generates an error if the field does not match one or more + * other fields. + * + * @param mixed input value + * @param array input names to match against + * @return bool + */ + public function matches($str, array $inputs) + { + foreach ($inputs as $key) + { + if ($str !== (isset($this[$key]) ? $this[$key] : NULL)) + return FALSE; + } + + return TRUE; + } + + /** + * Rule: length. Generates an error if the field is too long or too short. + * + * @param mixed input value + * @param array minimum, maximum, or exact length to match + * @return bool + */ + public function length($str, array $length) + { + if ( ! is_string($str)) + return FALSE; + + $size = utf8::strlen($str); + $status = FALSE; + + if (count($length) > 1) + { + list ($min, $max) = $length; + + if ($size >= $min AND $size <= $max) + { + $status = TRUE; + } + } + else + { + $status = ($size === (int) $length[0]); + } + + return $status; + } + + /** + * Rule: depends_on. Generates an error if the field does not depend on one + * or more other fields. + * + * @param mixed field name + * @param array field names to check dependency + * @return bool + */ + public function depends_on($field, array $fields) + { + foreach ($fields as $depends_on) + { + if ( ! isset($this[$depends_on]) OR $this[$depends_on] == NULL) + return FALSE; + } + + return TRUE; + } + + /** + * Rule: chars. Generates an error if the field contains characters outside of the list. + * + * @param string field value + * @param array allowed characters + * @return bool + */ + public function chars($value, array $chars) + { + return ! preg_match('![^'.implode('', $chars).']!u', $value); + } + +} // End Validation diff --git a/lib/kohana/system/libraries/View.php b/lib/kohana/system/libraries/View.php new file mode 100644 index 0000000..2b8471c --- /dev/null +++ b/lib/kohana/system/libraries/View.php @@ -0,0 +1,309 @@ +set_filename($name, $type); + } + + if (is_array($data) AND ! empty($data)) + { + // Preload data using array_merge, to allow user extensions + $this->kohana_local_data = array_merge($this->kohana_local_data, $data); + } + } + + /** + * Magic method access to test for view property + * + * @param string View property to test for + * @return boolean + */ + public function __isset($key = NULL) + { + return $this->is_set($key); + } + + /** + * Sets the view filename. + * + * @chainable + * @param string view filename + * @param string view file type + * @return object + */ + public function set_filename($name, $type = NULL) + { + if ($type == NULL) + { + // Load the filename and set the content type + $this->kohana_filename = Kohana::find_file('views', $name, TRUE); + $this->kohana_filetype = EXT; + } + else + { + // Check if the filetype is allowed by the configuration + if ( ! in_array($type, Kohana::config('view.allowed_filetypes'))) + throw new Kohana_Exception('core.invalid_filetype', $type); + + // Load the filename and set the content type + $this->kohana_filename = Kohana::find_file('views', $name, TRUE, $type); + $this->kohana_filetype = Kohana::config('mimes.'.$type); + + if ($this->kohana_filetype == NULL) + { + // Use the specified type + $this->kohana_filetype = $type; + } + } + + return $this; + } + + /** + * Sets a view variable. + * + * @param string|array name of variable or an array of variables + * @param mixed value when using a named variable + * @return object + */ + public function set($name, $value = NULL) + { + if (is_array($name)) + { + foreach ($name as $key => $value) + { + $this->__set($key, $value); + } + } + else + { + $this->__set($name, $value); + } + + return $this; + } + + /** + * Checks for a property existence in the view locally or globally. Unlike the built in __isset(), + * this method can take an array of properties to test simultaneously. + * + * @param string $key property name to test for + * @param array $key array of property names to test for + * @return boolean property test result + * @return array associative array of keys and boolean test result + */ + public function is_set( $key = FALSE ) + { + // Setup result; + $result = FALSE; + + // If key is an array + if (is_array($key)) + { + // Set the result to an array + $result = array(); + + // Foreach key + foreach ($key as $property) + { + // Set the result to an associative array + $result[$property] = (array_key_exists($property, $this->kohana_local_data) OR array_key_exists($property, View::$kohana_global_data)) ? TRUE : FALSE; + } + } + else + { + // Otherwise just check one property + $result = (array_key_exists($key, $this->kohana_local_data) OR array_key_exists($key, View::$kohana_global_data)) ? TRUE : FALSE; + } + + // Return the result + return $result; + } + + /** + * Sets a bound variable by reference. + * + * @param string name of variable + * @param mixed variable to assign by reference + * @return object + */ + public function bind($name, & $var) + { + $this->kohana_local_data[$name] =& $var; + + return $this; + } + + /** + * Sets a view global variable. + * + * @param string|array name of variable or an array of variables + * @param mixed value when using a named variable + * @return void + */ + public static function set_global($name, $value = NULL) + { + if (is_array($name)) + { + foreach ($name as $key => $value) + { + View::$kohana_global_data[$key] = $value; + } + } + else + { + View::$kohana_global_data[$name] = $value; + } + } + + /** + * Magically sets a view variable. + * + * @param string variable key + * @param string variable value + * @return void + */ + public function __set($key, $value) + { + $this->kohana_local_data[$key] = $value; + } + + /** + * Magically gets a view variable. + * + * @param string variable key + * @return mixed variable value if the key is found + * @return void if the key is not found + */ + public function &__get($key) + { + if (isset($this->kohana_local_data[$key])) + return $this->kohana_local_data[$key]; + + if (isset(View::$kohana_global_data[$key])) + return View::$kohana_global_data[$key]; + + if (isset($this->$key)) + return $this->$key; + } + + /** + * Magically converts view object to string. + * + * @return string + */ + public function __toString() + { + try + { + return $this->render(); + } + catch (Exception $e) + { + // Display the exception using its internal __toString method + return (string) $e; + } + } + + /** + * Renders a view. + * + * @param boolean set to TRUE to echo the output instead of returning it + * @param callback special renderer to pass the output through + * @return string if print is FALSE + * @return void if print is TRUE + */ + public function render($print = FALSE, $renderer = FALSE) + { + if (empty($this->kohana_filename)) + throw new Kohana_Exception('core.view_set_filename'); + + if (is_string($this->kohana_filetype)) + { + // Merge global and local data, local overrides global with the same name + $data = array_merge(View::$kohana_global_data, $this->kohana_local_data); + + // Load the view in the controller for access to $this + $output = Kohana::$instance->_kohana_load_view($this->kohana_filename, $data); + + if ($renderer !== FALSE AND is_callable($renderer, TRUE)) + { + // Pass the output through the user defined renderer + $output = call_user_func($renderer, $output); + } + + if ($print === TRUE) + { + // Display the output + echo $output; + return; + } + } + else + { + // Set the content type and size + header('Content-Type: '.$this->kohana_filetype[0]); + + if ($print === TRUE) + { + if ($file = fopen($this->kohana_filename, 'rb')) + { + // Display the output + fpassthru($file); + fclose($file); + } + return; + } + + // Fetch the file contents + $output = file_get_contents($this->kohana_filename); + } + + return $output; + } +} // End View \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Cache.php b/lib/kohana/system/libraries/drivers/Cache.php new file mode 100644 index 0000000..7c5e3c3 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Cache.php @@ -0,0 +1,40 @@ +directory = $directory; + } + + /** + * Finds an array of files matching the given id or tag. + * + * @param string cache id or tag + * @param bool search for tags + * @return array of filenames matching the id or tag + */ + public function exists($id, $tag = FALSE) + { + if ($id === TRUE) + { + // Find all the files + return glob($this->directory.'*~*~*'); + } + elseif ($tag === TRUE) + { + // Find all the files that have the tag name + $paths = glob($this->directory.'*~*'.$id.'*~*'); + + // Find all tags matching the given tag + $files = array(); + foreach ($paths as $path) + { + // Split the files + $tags = explode('~', basename($path)); + + // Find valid tags + if (count($tags) !== 3 OR empty($tags[1])) + continue; + + // Split the tags by plus signs, used to separate tags + $tags = explode('+', $tags[1]); + + if (in_array($tag, $tags)) + { + // Add the file to the array, it has the requested tag + $files[] = $path; + } + } + + return $files; + } + else + { + // Find the file matching the given id + return glob($this->directory.$id.'~*'); + } + } + + /** + * Sets a cache item to the given data, tags, and lifetime. + * + * @param string cache id to set + * @param string data in the cache + * @param array cache tags + * @param integer lifetime + * @return bool + */ + public function set($id, $data, array $tags = NULL, $lifetime) + { + // Remove old cache files + $this->delete($id); + + // Cache File driver expects unix timestamp + if ($lifetime !== 0) + { + $lifetime += time(); + } + + if ( ! empty($tags)) + { + // Convert the tags into a string list + $tags = implode('+', $tags); + } + + // Write out a serialized cache + return (bool) file_put_contents($this->directory.$id.'~'.$tags.'~'.$lifetime, serialize($data)); + } + + /** + * Finds an array of ids for a given tag. + * + * @param string tag name + * @return array of ids that match the tag + */ + public function find($tag) + { + // An array will always be returned + $result = array(); + + if ($paths = $this->exists($tag, TRUE)) + { + // Length of directory name + $offset = strlen($this->directory); + + // Find all the files with the given tag + foreach ($paths as $path) + { + // Get the id from the filename + list($id, $junk) = explode('~', basename($path), 2); + + if (($data = $this->get($id)) !== FALSE) + { + // Add the result to the array + $result[$id] = $data; + } + } + } + + return $result; + } + + /** + * Fetches a cache item. This will delete the item if it is expired or if + * the hash does not match the stored hash. + * + * @param string cache id + * @return mixed|NULL + */ + public function get($id) + { + if ($file = $this->exists($id)) + { + // Use the first file + $file = current($file); + + // Validate that the cache has not expired + if ($this->expired($file)) + { + // Remove this cache, it has expired + $this->delete($id); + } + else + { + // Turn off errors while reading the file + $ER = error_reporting(0); + + if (($data = file_get_contents($file)) !== FALSE) + { + // Unserialize the data + $data = unserialize($data); + } + else + { + // Delete the data + unset($data); + } + + // Turn errors back on + error_reporting($ER); + } + } + + // Return NULL if there is no data + return isset($data) ? $data : NULL; + } + + /** + * Deletes a cache item by id or tag + * + * @param string cache id or tag, or TRUE for "all items" + * @param boolean use tags + * @return boolean + */ + public function delete($id, $tag = FALSE) + { + $files = $this->exists($id, $tag); + + if (empty($files)) + return FALSE; + + // Disable all error reporting while deleting + $ER = error_reporting(0); + + foreach ($files as $file) + { + // Remove the cache file + if ( ! unlink($file)) + Kohana::log('error', 'Cache: Unable to delete cache file: '.$file); + } + + // Turn on error reporting again + error_reporting($ER); + + return TRUE; + } + + /** + * Deletes all cache files that are older than the current time. + * + * @return void + */ + public function delete_expired() + { + if ($files = $this->exists(TRUE)) + { + // Disable all error reporting while deleting + $ER = error_reporting(0); + + foreach ($files as $file) + { + if ($this->expired($file)) + { + // The cache file has already expired, delete it + if ( ! unlink($file)) + Kohana::log('error', 'Cache: Unable to delete cache file: '.$file); + } + } + + // Turn on error reporting again + error_reporting($ER); + } + } + + /** + * Check if a cache file has expired by filename. + * + * @param string filename + * @return bool + */ + protected function expired($file) + { + // Get the expiration time + $expires = (int) substr($file, strrpos($file, '~') + 1); + + // Expirations of 0 are "never expire" + return ($expires !== 0 AND $expires <= time()); + } + +} // End Cache File Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Cache/Memcache.php b/lib/kohana/system/libraries/drivers/Cache/Memcache.php new file mode 100644 index 0000000..d801de9 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Cache/Memcache.php @@ -0,0 +1,191 @@ +backend = new Memcache; + $this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : FALSE; + + $servers = Kohana::config('cache_memcache.servers'); + + foreach ($servers as $server) + { + // Make sure all required keys are set + $server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => FALSE); + + // Add the server to the pool + $this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent']) + or Kohana::log('error', 'Cache: Connection failed: '.$server['host']); + } + + // Load tags + self::$tags = $this->backend->get(self::TAGS_KEY); + + if ( ! is_array(self::$tags)) + { + // Create a new tags array + self::$tags = array(); + + // Tags have been created + self::$tags_changed = TRUE; + } + } + + public function __destruct() + { + if (self::$tags_changed === TRUE) + { + // Save the tags + $this->backend->set(self::TAGS_KEY, self::$tags, $this->flags, 0); + + // Tags are now unchanged + self::$tags_changed = FALSE; + } + } + + public function find($tag) + { + if (isset(self::$tags[$tag]) AND $results = $this->backend->get(self::$tags[$tag])) + { + // Return all the found caches + return $results; + } + else + { + // No matching tags + return array(); + } + } + + public function get($id) + { + return (($return = $this->backend->get($id)) === FALSE) ? NULL : $return; + } + + public function set($id, $data, array $tags = NULL, $lifetime) + { + if ( ! empty($tags)) + { + // Tags will be changed + self::$tags_changed = TRUE; + + foreach ($tags as $tag) + { + // Add the id to each tag + self::$tags[$tag][$id] = $id; + } + } + + if ($lifetime !== 0) + { + // Memcache driver expects unix timestamp + $lifetime += time(); + } + + // Set a new value + return $this->backend->set($id, $data, $this->flags, $lifetime); + } + + public function delete($id, $tag = FALSE) + { + // Tags will be changed + self::$tags_changed = TRUE; + + if ($id === TRUE) + { + if ($status = $this->backend->flush()) + { + // Remove all tags, all items have been deleted + self::$tags = array(); + + // We must sleep after flushing, or overwriting will not work! + // @see http://php.net/manual/en/function.memcache-flush.php#81420 + sleep(1); + } + + return $status; + } + elseif ($tag === TRUE) + { + if (isset(self::$tags[$id])) + { + foreach (self::$tags[$id] as $_id) + { + // Delete each id in the tag + $this->backend->delete($_id); + } + + // Delete the tag + unset(self::$tags[$id]); + } + + return TRUE; + } + else + { + foreach (self::$tags as $tag => $_ids) + { + if (isset(self::$tags[$tag][$id])) + { + // Remove the id from the tags + unset(self::$tags[$tag][$id]); + } + } + + return $this->backend->delete($id); + } + } + + public function delete_expired() + { + // Tags will be changed + self::$tags_changed = TRUE; + + foreach (self::$tags as $tag => $_ids) + { + foreach ($_ids as $id) + { + if ( ! $this->backend->get($id)) + { + // This id has disappeared, delete it from the tags + unset(self::$tags[$tag][$id]); + } + } + + if (empty(self::$tags[$tag])) + { + // The tag no longer has any valid ids + unset(self::$tags[$tag]); + } + } + + // Memcache handles garbage collection internally + return TRUE; + } + +} // End Cache Memcache Driver diff --git a/lib/kohana/system/libraries/drivers/Cache/Sqlite.php b/lib/kohana/system/libraries/drivers/Cache/Sqlite.php new file mode 100644 index 0000000..9458d85 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Cache/Sqlite.php @@ -0,0 +1,257 @@ +db = new SQLiteDatabase($filename, '0666', $error); + + // Throw an exception if there's an error + if ( ! empty($error)) + throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error)); + + $query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'"; + $tables = $this->db->query($query, SQLITE_BOTH, $error); + + // Throw an exception if there's an error + if ( ! empty($error)) + throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error)); + + if ($tables->numRows() == 0) + { + Kohana::log('error', 'Cache: Initializing new SQLite cache database'); + + // Issue a CREATE TABLE command + $this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema')); + } + } + + /** + * Checks if a cache id is already set. + * + * @param string cache id + * @return boolean + */ + public function exists($id) + { + // Find the id that matches + $query = "SELECT id FROM caches WHERE id = '$id'"; + + return ($this->db->query($query)->numRows() > 0); + } + + /** + * Sets a cache item to the given data, tags, and lifetime. + * + * @param string cache id to set + * @param string data in the cache + * @param array cache tags + * @param integer lifetime + * @return bool + */ + public function set($id, $data, array $tags = NULL, $lifetime) + { + // Serialize and escape the data + $data = sqlite_escape_string(serialize($data)); + + if ( ! empty($tags)) + { + // Escape the tags, adding brackets so the tag can be explicitly matched + $tags = sqlite_escape_string('<'.implode('>,<', $tags).'>'); + } + + // Cache Sqlite driver expects unix timestamp + if ($lifetime !== 0) + { + $lifetime += time(); + } + + $query = $this->exists($id) + ? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'" + : "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')"; + + // Run the query + $this->db->unbufferedQuery($query, SQLITE_BOTH, $error); + + if ( ! empty($error)) + { + self::log_error($error); + return FALSE; + } + else + { + return TRUE; + } + } + + /** + * Finds an array of ids for a given tag. + * + * @param string tag name + * @return array of ids that match the tag + */ + public function find($tag) + { + $query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'"; + $query = $this->db->query($query, SQLITE_BOTH, $error); + + // An array will always be returned + $result = array(); + + if ( ! empty($error)) + { + self::log_error($error); + } + elseif ($query->numRows() > 0) + { + // Disable notices for unserializing + $ER = error_reporting(~E_NOTICE); + + while ($row = $query->fetchObject()) + { + // Add each cache to the array + $result[$row->id] = unserialize($row->cache); + } + + // Turn notices back on + error_reporting($ER); + } + + return $result; + } + + /** + * Fetches a cache item. This will delete the item if it is expired or if + * the hash does not match the stored hash. + * + * @param string cache id + * @return mixed|NULL + */ + public function get($id) + { + $query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1"; + $query = $this->db->query($query, SQLITE_BOTH, $error); + + if ( ! empty($error)) + { + self::log_error($error); + } + elseif ($cache = $query->fetchObject()) + { + // Make sure the expiration is valid and that the hash matches + if ($cache->expiration != 0 AND $cache->expiration <= time()) + { + // Cache is not valid, delete it now + $this->delete($cache->id); + } + else + { + // Disable notices for unserializing + $ER = error_reporting(~E_NOTICE); + + // Return the valid cache data + $data = $cache->cache; + + // Turn notices back on + error_reporting($ER); + } + } + + // No valid cache found + return NULL; + } + + /** + * Deletes a cache item by id or tag + * + * @param string cache id or tag, or TRUE for "all items" + * @param bool delete a tag + * @return bool + */ + public function delete($id, $tag = FALSE) + { + if ($id === TRUE) + { + // Delete all caches + $where = '1'; + } + elseif ($tag === TRUE) + { + // Delete by tag + $where = "tags LIKE '%<{$id}>%'"; + } + else + { + // Delete by id + $where = "id = '$id'"; + } + + $this->db->unbufferedQuery('DELETE FROM caches WHERE '.$where, SQLITE_BOTH, $error); + + if ( ! empty($error)) + { + self::log_error($error); + return FALSE; + } + else + { + return TRUE; + } + } + + /** + * Deletes all cache files that are older than the current time. + */ + public function delete_expired() + { + // Delete all expired caches + $query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= '.time(); + + $this->db->unbufferedQuery($query); + + return TRUE; + } + +} // End Cache SQLite Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Cache/Xcache.php b/lib/kohana/system/libraries/drivers/Cache/Xcache.php new file mode 100644 index 0000000..6254bbb --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Cache/Xcache.php @@ -0,0 +1,119 @@ +auth(); + $result = TRUE; + for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) + { + if (xcache_clear_cache(XC_TYPE_VAR, $i) !== NULL) + { + $result = FALSE; + break; + } + } + + // Undo the login + $this->auth(TRUE); + return $result; + } + + return TRUE; + } + + public function delete_expired() + { + return TRUE; + } + + private function auth($reverse = FALSE) + { + static $backup = array(); + + $keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW'); + + foreach ($keys as $key) + { + if ($reverse) + { + if (isset($backup[$key])) + { + $_SERVER[$key] = $backup[$key]; + unset($backup[$key]); + } + else + { + unset($_SERVER[$key]); + } + } + else + { + $value = getenv($key); + + if ( ! empty($value)) + { + $backup[$key] = $value; + } + + $_SERVER[$key] = Kohana::config('cache_xcache.'.$key); + } + } + } + +} // End Cache Xcache Driver diff --git a/lib/kohana/system/libraries/drivers/Captcha.php b/lib/kohana/system/libraries/drivers/Captcha.php new file mode 100644 index 0000000..a4343e1 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha.php @@ -0,0 +1,227 @@ +response = $this->generate_challenge(); + + // Store the correct Captcha response in a session + Event::add('system.post_controller', array($this, 'update_response_session')); + } + + /** + * Generate a new Captcha challenge. + * + * @return string the challenge answer + */ + abstract public function generate_challenge(); + + /** + * Output the Captcha challenge. + * + * @param boolean html output + * @return mixed the rendered Captcha (e.g. an image, riddle, etc.) + */ + abstract public function render($html); + + /** + * Stores the response for the current Captcha challenge in a session so it is available + * on the next page load for Captcha::valid(). This method is called after controller + * execution (in the system.post_controller event) in order not to overwrite itself too soon. + * + * @return void + */ + public function update_response_session() + { + Session::instance()->set('captcha_response', sha1(strtoupper($this->response))); + } + + /** + * Validates a Captcha response from a user. + * + * @param string captcha response + * @return boolean + */ + public function valid($response) + { + return (sha1(strtoupper($response)) === Session::instance()->get('captcha_response')); + } + + /** + * Returns the image type. + * + * @param string filename + * @return string|FALSE image type ("png", "gif" or "jpeg") + */ + public function image_type($filename) + { + switch (strtolower(substr(strrchr($filename, '.'), 1))) + { + case 'png': + return 'png'; + + case 'gif': + return 'gif'; + + case 'jpg': + case 'jpeg': + // Return "jpeg" and not "jpg" because of the GD2 function names + return 'jpeg'; + + default: + return FALSE; + } + } + + /** + * Creates an image resource with the dimensions specified in config. + * If a background image is supplied, the image dimensions are used. + * + * @throws Kohana_Exception if no GD2 support + * @param string path to the background image file + * @return void + */ + public function image_create($background = NULL) + { + // Check for GD2 support + if ( ! function_exists('imagegd2')) + throw new Kohana_Exception('captcha.requires_GD2'); + + // Create a new image (black) + $this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']); + + // Use a background image + if ( ! empty($background)) + { + // Create the image using the right function for the filetype + $function = 'imagecreatefrom'.$this->image_type($background); + $this->background_image = $function($background); + + // Resize the image if needed + if (imagesx($this->background_image) !== Captcha::$config['width'] + OR imagesy($this->background_image) !== Captcha::$config['height']) + { + imagecopyresampled + ( + $this->image, $this->background_image, 0, 0, 0, 0, + Captcha::$config['width'], Captcha::$config['height'], + imagesx($this->background_image), imagesy($this->background_image) + ); + } + + // Free up resources + imagedestroy($this->background_image); + } + } + + /** + * Fills the background with a gradient. + * + * @param resource gd image color identifier for start color + * @param resource gd image color identifier for end color + * @param string direction: 'horizontal' or 'vertical', 'random' by default + * @return void + */ + public function image_gradient($color1, $color2, $direction = NULL) + { + $directions = array('horizontal', 'vertical'); + + // Pick a random direction if needed + if ( ! in_array($direction, $directions)) + { + $direction = $directions[array_rand($directions)]; + + // Switch colors + if (mt_rand(0, 1) === 1) + { + $temp = $color1; + $color1 = $color2; + $color2 = $temp; + } + } + + // Extract RGB values + $color1 = imagecolorsforindex($this->image, $color1); + $color2 = imagecolorsforindex($this->image, $color2); + + // Preparations for the gradient loop + $steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height']; + + $r1 = ($color1['red'] - $color2['red']) / $steps; + $g1 = ($color1['green'] - $color2['green']) / $steps; + $b1 = ($color1['blue'] - $color2['blue']) / $steps; + + if ($direction === 'horizontal') + { + $x1 =& $i; + $y1 = 0; + $x2 =& $i; + $y2 = Captcha::$config['height']; + } + else + { + $x1 = 0; + $y1 =& $i; + $x2 = Captcha::$config['width']; + $y2 =& $i; + } + + // Execute the gradient loop + for ($i = 0; $i <= $steps; $i++) + { + $r2 = $color1['red'] - floor($i * $r1); + $g2 = $color1['green'] - floor($i * $g1); + $b2 = $color1['blue'] - floor($i * $b1); + $color = imagecolorallocate($this->image, $r2, $g2, $b2); + + imageline($this->image, $x1, $y1, $x2, $y2, $color); + } + } + + /** + * Returns the img html element or outputs the image to the browser. + * + * @param boolean html output + * @return mixed html string or void + */ + public function image_render($html) + { + // Output html element + if ($html) + return 'Captcha'; + + // Send the correct HTTP header + header('Content-Type: image/'.$this->image_type); + + // Pick the correct output function + $function = 'image'.$this->image_type; + $function($this->image); + + // Free up resources + imagedestroy($this->image); + } + +} // End Captcha Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Captcha/Alpha.php b/lib/kohana/system/libraries/drivers/Captcha/Alpha.php new file mode 100644 index 0000000..2779580 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha/Alpha.php @@ -0,0 +1,92 @@ +image + $this->image_create(Captcha::$config['background']); + + // Add a random gradient + if (empty(Captcha::$config['background'])) + { + $color1 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); + $color2 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); + $this->image_gradient($color1, $color2); + } + + // Add a few random circles + for ($i = 0, $count = mt_rand(10, Captcha::$config['complexity'] * 3); $i < $count; $i++) + { + $color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255), mt_rand(80, 120)); + $size = mt_rand(5, Captcha::$config['height'] / 3); + imagefilledellipse($this->image, mt_rand(0, Captcha::$config['width']), mt_rand(0, Captcha::$config['height']), $size, $size, $color); + } + + // Calculate character font-size and spacing + $default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / strlen($this->response); + $spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response)); + + // Background alphabetic character attributes + $color_limit = mt_rand(96, 160); + $chars = 'ABEFGJKLPQRTVY'; + + // Draw each Captcha character with varying attributes + for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++) + { + // Use different fonts if available + $font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])]; + + $angle = mt_rand(-40, 20); + // Scale the character size on image height + $size = $default_size / 10 * mt_rand(8, 12); + $box = imageftbbox($size, $angle, $font, $this->response[$i]); + + // Calculate character starting coordinates + $x = $spacing / 4 + $i * $spacing; + $y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4; + + // Draw captcha text character + // Allocate random color, size and rotation attributes to text + $color = imagecolorallocate($this->image, mt_rand(150, 255), mt_rand(200, 255), mt_rand(0, 255)); + + // Write text character to image + imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]); + + // Draw "ghost" alphabetic character + $text_color = imagecolorallocatealpha($this->image, mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand(70, 120)); + $char = $chars[mt_rand(0, 14)]; + imagettftext($this->image, $size * 2, mt_rand(-45, 45), ($x - (mt_rand(5, 10))), ($y + (mt_rand(5, 10))), $text_color, $font, $char); + } + + // Output + return $this->image_render($html); + } + +} // End Captcha Alpha Driver Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Captcha/Basic.php b/lib/kohana/system/libraries/drivers/Captcha/Basic.php new file mode 100644 index 0000000..d212e72 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha/Basic.php @@ -0,0 +1,81 @@ +image + $this->image_create(Captcha::$config['background']); + + // Add a random gradient + if (empty(Captcha::$config['background'])) + { + $color1 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255)); + $color2 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255)); + $this->image_gradient($color1, $color2); + } + + // Add a few random lines + for ($i = 0, $count = mt_rand(5, Captcha::$config['complexity'] * 4); $i < $count; $i++) + { + $color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(100, 255), mt_rand(50, 120)); + imageline($this->image, mt_rand(0, Captcha::$config['width']), 0, mt_rand(0, Captcha::$config['width']), Captcha::$config['height'], $color); + } + + // Calculate character font-size and spacing + $default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / (strlen($this->response) + 1); + $spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response)); + + // Draw each Captcha character with varying attributes + for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++) + { + // Use different fonts if available + $font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])]; + + // Allocate random color, size and rotation attributes to text + $color = imagecolorallocate($this->image, mt_rand(0, 150), mt_rand(0, 150), mt_rand(0, 150)); + $angle = mt_rand(-40, 20); + + // Scale the character size on image height + $size = $default_size / 10 * mt_rand(8, 12); + $box = imageftbbox($size, $angle, $font, $this->response[$i]); + + // Calculate character starting coordinates + $x = $spacing / 4 + $i * $spacing; + $y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4; + + // Write text character to image + imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]); + } + + // Output + return $this->image_render($html); + } + +} // End Captcha Basic Driver Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Captcha/Black.php b/lib/kohana/system/libraries/drivers/Captcha/Black.php new file mode 100644 index 0000000..6a2e222 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha/Black.php @@ -0,0 +1,72 @@ +image_create(Captcha::$config['background']); + + // Add random white/gray arcs, amount depends on complexity setting + $count = (Captcha::$config['width'] + Captcha::$config['height']) / 2; + $count = $count / 5 * min(10, Captcha::$config['complexity']); + for ($i = 0; $i < $count; $i++) + { + imagesetthickness($this->image, mt_rand(1, 2)); + $color = imagecolorallocatealpha($this->image, 255, 255, 255, mt_rand(0, 120)); + imagearc($this->image, mt_rand(-Captcha::$config['width'], Captcha::$config['width']), mt_rand(-Captcha::$config['height'], Captcha::$config['height']), mt_rand(-Captcha::$config['width'], Captcha::$config['width']), mt_rand(-Captcha::$config['height'], Captcha::$config['height']), mt_rand(0, 360), mt_rand(0, 360), $color); + } + + // Use different fonts if available + $font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])]; + + // Draw the character's white shadows + $size = (int) min(Captcha::$config['height'] / 2, Captcha::$config['width'] * 0.8 / strlen($this->response)); + $angle = mt_rand(-15 + strlen($this->response), 15 - strlen($this->response)); + $x = mt_rand(1, Captcha::$config['width'] * 0.9 - $size * strlen($this->response)); + $y = ((Captcha::$config['height'] - $size) / 2) + $size; + $color = imagecolorallocate($this->image, 255, 255, 255); + imagefttext($this->image, $size, $angle, $x + 1, $y + 1, $color, $font, $this->response); + + // Add more shadows for lower complexities + (Captcha::$config['complexity'] < 10) and imagefttext($this->image, $size, $angle, $x - 1, $y - 1, $color, $font , $this->response); + (Captcha::$config['complexity'] < 8) and imagefttext($this->image, $size, $angle, $x - 2, $y + 2, $color, $font , $this->response); + (Captcha::$config['complexity'] < 6) and imagefttext($this->image, $size, $angle, $x + 2, $y - 2, $color, $font , $this->response); + (Captcha::$config['complexity'] < 4) and imagefttext($this->image, $size, $angle, $x + 3, $y + 3, $color, $font , $this->response); + (Captcha::$config['complexity'] < 2) and imagefttext($this->image, $size, $angle, $x - 3, $y - 3, $color, $font , $this->response); + + // Finally draw the foreground characters + $color = imagecolorallocate($this->image, 0, 0, 0); + imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response); + + // Output + return $this->image_render($html); + } + +} // End Captcha Black Driver Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Captcha/Math.php b/lib/kohana/system/libraries/drivers/Captcha/Math.php new file mode 100644 index 0000000..4ac2024 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha/Math.php @@ -0,0 +1,61 @@ +math_exercice = implode(' + ', $numbers).' = '; + + // Return the answer + return array_sum($numbers); + } + + /** + * Outputs the Captcha riddle. + * + * @param boolean html output + * @return mixed + */ + public function render($html) + { + return $this->math_exercice; + } + +} // End Captcha Math Driver Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Captcha/Riddle.php b/lib/kohana/system/libraries/drivers/Captcha/Riddle.php new file mode 100644 index 0000000..765eeaa --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha/Riddle.php @@ -0,0 +1,47 @@ +riddle = $riddle[0]; + + // Return the answer + return $riddle[1]; + } + + /** + * Outputs the Captcha riddle. + * + * @param boolean html output + * @return mixed + */ + public function render($html) + { + return $this->riddle; + } + +} // End Captcha Riddle Driver Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Captcha/Word.php b/lib/kohana/system/libraries/drivers/Captcha/Word.php new file mode 100644 index 0000000..856bd9b --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Captcha/Word.php @@ -0,0 +1,37 @@ +escape_table($table).' WHERE '.implode(' ', $where); + } + + /** + * Builds an UPDATE query. + * + * @param string table name + * @param array key => value pairs + * @param array where clause + * @return string + */ + public function update($table, $values, $where) + { + foreach ($values as $key => $val) + { + $valstr[] = $this->escape_column($key).' = '.$val; + } + return 'UPDATE '.$this->escape_table($table).' SET '.implode(', ', $valstr).' WHERE '.implode(' ',$where); + } + + /** + * Set the charset using 'SET NAMES '. + * + * @param string character set to use + */ + public function set_charset($charset) + { + throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); + } + + /** + * Wrap the tablename in backticks, has support for: table.field syntax. + * + * @param string table name + * @return string + */ + abstract public function escape_table($table); + + /** + * Escape a column/field name, has support for special commands. + * + * @param string column name + * @return string + */ + abstract public function escape_column($column); + + /** + * Builds a WHERE portion of a query. + * + * @param mixed key + * @param string value + * @param string type + * @param int number of where clauses + * @param boolean escape the value + * @return string + */ + public function where($key, $value, $type, $num_wheres, $quote) + { + $prefix = ($num_wheres == 0) ? '' : $type; + + if ($quote === -1) + { + $value = ''; + } + else + { + if ($value === NULL) + { + if ( ! $this->has_operator($key)) + { + $key .= ' IS'; + } + + $value = ' NULL'; + } + elseif (is_bool($value)) + { + if ( ! $this->has_operator($key)) + { + $key .= ' ='; + } + + $value = ($value == TRUE) ? ' 1' : ' 0'; + } + else + { + if ( ! $this->has_operator($key) AND ! empty($key)) + { + $key = $this->escape_column($key).' ='; + } + else + { + preg_match('/^(.+?)([<>!=]+|\bIS(?:\s+NULL))\s*$/i', $key, $matches); + if (isset($matches[1]) AND isset($matches[2])) + { + $key = $this->escape_column(trim($matches[1])).' '.trim($matches[2]); + } + } + + $value = ' '.(($quote == TRUE) ? $this->escape($value) : $value); + } + } + + return $prefix.$key.$value; + } + + /** + * Builds a LIKE portion of a query. + * + * @param mixed field name + * @param string value to match with field + * @param boolean add wildcards before and after the match + * @param string clause type (AND or OR) + * @param int number of likes + * @return string + */ + public function like($field, $match, $auto, $type, $num_likes) + { + $prefix = ($num_likes == 0) ? '' : $type; + + $match = $this->escape_str($match); + + if ($auto === TRUE) + { + // Add the start and end quotes + $match = '%'.str_replace('%', '\\%', $match).'%'; + } + + return $prefix.' '.$this->escape_column($field).' LIKE \''.$match . '\''; + } + + /** + * Builds a NOT LIKE portion of a query. + * + * @param mixed field name + * @param string value to match with field + * @param string clause type (AND or OR) + * @param int number of likes + * @return string + */ + public function notlike($field, $match, $auto, $type, $num_likes) + { + $prefix = ($num_likes == 0) ? '' : $type; + + $match = $this->escape_str($match); + + if ($auto === TRUE) + { + // Add the start and end quotes + $match = '%'.$match.'%'; + } + + return $prefix.' '.$this->escape_column($field).' NOT LIKE \''.$match.'\''; + } + + /** + * Builds a REGEX portion of a query. + * + * @param string field name + * @param string value to match with field + * @param string clause type (AND or OR) + * @param integer number of regexes + * @return string + */ + public function regex($field, $match, $type, $num_regexs) + { + throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); + } + + /** + * Builds a NOT REGEX portion of a query. + * + * @param string field name + * @param string value to match with field + * @param string clause type (AND or OR) + * @param integer number of regexes + * @return string + */ + public function notregex($field, $match, $type, $num_regexs) + { + throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); + } + + /** + * Builds an INSERT query. + * + * @param string table name + * @param array keys + * @param array values + * @return string + */ + public function insert($table, $keys, $values) + { + // Escape the column names + foreach ($keys as $key => $value) + { + $keys[$key] = $this->escape_column($value); + } + return 'INSERT INTO '.$this->escape_table($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; + } + + /** + * Builds a MERGE portion of a query. + * + * @param string table name + * @param array keys + * @param array values + * @return string + */ + public function merge($table, $keys, $values) + { + throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); + } + + /** + * Builds a LIMIT portion of a query. + * + * @param integer limit + * @param integer offset + * @return string + */ + abstract public function limit($limit, $offset = 0); + + /** + * Creates a prepared statement. + * + * @param string SQL query + * @return Database_Stmt + */ + public function stmt_prepare($sql = '') + { + throw new Kohana_Database_Exception('database.not_implemented', __FUNCTION__); + } + + /** + * Compiles the SELECT statement. + * Generates a query string based on which functions were used. + * Should not be called directly, the get() function calls it. + * + * @param array select query values + * @return string + */ + abstract public function compile_select($database); + + /** + * Determines if the string has an arithmetic operator in it. + * + * @param string string to check + * @return boolean + */ + public function has_operator($str) + { + return (bool) preg_match('/[<>!=]|\sIS(?:\s+NOT\s+)?\b|BETWEEN/i', trim($str)); + } + + /** + * Escapes any input value. + * + * @param mixed value to escape + * @return string + */ + public function escape($value) + { + if ( ! $this->db_config['escape']) + return $value; + + switch (gettype($value)) + { + case 'string': + $value = '\''.$this->escape_str($value).'\''; + break; + case 'boolean': + $value = (int) $value; + break; + case 'double': + // Convert to non-locale aware float to prevent possible commas + $value = sprintf('%F', $value); + break; + default: + $value = ($value === NULL) ? 'NULL' : $value; + break; + } + + return (string) $value; + } + + /** + * Escapes a string for a query. + * + * @param mixed value to escape + * @return string + */ + abstract public function escape_str($str); + + /** + * Lists all tables in the database. + * + * @return array + */ + abstract public function list_tables(); + + /** + * Lists all fields in a table. + * + * @param string table name + * @return array + */ + abstract function list_fields($table); + + /** + * Returns the last database error. + * + * @return string + */ + abstract public function show_error(); + + /** + * Returns field data about a table. + * + * @param string table name + * @return array + */ + abstract public function field_data($table); + + /** + * Fetches SQL type information about a field, in a generic format. + * + * @param string field datatype + * @return array + */ + protected function sql_type($str) + { + static $sql_types; + + if ($sql_types === NULL) + { + // Load SQL data types + $sql_types = Kohana::config('sql_types'); + } + + $str = strtolower(trim($str)); + + if (($open = strpos($str, '(')) !== FALSE) + { + // Find closing bracket + $close = strpos($str, ')', $open) - 1; + + // Find the type without the size + $type = substr($str, 0, $open); + } + else + { + // No length + $type = $str; + } + + empty($sql_types[$type]) and exit + ( + 'Unknown field type: '.$type.'. '. + 'Please report this: http://trac.kohanaphp.com/newticket' + ); + + // Fetch the field definition + $field = $sql_types[$type]; + + switch ($field['type']) + { + case 'string': + case 'float': + if (isset($close)) + { + // Add the length to the field info + $field['length'] = substr($str, $open + 1, $close - $open); + } + break; + case 'int': + // Add unsigned value + $field['unsigned'] = (strpos($str, 'unsigned') !== FALSE); + break; + } + + return $field; + } + + /** + * Clears the internal query cache. + * + * @param string SQL query + */ + public function clear_cache($sql = NULL) + { + if (empty($sql)) + { + $this->query_cache = array(); + } + else + { + unset($this->query_cache[$this->query_hash($sql)]); + } + + Kohana::log('debug', 'Database cache cleared: '.get_class($this)); + } + + /** + * Creates a hash for an SQL query string. Replaces newlines with spaces, + * trims, and hashes. + * + * @param string SQL query + * @return string + */ + protected function query_hash($sql) + { + return sha1(str_replace("\n", ' ', trim($sql))); + } + +} // End Database Driver Interface + +/** + * Database_Result + * + */ +abstract class Database_Result implements ArrayAccess, Iterator, Countable { + + // Result resource, insert id, and SQL + protected $result; + protected $insert_id; + protected $sql; + + // Current and total rows + protected $current_row = 0; + protected $total_rows = 0; + + // Fetch function and return type + protected $fetch_type; + protected $return_type; + + /** + * Returns the SQL used to fetch the result. + * + * @return string + */ + public function sql() + { + return $this->sql; + } + + /** + * Returns the insert id from the result. + * + * @return mixed + */ + public function insert_id() + { + return $this->insert_id; + } + + /** + * Prepares the query result. + * + * @param boolean return rows as objects + * @param mixed type + * @return Database_Result + */ + abstract function result($object = TRUE, $type = FALSE); + + /** + * Builds an array of query results. + * + * @param boolean return rows as objects + * @param mixed type + * @return array + */ + abstract function result_array($object = NULL, $type = FALSE); + + /** + * Gets the fields of an already run query. + * + * @return array + */ + abstract public function list_fields(); + + /** + * Seek to an offset in the results. + * + * @return boolean + */ + abstract public function seek($offset); + + /** + * Countable: count + */ + public function count() + { + return $this->total_rows; + } + + /** + * ArrayAccess: offsetExists + */ + public function offsetExists($offset) + { + if ($this->total_rows > 0) + { + $min = 0; + $max = $this->total_rows - 1; + + return ! ($offset < $min OR $offset > $max); + } + + return FALSE; + } + + /** + * ArrayAccess: offsetGet + */ + public function offsetGet($offset) + { + if ( ! $this->seek($offset)) + return FALSE; + + // Return the row by calling the defined fetching callback + return call_user_func($this->fetch_type, $this->result, $this->return_type); + } + + /** + * ArrayAccess: offsetSet + * + * @throws Kohana_Database_Exception + */ + final public function offsetSet($offset, $value) + { + throw new Kohana_Database_Exception('database.result_read_only'); + } + + /** + * ArrayAccess: offsetUnset + * + * @throws Kohana_Database_Exception + */ + final public function offsetUnset($offset) + { + throw new Kohana_Database_Exception('database.result_read_only'); + } + + /** + * Iterator: current + */ + public function current() + { + return $this->offsetGet($this->current_row); + } + + /** + * Iterator: key + */ + public function key() + { + return $this->current_row; + } + + /** + * Iterator: next + */ + public function next() + { + ++$this->current_row; + return $this; + } + + /** + * Iterator: prev + */ + public function prev() + { + --$this->current_row; + return $this; + } + + /** + * Iterator: rewind + */ + public function rewind() + { + $this->current_row = 0; + return $this; + } + + /** + * Iterator: valid + */ + public function valid() + { + return $this->offsetExists($this->current_row); + } + +} // End Database Result Interface diff --git a/lib/kohana/system/libraries/drivers/Database/Mssql.php b/lib/kohana/system/libraries/drivers/Database/Mssql.php new file mode 100644 index 0000000..8b5ed50 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Database/Mssql.php @@ -0,0 +1,462 @@ +db_config = $config; + + Kohana::log('debug', 'MSSQL Database Driver Initialized'); + } + + /** + * Closes the database connection. + */ + public function __destruct() + { + is_resource($this->link) and mssql_close($this->link); + } + + /** + * Make the connection + * + * @return return connection + */ + public function connect() + { + // Check if link already exists + if (is_resource($this->link)) + return $this->link; + + // Import the connect variables + extract($this->db_config['connection']); + + // Persistent connections enabled? + $connect = ($this->db_config['persistent'] == TRUE) ? 'mssql_pconnect' : 'mssql_connect'; + + // Build the connection info + $host = isset($host) ? $host : $socket; + + // Windows uses a comma instead of a colon + $port = (isset($port) AND is_string($port)) ? (KOHANA_IS_WIN ? ',' : ':').$port : ''; + + // Make the connection and select the database + if (($this->link = $connect($host.$port, $user, $pass, TRUE)) AND mssql_select_db($database, $this->link)) + { + /* This is being removed so I can use it, will need to come up with a more elegant workaround in the future... + * + if ($charset = $this->db_config['character_set']) + { + $this->set_charset($charset); + } + */ + + // Clear password after successful connect + $this->db_config['connection']['pass'] = NULL; + + return $this->link; + } + + return FALSE; + } + + public function query($sql) + { + // Only cache if it's turned on, and only cache if it's not a write statement + if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET)\b#i', $sql)) + { + $hash = $this->query_hash($sql); + + if ( ! isset($this->query_cache[$hash])) + { + // Set the cached object + $this->query_cache[$hash] = new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql); + } + else + { + // Rewind cached result + $this->query_cache[$hash]->rewind(); + } + + // Return the cached query + return $this->query_cache[$hash]; + } + + return new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql); + } + + public function escape_table($table) + { + if (stripos($table, ' AS ') !== FALSE) + { + // Force 'AS' to uppercase + $table = str_ireplace(' AS ', ' AS ', $table); + + // Runs escape_table on both sides of an AS statement + $table = array_map(array($this, __FUNCTION__), explode(' AS ', $table)); + + // Re-create the AS statement + return implode(' AS ', $table); + } + return '['.str_replace('.', '[.]', $table).']'; + } + + public function escape_column($column) + { + if (!$this->db_config['escape']) + return $column; + + if ($column == '*') + return $column; + + // This matches any functions we support to SELECT. + if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) + { + if ( count($matches) == 3) + { + return $matches[1].'('.$this->escape_column($matches[2]).')'; + } + else if ( count($matches) == 5) + { + return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]); + } + } + + // This matches any modifiers we support to SELECT. + if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) + { + if (stripos($column, ' AS ') !== FALSE) + { + // Force 'AS' to uppercase + $column = str_ireplace(' AS ', ' AS ', $column); + + // Runs escape_column on both sides of an AS statement + $column = array_map(array($this, __FUNCTION__), explode(' AS ', $column)); + + // Re-create the AS statement + return implode(' AS ', $column); + } + + return preg_replace('/[^.*]+/', '[$0]', $column); + } + + $parts = explode(' ', $column); + $column = ''; + + for ($i = 0, $c = count($parts); $i < $c; $i++) + { + // The column is always last + if ($i == ($c - 1)) + { + $column .= preg_replace('/[^.*]+/', '[$0]', $parts[$i]); + } + else // otherwise, it's a modifier + { + $column .= $parts[$i].' '; + } + } + return $column; + } + + /** + * Limit in SQL Server 2000 only uses the keyword + * 'TOP'; 2007 may have an offset keyword, but + * I am unsure - for pagination style limit,offset + * functionality, a fancy query needs to be built. + * + * @param unknown_type $limit + * @return unknown + */ + public function limit($limit, $offset=null) + { + return 'TOP '.$limit; + } + + public function compile_select($database) + { + $sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT '; + $sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*'; + + if (count($database['from']) > 0) + { + // Escape the tables + $froms = array(); + foreach ($database['from'] as $from) + $froms[] = $this->escape_column($from); + $sql .= "\nFROM "; + $sql .= implode(', ', $froms); + } + + if (count($database['join']) > 0) + { + foreach($database['join'] AS $join) + { + $sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions']; + } + } + + if (count($database['where']) > 0) + { + $sql .= "\nWHERE "; + } + + $sql .= implode("\n", $database['where']); + + if (count($database['groupby']) > 0) + { + $sql .= "\nGROUP BY "; + $sql .= implode(', ', $database['groupby']); + } + + if (count($database['having']) > 0) + { + $sql .= "\nHAVING "; + $sql .= implode("\n", $database['having']); + } + + if (count($database['orderby']) > 0) + { + $sql .= "\nORDER BY "; + $sql .= implode(', ', $database['orderby']); + } + + if (is_numeric($database['limit'])) + { + $sql .= "\n"; + $sql .= $this->limit($database['limit']); + } + + return $sql; + } + + public function escape_str($str) + { + if (!$this->db_config['escape']) + return $str; + + is_resource($this->link) or $this->connect(); + //mssql_real_escape_string($str, $this->link); <-- this function doesn't exist + + $characters = array('/\x00/', '/\x1a/', '/\n/', '/\r/', '/\\\/', '/\'/'); + $replace = array('\\\x00', '\\x1a', '\\n', '\\r', '\\\\', "''"); + return preg_replace($characters, $replace, $str); + } + + public function list_tables() + { + $sql = 'SHOW TABLES FROM ['.$this->db_config['connection']['database'].']'; + $result = $this->query($sql)->result(FALSE, MSSQL_ASSOC); + + $retval = array(); + foreach ($result as $row) + { + $retval[] = current($row); + } + + return $retval; + } + + public function show_error() + { + return mssql_get_last_message($this->link); + } + + public function list_fields($table) + { + $result = array(); + + foreach ($this->field_data($table) as $row) + { + // Make an associative array + $result[$row->Field] = $this->sql_type($row->Type); + } + + return $result; + } + + public function field_data($table) + { + $query = $this->query("SELECT COLUMN_NAME AS Field, DATA_TYPE as Type FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->escape_table($table)."'", $this->link); + + return $query->result_array(TRUE); + } +} + +/** + * MSSQL Result + */ +class Mssql_Result extends Database_Result { + + // Fetch function and return type + protected $fetch_type = 'mssql_fetch_object'; + protected $return_type = MSSQL_ASSOC; + + /** + * Sets up the result variables. + * + * @param resource query result + * @param resource database link + * @param boolean return objects or arrays + * @param string SQL query that was run + */ + public function __construct($result, $link, $object = TRUE, $sql) + { + $this->result = $result; + + // If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query + if (is_resource($result)) + { + $this->current_row = 0; + $this->total_rows = mssql_num_rows($this->result); + $this->fetch_type = ($object === TRUE) ? 'mssql_fetch_object' : 'mssql_fetch_array'; + } + elseif (is_bool($result)) + { + if ($result == FALSE) + { + // SQL error + throw new Kohana_Database_Exception('database.error', mssql_get_last_message($link).' - '.$sql); + } + else + { + // Its an DELETE, INSERT, REPLACE, or UPDATE querys + $last_id = mssql_query('SELECT @@IDENTITY AS last_id', $link); + $result = mssql_fetch_assoc($last_id); + $this->insert_id = $result['last_id']; + $this->total_rows = mssql_rows_affected($link); + } + } + + // Set result type + $this->result($object); + + // Store the SQL + $this->sql = $sql; + } + + /** + * Destruct, the cleanup crew! + */ + public function __destruct() + { + if (is_resource($this->result)) + { + mssql_free_result($this->result); + } + } + + public function result($object = TRUE, $type = MSSQL_ASSOC) + { + $this->fetch_type = ((bool) $object) ? 'mssql_fetch_object' : 'mssql_fetch_array'; + + // This check has to be outside the previous statement, because we do not + // know the state of fetch_type when $object = NULL + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + if ($this->fetch_type == 'mssql_fetch_object') + { + $this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $this->return_type = $type; + } + + return $this; + } + + public function as_array($object = NULL, $type = MSSQL_ASSOC) + { + return $this->result_array($object, $type); + } + + public function result_array($object = NULL, $type = MSSQL_ASSOC) + { + $rows = array(); + + if (is_string($object)) + { + $fetch = $object; + } + elseif (is_bool($object)) + { + if ($object === TRUE) + { + $fetch = 'mssql_fetch_object'; + + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $fetch = 'mssql_fetch_array'; + } + } + else + { + // Use the default config values + $fetch = $this->fetch_type; + + if ($fetch == 'mssql_fetch_object') + { + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + } + + if (mssql_num_rows($this->result)) + { + // Reset the pointer location to make sure things work properly + mssql_data_seek($this->result, 0); + + while ($row = $fetch($this->result, $type)) + { + $rows[] = $row; + } + } + + return isset($rows) ? $rows : array(); + } + + public function list_fields() + { + $field_names = array(); + while ($field = mssql_fetch_field($this->result)) + { + $field_names[] = $field->name; + } + + return $field_names; + } + + public function seek($offset) + { + if ( ! $this->offsetExists($offset)) + return FALSE; + + return mssql_data_seek($this->result, $offset); + } + +} // End mssql_Result Class diff --git a/lib/kohana/system/libraries/drivers/Database/Mysql.php b/lib/kohana/system/libraries/drivers/Database/Mysql.php new file mode 100644 index 0000000..d5222f5 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Database/Mysql.php @@ -0,0 +1,496 @@ +db_config = $config; + + Kohana::log('debug', 'MySQL Database Driver Initialized'); + } + + /** + * Closes the database connection. + */ + public function __destruct() + { + is_resource($this->link) and mysql_close($this->link); + } + + public function connect() + { + // Check if link already exists + if (is_resource($this->link)) + return $this->link; + + // Import the connect variables + extract($this->db_config['connection']); + + // Persistent connections enabled? + $connect = ($this->db_config['persistent'] == TRUE) ? 'mysql_pconnect' : 'mysql_connect'; + + // Build the connection info + $host = isset($host) ? $host : $socket; + $port = isset($port) ? ':'.$port : ''; + + // Make the connection and select the database + if (($this->link = $connect($host.$port, $user, $pass, TRUE)) AND mysql_select_db($database, $this->link)) + { + if ($charset = $this->db_config['character_set']) + { + $this->set_charset($charset); + } + + // Clear password after successful connect + $this->db_config['connection']['pass'] = NULL; + + return $this->link; + } + + return FALSE; + } + + public function query($sql) + { + // Only cache if it's turned on, and only cache if it's not a write statement + if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql)) + { + $hash = $this->query_hash($sql); + + if ( ! isset($this->query_cache[$hash])) + { + // Set the cached object + $this->query_cache[$hash] = new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql); + } + else + { + // Rewind cached result + $this->query_cache[$hash]->rewind(); + } + + // Return the cached query + return $this->query_cache[$hash]; + } + + return new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql); + } + + public function set_charset($charset) + { + $this->query('SET NAMES '.$this->escape_str($charset)); + } + + public function escape_table($table) + { + if (!$this->db_config['escape']) + return $table; + + if (stripos($table, ' AS ') !== FALSE) + { + // Force 'AS' to uppercase + $table = str_ireplace(' AS ', ' AS ', $table); + + // Runs escape_table on both sides of an AS statement + $table = array_map(array($this, __FUNCTION__), explode(' AS ', $table)); + + // Re-create the AS statement + return implode(' AS ', $table); + } + return '`'.str_replace('.', '`.`', $table).'`'; + } + + public function escape_column($column) + { + if (!$this->db_config['escape']) + return $column; + + if ($column == '*') + return $column; + + // This matches any functions we support to SELECT. + if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) + { + if ( count($matches) == 3) + { + return $matches[1].'('.$this->escape_column($matches[2]).')'; + } + else if ( count($matches) == 5) + { + return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]); + } + } + + // This matches any modifiers we support to SELECT. + if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) + { + if (stripos($column, ' AS ') !== FALSE) + { + // Force 'AS' to uppercase + $column = str_ireplace(' AS ', ' AS ', $column); + + // Runs escape_column on both sides of an AS statement + $column = array_map(array($this, __FUNCTION__), explode(' AS ', $column)); + + // Re-create the AS statement + return implode(' AS ', $column); + } + + return preg_replace('/[^.*]+/', '`$0`', $column); + } + + $parts = explode(' ', $column); + $column = ''; + + for ($i = 0, $c = count($parts); $i < $c; $i++) + { + // The column is always last + if ($i == ($c - 1)) + { + $column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]); + } + else // otherwise, it's a modifier + { + $column .= $parts[$i].' '; + } + } + return $column; + } + + public function regex($field, $match, $type, $num_regexs) + { + $prefix = ($num_regexs == 0) ? '' : $type; + + return $prefix.' '.$this->escape_column($field).' REGEXP \''.$this->escape_str($match).'\''; + } + + public function notregex($field, $match, $type, $num_regexs) + { + $prefix = $num_regexs == 0 ? '' : $type; + + return $prefix.' '.$this->escape_column($field).' NOT REGEXP \''.$this->escape_str($match) . '\''; + } + + public function merge($table, $keys, $values) + { + // Escape the column names + foreach ($keys as $key => $value) + { + $keys[$key] = $this->escape_column($value); + } + return 'REPLACE INTO '.$this->escape_table($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; + } + + public function limit($limit, $offset = 0) + { + return 'LIMIT '.$offset.', '.$limit; + } + + public function compile_select($database) + { + $sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT '; + $sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*'; + + if (count($database['from']) > 0) + { + // Escape the tables + $froms = array(); + foreach ($database['from'] as $from) + { + $froms[] = $this->escape_column($from); + } + $sql .= "\nFROM ("; + $sql .= implode(', ', $froms).")"; + } + + if (count($database['join']) > 0) + { + foreach($database['join'] AS $join) + { + $sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions']; + } + } + + if (count($database['where']) > 0) + { + $sql .= "\nWHERE "; + } + + $sql .= implode("\n", $database['where']); + + if (count($database['groupby']) > 0) + { + $sql .= "\nGROUP BY "; + $sql .= implode(', ', $database['groupby']); + } + + if (count($database['having']) > 0) + { + $sql .= "\nHAVING "; + $sql .= implode("\n", $database['having']); + } + + if (count($database['orderby']) > 0) + { + $sql .= "\nORDER BY "; + $sql .= implode(', ', $database['orderby']); + } + + if (is_numeric($database['limit'])) + { + $sql .= "\n"; + $sql .= $this->limit($database['limit'], $database['offset']); + } + + return $sql; + } + + public function escape_str($str) + { + if (!$this->db_config['escape']) + return $str; + + is_resource($this->link) or $this->connect(); + + return mysql_real_escape_string($str, $this->link); + } + + public function list_tables() + { + $tables = array(); + + if ($query = $this->query('SHOW TABLES FROM '.$this->escape_table($this->db_config['connection']['database']))) + { + foreach ($query->result(FALSE) as $row) + { + $tables[] = current($row); + } + } + + return $tables; + } + + public function show_error() + { + return mysql_error($this->link); + } + + public function list_fields($table) + { + $result = NULL; + + foreach ($this->field_data($table) as $row) + { + // Make an associative array + $result[$row->Field] = $this->sql_type($row->Type); + + if ($row->Key === 'PRI' AND $row->Extra === 'auto_increment') + { + // For sequenced (AUTO_INCREMENT) tables + $result[$row->Field]['sequenced'] = TRUE; + } + + if ($row->Null === 'YES') + { + // Set NULL status + $result[$row->Field]['null'] = TRUE; + } + } + + if (!isset($result)) + throw new Kohana_Database_Exception('database.table_not_found', $table); + + return $result; + } + + public function field_data($table) + { + $result = $this->query('SHOW COLUMNS FROM '.$this->escape_table($table)); + + return $result->result_array(TRUE); + } + +} // End Database_Mysql_Driver Class + +/** + * MySQL Result + */ +class Mysql_Result extends Database_Result { + + // Fetch function and return type + protected $fetch_type = 'mysql_fetch_object'; + protected $return_type = MYSQL_ASSOC; + + /** + * Sets up the result variables. + * + * @param resource query result + * @param resource database link + * @param boolean return objects or arrays + * @param string SQL query that was run + */ + public function __construct($result, $link, $object = TRUE, $sql) + { + $this->result = $result; + + // If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query + if (is_resource($result)) + { + $this->current_row = 0; + $this->total_rows = mysql_num_rows($this->result); + $this->fetch_type = ($object === TRUE) ? 'mysql_fetch_object' : 'mysql_fetch_array'; + } + elseif (is_bool($result)) + { + if ($result == FALSE) + { + // SQL error + throw new Kohana_Database_Exception('database.error', mysql_error($link).' - '.$sql); + } + else + { + // Its an DELETE, INSERT, REPLACE, or UPDATE query + $this->insert_id = mysql_insert_id($link); + $this->total_rows = mysql_affected_rows($link); + } + } + + // Set result type + $this->result($object); + + // Store the SQL + $this->sql = $sql; + } + + /** + * Destruct, the cleanup crew! + */ + public function __destruct() + { + if (is_resource($this->result)) + { + mysql_free_result($this->result); + } + } + + public function result($object = TRUE, $type = MYSQL_ASSOC) + { + $this->fetch_type = ((bool) $object) ? 'mysql_fetch_object' : 'mysql_fetch_array'; + + // This check has to be outside the previous statement, because we do not + // know the state of fetch_type when $object = NULL + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + if ($this->fetch_type == 'mysql_fetch_object' AND $object === TRUE) + { + $this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $this->return_type = $type; + } + + return $this; + } + + public function as_array($object = NULL, $type = MYSQL_ASSOC) + { + return $this->result_array($object, $type); + } + + public function result_array($object = NULL, $type = MYSQL_ASSOC) + { + $rows = array(); + + if (is_string($object)) + { + $fetch = $object; + } + elseif (is_bool($object)) + { + if ($object === TRUE) + { + $fetch = 'mysql_fetch_object'; + + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $fetch = 'mysql_fetch_array'; + } + } + else + { + // Use the default config values + $fetch = $this->fetch_type; + + if ($fetch == 'mysql_fetch_object') + { + $type = (is_string($this->return_type) AND Kohana::auto_load($this->return_type)) ? $this->return_type : 'stdClass'; + } + } + + if (mysql_num_rows($this->result)) + { + // Reset the pointer location to make sure things work properly + mysql_data_seek($this->result, 0); + + while ($row = $fetch($this->result, $type)) + { + $rows[] = $row; + } + } + + return isset($rows) ? $rows : array(); + } + + public function list_fields() + { + $field_names = array(); + while ($field = mysql_fetch_field($this->result)) + { + $field_names[] = $field->name; + } + + return $field_names; + } + + public function seek($offset) + { + if ($this->offsetExists($offset) AND mysql_data_seek($this->result, $offset)) + { + // Set the current row to the offset + $this->current_row = $offset; + + return TRUE; + } + else + { + return FALSE; + } + } + +} // End Mysql_Result Class diff --git a/lib/kohana/system/libraries/drivers/Database/Mysqli.php b/lib/kohana/system/libraries/drivers/Database/Mysqli.php new file mode 100644 index 0000000..0dd9f05 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Database/Mysqli.php @@ -0,0 +1,358 @@ +db_config = $config; + + Kohana::log('debug', 'MySQLi Database Driver Initialized'); + } + + /** + * Closes the database connection. + */ + public function __destruct() + { + is_object($this->link) and $this->link->close(); + } + + public function connect() + { + // Check if link already exists + if (is_object($this->link)) + return $this->link; + + // Import the connect variables + extract($this->db_config['connection']); + + // Build the connection info + $host = isset($host) ? $host : $socket; + + // Make the connection and select the database + if ($this->link = new mysqli($host, $user, $pass, $database, $port)) + { + if ($charset = $this->db_config['character_set']) + { + $this->set_charset($charset); + } + + // Clear password after successful connect + $this->db_config['connection']['pass'] = NULL; + + return $this->link; + } + + return FALSE; + } + + public function query($sql) + { + // Only cache if it's turned on, and only cache if it's not a write statement + if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql)) + { + $hash = $this->query_hash($sql); + + if ( ! isset($this->query_cache[$hash])) + { + // Set the cached object + $this->query_cache[$hash] = new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql); + } + else + { + // Rewind cached result + $this->query_cache[$hash]->rewind(); + } + + // Return the cached query + return $this->query_cache[$hash]; + } + + return new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql); + } + + public function set_charset($charset) + { + if ($this->link->set_charset($charset) === FALSE) + throw new Kohana_Database_Exception('database.error', $this->show_error()); + } + + public function escape_str($str) + { + if (!$this->db_config['escape']) + return $str; + + is_object($this->link) or $this->connect(); + + return $this->link->real_escape_string($str); + } + + public function show_error() + { + return $this->link->error; + } + +} // End Database_Mysqli_Driver Class + +/** + * MySQLi Result + */ +class Kohana_Mysqli_Result extends Database_Result { + + // Database connection + protected $link; + + // Data fetching types + protected $fetch_type = 'mysqli_fetch_object'; + protected $return_type = MYSQLI_ASSOC; + + /** + * Sets up the result variables. + * + * @param object database link + * @param boolean return objects or arrays + * @param string SQL query that was run + */ + public function __construct($link, $object = TRUE, $sql) + { + $this->link = $link; + + if ( ! $this->link->multi_query($sql)) + { + // SQL error + throw new Kohana_Database_Exception('database.error', $this->link->error.' - '.$sql); + } + else + { + $this->result = $this->link->store_result(); + + // If the query is an object, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query + if (is_object($this->result)) + { + $this->current_row = 0; + $this->total_rows = $this->result->num_rows; + $this->fetch_type = ($object === TRUE) ? 'fetch_object' : 'fetch_array'; + } + elseif ($this->link->error) + { + // SQL error + throw new Kohana_Database_Exception('database.error', $this->link->error.' - '.$sql); + } + else + { + // Its an DELETE, INSERT, REPLACE, or UPDATE query + $this->insert_id = $this->link->insert_id; + $this->total_rows = $this->link->affected_rows; + } + } + + // Set result type + $this->result($object); + + // Store the SQL + $this->sql = $sql; + } + + /** + * Magic __destruct function, frees the result. + */ + public function __destruct() + { + if (is_object($this->result)) + { + $this->result->free_result(); + + // this is kinda useless, but needs to be done to avoid the "Commands out of sync; you + // can't run this command now" error. Basically, we get all results after the first one + // (the one we actually need) and free them. + if (is_resource($this->link) AND $this->link->more_results()) + { + do + { + if ($result = $this->link->store_result()) + { + $result->free_result(); + } + } while ($this->link->next_result()); + } + } + } + + public function result($object = TRUE, $type = MYSQLI_ASSOC) + { + $this->fetch_type = ((bool) $object) ? 'fetch_object' : 'fetch_array'; + + // This check has to be outside the previous statement, because we do not + // know the state of fetch_type when $object = NULL + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + if ($this->fetch_type == 'fetch_object') + { + $this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $this->return_type = $type; + } + + return $this; + } + + public function as_array($object = NULL, $type = MYSQLI_ASSOC) + { + return $this->result_array($object, $type); + } + + public function result_array($object = NULL, $type = MYSQLI_ASSOC) + { + $rows = array(); + + if (is_string($object)) + { + $fetch = $object; + } + elseif (is_bool($object)) + { + if ($object === TRUE) + { + $fetch = 'fetch_object'; + + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $fetch = 'fetch_array'; + } + } + else + { + // Use the default config values + $fetch = $this->fetch_type; + + if ($fetch == 'fetch_object') + { + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + } + + if ($this->result->num_rows) + { + // Reset the pointer location to make sure things work properly + $this->result->data_seek(0); + + while ($row = $this->result->$fetch($type)) + { + $rows[] = $row; + } + } + + return isset($rows) ? $rows : array(); + } + + public function list_fields() + { + $field_names = array(); + while ($field = $this->result->fetch_field()) + { + $field_names[] = $field->name; + } + + return $field_names; + } + + public function seek($offset) + { + if ($this->offsetExists($offset) AND $this->result->data_seek($offset)) + { + // Set the current row to the offset + $this->current_row = $offset; + + return TRUE; + } + + return FALSE; + } + + public function offsetGet($offset) + { + if ( ! $this->seek($offset)) + return FALSE; + + // Return the row + $fetch = $this->fetch_type; + return $this->result->$fetch($this->return_type); + } + +} // End Mysqli_Result Class + +/** + * MySQLi Prepared Statement (experimental) + */ +class Kohana_Mysqli_Statement { + + protected $link = NULL; + protected $stmt; + protected $var_names = array(); + protected $var_values = array(); + + public function __construct($sql, $link) + { + $this->link = $link; + + $this->stmt = $this->link->prepare($sql); + + return $this; + } + + public function __destruct() + { + $this->stmt->close(); + } + + // Sets the bind parameters + public function bind_params($param_types, $params) + { + $this->var_names = array_keys($params); + $this->var_values = array_values($params); + call_user_func_array(array($this->stmt, 'bind_param'), array_merge($param_types, $var_names)); + + return $this; + } + + public function bind_result($params) + { + call_user_func_array(array($this->stmt, 'bind_result'), $params); + } + + // Runs the statement + public function execute() + { + foreach ($this->var_names as $key => $name) + { + $$name = $this->var_values[$key]; + } + $this->stmt->execute(); + return $this->stmt; + } +} diff --git a/lib/kohana/system/libraries/drivers/Database/Pdosqlite.php b/lib/kohana/system/libraries/drivers/Database/Pdosqlite.php new file mode 100644 index 0000000..c2d1bb2 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Database/Pdosqlite.php @@ -0,0 +1,486 @@ + + */ + +class Database_Pdosqlite_Driver extends Database_Driver { + + // Database connection link + protected $link; + protected $db_config; + + /* + * Constructor: __construct + * Sets up the config for the class. + * + * Parameters: + * config - database configuration + * + */ + public function __construct($config) + { + $this->db_config = $config; + + Kohana::log('debug', 'PDO:Sqlite Database Driver Initialized'); + } + + public function connect() + { + // Import the connect variables + extract($this->db_config['connection']); + + try + { + $this->link = new PDO('sqlite:'.$socket.$database, $user, $pass, + array(PDO::ATTR_PERSISTENT => $this->db_config['persistent'])); + + $this->link->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); + //$this->link->query('PRAGMA count_changes=1;'); + + if ($charset = $this->db_config['character_set']) + { + $this->set_charset($charset); + } + } + catch (PDOException $e) + { + throw new Kohana_Database_Exception('database.error', $e->getMessage()); + } + + // Clear password after successful connect + $this->db_config['connection']['pass'] = NULL; + + return $this->link; + } + + public function query($sql) + { + try + { + $sth = $this->link->prepare($sql); + } + catch (PDOException $e) + { + throw new Kohana_Database_Exception('database.error', $e->getMessage()); + } + return new Pdosqlite_Result($sth, $this->link, $this->db_config['object'], $sql); + } + + public function set_charset($charset) + { + $this->link->query('PRAGMA encoding = '.$this->escape_str($charset)); + } + + public function escape_table($table) + { + if ( ! $this->db_config['escape']) + return $table; + + return '`'.str_replace('.', '`.`', $table).'`'; + } + + public function escape_column($column) + { + if ( ! $this->db_config['escape']) + return $column; + + if ($column == '*') + return $column; + + // This matches any functions we support to SELECT. + if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) + { + if ( count($matches) == 3) + { + return $matches[1].'('.$this->escape_column($matches[2]).')'; + } + else if ( count($matches) == 5) + { + return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]); + } + } + + // This matches any modifiers we support to SELECT. + if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) + { + if (stripos($column, ' AS ') !== FALSE) + { + // Force 'AS' to uppercase + $column = str_ireplace(' AS ', ' AS ', $column); + + // Runs escape_column on both sides of an AS statement + $column = array_map(array($this, __FUNCTION__), explode(' AS ', $column)); + + // Re-create the AS statement + return implode(' AS ', $column); + } + + return preg_replace('/[^.*]+/', '`$0`', $column); + } + + $parts = explode(' ', $column); + $column = ''; + + for ($i = 0, $c = count($parts); $i < $c; $i++) + { + // The column is always last + if ($i == ($c - 1)) + { + $column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]); + } + else // otherwise, it's a modifier + { + $column .= $parts[$i].' '; + } + } + return $column; + } + + public function limit($limit, $offset = 0) + { + return 'LIMIT '.$offset.', '.$limit; + } + + public function compile_select($database) + { + $sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT '; + $sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*'; + + if (count($database['from']) > 0) + { + $sql .= "\nFROM "; + $sql .= implode(', ', $database['from']); + } + + if (count($database['join']) > 0) + { + foreach($database['join'] AS $join) + { + $sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions']; + } + } + + if (count($database['where']) > 0) + { + $sql .= "\nWHERE "; + } + + $sql .= implode("\n", $database['where']); + + if (count($database['groupby']) > 0) + { + $sql .= "\nGROUP BY "; + $sql .= implode(', ', $database['groupby']); + } + + if (count($database['having']) > 0) + { + $sql .= "\nHAVING "; + $sql .= implode("\n", $database['having']); + } + + if (count($database['orderby']) > 0) + { + $sql .= "\nORDER BY "; + $sql .= implode(', ', $database['orderby']); + } + + if (is_numeric($database['limit'])) + { + $sql .= "\n"; + $sql .= $this->limit($database['limit'], $database['offset']); + } + + return $sql; + } + + public function escape_str($str) + { + if ( ! $this->db_config['escape']) + return $str; + + if (function_exists('sqlite_escape_string')) + { + $res = sqlite_escape_string($str); + } + else + { + $res = str_replace("'", "''", $str); + } + return $res; + } + + public function list_tables() + { + $sql = "SELECT `name` FROM `sqlite_master` WHERE `type`='table' ORDER BY `name`;"; + try + { + $result = $this->query($sql)->result(FALSE, PDO::FETCH_ASSOC); + $tables = array(); + foreach ($result as $row) + { + $tables[] = current($row); + } + } + catch (PDOException $e) + { + throw new Kohana_Database_Exception('database.error', $e->getMessage()); + } + return $tables; + } + + public function show_error() + { + $err = $this->link->errorInfo(); + return isset($err[2]) ? $err[2] : 'Unknown error!'; + } + + public function list_fields($table, $query = FALSE) + { + static $tables; + if (is_object($query)) + { + if (empty($tables[$table])) + { + $tables[$table] = array(); + + foreach ($query->result() as $row) + { + $tables[$table][] = $row->name; + } + } + + return $tables[$table]; + } + else + { + $result = $this->link->query( 'PRAGMA table_info('.$this->escape_table($table).')' ); + + foreach ($result as $row) + { + $tables[$table][$row['name']] = $this->sql_type($row['type']); + } + + return $tables[$table]; + } + } + + public function field_data($table) + { + Kohana::log('error', 'This method is under developing'); + } + /** + * Version number query string + * + * @access public + * @return string + */ + function version() + { + return $this->link->getAttribute(constant("PDO::ATTR_SERVER_VERSION")); + } + +} // End Database_PdoSqlite_Driver Class + +/* + * PDO-sqlite Result + */ +class Pdosqlite_Result extends Database_Result { + + // Data fetching types + protected $fetch_type = PDO::FETCH_OBJ; + protected $return_type = PDO::FETCH_ASSOC; + + /** + * Sets up the result variables. + * + * @param resource query result + * @param resource database link + * @param boolean return objects or arrays + * @param string SQL query that was run + */ + public function __construct($result, $link, $object = TRUE, $sql) + { + if (is_object($result) OR $result = $link->prepare($sql)) + { + // run the query. Return true if success, false otherwise + if( ! $result->execute()) + { + // Throw Kohana Exception with error message. See PDOStatement errorInfo() method + $arr_infos = $result->errorInfo(); + throw new Kohana_Database_Exception('database.error', $arr_infos[2]); + } + + if (preg_match('/^SELECT|PRAGMA|EXPLAIN/i', $sql)) + { + $this->result = $result; + $this->current_row = 0; + + $this->total_rows = $this->sqlite_row_count(); + + $this->fetch_type = ($object === TRUE) ? PDO::FETCH_OBJ : PDO::FETCH_ASSOC; + } + elseif (preg_match('/^DELETE|INSERT|UPDATE/i', $sql)) + { + $this->insert_id = $link->lastInsertId(); + + $this->total_rows = $result->rowCount(); + } + } + else + { + // SQL error + throw new Kohana_Database_Exception('database.error', $link->errorInfo().' - '.$sql); + } + + // Set result type + $this->result($object); + + // Store the SQL + $this->sql = $sql; + } + + private function sqlite_row_count() + { + $count = 0; + while ($this->result->fetch()) + { + $count++; + } + + // The query must be re-fetched now. + $this->result->execute(); + + return $count; + } + + /* + * Destructor: __destruct + * Magic __destruct function, frees the result. + */ + public function __destruct() + { + if (is_object($this->result)) + { + $this->result->closeCursor(); + $this->result = NULL; + } + } + + public function result($object = TRUE, $type = PDO::FETCH_BOTH) + { + $this->fetch_type = (bool) $object ? PDO::FETCH_OBJ : PDO::FETCH_BOTH; + + if ($this->fetch_type == PDO::FETCH_OBJ) + { + $this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $this->return_type = $type; + } + + return $this; + } + + public function as_array($object = NULL, $type = PDO::FETCH_ASSOC) + { + return $this->result_array($object, $type); + } + + public function result_array($object = NULL, $type = PDO::FETCH_ASSOC) + { + $rows = array(); + + if (is_string($object)) + { + $fetch = $object; + } + elseif (is_bool($object)) + { + if ($object === TRUE) + { + $fetch = PDO::FETCH_OBJ; + + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $fetch = PDO::FETCH_OBJ; + } + } + else + { + // Use the default config values + $fetch = $this->fetch_type; + + if ($fetch == PDO::FETCH_OBJ) + { + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + } + try + { + while ($row = $this->result->fetch($fetch)) + { + $rows[] = $row; + } + } + catch(PDOException $e) + { + throw new Kohana_Database_Exception('database.error', $e->getMessage()); + return FALSE; + } + return $rows; + } + + public function list_fields() + { + $field_names = array(); + for ($i = 0, $max = $this->result->columnCount(); $i < $max; $i++) + { + $info = $this->result->getColumnMeta($i); + $field_names[] = $info['name']; + } + return $field_names; + } + + public function seek($offset) + { + // To request a scrollable cursor for your PDOStatement object, you must + // set the PDO::ATTR_CURSOR attribute to PDO::CURSOR_SCROLL when you + // prepare the statement. + Kohana::log('error', get_class($this).' does not support scrollable cursors, '.__FUNCTION__.' call ignored'); + + return FALSE; + } + + public function offsetGet($offset) + { + try + { + return $this->result->fetch($this->fetch_type, PDO::FETCH_ORI_ABS, $offset); + } + catch(PDOException $e) + { + throw new Kohana_Database_Exception('database.error', $e->getMessage()); + } + } + + public function rewind() + { + // Same problem that seek() has, see above. + return $this->seek(0); + } + +} // End PdoSqlite_Result Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Database/Pgsql.php b/lib/kohana/system/libraries/drivers/Database/Pgsql.php new file mode 100644 index 0000000..c53c843 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Database/Pgsql.php @@ -0,0 +1,538 @@ +db_config = $config; + + Kohana::log('debug', 'PgSQL Database Driver Initialized'); + } + + public function connect() + { + // Check if link already exists + if (is_resource($this->link)) + return $this->link; + + // Import the connect variables + extract($this->db_config['connection']); + + // Persistent connections enabled? + $connect = ($this->db_config['persistent'] == TRUE) ? 'pg_pconnect' : 'pg_connect'; + + // Build the connection info + $port = isset($port) ? 'port=\''.$port.'\'' : ''; + $host = isset($host) ? 'host=\''.$host.'\' '.$port : ''; // if no host, connect with the socket + + $connection_string = $host.' dbname=\''.$database.'\' user=\''.$user.'\' password=\''.$pass.'\''; + // Make the connection and select the database + if ($this->link = $connect($connection_string)) + { + if ($charset = $this->db_config['character_set']) + { + echo $this->set_charset($charset); + } + + // Clear password after successful connect + $this->db_config['connection']['pass'] = NULL; + + return $this->link; + } + + return FALSE; + } + + public function query($sql) + { + // Only cache if it's turned on, and only cache if it's not a write statement + if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|SET)\b#i', $sql)) + { + $hash = $this->query_hash($sql); + + if ( ! isset($this->query_cache[$hash])) + { + // Set the cached object + $this->query_cache[$hash] = new Pgsql_Result(pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql); + } + else + { + // Rewind cached result + $this->query_cache[$hash]->rewind(); + } + + return $this->query_cache[$hash]; + } + + // Suppress warning triggered when a database error occurs (e.g., a constraint violation) + return new Pgsql_Result(@pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql); + } + + public function set_charset($charset) + { + $this->query('SET client_encoding TO '.pg_escape_string($this->link, $charset)); + } + + public function escape_table($table) + { + if (!$this->db_config['escape']) + return $table; + + return '"'.str_replace('.', '"."', $table).'"'; + } + + public function escape_column($column) + { + if (!$this->db_config['escape']) + return $column; + + if ($column == '*') + return $column; + + // This matches any functions we support to SELECT. + if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) + { + if ( count($matches) == 3) + { + return $matches[1].'('.$this->escape_column($matches[2]).')'; + } + else if ( count($matches) == 5) + { + return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]); + } + } + + // This matches any modifiers we support to SELECT. + if ( ! preg_match('/\b(?:all|distinct)\s/i', $column)) + { + if (stripos($column, ' AS ') !== FALSE) + { + // Force 'AS' to uppercase + $column = str_ireplace(' AS ', ' AS ', $column); + + // Runs escape_column on both sides of an AS statement + $column = array_map(array($this, __FUNCTION__), explode(' AS ', $column)); + + // Re-create the AS statement + return implode(' AS ', $column); + } + + return preg_replace('/[^.*]+/', '"$0"', $column); + } + + $parts = explode(' ', $column); + $column = ''; + + for ($i = 0, $c = count($parts); $i < $c; $i++) + { + // The column is always last + if ($i == ($c - 1)) + { + $column .= preg_replace('/[^.*]+/', '"$0"', $parts[$i]); + } + else // otherwise, it's a modifier + { + $column .= $parts[$i].' '; + } + } + return $column; + } + + public function regex($field, $match, $type, $num_regexs) + { + $prefix = ($num_regexs == 0) ? '' : $type; + + return $prefix.' '.$this->escape_column($field).' ~* \''.$this->escape_str($match).'\''; + } + + public function notregex($field, $match, $type, $num_regexs) + { + $prefix = $num_regexs == 0 ? '' : $type; + + return $prefix.' '.$this->escape_column($field).' !~* \''.$this->escape_str($match) . '\''; + } + + public function limit($limit, $offset = 0) + { + return 'LIMIT '.$limit.' OFFSET '.$offset; + } + + public function compile_select($database) + { + $sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT '; + $sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*'; + + if (count($database['from']) > 0) + { + $sql .= "\nFROM "; + $sql .= implode(', ', $database['from']); + } + + if (count($database['join']) > 0) + { + foreach($database['join'] AS $join) + { + $sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions']; + } + } + + if (count($database['where']) > 0) + { + $sql .= "\nWHERE "; + } + + $sql .= implode("\n", $database['where']); + + if (count($database['groupby']) > 0) + { + $sql .= "\nGROUP BY "; + $sql .= implode(', ', $database['groupby']); + } + + if (count($database['having']) > 0) + { + $sql .= "\nHAVING "; + $sql .= implode("\n", $database['having']); + } + + if (count($database['orderby']) > 0) + { + $sql .= "\nORDER BY "; + $sql .= implode(', ', $database['orderby']); + } + + if (is_numeric($database['limit'])) + { + $sql .= "\n"; + $sql .= $this->limit($database['limit'], $database['offset']); + } + + return $sql; + } + + public function escape_str($str) + { + if (!$this->db_config['escape']) + return $str; + + is_resource($this->link) or $this->connect(); + + return pg_escape_string($this->link, $str); + } + + public function list_tables() + { + $sql = 'SELECT table_schema || \'.\' || table_name FROM information_schema.tables WHERE table_schema NOT IN (\'pg_catalog\', \'information_schema\')'; + $result = $this->query($sql)->result(FALSE, PGSQL_ASSOC); + + $retval = array(); + foreach ($result as $row) + { + $retval[] = current($row); + } + + return $retval; + } + + public function show_error() + { + return pg_last_error($this->link); + } + + public function list_fields($table) + { + $result = NULL; + + foreach ($this->field_data($table) as $row) + { + // Make an associative array + $result[$row->column_name] = $this->sql_type($row->data_type); + + if (!strncmp($row->column_default, 'nextval(', 8)) + { + $result[$row->column_name]['sequenced'] = TRUE; + } + + if ($row->is_nullable === 'YES') + { + $result[$row->column_name]['null'] = TRUE; + } + } + + if (!isset($result)) + throw new Kohana_Database_Exception('database.table_not_found', $table); + + return $result; + } + + public function field_data($table) + { + // http://www.postgresql.org/docs/8.3/static/infoschema-columns.html + $result = $this->query(' + SELECT column_name, column_default, is_nullable, data_type, udt_name, + character_maximum_length, numeric_precision, numeric_precision_radix, numeric_scale + FROM information_schema.columns + WHERE table_name = \''. $this->escape_str($table) .'\' + ORDER BY ordinal_position + '); + + return $result->result_array(TRUE); + } + +} // End Database_Pgsql_Driver Class + +/** + * PostgreSQL Result + */ +class Pgsql_Result extends Database_Result { + + // Data fetching types + protected $fetch_type = 'pgsql_fetch_object'; + protected $return_type = PGSQL_ASSOC; + + /** + * Sets up the result variables. + * + * @param resource query result + * @param resource database link + * @param boolean return objects or arrays + * @param string SQL query that was run + */ + public function __construct($result, $link, $object = TRUE, $sql) + { + $this->link = $link; + $this->result = $result; + + // If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query + if (is_resource($result)) + { + // Its an DELETE, INSERT, REPLACE, or UPDATE query + if (preg_match('/^(?:delete|insert|replace|update)\b/iD', trim($sql), $matches)) + { + $this->insert_id = (strtolower($matches[0]) == 'insert') ? $this->insert_id() : FALSE; + $this->total_rows = pg_affected_rows($this->result); + } + else + { + $this->current_row = 0; + $this->total_rows = pg_num_rows($this->result); + $this->fetch_type = ($object === TRUE) ? 'pg_fetch_object' : 'pg_fetch_array'; + } + } + else + { + throw new Kohana_Database_Exception('database.error', pg_last_error().' - '.$sql); + } + + // Set result type + $this->result($object); + + // Store the SQL + $this->sql = $sql; + } + + /** + * Magic __destruct function, frees the result. + */ + public function __destruct() + { + if (is_resource($this->result)) + { + pg_free_result($this->result); + } + } + + public function result($object = TRUE, $type = PGSQL_ASSOC) + { + $this->fetch_type = ((bool) $object) ? 'pg_fetch_object' : 'pg_fetch_array'; + + // This check has to be outside the previous statement, because we do not + // know the state of fetch_type when $object = NULL + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + if ($this->fetch_type == 'pg_fetch_object') + { + $this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $this->return_type = $type; + } + + return $this; + } + + public function as_array($object = NULL, $type = PGSQL_ASSOC) + { + return $this->result_array($object, $type); + } + + public function result_array($object = NULL, $type = PGSQL_ASSOC) + { + $rows = array(); + + if (is_string($object)) + { + $fetch = $object; + } + elseif (is_bool($object)) + { + if ($object === TRUE) + { + $fetch = 'pg_fetch_object'; + + // NOTE - The class set by $type must be defined before fetching the result, + // autoloading is disabled to save a lot of stupid overhead. + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + else + { + $fetch = 'pg_fetch_array'; + } + } + else + { + // Use the default config values + $fetch = $this->fetch_type; + + if ($fetch == 'pg_fetch_object') + { + $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass'; + } + } + + if ($this->total_rows) + { + pg_result_seek($this->result, 0); + + while ($row = $fetch($this->result, NULL, $type)) + { + $rows[] = $row; + } + } + + return $rows; + } + + public function insert_id() + { + if ($this->insert_id === NULL) + { + $query = 'SELECT LASTVAL() AS insert_id'; + + // Disable error reporting for this, just to silence errors on + // tables that have no serial column. + $ER = error_reporting(0); + + $result = pg_query($this->link, $query); + $insert_id = pg_fetch_array($result, NULL, PGSQL_ASSOC); + + $this->insert_id = $insert_id['insert_id']; + + // Reset error reporting + error_reporting($ER); + } + + return $this->insert_id; + } + + public function seek($offset) + { + if ($this->offsetExists($offset) AND pg_result_seek($this->result, $offset)) + { + // Set the current row to the offset + $this->current_row = $offset; + + return TRUE; + } + + return FALSE; + } + + public function list_fields() + { + $field_names = array(); + + $fields = pg_num_fields($this->result); + for ($i = 0; $i < $fields; ++$i) + { + $field_names[] = pg_field_name($this->result, $i); + } + + return $field_names; + } + + /** + * ArrayAccess: offsetGet + */ + public function offsetGet($offset) + { + if ( ! $this->seek($offset)) + return FALSE; + + // Return the row by calling the defined fetching callback + $fetch = $this->fetch_type; + return $fetch($this->result, NULL, $this->return_type); + } + +} // End Pgsql_Result Class + +/** + * PostgreSQL Prepared Statement (experimental) + */ +class Kohana_Pgsql_Statement { + + protected $link = NULL; + protected $stmt; + + public function __construct($sql, $link) + { + $this->link = $link; + + $this->stmt = $this->link->prepare($sql); + + return $this; + } + + public function __destruct() + { + $this->stmt->close(); + } + + // Sets the bind parameters + public function bind_params() + { + $argv = func_get_args(); + return $this; + } + + // sets the statement values to the bound parameters + public function set_vals() + { + return $this; + } + + // Runs the statement + public function execute() + { + return $this; + } +} diff --git a/lib/kohana/system/libraries/drivers/Image.php b/lib/kohana/system/libraries/drivers/Image.php new file mode 100644 index 0000000..5c4ab1b --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Image.php @@ -0,0 +1,149 @@ + $args) + { + if ( ! $this->$func($args)) + return FALSE; + } + + return TRUE; + } + + /** + * Sanitize and normalize a geometry array based on the temporary image + * width and height. Valid properties are: width, height, top, left. + * + * @param array geometry properties + * @return void + */ + protected function sanitize_geometry( & $geometry) + { + list($width, $height) = $this->properties(); + + // Turn off error reporting + $reporting = error_reporting(0); + + // Width and height cannot exceed current image size + $geometry['width'] = min($geometry['width'], $width); + $geometry['height'] = min($geometry['height'], $height); + + // Set standard coordinates if given, otherwise use pixel values + if ($geometry['top'] === 'center') + { + $geometry['top'] = floor(($height / 2) - ($geometry['height'] / 2)); + } + elseif ($geometry['top'] === 'top') + { + $geometry['top'] = 0; + } + elseif ($geometry['top'] === 'bottom') + { + $geometry['top'] = $height - $geometry['height']; + } + + // Set standard coordinates if given, otherwise use pixel values + if ($geometry['left'] === 'center') + { + $geometry['left'] = floor(($width / 2) - ($geometry['width'] / 2)); + } + elseif ($geometry['left'] === 'left') + { + $geometry['left'] = 0; + } + elseif ($geometry['left'] === 'right') + { + $geometry['left'] = $width - $geometry['height']; + } + + // Restore error reporting + error_reporting($reporting); + } + + /** + * Return the current width and height of the temporary image. This is mainly + * needed for sanitizing the geometry. + * + * @return array width, height + */ + abstract protected function properties(); + + /** + * Process an image with a set of actions. + * + * @param string image filename + * @param array actions to execute + * @param string destination directory path + * @param string destination filename + * @return boolean + */ + abstract public function process($image, $actions, $dir, $file); + + /** + * Flip an image. Valid directions are horizontal and vertical. + * + * @param integer direction to flip + * @return boolean + */ + abstract function flip($direction); + + /** + * Crop an image. Valid properties are: width, height, top, left. + * + * @param array new properties + * @return boolean + */ + abstract function crop($properties); + + /** + * Resize an image. Valid properties are: width, height, and master. + * + * @param array new properties + * @return boolean + */ + abstract public function resize($properties); + + /** + * Rotate an image. Valid amounts are -180 to 180. + * + * @param integer amount to rotate + * @return boolean + */ + abstract public function rotate($amount); + + /** + * Sharpen and image. Valid amounts are 1 to 100. + * + * @param integer amount to sharpen + * @return boolean + */ + abstract public function sharpen($amount); + +} // End Image Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Image/GD.php b/lib/kohana/system/libraries/drivers/Image/GD.php new file mode 100644 index 0000000..b3610b3 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Image/GD.php @@ -0,0 +1,379 @@ +image = $image; + + // Create the GD image resource + $this->tmp_image = $create($image['file']); + + // Get the quality setting from the actions + $quality = arr::remove('quality', $actions); + + if ($status = $this->execute($actions)) + { + // Prevent the alpha from being lost + imagealphablending($this->tmp_image, TRUE); + imagesavealpha($this->tmp_image, TRUE); + + switch ($save) + { + case 'imagejpeg': + // Default the quality to 95 + ($quality === NULL) and $quality = 95; + break; + case 'imagegif': + // Remove the quality setting, GIF doesn't use it + unset($quality); + break; + case 'imagepng': + // Always use a compression level of 9 for PNGs. This does not + // affect quality, it only increases the level of compression! + $quality = 9; + break; + } + + if ($render === FALSE) + { + // Set the status to the save return value, saving with the quality requested + $status = isset($quality) ? $save($this->tmp_image, $dir.$file, $quality) : $save($this->tmp_image, $dir.$file); + } + else + { + // Output the image directly to the browser + switch ($save) + { + case 'imagejpeg': + header('Content-Type: image/jpeg'); + break; + case 'imagegif': + header('Content-Type: image/gif'); + break; + case 'imagepng': + header('Content-Type: image/png'); + break; + } + + $status = isset($quality) ? $save($this->tmp_image, NULL, $quality) : $save($this->tmp_image); + } + + // Destroy the temporary image + imagedestroy($this->tmp_image); + } + + return $status; + } + + public function flip($direction) + { + // Get the current width and height + $width = imagesx($this->tmp_image); + $height = imagesy($this->tmp_image); + + // Create the flipped image + $flipped = $this->imagecreatetransparent($width, $height); + + if ($direction === Image::HORIZONTAL) + { + for ($x = 0; $x < $width; $x++) + { + $status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height); + } + } + elseif ($direction === Image::VERTICAL) + { + for ($y = 0; $y < $height; $y++) + { + $status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1); + } + } + else + { + // Do nothing + return TRUE; + } + + if ($status === TRUE) + { + // Swap the new image for the old one + imagedestroy($this->tmp_image); + $this->tmp_image = $flipped; + } + + return $status; + } + + public function crop($properties) + { + // Sanitize the cropping settings + $this->sanitize_geometry($properties); + + // Get the current width and height + $width = imagesx($this->tmp_image); + $height = imagesy($this->tmp_image); + + // Create the temporary image to copy to + $img = $this->imagecreatetransparent($properties['width'], $properties['height']); + + // Execute the crop + if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height)) + { + // Swap the new image for the old one + imagedestroy($this->tmp_image); + $this->tmp_image = $img; + } + + return $status; + } + + public function resize($properties) + { + // Get the current width and height + $width = imagesx($this->tmp_image); + $height = imagesy($this->tmp_image); + + if (substr($properties['width'], -1) === '%') + { + // Recalculate the percentage to a pixel size + $properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100)); + } + + if (substr($properties['height'], -1) === '%') + { + // Recalculate the percentage to a pixel size + $properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100)); + } + + // Recalculate the width and height, if they are missing + empty($properties['width']) and $properties['width'] = round($width * $properties['height'] / $height); + empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width); + + if ($properties['master'] === Image::AUTO) + { + // Change an automatic master dim to the correct type + $properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT; + } + + if (empty($properties['height']) OR $properties['master'] === Image::WIDTH) + { + // Recalculate the height based on the width + $properties['height'] = round($height * $properties['width'] / $width); + } + + if (empty($properties['width']) OR $properties['master'] === Image::HEIGHT) + { + // Recalculate the width based on the height + $properties['width'] = round($width * $properties['height'] / $height); + } + + // Test if we can do a resize without resampling to speed up the final resize + if ($properties['width'] > $width / 2 AND $properties['height'] > $height / 2) + { + // Presize width and height + $pre_width = $width; + $pre_height = $height; + + // The maximum reduction is 10% greater than the final size + $max_reduction_width = round($properties['width'] * 1.1); + $max_reduction_height = round($properties['height'] * 1.1); + + // Reduce the size using an O(2n) algorithm, until it reaches the maximum reduction + while ($pre_width / 2 > $max_reduction_width AND $pre_height / 2 > $max_reduction_height) + { + $pre_width /= 2; + $pre_height /= 2; + } + + // Create the temporary image to copy to + $img = $this->imagecreatetransparent($pre_width, $pre_height); + + if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height)) + { + // Swap the new image for the old one + imagedestroy($this->tmp_image); + $this->tmp_image = $img; + } + + // Set the width and height to the presize + $width = $pre_width; + $height = $pre_height; + } + + // Create the temporary image to copy to + $img = $this->imagecreatetransparent($properties['width'], $properties['height']); + + // Execute the resize + if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height)) + { + // Swap the new image for the old one + imagedestroy($this->tmp_image); + $this->tmp_image = $img; + } + + return $status; + } + + public function rotate($amount) + { + // Use current image to rotate + $img = $this->tmp_image; + + // White, with an alpha of 0 + $transparent = imagecolorallocatealpha($img, 255, 255, 255, 127); + + // Rotate, setting the transparent color + $img = imagerotate($img, 360 - $amount, $transparent, -1); + + // Fill the background with the transparent "color" + imagecolortransparent($img, $transparent); + + // Merge the images + if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100)) + { + // Prevent the alpha from being lost + imagealphablending($img, TRUE); + imagesavealpha($img, TRUE); + + // Swap the new image for the old one + imagedestroy($this->tmp_image); + $this->tmp_image = $img; + } + + return $status; + } + + public function sharpen($amount) + { + // Make sure that the sharpening function is available + if ( ! function_exists('imageconvolution')) + throw new Kohana_Exception('image.unsupported_method', __FUNCTION__); + + // Amount should be in the range of 18-10 + $amount = round(abs(-18 + ($amount * 0.08)), 2); + + // Gaussian blur matrix + $matrix = array + ( + array(-1, -1, -1), + array(-1, $amount, -1), + array(-1, -1, -1), + ); + + // Perform the sharpen + return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0); + } + + protected function properties() + { + return array(imagesx($this->tmp_image), imagesy($this->tmp_image)); + } + + /** + * Returns an image with a transparent background. Used for rotating to + * prevent unfilled backgrounds. + * + * @param integer image width + * @param integer image height + * @return resource + */ + protected function imagecreatetransparent($width, $height) + { + if (self::$blank_png === NULL) + { + // Decode the blank PNG if it has not been done already + self::$blank_png = imagecreatefromstring(base64_decode + ( + 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29'. + 'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN'. + 'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ'. + 'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH'. + 'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB'. + '3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII=' + )); + + // Set the blank PNG width and height + self::$blank_png_width = imagesx(self::$blank_png); + self::$blank_png_height = imagesy(self::$blank_png); + } + + $img = imagecreatetruecolor($width, $height); + + // Resize the blank image + imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height); + + // Prevent the alpha from being lost + imagealphablending($img, FALSE); + imagesavealpha($img, TRUE); + + return $img; + } + +} // End Image GD Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Image/GraphicsMagick.php b/lib/kohana/system/libraries/drivers/Image/GraphicsMagick.php new file mode 100644 index 0000000..8840eb8 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Image/GraphicsMagick.php @@ -0,0 +1,211 @@ +ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : ''; + + // Check to make sure the provided path is correct + if ( ! is_file(realpath($config['directory']).'/gm'.$this->ext)) + throw new Kohana_Exception('image.graphicsmagick.not_found', 'gm'.$this->ext); + + + // Set the installation directory + $this->dir = str_replace('\\', '/', realpath($config['directory'])).'/'; + } + + /** + * Creates a temporary image and executes the given actions. By creating a + * temporary copy of the image before manipulating it, this process is atomic. + */ + public function process($image, $actions, $dir, $file, $render = FALSE) + { + // We only need the filename + $image = $image['file']; + + // Unique temporary filename + $this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.')); + + // Copy the image to the temporary file + copy($image, $this->tmp_image); + + // Quality change is done last + $quality = (int) arr::remove('quality', $actions); + + // Use 95 for the default quality + empty($quality) and $quality = 95; + + // All calls to these will need to be escaped, so do it now + $this->cmd_image = escapeshellarg($this->tmp_image); + $this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file); + + if ($status = $this->execute($actions)) + { + // Use convert to change the image into its final version. This is + // done to allow the file type to change correctly, and to handle + // the quality conversion in the most effective way possible. + if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image)) + { + $this->errors[] = $error; + } + else + { + // Output the image directly to the browser + if ($render !== FALSE) + { + $contents = file_get_contents($this->tmp_image); + switch (substr($file, strrpos($file, '.') + 1)) + { + case 'jpg': + case 'jpeg': + header('Content-Type: image/jpeg'); + break; + case 'gif': + header('Content-Type: image/gif'); + break; + case 'png': + header('Content-Type: image/png'); + break; + } + echo $contents; + } + } + } + + // Remove the temporary image + unlink($this->tmp_image); + $this->tmp_image = ''; + + return $status; + } + + public function crop($prop) + { + // Sanitize and normalize the properties into geometry + $this->sanitize_geometry($prop); + + // Set the IM geometry based on the properties + $geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']); + + if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function flip($dir) + { + // Convert the direction into a GM command + $dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip'; + + if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function resize($prop) + { + switch ($prop['master']) + { + case Image::WIDTH: // Wx + $dim = escapeshellarg($prop['width'].'x'); + break; + case Image::HEIGHT: // xH + $dim = escapeshellarg('x'.$prop['height']); + break; + case Image::AUTO: // WxH + $dim = escapeshellarg($prop['width'].'x'.$prop['height']); + break; + case Image::NONE: // WxH! + $dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!'); + break; + } + + // Use "convert" to change the width and height + if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function rotate($amt) + { + if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function sharpen($amount) + { + // Set the sigma, radius, and amount. The amount formula allows a nice + // spread between 1 and 100 without pixelizing the image badly. + $sigma = 0.5; + $radius = $sigma * 2; + $amount = round(($amount / 80) * 3.14, 2); + + // Convert the amount to an GM command + $sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0'); + + if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + protected function properties() + { + return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE); + } + +} // End Image GraphicsMagick Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Image/ImageMagick.php b/lib/kohana/system/libraries/drivers/Image/ImageMagick.php new file mode 100644 index 0000000..5a86663 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Image/ImageMagick.php @@ -0,0 +1,212 @@ +ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : ''; + + // Check to make sure the provided path is correct + if ( ! is_file(realpath($config['directory']).'/convert'.$this->ext)) + throw new Kohana_Exception('image.imagemagick.not_found', 'convert'.$this->ext); + + // Set the installation directory + $this->dir = str_replace('\\', '/', realpath($config['directory'])).'/'; + } + + /** + * Creates a temporary image and executes the given actions. By creating a + * temporary copy of the image before manipulating it, this process is atomic. + */ + public function process($image, $actions, $dir, $file, $render = FALSE) + { + // We only need the filename + $image = $image['file']; + + // Unique temporary filename + $this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.')); + + // Copy the image to the temporary file + copy($image, $this->tmp_image); + + // Quality change is done last + $quality = (int) arr::remove('quality', $actions); + + // Use 95 for the default quality + empty($quality) and $quality = 95; + + // All calls to these will need to be escaped, so do it now + $this->cmd_image = escapeshellarg($this->tmp_image); + $this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file); + + if ($status = $this->execute($actions)) + { + // Use convert to change the image into its final version. This is + // done to allow the file type to change correctly, and to handle + // the quality conversion in the most effective way possible. + if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image)) + { + $this->errors[] = $error; + } + else + { + // Output the image directly to the browser + if ($render !== FALSE) + { + $contents = file_get_contents($this->tmp_image); + switch (substr($file, strrpos($file, '.') + 1)) + { + case 'jpg': + case 'jpeg': + header('Content-Type: image/jpeg'); + break; + case 'gif': + header('Content-Type: image/gif'); + break; + case 'png': + header('Content-Type: image/png'); + break; + } + echo $contents; + } + } + } + + // Remove the temporary image + unlink($this->tmp_image); + $this->tmp_image = ''; + + return $status; + } + + public function crop($prop) + { + // Sanitize and normalize the properties into geometry + $this->sanitize_geometry($prop); + + // Set the IM geometry based on the properties + $geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']); + + if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function flip($dir) + { + // Convert the direction into a IM command + $dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip'; + + if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function resize($prop) + { + switch ($prop['master']) + { + case Image::WIDTH: // Wx + $dim = escapeshellarg($prop['width'].'x'); + break; + case Image::HEIGHT: // xH + $dim = escapeshellarg('x'.$prop['height']); + break; + case Image::AUTO: // WxH + $dim = escapeshellarg($prop['width'].'x'.$prop['height']); + break; + case Image::NONE: // WxH! + $dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!'); + break; + } + + // Use "convert" to change the width and height + if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function rotate($amt) + { + if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + public function sharpen($amount) + { + // Set the sigma, radius, and amount. The amount formula allows a nice + // spread between 1 and 100 without pixelizing the image badly. + $sigma = 0.5; + $radius = $sigma * 2; + $amount = round(($amount / 80) * 3.14, 2); + + // Convert the amount to an IM command + $sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0'); + + if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image)) + { + $this->errors[] = $error; + return FALSE; + } + + return TRUE; + } + + protected function properties() + { + return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE); + } + +} // End Image ImageMagick Driver \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Session.php b/lib/kohana/system/libraries/drivers/Session.php new file mode 100644 index 0000000..fb58c8d --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Session.php @@ -0,0 +1,70 @@ + 'apc', + * 'requests' => 10000 + * ); + * Lifetime does not need to be set as it is + * overridden by the session expiration setting. + * + * $Id: Cache.php 3769 2008-12-15 00:48:56Z zombor $ + * + * @package Core + * @author Kohana Team + * @copyright (c) 2007-2008 Kohana Team + * @license http://kohanaphp.com/license.html + */ +class Session_Cache_Driver implements Session_Driver { + + protected $cache; + protected $encrypt; + + public function __construct() + { + // Load Encrypt library + if (Kohana::config('session.encryption')) + { + $this->encrypt = new Encrypt; + } + + Kohana::log('debug', 'Session Cache Driver Initialized'); + } + + public function open($path, $name) + { + $config = Kohana::config('session.storage'); + + if (empty($config)) + { + // Load the default group + $config = Kohana::config('cache.default'); + } + elseif (is_string($config)) + { + $name = $config; + + // Test the config group name + if (($config = Kohana::config('cache.'.$config)) === NULL) + throw new Kohana_Exception('cache.undefined_group', $name); + } + + $config['lifetime'] = (Kohana::config('session.expiration') == 0) ? 86400 : Kohana::config('session.expiration'); + $this->cache = new Cache($config); + + return is_object($this->cache); + } + + public function close() + { + return TRUE; + } + + public function read($id) + { + $id = 'session_'.$id; + if ($data = $this->cache->get($id)) + { + return Kohana::config('session.encryption') ? $this->encrypt->decode($data) : $data; + } + + // Return value must be string, NOT a boolean + return ''; + } + + public function write($id, $data) + { + $id = 'session_'.$id; + $data = Kohana::config('session.encryption') ? $this->encrypt->encode($data) : $data; + + return $this->cache->set($id, $data); + } + + public function destroy($id) + { + $id = 'session_'.$id; + return $this->cache->delete($id); + } + + public function regenerate() + { + session_regenerate_id(TRUE); + + // Return new session id + return session_id(); + } + + public function gc($maxlifetime) + { + // Just return, caches are automatically cleaned up + return TRUE; + } + +} // End Session Cache Driver diff --git a/lib/kohana/system/libraries/drivers/Session/Cookie.php b/lib/kohana/system/libraries/drivers/Session/Cookie.php new file mode 100644 index 0000000..7b79106 --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Session/Cookie.php @@ -0,0 +1,80 @@ +cookie_name = Kohana::config('session.name').'_data'; + + if (Kohana::config('session.encryption')) + { + $this->encrypt = Encrypt::instance(); + } + + Kohana::log('debug', 'Session Cookie Driver Initialized'); + } + + public function open($path, $name) + { + return TRUE; + } + + public function close() + { + return TRUE; + } + + public function read($id) + { + $data = (string) cookie::get($this->cookie_name); + + if ($data == '') + return $data; + + return empty($this->encrypt) ? base64_decode($data) : $this->encrypt->decode($data); + } + + public function write($id, $data) + { + $data = empty($this->encrypt) ? base64_encode($data) : $this->encrypt->encode($data); + + if (strlen($data) > 4048) + { + Kohana::log('error', 'Session ('.$id.') data exceeds the 4KB limit, ignoring write.'); + return FALSE; + } + + return cookie::set($this->cookie_name, $data, Kohana::config('session.expiration')); + } + + public function destroy($id) + { + return cookie::delete($this->cookie_name); + } + + public function regenerate() + { + session_regenerate_id(TRUE); + + // Return new id + return session_id(); + } + + public function gc($maxlifetime) + { + return TRUE; + } + +} // End Session Cookie Driver Class \ No newline at end of file diff --git a/lib/kohana/system/libraries/drivers/Session/Database.php b/lib/kohana/system/libraries/drivers/Session/Database.php new file mode 100644 index 0000000..b4144ff --- /dev/null +++ b/lib/kohana/system/libraries/drivers/Session/Database.php @@ -0,0 +1,163 @@ +encrypt = Encrypt::instance(); + } + + if (is_array($config['storage'])) + { + if ( ! empty($config['storage']['group'])) + { + // Set the group name + $this->db = $config['storage']['group']; + } + + if ( ! empty($config['storage']['table'])) + { + // Set the table name + $this->table = $config['storage']['table']; + } + } + + // Load database + $this->db = Database::instance($this->db); + + Kohana::log('debug', 'Session Database Driver Initialized'); + } + + public function open($path, $name) + { + return TRUE; + } + + public function close() + { + return TRUE; + } + + public function read($id) + { + // Load the session + $query = $this->db->from($this->table)->where('session_id', $id)->limit(1)->get()->result(TRUE); + + if ($query->count() === 0) + { + // No current session + $this->session_id = NULL; + + return ''; + } + + // Set the current session id + $this->session_id = $id; + + // Load the data + $data = $query->current()->data; + + return ($this->encrypt === NULL) ? base64_decode($data) : $this->encrypt->decode($data); + } + + public function write($id, $data) + { + $data = array + ( + 'session_id' => $id, + 'last_activity' => time(), + 'data' => ($this->encrypt === NULL) ? base64_encode($data) : $this->encrypt->encode($data) + ); + + if ($this->session_id === NULL) + { + // Insert a new session + $query = $this->db->insert($this->table, $data); + } + elseif ($id === $this->session_id) + { + // Do not update the session_id + unset($data['session_id']); + + // Update the existing session + $query = $this->db->update($this->table, $data, array('session_id' => $id)); + } + else + { + // Update the session and id + $query = $this->db->update($this->table, $data, array('session_id' => $this->session_id)); + + // Set the new session id + $this->session_id = $id; + } + + return (bool) $query->count(); + } + + public function destroy($id) + { + // Delete the requested session + $this->db->delete($this->table, array('session_id' => $id)); + + // Session id is no longer valid + $this->session_id = NULL; + + return TRUE; + } + + public function regenerate() + { + // Generate a new session id + session_regenerate_id(); + + // Return new session id + return session_id(); + } + + public function gc($maxlifetime) + { + // Delete all expired sessions + $query = $this->db->delete($this->table, array('last_activity <' => time() - $maxlifetime)); + + Kohana::log('debug', 'Session garbage collected: '.$query->count().' row(s) deleted.'); + + return TRUE; + } + +} // End Session Database Driver diff --git a/lib/kohana/system/views/kohana/template.php b/lib/kohana/system/views/kohana/template.php new file mode 100644 index 0000000..b090fd8 --- /dev/null +++ b/lib/kohana/system/views/kohana/template.php @@ -0,0 +1,36 @@ + + + + + + + + <?php echo html::specialchars($title) ?> + + + + + + +

    + + + + + + \ No newline at end of file diff --git a/lib/kohana/system/views/kohana_calendar.php b/lib/kohana/system/views/kohana_calendar.php new file mode 100644 index 0000000..39545e2 --- /dev/null +++ b/lib/kohana/system/views/kohana_calendar.php @@ -0,0 +1,52 @@ + date('n', $prev), 'year' => date('Y', $prev)))); +$next = Router::$current_uri.'?'.http_build_query(array_merge($qs, array('month' => date('n', $next), 'year' => date('Y', $next)))); + +?> + + + + + + + + + + + + + +
  • '.implode('
  • ', $data['output']).'
  • '; +} +else +{ + $classes = array(); + $output = ''; +} + +?> + + + + +
    diff --git a/lib/kohana/system/views/kohana_error_disabled.php b/lib/kohana/system/views/kohana_error_disabled.php new file mode 100644 index 0000000..cd91132 --- /dev/null +++ b/lib/kohana/system/views/kohana_error_disabled.php @@ -0,0 +1,17 @@ + + + + + + +<?php echo $error ?> + + +
    +

    +

    +
    + + \ No newline at end of file diff --git a/lib/kohana/system/views/kohana_error_page.php b/lib/kohana/system/views/kohana_error_page.php new file mode 100644 index 0000000..944064c --- /dev/null +++ b/lib/kohana/system/views/kohana_error_page.php @@ -0,0 +1,27 @@ + + + + + + +<?php echo $error ?> + + + +
    +

    +

    + +

    + +

    + +

    + + +

    +
    + + \ No newline at end of file diff --git a/lib/kohana/system/views/kohana_errors.css b/lib/kohana/system/views/kohana_errors.css new file mode 100644 index 0000000..1341f57 --- /dev/null +++ b/lib/kohana/system/views/kohana_errors.css @@ -0,0 +1,21 @@ +div#framework_error { background:#fff; border:solid 1px #ccc; font-family:sans-serif; color:#111; font-size:14px; line-height:130%; } +div#framework_error h3 { color:#fff; font-size:16px; padding:8px 6px; margin:0 0 8px; background:#f15a00; text-align:center; } +div#framework_error a { color:#228; text-decoration:none; } +div#framework_error a:hover { text-decoration:underline; } +div#framework_error strong { color:#900; } +div#framework_error p { margin:0; padding:4px 6px 10px; } +div#framework_error tt, +div#framework_error pre, +div#framework_error code { font-family:monospace; padding:2px 4px; font-size:12px; color:#333; + white-space:pre-wrap; /* CSS 2.1 */ + white-space:-moz-pre-wrap; /* For Mozilla */ + word-wrap:break-word; /* For IE5.5+ */ +} +div#framework_error tt { font-style:italic; } +div#framework_error tt:before { content:">"; color:#aaa; } +div#framework_error code tt:before { content:""; } +div#framework_error pre, +div#framework_error code { background:#eaeee5; border:solid 0 #D6D8D1; border-width:0 1px 1px 0; } +div#framework_error .block { display:block; text-align:left; } +div#framework_error .stats { padding:4px; background: #eee; border-top:solid 1px #ccc; text-align:center; font-size:10px; color:#888; } +div#framework_error .backtrace { margin:0; padding:0 6px; list-style:none; line-height:12px; } \ No newline at end of file diff --git a/lib/kohana/system/views/kohana_profiler.php b/lib/kohana/system/views/kohana_profiler.php new file mode 100644 index 0000000..da77a66 --- /dev/null +++ b/lib/kohana/system/views/kohana_profiler.php @@ -0,0 +1,37 @@ + + +
    +render(); +} +?> +

    Profiler executed in s

    +
    \ No newline at end of file diff --git a/lib/kohana/system/views/kohana_profiler_table.css b/lib/kohana/system/views/kohana_profiler_table.css new file mode 100644 index 0000000..6e7601c --- /dev/null +++ b/lib/kohana/system/views/kohana_profiler_table.css @@ -0,0 +1,53 @@ +#kohana-profiler .kp-table +{ + font-size: 1.0em; + color: #4D6171; + width: 100%; + border-collapse: collapse; + border-top: 1px solid #E5EFF8; + border-right: 1px solid #E5EFF8; + border-left: 1px solid #E5EFF8; + margin-bottom: 10px; +} +#kohana-profiler .kp-table td +{ + background-color: #FFFFFF; + border-bottom: 1px solid #E5EFF8; + padding: 3px; + vertical-align: top; +} +#kohana-profiler .kp-table .kp-title td +{ + font-weight: bold; + background-color: inherit; +} +#kohana-profiler .kp-table .kp-altrow td +{ + background-color: #F7FBFF; +} +#kohana-profiler .kp-table .kp-totalrow td +{ + background-color: #FAFAFA; + border-top: 1px solid #D2DCE5; + font-weight: bold; +} +#kohana-profiler .kp-table .kp-column +{ + width: 100px; + border-left: 1px solid #E5EFF8; + text-align: center; +} +#kohana-profiler .kp-table .kp-data, #kohana-profiler .kp-table .kp-name +{ + background-color: #FAFAFB; + vertical-align: top; +} +#kohana-profiler .kp-table .kp-name +{ + width: 200px; + border-right: 1px solid #E5EFF8; +} +#kohana-profiler .kp-table .kp-altrow .kp-data, #kohana-profiler .kp-table .kp-altrow .kp-name +{ + background-color: #F6F8FB; +} \ No newline at end of file diff --git a/lib/kohana/system/views/kohana_profiler_table.php b/lib/kohana/system/views/kohana_profiler_table.php new file mode 100644 index 0000000..b6b4653 --- /dev/null +++ b/lib/kohana/system/views/kohana_profiler_table.php @@ -0,0 +1,25 @@ + + + + > + $column) + { + $class = empty($column['class']) ? '' : ' class="'.$column['class'].'"'; + $style = empty($column['style']) ? '' : ' style="'.$column['style'].'"'; + $value = $row['data'][$index]; + $value = (is_array($value) OR is_object($value)) ? '
    '.html::specialchars(print_r($value, TRUE)).'
    ' : html::specialchars($value); + echo '', $value, ''; + } + ?> + + +
    \ No newline at end of file diff --git a/lib/kohana/system/views/pagination/classic.php b/lib/kohana/system/views/pagination/classic.php new file mode 100644 index 0000000..5272c2c --- /dev/null +++ b/lib/kohana/system/views/pagination/classic.php @@ -0,0 +1,39 @@ + Last › + */ +?> + +

    + + + ‹  + + + + < + + + + + + + + + + + + + + + + > + + + +  › + + +

    \ No newline at end of file diff --git a/lib/kohana/system/views/pagination/digg.php b/lib/kohana/system/views/pagination/digg.php new file mode 100644 index 0000000..0e065a6 --- /dev/null +++ b/lib/kohana/system/views/pagination/digg.php @@ -0,0 +1,83 @@ + + +

    + + + «  + + «  + + + + + + + + + + + + + + + + + + + + + + + + … + + + + $total_pages - 8): /* « Previous 1 2 … 17 18 19 20 21 22 23 24 25 26 Next » */ ?> + + 1 + 2 + … + + + + + + + + + + + + 1 + 2 + … + + + + + + + + + + … + + + + + + + +  » + +  » + + +

    \ No newline at end of file diff --git a/lib/kohana/system/views/pagination/extended.php b/lib/kohana/system/views/pagination/extended.php new file mode 100644 index 0000000..2427a4e --- /dev/null +++ b/lib/kohana/system/views/pagination/extended.php @@ -0,0 +1,27 @@ + + +

    + + + «  + + «  + + + | + + | + + | +  » + +  » + + +

    \ No newline at end of file diff --git a/lib/kohana/system/views/pagination/punbb.php b/lib/kohana/system/views/pagination/punbb.php new file mode 100644 index 0000000..6599831 --- /dev/null +++ b/lib/kohana/system/views/pagination/punbb.php @@ -0,0 +1,37 @@ + + +

    + + : + + 3): ?> + 1 + + + + + + + $total_pages) continue ?> + + + + + + + + + + + + + + + +

    \ No newline at end of file diff --git a/man/Makefile.in b/man/Makefile.in new file mode 100644 index 0000000..614ea84 --- /dev/null +++ b/man/Makefile.in @@ -0,0 +1,23 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +MANDIR=@mandir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +DATAROOTDIR=@datarootdir@ + +CP=@CP@ + +all html: + +clean: + -rm -f npcd.8 + +distclean: clean + -rm -f Makefile + +devclean: distclean + +install: + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(MANDIR)/man8 + $(INSTALL) -m 755 $(INSTALL_OPTS) npcd.8 $(DESTDIR)$(MANDIR)/man8 + diff --git a/man/npcd.8.in b/man/npcd.8.in new file mode 100644 index 0000000..c3153ce --- /dev/null +++ b/man/npcd.8.in @@ -0,0 +1,38 @@ +.\" In .TH, FOO should be all caps, SECTION should be 1-8, maybe w/ subsection +.\" other parms are allowed: see man(7), man(1) +.\" +.\" This template provided by Tom Christiansen . +.\" +.TH NPCD 8 +.SH NAME +npcd \- Nagios Performance C Daemon +.SH SYNOPSIS +\fBnpcd\fR [ \fB\-d | \--daemon\fR ] ( \fB\-f | \--config\fR ) \fI +.SH DESCRIPTION +The \fBnpcd\fR is a daemon processing nagios performance data. +.PP +For more information you can visit pnp4nagios website: +.IP +http://docs.pnp4nagios.org/ +.PP +and SourceForge project: +.IP +http://pnp4nagios.sourceforge.net +.SH OPTIONS +.TP +\fB\-d, \--daemon +Run \fBnpcd\fR as daemon in the background. +.TP +\fB\-f, \--config\fR \fI +Path to the \fBnpcd\fR config file (typically @sysconfdir@/npcd.cfg). +.SH "RETURN VALUE" +On success starting \fBnpcd\fR 0 is returned. +.SH ERRORS +On error starting \fBnpcd\fR 1 is returned. +.SH FILES +.br +.nf +\fI@sysconfdir@/npcd.cfg\fR default config file +.SH AUTHORS +Joerg Linge , +Hendrik Baecker diff --git a/sample-config/Makefile.in b/sample-config/Makefile.in new file mode 100644 index 0000000..3f6b171 --- /dev/null +++ b/sample-config/Makefile.in @@ -0,0 +1,84 @@ +prefix=@prefix@ +SYSCONFDIR=@sysconfdir@ +BINDIR=@bindir@ +LIBEXECDIR=@libexecdir@ +LIBDIR=@libdir@ +CGIDIR=@sbindir@ +HTMLDIR=@datadir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +PERFDATADIR=@PERFDATA_DIR@ +DATAROOTDIR=@datarootdir@ +PKG_NAME=@PKG_NAME@ +PKG_VERSION=@PKG_VERSION@ +HTTPD_CONF=@HTTPD_CONF@ +CP=@CP@ + +all html: + +clean: + -rm -f pnp/config.php + -rm -f pnp/process_perfdata.cfg-sample + -rm -f pnp/npcd.cfg-sample + -rm -f misccommands.cfg-sample + -rm -f nagios.cfg-sample + -rm -f httpd.conf + -rm -f pnp/pnp4nagios_release + -rm -f lighttpd.pnp4nagios.conf + -rm -f nginx.pnp4nagios.conf + +distclean: clean + -rm -f Makefile + +devclean: distclean + +install: + -rm -f $(DESTDIR)$(HTMLDIR)/conf/config.php + + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR)/config.d + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR)/check_commands + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR)/pages + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/pnp4nagios_release $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/background.pdf $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/config.php $(DESTDIR)$(SYSCONFDIR)/config.php.$(PKG_VERSION); \ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/config.php $(DESTDIR)$(SYSCONFDIR); \ + +install-config: + + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR)/check_commands + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(SYSCONFDIR)/pages + + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/config.php $(DESTDIR)$(SYSCONFDIR)/config.php.$(PKG_VERSION); \ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/config.php $(DESTDIR)$(SYSCONFDIR); \ + + if [ ! -e $(DESTDIR)$(SYSCONFDIR)/config_local.php ] ;then \ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/config.php $(DESTDIR)$(SYSCONFDIR)/config_local.php; \ + fi + + if [ -e $(DESTDIR)$(SYSCONFDIR)/process_perfdata.cfg ] ;then \ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/process_perfdata.cfg-sample $(DESTDIR)$(SYSCONFDIR)/process_perfdata.cfg.$(PKG_VERSION); \ + else\ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/process_perfdata.cfg-sample $(DESTDIR)$(SYSCONFDIR)/process_perfdata.cfg; \ + fi + + if [ -e $(DESTDIR)$(SYSCONFDIR)/npcd.cfg ] ;then \ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/npcd.cfg-sample $(DESTDIR)$(SYSCONFDIR)/npcd.cfg.$(PKG_VERSION); \ + else\ + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/npcd.cfg-sample $(DESTDIR)$(SYSCONFDIR)/npcd.cfg; \ + fi + + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/rra.cfg-sample $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 644 $(INSTALL_OPTS) misccommands.cfg-sample $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 644 $(INSTALL_OPTS) nagios.cfg-sample $(DESTDIR)$(SYSCONFDIR) + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/check_commands/check_nwstat.cfg-sample $(DESTDIR)$(SYSCONFDIR)/check_commands + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/check_commands/check_nrpe.cfg-sample $(DESTDIR)$(SYSCONFDIR)/check_commands + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/check_commands/check_all_local_disks.cfg-sample $(DESTDIR)$(SYSCONFDIR)/check_commands + $(INSTALL) -m 644 $(INSTALL_OPTS) pnp/pages/web_traffic.cfg-sample $(DESTDIR)$(SYSCONFDIR)/pages + +install-webconf: + + $(INSTALL) -m 755 -d $(DESTDIR)$(HTTPD_CONF) + $(INSTALL) -m 644 httpd.conf $(DESTDIR)$(HTTPD_CONF)/$(PKG_NAME).conf + diff --git a/sample-config/httpd.conf.in b/sample-config/httpd.conf.in new file mode 100644 index 0000000..72b81cb --- /dev/null +++ b/sample-config/httpd.conf.in @@ -0,0 +1,30 @@ +# SAMPLE CONFIG SNIPPETS FOR APACHE WEB SERVER + +Alias @BASE_URL@ "@datarootdir@" + + + AllowOverride None + Order allow,deny + Allow from all + # + # Use the same value as defined in nagios.conf + # + AuthName "Nagios Access" + AuthType Basic + AuthUserFile /usr/local/nagios/etc/htpasswd.users + Require valid-user + + # Turn on URL rewriting + RewriteEngine On + Options symLinksIfOwnerMatch + # Installation directory + RewriteBase @BASE_URL@/ + # Protect application and system files from being viewed + RewriteRule "^(?:application|modules|system)/" - [F] + # Allow any files or directories that exist to be displayed directly + RewriteCond "%{REQUEST_FILENAME}" !-f + RewriteCond "%{REQUEST_FILENAME}" !-d + # Rewrite all other URLs to index.php/URL + RewriteRule "^.*$" "index.php/$0" [PT] + + diff --git a/sample-config/lighttpd.pnp4nagios.conf.in b/sample-config/lighttpd.pnp4nagios.conf.in new file mode 100644 index 0000000..a0b3a3b --- /dev/null +++ b/sample-config/lighttpd.pnp4nagios.conf.in @@ -0,0 +1,20 @@ +# +# Sample Lighttpd Config snippet. +# Tested on Debian. +# +server.modules += ( "mod_auth" ) + +alias.url += ( + "@BASE_URL@" => "@datarootdir@" + ) + +$HTTP["url"] =~ "(^@BASE_URL@)" { + auth.backend = "htpasswd" + auth.backend.htpasswd.userfile = "/usr/local/nagios/etc/htpasswd.users" + auth.require = ( "" => ( + "method" => "basic", + "realm" => "Nagios Access", + "require" => "valid-user" + ) + ) +} diff --git a/sample-config/misccommands.cfg-sample.in b/sample-config/misccommands.cfg-sample.in new file mode 100644 index 0000000..1280c27 --- /dev/null +++ b/sample-config/misccommands.cfg-sample.in @@ -0,0 +1,44 @@ +# +# definitions for PNP processing commands +# +# please uncomment the appropriate definitions and make sure +# that there aren't duplicate entries in your config +# +# Synchronous mode +# + +#define command { +# command_name process-service-perfdata +# command_line @PERL@ @libexecdir@/process_perfdata.pl +#} +# +#define command { +# command_name process-host-perfdata +# command_line @PERL@ @libexecdir@/process_perfdata.pl -d HOSTPERFDATA +#} + +# +# Bulk mode +# +#define command { +# command_name process-service-perfdata-file +# command_line @libexecdir@/process_perfdata.pl --bulk @localstatedir@/service-perfdata +#} + +#define command { +# command_name process-host-perfdata-file +# command_line @libexecdir@/process_perfdata.pl --bulk @localstatedir@/host-perfdata +#} + +# +# Bulk with NPCD mode +# +#define command { +# command_name process-service-perfdata-file +# command_line /bin/mv @localstatedir@/service-perfdata @PERFDATA_SPOOL_DIR@/service-perfdata.$TIMET$ +#} + +#define command { +# command_name process-host-perfdata-file +# command_line /bin/mv @localstatedir@/host-perfdata @PERFDATA_SPOOL_DIR@/host-perfdata.$TIMET$ +#} diff --git a/sample-config/nagios.cfg-sample.in b/sample-config/nagios.cfg-sample.in new file mode 100644 index 0000000..fef969b --- /dev/null +++ b/sample-config/nagios.cfg-sample.in @@ -0,0 +1,42 @@ +# +# definitions for PNP in nagios.cfg (icinga.cfg) +# please make sure that you don't have duplicate entries +# +# Synchronous mode +# +process_performance_data=1 + +enable_environment_macros=1 # available since Nagios 3.x + +service_perfdata_command=process-service-perfdata + +host_perfdata_command=process-host-perfdata # NOT advisable prior to Nagios 3.0 + +# +# Bulk / NPCD mode +# + +process_performance_data=1 + +# *** the template definition differs from the one in the original nagios.cfg +# +service_perfdata_file=@localstatedir@/service-perfdata +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$ +service_perfdata_file_mode=a +service_perfdata_file_processing_interval=15 +service_perfdata_file_processing_command=process-service-perfdata-file + +# *** the template definition differs from the one in the original nagios.cfg +# +host_perfdata_file=@localstatedir@/host-perfdata +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$ +host_perfdata_file_mode=a +host_perfdata_file_processing_interval=15 +host_perfdata_file_processing_command=process-host-perfdata-file + +# +# Module mode +# +event_broker_options=-1 # minimum 4+8=12 +process_performance_data=1 +broker_module=@libdir@/npcdmod.o config_file=@sysconfdir@/npcd.cfg diff --git a/sample-config/nginx.pnp4nagios.conf.in b/sample-config/nginx.pnp4nagios.conf.in new file mode 100644 index 0000000..1a1bfc4 --- /dev/null +++ b/sample-config/nginx.pnp4nagios.conf.in @@ -0,0 +1,34 @@ +# SAMPLE CONFIG SNIPPETS FOR NGINX WEB SERVER +# Contributed by Thomas Charbonnel +# +location @BASE_URL@ { + # e.g. /usr/local/pnp4nagios/share; + alias @datarootdir@; + auth_basic "Nagios Access"; + auth_basic_user_file /usr/local/nagios/etc/htpasswd.users; + index index.php; + # if we have e.g. /pnp4nagios/media/css/common.css + # nginx will check + # /usr/local/png4nagios/share/media/css/common/css + # and return it if it's found + # if it can't find a matching file even adding a trailing / + # the request is handled to the @pnp4nagios location + try_files $uri $uri/ @pnp4nagios; +} +location @pnp4nagios { + # this implies the definition of some backend + # e.g + # upstream php { + # server 127.0.0.1:9000; + # } + fastcgi_pass php; + fastcgi_index index.php; + # implies an external file, but this is common nginx practice + include fastcgi_params; + # this splits out the trailing path + # eg index.php?host -> $fastcgi_path_info == 'host' + fastcgi_split_path_info ^(.+\.php)(.*)$; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param SCRIPT_FILENAME @datarootdir@/index.php; +} + diff --git a/sample-config/pnp/background-letter.pdf b/sample-config/pnp/background-letter.pdf new file mode 100644 index 0000000000000000000000000000000000000000..83e4c66d25fd574e788402622144d07eb575b5b9 GIT binary patch literal 237627 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 literal 0 HcmV?d00001 diff --git a/sample-config/pnp/background.pdf b/sample-config/pnp/background.pdf new file mode 100644 index 0000000000000000000000000000000000000000..174428c20af8e41539689c8f3cede9eec614ac6c GIT binary patch literal 29383 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 +# Example: conf['allowed_for_all_services'] = "nagiosadmin,operator"; +# This option is used while $conf['auth_enabled'] = TRUE +$conf['allowed_for_all_services'] = ""; +$conf['allowed_for_all_hosts'] = ""; + +# Which user is allowed to see additional service links ? +# Keywords: EVERYONE NONE +# Example: conf['allowed_for_service_links'] = "nagiosadmin,operator"; +# +$conf['allowed_for_service_links'] = "EVERYONE"; + +# +# Who can use the host search function ? +# Keywords: EVERYONE NONE +# +$conf['allowed_for_host_search'] = "EVERYONE"; + +# +# Who can use the host overview ? +# This function is called if no Service Description is given. +# +$conf['allowed_for_host_overview'] = "EVERYONE"; + +# +# Who can use the Pages function? +# Keywords: EVERYONE NONE +# Example: conf['allowed_for_pages'] = "nagiosadmin,operator"; +# +$conf['allowed_for_pages'] = "EVERYONE"; + +# +# Which timerange should be used for the host overview site ? +# use a key from array $views[] +# +$conf['overview-range'] = 1 ; + +# +# Scale the preview images used in /popup +# +$conf['popup-width'] = "300px"; + +# +# jQuery UI Theme +# http://jqueryui.com/themeroller/ +# Possible values are: lightness, smoothness, redmond, multisite +$conf['ui-theme'] = 'smoothness'; + +# Language definitions to use. +# valid options are en_US, de_DE, es_ES, ru_RU, fr_FR +# +$conf['lang'] = "en_US"; + +# +# Date format +# +$conf['date_fmt'] = "d.m.y G:i"; + +# +# This option breaks down the template name based on _ and then starts to +# build it up and check the different template directories for a suitable template. +# +# Example: +# +# Template to be used: check_esx3_host_net_usage you create a check_esx3.php +# +# It will find and match on check_esx3 first in templates dir then in templates.dist +# +$conf['enable_recursive_template_search'] = 1; + +# +# Direct link to the raw XML file. +# +$conf['show_xml_icon'] = 1; + +# +# Use FPDF Lib for PDF creation ? +# +$conf['use_fpdf'] = 1; + +# +# Use this file as PDF background. +# +$conf['background_pdf'] = '@sysconfdir@/background.pdf' ; + +# +# Enable Calendar +# +$conf['use_calendar'] = 1; + +# +# Define default views with title and start timerange in seconds +# +# remarks: required escape on " with backslash +# +#$views[] = array('title' => 'One Hour', 'start' => (60*60) ); +$views[] = array('title' => '4 Hours', 'start' => (60*60*4) ); +$views[] = array('title' => '25 Hours', 'start' => (60*60*25) ); +$views[] = array('title' => 'One Week', 'start' => (60*60*25*7) ); +$views[] = array('title' => 'One Month', 'start' => (60*60*24*32) ); +$views[] = array('title' => 'One Year', 'start' => (60*60*24*380) ); + +# +# rrdcached support +# Use only with rrdtool svn revision 1511+ +# +# $conf['RRD_DAEMON_OPTS'] = 'unix:/tmp/rrdcached.sock'; +$conf['RRD_DAEMON_OPTS'] = ''; + +# A list of directories to search for templates +# @datarootdir@/templates.dist is always the last directory to be searched for templates +# +# Add your own template directories here +# First match wins! +#$conf['template_dirs'][] = '/usr/local/check_mk/pnp-templates'; +$conf['template_dirs'][] = '@datarootdir@/templates'; +$conf['template_dirs'][] = '@datarootdir@/templates.dist'; + +# +# Directory to search for special templates +# +$conf['special_template_dir'] = '@datarootdir@/templates.special'; + +# +# Regex to detect mobile devices +# This regex is evaluated against the USER_AGENT String +# +$conf['mobile_devices'] = 'iPhone|iPod|iPad|android'; + +# +# additional colour schemes +# values taken from www.colorbrewer2.org +# for details on usage refer to the documentation of the helper functions +# +$scheme['Reds'] = array ('#FEE0D2','#FCBBA1','#FC9272','#FB6A4A','#EF3B2C','#CB181D','#A50F15','#67000D'); +$scheme['Greens'] = array ('#E5F5E0','#C7E9C0','#A1D99B','#74C476','#41AB5D','#23AB45','#006D2C','#00441B'); +$scheme['Blues'] = array ('#DEEBF7','#C6DBEF','#9ECAE1','#6BAED6','#4292C6','#2171B5','#08519C','#08306B'); +$scheme['Oranges'] = array ('#FEE6CE','#FDD0A2','#FDAE6B','#FD8D3C','#F16913','#D94801','#A63603','#7F2704'); +$scheme['Purples'] = array ('#EFEDF5','#DADAEB','#BDBDDC','#9E9AC8','#807DBA','#6A51A3','#54278F','#3F007A'); +$scheme['RdPu'] = array ('#FDE0DD','#FCC5C0','#FA9FB5','#F768A1','#DD3497','#AE017E','#7A0177','#49006A'); +$scheme['Dark2'] = array ('#1B9E77','#D95F02','#7570B3','#E7298A','#66A61E','#E6ab02','#a6761d','#666666'); +$scheme['BrBG'] = array ('#543005','#8C510A','#BF812D','#DFC27D','#F6E8C3','#C7EAE5','#80CDC1','#35978F','#01665E','#003C30'); +$scheme['PiYG'] = array ('#8E0152','#C51B7D','#DE77AE','#F1B6DA','#FDE0EF','#E6F5D0','#B8E186','#7FBC41','#4D9221','#276419'); +$scheme['PRGn'] = array ('#40004B','#762A83','#9970AB','#C2A5CF','#E7D4E8','#D9F0D3','#A6DBA0','#5AAE61','#1B7837','#00441B'); +$scheme['PuOr'] = array ('#7F3B08','#B35806','#E08214','#FDB863','#FEE0B6','#D8DAEB','#B2ABD2','#8073AC','#542788','#2D004B'); +$scheme['RdBu'] = array ('#67001F','#B2182B','#D6604D','#F4A582','#FDDBC7','#D1E5F0','#92C5DE','#4393C3','#2166AC','#053061'); +$scheme['RdGy'] = array ('#67001F','#B2182B','#D6604D','#F4A582','#FDDBC7','#E0E0E0','#BABABA','#878787','#4D4D4D','#1A1A1A'); +$scheme['RdYlBu'] = array ('#A50026','#D73027','#F46D43','#FDAE61','#FEE090','#E0F3F8','#ABD9E9','#74ADD1','#4575B4','#313695'); +$scheme['RdYlGn'] = array ('#A50026','#D73027','#F46D43','#FDAE61','#FEE08B','#D9EF8B','#A6D96A','#66BD63','#1A9850','#006837'); +$scheme['Spectral'] = array ('#9E0142','#D53E4F','#F46D43','#FDAE61','#FEE08B','#E6F598','#ABDDA4','#66C2A5','#3288BD','#5E4FA2'); +$scheme['Paired'] = array ('#A6CEE3','#1F78B4','#B2DF8A','#33A02C','#FB9A99','#E31A1C','#FDBF6F','#FF7F00','#CAB2D6','#6A3D9A'); +$scheme['mixed1'] = array ('#8C510A','#2166ac','#BF812D','#4393c3','#DFC27D','#92c5de','#F6E8C3','#d1e5f0', + '#fddbc7','#C7EAE5','#f4a582','#80CDC1','#d6604d','#35978F','#b2182b','#01665E'); +$scheme['mixed2'] = array ('#b2182b','#2166ac','#d6604d','#4393c3','#f4a582','#92c5de','#fddbc7','#d1e5f0', + '#F6E8C3','#C7EAE5','#DFC27D','#80CDC1','#BF812D','#35978F','#8C510A','#01665E'); +$scheme['mixed3'] = array ('#67001F','#80CDC1','#B2182B','#35978F','#D6604D','#01665E','#F4A582','#003C30', + '#FDDBC7','#92C5DE','#D1E5F0','#2166AC','#4393C3','#8C510A','#053061','#BF812D'); +?> diff --git a/sample-config/pnp/npcd.cfg-sample.in b/sample-config/pnp/npcd.cfg-sample.in new file mode 100644 index 0000000..7811530 --- /dev/null +++ b/sample-config/pnp/npcd.cfg-sample.in @@ -0,0 +1,195 @@ +# NPCD.cfg - sample configuration file for PNPs NPCD +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation; +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Privilege Options + +user = @nagios_user@ +group = @nagios_grp@ + +######################### +# # +# Logging Options # +# # +######################### + +# log_type - define if you want your logs to +# 'syslog' or to a 'file' +# +# log_type = +# + +#log_type = file +log_type = syslog + + +# log_file - define a path to your logfile +# needed if 'log_type'='file' +# +# log_file =
    +# + +log_file = @localstatedir@/npcd.log + + +# max_logfile_size - defines the maximum filesize (bytes) +# before the logfile will rotated. +# +# max_logfile_size = (default 10Mbyte) +# + +max_logfile_size = 10485760 + + +# log_level - how much should we log? +# +# log_level = +# +# 0 = No logging - except errors +# 1 = Small logging - some few more output +# 2 = More Logging (actual ALL logs) +# -1 = DEBUG Mode - ALL Logging and slower processing +# + +log_level = 0 + +######################### +# # +# NEEDED OPTIONS # +# # +######################### + +# perfdata_spool_dir - where we can find the +# performance data files +# +# perfdata_spool_dir =
    +# + +perfdata_spool_dir = @PERFDATA_SPOOL_DIR@ + + +# Execute following command for each found file +# in 'perfdata_spool_dir' +# +# perfdata_file_run_cmd = +# +# Must be executable by user/group from above +# +# perfdata_file_run_cmd = +# + +perfdata_file_run_cmd = @libexecdir@/@pp_pl_name@ + + +# perfdata_file_run_cmd_args (optional) +# +# If you wish, you can apply more arguments to the +# perfdata_file_run_cmd +# +# Hint: +# NPCD will create a command line like this: +# ' ' +# + +perfdata_file_run_cmd_args = --bulk + + +# identify_npcd (optional) +# +# If set to one (by default) npcd will append +# '-n' to the perfdata_file_run_cmd +# +# identify_npcd = 0|1 (default: 1) + +identify_npcd = 1 + + +# npcd_max_threads - define how many parallel threads we +# should start + +npcd_max_threads = 5 + +# sleep_time - how many seconds npcd should wait between dirscans +# +# sleep_time = 15 (default) + +sleep_time = 15 + + +# EXPERIMENTAL +# +# load_threshold - npcd won't start new threads +# if your system load is above this threshold +# +# load_threshold = (default: 0.0) +# +# Hint: Do not use "," as decimal delimiter +# +# 07/15/2008: Every value above 0.0 will +# enable this feature + +load_threshold = 0.0 + + +# location of your pid file + +pid_file=/var/run/npcd.pid + + +######################### +# # +# NPCDMOD OPTIONS # +# # +######################### + + +# perfdata_file - where should the npcdmod.o +# write the performance data +# +# must not be within the same directory as +# perfdata_spool_dir +# +# perfdata_file = +# + +perfdata_file = @localstatedir@/perfdata.dump + + +# perfdata_spool_filename - declare the destination +# filename for the spooled files +# +# This option allows you a customized filename. +# Usefull if you own different nagios servers +# which write their data to a shared storage. +# +# perfdata_spool_filename = +# +# Hint: +# The final files will be moved to +# 'perfdata_spool_dir/perfdata_spool_filename-TIMESTAMP' +# +# Example: +# +# perfdata_spool_filename = perfdata-NY +# perfdata_spool_filename = perfdata-LA + +perfdata_spool_filename = perfdata + +# +# perfdata_file_processing_interval +# +perfdata_file_processing_interval = 15 + +# We have to end with a newline + diff --git a/sample-config/pnp/pages/web_traffic.cfg-sample b/sample-config/pnp/pages/web_traffic.cfg-sample new file mode 100644 index 0000000..0d0c80a --- /dev/null +++ b/sample-config/pnp/pages/web_traffic.cfg-sample @@ -0,0 +1,23 @@ +# +# Sample Page Config +# +# Global Section +# use_regex [0|1] +# page_name < your page title > +# background_pdf + +define page { + use_regex 1 + page_name Webserver Traffic +} + +# +# Define the first Graph +# +define graph { + host_name ^websrv # Every host starting with 'websrv' + service_desc ^traffic # Every service starting with 'traffic' + source 0 # OPTIONAL Show only the first image +} + + diff --git a/sample-config/pnp/pnp4nagios_release.in b/sample-config/pnp/pnp4nagios_release.in new file mode 100644 index 0000000..b4ba121 --- /dev/null +++ b/sample-config/pnp/pnp4nagios_release.in @@ -0,0 +1,8 @@ +PKG_REL_DATE="@PKG_REL_DATE@" +PKG_VERSION="@PKG_VERSION@" +PKG_NAME="@PKG_NAME@" + +# +# Configure Arguments +# +CONFIGURE_ARGS=@ac_configure_args@ diff --git a/sample-config/pnp/process_perfdata.cfg-sample.in b/sample-config/pnp/process_perfdata.cfg-sample.in new file mode 100644 index 0000000..67a7c4c --- /dev/null +++ b/sample-config/pnp/process_perfdata.cfg-sample.in @@ -0,0 +1,135 @@ +# @PKG_NAME@–@PKG_VERSION@ +# Config File for process_perfdata.pl +# +# More info on RRDtool can be found at www.rrdtool.org + +# +# process_perfdata.pl timeout in seconds +# +TIMEOUT = 15 + +# +# Use RRDs Perl module +# +USE_RRDs = 1 + +# +# Path to XML/RRD files +# +RRDPATH = @PERFDATA_DIR@ + +# +# Location of RRDtool binary +# +RRDTOOL = @RRDTOOL@ + +# +# Location of PNP config files +# +CFG_DIR = @sysconfdir@ + +# +# Use a single RRD database per service +# one or more datasources per RRD database +# RRD_STORAGE_TYPE = SINGLE +# +# Use multiple RRD databases per service +# one RRD database per datasource. +# RRD_STORAGE_TYPE = MULTIPLE +# +RRD_STORAGE_TYPE = SINGLE + +# +# Max. interval between samples/updates +# +RRD_HEARTBEAT = 8460 + +# +# File with RRA options used to create new RRD files +# +RRA_CFG = @sysconfdir@/rra.cfg + +# +# Interval at which PDPs are generated +# +RRA_STEP = 60 + +# +# Name of the log file +# +LOG_FILE = @PERFDATA_LOG@ + +# +# Loglevel 0=silent 1=normal 2=debug +# +LOG_LEVEL = @DEBUG@ + +# +# XML encoding +# The supported encodings are ISO-8859-1, UTF-8 and US-ASCII. +# http://www.php.net/xml-parser-create +# +XML_ENC = UTF-8 + +# +# XML update delay in seconds +# 0 = Update XML Files everytime new data arrives +# +# Use this option to reduce disk I/O +# +XML_UPDATE_DELAY = 0 + +# +# Use only with RRDtool svn revision 1511+ +# +# RRD_DAEMON_OPTS = unix:/tmp/rrdcached.sock +RRD_DAEMON_OPTS = + +# +# Spool directory used for internal statistics +# +STATS_DIR = @localstatedir@/stats + + +######################################################### +# Gearman Worker Config +# Only used when running as Gearman worker + +# +# How many child processes +# +PREFORK = 1 + +# +# Gearman server to connect to +# Comma separated list of Gearman job servers +# +GEARMAN_HOST = localhost:4730 + +# +# Restart child process after a given count of requests +# +REQUESTS_PER_CHILD = 10000 + +# +# Enables or disables encryption. +# It is strongly advised to not disable encryption, or +# anybody will be able to inject packages to your worker. +# When using encryption, you will have to specify a shared +# secret eithr via the KEY or the KEY_FILE option. +# Default is 1. +# +ENCRYPTION = 1 + +# +# A shared password which will be used for +# encryption of data pakets. Should be at least 8 +# bytes long. Maximum length is 32 characters. +# +KEY = should_be_changed + +# +# The shared password will be read from this file. +# Only the first 32 characters will be used. +# +# KEY_FILE = @sysconfdir@/secret.key diff --git a/sample-config/pnp/rra.cfg-sample b/sample-config/pnp/rra.cfg-sample new file mode 100644 index 0000000..7c427f5 --- /dev/null +++ b/sample-config/pnp/rra.cfg-sample @@ -0,0 +1,36 @@ +# +# Define the default RRA Step in seconds +# More Infos on +# http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +# +RRA_STEP=60 +# +# PNP default RRA config +# +# you will get 400kb of data per datasource +# +# 2880 entries with 1 minute step = 48 hours +# +RRA:AVERAGE:0.5:1:2880 +# +# 2880 entries with 5 minute step = 10 days +# +RRA:AVERAGE:0.5:5:2880 +# +# 4320 entries with 30 minute step = 90 days +# +RRA:AVERAGE:0.5:30:4320 +# +# 5840 entries with 360 minute step = 4 years +# +RRA:AVERAGE:0.5:360:5840 + +RRA:MAX:0.5:1:2880 +RRA:MAX:0.5:5:2880 +RRA:MAX:0.5:30:4320 +RRA:MAX:0.5:360:5840 + +RRA:MIN:0.5:1:2880 +RRA:MIN:0.5:5:2880 +RRA:MIN:0.5:30:4320 +RRA:MIN:0.5:360:5840 diff --git a/scripts/Makefile.in b/scripts/Makefile.in new file mode 100644 index 0000000..ebcee9a --- /dev/null +++ b/scripts/Makefile.in @@ -0,0 +1,52 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +LOGDIR=@localstatedir@ +CFGDIR=@sysconfdir@ +BINDIR=@bindir@ +LIBEXECDIR=@libexecdir@ +CGIDIR=@sbindir@ +INIT_DIR=@init_dir@ +INIT_OPTS=-o root -g root +HTMLDIR=@datarootdir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +PERFDATADIR=@PERFDATA_DIR@ + +CP=@CP@ + +all html: + +clean: + +distclean: clean + -rm -f process_perfdata.pl check_pnp_rrds.pl net2pnp.pl rc.npcd rc.pnp_gearman_worker rrd_convert.pl + -rm -f Makefile + +devclean: distclean + +install-init: + $(INSTALL) -m 755 $(INIT_OPTS) -d $(DESTDIR)$(INIT_DIR) + $(INSTALL) -m 755 $(INIT_OPTS) rc.npcd $(DESTDIR)$(INIT_DIR)/npcd + $(INSTALL) -m 755 $(INIT_OPTS) rc.pnp_gearman_worker $(DESTDIR)$(INIT_DIR)/pnp_gearman_worker + +install-processperfdata: + $(INSTALL) -m 755 $(INSTALL_OPTS) process_perfdata.pl $(DESTDIR)$(LIBEXECDIR) + +install-plugins: + $(INSTALL) -m 755 $(INSTALL_OPTS) check_pnp_rrds.pl $(DESTDIR)$(LIBEXECDIR) + +install-rrdconvert: + $(INSTALL) -m 755 $(INSTALL_OPTS) rrd_convert.pl $(DESTDIR)$(LIBEXECDIR) + +install-rrdmodify: + $(INSTALL) -m 755 $(INSTALL_OPTS) rrd_modify.pl $(DESTDIR)$(LIBEXECDIR) + +install: + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(PERFDATADIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBEXECDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR)/stats + $(MAKE) install-processperfdata + $(MAKE) install-plugins + $(MAKE) install-rrdconvert + $(MAKE) install-rrdmodify + diff --git a/scripts/check_pnp_rrds.pl.in b/scripts/check_pnp_rrds.pl.in new file mode 100644 index 0000000..be08e52 --- /dev/null +++ b/scripts/check_pnp_rrds.pl.in @@ -0,0 +1,298 @@ +#!@PERL@ +# nagios: -epn +## check_pnp_rrds - PNP4Nagios. +## Copyright (c) 2006-2009 Joerg Linge (http://www.pnp4nagios.org) +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +use File::Find; +use File::Basename; +use warnings; +use strict; +use Getopt::Long; + +my $read_input; +if (eval {require "Term/ReadKey.pm"}) { + import Term::ReadKey; + $read_input = \&read_key; +} else { + $read_input = \&read_stdin; +} + +Getopt::Long::Configure('bundling'); +my ( $opt_V, $opt_h, $opt_b ); +my $opt_a = 7; +my $opt_dxml = 0; +my $opt_drrd = 0; +my $opt_w = 1; +my $opt_c = 10; +my $opt_t = 10; +my $opt_p = "@PERFDATA_DIR@"; +my $opt_ncmd = "/usr/local/nagios/var/rw/nagios.cmd"; +my $opt_phost = ""; +my $opt_pservice = ""; +my $opt_ignore; +my $VERSION = "@PKG_VERSION@"; +my $PROGNAME = basename($0); +my $PASV = 0; +my $USER = getpwuid($<); + +sub print_help () ; +sub print_usage () ; + +GetOptions( + "V" => \$opt_V, + "version" => \$opt_V, + "h" => \$opt_h, + "help" => \$opt_h, + "t=i" => \$opt_t, + "timeout=i" => \$opt_t, + "w=i" => \$opt_w, + "warning=i" => \$opt_w, + "c=i" => \$opt_c, + "critical=i" => \$opt_c, + "fileage=i" => \$opt_a, + "a=i" => \$opt_a, + "deletexml" => \$opt_dxml, + "deleterrd" => \$opt_drrd, + "p=s" => \$opt_p, + "rrdpath=s" => \$opt_p, + "passiv-hostname=s" => \$opt_phost, + "passiv-servicedesc=s" => \$opt_pservice, + "nagios-cmd=s" => \$opt_ncmd, + "ignore-hosts=s" => \$opt_ignore, +) or print_help(); + + + +print_help() if ($opt_h); + +my $RRD_ERRORS = 0; +my $RRD_ERR = ""; +my $RRD_AGE = ""; +my $XML_COUNT_AGE = 0; +my $XML_COUNT = 0; +my $RRD_COUNT = 0; +my $RC = 0; +my $OUT = "OK: "; +my $PERF = ""; + +$SIG{'ALRM'} = sub { + print "UNKNOWN: Timeout after $opt_t sec.\n"; + exit 3; +}; + +alarm($opt_t); + +$PASV = 1 if($opt_phost && $opt_pservice && $opt_ncmd); + +if($PASV == 1 && !-e $opt_ncmd){ + print "\n\nUNKNOWN: $opt_ncmd does not exist\n\n"; + print_usage(); + exit 3; +} + +if($PASV == 1 && !-w $opt_ncmd){ + print "\n\nUNKNOWN: $opt_ncmd is not writable by \"$USER\" \n\n"; + print_usage(); + exit 3; +} + +if ( -r $opt_p ) { + find { no_chdir => 1, + wanted => \&inspect_files, + } => $opt_p +} +else { + print "UNKNOWN: $opt_p not readable\n"; + exit 3; +} + +sub inspect_files { + my $file = $File::Find::name; + return unless m/\.xml$/; + return unless -f $file; + my $found = -1; + my $TXT = "invalid xml file"; + my $host; + my $service; + my $dir = $File::Find::dir; + if ( $file =~ /\.xml/ ) { + $service = basename($file); + $host = dirname($file); + $host = basename($host); + + if ( defined $opt_ignore && $host =~ $opt_ignore ) { + return; + } + + $XML_COUNT++; + open F, $file or print "couldn't open $file\n" && return; + while () { + if (m/(.*)<\/RC>/) { + $found = $1; + } + if ( $found != 0 && m/(.*)<\/TXT>/ ) { + $TXT = $1; + last; + } + } + close F; + my $mtime = ( stat($file) )[9]; + my $fileage = ( ( time() - $mtime ) / 86400 ); + if ( $fileage >= ( $opt_a ) ) { + if ($opt_dxml) { + print $host . " / " . $service . " is ".$fileage." days old. Delete? (y/n/q) "; + my $ret1 = &$read_input; +# my $ret1 = <>; + if ($ret1 =~ /y/i) { + if (! unlink($file)) { + print " ...Deletion of $file failed!"; + } else { + print " ...Deleted file $file."; + } + } elsif ($ret1 =~ /q/i) { + exit; + } + print "\n"; + + if ($opt_drrd) { + my $rrd = $file; + $rrd =~ s/\.[^.]+$//; + $rrd .= ".rrd"; + if (-e $rrd) { + print " Delete " . basename($rrd) . "? (y/n/q) "; + my $ret2 = &$read_input; + if ($ret2 =~ /y/i) { + unlink($rrd) ? print " $rrd deleted." : print " Deletion of $rrd failed."; + } elsif ($ret2 =~/q/i) { + exit; + } + } + } + print "\n\n"; + } else { + $XML_COUNT_AGE++; + $RRD_AGE .= sprintf(".../%s/%s is %d days old.\n",$host,$service,$fileage); + } + } + $RRD_ERRORS++ if $found != "0"; + $RRD_ERR .= ".../$host/$service $TXT\n" if $found != 0; + } + else { + return; + } +} + +sub PROCESS_SERVICE_CHECK_RESULT { + my $RC = shift; + my $OUT = shift; + my $time = time(); + my $CommandLine = "[$time] PROCESS_SERVICE_CHECK_RESULT;$opt_phost;$opt_pservice;$RC;$OUT"; + + print "PROCESS_SERVICE_CHECK_RESULT\n"; + print $OUT; + + open(CommandFile, ">>$opt_ncmd"); + print CommandFile $CommandLine; + close CommandFile; +} + + +if ( $XML_COUNT == 0 ) { + print "UNKNOWN: No XML files found in $opt_p\n"; + exit 3; +} + +if ( $RRD_ERRORS >= $opt_w || $XML_COUNT_AGE >= $opt_w ) { + $RC = 1; + $OUT = "WARNING: "; +} +if ( $RRD_ERRORS >= $opt_c || $XML_COUNT_AGE >= $opt_c ) { + $RC = 2; + $OUT = "CRITICAL: "; +} + +$OUT .= "$XML_COUNT XML Files checked. $RRD_ERRORS RRD Errors found. $XML_COUNT_AGE old XML Files found"; +$PERF = " | total=$XML_COUNT errors=$RRD_ERRORS;$opt_w;$opt_c;0;$XML_COUNT old=$XML_COUNT_AGE;$opt_w;$opt_c;0;$XML_COUNT\n"; +$OUT .= $PERF . $RRD_ERR . $RRD_AGE; +if($PASV == 0){ + print $OUT; + exit $RC; +}else{ + PROCESS_SERVICE_CHECK_RESULT($RC,$OUT); +} + +sub print_help (){ + print "Copyright (c) 2008 Joerg Linge, Pitchfork\@pnp4nagios.org\n\n"; + print "\n"; + print "$PROGNAME $VERSION\n"; + print "$PROGNAME is used to find old or unusable RRD Files\n"; + print "\n"; + print_usage(); + print "\n"; + print "\n"; + print_support(); + exit 3; +} + +sub print_usage () { + print "USAGE: $PROGNAME [OPTIONS]\n"; + print " -w,--warning\n"; + print " Default: $opt_w\n"; + print " -c,--critical\n"; + print " Default: $opt_c\n"; + print " -a,--fileage Max XML File Age.\n"; + print " Default: $opt_a Days\n"; + print " -p,--rrdpath Path to your RRD and XML Files.\n"; + print " Default: $opt_p\n"; + print " -t,--timeout Max Plugin Runtime.\n"; + print " Default: $opt_t Seconds\n"; + print " --ignore-hosts \n"; + print " Regular expression to ignore a set of hosts"; + print "\n\n"; + print " --deletexml\n"; + print " delete old XML files (interactive). \n"; + print " --deleterrd\n"; + print " delete old RRD files (interactive, only if --deletexml). \n"; + print "\n\n"; + print " --passiv-hostname=\n"; + print " Nagios Hostname\n"; + print " --passiv-servicedesc=\n"; + print " Nagios Servicedesc\n"; + print " --nagios-cmd=\n"; + print " External Command File (nagios.cmd)\n"; + +} + +sub print_support { + print "SUPPORT: http://www.pnp4nagios.org/pnp/\n"; + print "\n\n"; +} + +sub read_stdin { + my $rk; + $rk = <>; + return $rk; +} + +sub read_key { + my $rk; + ReadMode('cbreak'); + $rk = ReadKey(0); + ReadMode('normal'); + return $rk; +} +# vim: set ai tabstop=4 shiftwidth=4 diff --git a/scripts/process_perfdata.pl.in b/scripts/process_perfdata.pl.in new file mode 100644 index 0000000..4cc3d83 --- /dev/null +++ b/scripts/process_perfdata.pl.in @@ -0,0 +1,1596 @@ +#!@PERL@ +# nagios: -epn +## @PKG_NAME@–@PKG_VERSION@ +## Copyright (c) 2005-2010 Joerg Linge (http://www.pnp4nagios.org) +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +@PERL_LIB_PATH_CODE@ + +if( $< == 0 ){ + print "dont try this as root \n"; + exit 1; +} + +use warnings; +use strict; +use POSIX; +use Getopt::Long; +use Time::HiRes qw(gettimeofday tv_interval); +use vars qw ( $TEMPLATE %NAGIOS $t0 $t1 $rt $delayed_write $rrdfile @ds_create $count $line $name $ds_update $dstype %CTPL); + +my %conf = ( + TIMEOUT => 15, + CFG_DIR => "@sysconfdir@/", + USE_RRDs => 1, + RRDPATH => "@PERFDATA_DIR@", + RRDTOOL => "@RRDTOOL@", + RRD_STORAGE_TYPE => "SINGLE", + RRD_HEARTBEAT => 8640, + RRA_STEP => 60, + RRA_CFG => "@sysconfdir@/rra.cfg", + STATS_DIR => "@localstatedir@/stats", + LOG_FILE => "@PERFDATA_LOG@", + LOG_FILE_MAX_SIZE => "10485760", #Truncate after 10MB + LOG_LEVEL => @DEBUG@, + XML_ENC => "UTF-8", + XML_UPDATE_DELAY => 0, # Write XML only if file is older then XML_UPDATE_DELAY seconds + RRD_DAEMON_OPTS => "", + GEARMAN_HOST => "localhost:4730", # How many gearman worker childs to start + PREFORK => 2, # How many gearman worker childs to start + REQUESTS_PER_CHILD => 20000, # Restart after a given count of requests + ENCRYPTION => 1, # Decrypt mod_gearman packets + KEY => 'should_be_changed', + KEY_FILE => '@sysconfdir@/secret.key', + UOM2TYPE => { 'c' => 'DERIVE', 'd' => 'DERIVE' }, +); + +my %const = ( + XML_STRUCTURE_VERSION => "@XML_STRUCTURE_VERSION@", + VERSION => "@PKG_VERSION@", +); + +# +# Dont change anything below these lines ... +# +# +# "rrdtool create" Syntax +# +my @default_rrd_create = ( "RRA:AVERAGE:0.5:1:2880", "RRA:AVERAGE:0.5:5:2880", "RRA:AVERAGE:0.5:30:4320", "RRA:AVERAGE:0.5:360:5840", "RRA:MAX:0.5:1:2880", "RRA:MAX:0.5:5:2880", "RRA:MAX:0.5:30:4320", "RRA:MAX:0.5:360:5840", "RRA:MIN:0.5:1:2880", "RRA:MIN:0.5:5:2880", "RRA:MIN:0.5:30:4320", "RRA:MIN:0.5:360:5840", ); + +Getopt::Long::Configure('bundling'); +my ( $opt_d, $opt_V, $opt_h, $opt_i, $opt_n, $opt_b, $opt_s, $opt_gm, $opt_pidfile,$opt_daemon ); +my $opt_t = my $opt_t_default = $conf{TIMEOUT}; # Default Timeout +my $opt_c = $conf{CFG_DIR} . "process_perfdata.cfg"; +GetOptions( + "V" => \$opt_V, + "version" => \$opt_V, + "h" => \$opt_h, + "help" => \$opt_h, + "i" => \$opt_i, + "inetd" => \$opt_i, + "b=s" => \$opt_b, + "bulk=s" => \$opt_b, + "d=s" => \$opt_d, + "datatype=s" => \$opt_d, + "t=i" => \$opt_t, + "timeout=i" => \$opt_t, + "c=s" => \$opt_c, + "config=s" => \$opt_c, + "n" => \$opt_n, + "npcd" => \$opt_n, + "s" => \$opt_s, + "stdin" => \$opt_s, + "gearman:s" => \$opt_gm, + "daemon" => \$opt_daemon, + "pidfile=s" => \$opt_pidfile, +); + +parse_config($opt_c); +$conf{'GLOBAL_RRD_STORAGE_TYPE'} = uc($conf{'RRD_STORAGE_TYPE'}); # store the initial value for later use + +my %stats = init_stats(); +my $cypher; + +# +# RRDs Perl Module Detection +# +if ( $conf{USE_RRDs} == 1 ) { + unless ( eval "use RRDs;1" ) { + $conf{USE_RRDs} = 0; + } +} + +# +# Include Gearman modules if needed +# +if ( defined($opt_gm) ) { + unless ( eval "use Gearman::Worker;1" ) { + print "Perl module Gearman::Worker not found\n"; + exit 1; + } + unless ( eval "use MIME::Base64;1" ) { + print "Perl module MIME::Base64 not found\n"; + exit 1; + } + unless ( eval "use Crypt::Rijndael;1" ) { + print "Perl module Crypt::Rijndael not found\n"; + exit 1; + } +} + +print_help() if ($opt_h); +print_version() if ($opt_V); + +# Use the timeout specified on the command line and if none use what is in the configuration +# If timeout is not in command line or the config file use the default +$opt_t = $conf{TIMEOUT} if ( $opt_t == $opt_t_default && $opt_t != $conf{TIMEOUT} ); +print_log( "Default Timeout: $opt_t_default secs.", 2 ); +print_log( "Config Timeout: $conf{TIMEOUT} secs.", 2 ); +print_log( "Actual Timeout: $opt_t secs.", 2 ); + +init_signals(); +my %children = (); # keys are current child process IDs +my $children = 0; # current number of children +if( ! defined($opt_gm) ){ + # + # synchronos / bulk / npcd mode + # + main(); +}else{ + # + # Gearman worker main loop + # + print_log( "process_perfdata.pl-$const{VERSION} Gearman Worker Daemon", 0 ); + if($opt_gm =~ /:\d+/ ){ + $conf{'GEARMAN_HOST'} = $opt_gm; + } + if($conf{ENCRYPTION} == 1){ + print_log( "Encryptions is enabled", 0 ); + read_keyfile($conf{'KEY_FILE'}); + # fill key up to 32 bytes + $conf{'KEY'} = substr($conf{'KEY'},0,32) . chr(0) x ( 32 - length( $conf{'KEY'} ) ); + $cypher = Crypt::Rijndael->new( $conf{'KEY'}, Crypt::Rijndael::MODE_ECB() ); + } + daemonize(); +} + +# +# Subs +# +# Main function to switch to the right mode. +sub main { + my $job = shift; + my $t0 = [gettimeofday]; + my $t1; + my $rt; + my $lines = 0; + # Gearman Worker + if (defined $opt_gm) { + print_log( "Gearman Worker Job start", 1 ); + %NAGIOS = parse_env($job->arg); + $lines = process_perfdata(); + $t1 = [gettimeofday]; + $rt = tv_interval $t0, $t1; + $stats{runtime} += $rt; + $stats{rows}++; + if( ( int $stats{timet} / 60 ) < ( int time / 60 )){ + store_internals(); + init_stats(); + } + print_log( "Gearman job end (runtime ${rt}s) ...", 1 ); + return 1; + } elsif ( $opt_b && !$opt_n && !$opt_s ) { + # Bulk mode + alarm($opt_t); + print_log( "process_perfdata.pl-$const{VERSION} starting in BULK Mode called by Nagios", 1 ); + $lines = process_perfdata_file(); + } elsif ( $opt_b && $opt_n && !$opt_s ) { + # Bulk mode with npcd + alarm($opt_t); + print_log( "process_perfdata.pl-$const{VERSION} starting in BULK Mode called by NPCD", 1 ); + $lines = process_perfdata_file(); + } elsif ( $opt_s ) { + # STDIN mode + alarm($opt_t); + print_log( "starting in STDIN Mode", 1 ); + $lines = process_perfdata_stdin(); + } else { + # Synchronous mode + $opt_t = 5 if $opt_t > 5; # maximum timeout + alarm($opt_t); + print_log( "process_perfdata.pl-$const{VERSION} starting in SYNC Mode", 1 ); + %NAGIOS = parse_env(); + $lines = process_perfdata(); + } + $rt = tv_interval $t0, $t1; + $stats{runtime} = $rt; + $stats{rows} = $lines; + store_internals(); + print_log( "PNP exiting (runtime ${rt}s) ...", 1 ); + exit 0; +} + +# +# Parse %ENV and return a global hash %NAGIOS +# +sub parse_env { + my $job_data = shift; + %NAGIOS = (); + $NAGIOS{DATATYPE} = "SERVICEPERFDATA"; + + if(defined $opt_gm){ + # Gearman Worker + $job_data = decode_base64($job_data); + if($conf{ENCRYPTION} == 1){ + $job_data = $cypher->decrypt( $job_data ); + } + my @LINE = split(/\t/, $job_data); + foreach my $k (@LINE) { + $k =~ /([A-Z 0-9_]+)::(.*)$/; + $NAGIOS{$1} = $2 if ($2); + } + if ( !$NAGIOS{HOSTNAME} ) { + print_log( "Gearman job data missmatch. Please check your encryption key.", 0 ); + return %NAGIOS; + } + } elsif ( defined($opt_b) || defined($opt_s) ){ + # Bulk Mode/Stdin Mode + my @LINE = split(/\t/, $job_data); + foreach my $k (@LINE) { + $k =~ /([A-Z 0-9_]+)::(.*)$/; + $NAGIOS{$1} = $2 if ($2); + } + }else{ + + if ( ( !$ENV{NAGIOS_HOSTNAME} ) and ( !$ENV{ICINGA_HOSTNAME} ) ) { + print_log( "Cant find Nagios Environment. Exiting ....", 1 ); + exit 2; + } + foreach my $key ( sort keys %ENV ) { + if ( $key =~ /^(NAGIOS|ICINGA)_(.*)/ ) { + $NAGIOS{$2} = $ENV{$key}; + } + } + + } + + if ($opt_d) { + $NAGIOS{DATATYPE} = $opt_d; + } + + $NAGIOS{DISP_HOSTNAME} = $NAGIOS{HOSTNAME}; + $NAGIOS{DISP_SERVICEDESC} = $NAGIOS{SERVICEDESC}; + $NAGIOS{HOSTNAME} = cleanup( $NAGIOS{HOSTNAME} ); + $NAGIOS{SERVICEDESC} = cleanup( $NAGIOS{SERVICEDESC} ); + $NAGIOS{PERFDATA} = $NAGIOS{SERVICEPERFDATA}; + $NAGIOS{CHECK_COMMAND} = $NAGIOS{SERVICECHECKCOMMAND}; + + if ( $NAGIOS{DATATYPE} eq "HOSTPERFDATA" ) { + $NAGIOS{SERVICEDESC} = "_HOST_"; + $NAGIOS{DISP_SERVICEDESC} = "Host Perfdata"; + $NAGIOS{PERFDATA} = $NAGIOS{HOSTPERFDATA}; + $NAGIOS{CHECK_COMMAND} = $NAGIOS{HOSTCHECKCOMMAND}; + } + print_log( "Datatype set to '$NAGIOS{DATATYPE}' ", 2 ); + return %NAGIOS; +} + +# +# Perfdata sanity check +# +sub process_perfdata { + if ( keys( %NAGIOS ) == 1 && defined($opt_gm) ) { + $stats{skipped}++; + return 1; + } + if ( ! defined($NAGIOS{PERFDATA}) && ! defined($opt_gm) ) { + print_log( "No Performance Data for $NAGIOS{HOSTNAME} / $NAGIOS{SERVICEDESC} ", 1 ); + if ( !$opt_b && !$opt_s ) { + print_log( "PNP exiting ...", 1 ); + exit 3; + } + } + + if ( $NAGIOS{PERFDATA} =~ /^(.*)\s\[(.*)\]$/ ) { + $NAGIOS{PERFDATA} = $1; + $NAGIOS{CHECK_COMMAND} = $2; + print_log( "Found Perfdata from Distributed Server $NAGIOS{HOSTNAME} / $NAGIOS{SERVICEDESC} ($NAGIOS{PERFDATA})", 1 ); + } + else { + print_log( "Found Performance Data for $NAGIOS{HOSTNAME} / $NAGIOS{SERVICEDESC} ($NAGIOS{PERFDATA}) ", 1 ); + } + + $NAGIOS{PERFDATA} =~ s/,/./g; + $NAGIOS{PERFDATA} =~ s/\s+=/=/g; + $NAGIOS{PERFDATA} =~ s/=\s+/=/g; + $NAGIOS{PERFDATA} =~ s/\\n//g; + $NAGIOS{PERFDATA} .= " "; + parse_perfstring( $NAGIOS{PERFDATA} ); + return 1; +} + +# +# Process Perfdata in Bulk Mode +# +sub process_perfdata_file { + if ( $opt_b =~ /-PID-(\d+)/ ) { + print_log( "Oops: $opt_b already processed by $1 - please check timeout settings", 0 ); + } + + print_log( "searching for $opt_b", 2 ); + if ( -e "$opt_b" ) { + my $pdfile = "$opt_b" . "-PID-" . $$; + print_log( "renaming $opt_b to $pdfile for bulk update", 2 ); + unless ( rename "$opt_b", "$pdfile" ) { + print_log( "ERROR: rename $opt_b to $pdfile failed", 1 ); + exit 4; + } + + print_log( "reading $pdfile for bulk update", 2 ); + open( PDFILE, "< $pdfile" ); + my $count = 0; + while () { + my $job_data = $_; + $count++; + print_log( "Processing Line $count", 2 ); + my @LINE = split(/\t/); + %NAGIOS = (); # cleaning %NAGIOS Hash + #foreach my $k (@LINE) { + # $k =~ /([A-Z 0-9_]+)::(.*)$/; + # $ENV{ 'NAGIOS_' . $1 } = $2 if ($2); + #} + parse_env($job_data); + if ( $NAGIOS{SERVICEPERFDATA} || $NAGIOS{HOSTPERFDATA} ) { + process_perfdata(); + } else { + print_log( "No Perfdata. Skipping line $count", 2 ); + $stats{skipped}++; + } + } + + print_log( "$count lines processed", 1 ); + + if ( unlink("$pdfile") == 1 ) { + print_log( "$pdfile deleted", 1 ); + }else { + print_log( "Could not delete $pdfile:$!", 1 ); + } + return $count; + } + else { + print_log( "ERROR: File $opt_b not found", 1 ); + } +} + +# +# Process Perfdata in STDIN Mode +# +sub process_perfdata_stdin { + print_log( "reading from STDIN for bulk update", 2 ); + my $count = 0; + while () { + my $job_data = $_; + $count++; + print_log( "Processing Line $count", 2 ); + my @LINE = split(/\t/); + %NAGIOS = (); # cleaning %NAGIOS Hash + parse_env($job_data); + if ( $NAGIOS{SERVICEPERFDATA} || $NAGIOS{HOSTPERFDATA} ) { + process_perfdata(); + } else { + print_log( "No Perfdata. Skipping line $count", 2 ); + $stats{skipped}++; + } + } + + print_log( "$count lines processed", 1 ); + return $count; +} + +# +# Write Data to RRD Files +# +sub data2rrd { + + my @data = @_; + my @rrd_state = (); + my $rrd_storage_type; + + print_log( "data2rrd called", 2 ); + $NAGIOS{XMLFILE} = $conf{RRDPATH} . "/" . $data[0]{hostname} . "/" . $data[0]{servicedesc} . ".xml"; + $NAGIOS{SERVICEDESC} = $data[0]{servicedesc}; + $NAGIOS{DISP_SERVICEDESC} = $data[0]{disp_servicedesc}; + $NAGIOS{AUTH_SERVICEDESC} = $data[0]{auth_servicedesc} || ""; + $NAGIOS{AUTH_HOSTNAME} = $data[0]{auth_hostname} || ""; + $NAGIOS{MULTI_PARENT} = ""; + $NAGIOS{MULTI_PARENT} = $data[0]{multi_parent} || ""; + $TEMPLATE = $data[0]{template}; + + unless ( -d "$conf{RRDPATH}" ) { + unless ( mkdir "$conf{RRDPATH}" ) { + print_log( "mkdir $conf{RRDPATH}, permission denied ", 1 ); + print_log( "PNP exiting ...", 1 ); + exit 5; + } + } + + unless ( -d "$conf{RRDPATH}/$NAGIOS{HOSTNAME}" ) { + unless ( mkdir "$conf{RRDPATH}/$NAGIOS{HOSTNAME}" ) { + print_log( "mkdir $conf{RRDPATH}/$NAGIOS{HOSTNAME}, permission denied ", 1 ); + print_log( "PNP exiting ...", 1 ); + exit 6; + } + } + + # + # Create PHP Template File + # + open_template( $NAGIOS{XMLFILE} ); + + @ds_create = (); + $ds_update = ''; + + for my $i ( 0 .. $#data ) { + print_log( " -- Job $i ", 3 ); + my $DS = $i + 1; + + # + # for each datasource + # + for my $job ( sort keys %{ $data[$i] } ) { + if ( defined $data[$i]{$job} ) { + print_log( " -- $job -> $data[$i]{$job}", 3 ); + } + } + + if ( uc($conf{'GLOBAL_RRD_STORAGE_TYPE'}) eq "MULTIPLE" ) { + my $file = $conf{RRDPATH} . "/" . $data[$i]{hostname} . "/" . $data[$i]{servicedesc} . ".rrd"; + if ( -e $file ){ + print_log("RRD_STORAGE_TYPE=MULTIPLE ignored because $file exists!", 1 ) if $i == 0; + $data[$i]{rrd_storage_type} = "SINGLE"; + } + } + + if ( $i == 0 ){ + $ds_update = "$data[$i]{timet}"; + } + + if ( $data[$i]{rrd_storage_type} eq "MULTIPLE" ) { + print_log( "DEBUG: MULTIPLE Storage Type", 3 ); + $DS = 1; + # PNP 0.4.x Template compatibility + $NAGIOS{RRDFILE} = ""; + + # + $rrd_storage_type = "MULTIPLE"; + $rrdfile = $conf{RRDPATH} . "/" . $data[$i]{hostname} . "/" . $data[$i]{servicedesc} . "_" . $data[$i]{name} . ".rrd"; + + # DS is set to 1 + @ds_create = "DS:$DS:$data[$i]{dstype}:$data[$i]{rrd_heartbeat}:$data[$i]{rrd_min}:$data[$i]{rrd_max}"; + $ds_update = "$data[$i]{timet}:$data[$i]{value}"; + @rrd_state = write_rrd(); + @ds_create = (); + $ds_update = ""; + } + else { + print_log( "DEBUG: SINGLE Storage Type", 3 ); + + # PNP 0.4.x Template compatibility + $NAGIOS{RRDFILE} = $conf{RRDPATH} . "/" . $data[0]{hostname} . "/" . $data[0]{servicedesc} . ".rrd"; + + # + $rrd_storage_type = "SINGLE"; + $rrdfile = $conf{RRDPATH} . "/" . $data[$i]{hostname} . "/" . $data[$i]{servicedesc} . ".rrd"; + push( @ds_create, "DS:$DS:$data[$i]{dstype}:$data[$i]{rrd_heartbeat}:$data[$i]{rrd_min}:$data[$i]{rrd_max}" ); + $ds_update = "$ds_update:$data[$i]{value}"; + } + + write_to_template( "TEMPLATE", $data[0]{template} ); + write_to_template( "RRDFILE", $rrdfile ); + write_to_template( "RRD_STORAGE_TYPE", $data[$i]{rrd_storage_type} ); + write_to_template( "RRD_HEARTBEAT", $data[$i]{rrd_heartbeat} ); + write_to_template( "IS_MULTI", $data[0]{multi} ); + write_to_template( "DS", $DS ); + write_to_template( "NAME", $data[$i]{name} ); + write_to_template( "LABEL", $data[$i]{label} ); + write_to_template( "UNIT", $data[$i]{uom} ); + write_to_template( "ACT", $data[$i]{value} ); + write_to_template( "WARN", $data[$i]{warning} ); + write_to_template( "WARN_MIN", $data[$i]{warning_min} ); + write_to_template( "WARN_MAX", $data[$i]{warning_max} ); + write_to_template( "WARN_RANGE_TYPE", $data[$i]{warning_range_type} ); + write_to_template( "CRIT", $data[$i]{critical} ); + write_to_template( "CRIT_MIN", $data[$i]{critical_min} ); + write_to_template( "CRIT_MAX", $data[$i]{critical_max} ); + write_to_template( "CRIT_RANGE_TYPE", $data[$i]{critical_range_type} ); + write_to_template( "MIN", $data[$i]{min} ); + write_to_template( "MAX", $data[$i]{max} ); + + } + + if ( $rrd_storage_type eq "SINGLE" ) { + @rrd_state = write_rrd(); + } + + write_state_to_template(@rrd_state); + write_env_to_template(); + close_template( $NAGIOS{XMLFILE} ); +} + +sub write_rrd { + my @rrd_create = (); + my @rrd_state = (); + + print_log( "DEBUG: TPL-> $TEMPLATE", 3 ); + print_log( "DEBUG: CRE-> @ds_create", 3 ); + print_log( "DEBUG: UPD-> $ds_update", 3 ); + + if ( !-e "$rrdfile" ) { + @rrd_create = parse_rra_config($TEMPLATE); + if ( $conf{USE_RRDs} == 1 ) { + print_log( "RRDs::create $rrdfile @rrd_create @ds_create --start=$NAGIOS{TIMET} --step=$conf{RRA_STEP}", 2 ); + RRDs::create( "$rrdfile", @rrd_create, @ds_create, "--start=$NAGIOS{TIMET}", "--step=$conf{RRA_STEP}" ); + + my $err = RRDs::error(); + if ($err) { + print_log( "RRDs::create $rrdfile @rrd_create @ds_create --start=$NAGIOS{TIMET} --step=$conf{RRA_STEP}", 0 ); + print_log( "RRDs::create ERROR $err", 0 ); + @rrd_state = ( 1, $err ); + $stats{error}++; + } + else { + print_log( "$rrdfile created", 2 ); + @rrd_state = ( 0, "just created" ); + $stats{create}++; + } + } + else { + print_log( "RRDs Perl Modules are not installed. Falling back to rrdtool system call.", 2 ); + print_log( "$conf{RRDTOOL} create $rrdfile @rrd_create @ds_create --start=$NAGIOS{TIMET} --step=$conf{RRA_STEP}", 2 ); + system("$conf{RRDTOOL} create $rrdfile @rrd_create @ds_create --start=$NAGIOS{TIMET} --step=$conf{RRA_STEP}"); + if ( $? > 0 ) { + print_log( "$conf{RRDTOOL} create $rrdfile @rrd_create @ds_create --start=$NAGIOS{TIMET} --step=$conf{RRA_STEP}", 0 ); + print_log( "rrdtool create returns $?", 0 ); + @rrd_state = ( $?, "create failed" ); + $stats{error}++; + } + else { + print_log( "rrdtool create returns $?", 1 ); + @rrd_state = ( 0, "just created" ); + $stats{create}++; + } + } + } + else { + if ( $conf{USE_RRDs} == 1 ) { + if ( $conf{RRD_DAEMON_OPTS} ) { + print_log( "RRDs::update --daemon=$conf{RRD_DAEMON_OPTS} $rrdfile $ds_update", 2 ); + RRDs::update( "--daemon=$conf{RRD_DAEMON_OPTS}", "$rrdfile", "$ds_update" ); + } + else { + print_log( "RRDs::update $rrdfile $ds_update", 2 ); + RRDs::update( "$rrdfile", "$ds_update" ); + } + my $err = RRDs::error(); + if ($err) { + print_log( "RRDs::update $rrdfile $ds_update", 0 ); + print_log( "RRDs::update ERROR $err", 0 ); + @rrd_state = ( 1, $err ); + $stats{error}++; + } + else { + print_log( "$rrdfile updated", 2 ); + @rrd_state = ( 0, "successful updated" ); + $stats{update}++; + } + } + else { + print_log( "RRDs Perl Modules are not installed. Falling back to rrdtool system call.", 2 ); + if ( $conf{RRD_DAEMON_OPTS} ) { + print_log( "$conf{RRDTOOL} update --daemon=$conf{RRD_DAEMON_OPTS} $rrdfile $ds_update", 2 ); + system("$conf{RRDTOOL} update --daemon=$conf{RRD_DAEMON_OPTS} $rrdfile $ds_update"); + } + else { + print_log( "$conf{RRDTOOL} update $rrdfile $ds_update", 2 ); + system("$conf{RRDTOOL} update $rrdfile $ds_update"); + } + if ( $? > 0 ) { + print_log( "$conf{RRDTOOL} update $rrdfile $ds_update", 0 ); + print_log( "rrdtool update returns $?", 0 ); + @rrd_state = ( $?, "update failed" ); + $stats{error}++; + } + else { + print_log( "rrdtool update returns $?", 1 ); + @rrd_state = ( $?, "successful updated" ); + $stats{update}++; + } + } + } + return @rrd_state; +} + +# +# Write Template +# +sub open_template { + my $xmlfile = shift; + $delayed_write = 0; + if( -e $xmlfile ){ + my $mtime = (stat($xmlfile))[9]; + my $t = time(); + my $age = ($t - $mtime); + if ( $age < $conf{'XML_UPDATE_DELAY'} ){ + print_log( "DEBUG: XML File is $age seconds old. No update needed", 3 ); + $delayed_write = 1; + return; + } + print_log( "DEBUG: XML File is $age seconds old. UPDATE!", 3 ); + } + open( XML, "> $xmlfile.$$" ) or die "Cant create temporary XML file ", $!; + print XML "\n"; + print XML "\n"; +} + +# +# Close Template FH +# +sub close_template { + return if $delayed_write == 1; + my $xmlfile = shift; + printf( XML " \n" ); + printf( XML " %d\n", $const{'XML_STRUCTURE_VERSION'} ); + printf( XML " \n" ); + + printf( XML "\n" ); + close(XML); + rename( "$xmlfile.$$", "$xmlfile" ); +} + +# +# Add Lines +# +sub write_to_template { + return if $delayed_write == 1; + my $tag = shift; + my $data = shift; + if ( !defined $data ) { + $data = ""; + } + if ( $tag =~ /^TEMPLATE$/ ) { + printf( XML " \n" ); + printf( XML " <%s>%s\n", $tag, "$data", $tag ); + } + elsif ( $tag =~ /^MAX$/ ) { + printf( XML " <%s>%s\n", $tag, "$data", $tag ); + printf( XML " \n" ); + } + else { + printf( XML " <%s>%s\n", $tag, "$data", $tag ); + } +} + +sub write_state_to_template { + return if $delayed_write == 1; + my @rrd_state = @_; + printf( XML " \n" ); + printf( XML " %s\n", $rrd_state[0] ); + printf( XML " %s\n", $rrd_state[1] ); + printf( XML " \n" ); +} + +# +# Store the complete Nagios ENV +# +sub write_env_to_template { + return if $delayed_write == 1; + foreach my $key ( sort keys %NAGIOS ) { + $NAGIOS{$key} = urlencode($NAGIOS{$key}); + printf( XML " %s\n", $key, $NAGIOS{$key}, $key ); + } +} + +# +# Recursive Template search +# +sub adjust_template { + my $command = shift; + my $uom = shift; + my $count = shift; + my @temp_template = split /\!/, $command; + my $initial_template = cleanup( $temp_template[0] ); + my $template = cleanup( $temp_template[0] ); + %CTPL = ( + UOM => $uom, + COUNT => $count, + COMMAND => $command, + TEMPLATE => $template, + DSTYPE => $dstype, + RRD_STORAGE_TYPE => $conf{'RRD_STORAGE_TYPE'}, + RRD_HEARTBEAT => $conf{'RRD_HEARTBEAT'}, + USE_MIN_ON_CREATE => 0, + USE_MAX_ON_CREATE => 0, + ); + + read_custom_template ( ); + # + if ( $CTPL{'TEMPLATE'} ne $initial_template ){ + read_custom_template ( ); + } + return %CTPL; +} + + +# +# Analyse check_command to find PNP Template . +# +sub read_custom_template { + my $command = $CTPL{'COMMAND'}; + my $uom = $CTPL{'UOM'}; + my $count = $CTPL{'COUNT'}; + my @dstype_list = (); + my $use_min_on_create = 0; + my $use_max_on_create = 0; + my $rrd_storage_type = $CTPL{'RRD_STORAGE_TYPE'}; + my $rrd_heartbeat = $CTPL{'RRD_HEARTBEAT'}; + + if ( defined($conf{'UOM2TYPE'}{$uom}) ) { + $dstype = $conf{'UOM2TYPE'}{$uom}; + print_log( "DEBUG: DSTYPE adjusted to $dstype by UOM", 3 ); + }else { + $dstype = 'GAUGE'; + } + + print_log( "DEBUG: RAW Command -> $command", 3 ); + my @temp_template = split /\!/, $command; + my $template = cleanup( $temp_template[0] ); + $template = trim($template); + my $template_cfg = "$conf{CFG_DIR}/check_commands/$template.cfg"; + print_log( "DEBUG: read_custom_template() => $command", 3 ); + if ( -e $template_cfg ) { + print_log( "DEBUG: adjust_template() => $template_cfg", 3 ); + my $initial_dstype = $dstype; + open FH, "<", $template_cfg; + while () { + next if /^#/; + next if /^$/; + s/#.*//; + s/ //g; + if (/^(.*)=(.*)$/) { + if ( $1 eq "DATATYPE" ) { + $dstype = uc($2); + $dstype =~ s/ //g; + @dstype_list = split /,/, $dstype; + if ( exists $dstype_list[$count] && $dstype_list[$count] =~ /^(COUNTER|GAUGE|ABSOLUTE|DERIVE)$/ ) { + $dstype = $dstype_list[$count]; + print_log( "Adapting RRD Datatype to \"$dstype\" as defined in $template_cfg with key $count", 2 ); + } + elsif ( $dstype =~ /^(COUNTER|GAUGE|ABSOLUTE|DERIVE)$/ ) { + print_log( "Adapting RRD Datatype to \"$dstype\" as defined in $template_cfg", 2 ); + } + else { + print_log( "RRD Datatype \"$dstype\" defined in $template_cfg is invalid", 2 ); + $dstype = $initial_dstype; + } + + } + if ( $1 eq "CUSTOM_TEMPLATE" ) { + print_log( "Adapting Template using ARG $2", 2 ); + my $i = 1; + my @keys = split /,/, $2; + foreach my $keys (@keys) { + if ( $i == 1 && exists $temp_template[$keys] ) { + $template = trim( $temp_template[$keys] ); + print_log( "Adapting Template to $template.php (added ARG$keys)", 2 ); + }elsif( exists $temp_template[$keys] ){ + $template .= "_" . trim( $temp_template[$keys] ); + print_log( "Adapting Template to $template.php (added ARG$keys)", 2 ); + } + $i++; + } + print_log( "Adapting Template to $template.php as defined in $template_cfg", 2 ); + } + if ( $1 eq "USE_MIN_ON_CREATE" && $2 eq "1" ) { + $use_min_on_create = 1; + } + if ( $1 eq "USE_MAX_ON_CREATE" && $2 eq "1" ) { + $use_max_on_create = 1; + } + if ( $1 eq "RRD_STORAGE_TYPE" && uc($2) eq "MULTIPLE" ) { + $rrd_storage_type = uc($2); + } + if ( $1 eq "RRD_HEARTBEAT" ) { + $rrd_heartbeat = $2; + } + } + } + close FH; + } + else { + print_log( "No Custom Template found for $template ($template_cfg) ", 3 ); + print_log( "RRD Datatype is $dstype", 3 ); + } + print_log( "Template is $template.php", 3 ); + $CTPL{'COMMAND'} = $template; + $CTPL{'TEMPLATE'} = $template; + $CTPL{'DSTYPE'} = $dstype; + $CTPL{'RRD_STORAGE_TYPE'} = $rrd_storage_type; + $CTPL{'RRD_HEARTBEAT'} = $rrd_heartbeat; + $CTPL{'USE_MIN_ON_CREATE'} = $use_min_on_create; + $CTPL{'USE_MAX_ON_CREATE'} = $use_max_on_create; + return %CTPL; +} + +# +# Parse process_perfdata.cfg +# +sub parse_config { + my $config_file = shift; + my $line = 0; + + if ( -e $config_file ) { + open CFG, '<', "$config_file"; + while () { + $line++; + chomp; + s/ //g; + next if /^#/; + next if /^$/; + s/#.*//; + + if (/^(.*)=(.*)$/) { + if ( defined $conf{$1} ) { + $conf{$1} = $2; + } + } + } + close CFG; + print_log( "Using Config File $config_file parameters", 2 ); + } + else { + print_log( "Config File $config_file not found, using defaults", 2 ); + } +} + +# +# Parse rra.cfg +# +sub parse_rra_config { + my $template = shift; + my $rra_template = ""; + my @rrd_create = @default_rrd_create; + if ( -r $conf{'CFG_DIR'} . "/" . $template . ".rra.cfg" ) { + $rra_template = $conf{'CFG_DIR'} . "/" . $template . ".rra.cfg"; + print_log( "Reading $rra_template", 2 ); + } + elsif ( -r $conf{'RRA_CFG'} ) { + $rra_template = $conf{'RRA_CFG'}; + print_log( "Reading $conf{'RRA_CFG'}", 2 ); + } + else { + print_log( "No usable rra.cfg found. Using default values.", 2 ); + } + + if ( $rra_template ne "" ) { + @rrd_create = (); + open RRA, "<", $rra_template; + while () { + next if /^#/; + next if /^$/; + s/#.*//; + if(/^RRA_STEP=(\d+)/i){ + $conf{'RRA_STEP'} = $1; + next; + } + chomp; + push @rrd_create, "$_"; + } + close RRA; + } + else { + @rrd_create = @default_rrd_create; + } + return @rrd_create; + +} + +# +# Function adapted from Nagios::Plugin::Performance +# Thanks to Gavin Carr and Ton Voon +# + +sub _parse { + # Nagios::Plugin::Performance + my $string = shift; + my $tmp_string = $string; + $string =~ s/^([^=]+)=(U|[\d\.\-]+)([\w\/%]*);?([\d\.\-:~@]+)?;?([\d\.\-:~@]+)?;?([\d\.\-]+)?;?([\d\.\-]+)?;?\s*//; + + if ( $tmp_string eq $string ) { + print_log( "No pattern match in function _parse($string)", 2 ); + return undef; + } + + return undef unless ( ( defined $1 && $1 ne "" ) && ( defined $2 && $2 ne "" ) ); + + # create hash from all performance data values + + my %p = ( + "label" => $1, + "name" => $1, + "value" => $2, + "uom" => $3, + "warning" => $4, + "critical" => $5, + "min" => $6, + "max" => $7 + ); + + $p{label} =~ s/[&"']//g; # cleanup + $p{name} =~ s/["']//g; # cleanup + $p{name} =~ s/[\/\\]/_/g; # cleanup + $p{name} = cleanup($p{name}); + + if ( $p{uom} eq "%" ) { + $p{uom} = "%%"; + print_log( "DEBUG: UOM adjust = $p{uom}", 3 ); + } + + # + # Check for warning and critical ranges + # + if ( $p{warning} && $p{warning} =~ /^([\d\.\-~@]+)?:([\d\.\-~@]+)?$/ ) { + print_log( "DEBUG: Processing warning ranges ( $p{warning} )", 3 ); + $p{warning_min} = $1; + $p{warning_max} = $2; + delete( $p{warning} ); + if ( $p{warning_min} =~ /^@/ ) { + $p{warning_min} =~ s/@//; + $p{warning_range_type} = "inside"; + } + else { + $p{warning_range_type} = "outside"; + } + } + if ( $p{critical} && $p{critical} =~ /^([\d\.\-~@]+)?:([\d\.\-~@]+)?$/ ) { + print_log( "DEBUG: Processing critical ranges ( $p{critical} )", 3 ); + $p{critical_min} = $1; + $p{critical_max} = $2; + delete( $p{critical} ); + if ( $p{critical_min} =~ /^@/ ) { + $p{critical_min} =~ s/@//; + $p{critical_range_type} = "inside"; + } + else { + $p{critical_range_type} = "outside"; + } + } + # Strip Range indicators + $p{warning} =~ s/[~@]// if($p{warning}); + $p{critical} =~ s/[~@]// if($p{critical}); + + return ( $string, %p ); +} + +# +# clean Strings +# +sub cleanup { + my $string = shift; + if ($string) { + $string =~ s/[& :\/\\]/_/g; + } + return $string; +} + +# +# Urlencode +# +sub urlencode { + my $string = shift; + if ($string) { + $string =~ s/([<>&])/sprintf("%%%02x",ord($1))/eg; # URLencode; + } + return $string; +} + +# +# Trim leading whitespaces +# +sub trim { + my $string = shift; + $string =~ s/^\s*//g; + return $string; +} + +# +# Parse the Performance String and call data2rrd() +# +sub parse_perfstring { + + # + # Default RRD Datatype + # Value will be overwritten by adjust_template() + # + my %CTPL = (); + $dstype = "GAUGE"; + my $perfstring = shift; + my $is_multi = "0"; + my @perfs; + my @multi; + my %p; + my $use_min_on_create = 0; + my $use_max_on_create = 0; + + # + # check_multi + # + if ( $perfstring =~ /^[']?([a-zA-Z0-9\.\-_\s\/\#]+)::([a-zA-Z0-9\.\-_\s]+)::([^=]+)[']?=/ ) { + $is_multi = 1; + print_log( "check_multi Perfdata start", 3 ); + my $count = 0; + my $check_multi_blockcount = 0; + my $multi_parent = cleanup( $NAGIOS{SERVICEDESC} ); + my $auth_servicedesc = $NAGIOS{DISP_SERVICEDESC}; + while ($perfstring) { + ( $perfstring, %p ) = _parse($perfstring); + if ( !$p{label} ) { + print_log( "Invalid Perfdata detected ", 1 ); + $stats{invalid}++; + @perfs = (); + last; + } + if ( $p{label} =~ /^[']?([a-zA-Z0-9\.\-_\s\/\#]+)::([a-zA-Z0-9\.\-_\s]+)::([^=]+)[']?$/ ) { + @multi = ( $1, $2, $3 ); + if ( $count == 0 ) { + print_log( "DEBUG: First check_multi block", 3 ); + + # Keep servicedesc while processing the first block. + $p{servicedesc} = cleanup( $NAGIOS{SERVICEDESC} ); + $p{disp_servicedesc} = $NAGIOS{DISP_SERVICEDESC}; + $p{auth_servicedesc} = $auth_servicedesc; + $p{multi} = 1; + $p{multi_parent} = $multi_parent; + } + else { + print_log( "DEBUG: A new check_multi block ($count) starts", 3 ); + $p{servicedesc} = cleanup( $multi[0] ); # Use the multi servicedesc. + $p{multi} = 2; + $p{multi_parent} = $multi_parent; + $p{servicedesc} = cleanup( $multi[0] ); # Use the multi servicedesc. + $p{disp_servicedesc} = cleanup( $multi[0] ); # Use the multi servicedesc. + $p{auth_servicedesc} = $auth_servicedesc; + data2rrd(@perfs) if ( $#perfs >= 0 ); # Process when a new block starts. + @perfs = (); # Clear the perfs array. + # reset check_multi block count + $check_multi_blockcount = 0; + } + %CTPL = adjust_template( $multi[1], $p{uom}, $check_multi_blockcount++ ); + + if ( $CTPL{'USE_MAX_ON_CREATE'} == 1 && defined $p{max} ) { + $p{rrd_max} = $p{max}; + } else { + $p{rrd_max} = "U"; + } + if ( $CTPL{'USE_MIN_ON_CREATE'} == 1 && defined $p{min} ) { + $p{rrd_min} = $p{min}; + } elsif( $CTPL{'DSTYPE'} eq 'DERIVE' ){ + $p{rrd_min} = 0; # Add minimum value 0 if DSTYPE = DERIVE + } else { + $p{rrd_min} = "U"; + } + $p{template} = $CTPL{'TEMPLATE'}; + $p{dstype} = $CTPL{'DSTYPE'}; + $p{rrd_storage_type} = $CTPL{'RRD_STORAGE_TYPE'}; + $p{rrd_heartbeat} = $CTPL{'RRD_HEARTBEAT'}; + $p{label} = cleanup( $multi[2] ); # store the original label from check_multi header + $p{name} = cleanup( $multi[2] ); # store the original label from check_multi header + $p{hostname} = cleanup( $NAGIOS{HOSTNAME} ); + $p{disp_hostname} = $NAGIOS{DISP_HOSTNAME}; + $p{auth_hostname} = $NAGIOS{HOSTNAME}; + $p{timet} = $NAGIOS{TIMET}; + push @perfs, {%p}; + $count++; + } + else { + print_log( "DEBUG: Next check_multi data for block $count multiblock $check_multi_blockcount", 3 ); + + # additional check_multi data + %CTPL = adjust_template( $multi[1], $p{uom}, $check_multi_blockcount++ ); + + if ( $CTPL{'USE_MAX_ON_CREATE'} == 1 && defined $p{max} ) { + $p{rrd_max} = $p{max}; + } else { + $p{rrd_max} = "U"; + } + + if ( $CTPL{'USE_MIN_ON_CREATE'} == 1 && defined $p{min} ) { + $p{rrd_min} = $p{min}; + } elsif( $CTPL{'DSTYPE'} eq 'DERIVE' ){ + $p{rrd_min} = 0; # Add minimum value 0 if DSTYPE = DERIVE + } else { + $p{rrd_min} = "U"; + } + + $p{template} = $CTPL{'TEMPLATE'}; + $p{dstype} = $CTPL{'DSTYPE'}; + $p{rrd_storage_type} = $CTPL{'RRD_STORAGE_TYPE'}; + $p{rrd_heartbeat} = $CTPL{'RRD_HEARTBEAT'}; + $p{hostname} = cleanup( $NAGIOS{HOSTNAME} ); + $p{disp_hostname} = $NAGIOS{DISP_HOSTNAME}; + $p{auth_hostname} = $NAGIOS{HOSTNAME}; + $p{timet} = $NAGIOS{TIMET}; + if ( $count == 1 ) { + $p{servicedesc} = cleanup( $NAGIOS{SERVICEDESC} ); # Use the servicedesc. + $p{disp_servicedesc} = $NAGIOS{DISP_SERVICEDESC}; # Use the servicedesc. + } else { + $p{servicedesc} = cleanup( $multi[0] ); # Use the multi servicedesc. + $p{disp_servicedesc} = $multi[0]; # Use the multi servicedesc. + } + $p{multi} = $is_multi; + $p{multi_parent} = $multi_parent; + $p{auth_servicedesc} = $auth_servicedesc; # Use the servicedesc. + push @perfs, {%p}; + } + } + data2rrd(@perfs) if ( $#perfs >= 0 ); + @perfs = (); + } else { + + # + # Normal Performance Data + # + print_log( "DEBUG: Normal perfdata", 3 ); + my $count = 0; + while ($perfstring) { + ( $perfstring, %p ) = _parse($perfstring); + if ( !$p{label} ) { + print_log( "Invalid Perfdata detected ", 1 ); + @perfs = (); + last; + } + %CTPL = adjust_template( $NAGIOS{CHECK_COMMAND}, $p{uom}, $count ); + + if ( $CTPL{'USE_MAX_ON_CREATE'} == 1 && defined $p{max} ) { + $p{rrd_max} = $p{max}; + } else { + $p{rrd_max} = "U"; + } + if ( $CTPL{'USE_MIN_ON_CREATE'} == 1 && defined $p{min} ) { + $p{rrd_min} = $p{min}; + } elsif ( $CTPL{'DSTYPE'} eq 'DERIVE' ){ + $p{rrd_min} = 0; # Add minimum value 0 if DSTYPE = DERIVE + } else { + $p{rrd_min} = "U"; + } + + $p{template} = $CTPL{'TEMPLATE'}; + $p{dstype} = $CTPL{'DSTYPE'}; + $p{rrd_storage_type} = $CTPL{'RRD_STORAGE_TYPE'}; + $p{rrd_heartbeat} = $CTPL{'RRD_HEARTBEAT'}; + $p{multi} = $is_multi; + $p{hostname} = cleanup( $NAGIOS{HOSTNAME} ); + $p{disp_hostname} = $NAGIOS{DISP_HOSTNAME}; + $p{auth_hostname} = $NAGIOS{DISP_HOSTNAME}; + $p{servicedesc} = cleanup( $NAGIOS{SERVICEDESC} ); + $p{disp_servicedesc} = $NAGIOS{DISP_SERVICEDESC}; + $p{auth_servicedesc} = $NAGIOS{DISP_SERVICEDESC}; + $p{timet} = $NAGIOS{TIMET}; + + push @perfs, {%p}; + $count++; + } + data2rrd(@perfs) if ( $#perfs >= 0 ); + @perfs = (); + } +} + +# +# Write to Logfile +# +sub print_log { + my $out = shift; + my $severity = shift; + if ( $severity <= $conf{LOG_LEVEL} ) { + open( LOG, ">>" . $conf{LOG_FILE} ) || die "Can't open logfile ($conf{LOG_FILE}) ", $!; + if ( -s LOG > $conf{LOG_FILE_MAX_SIZE} ) { + truncate( LOG, 0 ); + printf( LOG "File truncated" ); + } + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(time); + printf( LOG "%02d-%02d-%02d %02d:%02d:%02d [%d] [%d] %s\n", $year + 1900, $mon + 1, $mday, $hour, $min, $sec, $$, $severity, $out ); + close(LOG); + } +} + +# +# Signals and Handlers +# +sub init_signals { + $SIG{'INT'} = \&handle_signal; + $SIG{'QUIT'} = \&handle_signal; + $SIG{'ALRM'} = \&handle_signal; + $SIG{'ILL'} = \&handle_signal; + $SIG{'ABRT'} = \&handle_signal; + $SIG{'FPE'} = \&handle_signal; + $SIG{'SEGV'} = \&handle_signal; + $SIG{'TERM'} = \&handle_signal; + $SIG{'BUS'} = \&handle_signal; + $SIG{'SYS'} = \&handle_signal; + $SIG{'XCPU'} = \&handle_signal; + $SIG{'XFSZ'} = \&handle_signal; + $SIG{'IOT'} = \&handle_signal; + $SIG{'PIPE'} = \&handle_signal; + $SIG{'HUP'} = \&handle_signal; + $SIG{'CHLD'} = \&handle_signal; +} + +# +# Handle Signals +# +sub handle_signal { + my ($signal) = (@_); + # + # Gearman child process + # + if ( defined ( $opt_gm ) ){ + if($signal eq "CHLD" && defined($opt_gm) ){ + my $pid = waitpid(-1, &WNOHANG); + if($pid == -1){ + print_log( "### no hanging child ###", 1 ); + } elsif ( WIFEXITED($?)) { + print_log( "### child $pid exited ###", 1 ); + $children--; + } else { + print_log( "### wrong signal ###", 1 ); + $children--; + } + $SIG{'CHLD'} = \&handle_signal; + } + if($signal eq "INT" || $signal eq "TERM"){ + local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children + kill $signal => keys %children; + print_log( "*** process_perfdata.pl terminated on signal $signal", 0 ); + pidlock("remove"); + exit; # clean up with dignity + } + print_log( "*** process_perfdata.pl received signal $signal (ignored)", 0 ); + }else{ + if ( $signal eq "ALRM" ) { + print_log( "*** TIMEOUT: Timeout after $opt_t secs. ***", 0 ); + if ( $opt_b && !$opt_n && !$opt_s ) { + print_log( "*** TIMEOUT: Deleting current file to avoid loops", 0 ); + print_log( "*** TIMEOUT: Please check your process_perfdata.cfg", 0 ); + } + elsif ( $opt_b && $opt_n && !$opt_s ) { + print_log( "*** TIMEOUT: Deleting current file to avoid NPCD loops", 0 ); + print_log( "*** TIMEOUT: Please check your process_perfdata.cfg", 0 ); + } + if ($opt_b && !$opt_s ) { + my $pdfile = "$opt_b" . "-PID-" . $$; + if ( unlink("$pdfile") == 1 ) { + print_log( "*** TIMEOUT: $pdfile deleted", 0 ); + } + else { + print_log( "*** TIMEOUT: Could not delete $pdfile:$!", 0 ); + } + } + my $temp_file = "$conf{RRDPATH}/$NAGIOS{HOSTNAME}/$NAGIOS{SERVICEDESC}.xml.$$"; + if ( -f $temp_file ) { + unlink($temp_file); + } + $t1 = [gettimeofday]; + $rt = tv_interval $t0, $t1; + $stats{runtime} = $rt; + print_log( "*** Timeout while processing Host: \"$NAGIOS{HOSTNAME}\" Service: \"$NAGIOS{SERVICEDESC}\"", 0 ); + print_log( "*** process_perfdata.pl terminated on signal $signal", 0 ); + exit 7; + } + } +} + + +sub init_stats { + %stats = ( + timet => time, + error => 0, + invalid => 0, + skipped => 0, + runtime => 0, + rows => 0, + create => 0, + update => 0, + ); +} + +# +# Store some internal runtime infos +# +sub store_internals { + if( ! -w $conf{'STATS_DIR'}){ + print_log("*** ERROR: ".$conf{'STATS_DIR'}." is not writable or does not exist",0); + return; + } + my $statsfile = $conf{'STATS_DIR'}."/".(int $stats{timet} / 60); + open( STAT, ">> $statsfile" ) or die "Cant create statistic file ", $!; + printf(STAT "%d %f %d %d %d %d %d %d\n", $stats{timet},$stats{runtime},$stats{rows},$stats{update},$stats{create},$stats{error},$stats{invalid},$stats{skipped}); + close(STAT); + check_internals(); +} + +# +# Search for statistic files +# +sub check_internals { + my $file; + my @files; + opendir(STATS, $conf{'STATS_DIR'}); + while ( defined ( my $file = readdir STATS) ){ + next if $file =~ /^\.\.?$/; # skip . and .. + next if $file =~ /-PID-/; # skip temporary files + next if $file == (int $stats{timet} / 60); # skip our current file + push @files, $file; + } + read_internals(@files); +} + +# +# Read and aggregate files found by check_internals() +# +sub read_internals { + my @files = @_; + my @chunks; + foreach my $file (sort { $a <=> $b} @files){ + unless ( rename($conf{'STATS_DIR'}."/".$file, $conf{'STATS_DIR'}."/".$file."-PID-".$$) ){ + print_log( "ERROR: renaming stats file " . $conf{'STATS_DIR'}."/".$file . " to " . $conf{'STATS_DIR'}."/".$file."-PID-".$$ . " failed", 1 ); + next; + } + open( STAT, "< ".$conf{'STATS_DIR'}."/".$file."-PID-".$$ ); + %stats = ( + timet => 0, + error => 0, + invalid => 0, + skipped => 0, + runtime => 0, + rows => 0, + create => 0, + update => 0, + ); + while(){ + @chunks = split(); + $stats{timet} = $chunks[0]; + $stats{runtime} += $chunks[1]; + $stats{rows} += $chunks[2]; + $stats{update} += $chunks[3]; + $stats{create} += $chunks[4]; + $stats{error} += $chunks[5]; + $stats{invalid} += $chunks[6]; + $stats{skipped} += $chunks[7]; + } + close(STAT); + unlink($conf{'STATS_DIR'}."/".$file."-PID-".$$); + process_internals(); + } +} +# +# +# +sub process_internals { + my $last_rrd_dtorage_type = $conf{'RRD_STORAGE_TYPE'}; + $conf{'RRD_STORAGE_TYPE'} = "MULTIPLE"; + %NAGIOS = ( + HOSTNAME => '.pnp-internal', + DISP_HOSTNAME => 'pnp-internal', + SERVICEDESC => 'runtime', + DISP_SERVICEDESC => 'runtime', + TIMET => $stats{timet}, + DATATYPE => 'SERVICEPERFDATA', + CHECK_COMMAND => 'pnp-runtime', + PERFDATA => "runtime=".$stats{runtime}."s rows=".$stats{rows}." errors=".$stats{error}." invalid=".$stats{invalid}." skipped=".$stats{skipped} ." update=".$stats{update}. " create=".$stats{create} + ); + parse_perfstring( $NAGIOS{PERFDATA} ); + $conf{'RRD_STORAGE_TYPE'} = $last_rrd_dtorage_type; +} + +# +# Gearman Worker Daemon +# +sub daemonize { + if( defined($opt_daemon) ){ + print_log("daemonize init",1); + chdir '/' or die "Can't chdir to /: $!"; + open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; + open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!"; + open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!"; + defined( my $pid = fork ) or die "Can't fork: $!"; + exit if $pid; + pidlock("create"); + setsid or die "Can't start a new session: $!"; + } else { + pidlock("create"); + } + # Fork off our children. + for (1 .. $conf{'PREFORK'}) { + new_child(); + print_log( "starting child process $children", 1 ); + } + while (1) { + sleep; # wait for a signal (i.e., child's death) + for (my $i = $children; $i < $conf{'PREFORK'}; $i++) { + print_log("starting new child (running = $i)",1); + new_child(); # top up the child pool + } + } + return; +} + +# +# start a new worker process +# +sub new_child { + my $pid; + my $sigset; + my $req = 0; + # block signal for fork + $sigset = POSIX::SigSet->new(SIGINT); + sigprocmask(SIG_BLOCK, $sigset) + or die "Can't block SIGINT for fork: $!\n"; + + die "fork: $!" unless defined ($pid = fork); + + if ($pid) { + # Parent records the child's birth and returns. + sigprocmask(SIG_UNBLOCK, $sigset) + or die "Can't unblock SIGINT for fork: $!\n"; + $children{$pid} = 1; + $children++; + return; + } else { + # Child can *not* return from this subroutine. + $SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did before + + # unblock signals + sigprocmask(SIG_UNBLOCK, $sigset) + or die "Can't unblock SIGINT for fork: $!\n"; + + my $worker = Gearman::Worker->new(); + my @job_servers = split(/,/, $conf{'GEARMAN_HOST'}); # allow multiple gearman job servers + $worker->job_servers(@job_servers); + $worker->register_function("perfdata", 2, sub { return main(@_); }); + my %opt = ( + on_complete => sub { $req++; }, + stop_if => sub { if ( $req > $conf{'REQUESTS_PER_CHILD'} ) { return 1;}; } + ); + print_log("connecting to gearmand '".$conf{'GEARMAN_HOST'}."'",0); + $worker->work( %opt ); + print_log("max requests per child reached (".$conf{'REQUESTS_PER_CHILD'}.")",1); + # this exit is VERY important, otherwise the child will become + # a producer of more and more children, forking yourself into + # process death. + exit; + } +} +# +# Create a pid file +# +sub pidlock { + return unless defined $opt_pidfile; + my $action = shift; + my $PIDFILE = $opt_pidfile; + if($action eq "create"){ + if ( -e $PIDFILE ) { + if ( open( OLDPID, "<$PIDFILE" ) ) { + $_ = ; + chop($_); + my $oldpid = $_; + close(OLDPID); + if ( -e "/proc/$oldpid/cmdline" ) { + print_log("Another instance is already running with PID: $oldpid",0); + exit 0; + } else { + print_log("Pidfile $PIDFILE seems to be stale!",0); + print_log("Removing old pidfile",0); + unlink $PIDFILE; + } + } + } + if ( !open( PID, ">$PIDFILE" ) ) { + print_log("Can not create $PIDFILE ( $! )",0); + exit 1; + } + print( PID "$$\n" ); + close(PID); + print_log("Pidfile ($PIDFILE) created",0); + }elsif( $action eq "remove" ){ + if ( -e $PIDFILE ) { + print_log("Removing pidfile ($PIDFILE)",0); + unlink $PIDFILE; + } + } +} + +# +# Read crypt key +# +sub read_keyfile { + my $file = shift; + my $key = ''; + if( -r $file){ + open(FH, "<", $file); + while(){ + chomp(); # avoid \n on last field + $conf{'KEY'} = $_; + last; + } + close(FH); + print_log("Using encryption key specified in '$file'",0); + return 1; + }else{ + print_log("Using encryption key specified in ".$conf{'CFG_DIR'}."/process_perfdata.cfg",0); + return 0; + } +} +# +# +# +sub print_help { + print < + Use process_perfdata.pl to store Nagios Plugin Performance Data into RRD Databases + + Options: + -h, --help + Print detailed help screen + -V, --version + Print version information + -t, --timeout=INTEGER + Seconds before process_perfdata.pl times out (default: $opt_t_default) + -i, --inetd + Use this Option if process_perfdata.pl is executed by inetd/xinetd. + -d, --datatype + Defaults to \"SERVICEPERFDATA\". Use \"HOSTPERFDATA\" to process Perfdata from regular Host Checks + Only used in default or inetd mode + -b, --bulk + Provide a file for bulk update + -s, --stdin + Read input from stdin + -n, --npcd + Hint the program, that it was invoked by NPCD + -c, --config + Optional process_perfdata config file + Default: @sysconfdir@/process_perfdata.cfg + + Gearman Worker Options: + --gearman + Start in Gearman worker mode + --daemon + Run as daemon + --pidfile=/var/run/process_perfdata.pid + The pidfile used while running in as Gearman worker daemon + +EOD + exit 0; +} + +# +# +# +sub print_version { + print "Version: process_perfdata.pl $const{VERSION}\n"; + print "Copyright (c) 2005-2010 Joerg Linge \n"; + exit 0; +} + diff --git a/scripts/rc.npcd.in b/scripts/rc.npcd.in new file mode 100644 index 0000000..c5f2c9e --- /dev/null +++ b/scripts/rc.npcd.in @@ -0,0 +1,162 @@ +#!@SHELL@ +# +### BEGIN INIT INFO +# Provides: npcd +# Required-Start: +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: @PKG_NAME@ NPCD Daemon Version @PKG_VERSION@ +# Description: Nagios Performance Data C Daemon +### END INIT INFO + +# chkconfig: 345 99 01 +# +# File : npcd +# + +servicename=@npcd_name@ +prefix=@prefix@ +exec_prefix=${prefix} +NpcdBin=@bindir@/@npcd_name@ +NpcdCfgFile=@sysconfdir@/npcd.cfg +NpcdVarDir=@localstatedir@ +NpcdRunFile=/var/run/npcd.pid +NpcdLockDir=/var/lock/subsys +NpcdLockFile=@npcd_name@ +NpcdUser=@nagios_user@ +NpcdGroup=@nagios_grp@ + +status_npcd (){ + pid_npcd + if ps -p $NpcdPID > /dev/null 2>&1; then + return 0 + else + if test -f $NpcdLockDir/$NpcdLockFile; then + return 2 + else + return 1 + fi + fi + return 1 +} + +printstatus_npcd(){ + if status_npcd $1 $2; then + echo "$servicename (pid $NpcdPID) is running..." + exit 0 + elif test $? -eq 2; then + echo "$servicename is not running but subsystem locked" + exit 2 + else + echo "$servicename is not running" + exit 1 + fi +} + +killproc_npcd (){ + kill $2 $NpcdPID +} + +pid_npcd (){ + if test ! -f $NpcdRunFile; then + return 1 + fi + NpcdPID=`head -n 1 $NpcdRunFile` + return 0 +} + + +# Source function library +# Solaris doesn't have an rc.d directory, so do a test first +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +elif [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +fi + +# Check that npcd exists. +if [ ! -f $NpcdBin ]; then + echo "Executable file $NpcdBin not found. Exiting." + exit 1 +fi + +# Check that npcd.cfg exists. +if [ ! -f $NpcdCfgFile ]; then + echo "Configuration file $NpcdCfgFile not found. Exiting." + exit 1 +fi + +# See how we were called. +case "$1" in + + start) + status_npcd + if [ $? -eq 0 ]; then + echo "$servicename already started..." + exit 1 + fi + echo -n "Starting $servicename:" + touch $NpcdRunFile + chown $NpcdUser:$NpcdGroup $NpcdRunFile + $NpcdBin -d -f $NpcdCfgFile + if [ -d $NpcdLockDir ]; then touch $NpcdLockDir/$NpcdLockFile; fi + echo " done." + exit 0 + ;; + + stop) + status_npcd + if ! [ $? -eq 0 ]; then + echo "$servicename was not running... could not stop" + exit 1 + fi + echo -n "Stopping $servicename: " + + pid_npcd + killproc_npcd npcd + + # now we have to wait for npcd to exit and remove its + # own NpcdRunFile, otherwise a following "start" could + # happen, and then the exiting npcd will remove the + # new NpcdRunFile, allowing multiple npcd daemons + # to (sooner or later) run - John Sellens + #echo -n 'Waiting for npcd to exit .' + for i in 1 2 3 4 5 6 7 8 9 10 ; do + if status_npcd > /dev/null; then + echo -n '.' + sleep 1 + else + break + fi + done + if status_npcd > /dev/null; then + echo '' + echo 'Warning - $servicename did not exit in a timely manner' + else + echo 'done.' + fi + rm -f $NpcdLockDir/$NpcdLockFile + ;; + + status) + printstatus_npcd + ;; + + reload) + $0 restart + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $servicename {start|stop|restart|status}" + exit 1 + ;; + +esac + +# End of this script diff --git a/scripts/rc.pnp_gearman_worker.in b/scripts/rc.pnp_gearman_worker.in new file mode 100644 index 0000000..b2325ba --- /dev/null +++ b/scripts/rc.pnp_gearman_worker.in @@ -0,0 +1,113 @@ +#!@SHELL@ + +### BEGIN INIT INFO +# Provides: pnp_gearman_worker +# Required-Start: $all +# Required-Stop: $all +# Should-Start: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start/Stop the pnp4nagios gearman worker +### END INIT INFO + +DAEMON="@libexecdir@/process_perfdata.pl" +CFG="@sysconfdir@/process_perfdata.cfg" +NAME=pnp_gearman_worker +PIDFILE=@localstatedir@/${NAME}.pid +LOCKFILE=/var/lock/subsys/${NAME} +USER=@nagios_user@ +USERID=`id -u` +CMD="$DAEMON --pidfile=$PIDFILE --config=$CFG --gearman --daemon" + +function get_status() { + pid=`cat $PIDFILE 2>/dev/null` + if [ "$pid" != "" ]; then + ps -p $pid > /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo "$NAME is running with pid $pid" + return 0; + fi + fi + echo "$NAME is not running" + return 1; +} + +function kill_procs() { + pid=`cat $PIDFILE 2>/dev/null` + if [ -z $pid ]; then + echo ". Not running." + else + # do a kill if still now down + ps -p $pid > /dev/null 2>&1 && kill $pid + for x in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5; do + echo -n "." + ps -p $pid > /dev/null 2>&1 && sleep 1; + done + ps -p $pid > /dev/null 2>&1; + if [ $? -ne 0 ]; then + rm -f $PIDFILE + if [ "$USERID" -eq 0 ]; then + rm -f $LOCKFILE + fi + echo "done" + exit 0; + else + echo "failed" + exit 1; + fi + fi +} + +case "$1" in + start) + echo -n "Starting $NAME " + get_status > /dev/null; + if [ $? = 0 ]; then + echo "failed" + echo "$NAME already running" + exit 0; + fi + + if [ "$USERID" -eq 0 ]; then + su -s $SHELL - $USER -c "$CMD" + else + $CMD + fi + if [ $? -eq 0 ]; then + if [ "$USERID" -eq 0 ]; then + touch $LOCKFILE + fi + echo "done" + exit 0; + else + echo "failed" + exit 1; + fi + ;; + stop) + echo -n "Stopping $NAME" + pid=`cat $PIDFILE 2>/dev/null` + if [ -z $pid ]; then + echo ". Not running." + else + # kill if still running + ps -p $pid > /dev/null 2>&1 && kill_procs; + fi + ;; + status) + get_status; + exit $?; + ;; + restart) + $0 stop && sleep 1 && $0 start + exit $? + ;; + *) + echo "Usage: $NAME {start|stop|status|restart}" + exit 1 + ;; +esac + +exit 0 + diff --git a/scripts/rrd_convert.pl.in b/scripts/rrd_convert.pl.in new file mode 100644 index 0000000..4dd3651 --- /dev/null +++ b/scripts/rrd_convert.pl.in @@ -0,0 +1,555 @@ +#!@PERL@ +## @PKG_NAME@–@PKG_VERSION@ rrd_convert.pl +## Copyright (c) 2006-2010 Joerg Linge (http://www.pnp4nagios.org) +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +@PERL_LIB_PATH_CODE@ + +use strict; +use warnings; +use Getopt::Long; +use Time::HiRes qw(gettimeofday tv_interval); +use File::Find; +use File::Copy; + +if( $< == 0 ){ + print "dont try this as root \n"; + exit 1; +} + +# +# Some global Vars +# + +my %conf = ( + CFG_DIR => "@sysconfdir@/", + RRDPATH => "@PERFDATA_DIR@", + RRDTOOL => "@RRDTOOL@", + LOG_LEVEL => 0, + DRY_RUN => 0, + FORCE => 0, + RRD_BACKUP => 1, + RRD_STORAGE_TYPE => "SINGLE", + TMP_DIR => '/tmp/rrd_convert', + RRD_DAEMON_OPTS => "", + XML_MAX_AGE => 3600, +); + +Getopt::Long::Configure('bundling'); +my ( $opt_V, $opt_h, $opt_c, $opt_l, $opt_x, $opt_p ); +# defaults +$opt_x = 1; + +GetOptions( + "V|version" => \$opt_V, + "h|help" => \$opt_h, + "c|check_command=s" => \$opt_c, + "p|cfg_dir=s" => \$opt_p, + "l|list_commands" => \$opt_l, + "x|no_structure_check" => \$opt_x, + "d|dry-run" => \$conf{DRY_RUN}, + "t|tmp_dir=s" => \$conf{TMP_DIR}, + "force" => \$conf{FORCE}, +); + +print_help() if $opt_h; +print_help_opt_p() if !$opt_p; +print_help() if !$opt_c and !$opt_l; +print_version() if $opt_V; + +if($opt_p){ + $conf{CFG_DIR} = $opt_p; +} +parse_config($conf{CFG_DIR}."/process_perfdata.cfg"); +if ( $conf{RRD_DAEMON_OPTS} ){ + $conf{RRD_DAEMON_OPTS} = "--daemon=".$conf{RRD_DAEMON_OPTS}; +} + +my @STRUCT; +my %FILEHANDLE; + +my @commands; # list of commands +my @worklist; # list of found xml files + +my %ds_list; +my %original_ds_list; +my $max_age = time() - $conf{XML_MAX_AGE}; + +my %stats = ( + 'rrd_in' => 0, + 'rrd_out' => 0, + 'old_xml' => 0, + 'xml_without_rrd' => 0, + 'runtime' => 0, +); + +main(); + +sub main{ + check_storage_type(); + find(\&wanted_xml_files, $conf{RRDPATH}); + summary(); + if($opt_l){ # List commands and exit + summary_command_list(); + exit; + } + if($#worklist+1 > 0 ){ + my $answer = read_choice("Start Converter [n|y]?"); + unless ( $answer =~ m/^y$/i ){ + print "Exit...\n"; + exit; + } + }else{ + print "Check Command '".$opt_c."' not found in any XML File\n"; + print "\n"; + print "\n"; + summary_command_list(); + exit; + } + check_custom_template(); + write_custom_template(); + my $t0 = [gettimeofday]; + my $i = 0; + foreach my $xmlfile ( @worklist ) { + $i++; + undef %ds_list; + undef %original_ds_list; + my($host,$service) = parse_xml_filename($xmlfile); + my ($rrdfile) = $xmlfile =~ /^(.*)\.xml$/; + $rrdfile .= ".rrd"; + if(-r $rrdfile){ + create_dir($conf{TMP_DIR}); + my $dumpfile = sprintf("%s/%s-%s.dump",$conf{TMP_DIR},$host,$service); + print "File ".$i."/".($#worklist+1)."\n"; + rrdtool_dump($rrdfile,$dumpfile); + parse_pnp_xml($xmlfile); + build_ds_list($rrdfile); + next if check_ds_list(); + open_files($host,$service); + manipulate_rrd_dump($dumpfile); + close_files(); + restore_files($host,$service); + backup_rrd_file($rrdfile); + } + } + my $t1 = [gettimeofday]; + $stats{runtime} = tv_interval $t0, $t1; + print "DONE\n"; + stats(); +} + + +sub build_ds_list{ + my $rrdfile = shift; + my @info; + @info = `$conf{'RRDTOOL'} info $rrdfile`; + if( $? > 0 ){ + print "ERROR: $conf{'RRDTOOL'} info $rrdfile returns with $?\n"; + exit 1; + } + foreach(@info){ + if(m/ds\[(\d+)\]\.type/ ) { + $ds_list{$1} = $1; + } + } + my $test = keys %ds_list; + %original_ds_list = %ds_list; +} + +sub check_ds_list{ + my $rrd_ds_count = keys %ds_list; + my $xml_ds_count = $#STRUCT; + if($rrd_ds_count == $xml_ds_count){ + return 0; + }elsif($rrd_ds_count <= $xml_ds_count && $opt_x){ + printf("OK: RRD contains '%s' DS but XML contains '%s'. Convert forced by --no_structure_check\n",$rrd_ds_count,$xml_ds_count); + return 0; + }else{ + printf ("ERROR: RRD Structure mismatch. DS Count is '%s' but should be '%s'\n",$rrd_ds_count,$xml_ds_count); + return 1; + } +} + +sub wanted_xml_files{ + if(m/.xml$/){ + #printf("File: %s\n",$File::Find::name); + my $xmlfile = $File::Find::name; + my ($rrdfile) = $xmlfile =~ /^(.*)\.xml$/; + $rrdfile .= ".rrd"; + my $mtime = (stat($xmlfile))[9]; + if ( $mtime < $max_age ){ + $stats{old_xml}++; + return; + } + open(XML, $xmlfile); + while () { + if(/TEMPLATE>(.*) $seen{$a} } keys %seen ) { + printf " |- %-36s %5s\n",$key,$seen{$key}; + } +} + +sub stats{ + print "\n\n \\Statistics:\n"; + foreach my $key (sort { $stats{$b} cmp $stats{$a} } keys %stats ) { + printf " |- %-15s %s\n",$key,$stats{$key}; + } +} + +sub create_dir{ + my $dir = shift; + unless ( -d "$dir" ) { + unless ( mkdir "$dir" ) { + print "ERROR: $dir is not writable\n"; + exit 1; + } + } +} + +sub open_files(){ + my $host = shift; + my $service = shift; + foreach my $ds (keys %ds_list){ + my $file = sprintf("%s/%s-%s-%s.restore",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME}); + #print "Open Filehandle ".$file."\n"; + open($FILEHANDLE{$ds}, ">", $file); + } +} + +sub close_files(){ + foreach my $ds (keys %ds_list){ + #$ds--; + #print "Close Filehandle ".$STRUCT[$ds]{NAME}."\n"; + close($FILEHANDLE{$ds}); + } +} + +sub write_to_files{ + my $data = shift; + foreach my $ds (keys %ds_list){ + print { $FILEHANDLE{$ds} } $data; + } +} + +sub restore_files(){ + my $host = shift; + my $service = shift; + my $err; + $| = 1; + print "Restoring File\n"; + foreach my $ds (keys %ds_list){ + my $rrdfile = ''; + my $restorefile = sprintf("%s/%s-%s-%s.restore",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME}); + if( $conf{'DRY_RUN'} == 1 ){ + $rrdfile = sprintf("%s/%s/%s_%s.rrd",$conf{TMP_DIR},$host,$service,$STRUCT[$ds]{NAME}); + create_dir(sprintf("%s/%s", $conf{TMP_DIR},$host )); + }else{ + $rrdfile = sprintf("%s/%s/%s_%s.rrd",$conf{RRDPATH},$host,$service,$STRUCT[$ds]{NAME}); + } + print "$rrdfile\n"; + $err = system("$conf{'RRDTOOL'} restore -f '$restorefile' '$rrdfile'"); + if($err){ + printf("RRDtool Error: %s\n",$err); + exit; + } + unlink($restorefile); + $stats{rrd_out}++; + } + print "... done\n"; + $| = 0; +} + +sub backup_rrd_file{ + my $rrdfile = shift; + if ( $conf{RRD_BACKUP} == 1 ){ + move($rrdfile, $rrdfile.".backup"); + } +} + +sub parse_pnp_xml{ + my $xmlfile = shift; + undef @STRUCT; + #print "reading $xmlfile\n"; + open(XML, $xmlfile); + my $DATASOURCE = 0; + while () { + if(//){ + $DATASOURCE++; + } + if(//){ + $DATASOURCE = 0; + } + if(/<([A-Z_]+)>(.*)<\/[A-Z_]+>/ && $DATASOURCE != -1){ + $STRUCT[$DATASOURCE]{$1} = $2; + } + } + close(XML); + return @STRUCT; +} + +sub rrdtool_dump{ + my $rrdfile = shift; + my $dumpfile = shift; + my $err; + print "RRDtool dump to $dumpfile\n"; + if ( $conf{RRD_DAEMON_OPTS} ){ + $err = system("$conf{'RRDTOOL'} dump $conf{RRD_DAEMON_OPTS} $rrdfile > $dumpfile"); + }else{ + $err = system("$conf{'RRDTOOL'} dump $rrdfile > $dumpfile"); + } + if($err){ + printf("RRDtool Error: %s\n",$err); + exit; + } + $stats{rrd_in}++; + return $dumpfile; +} + +sub manipulate_rrd_dump{ + my $tmpfile = shift; + my $i = 0; + open (XML,$tmpfile); + my @ROW = (); + my $tmpds = 1; + my $inside_ds_block = 0; + print "Manipulating $tmpfile\n"; + while (){ + $i++; + unless ( $i % 5000 ){ + $| = 1; print "."; $| = 0; + } + my $d = $_; + # + # A Data Row + if(m//){ + m/(.*)/; + my $rowstart = $1; + @ROW = m{([^<].*?)<\/v>}gc; + my $fh = 1; + foreach my $VAL (@ROW){ + undef %ds_list; + $ds_list{$fh} = $fh; + write_to_files($rowstart."".$VAL."\n"); + $fh++; + } + next; + } + if(m//){ + $inside_ds_block = 1; + undef %ds_list; + $ds_list{$tmpds} = $tmpds; + write_to_files($d); + $tmpds++; + next; + } + if(m//){ + write_to_files($d); + $inside_ds_block = 0; + $tmpds = 1; + %ds_list = %original_ds_list; + next; + } + if(m/<\/ds>/){ + write_to_files($d); + $inside_ds_block = 0; + # write to all files alter + %ds_list = %original_ds_list; + next; + } + if(m/<\/database>/){ + # write to all files alter + %ds_list = %original_ds_list; + write_to_files($d); + next; + } + if($inside_ds_block == 1){ + # rename DS + $d =~ s/(.*)<\/name>/ 1 <\/name>/; + } + write_to_files($d); + } + close(XML); + print "... done $i lines\n"; + unlink($tmpfile); +} + +# +# Parse process_perfdata.cfg +# +sub parse_config { + my $config_file = shift; + my $line = 0; + if( ! -e $config_file ){ + print "$config_file not found\n"; + exit; + } + if ( -e $config_file ) { + open CFG, '<', "$config_file"; + while () { + $line++; + chomp; + s/ //g; + next if /^#/; + next if /^$/; + s/#.*//; + + if (/^(.*)=(.*)$/) { + if ( defined $conf{$1} ) { + $conf{$1} = $2; + } + } + } + close CFG; + } +} + +# +# Change RRD_STORAGE_TYPE to MULTIPLE +# +sub change_config { + my $cfg_file = $conf{'CFG_DIR'}."/process_perfdata.cfg"; + my $error = system("sed -i -e ".'s/\s*RRD_STORAGE_TYPE\s*=\s*SINGLE/RRD_STORAGE_TYPE=MULTIPLE/i'." $cfg_file"); +} + +sub check_storage_type{ + if($conf{'RRD_STORAGE_TYPE'} eq "MULTIPLE"){ + print "RRD_STORAGE_TYPE is already set to ".$conf{'RRD_STORAGE_TYPE'}."\n"; + } +} +sub check_custom_template { + my $command = $opt_c; + if ( $conf{DRY_RUN} == 1 ){ + print "No config check while DRY_RUN = 1\n"; + return; + } + if ( $command eq "ALL" ){ + return; + } + my $config_file = $conf{'CFG_DIR'}."/check_commands/".$command.".cfg"; + my $storage_type = "MULTIPLE"; + if ( -e $config_file && $conf{'FORCE'} == 0 ) { + print "\nConfig for command $command does already exist ($config_file)\n\n"; + exit 0; + } +} + +sub write_custom_template { + my $command = $opt_c; + if ( $conf{DRY_RUN} == 1 ){ + print "No config check while DRY_RUN = 1\n"; + return; + } + if ( $opt_c eq "ALL"){ + change_config(); + return; + } + my $config_file = $conf{'CFG_DIR'}."/check_commands/".$command.".cfg"; + my $storage_type = "MULTIPLE"; + open(CFG, ">", $config_file); + print CFG "# Generated by rrd_convert.pl @PKG_VERSION@\n"; + print CFG "RRD_STORAGE_TYPE = MULTIPLE\n"; + close(CFG); + if ( -s $config_file ) { + print "\nConfig for command $command created ($config_file)\n"; + } +} +sub read_choice{ + my $question = shift; + print $question.":"; + my $answer = ; + chomp $answer; + return $answer; +} + + +sub print_help{ + print "Usage: $0 --check_command=\n"; + print " --cfg_dir=\n"; + print " [ --list_commands ]\n"; + print " [ --dry-run ]\n"; + print " [ --tmp_dir= ]\n"; + print " [ --no_structure_check ]\n"; + print "\n"; + print "This script is used to switch to RRD_STORAGE_TYPE = MULTIPLE for a given Nagios Check Command\n"; + print "More info online http://docs.pnp4nagios.org/pnp-0.6/rrd_convert\n"; + exit; +} + +sub print_help_opt_p{ + print "\n"; + print "--cfg_dir not set\n"; + print "Please provide the path to your PNP4Nagios config directory\n"; + print "\n"; + print_help(); +} + +sub print_version{ + print "Version @PKG_VERSION@\n"; + exit; +} diff --git a/scripts/rrd_modify.pl.in b/scripts/rrd_modify.pl.in new file mode 100644 index 0000000..241dfcd --- /dev/null +++ b/scripts/rrd_modify.pl.in @@ -0,0 +1,282 @@ +#!@PERL@ -w +# nagios: -epn +## @PKG_NAME@–@PKG_VERSION@ +# +# Copyright (c) 2012 PNP4Nagios Developer Team (http://www.pnp4nagios.org) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# There are several Perl modules out there on www.cpan.org which allow adding +# columns to an RRD file, so if this one doesn't fit your needs please have +# a look there. +# Please report any errors nevertheless. +# See http://docs.pnp4nagios.org/pnp-0.6/about#support for details. + +use strict; +use warnings; + +# you may have to adapt the path to your environment +my $rrdtool = "@RRDTOOL@"; +# set to 1 if using PNP4Nagios where data source names are numerical +my $PNP = 1; + +### ---------------------------------------- ### +### no user servicable parts below this line ### + +my $pgm = "rrd_modify.pl"; +my $version = "0.01"; +my $legal = "Copyright (c) 2012 PNP4Nagios Developer Team (http://www.pnp4nagios.org)"; + +my ($rrd,$action,$columns,$type) = @ARGV; +# valid actions +my %action = (insert => 1, delete => 2); +# valid data types +my %type = (GAUGE => 1, COUNTER => 2, DERIVE => 3, ABSOLUTE => 4, COMPUTE => 5); +# xml tags within cdp_prep +my @cdp = ('primary_value','secondary_value','value', + 'unknown_datapoints','seasonal','last_seasonal', + 'init_flag','intercept','last_intercept', + 'slope','last_slope','nan_count','last_nan_count'); + +my @ds = (); # number of data sources within the rrd file +my $out = 1; # output lines to file +my $sign = "."; # decimal sign (locale dependent) +my %xml = (); # lines within ds structure + +# defined? +if ($#ARGV < 2) { + usage(); + exit 1; +} + +die "$rrd does not exist\n" unless (-f $rrd); +die "$rrd is not readable\n" unless (-r $rrd); +die "$rrd is not writable\n" unless (-w $rrd); +die "$rrdtool is a directory\n" if (-d $rrdtool); +die "$rrdtool does not exist\n" unless (-f $rrdtool); +die "$rrdtool is not executable\n" unless (-x $rrdtool); + +$action = lc($action); +unless (exists($action{$action})) { + print "ERROR: action $action is not valid\n\n"; + usage(); + exit 1; +} + +my ($start,$no) = split(/,/,$columns); +$no = 1 unless (defined $no); +# determine the number of data sources +my $ds = `$rrdtool info $rrd | grep '^ds' | grep 'value' | wc -l`; +# determine the decimal sign +$sign = `$rrdtool info $rrd | grep '^ds' | grep 'value' | tail -1`; +($sign) = $sign =~ /.* \d(.)\d+/; +my $end = ($action eq "insert" ? $ds+$no : $ds); +if (($start < 1) or ($start > $ds + 1)) { + print "ERROR: number ($start) must be within 1..".($ds+1)."\n"; + exit 2; +} + +# check / set type of data source to be created +if ($action eq "insert") { + if (defined $type) { + $type = uc($type); + unless (exists($type{$type})) { + print "ERROR: type $type is not valid\n\n"; + usage(); + exit 3; + } + } else { + $type = "GAUGE"; + } +} + +# names of temporary/output files +my $tmp1 = "$rrd.in"; +my $tmp2 = "$rrd.out"; +my $cmd = "$rrdtool dump $rrd > $tmp1"; +my $erg = system("$cmd"); +print "$cmd: RC=$erg\n" if ($erg); + +processing ("$rrd"); + +$cmd = "$rrdtool restore $tmp2 $rrd.chg"; +$erg = system("$cmd"); +print "$cmd: RC=$erg\n" if ($erg); +unlink "$tmp1"; +unlink "$tmp2"; +exit; + +### some sub routines + +sub processing { + open (IFILE, "$tmp1") || die "error during open of $tmp1, RC=$!\n"; + open (OFILE, ">$tmp2") || die "error during create of $tmp2, RC=$!\n"; + while () { + my $tmp = $_; + if (//) { + $out = 0; + %xml = (); + next; + } + if (/<\/ds>/) { + my %tmp = %xml; + push @ds, \%tmp; + next; + } + if ((m|Round Robin Archives|) or (m||)) { + $out = 1; + if ($action eq "insert") { + my @save = splice(@ds,$start-1); + for (1..$no) { + my %xml = (@save) ? %{$save[0]} : %{$ds[0]}; + $xml{name} = $start+$_-1; + # set defaults + if (m|Round Robin Archives|) { + $xml{last_ds} = "U"; + $xml{value} = "0${sign}0000000000e+00"; + $xml{unknown_sec} = 0; + } else { + $xml{primary_value} = "0${sign}0000000000e+00"; + $xml{secondary_value} = "0${sign}0000000000e+00"; + $xml{value} = "NaN" if (exists $xml{value}); + $xml{unknown_datapoints} = 0 if (exists $xml{unknown_datapoints}); + $xml{init_flag} = 1 if (exists $xml{init_flag}); + $xml{seasonal} = "NaN" if (exists $xml{seasonal}); + $xml{last_seasonal} = "NaN" if (exists $xml{last_seasonal}); + $xml{intercept} = "NaN" if (exists $xml{intercept}); + $xml{last_intercept} = "NaN" if (exists $xml{last_intercept}); + $xml{slope} = "NaN" if (exists $xml{slope}); + $xml{last_slope} = "NaN" if (exists $xml{last_slope}); + $xml{nan_count} = 1 if (exists $xml{nan_count}); + $xml{last_nan_count} = 1 if (exists $xml{last_nan_count}); + } + push @ds,\%xml; + } + push @ds,@save; + } else { + my @save = splice(@ds,$start-1,$no); + if ($PNP) { # renumber data source names + for my $idx ($start..$end-$no) { + $ds[$idx-1]->{name} = $idx; + } + } + } + if (m|Round Robin Archives|) { + out_ds1(); + } else { + out_ds2(); + } + print OFILE $tmp; + @ds = (); + next; + } + if (//) { + row($_); + next; + } + # value enclosed in XML tags + if (/<(\S+)>\s+(\S+)\s+)(.*)<\/row>/; + for (1..$start-1) { + if ($r =~ s#^(.*?)##) { + $line .= $1; + } + } + for ($start..$start+$no-1) { + if ($action eq "insert") { + $line .= " NaN "; + } else { + $r =~ s#^(.*?)##; + } + } + for ($start+$no..$end) { + if ($r =~ s#^(.*?)##) { + $line .= $1; + } + } + $line .= "\n"; + print OFILE $line; +} + +sub out_ds1 { + for (0..$#ds) { + print OFILE < +\t\t $ds[$_]->{name} +\t\t $ds[$_]->{type} +\t\t $ds[$_]->{minimal_heartbeat} +\t\t $ds[$_]->{min} +\t\t $ds[$_]->{max} + +\t\t +\t\t $ds[$_]->{last_ds} +\t\t $ds[$_]->{value} +\t\t $ds[$_]->{unknown_sec} +\t + +EOD + } +} + +sub out_ds2 { + for my $ds_no (0..$#ds) { + print OFILE "\t\t\t\n"; + for my $tag (0..$#cdp) { + print OFILE "\t\t\t<$cdp[$tag]> $ds[$ds_no]->{$cdp[$tag]} \n" if (exists($ds[$ds_no]->{$cdp[$tag]})); + } + print OFILE "\t\t\t\n"; + } +} + +sub usage { +print < \$help, + "d|debug" => \$debug, + "m|mode=s" => \$mode, + "c|config=s" => \$MainCfg, + "p|pnpcfg=s" => \$PNPCfg, + "o|object=s" => \$object, +); + +my @modes = ("bulk", "bulk+npcd", "sync", "npcdmod"); +my @products = ("nagios", "icinga"); +my @states = ("OK", "WARN", "CRIT", "UNKN", "INFO", "HINT", "DBG"); +my @colors = ("bold green", "bold yellow", "bold red", "bold blue", "bold blue", "bold yellow", "black on_red"); +my %process_perf_data_stats = ('hosts' => 0, 'services' => 0, 'noperf' => 0, 'noperf_but_enabled' => 0 , 0 => 0, 1 => 0); +my %stats = ( 0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 =>0 ); +my %sizing = ( + 50 => 'sync', + 200 => 'bulk', + 5000 => 'bulk+npcd', + 10000 => 'npcdmod', +); + +if ( ! $MainCfg ){ + usage(); + usage_no_config(); + exit; +} + +if ( ! $mode ){ + usage(); + usage_no_mode(); + exit; +} + +if ( ! $PNPCfg ){ + usage(); + usage_no_pnpcfg(); + exit; +} + +if( ! in_array(\@modes, $mode)){ + usage(); + info("'$mode' is not a valid option",2); + info("Valid modes are [@modes]",2); + exit; +} + +my %statistics = ( + 'OK' => 0, + 'WARN' => 0, + 'CRIT' => 0, +); + + +my %cfg = (); +my %commands = (); +my $uid = 0; +my $gid = 0; +my $process_perfdata_cfg = 0; + +# +# Begin +# + +info("========== Starting Environment Checks ============",4); +info("My version is: ".$version,4); +info("Start Options: ".$start_options, 4); + +# +# Read Main config file +# +process_nagios_cfg(); +# +# get the product name +# +my $product = get_product(); +if( $product eq 0 ){ + info("Can´t determine product while reading $MainCfg", 4); + info_and_exit("$MainCfg does not look like a valid config file", 2); +}else{ + info("Running product is '$product'", 0); +} + +# +# Read objects cache file to get more information +# Needs a running product +# +check_config_var('object_cache_file', 'exists', 'break'); +if( -r $cfg{'object_cache_file'} ){ + process_objects_file($cfg{'object_cache_file'}); +}else{ + info_and_exit($cfg{'object_cache_file'}. " is not readable", 2); +} + +# +# Read resource.cfg +# +check_config_var('resource_file', 'exists', 'break'); +if( -r $cfg{'resource_file'} ){ + process_npcd_cfg($cfg{'resource_file'}); +}else{ + info_and_exit($cfg{'resource_file'}. " is not readable", 2); +} + +# +# Read process_perfdata.cfg +# +if ( ! -d $PNPCfg ){ + info_and_exit("Directory $PNPCfg does not exist",2); +} +if ( ! -d "$PNPCfg/check_commands" ){ + info("Directory $PNPCfg/check_commands does not exist",2); + info_and_exit("$PNPCfg does not look like a PNP4Nagios config directory",2); +} +my $ppcfg = "$PNPCfg/process_perfdata.cfg"; +process_perfdata_cfg($ppcfg); + +# +# Read etc/pnp_release file if exists +# +if( -r "$PNPCfg/pnp4nagios_release" ){ + process_pnp4nagios_release("$PNPCfg/pnp4nagios_release"); + info("Found PNP4Nagios version ".get_config_var('PKG_VERSION'), 0); + info("./configure Options ".get_config_var('CONFIGURE_ARGS'), 0) if get_config_var('CONFIGURE_ARGS'); +}else{ + info("No pnp4nagios_release file found. This might be an older version of PNP4Nagios", 0); +} + +# +# Start Main config checks +# + +if(config_var_exists($product.'_user') ){ + my $user = get_config_var($product.'_user'); + $uid = getpwnam($user); + info( "Effective User is '$user'", 0); + if($uid){ + info("User $user exists with ID '$uid'", 0 ); + }else{ + info_and_exit("User $user does not exist", 2 ); + } +}else{ + info_and_exit("Option '".$product."_user' not found in $MainCfg", 2); +} + +if(config_var_exists($product.'_group') ){ + my $group = get_config_var($product.'_group'); + $gid = getgrnam($group); + info( "Effective group is '$group'", 0); + if($gid){ + info("Group $group exists with ID '$gid'", 0 ); + }else{ + info_and_exit("Group $group does not exist", 2 ); + } +}else{ + info_and_exit("Option '".$product."_group' not found in $MainCfg", 2); +} + +# +# Start sync config checks +# + +if($mode eq "sync"){ + info("========== Checking Sync Mode Config ============",4); + + compare_config_var('process_performance_data', '1'); + compare_config_var('enable_environment_macros', '1'); + + check_config_var('service_perfdata_command', 'exists'); + check_config_var('host_perfdata_command', 'exists');; + last_info("Needed config options are missing.",5,$last_check); + + # Options not allowed in sync mode + check_config_var('service_perfdata_file', 'notexists'); + check_config_var('service_perfdata_file_template', 'notexists'); + check_config_var('service_perfdata_file_mode', 'notexists'); + check_config_var('service_perfdata_file_processing_interval', 'notexists'); + check_config_var('service_perfdata_file_processing_command', 'notexists',); + check_config_var('host_perfdata_file', 'notexists'); + check_config_var('host_perfdata_file_template', 'notexists'); + check_config_var('host_perfdata_file_mode', 'notexists'); + check_config_var('host_perfdata_file_processing_interval', 'notexists'); + check_config_var('host_perfdata_file_processing_command', 'notexists'); + check_config_var('broker_module', 'notexists'); + last_info("Config options are not allowed in sync mode. http://docs.pnp4nagios.org",5,$last_check); + + info(ucfirst($product)." config looks good so far",4); + info("========== Checking config values ============",4); + my $command_line; + + $command_line = check_command_definition('service_perfdata_command'); + check_process_perfdata_pl($command_line); + + $command_line = check_command_definition('host_perfdata_command'); + check_process_perfdata_pl($command_line); + +} + +if($mode eq "bulk"){ + info("========== Checking Bulk Mode Config ============",4); + + compare_config_var('process_performance_data', '1'); + check_config_var('service_perfdata_file', 'exists'); + check_config_var('service_perfdata_file_template', 'exists'); + check_perfdata_file_template(get_config_var('service_perfdata_file_template')); + check_config_var('service_perfdata_file_mode', 'exists'); + check_config_var('service_perfdata_file_processing_interval', 'exists'); + check_config_var('service_perfdata_file_processing_command', 'exists'); + + check_config_var('host_perfdata_file', 'exists'); + check_config_var('host_perfdata_file_template', 'exists'); + check_perfdata_file_template(get_config_var('host_perfdata_file_template')); + check_config_var('host_perfdata_file_mode', 'exists'); + check_config_var('host_perfdata_file_processing_interval', 'exists'); + check_config_var('host_perfdata_file_processing_command', 'exists'); + last_info("Needed config options are missing.",5,$last_check); + + # Options not allowed in bulk mode + check_config_var('service_perfdata_command', 'notexists'); + check_config_var('host_perfdata_command', 'notexists'); + check_config_var('broker_module', 'notexists'); + last_info("Config options are not allowed in bulk mode",5,$last_check); + + info(ucfirst($product)." config looks good so far",4); + info("========== Checking config values ============",4); + my $command_line; + + $command_line = check_command_definition('service_perfdata_file_processing_command'); + check_process_perfdata_pl($command_line); + + $command_line = check_command_definition('host_perfdata_file_processing_command'); + check_process_perfdata_pl($command_line); +} + +if($mode eq "bulk+npcd"){ + info("========== Checking Bulk Mode + NPCD Config ============",4); + + compare_config_var('process_performance_data', '1'); + check_config_var('service_perfdata_file', 'exists'); + check_config_var('service_perfdata_file_template', 'exists'); + check_perfdata_file_template(get_config_var('service_perfdata_file_template')); + check_config_var('service_perfdata_file_mode', 'exists'); + check_config_var('service_perfdata_file_processing_interval', 'exists'); + check_config_var('service_perfdata_file_processing_command', 'exists'); + + check_config_var('host_perfdata_file', 'exists'); + check_config_var('host_perfdata_file_template', 'exists'); + check_perfdata_file_template(get_config_var('host_perfdata_file_template')); + check_config_var('host_perfdata_file_mode', 'exists'); + check_config_var('host_perfdata_file_processing_interval', 'exists'); + check_config_var('host_perfdata_file_processing_command', 'exists'); + last_info("Needed config options are missing. http://docs.pnp4nagios.org",5,$last_check); + + # Options not allowed in bulk mode + check_config_var('service_perfdata_command', 'notexists'); + check_config_var('host_perfdata_command', 'notexists'); + check_config_var('broker_module', 'notexists'); + last_info("Config options are not allowed in bulk mode with npcd",5,$last_check); + + info(ucfirst($product)." config looks good so far",4); + info("========== Checking config values ============",4); + my $command_line; + + my $npcd_cfg = check_proc_npcd(get_config_var($product.'_user')); + + if( -r $npcd_cfg){ + info("$npcd_cfg is used by npcd and readable",0); + }else{ + info_and_exit("$npcd_cfg is not readable",0); + } + # read npcd.cfg into %cfg + process_npcd_cfg($npcd_cfg); + + check_config_var('perfdata_spool_dir', 'exists'); + count_spool_files(get_config_var('perfdata_spool_dir')); + + $command_line = check_command_definition('service_perfdata_file_processing_command'); + $command_line = check_command_definition('host_perfdata_file_processing_command'); + + check_process_perfdata_pl($cfg{'perfdata_file_run_cmd'}); +} + +if($mode eq "npcdmod"){ + my $val; + + info("========== Checking npcdmod Mode Config ============",4); + + compare_config_var('process_performance_data', '1'); + last_info ("Needed config options are missing. http://docs.pnp4nagios.org",5,$last_check); + + # Options not allowed in sync mode + check_config_var('service_perfdata_file', 'notexists'); + check_config_var('service_perfdata_file_template', 'notexists'); + check_config_var('service_perfdata_file_mode', 'notexists'); + check_config_var('service_perfdata_file_processing_interval', 'notexists'); + check_config_var('service_perfdata_file_processing_command', 'notexists'); + check_config_var('host_perfdata_file', 'notexists'); + check_config_var('host_perfdata_file_template', 'notexists'); + check_config_var('host_perfdata_file_mode', 'notexists'); + check_config_var('host_perfdata_file_processing_interval', 'notexists'); + check_config_var('host_perfdata_file_processing_command', 'notexists'); + last_info("Config options are not allowed in bulk mode with npcd",5,$last_check); + + # event_broker_option must have enabled bits 2 and 3 (0b01100) + check_config_var ('event_broker_options', 'exists'); + $val = get_config_var('event_broker_options') & 0x0c; + if($val == 12){ + info("event_broker_option bits 2 and 3 enabled ($val)",0); + }else{ + info_and_exit("event_broker_option bits 2 and/or 3 not enabled",2); + } + + check_config_var('broker_module', 'exists', 'break'); + + $val = get_config_var('broker_module'); + # extract npcd.cfg patch from broker_module definition + my $npcdmod_npcd_cfg; + $val =~ /npcdmod\.o\s+config_file=(.*)$/; + if($1){ + $npcdmod_npcd_cfg=$1; + info("npcdmod.o config file is $npcdmod_npcd_cfg",0); + if( -r $npcdmod_npcd_cfg){ + info("$npcdmod_npcd_cfg used by npcdmod.o is readable",0); + }else{ + info_and_exit("$npcdmod_npcd_cfg used by npcdmod.o is not readable",2); + } + }else{ + info("broker_module definition looks suspect '$val'",2); + info_and_exit("Can´t extract path to npcd.cfg from your broker_module definition",2); + } + # extract npcd.cfg path from process list + my $npcd_cfg = check_proc_npcd(get_config_var($product.'_user')); + if( -r $npcd_cfg){ + info("$npcd_cfg is used by npcd and readable",0); + } + if($npcd_cfg eq $npcdmod_npcd_cfg){ + info("npcd and npcdmod.o are using the same config file ($npcd_cfg)",0); + }else{ + info_and_exit("npcd and npcdmod.o are not using the same config file($npcd_cfg<=>$npcdmod_npcd_cfg)",2); + } + + # read npcd.cfg into %cfg + process_npcd_cfg($npcd_cfg); + check_config_var('perfdata_spool_dir', 'exists'); + count_spool_files(get_config_var('perfdata_spool_dir')); + + info(ucfirst($product)." config looks good so far",4); + info("========== Checking config values ============",4); + + # read npcd.cfg into %cfg + process_npcd_cfg($npcd_cfg); + check_process_perfdata_pl($cfg{'perfdata_file_run_cmd'}); + +} + +info("========== Starting global checks ============",4); +check_config_var('status_file', 'exists', 'break'); +process_status_file(); +info("==== Starting rrdtool checks ====",4); +check_rrdtool(); + +info("==== Starting directory checks ====",4); +check_config_var('RRDPATH', 'exists', 'break'); +check_perfdata_dir(get_config_var('RRDPATH')); + +if($process_perf_data_stats{1} == 0){ + info("'process_perf_data 1' is not set for any of your hosts/services",2); +} +if($process_perf_data_stats{'noperf'} > 0){ + info($process_perf_data_stats{'noperf'}." hosts/services are not providing performance data",1); +} +if($process_perf_data_stats{'noperf_but_enabled'} > 0){ + info("'process_perf_data 1' is set for ".$process_perf_data_stats{'noperf_but_enabled'}." hosts/services which are not providing performance data!",1); +} +if($process_perf_data_stats{0} > 0){ + info("'process_perf_data 0' is set for ".$process_perf_data_stats{0}." of your hosts/services",1); +} +if($process_perf_data_stats{1} > 0){ + info("'process_perf_data 1' is set for ".$process_perf_data_stats{1}." of your hosts/services",0); +} + +if ( get_config_var('LOG_LEVEL') gt 0 ){ + info("Logging is enabled in process_perfdata.cfg. This will reduce the overall performance of PNP4Nagios",1) +} + +info("==== System sizing ====",4); +print_sizing(); + +info("==== Check statistics ====",4); +print_stats(); +exit; + +# +# Helper Functions +# + +sub config_var_exists { + my $key = shift; + if(exists $cfg{$key}){ + return 1; + }else{ + return 0; + } +} + +sub get_config_var { + my $key = shift; + if(exists $cfg{$key}){ + return $cfg{$key}; + }else{ + return undef; + } +} + +sub count_spool_files { + my $spool_dir = shift; + my @all_files = glob "$spool_dir/*"; + if($#all_files >= 10){ + info("$#all_files files found in $spool_dir",2); + info("Something went wrong here!",5); + }elsif($#all_files >= 3){ + info("$#all_files files found in $spool_dir",1); + info("Something went wrong here!",5); + }else{ + info("$#all_files files found in $spool_dir",0); + } +} +sub check_command_definition { + my $option = shift; + warn $option; + my $key = get_config_var($option); + my $val = $commands{$key}; + if(exists $commands{$key}){ + info("Command $key is defined",0); + info("'$val'",0); + }else{ + info_and_exit("Command $key is not defined",2); + } + if($mode eq "sync"){ + if ( $option eq "host_perfdata_command"){ + if( $val =~ m/process_perfdata.pl\s+-d\s+HOSTPERFDATA/ ){ + info ( "Command looks good",0 ); + }else{ + info_and_exit ( "Command looks suspect ($val)",2 ); + } + }else{ + if( $val =~ m/process_perfdata.pl$/ or $val =~ m/process_perfdata.pl\s+-d\s+SERVICEPERFDATA/ ){ + info ( "Command looks good",0 ); + }else{ + info_and_exit ( "Command looks suspect ($val)",2 ); + } + } + } + if($mode eq "bulk"){ + if( $val =~ m/process_perfdata.pl\s+--bulk=/){ + info ( "Command looks good",0 ); + }else{ + info_and_exit ( "Command looks suspect ($val)",2 ); + } + } + if($mode eq "bulk+npcd"){ + my $dump_file = get_config_var( $option =~m/(.*)_processing_command/ ); + my $perfdata_spool_dir = get_config_var( 'perfdata_spool_dir'); + #print "$dump_file\n"; + my $regex = qr/\/bin\/mv\s+$dump_file\s+$perfdata_spool_dir/; + if( $val =~ m/$regex/){ + info ( "Command looks good",0 ); + }else{ + info ( "Regex = $regex", 4 ); + info_and_exit ( "Command looks suspect ($val)",2 ); + } + } + return $commands{$key}; + +} + +# +# Max three parameters +# +sub check_config_var { + my $key = shift; + my $check = shift; + my $break = shift||0; + my $var = get_config_var($key); + if($check eq "exists"){ + if(defined($var)){ + info("$key is defined",0); + info("$key=$var",0); + #$last_check = 0; + }else{ + info("$key is not defined",2); + $last_check++; + exit if $break; + } + } + if($check eq "notexists"){ + if( ! defined($var)){ + #info("$key is not defined",0); + #$last_check = 0; + }else{ + info("$key is defined ($key=$var)",2); + info("$key is not allowed in mode '$mode'",2); + $last_check++; + exit if $break; + } + } +} + +sub compare_config_var { + my $key = shift; + my $compare = shift; + my $break = shift||0; + my $var = get_config_var($key); + if( $var =~ /$compare/){ + info("$key is $var compared with '/$compare/'",0); + }else{ + info("$key is $var compared with '/$compare/'",2); + exit if $break; + } +} + +sub check_perfdata_file_template { + $_ = shift; + if ( not $_ ){ + return; + } + + if( /^DATATYPE::(HOST|SERVICE)PERFDATA/ ){ + info("PERFDATA template looks good",0); + }else{ + info("PERFDATA template looks suspect",2); + } +} + +sub info { + my $string = shift; + my $state = shift||0; + my $break = shift||0; + + $stats{$state}++; + return if $state == 6 and not defined $debug; + $statistics{$states[$state]}++; + print color $colors[$state]; + printf("[%-4s]", $states[$state]); + print color 'reset'; + printf(" %s\n", $string); +} + +sub last_info { + my $string = shift; + my $state = shift; + my $break = shift||0; + return if $break == 0; + info("$string ($break)", $state); + exit if $break > 0; +} +sub info_and_exit { + my $string = shift; + my $state = shift; + info($string, $state); + exit $state; +} + +sub print_stats { + my $state = 0; + $state = 1 if $stats{1} > 0; + $state = 2 if $stats{2} > 0; + info(sprintf("Warning: %d, Critical: %d",$stats{1}, $stats{2}),$state); + info("Checks finished...", $state); +} + +sub print_sizing { + my $object_count = ($process_perf_data_stats{'hosts'} + $process_perf_data_stats{'services'}); + my $graph_count = ($process_perf_data_stats{'hosts'} + $process_perf_data_stats{'services'}); + info("$object_count hosts/service objects defined",0); + foreach my $limit ( sort {$a <=> $b} keys %sizing){ + if($graph_count >= $limit and $sizing{$limit} eq $mode){ + info("Use at least mode '".get_mode_by_size($graph_count)."' to reduce I/O",5); + last; + } + } +} + +sub get_mode_by_size { + my $graph_count = shift; + foreach my $limit ( sort {$a <=> $b} keys %sizing){ + return $sizing{$limit} if $limit >= $graph_count; + } + return 'gearman'; +} + +sub check_rrdtool { + check_config_var('RRDTOOL', 'exists', 'break'); + my $rrdtool = get_config_var('RRDTOOL'); + if ( -x $rrdtool ){ + info("$rrdtool is executable",0); + }else{ + info_and_exit("$rrdtool is not executable",2); + } + my @version = `$rrdtool`; + chomp $version[0]; + info($version[0],0); + check_config_var('USE_RRDs', 'exists', 'break'); + if(get_config_var('USE_RRDs')){ + unless ( eval "use RRDs;1" ) { + info("Perl RRDs modules are not loadable",1); + }else{ + info("Perl RRDs modules are loadable",0); + } + }else{ + unless ( eval "use RRDs;1" ) { + info("Perl RRDs modules are neither loadable nor enabled (USE_RRDs = 0)",1); + }else{ + info("RRDs modules are loadable but not enabled (USE_RRDs = 0)",1); + } + } +} + +sub check_proc_npcd { + my $user = shift; + my $out = `ps -u $user -o cmd | grep /npcd | grep -v grep`; + my $rc = $?; + chomp $out; + info("Check process: 'ps -u $user -o cmd | grep /npcd | grep -v grep'", 6); + info("Result: $out", 6); + info("Returncode: $rc", 6); + #extract npcd.cfg + $out =~ /-f\s?(\S+)/; + my $npcd_cfg = $1; + if($rc == 0){ + info("npcd daemon is running",0); + }else{ + info("npcd daemon is not running",2); + info_and_exit("A running npcd daemon is needed to process data.",4); + } + return $npcd_cfg; +} + +# process nagios.cfg +sub process_nagios_cfg { + info ("Reading $MainCfg", 4); + open (NFILE, "$MainCfg") || info_and_exit("Failed to open '$MainCfg'. $! ", 2); + while () { + process_main_cfg_line(); + } + close (NFILE); +} + +# process process_perfdata.cfg +sub process_perfdata_cfg { + my $cfg_file = shift; + if ( -r $cfg_file ){ + if ( process_cfg($cfg_file) ){ + $process_perfdata_cfg = 1; + }else{ + $process_perfdata_cfg = 0; + } + }elsif(-e "$PNPCfg/process_perfdata.cfg-sample"){ + info ("$cfg_file does not exist.",1); + info ("We will try to parse defaults from process_perfdata.pl later on", 1); + info ("process_perfdata.cfg-sample exists in $PNPCfg", 5); + info ("It is recommended to rename process_perfdata.cfg-sample to process_perfdata.cfg", 5); + $process_perfdata_cfg = 0; # we have to parse process_perfdata.pl to get defaults + }else{ + info ("$cfg_file does not exist.",1); + info ("We will try to parse defaults from process_perfdata.pl later on", 1); + info ("It is recommended to place $cfg_file in $PNPCfg", 5); + info ("A sample file is installed by 'make install-config'", 5); + $process_perfdata_cfg = 0; # we have to parse process_perfdata.pl to get defaults + } +} + +sub process_pnp4nagios_release { + my $cfg_file = shift; + if ( -r $cfg_file ){ + process_cfg($cfg_file); + } +} + +sub process_cfg { + my $cfg_file = shift; + if ( -r $cfg_file ){ + info ("Reading $cfg_file", 4); + + open (NFILE, "$cfg_file") || info_and_exit("Failed to open '$cfg_file'. $! ", 2); + while () { + process_main_cfg_line(); + } + close (NFILE); + return 1; + } + return 0; +} + +# process npcd.cfg +sub process_npcd_cfg { + my $cfg_file = shift; + if ( -r $cfg_file ){ + info ("Reading $cfg_file", 4); + }else{ + info ("$cfg_file does not exist", 4); + info ("this file is needed to get more information about your system", 5); + info_and_exit("no further processing possible",2); + } + + open (NFILE, "$cfg_file") || info_and_exit("Failed to open '$cfg_file'. $! ", 2); + while () { + process_main_cfg_line(); + } + close (NFILE); +} + +# process main config line +sub process_main_cfg_line { + chomp; + return if (/^$/); + return if (/^#/); + s/#.*//; + s/\s*$//; + if (my ($par, $val) = /([^=]+)\s?=\s?(.*)/){ + $par = trim($par); + $val = trim($val);; + if ( (defined($par) && $par eq "") ) { + info ("oddLine -> $_" ,4); + return;; + } + # skip broker_module lines. + return if (($par eq "broker_module") and ($val !~ /npcdmod.o/)); + info("'$par' -> '$val'",6); + $cfg{"$par"} = $val; + } +} + +sub trim { + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +# read object_file +sub process_objects_file { + my ($file) = @_; + my $cmd = ""; + my $line = ""; + info ("Reading $file", 4); + open (CFILE, "$file") || info_and_exit("Failed to open '$file'. $! ", 2); + while () { + s/#.*//; + next if (/^$/); + chomp; + if (/command_name/) { + ($cmd) = /command_name\s*(.*)/; + next; + } + next unless ( /command_line/); + ($line) = /command_line\s*(.*)/ ; + $commands{"$cmd"} = "$line"; + next unless (/process_perfdata.pl/); + my @cmd = split (/\s+/,$line); + } + close (CFILE); +} + +sub process_status_file { + my ($file) = get_config_var('status_file'); + my $line = ""; + my $perfdata_found = 0; + my ($host_query,$service_query) = split(/;/,$object) if ($object); + $host_query = "" unless (defined $host_query); + $service_query = "" unless (defined $service_query); + info("host_query = $host_query",4); + info("service_query = $service_query",4); + my $hst = ""; + my $srv = ""; + my $perf = ""; + my $ppd = ""; + info ("Reading $file", 4); + open (CFILE, "$file") || info_and_exit("Failed to open '$file'. $! ", 2); + while () { + s/#.*//; + next if (/^$/); + chomp; + if(/\shost_name=(.+)/){ + $hst = $1; + $srv = ""; + } + if(/\sservice_description=(.+)/){ + $srv = $1; + } + if(/\sperformance_data=$/){ + $process_perf_data_stats{'noperf'}++; + $perfdata_found = 0; + $perf = " $hst/$srv: [empty perf data]"; + } + if(/\sperformance_data=(.+)$/){ + $perfdata_found = 1; + $perf = " $hst/$srv: [$1]"; + } + # count process_perf_data definitions + if (/process_performance_data=(\d)$/){ + $ppd=$1; + $process_perf_data_stats{$1}++ ; + if ( $perfdata_found == 0 && $1 == 1){ + $process_perf_data_stats{'noperf_but_enabled'}++; + } + if ($host_query ne '') { + $perf = "" if ($hst !~ /$host_query/i); + if ($service_query ne '') { + $perf = "" if ($srv !~ /$service_query/i); + }else{ + $perf = ''; + } + }else{ + $perf=''; + } + if ($perf ne ""){ + info ("$perf, ppd=$ppd", 4); + } + } + if(/^hoststatus /){ + $process_perf_data_stats{'hosts'}++; + } + if(/^servicestatus /){ + $process_perf_data_stats{'services'}++; + } + } + close (CFILE); +} + +sub check_process_perfdata_pl { + my $command_line = shift; + my $path = ''; + if( $command_line =~ /\s?([^\s]*)\/process_perfdata.pl\s?/ ){ + $path = $1; + if ($path =~ /(\$USER\d+\$)/) { + if (exists $cfg{"$1"}) { + my $val = $cfg{"$1"}; + $path =~ s/\$USER\d+\$/$val/; + } + } + if( -x "$path/process_perfdata.pl" ){ + info("Script $path/process_perfdata.pl is executable",0); + }else{ + info_and_exit("Script $path/process_perfdata.pl is not executable",2); + } + process_pp_pl ("$path/process_perfdata.pl") if $process_perfdata_cfg == 0; + }else{ + info_and_exit("Can´t find path to process_perfdata.pl",2); + } +} + +sub check_perfdata_spool_dir { + my $dir = shift; + if( -d $dir ){ + info("Spool directory '$dir' exists",0); + }else{ + info_and_exit("Spool directory $dir does not exist",2); + } + my @files = <$dir/*>; + my $count = @files; + if($count > 1){ + info("$count files in $dir", 1); + }else{ + info("$dir is empty", 0); + } +} + +# +sub check_perfdata_dir { + my $dir = shift; + if( -d $dir ){ + info("Perfdata directory '$dir' exists",0); + find(\&check_perm, "$dir"); + }else{ + info_and_exit("Perfdata directory $dir does not exist",2); + } +} + +sub check_perm { + -d ; + my $f = "$File::Find::name"; + return unless (($f =~ /\/$/) or ($f =~ /rrd$|xml$/)); + check_usrgrp ($f); +} + +sub check_usrgrp { + my $file = shift; + my $break = shift || 0; + if ($uid) { + my $fuid = (stat("$file"))[4]; + my $fname = getpwuid($fuid); + info ("$file: owner is $fname", 2, $break) if ($fuid != $uid); + } + if ($gid) { + my $fgid = (stat("$file"))[5]; + my $fgroup = getgrgid($fgid); + info ("$file: group is $fgroup", 2, $break) if ($fgid != $gid); + } +} + +# read config inside process_perfdata.pl +sub process_pp_pl { + my $cfg_file = shift; + my $loop = 0; + info ("Reading $cfg_file", 4); + open (NFILE, "$cfg_file") || info_and_exit("Failed to open '$cfg_file'. $! ", 2); + while () { + chomp; + last if (/^\s*\);/); + s/#.*//; + s/\s*$//; + s/^\s+//; + next if (/^$/); + #$loop++ if (/%conf/); + #next unless ($loop); + my ($par, $val) = /([^\s]+)\s+=>\s+([^\s]+)/; # shortest string + next unless ((defined $par) and (defined $val)); + $val =~ s/['",]//g; + $cfg{"$par"} = $val; + } + close (NFILE); +} + +sub get_product { + for my $product (@products){ + my $string = $product . "_user"; + if ( exists $cfg{$string} ){ + return $product; + } + } + return 0; +} + +sub in_array{ + my ($arr,$search_for) = @_; + my %items = map {$_ => 1} @$arr; + return (exists($items{$search_for}))?1:0; +} + +sub usage{ +print <auto_render = FALSE; + } + + public function index(){ + url::redirect("start", 302); + } + + public function search() { + $query = pnp::clean($this->input->get('term')); + $result = array(); + if(strlen($query)>=1) { + $hosts = $this->data->getHosts(); + foreach($hosts as $host){ + if(preg_match("/$query/i",$host['name'])){ + array_push($result,$host['name']); + } + } + echo json_encode($result); + } + } + + public function remove($what){ + if($what == 'timerange'){ + $this->session->delete('start'); + $this->session->delete('end'); + $this->session->set('timerange-reset', 1); + } + } + + public function filter($what){ + if($what == 'set-sfilter'){ + $this->session->set('sfilter', $_POST['sfilter']); + }elseif($what == 'set-spfilter'){ + $this->session->set('spfilter', $_POST['spfilter']); + }elseif($what == 'set-pfilter'){ + $this->session->set('pfilter', $_POST['pfilter']); + } + } + + public function basket($action=FALSE){ + // Disable auto-rendering + $this->auto_render = FALSE; + $host = false; + $service = false; + $basket = array(); + + if($action == "list"){ + $basket = $this->session->get("basket"); + if(is_array($basket) && sizeof($basket) > 0){ + foreach($basket as $item){ + printf("
  • %s
  • \n", + "basket_action_remove", + $item, + $item, + Kohana::lang('common.basket-remove', $item), + url::base(), + pnp::shorten($item) + ); + } + } + }elseif($action == "add"){ + $item = $_POST['item']; + $basket = $this->session->get("basket"); + if(!is_array($basket)){ + $basket[] = "$item"; + }else{ + if(!in_array($item,$basket)){ + $basket[] = $item; + } + } + $this->session->set("basket", $basket); + foreach($basket as $item){ + printf("
  • %s
  • \n", + "basket_action_remove", + $item, + $item, + Kohana::lang('common.basket-remove', $item), + url::base(), + pnp::shorten($item) + ); + } + }elseif($action == "sort"){ + $items = $_POST['items']; + $basket = explode(',', $items); + array_pop($basket); + $this->session->set("basket", $basket); + foreach($basket as $item){ + printf("
  • %s
  • \n", + "basket_action_remove", + $item, + $item, + Kohana::lang('common.basket-remove', $item), + url::base(), + pnp::shorten($item) + ); + } + }elseif($action == "remove"){ + $basket = $this->session->get("basket"); + $item_to_remove = $_POST['item']; + $new_basket = array(); + foreach($basket as $item){ + if($item == $item_to_remove){ + continue; + } + $new_basket[] = $item; + } + $basket = $new_basket; + $this->session->set("basket", $basket); + foreach($basket as $item){ + printf("
  • %s
  • \n", + "basket_action_remove", + $item, + $item, + Kohana::lang('common.basket-remove', $item), + url::base(), + pnp::shorten($item) + ); + } + }elseif($action == "clear"){ + $this->session->delete("basket"); + }else{ + echo "Action $action not known"; + } + $basket = $this->session->get("basket"); + if(is_array($basket) && sizeof($basket) == 0){ + echo Kohana::lang('common.basket-empty'); + }else{ + echo "
    \n"; + echo "\n"; + echo "\n"; + echo "
    \n"; + } + } + +} diff --git a/share/pnp/application/controllers/color.php b/share/pnp/application/controllers/color.php new file mode 100644 index 0000000..b75ce00 --- /dev/null +++ b/share/pnp/application/controllers/color.php @@ -0,0 +1,26 @@ +template = $this->add_view('template'); + $this->template->color = $this->add_view('color'); + $this->template->color->color_box = $this->add_view('color_box'); + $this->template->color->logo_box = $this->add_view('logo_box'); + } + + public function index() + { + $this->scheme = $this->config->scheme; + + } +} diff --git a/share/pnp/application/controllers/debug.php b/share/pnp/application/controllers/debug.php new file mode 100644 index 0000000..b67354e --- /dev/null +++ b/share/pnp/application/controllers/debug.php @@ -0,0 +1,66 @@ +template = $this->add_view('template'); + $this->template->debug = $this->add_view('debug'); + } + + public function index() + { + + $this->data->getTimeRange($this->start,$this->end,$this->view); + + if(isset($this->host) && isset($this->service)){ + $this->url = "?host=".$this->host."&srv=".$this->service; + if($this->start){ + $this->url .= "&start=".$this->start; + $this->session->set("start", $this->start); + } + if($this->end){ + $this->url .= "&end=".$this->end; + $this->session->set("end", $this->end); + } + $services = $this->data->getServices($this->host); + $this->data->buildDataStruct($this->host,$this->service,$this->view); + $this->is_authorized = $this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']); + $this->title = "Service Details ". $this->host ." -> " . $this->data->MACRO['DISP_SERVICEDESC']; + }elseif(isset($this->host)){ + $this->is_authorized = $this->auth->is_authorized($this->host); + if($this->view == ""){ + $this->view = $this->config->conf['overview-range']; + } + if($this->start){ + $this->url .= "&start=".$this->start; + $this->session->set("start", $this->start); + } + if($this->end){ + $this->url .= "&end=".$this->end; + $this->session->set("end", $this->end); + } + $this->title = "Start $this->host"; + $services = $this->data->getServices($this->host); + $this->title = "Service Overview for $this->host"; + foreach($services as $service){ + if($service['state'] == 'active') + $this->data->buildDataStruct($this->host,$service['name'],$this->view); + } + }else{ + if(isset($this->host)){ + url::redirect("/graph"); + }else{ + throw new Kohana_Exception('error.get-first-host'); + } + } + } +} diff --git a/share/pnp/application/controllers/docs.php b/share/pnp/application/controllers/docs.php new file mode 100644 index 0000000..004b8b7 --- /dev/null +++ b/share/pnp/application/controllers/docs.php @@ -0,0 +1,80 @@ +template = $this->add_view('template'); + $this->template->docs = $this->add_view('docs'); + $this->template->docs->search_box = $this->add_view('search_box'); + $this->template->docs->docs_box = $this->add_view('docs_box'); + $this->template->docs->logo_box = $this->add_view('logo_box'); + $this->doc_language = $this->config->conf['doc_language']; + } + + public function index(){ + url::redirect("docs/view/"); + } + + public function view($lang=FALSE, $page=FALSE){ + if($lang == FALSE){ + if(!in_array($this->config->conf['lang'],$this->doc_language) ){ + $this->lang = $this->doc_language[0]; + }else{ + $this->lang = $this->config->conf['lang'] ; + } + }else{ + if(in_array($lang,$this->doc_language) ){ + $this->lang = $lang; + }else{ + $this->lang = $this->doc_language[0]; + url::redirect("docs/view/"); + } + } + + if($page == FALSE){ + url::redirect("docs/view/".$this->lang."/start"); + } + + $this->page = $page; + $file = sprintf("documents/%s/%s.html", $this->lang, $this->page); + $file_toc = sprintf("documents/%s/start.html", $this->lang); + if(!file_exists($file)){ + url::redirect("docs/view/start"); + } + $this->content = file_get_contents($file); + $toc = file( $file_toc ); + $this->toc = ""; + $in = FALSE; + foreach($toc as $t){ + if(preg_match("/SECTION/", $t) ){ + $in = ! $in; + continue; + } + if($in == TRUE){ + $this->toc .= $t; + } + } + # + # some string replacements + # + $this->toc = str_replace("/de/pnp-0.6/", "", $this->toc); + $this->toc = str_replace("/pnp-0.6/", "", $this->toc); + $this->toc = preg_replace("/

    .*<\/h2>/", "" , $this->toc); + $this->content = str_replace("/templates/", "http://docs.pnp4nagios.org/templates/", $this->content); + $this->content = str_replace("/de/pnp-0.6/", "", $this->content); + $this->content = str_replace("/pnp-0.6/", "", $this->content); + $this->content = str_replace("/_media", url::base()."documents/_media", $this->content); + $this->content = str_replace("gallery", "", $this->content); + $this->content = str_replace("/_detail", url::base()."documents/_media", $this->content); + $this->content = str_replace("/lib/images", url::base()."documents/images", $this->content); + $this->graph_width = ($this->config->conf['graph_width'] + 140); + } +} diff --git a/share/pnp/application/controllers/graph.php b/share/pnp/application/controllers/graph.php new file mode 100644 index 0000000..7dd72ca --- /dev/null +++ b/share/pnp/application/controllers/graph.php @@ -0,0 +1,129 @@ +template = $this->add_view('template'); + if (isset($this->version) && $this->version == "tiny" ) + $this->template->graph = $this->add_view('graph_tiny'); + else + $this->template->graph = $this->add_view('graph'); + $this->template->zoom_header = $this->add_view('zoom_header'); + $this->template->zoom_header->graph_width = ($this->config->conf['zgraph_width'] + 140); + $this->template->zoom_header->graph_height = ($this->config->conf['zgraph_height'] + 230); + $this->template->graph->icon_box = $this->add_view('icon_box'); + $this->template->graph->icon_box->position = "graph"; + $this->template->graph->icon_box->xml_icon = TRUE; + $this->template->graph->icon_box->pdf_icon = TRUE; + } + + public function index() + { + $this->template->graph->graph_content = $this->add_view('graph_content'); + $this->template->graph->graph_content->graph_width = ($this->config->conf['graph_width'] + 85); + $this->template->graph->graph_content->timerange_select = $this->add_view('timerange_select'); + $this->template->graph->header = $this->add_view('header'); + $this->template->graph->search_box = $this->add_view('search_box'); + $this->template->graph->service_box = $this->add_view('service_box'); + $this->template->graph->basket_box = $this->add_view('basket_box'); + $this->template->graph->widget_menu = $this->add_view('widget_menu'); + $this->template->graph->graph_content->widget_graph = $this->add_view('widget_graph'); + // Change the status box while multisite theme is in use + if($this->theme == "multisite"){ + $this->template->graph->status_box = $this->add_view('multisite_box'); + $this->template->graph->status_box->base_url = $this->config->conf['multisite_base_url']; + $this->template->graph->status_box->site = $this->config->conf['multisite_site']; + }else{ + $this->template->graph->status_box = $this->add_view('status_box'); + } + // Service Details + if($this->host != "" && $this->service != ""){ + $this->service = pnp::clean($this->service); + $this->host = pnp::clean($this->host); + $this->url = "?host=".$this->host."&srv=".$this->service; + $services = $this->data->getServices($this->host); + #Landingpage for mobile devices + if($this->isMobileDevice()){ + url::redirect( "mobile/host/".urlencode($this->host)."/".urlencode($this->service) ); + } + #print Kohana::debug($services); + $this->data->buildDataStruct($this->host,$this->service,$this->view); + $this->is_authorized = $this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']); + + $this->title = Kohana::lang('common.service-details') . " ". $this->host ." -> " . $this->data->MACRO['DISP_SERVICEDESC']; + $this->template->graph->graph_content->graph_width = ($this->data->STRUCT[0]['GRAPH_WIDTH'] + 85); + // Status Box Vars + $this->template->graph->status_box->host = $this->data->MACRO['DISP_HOSTNAME']; + $this->template->graph->status_box->lhost = $this->data->MACRO['HOSTNAME']; + $this->template->graph->status_box->service = $this->data->MACRO['DISP_SERVICEDESC']; + $this->template->graph->status_box->lservice = $this->data->MACRO['SERVICEDESC']; + $this->template->graph->status_box->timet = date($this->config->conf['date_fmt'],intval($this->data->MACRO['TIMET'])); + // Service Box Vars + $this->template->graph->service_box->services = $services; + $this->template->graph->service_box->host = $this->host; + // Timerange Box Vars + $this->template->graph->timerange_box = $this->add_view('timerange_box'); + $this->template->graph->timerange_box->timeranges = $this->data->TIMERANGE; + // + // Host Overview + }elseif($this->host != ""){ + $this->is_authorized = $this->auth->is_authorized($this->host); + $this->host = pnp::clean($this->host); + #Landingpage for mobile devices + if($this->isMobileDevice()){ + url::redirect( "mobile/host/".urlencode($this->host) ); + } + if($this->view == ""){ + $this->view = $this->config->conf['overview-range']; + } + $this->url = "?host=".$this->host; + $this->title = Kohana::lang('common.start'). " ". $this->host; + $services = $this->data->getServices($this->host); + // Status Box Vars + $this->template->graph->status_box->host = $this->data->MACRO['DISP_HOSTNAME']; + $this->template->graph->status_box->lhost = $this->data->MACRO['HOSTNAME']; + $this->template->graph->status_box->shost = pnp::shorten($this->data->MACRO['DISP_HOSTNAME']); + $this->template->graph->status_box->timet = date($this->config->conf['date_fmt'],intval($this->data->MACRO['TIMET'])); + // Service Box Vars + $this->template->graph->service_box->services = $services; + $this->template->graph->service_box->host = $this->host; + // Timerange Box Vars + $this->template->graph->timerange_box = $this->add_view('timerange_box'); + $this->template->graph->timerange_box->timeranges = $this->data->TIMERANGE; + + $this->template->graph->icon_box->xml_icon = FALSE; + + $this->title = Kohana::lang('common.service-overview', $this->host); + foreach($services as $service){ + if($service['state'] == 'active') + $this->data->buildDataStruct($this->host,$service['name'],$this->view); + } + }else{ + #Landingpage for mobile devices + if($this->isMobileDevice()){ + url::redirect("mobile"); + return; + } + if($this->isAuthorizedFor('host_overview' ) ){ + $this->host = $this->data->getFirstHost(); + if(isset($this->host)){ + url::redirect("graph?host=".$this->host); + }else{ + throw new Kohana_Exception('error.get-first-host'); + } + }else{ + throw new Kohana_Exception('error.not_authorized_for_host_overview'); + } + } + $this->template->graph->logo_box = $this->add_view('logo_box'); + $this->template->graph->header->title = $this->title; + } +} diff --git a/share/pnp/application/controllers/image.php b/share/pnp/application/controllers/image.php new file mode 100644 index 0000000..ddf1725 --- /dev/null +++ b/share/pnp/application/controllers/image.php @@ -0,0 +1,56 @@ +auto_render = FALSE; + + if($this->input->get('w') != "" ) + $this->rrdtool->config->conf['graph_width'] = intval($this->input->get('w')); + if($this->input->get('graph_width') != "" ) + $this->rrdtool->config->conf['graph_width'] = intval($this->input->get('graph_width')); + + if($this->input->get('h') != "" ) + $this->rrdtool->config->conf['graph_height'] = intval($this->input->get('h')); + if($this->input->get('graph_height') != "" ) + $this->rrdtool->config->conf['graph_height'] = intval($this->input->get('graph_height')); + + $this->data->getTimeRange($this->start,$this->end,$this->view); + + if($this->tpl != ""){ + $this->data->buildDataStruct('__special',$this->tpl,$this->view,$this->source); + #print Kohana::debug($this->data->STRUCT); + $image = $this->rrdtool->doImage($this->data->STRUCT[0]['RRD_CALL']); + $this->rrdtool->streamImage($image); + }elseif(isset($this->host) && isset($this->service)){ + $this->data->buildDataStruct($this->host,$this->service,$this->view,$this->source); + if($this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']) === FALSE) + $this->rrdtool->streamImage("ERROR: NOT_AUTHORIZED"); + + #print Kohana::debug($this->data->STRUCT); + if(sizeof($this->data->STRUCT) > 0){ + $image = $this->rrdtool->doImage($this->data->STRUCT[0]['RRD_CALL']); + }else{ + $image = FALSE; + } + $this->rrdtool->streamImage($image); + }else{ + url::redirect("start", 302); + } + } + + +} diff --git a/share/pnp/application/controllers/json.php b/share/pnp/application/controllers/json.php new file mode 100644 index 0000000..306ec93 --- /dev/null +++ b/share/pnp/application/controllers/json.php @@ -0,0 +1,75 @@ +auto_render = FALSE; + // Service Details + if($this->host != "" && $this->service != ""){ + $services = $this->data->getServices($this->host); + $this->data->buildDataStruct($this->host,$this->service,$this->view); + if($this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']) === FALSE){ + print json_encode("not authorized"); + exit; + } + $i = 0; + $json = array(); + foreach($this->data->STRUCT as $struct){ + $json[$i]['image_url'] = "host=".$struct['MACRO']['HOSTNAME']."&srv=".$struct['MACRO']['SERVICEDESC']."&source=".$struct['SOURCE']."&view=".$struct['VIEW']; + $json[$i]['ds_name'] = $struct['ds_name']; + $json[$i]['start'] = $struct['TIMERANGE']['start']; + $json[$i]['end'] = $struct['TIMERANGE']['end']; + $json[$i]['title'] = $struct['TIMERANGE']['title']; + $i++; + } + print json_encode($json); + // Host Overview + }elseif($this->host != ""){ + if($this->auth->is_authorized($this->host) === FALSE){ + print json_encode("not authorized"); + exit; + } + $services = $this->data->getServices($this->host); + foreach($services as $service){ + if($service['state'] == 'active'){ + $this->data->buildDataStruct($this->host,$service['name'],$this->view); + } + } + $i = 0; + $json = array(); + foreach($this->data->STRUCT as $struct){ + $json[$i]['image_url'] = "host=".$struct['MACRO']['HOSTNAME']."&srv=".$struct['MACRO']['SERVICEDESC']."&source=".$struct['SOURCE']."&view=".$struct['VIEW']; + $json[$i]['servicedesc'] = $struct['MACRO']['SERVICEDESC']; + $json[$i]['ds_name'] = $struct['ds_name']; + $json[$i]['start'] = $struct['TIMERANGE']['start']; + $json[$i]['end'] = $struct['TIMERANGE']['end']; + $json[$i]['title'] = $struct['TIMERANGE']['title']; + $i++; + } + print json_encode($json); + }else{ + $this->hosts = $this->data->getHosts(); + $i = 0; + $json = array(); + foreach($this->hosts as $host){ + if($host['state'] == "active"){ + $json[$i]['hostname'] = $host['name']; + $i++; + } + } + print json_encode($json); + } + } +} diff --git a/share/pnp/application/controllers/mobile.php b/share/pnp/application/controllers/mobile.php new file mode 100644 index 0000000..dace76f --- /dev/null +++ b/share/pnp/application/controllers/mobile.php @@ -0,0 +1,93 @@ +session->set('classic-ui',0); + $this->template = $this->add_view('mobile'); + } + + public function index() + { + $this->template->home = $this->add_view('mobile_home'); + } + public function about() + { + $this->template->about = $this->add_view('mobile_about'); + } + public function overview() + { + $this->template->overview = $this->add_view('mobile_overview'); + $this->template->overview->hosts = $this->data->getHosts(); + } + public function host($host=NULL) + { + $this->template->host = $this->add_view('mobile_host'); + $this->is_authorized = $this->auth->is_authorized($host); + $this->template->host->hostname = $host; + $this->template->host->services = $this->data->getServices($host); + } + public function graph($host=NULL, $service=NULL) + { + $this->template->graph = $this->add_view('mobile_graph'); + $this->data->buildDataStruct($host,$service,$this->view); + $this->is_authorized = $this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']); + } + public function search() + { + $this->template->query = $this->add_view('mobile_search'); + $query = pnp::clean($this->input->post('term')); + $result = array(); + if(strlen($query)>=1) { + $hosts = $this->data->getHosts(); + foreach($hosts as $host){ + if(preg_match("/$query/i",$host['name'])){ + array_push($result,$host['name']); + } + } + } + $this->result = $result; + } + public function pages($page=NULL) + { + $this->is_authorized=TRUE; + if($this->view == ""){ + $this->view = $this->config->conf['overview-range']; + } + + $this->page = $page; + if(is_null($this->page) ){ + $this->template->pages = $this->add_view('mobile_pages'); + $this->template->pages->pages = $this->data->getPages(); + return; + } + $this->data->buildPageStruct($this->page,$this->view); + $this->template->pages = $this->add_view('mobile_graph'); + } + public function special($tpl=NULL) + { + $this->tpl = $tpl; + if(is_null($this->tpl) ){ + $this->template->special = $this->add_view('mobile_special'); + $this->template->special->templates = $this->data->getSpecialTemplates(); + return; + } + $this->data->buildDataStruct('__special',$this->tpl,$this->view); + $this->template->special = $this->add_view('mobile_graph_special'); + } + public function go($goto=FALSE) + { + if($goto == 'classic'){ + $this->session->set('classic-ui',1); + url::redirect("graph"); + } + } +} diff --git a/share/pnp/application/controllers/page.php b/share/pnp/application/controllers/page.php new file mode 100644 index 0000000..7bd877e --- /dev/null +++ b/share/pnp/application/controllers/page.php @@ -0,0 +1,80 @@ +template = $this->add_view('template'); + $this->template->page = $this->add_view('page'); + $this->template->zoom_header = $this->add_view('zoom_header'); + $this->template->zoom_header->graph_width = ($this->config->conf['graph_width'] + 140); + $this->template->zoom_header->graph_height = ($this->config->conf['graph_height'] + 230); + $this->template->page->graph_content = $this->add_view('graph_content'); + $this->template->page->graph_content->graph_width = ($this->config->conf['graph_width'] + 85); + $this->template->page->graph_content->timerange_select = $this->add_view('timerange_select'); + $this->template->page->header = $this->add_view('header'); + $this->template->page->search_box = $this->add_view('search_box'); + $this->template->page->logo_box = $this->add_view('logo_box'); + $this->is_authorized=TRUE; + } + + public function index(){ + if( !$this->isAuthorizedFor('pages') ){ + throw new Kohana_Exception('error.auth-pages'); + } + $this->page = pnp::clean($this->input->get('page')); + if($this->page == ""){ + $this->page = $this->data->getFirstPage(); + } + if($this->page == ""){ + throw new Kohana_Exception('error.page-config-dir', $this->config->conf['page_dir']); + } + if($this->view == ""){ + $this->view = $this->config->conf['overview-range']; + } + $this->data->buildPageStruct($this->page,$this->view); + $this->template->page->header->title = Kohana::lang('common.page',$this->data->PAGE_DEF['page_name']); + $this->url = "?page&page=$this->page"; + // Timerange Box Vars + $this->template->page->timerange_box = $this->add_view('timerange_box'); + $this->template->page->timerange_box->timeranges = $this->data->TIMERANGE; + // Pages Box + $this->pages = $this->data->getPages(); + $this->template->page->pages_box = $this->add_view('pages_box'); + $this->template->page->pages_box->pages = $this->pages; + // Basket Box + $this->template->page->basket_box = $this->add_view('basket_box'); + // Icon Box + $this->template->page->icon_box = $this->add_view('icon_box'); + $this->template->page->icon_box->position = "page"; + + } + + public function basket(){ + $basket = $this->session->get("basket"); + if(is_array($basket) && sizeof($basket) > 0){ + $this->data->buildBasketStruct($basket,$this->view); + $this->template->page->basket_box = $this->add_view('basket_box'); + $this->template->page->header->title = Kohana::lang('common.page-basket'); + $this->url = "basket?"; + // Timerange Box Vars + $this->template->page->timerange_box = $this->add_view('timerange_box'); + $this->template->page->timerange_box->timeranges = $this->data->TIMERANGE; + // Pages Box + $this->pages = $this->data->getPages(); + $this->template->page->pages_box = $this->add_view('pages_box'); + $this->template->page->pages_box->pages = $this->pages; + // Icon Box + $this->template->page->icon_box = $this->add_view('icon_box'); + $this->template->page->icon_box->position = "basket"; + }else{ + url::redirect("start", 302); + } + } +} diff --git a/share/pnp/application/controllers/pdf.php b/share/pnp/application/controllers/pdf.php new file mode 100644 index 0000000..15f2ab4 --- /dev/null +++ b/share/pnp/application/controllers/pdf.php @@ -0,0 +1,280 @@ +use_bg = 0; + $this->bg = $this->config->conf['background_pdf']; + $this->pdf_page_size = $this->config->conf['pdf_page_size']; + $this->pdf_margin_left = $this->config->conf['pdf_margin_left']; + $this->pdf_margin_top = $this->config->conf['pdf_margin_top']; + $this->pdf_margin_right = $this->config->conf['pdf_margin_right']; + + // Define PDF background per url option + if(isset($this->bg) && $this->bg != ""){ + if( is_readable( Kohana::config( 'core.pnp_etc_path')."/".$this->bg ) ){ + $this->bg = Kohana::config('core.pnp_etc_path')."/".$this->bg; + }else{ + $this->bg = $this->config->conf['background_pdf']; + } + } + // Use PDF background if readable + if(is_readable($this->bg)){ + $this->use_bg = 1; + } + + } + + public function index(){ + + $this->tpl = pnp::clean($this->input->get('tpl')); + $this->type = "normal"; + + $this->data->getTimeRange($this->start,$this->end,$this->view); + + // Service Details + if($this->host != "" && $this->service != ""){ + $this->data->buildDataStruct($this->host,$this->service,$this->view); + // Host Overview + }elseif($this->host != ""){ + if($this->view == ""){ + $this->view = $this->config->conf['overview-range']; + } + $services = $this->data->getServices($this->host); + foreach($services as $service){ + if($service['state'] == 'active') + $this->data->buildDataStruct($this->host,$service['name'],$this->view); + } + // Special Templates + }elseif($this->tpl != ""){ + $this->data->buildDataStruct('__special',$this->tpl,$this->view); + $this->type = 'special'; + }else{ + $this->host = $this->data->getFirstHost(); + if(isset($this->host)){ + url::redirect("/graph?host=$this->host"); + }else{ + throw new Kohana_User_Exception('Hostname not set ;-)', "RTFM my Friend, RTFM!"); + } + } + #throw new Kohana_Exception(print_r($this->data->STRUCT,TRUE)); + /* + * PDF Output + */ + $pdf = new PDF("P", "mm", $this->pdf_page_size); + $pdf->AliasNbPages(); + $pdf->SetAutoPageBreak('off'); + $pdf->SetMargins($this->pdf_margin_left,$this->pdf_margin_top,$this->pdf_margin_right); + $pdf->AddPage(); + if($this->use_bg){ + $pdf->setSourceFile($this->bg); + $tplIdx = $pdf->importPage(1,'/MediaBox'); + $pdf->useTemplate($tplIdx); + } + $pdf->SetCreator('Created with PNP'); + $pdf->SetFont('Arial', '', 10); + // Title + $header = TRUE; + foreach($this->data->STRUCT as $key=>$data){ + if($key != 0){ + $header = FALSE; + } + if ($pdf->GetY() > 200) { + $pdf->AddPage(); + if($this->use_bg){$pdf->useTemplate($tplIdx);} + } + if($this->type == 'normal'){ + if($data['LEVEL'] == 0){ + $pdf->SetFont('Arial', '', 12); + $pdf->CELL(120, 10, $data['MACRO']['DISP_HOSTNAME']." -- ".$data['MACRO']['DISP_SERVICEDESC'], 0, 1); + $pdf->SetFont('Arial', '', 10); + $pdf->CELL(120, 5, $data['TIMERANGE']['title']." (".$data['TIMERANGE']['f_start']." - ".$data['TIMERANGE']['f_end'].")", 0, 1); + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + }else{ + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + } + }elseif($this->type == 'special'){ + if($header){ + $pdf->SetFont('Arial', '', 12); + $pdf->CELL(120, 10, $data['MACRO']['TITLE'], 0, 1); + $pdf->SetFont('Arial', '', 10); + $pdf->CELL(120, 5, $data['TIMERANGE']['title']." (".$data['TIMERANGE']['f_start']." - ".$data['TIMERANGE']['f_end'].")", 0, 1); + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + }else{ + $pdf->SetFont('Arial', '', 10); + $pdf->CELL(120, 5, $data['TIMERANGE']['title']." (".$data['TIMERANGE']['f_start']." - ".$data['TIMERANGE']['f_end'].")", 0, 1); + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + } + } + $image = $this->rrdtool->doImage($data['RRD_CALL'],$out='PDF'); + $img = $this->rrdtool->saveImage($image); + $Y = $pdf->GetY(); + $cell_height = ($img['height'] * 0.23); + $cell_width = ($img['width'] * 0.23); + $pdf->Image($img['file'], $this->pdf_margin_left, $Y, $cell_width, $cell_height, 'PNG'); + $pdf->CELL(120, $cell_height, '', 0, 1); + unlink($img['file']); + } + $pdf->Output("pnp4nagios.pdf","I"); + + } + + public function page($page){ + $this->start = $this->input->get('start'); + $this->end = $this->input->get('end'); + $this->view = ""; + + if(isset($_GET['view']) && $_GET['view'] != "" ){ + $this->view = pnp::clean($_GET['view']); + } + + $this->data->getTimeRange($this->start,$this->end,$this->view); + $this->data->buildPageStruct($page,$this->view); + // Define PDF background per url option + if(isset($this->data->PAGE_DEF['background_pdf'])){ + if( is_readable( Kohana::config( 'core.pnp_etc_path')."/".$this->data->PAGE_DEF['background_pdf'] ) ){ + $this->bg = Kohana::config('core.pnp_etc_path')."/".$this->data->PAGE_DEF['background_pdf']; + } + } + /* + * PDF Output + */ + $pdf = new PDF("P", "mm", $this->pdf_page_size); + $pdf->AliasNbPages(); + $pdf->SetAutoPageBreak('off'); + $pdf->SetMargins($this->pdf_margin_left,$this->pdf_margin_top,$this->pdf_margin_right); + $pdf->AddPage(); + if($this->use_bg){ + $pdf->setSourceFile($this->bg); + $tplIdx = $pdf->importPage(1,'/MediaBox'); + $pdf->useTemplate($tplIdx); + } + + $pdf->SetCreator('Created with PNP'); + $pdf->SetFont('Arial', '', 10); + // Title + foreach($this->data->STRUCT as $data){ + if ($pdf->GetY() > 200) { + $pdf->AddPage(); + if($this->use_bg){$pdf->useTemplate($tplIdx);} + } + if($data['LEVEL'] == 0){ + $pdf->SetFont('Arial', '', 12); + $pdf->CELL(120, 10, $data['MACRO']['DISP_HOSTNAME']." -- ".$data['MACRO']['DISP_SERVICEDESC'], 0, 1); + $pdf->SetFont('Arial', '', 10); + $pdf->CELL(120, 5, $data['TIMERANGE']['title']." (".$data['TIMERANGE']['f_start']." - ".$data['TIMERANGE']['f_end'].")", 0, 1); + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + }else{ + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + } + $image = $this->rrdtool->doImage($data['RRD_CALL'],$out='PDF'); + $img = $this->rrdtool->saveImage($image); + $Y = $pdf->GetY(); + $cell_height = ($img['height'] * 0.23); + $cell_width = ($img['width'] * 0.23); + $pdf->Image($img['file'], $this->pdf_margin_left, $Y, $cell_width, $cell_height, 'PNG'); + $pdf->CELL(120, $cell_height, '', 0, 1); + unlink($img['file']); + } + $pdf->Output("pnp4nagios.pdf","I"); + } + + public function basket(){ + $this->start = $this->input->get('start'); + $this->end = $this->input->get('end'); + $this->view = ""; + if(isset($_GET['view']) && $_GET['view'] != "" ){ + $this->view = pnp::clean($_GET['view']); + } + $this->data->getTimeRange($this->start,$this->end,$this->view); + $basket = $this->session->get("basket"); + if(is_array($basket) && sizeof($basket) > 0){ + $this->data->buildBasketStruct($basket,$this->view); + } + //echo Kohana::debug($this->data->STRUCT); + /* + * PDF Output + */ + $pdf = new PDF("P", "mm", $this->pdf_page_size); + $pdf->AliasNbPages(); + $pdf->SetAutoPageBreak('off'); + $pdf->SetMargins($this->pdf_margin_left,$this->pdf_margin_top,$this->pdf_margin_right); + $pdf->AddPage(); + if($this->use_bg){ + $pdf->setSourceFile($this->config->conf['background_pdf']); + $tplIdx = $pdf->importPage(1,'/MediaBox'); + $pdf->useTemplate($tplIdx); + } + + $pdf->SetCreator('Created with PNP'); + $pdf->SetFont('Arial', '', 10); + // Title + foreach($this->data->STRUCT as $data){ + if ($pdf->GetY() > 200) { + $pdf->AddPage(); + if($this->use_bg){$pdf->useTemplate($tplIdx);} + } + if($data['LEVEL'] == 0){ + $pdf->SetFont('Arial', '', 12); + $pdf->CELL(120, 10, $data['MACRO']['DISP_HOSTNAME']." -- ".$data['MACRO']['DISP_SERVICEDESC'], 0, 1); + $pdf->SetFont('Arial', '', 10); + $pdf->CELL(120, 5, $data['TIMERANGE']['title']." (".$data['TIMERANGE']['f_start']." - ".$data['TIMERANGE']['f_end'].")", 0, 1); + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + }else{ + $pdf->SetFont('Arial', '', 8); + $pdf->CELL(120, 5, "Datasource ".$data["ds_name"], 0, 1); + } + $image = $this->rrdtool->doImage($data['RRD_CALL'],$out='PDF'); + $img = $this->rrdtool->saveImage($image); + $Y = $pdf->GetY(); + $cell_height = ($img['height'] * 0.23); + $cell_width = ($img['width'] * 0.23); + $pdf->Image($img['file'], $this->pdf_margin_left, $Y, $cell_width, $cell_height, 'PNG'); + $pdf->CELL(120, $cell_height, '', 0, 1); + unlink($img['file']); + } + $pdf->Output("pnp4nagios.pdf","I"); + + } +} + + +/* ++ +* +*/ +require Kohana::find_file('vendor/fpdf', 'fpdf'); +require Kohana::find_file('vendor/fpdf', 'fpdi'); +class PDF extends FPDI { + //Page header + function Header() { + //Arial bold 10 + $this->SetFont('Arial', 'B', 10); + } + + //Page footer + function Footer() { + //Position at 1.5 cm from bottom + $this->SetY(-20); + //Arial italic 8 + $this->SetFont('Arial', 'I', 8); + //Page number + $this->Cell(0, 10, $this->PageNo() . '/{nb}', 0, 0, 'C'); + } +} + diff --git a/share/pnp/application/controllers/popup.php b/share/pnp/application/controllers/popup.php new file mode 100644 index 0000000..162ca73 --- /dev/null +++ b/share/pnp/application/controllers/popup.php @@ -0,0 +1,41 @@ +template = $this->add_view('popup'); + } + + public function index() + { + if ( $this->view == "" ){ + $this->view = $this->config->conf['overview-range']; + } + + $this->imgwidth = pnp::clean($this->input->get('width',$this->config->conf['popup-width'])); + + $this->data->getTimeRange($this->start,$this->end,$this->view); + + if(isset($this->host) && isset($this->service)){ + $this->data->buildDataStruct($this->host,$this->service,$this->view,$this->source); + $this->template->host = $this->host; + $this->template->srv = $this->service; + $this->template->view = $this->view; + $this->template->source = $this->source; + $this->template->end = $this->end; + $this->template->start = $this->start; + $this->template->imgwidth = $this->imgwidth; + }else{ + url::redirect("/graph"); + } + } +} diff --git a/share/pnp/application/controllers/special.php b/share/pnp/application/controllers/special.php new file mode 100644 index 0000000..bc98518 --- /dev/null +++ b/share/pnp/application/controllers/special.php @@ -0,0 +1,52 @@ +template = $this->add_view('template'); + $this->template->graph = $this->add_view('graph'); + $this->templates = $this->data->getSpecialTemplates(); + $this->data->GRAPH_TYPE = 'special'; + if($this->tpl == ''){ + if($this->templates) + $this->tpl = $this->templates[0]; + url::redirect('special?tpl='.$this->tpl, 302); + } + } + + public function index(){ + $this->url = "?tpl=".$this->tpl; + $this->template->zoom_header = $this->add_view('zoom_header'); + $this->template->zoom_header->graph_width = ($this->config->conf['graph_width'] + 140); + $this->template->zoom_header->graph_height = ($this->config->conf['graph_height'] + 230); + $this->template->graph->graph_content = $this->add_view('graph_content_special'); + $this->template->graph->graph_content->graph_width = ($this->config->conf['graph_width'] + 85); + $this->template->graph->graph_content->timerange_select = $this->add_view('timerange_select'); + $this->template->graph->header = $this->add_view('header'); + $this->template->graph->search_box = $this->add_view('search_box'); + $this->template->graph->service_box = $this->add_view('special_templates_box'); + #$this->template->graph->status_box = $this->add_view('status_box'); + #$this->template->graph->basket_box = $this->add_view('basket_box'); + $this->template->graph->widget_menu = $this->add_view('widget_menu'); + $this->template->graph->graph_content->widget_graph = $this->add_view('widget_graph'); + #print Kohana::debug($services); + $this->data->buildDataStruct('__special',$this->tpl,$this->view); + $this->template->graph->icon_box = $this->add_view('icon_box'); + $this->template->graph->icon_box->position = "special"; + $this->template->graph->logo_box = $this->add_view('logo_box'); + // Timerange Box Vars + $this->template->graph->timerange_box = $this->add_view('timerange_box'); + $this->template->graph->timerange_box->timeranges = $this->data->TIMERANGE; + $this->template->graph->header->title = $this->data->MACRO['TITLE']; + //print Kohana::debug($this->data); + } + +} diff --git a/share/pnp/application/controllers/start.php b/share/pnp/application/controllers/start.php new file mode 100644 index 0000000..b575655 --- /dev/null +++ b/share/pnp/application/controllers/start.php @@ -0,0 +1,21 @@ +data = new Data_Model(); + $this->config = new Config_Model(); + $this->rrdtool = new Rrdtool_Model(); + $this->auth = new Auth_Model(); + #$this->system = new System_Model(); + + $this->config->read_config(); + Kohana::config_set('locale.language',$this->config->conf['lang']); + // Check for mod_rewrite + $this->check_mod_rewrite(); + + $this->start = pnp::clean($this->input->get('start',FALSE)); + $this->end = pnp::clean($this->input->get('end',FALSE)); + $this->theme = pnp::clean($this->input->get('theme',FALSE)); + $this->view = pnp::clean($this->input->get('view', "")); + $this->host = pnp::clean($this->input->get('host',NULL)); + $this->service = pnp::clean($this->input->get('srv',NULL)); + $this->source = pnp::clean($this->input->get('source',0)); + $this->version = pnp::clean($this->input->get('version',NULL)); + $this->tpl = pnp::clean($this->input->get('tpl')); + $this->controller = Router::$controller; + + $this->data->getTimeRange($this->start,$this->end,$this->view); + if(Router::$controller != "image" && Router::$controller != "image_special"){ + $this->session = Session::instance(); + + # Session withou theme info + if($this->session->get("theme","new") == "new"){ + if($this->theme){ + # store $this->theme if available + Kohana::config_set('core.theme',$this->theme); + $this->session->set('theme', $this->theme ); + }else{ + # set $this->theme to default value + $this->theme = $this->config->conf['ui-theme']; + Kohana::config_set('core.theme',$this->theme); + } + # Sesion with theme info + }else{ + if($this->theme && $this->theme != 'default'){ + # store $this->theme if available + $this->session->set('theme', $this->theme ); + Kohana::config_set('core.theme',$this->theme); + }elseif($this->theme == 'default'){ + # reset to default theme + $this->theme = $this->config->conf['ui-theme']; + $this->session->set('theme', $this->theme ); + Kohana::config_set('core.theme',$this->theme); + }else{ + # set $this->theme with session infos + $this->theme = $this->session->get('theme'); + Kohana::config_set('core.theme',$this->theme); + } + } + + if($this->start && $this->end ){ + if($this->session->get('timerange-reset',0) == 0){ + $this->session->set("start", $this->start); + $this->session->set("end", $this->end); + }else{ + $this->session->set('timerange-reset', 0); + } + } + if($this->start && !$this->end){ + if($this->session->get('timerange-reset',0) == 0){ + $this->session->set("start", $this->start); + $this->session->set("end", ""); + }else{ + $this->session->set('timerange-reset', 0); + } + } + if($this->end && !$this->start){ + if($this->session->get('timerange-reset',0) == 0){ + $this->session->set("end", $this->end); + $this->session->set("start", ""); + }else{ + $this->session->set('timerange-reset', 0); + } + } + } + } + + public function __call($method, $arguments) + { + // Disable auto-rendering + $this->auto_render = FALSE; + + // By defining a __call method, all pages routed to this controller + // that result in 404 errors will be handled by this method, instead of + // being displayed as "Page Not Found" errors. + echo $this->_("The requested page doesn't exist") . " ($method)"; + } + + /** + * Handle paths to current theme etc + * + */ + public function add_view($view=false) + { + $view = trim($view); + if (empty($view)) { + return false; + } + if (!file_exists(APPPATH."/views/".$view.".php")) { + return false; + } + #return new View($this->theme_path.$view); + return new View($view); + } + + public function check_mod_rewrite(){ + if(!function_exists('apache_get_modules')){ + // Add index.php to every URL while not running withn apache mod_php + Kohana::config_set('core.index_page','index.php'); + return TRUE; + } + if(!in_array('mod_rewrite', apache_get_modules())){ + // Add index.php to every URL while mod_rewrite is not available + Kohana::config_set('core.index_page','index.php'); + } + if ( $this->config->conf['use_url_rewriting'] == 0 ){ + Kohana::config_set('core.index_page','index.php'); + } + } + + public function isAuthorizedFor($auth) { + $conf = $this->config->conf; + if ($auth == "service_links") { + + $users = explode(",", $conf['allowed_for_service_links']); + if (in_array('EVERYONE', $users)) { + return 1; + } + elseif (in_array('NONE', $users)) { + return 0; + } + elseif (in_array($this->auth->REMOTE_USER, $users)) { + return 1; + } else { + return 0; + } + } + if ($auth == "host_search") { + $users = explode(",", $conf['allowed_for_host_search']); + if (in_array('EVERYONE', $users)) { + return 1; + } + elseif (in_array('NONE', $users)) { + return 0; + } + elseif (in_array($this->auth->REMOTE_USER, $users)) { + return 1; + } else { + return 0; + } + } + if ($auth == "host_overview") { + $users = explode(",", $conf['allowed_for_host_overview']); + if (in_array('EVERYONE', $users)) { + return 1; + } + elseif (in_array('NONE', $users)) { + return 0; + } + elseif (in_array($this->auth->REMOTE_USER, $users)) { + return 1; + } else { + return 0; + } + } + if ($auth == "pages") { + $users = explode(",", $conf['allowed_for_pages']); + if (in_array('EVERYONE', $users)) { + return 1; + } + elseif (in_array('NONE', $users)) { + return 0; + } + elseif (in_array($this->auth->REMOTE_USER, $users)) { + return 1; + } else { + return 0; + } + } + } + public function isMobileDevice (){ + if( $this->session->get('classic-ui',0) == 1){ + return FALSE; + } + if ( preg_match('/'.$this->config->conf['mobile_devices'].'/', $_SERVER['HTTP_USER_AGENT'] ) ){ + return TRUE; + }else{ + return FALSE; + } + } +} diff --git a/share/pnp/application/controllers/xml.php b/share/pnp/application/controllers/xml.php new file mode 100644 index 0000000..3931a72 --- /dev/null +++ b/share/pnp/application/controllers/xml.php @@ -0,0 +1,48 @@ +config->read_config(); + } + + public function index() + { + $this->auto_render = FALSE; + if($this->service == "" && $this->host == ""){ + url::redirect("graph", 302); + } + $this->data->readXML($this->host, $this->service); + if($this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']) === FALSE){ + header('Content-Type: application/xml'); + print "\n"; + print "\n"; + print "not authorized\n"; + print "\n"; + exit; + }else{ + $xmlfile = $this->config->conf['rrdbase'].$this->host."/".$this->service.".xml"; + if(is_readable($xmlfile)){ + $fh = fopen($xmlfile, 'r'); + header('Content-Type: application/xml'); + fpassthru($fh); + fclose($fh); + exit; + }else{ + header('Content-Type: application/xml'); + print "\n"; + print "\n"; + print "file not found\n"; + print "\n"; + } + } + } +} diff --git a/share/pnp/application/controllers/xport.php b/share/pnp/application/controllers/xport.php new file mode 100644 index 0000000..fa26fad --- /dev/null +++ b/share/pnp/application/controllers/xport.php @@ -0,0 +1,74 @@ +auto_render = FALSE; + $this->data->getTimeRange($this->start,$this->end,$this->view); + + } + + public function xml(){ + if(isset($this->host) && isset($this->service)){ + $this->data->buildXport($this->host,$this->service); + if($this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']) === FALSE){ + header('Content-Type: application/xml'); + print "\n"; + print "\n"; + print "not authorized\n"; + print "\n"; + exit; + } + $data = $this->rrdtool->doXport($this->data->XPORT); + header('Content-Type: application/xml'); + print $data; + }else{ + throw new Kohana_Exception('error.xport-host-service'); + } + } + + public function json(){ + if(isset($this->host) && isset($this->service)){ + $this->data->buildXport($this->host,$this->service); + if($this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']) === FALSE){ + header('Content-type: application/json'); + print json_encode("not authorized"); + exit; + } + $data = $this->rrdtool->doXport($this->data->XPORT); + $json = json_encode(simplexml_load_string($data)); + header('Content-type: application/json'); + print $json; + }else{ + throw new Kohana_Exception('error.xport-host-service'); + } + } + + public function csv(){ + if(isset($this->host) && isset($this->service)){ + $this->data->buildXport($this->host,$this->service); + if($this->auth->is_authorized($this->data->MACRO['AUTH_HOSTNAME'], $this->data->MACRO['AUTH_SERVICEDESC']) === FALSE){ + header("Content-Type: text/plain; charset=UTF-8"); + print "not authorized"; + exit; + } + $data = $this->rrdtool->doXport($this->data->XPORT); + $csv = $this->data->xml2csv($data); + header("Content-Type: text/plain; charset=UTF-8"); + print $csv; + }else{ + throw new Kohana_Exception('error.xport-host-service'); + } + } + + +} diff --git a/share/pnp/application/controllers/zoom.php b/share/pnp/application/controllers/zoom.php new file mode 100644 index 0000000..7355738 --- /dev/null +++ b/share/pnp/application/controllers/zoom.php @@ -0,0 +1,80 @@ +template = $this->add_view('zoom'); + #$this->tpl = $this->input->get('tpl'); + $this->graph_width = $this->config->conf['zgraph_width']; + $this->graph_height = $this->config->conf['zgraph_height']; + } + + public function index() + { + #$this->source = intval($this->input->get('source')); + #$this->view = ""; + + #if(isset($_GET['view']) && $_GET['view'] != "" ){ + # $this->view = pnp::clean($_GET['view']); + #}else{ + # $this->view = $this->config->conf['overview-range']; + #} + + # + # Limit startto 2000/01/01 + # + $start_limit = strtotime("2000/01/01"); + $this->start = abs((int)$this->start); + if($this->start < $start_limit) + $this->start = $start_limit; + # + # Limit end to now + one hour + # + $end_limit = time() + 3600; + $this->end = abs((int)$this->end); + if($this->end > $end_limit) + $this->end = $end_limit; + + $this->data->getTimeRange($this->start,$this->end,$this->view); + + if(isset($this->tpl) && $this->tpl != 'undefined' ){ + if($this->start && $this->end ){ + $this->session->set("start", $this->start); + $this->session->set("end", $this->end); + } + $this->template->tpl = $this->tpl; + $this->template->view = $this->view; + $this->template->source = $this->source; + $this->template->end = $this->end; + $this->template->start = $this->start; + $this->url = "?tpl=".$this->tpl; + $this->template->graph_height = $this->graph_height; + $this->template->graph_width = $this->graph_width; + }elseif(isset($this->host) && isset($this->service)){ + if($this->start && $this->end ){ + $this->session->set("start", $this->start); + $this->session->set("end", $this->end); + } + $this->template->host = $this->host; + $this->template->srv = $this->service; + $this->template->view = $this->view; + $this->template->source = $this->source; + $this->template->end = $this->end; + $this->template->start = $this->start; + $this->url = "?host=".$this->host."&srv=".$this->service; + $this->template->graph_height = $this->graph_height; + $this->template->graph_width = $this->graph_width; + }else{ + url::redirect("/graph"); + } + } +} diff --git a/share/pnp/application/helpers/nagios.php b/share/pnp/application/helpers/nagios.php new file mode 100644 index 0000000..e1f70a9 --- /dev/null +++ b/share/pnp/application/helpers/nagios.php @@ -0,0 +1,58 @@ +read_config(); + + $smon = date('m' , $start); + $sday = date('d' , $start); + $syear = date('Y' , $start); + $shour = date('G' , $start); + $smin = date('i' , $start); + $ssec = date('s' , $start); + $emon = date('m' , $end); + $eday = date('d' , $end); + $eyear = date('Y' , $end); + $ehour = date('G' , $end); + $emin = date('i' , $end); + $esec = date('s' , $end); + $nagios_base = $config->conf['nagios_base']; + print "\n"; + } + + public static function AvailLink($hostname,$servicedesc,$start,$end){ + $config = new Config_Model(); + $config->read_config(); + $hostname = urlencode($hostname); + $servicedesc = urlencode($servicedesc); + $smon = date('m' , $start); + $sday = date('d' , $start); + $syear = date('Y' , $start); + $shour = date('G' , $start); + $smin = date('i' , $start); + $ssec = date('s' , $start); + $emon = date('m' , $end); + $eday = date('d' , $end); + $eyear = date('Y' , $end); + $ehour = date('G' , $end); + $emin = date('i' , $end); + $esec = date('s' , $end); + $nagios_base = $config->conf['nagios_base']; + if($servicedesc == "Host+Perfdata"){ + print "\n"; +} + + + +} diff --git a/share/pnp/application/helpers/pnp.php b/share/pnp/application/helpers/pnp.php new file mode 100644 index 0000000..7134a55 --- /dev/null +++ b/share/pnp/application/helpers/pnp.php @@ -0,0 +1,150 @@ + $length){ + $string = substr($string, 0, $length) . "..."; + } + return $string; + } + /* + * + */ + public static function xml_version_check($string = FALSE){ + if($string === FALSE){ + return FALSE; + } + if( $string == XML_STRUCTURE_VERSION ){ + $string = "valid"; + }else{ + $string = Kohana::lang('error.xml-structure-mismatch', $string, XML_STRUCTURE_VERSION); + } + return $string; + } + /* + * + */ + public static function zoom_icon($host,$service,$start,$end,$source,$view,$graph_width,$graph_height){ + print "\n"; + } + + /* + * + */ + public static function zoom_icon_special($tpl,$start,$end,$source,$view,$graph_width,$graph_height){ + print "\n"; + } + + /* + * + */ + public static function add_to_basket_icon($host,$service,$source=FALSE){ + if($source === FALSE){ + print "\n"; + }else{ + print "\n"; + } + } + + /* + * + */ + public static function multisite_link($base_url=FALSE,$site=FALSE,$host=FALSE,$service=FALSE){ + if($host && $service){ + $link = sprintf("'%s/view.py?view_name=service&site=%s&host=%s&service=%s'", $base_url,$site,urlencode($host),urlencode($service)); + return $link; + } + if($host){ + $link = sprintf("'%s/view.py?view_name=host&site=%s&host=%s'", $base_url,$site,urlencode($host)); + return $link; + } + } + + public static function addToUri($fields = array(),$base = True){ + if(!is_array($fields)){ + return false; + } + $get = $_GET; + if($base === True){ + $uri = url::base(TRUE); + $uri .= Router::$current_uri; + }else{ + $uri = ""; + } + $uri .= '?'; + foreach($fields as $key=>$value){ + $get[$key] = $value; + } + foreach($get as $key=>$value){ + if($value === ''){ + continue; + } + $uri .= $key."=".urlencode($value)."&"; + } + return rtrim($uri,"&"); + } + + /* "normalize" and adjust value / unit (similar to format string %s in RRDtool) + * Parameters in: + * value := number, maybe suffixed by unit string + * examples: 1234, 1.234, 1234M, 1234Kb + * base := base of value (1000, e.g. traffic or 1024, e.g. disk size) + * format := format string + * Parameters out: + * val_unit := formatted value (including unit) + * val_fmt := formatted value (without leading blanks and unit) + * unit := adjusted unit + * divisor := number used to "normalize" value + */ + public static function adjust_unit($value,$base=1000,$format='%.3lf'){ + preg_match('/^(-?[0-9\.,]+)\s*(\S?)(\S?)/',$value,$matches); + + $mag = 0; + while ($value >= $base){ + $value /= $base; + $mag++; + } + $pos = 0; + if ($matches[2] == "%") { + $unit = '%'; + } else { + if ($matches[2] == "") { + $matches[2] = " "; + } + if (($matches[2] == "B") or ($matches[2] == "b")) { + $matches[3] = $matches[2]; + $matches[2] = " "; + } + $pos = strpos(' KMGTP',strtoupper($matches[2])); + $unit = substr(' KMGTP',$mag+$pos,1).$matches[3]; + } + $val_unit = sprintf ("$format %s", $value, $unit); + $val_fmt = sprintf ($format, $value); + $val_fmt = str_replace(' ','',$val_fmt); + return array ($val_unit,$val_fmt,$unit,pow($base,$mag)); + } + + public static function print_version(){ + return PNP_NAME . "-" . PNP_VERSION . " [ " . PNP_REL_DATE . " ]"; + } + +} diff --git a/share/pnp/application/helpers/rrd.php b/share/pnp/application/helpers/rrd.php new file mode 100644 index 0000000..2da22f4 --- /dev/null +++ b/share/pnp/application/helpers/rrd.php @@ -0,0 +1,459 @@ += 1 ){ + $color .= "$ri"; + } else { + $color .= "00"; + } + if ( ($z & 2) >= 1 ){ + $color .= "$ri"; + } else { + $color .= "00"; + } + if ( ($z & 1) >= 1 ){ + $color .= "$ri"; + } else { + $color .= "00"; + } + $icolor = rrd::color_inverse($color); + $pos = array_search($color,$colors); + $ipos = array_search($icolor,$colors); + if ( $pos == false ) { + $colors[] = $color . $alpha; + } + if ( $ipos == false ) { + $colors[] = $icolor . $alpha; + } + } + } + if (array_key_exists($num, $colors)) { + return $colors[$num]; + } else { + return $colors[0]; + } + } + + /* + * Gradient Function + * Concept by Stefan Triep + */ + public static function gradient($vname=FALSE, $start_color='#0000a0', $end_color='#f0f0f0', $label=FALSE, $steps=20, $lower=FALSE){ + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if(preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i',$start_color,$matches)){ + $r1=hexdec($matches[1]); + $g1=hexdec($matches[2]); + $b1=hexdec($matches[3]); + }else{ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Wrong Color Format: '".$start_color."'"); + } + + if(preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i',$end_color,$matches)){ + $r2=hexdec($matches[1]); + $g2=hexdec($matches[2]); + $b2=hexdec($matches[3]); + }else{ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Wrong Color Format: '".$end_color."'"); + } + + $diff_r=$r2-$r1; + $diff_g=$g2-$g1; + $diff_b=$b2-$b1; + $spline = ""; + $spline_vname = "var".substr(sha1(rand()),1,4); + if(preg_match('/^([0-9]{1,3})%$/', $lower, $matches)){ + if($matches[1] > 100) + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Lower gradient start > 100% is not allowed: '".$lower."'"); + + $lower = $matches[1]; + $spline .= sprintf("CDEF:%sminimum=%s,100,/,%d,* ", $vname, $vname, $lower); + }elseif(preg_match('/^([0-9]+)$/', $lower, $matches)){ + $lower = $matches[1]; + $spline .= sprintf("CDEF:%sminimum=%s,%d,- ", $vname, $vname, $lower); + }else{ + $lower = 0; + $spline .= sprintf("CDEF:%sminimum=%s,%s,- ", $vname, $vname, $vname); + } + # debug + # $spline .= sprintf("GPRINT:%sminimum:MAX:\"minumum %%lf\\n\" ",$vname); + for ($i=$steps; $i>0; $i--){ + $spline .= sprintf("CDEF:%s%d=%s,%sminimum,-,%d,/,%d,*,%sminimum,+ ",$spline_vname,$i,$vname,$vname,$steps,$i,$vname ); + # debug + # $spline .= sprintf("GPRINT:%s%d:MAX:\"%22d %%lf\\n\" ",$spline_vname,$i,$i); + } + for ($i=$steps; $i>0; $i--){ + $factor=$i / $steps; + $r=round($r1 + $diff_r * $factor); + $g=round($g1 + $diff_g * $factor); + $b=round($b1 + $diff_b * $factor); + if (($i==$steps) and ($label!=FALSE)){ + $spline .= sprintf("AREA:%s%d#%02X%02X%02X:\"%s\" ", $spline_vname,$i,$r,$g,$b,$label); + }else{ + $spline .= sprintf("AREA:%s%d#%02X%02X%02X ", $spline_vname,$i,$r,$g,$b); + } + } + return $spline; + } + + + public static function cut($string, $length=18, $align='left'){ + if(strlen($string) > $length){ + $string = substr($string,0,($length-3))."..."; + } + if($align == 'left'){ + $format = "%-".$length."s"; + }else{ + $format = "%".$length."s"; + } + $s = sprintf($format,$string); + return $s; + } + + public static function area($vname=FALSE, $color=FALSE, $text=FALSE, $stack=FALSE){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + }else{ + $line .= "AREA:".$vname; + } + if($color === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'color' is missing"); + }else{ + $line .= $color; + } + $line .= ":\"$text\""; + if($stack != FALSE){ + $line .= ":STACK"; + } + $line .= " "; + return $line; + } + + public static function line($type=1,$vname=FALSE, $color=FALSE, $text=FALSE, $stack=FALSE){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + }else{ + $line .= "LINE".$type.":".$vname; + } + if($color === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'color' is missing"); + }else{ + $line .= $color; + } + $line .= ":\"$text\""; + if($stack != FALSE){ + $line .= ":STACK"; + } + $line .= " "; + return $line; + } + + public static function line1($vname=FALSE, $color=FALSE, $text=FALSE, $stack=FALSE){ + return rrd::line(1,$vname, $color,$text, $stack); + } + + public static function line2($vname=FALSE, $color=FALSE, $text=FALSE, $stack=FALSE){ + return rrd::line(2,$vname, $color,$text, $stack); + } + + public static function line3($vname=FALSE, $color=FALSE, $text=FALSE, $stack=FALSE){ + return rrd::line(3,$vname, $color,$text, $stack); + } + + public static function gprint($vname=FALSE, $cf="AVERAGE", $text="%6.2lf %s"){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + + if(is_array($cf)){ + foreach($cf as $key => $val){ + $line .= sprintf("GPRINT:%s:%s:",$vname,$val); + if($key == sizeof($cf)-1){ + $line .= '"'.$text.' '.ucfirst(strtolower($val)).'\\l" '; + }else{ + $line .= '"'.$text.' '.ucfirst(strtolower($val)).'" '; + } + } + }else{ + $line .= sprintf("GPRINT:%s:%s:",$vname,$cf); + $line .= '"'.$text.'" '; + } + return $line; + } + + /* + * Function to modify alignment of gprint + */ + public static function gprinta($vname=FALSE, $cf="AVERAGE", $text="%6.2lf %s", $align=""){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($align != ""){ + $align = '\\' . $align; + } + if(is_array($cf)){ + foreach($cf as $key => $val){ + $line .= sprintf("GPRINT:%s:%s:",$vname,$val); + if(($key == sizeof($cf)-1)and($align != "")){ + $line .= '"'.$text.' '.ucfirst(strtolower($val)).$align.'" '; + }else{ + $line .= '"'.$text.' '.ucfirst(strtolower($val)).'" '; + } + } + }else{ + $line .= sprintf("GPRINT:%s:%s:",$vname,$cf); + $line .= '"'.$text.'" '; + } + return $line; + } + + public static function def($vname=FALSE, $rrdfile=FALSE, $ds=FALSE, $cf="AVERAGE"){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($rrdfile === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'rrdfile' is missing"); + } + if($rrdfile === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Third Parameter 'ds' is missing"); + } + $line = sprintf("DEF:%s=%s:%s:%s ",$vname,$rrdfile,$ds,$cf); + return $line; + } + + public static function cdef($vname=FALSE, $rpn=FALSE){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($rpn === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'rpn' is missing"); + } + $line = sprintf("CDEF:%s=%s ",$vname,$rpn); + return $line; + } + + public static function vdef($vname=FALSE, $rpn=FALSE){ + $line = ""; + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($rpn === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'rpn' is missing"); + } + $line = sprintf("VDEF:%s=%s ",$vname,$rpn); + return $line; + } + + public static function hrule($value=FALSE, $color=FALSE, $text=FALSE){ + $line = ""; + if($value === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ ."() First Parameter 'value' is missing"); + } + if($color === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'color' is missing"); + } + if($value == "~" ) { + return ""; + } + $line = sprintf("HRULE:%s%s:\"%s\" ",$value,$color,$text); + return $line; + } + + public static function comment($text=FALSE){ + $line = sprintf("COMMENT:\"%s\" ", $text); + return $line; + } + + public static function tick($vname=FALSE, $color=FALSE, $fraction=FALSE, $label=FALSE){ + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'value' is missing"); + } + if($color === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'color' is missing"); + } + $line = sprintf("TICK:%s%s",$vname,$color); + if($fraction != FALSE) + $line .= ":$fraction"; + + if($label != FALSE) + $line .= ":$label"; + + $line .= " "; + return $line; + } + + + public static function alerter($vname=FALSE, $label=FALSE, $warning=FALSE, $critical=FALSE, $opacity = 'ff', $unit, $color_green = '#00ff00', $color_btw = '#ffff00', $color_red = '#ff0000', $line_col = '#0000ff') { + + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($label === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'label' is missing"); + } + if($warning === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Third Parameter 'warning' is missing"); + } + if($critical === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Fourth Parameter 'critical' is missing"); + } + $line = ""; + $green_vname = "var".substr(sha1(rand()),1,4); + $btw_vname = "var".substr(sha1(rand()),1,4); + $blue_vname = "var".substr(sha1(rand()),1,4); + $red_vname = "var".substr(sha1(rand()),1,4); + if($warning < $critical){ + $line .= "CDEF:".$green_vname."=".$vname.",".$warning.",LT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$btw_vname."=".$vname.",".$critical.",LT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$blue_vname."=".$btw_vname.",".$warning.",GE,".$btw_vname.",UNKN,IF "; + $line .= "CDEF:".$red_vname."=".$vname.",".$critical.",GE,".$vname.",UNKN,IF "; + } else { + $line .= "CDEF:".$green_vname."=".$vname.",".$warning.",GT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$btw_vname."=".$vname.",".$critical.",GE,".$vname.",UNKN,IF "; + $line .= "CDEF:".$blue_vname."=".$btw_vname.",".$warning.",LE,".$btw_vname.",UNKN,IF "; + $line .= "CDEF:".$red_vname."=".$vname.",".$critical.",LT,".$vname.",UNKN,IF "; + } + $line .= rrd::area($green_vname, $color_green.$opacity); + $line .= rrd::area($blue_vname, $color_btw.$opacity); + $line .= rrd::area($red_vname, $color_red.$opacity); + $line .= rrd::line1($vname,$line_col,$label); + + return $line; + } + + public static function alerter_gr($vname=FALSE,$label=FALSE,$warning=FALSE,$critical=FALSE,$opacity='ff',$unit,$color_green='#00ff00',$color_btw='#ffff00',$color_red='#ff0000',$line_col='#0000ff',$start_color="#ffffff") { + + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($label === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'label' is missing"); + } + if($warning === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Third Parameter 'warning' is missing"); + } + if($critical === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Fourth Parameter 'critical' is missing"); + } + $line = ""; + $green_vname = "var".substr(sha1(rand()),1,4); + $btw_vname = "var".substr(sha1(rand()),1,4); + $blue_vname = "var".substr(sha1(rand()),1,4); + $red_vname = "var".substr(sha1(rand()),1,4); + $line = ""; + if($warning < $critical){ + $line .= "CDEF:".$green_vname."=".$vname.",".$warning.",LT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$btw_vname."=".$vname.",".$critical.",LT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$blue_vname."=".$btw_vname.",".$warning.",GE,".$btw_vname.",UNKN,IF "; + $line .= "CDEF:".$red_vname."=".$vname.",".$critical.",GE,".$vname.",UNKN,IF "; + } else { + $line .= "CDEF:".$green_vname."=".$vname.",".$warning.",GT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$btw_vname."=".$vname.",".$critical.",GE,".$vname.",UNKN,IF "; + $line .= "CDEF:".$blue_vname."=".$btw_vname.",".$warning.",LE,".$btw_vname.",UNKN,IF "; + $line .= "CDEF:".$red_vname."=".$vname.",".$critical.",LT,".$vname.",UNKN,IF "; + } + $line .= rrd::gradient($green_vname, $start_color, $color_green.$opacity); + $line .= rrd::gradient($blue_vname, $start_color, $color_btw.$opacity); + $line .= rrd::gradient($red_vname, $start_color, $color_red.$opacity); + $line .= rrd::line1($vname,$line_col,$label); + return $line; + } + + public static function ticker($vname=FALSE, $warning=FALSE, $critical=FALSE, $fraction = -0.05, $opacity = 'ff', $color_green = '#00ff00', $color_btw = '#ffff00', $color_red = '#ff0000') { + + if($vname === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() First Parameter 'vname' is missing"); + } + if($warning === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Second Parameter 'warning' is missing"); + } + if($critical === FALSE){ + throw new Kohana_exception("rrd::". __FUNCTION__ . "() Third Parameter 'critical' is missing"); + } + $line = ""; + $green_vname = "var".substr(sha1(rand()),1,4); + $btw_vname = "var".substr(sha1(rand()),1,4); + $blue_vname = "var".substr(sha1(rand()),1,4); + $red_vname = "var".substr(sha1(rand()),1,4); + $green2_vname = "var".substr(sha1(rand()),1,4); + $line .= "CDEF:".$green_vname."=".$vname.",".$warning.",LT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$btw_vname."=".$vname.",".$critical.",LT,".$vname.",UNKN,IF "; + $line .= "CDEF:".$blue_vname."=".$btw_vname.",".$warning.",GE,".$btw_vname.",UNKN,IF "; + $line .= "CDEF:".$red_vname."=".$vname.",".$critical.",GE,".$vname.",UNKN,IF "; + $line .= "CDEF:".$green2_vname."=".$green_vname.",0,EQ,0.000001,".$green_vname.",IF "; + $line .= rrd::tick($green2_vname, $color_green.$opacity, $fraction); + $line .= rrd::tick($blue_vname, $color_btw.$opacity, $fraction); + $line .= rrd::tick($red_vname, $color_red.$opacity, $fraction); + + return $line; + } + + public static function darkteint(){ + $line = ''; + $line .= '--color=BACK#000000 '; + $line .= '--color=FONT#F7F7F7 '; + $line .= '--color=SHADEA#ffffff '; + $line .= '--color=SHADEB#ffffff '; + $line .= '--color=CANVAS#000000 '; + $line .= '--color=GRID#00991A '; + $line .= '--color=MGRID#00991A '; + $line .= '--color=ARROW#00FF00 '; + + return $line; + } + + public static function debug($data=FALSE){ + if($data != FALSE){ + ob_start(); + + var_dump($data); + $var_dump = ob_get_contents(); + $var_dump = preg_replace('/(HRULE|VDEF|DEF|CDEF|GPRINT|LINE|AREA|COMMENT)/',"\n\${1}", $var_dump); + ob_end_clean(); + throw new Kohana_exception("
    ".$var_dump."
    "); + } + } + +} diff --git a/share/pnp/application/i18n/de_DE/common.php b/share/pnp/application/i18n/de_DE/common.php new file mode 100644 index 0000000..bd7657c --- /dev/null +++ b/share/pnp/application/i18n/de_DE/common.php @@ -0,0 +1,59 @@ + 'Host: %s', + 'service' => 'Service: %s', + 'page' => 'Page: %s', + 'page-basket' => 'Page: Basket', + 'datasource' => 'Datasource: %s', + 'zoom-header' => 'Zoom', + 'status-box-header' => 'Status', + 'multisite-box-header' => 'Multisite Links', + 'search-box-header' => 'Suche', + 'icon-box-header' => 'Aktionen', + 'basket-box-header' => 'Mein Korb', + 'timerange-box-header' => 'Zeitbereiche', + 'service-box-header' => 'Services', + 'special-templates-box-header' => 'Special Templates', + 'pages-box-header' => 'Pages', + 'nagios-summary-link-title' => 'aktuellste Alarme für diesen Zeitbereich', + 'nagios-avail-link-title' => 'Nagios-Verügbarkeitsbericht für diesen Zeitbereich', + 'timerange-selector-legend' => 'Auswahl eines Zeitbereichs', + 'timerange-selector-title' => 'Auswahl eines Zeitbereichs', + 'timerange-selector-submit-button' => 'absenden', + 'timerange-selector-clear-button' => 'löschen', + 'timerange-selector-link' => 'Spezieller Zeitbereich', + 'timerange-selector-overview' => 'Übersicht', + 'start' => 'Start', + 'end' => 'Ende', + 'service-details' => 'Service-Details', + 'service-overview' => 'Service-Übersicht für "%s"', + 'title-pages-link' => 'Pages anzeigen', + 'title-pdf-link' => 'PDF anzeigen', + 'title-xml-link' => 'XML anzeigen', + 'title-statistics-link' => 'Interne PNP Statistiken', + 'title-calendar-link' => 'Einen Zeitbereich definieren', + 'title-special-templates-link' => 'Spezial Templates anzeigen', + 'title-docs-link' => 'Dokumentation', + 'title-home-link' => 'Zu den Graphen', + 'title-color-link' => 'View Color Schemes', + 'docs-home' => 'Home', + 'docs-box-header' => 'Menu', + 'docs-header' => 'Dokumentation Version %s', + 'back' => 'zurück', + 'mobile-all-hosts' => 'Alle Hosts', + 'mobile-search-hosts' => 'Hosts suchen', + 'mobile-pages' => 'Pages anzeigen', + 'mobile-special-templates' => 'Special Templates anzeigen', + 'mobile-statistics' => 'Interne PNP Statistiken', + 'mobile-go-classic' => 'Classic UI', + 'mobile-submit' => 'absenden', + 'basket-empty' => 'Basket ist leer', + 'basket-show' => 'Zeige Basket', + 'basket-clear' => 'Leere Basket', + 'basket-remove' => 'Entferne %s', + 'basket-add-item' => 'Graphen zum Basket hinzufügen', + 'basket-add-service' => 'Alle Graphen zum Basket hinzufügen', + 'color-box-header' => 'Colors', + 'color-header' => 'Colors Schemes', +); diff --git a/share/pnp/application/i18n/de_DE/error.php b/share/pnp/application/i18n/de_DE/error.php new file mode 100644 index 0000000..5814b7b --- /dev/null +++ b/share/pnp/application/i18n/de_DE/error.php @@ -0,0 +1,32 @@ + '"rrdtool"-Binary nicht in %s gefunden. FAQ online lesen', + 'config-not-found' => 'Config-Datei %s nicht gefunden. FAQ online lesen', + 'perfdata-dir-empty' => 'Das perfdata-Verzeichnis "%s" ist leer. Bitte die Nagios-Konfiguration prüfen. FAQ online lesen', + 'host-perfdata-dir-empty' => 'Das perfdata-Verzeichnis "%s" ist leer. Bitte die Nagios-Konfiguration prüfen. FAQ online lesen', + 'perfdata-dir-for-host' => 'Das perfdata-Verzeichnis "%s" für Host "%s" existiert nicht. FAQ online lesen', + 'xml-not-found' => 'XML-Datei "%s" nicht gefunden. FAQ online lesen', + 'get-first-service' => 'Konnte ersten Service für Host "%s" nicht finden. FAQ online lesen', + 'get-first-host' => 'Keinen Host gefunden. FAQ online lesen', + 'xml-structure-mismatch' => 'Version der XML-Struktur ungültig. Fand Version "%d", sollte aber "%d" sein. FAQ online lesen', + 'save-rrd-image' => 'Speichern des Graphen gescheitert. php fopen("%s") failed. FAQ online lesen', + 'xml-structure-without-version-tag' => 'Versionshinweis fehlt im XML-File. FAQ online lesen', + 'template-without-opt' => 'Template %s übergibt Array $opt[] nicht. FAQ online lesen', + 'template-without-def' => 'Template %s übergibt Array $def[] nicht. FAQ online lesen', + 'no-data-for-page' => 'Keine Daten für die Page "%s", FAQ online lesen', + 'page-not-readable' => 'Konfigurationsdatei "%s" ist nicht lesbar oder existiert nicht. FAQ online lesen', + 'auth-pages' => 'Sie sind nicht berechtigt, "Pages" anzusehen FAQ online lesen', + 'page-config-dir' => 'Keine page-Konfigurationsdatei in "%s" gefunden FAQ online lesen', + 'xport-host-service' => 'Xport-Controller benötigt "host"- und "srv"-URL-Parameter. FAQ online lesen', + 'mod-rewrite' => 'Apache Rewrite Module ist nicht aktiviert. Read FAQ online', + 'tpl-no-services-found' => 'Es wurden keine Services gefunden "%s". Read FAQ online', + 'tpl-no-hosts-found' => 'Es wurden keine Hosts gefunden "%s". Read FAQ online', + 'no-templates-found' => 'Es wurde kein passendes Template gefunden. Read FAQ online', + 'not_authorized' => 'You are not authorized to view this host/service', + 'remote_user_missing' => 'Remote user is missing. Authentication check cancled. Read FAQ online', + 'livestatus_socket_error' => 'Livestatus Socket error: %s (%s) Read FAQ online', + 'not_authorized_for_host_overview' => 'You are not authorized to access this host overview page.', + 'xml-generic_error' => 'XML file "%s" not parsable.

    XML Errors:%s

    ', + 'gd-missing' => 'PHP GD functions are missing. More on www.php.net', +); diff --git a/share/pnp/application/i18n/en_US/common.php b/share/pnp/application/i18n/en_US/common.php new file mode 100644 index 0000000..6c67c09 --- /dev/null +++ b/share/pnp/application/i18n/en_US/common.php @@ -0,0 +1,59 @@ + 'Datasource: %s', + 'host' => 'Host: %s', + 'service' => 'Service: %s', + 'page' => 'Page: %s', + 'page-basket' => 'Page: Basket', + 'zoom-header' => 'Zoom', + 'status-box-header' => 'Status', + 'multisite-box-header' => 'Multisite links', + 'search-box-header' => 'Search', + 'icon-box-header' => 'Actions', + 'basket-box-header' => 'My basket', + 'timerange-box-header' => 'Time ranges', + 'service-box-header' => 'Services', + 'special-templates-box-header' => 'Special Templates', + 'pages-box-header' => 'Pages', + 'nagios-summary-link-title' => 'Most recent alerts for this time range', + 'nagios-avail-link-title' => 'Nagios availability report for this time range', + 'timerange-selector-legend' => 'Select a custom time range', + 'timerange-selector-title' => 'Select a custom time range', + 'timerange-selector-submit-button' => 'Submit', + 'timerange-selector-clear-button' => 'Clear', + 'timerange-selector-link' => 'Custom time range', + 'timerange-selector-overview' => 'Overview', + 'start' => 'Start', + 'end' => 'End', + 'service-details' => 'Service details', + 'service-overview' => 'Service overview for "%s"', + 'title-pages-link' => 'View Pages', + 'title-pdf-link' => 'View PDF', + 'title-xml-link' => 'View XML', + 'title-statistics-link' => 'View internal statistics', + 'title-calendar-link' => 'Define a custom time range', + 'title-special-templates-link' => 'View Special Templates', + 'title-docs-link' => 'View Documentation', + 'title-home-link' => 'View Graphs', + 'title-color-link' => 'View Color Schemes', + 'docs-home' => 'Home', + 'docs-box-header' => 'Menu', + 'docs-header' => 'Documentation Version %s', + 'back' => 'back', + 'mobile-all-hosts' => 'All Hosts', + 'mobile-search-hosts' => 'Search Hosts', + 'mobile-pages' => 'View Pages', + 'mobile-special-templates' => 'View Special Templates', + 'mobile-statistics' => 'View internal statistics', + 'mobile-go-classic' => 'Classic UI', + 'mobile-submit' => 'Submit', + 'basket-empty' => 'Basket is empty', + 'basket-show' => 'Show basket', + 'basket-clear' => 'Clear basket', + 'basket-remove' => 'Remove %s', + 'basket-add-item' => 'Add this item to my basket', + 'basket-add-service' => 'Add this service to my basket', + 'color-box-header' => 'Colors', + 'color-header' => 'Colors Schemes', +); diff --git a/share/pnp/application/i18n/en_US/error.php b/share/pnp/application/i18n/en_US/error.php new file mode 100644 index 0000000..8d5d395 --- /dev/null +++ b/share/pnp/application/i18n/en_US/error.php @@ -0,0 +1,32 @@ + 'RRDTool not found in %s. Read FAQ online', + 'config-not-found' => 'Config file %s not found. Read FAQ online', + 'perfdata-dir-empty' => 'perfdata directory "%s" is empty. Please check your Nagios config. Read FAQ online', + 'host-perfdata-dir-empty' => 'perfdata directory "%s" is empty. Please check your Nagios config. Read FAQ online', + 'perfdata-dir-for-host' => 'perfdata directory "%s" for host "%s" does not exist. Read FAQ online', + 'xml-not-found' => 'XML file "%s" not found. Read FAQ online', + 'get-first-service' => 'Can´t find first service for host "%s". Read FAQ online', + 'get-first-host' => 'Can´t find any Host. Read FAQ online', + 'xml-structure-mismatch' => 'XML structure mismatch. Found version "%d" but should be "%d". Read FAQ online', + 'save-rrd-image' => 'php fopen("%s") failed. Read FAQ online', + 'xml-structure-without-version-tag' => 'XML structure mismatch. Version tag not found in "%s". Read FAQ online', + 'template-without-opt' => 'Template %s does not provide array $opt[]. Read FAQ online', + 'template-without-def' => 'Template %s does not provide array $def[]. Read FAQ online', + 'no-data-for-page' => 'Sorry, but we can´t find any data using config file "%s", Read FAQ online', + 'page-not-readable' => 'Config file "%s" is not readable or does not exist. Read FAQ online', + 'auth-pages' => 'You are not authorized to view "pages" Read FAQ online', + 'page-config-dir' => 'No page config file found in "%s" Read FAQ online', + 'xport-host-service' => 'Xport controller needs "host" and "srv" URL parameters. Read FAQ online', + 'mod-rewrite' => 'Apache Rewrite Module is not enabled. Read FAQ online', + 'tpl-no-services-found' => 'No services could be found "%s". Read FAQ online', + 'tpl-no-hosts-found' => 'No hosts could be found "%s". Read FAQ online', + 'no-templates-found' => 'No templates could be found. Read FAQ online', + 'not_authorized' => 'You are not authorized to view this host/service', + 'remote_user_missing' => 'Remote user is missing. Authentication check cancled. Read FAQ online', + 'livestatus_socket_error' => 'Livestatus Socket error: %s (%s) Read FAQ online', + 'not_authorized_for_host_overview' => 'You are not authorized to access this host overview page.', + 'xml-generic_error' => 'XML file "%s" not parsable.

    XML Errors:%s

    ', + 'gd-missing' => 'PHP GD functions are missing. More on www.php.net', +); diff --git a/share/pnp/application/i18n/es_ES/common.php b/share/pnp/application/i18n/es_ES/common.php new file mode 100644 index 0000000..0c9cc0b --- /dev/null +++ b/share/pnp/application/i18n/es_ES/common.php @@ -0,0 +1,58 @@ + 'Fuente de Datos: %s', + 'host' => 'Equipo: %s', + 'service' => 'Servicio: %s', + 'page' => 'Page: %s', + 'page-basket' => 'Página: Cesta', + 'zoom-header' => 'Zoom', + 'status-box-header' => 'Estado', + 'multisite-box-header' => 'Multisite links', + 'search-box-header' => 'Buscar', + 'icon-box-header' => 'Acciones', + 'basket-box-header' => 'Mi Cesta', + 'timerange-box-header' => 'Intervalos de Tiempo', + 'service-box-header' => 'Servicios', + 'pages-box-header' => 'Páginas', + 'nagios-summary-link-title' => 'Alertas Recientes en el Intervalo de Tiempo', + 'nagios-avail-link-title' => 'Informe de Disponibilidad en el Intervalo de Tiempo', + 'timerange-selector-legend' => 'Seleccione un intervalo de tiempo personalizado', + 'timerange-selector-title' => 'Seleccione un intervalo de tiempo personalizado', + 'timerange-selector-submit-button' => 'enviar', + 'timerange-selector-clear-button' => 'limpiar', + 'timerange-selector-link' => 'Intervalo de tiempo personalizado', + 'timerange-selector-overview' => 'Overview', + 'start' => 'Comienzo', + 'end' => 'Fin', + 'service-details' => 'Detalles de Servicio', + 'service-overview' => 'Vista General de Servicio para "%s"', + 'title-pages-link' => 'Ver páginas', + 'title-pdf-link' => 'Ver PDF', + 'title-xml-link' => 'Ver XML', + 'title-statistics-link' => 'Ver estadísticas internas de PNP', + 'title-calendar-link' => 'Definir un intervalo de tiempo personalizado', + 'title-special-templates-link' => 'View Special Templates', + 'title-docs-link' => 'View Documentation', + 'title-home-link' => 'View Graphs', + 'title-color-link' => 'View Color Schemes', + 'docs-home' => 'Home', + 'docs-box-header' => 'Menu', + 'docs-header' => 'Documentation Version %s', + 'back' => 'back', + 'mobile-all-hosts' => 'All Hosts', + 'mobile-search-hosts' => 'Search Hosts', + 'mobile-pages' => 'View Pages', + 'mobile-special-templates' => 'View Special Templates', + 'mobile-statistics' => 'View internal statistics', + 'mobile-go-classic' => 'Classic UI', + 'mobile-submit' => 'Submit', + 'basket-empty' => 'Basket is empty', + 'basket-show' => 'Show basket', + 'basket-clear' => 'Clear basket', + 'basket-remove' => 'Remove %s', + 'basket-add-item' => 'Add this item to my basket', + 'basket-add-service' => 'Add this service to my basket', + 'color-box-header' => 'Colors', + 'color-header' => 'Colors Schemes', +); diff --git a/share/pnp/application/i18n/es_ES/error.php b/share/pnp/application/i18n/es_ES/error.php new file mode 100644 index 0000000..5a638b1 --- /dev/null +++ b/share/pnp/application/i18n/es_ES/error.php @@ -0,0 +1,32 @@ + 'RRDTool no se encuentra en %s. Leer FAQ en línea', + 'config-not-found' => 'El fichero de configuración %s no se ha encontrado. Leer FAQ en línea', + 'perfdata-dir-empty' => 'El directorio de Perfdata "%s" está vacío. Compruebe la configuración de Nagios. Leer FAQ en línea', + 'host-perfdata-dir-empty' => 'El directorio de Perfdata "%s" está vacío. Compruebe la configuración de Nagios. Leer FAQ en línea', + 'perfdata-dir-for-host' => 'El directorio Perfdata "%s" para el Equipo "%s" no existe. Leer FAQ en línea', + 'xml-not-found' => 'Fichero XML "%s" no encontrado. Leer FAQ en línea', + 'get-first-service' => 'No puedo encontrar el primer servicio para el equipo "%s". Leer FAQ en línea', + 'get-first-host' => 'No puedo encuentrar ningún Equipo. Leer FAQ en línea', + 'xml-structure-mismatch' => 'Error en la Estructura XML. Versión Encontrada "%d" pero debería ser "%d". Read FAQ online', + 'save-rrd-image' => 'fallo en php fopen("%s"). Leer FAQ en línea', + 'xml-structure-without-version-tag' => 'Error en la estructura XML. Etiqueta de Versión no encontrada. Leer FAQ en línea', + 'template-without-opt' => 'La plantilla %s no tiene el array $opt[]. Leer FAQ en línea', + 'template-without-def' => 'La plantilla %s no tiene el array $def[]. Leer FAQ en línea', + 'no-data-for-page' => 'Lo siento, no puedo encontrar ningún dato usando el fichero de configuración "%s", Leer FAQ en línea', + 'page-not-readable' => 'El fichero de configuración "%s" no es legible o no existe. Leer FAQ en línea', + 'auth-pages' => 'No está autorizado a ver "páginas" Leer FAQ en línea', + 'page-config-dir' => 'No hay fichero de configuración de página en "%s" Leer FAQ en línea', + 'xport-host-service' => 'El controlador Xport necesita los parámetros de URL "host" y "srv". Leer FAQ en línea', + 'mod-rewrite' => 'El módulo Apache Rewrite no está habilitado. Leer FAQ en línea', + 'tpl-no-services-found' => 'No services could be found "%s". Read FAQ online', + 'tpl-no-hosts-found' => 'No hosts could be found "%s". Read FAQ online', + 'no-templates-found' => 'No templates could be found. Read FAQ online', + 'not_authorized' => 'You are not authorized to view this host/service', + 'remote_user_missing' => 'Remote user is missing. Authentication check cancled. Read FAQ online', + 'livestatus_socket_error' => 'Livestatus Socket error: %s (%s) Read FAQ online', + 'not_authorized_for_host_overview' => 'You are not authorized to access this host overview page.', + 'xml-generic_error' => 'XML file "%s" not parsable.

    XML Errors:%s

    ', + 'gd-missing' => 'PHP GD functions are missing. More on www.php.net', +); diff --git a/share/pnp/application/i18n/fr_FR/common.php b/share/pnp/application/i18n/fr_FR/common.php new file mode 100644 index 0000000..3d9b933 --- /dev/null +++ b/share/pnp/application/i18n/fr_FR/common.php @@ -0,0 +1,59 @@ + 'Source de données : %s', + 'host' => 'Machine : %s', + 'service' => 'Service : %s', + 'page' => 'Page : %s', + 'page-basket' => 'Page : Panier', + 'zoom-header' => 'Zoom', + 'status-box-header' => 'État', + 'multisite-box-header' => 'Liens multisite', + 'search-box-header' => 'Recherche', + 'icon-box-header' => 'Actions', + 'basket-box-header' => 'Mon panier', + 'timerange-box-header' => 'Plage de temps', + 'service-box-header' => 'Services', + 'special-templates-box-header' => 'Patrons spécifiques', + 'pages-box-header' => 'Pages', + 'nagios-summary-link-title' => 'Alarmes les plus récentes dans cette plage de temps', + 'nagios-avail-link-title' => 'Disponibilité de Nagios pendant cette plage de temps', + 'timerange-selector-legend' => 'Selectionner une plage de temps', + 'timerange-selector-title' => 'Selectionner une plage de temps', + 'timerange-selector-submit-button' => 'démarrer', + 'timerange-selector-clear-button' => 'effacer', + 'timerange-selector-link' => 'Plage de temps personnalisée', + 'timerange-selector-overview' => 'Overview', + 'start' => 'Début', + 'end' => 'Fin', + 'service-details' => 'Détails du service', + 'service-overview' => 'Aperçu du service sur "%s"', + 'title-pages-link' => 'Voir la page', + 'title-pdf-link' => 'Extraction PDF', + 'title-xml-link' => 'Extraction XML', + 'title-statistics-link' => 'Voir statistiques internes sur PNP', + 'title-calendar-link' => 'Définir une plage de temps', + 'title-special-templates-link' => 'Voir les patrons', + 'title-docs-link' => 'Accèder à la documentation', + 'title-home-link' => 'Accèder aux graphiques', + 'title-color-link' => 'View Color Schemes', + 'docs-home' => 'Accueil', + 'docs-box-header' => 'Menu', + 'docs-header' => 'Version de la documentation %s', + 'back' => 'back', + 'mobile-all-hosts' => 'All Hosts', + 'mobile-search-hosts' => 'Search Hosts', + 'mobile-pages' => 'View Pages', + 'mobile-special-templates' => 'View Special Templates', + 'mobile-statistics' => 'View internal statistics', + 'mobile-go-classic' => 'Classic UI', + 'mobile-submit' => 'Submit', + 'basket-empty' => 'Basket is empty', + 'basket-show' => 'Show basket', + 'basket-clear' => 'Clear basket', + 'basket-remove' => 'Remove %s', + 'basket-add-item' => 'Add this item to my basket', + 'basket-add-service' => 'Add this service to my basket', + 'color-box-header' => 'Colors', + 'color-header' => 'Colors Schemes', +); diff --git a/share/pnp/application/i18n/fr_FR/error.php b/share/pnp/application/i18n/fr_FR/error.php new file mode 100644 index 0000000..2ea5229 --- /dev/null +++ b/share/pnp/application/i18n/fr_FR/error.php @@ -0,0 +1,32 @@ + 'RRDTool non trouvé dans %s. Lire la FAQ', + 'config-not-found' => 'Fichier de config %s non trouvé. Lire la FAQ', + 'perfdata-dir-empty' => 'Répertoire perfdata "%s" vide. Merci de vérifier la configuration de Nagios. Lire la FAQ', + 'host-perfdata-dir-empty' => 'Répertoire perfdata "%s" vide. Merci de vérifier la configuration de Nagios. Lire la FAQ', + 'perfdata-dir-for-host' => 'Répertoire perfdata "%s" du serveur "%s" n\'existe pas. Lire la FAQ', + 'xml-not-found' => 'Fichier XML "%s" non trouvé. Lire la FAQ', + 'get-first-service' => 'Impossible de trouver le premier service du serveur "%s". Lire la FAQ', + 'get-first-host' => 'Impossible de trouver un serveur. Lire la FAQ', + 'xml-structure-mismatch' => 'Structure XML incorrecte. Version trouvé "%d" mais version attendu "%d". Lire la FAQ', + 'save-rrd-image' => 'Échec de la fonction php fopen("%s"). Lire la FAQ', + 'xml-structure-without-version-tag' => 'Structure XML incorrect. Balise de version introuvable dans "%s". Lire la FAQ', + 'template-without-opt' => 'Le template %s ne renvoie pas de tableau $opt[]. Lire la FAQ', + 'template-without-def' => 'Le template %s ne renvoie pas de tableau $def[]. Lire la FAQ', + 'no-data-for-page' => 'Désolé, mais impossible de trouver des données en utilisant le fichier de configuration "%s", Lire la FAQ', + 'page-not-readable' => 'Impossible de lire le fichier de configuration "%s" ou fichier introuvable. Lire la FAQ', + 'auth-pages' => 'Vous n\'êtes pas autorisé de voir "pages" Lire la FAQ', + 'page-config-dir' => 'Pas de fichier de configuration pour page dans "%s" Lire la FAQ', + 'xport-host-service' => 'Le contrôleur Xport nécessite les paramètres "host" et "srv" en paramètres d\'URL. Lire la FAQ', + 'mod-rewrite' => 'Module Apache Rewrite désactivé. Lire la FAQ', + 'tpl-no-services-found' => 'Impossible de trouver des services "%s". Read FAQ online', + 'tpl-no-hosts-found' => 'Impossible de trouver des serveurs "%s". Read FAQ online', + 'no-templates-found' => 'Impossible de trouver des modèles. Read FAQ online', + 'not_authorized' => 'You are not authorized to view this host/service', + 'remote_user_missing' => 'Remote user is missing. Authentication check cancled. Read FAQ online', + 'livestatus_socket_error' => 'Livestatus Socket error: %s (%s) Read FAQ online', + 'not_authorized_for_host_overview' => 'You are not authorized to access this host overview page.', + 'xml-generic_error' => 'XML file "%s" not parsable.

    XML Errors:%s

    ', + 'gd-missing' => 'PHP GD functions are missing. More on www.php.net', +); diff --git a/share/pnp/application/i18n/ru_RU/common.php b/share/pnp/application/i18n/ru_RU/common.php new file mode 100644 index 0000000..b49834c --- /dev/null +++ b/share/pnp/application/i18n/ru_RU/common.php @@ -0,0 +1,59 @@ + 'Источник данных: %s', + 'host' => 'Хост: %s', + 'service' => 'Служба: %s', + 'page' => 'Страница: %s', + 'page-basket' => 'Страница: Мой набор', + 'zoom-header' => 'Детализация', + 'status-box-header' => 'Статус', + 'multisite-box-header' => 'Multisite links', + 'search-box-header' => 'Поиск', + 'icon-box-header' => 'Действия', + 'basket-box-header' => 'Мой набор', + 'timerange-box-header' => 'Интервалы времени', + 'service-box-header' => 'Службы', + 'special-templates-box-header' => 'Специальные шаблоны', + 'pages-box-header' => 'Страницы', + 'nagios-summary-link-title' => 'Последние алерты за данный промежуток', + 'nagios-avail-link-title' => 'Сводка доступности за данный промежуток', + 'timerange-selector-legend' => 'Выберите промежуток', + 'timerange-selector-title' => 'Установка собственного интервала времени', + 'timerange-selector-submit-button' => 'ввести', + 'timerange-selector-clear-button' => 'очистить', + 'timerange-selector-link' => 'Собственный интервал', + 'timerange-selector-overview' => 'Overview', + 'start' => 'Начало', + 'end' => 'Окончание', + 'service-details' => 'Подробности о службе', + 'service-overview' => 'Обзор служб для "%s"', + 'title-pages-link' => 'Обзор страниц', + 'title-pdf-link' => 'Просмотр PDF', + 'title-xml-link' => 'Просмотр XML', + 'title-statistics-link' => 'Просмотр внутренней статистики PNP', + 'title-calendar-link' => 'Установка собственного временного интервала', + 'title-special-templates-link' => 'Просмотр специальных шаблонов', + 'title-docs-link' => 'Просмотреть документацию', + 'title-home-link' => 'Просмотр графиков', + 'title-color-link' => 'View Color Schemes', + 'docs-home' => 'На главную', + 'docs-box-header' => 'Меню', + 'docs-header' => 'Версия документации %s', + 'back' => 'назад', + 'mobile-all-hosts' => 'Все хосты', + 'mobile-search-hosts' => 'Поиск хостов', + 'mobile-pages' => 'Просмотр страниц', + 'mobile-special-templates' => 'Просмотр специальных шаблонов', + 'mobile-statistics' => 'Просмотр внутренней статистики', + 'mobile-go-classic' => 'Классический UI', + 'mobile-submit' => 'Ввести', + 'basket-empty' => 'Корзина пуста', + 'basket-show' => 'Показать корзину', + 'basket-clear' => 'Clear basket', + 'basket-remove' => 'Убрать %s', + 'basket-add-item' => 'Добавить этот элемент в мою корзину', + 'basket-add-service' => 'Добавить эту службу в мою корзину', + 'color-box-header' => 'Colors', + 'color-header' => 'Colors Schemes', +); diff --git a/share/pnp/application/i18n/ru_RU/error.php b/share/pnp/application/i18n/ru_RU/error.php new file mode 100644 index 0000000..989c8d6 --- /dev/null +++ b/share/pnp/application/i18n/ru_RU/error.php @@ -0,0 +1,32 @@ + 'RRDTool не обнаружено в %s. Read FAQ online', + 'config-not-found' => 'Файл конфигурации %s не найден. Read FAQ online', + 'perfdata-dir-empty' => 'Директория с данными производительности "%s" пуста. Пожалуйста, проверьте конфигурацию Nagios. Read FAQ online', + 'host-perfdata-dir-empty' => 'Директория с данными производительности "%s" пуста. Пожалуйста, проверьте конфигурацию Nagios. Read FAQ online', + 'perfdata-dir-for-host' => 'Директория с данными производительности "%s" для хоста "%s" не существует. Read FAQ online', + 'xml-not-found' => 'XML файл "%s" не найден. Read FAQ online', + 'get-first-service' => 'Невозможно определить первую службу для хоста "%s". Read FAQ online', + 'get-first-host' => 'Ни по одному хосту данных не обнаружено. Read FAQ online', + 'xml-structure-mismatch' => 'Несоответствие структуры данных XML. Обнаружена версия "%d", ожидаемая версия - "%d". Read FAQ online', + 'save-rrd-image' => 'Функция php fopen("%s") завершилась неудачей. Read FAQ online', + 'xml-structure-without-version-tag' => 'Несоответствие структуры данных XML. Тэг версии не найден в "%s". Read FAQ online', + 'template-without-opt' => 'Шаблон %s не предоставляет массив $opt[]. Read FAQ online', + 'template-without-def' => 'Шаблон %s не предоставляет массив $def[]. Read FAQ online', + 'no-data-for-page' => 'Извините, не удалось обнаружить никаких данных используя конфигурационный файл "%s", Read FAQ online', + 'page-not-readable' => 'Конфигурационный файл "%s" не может быть прочитан или не существует. Read FAQ online', + 'auth-pages' => 'Вы не авторизованы для просмотра "страниц" Read FAQ online', + 'page-config-dir' => 'Файл конфигурации "страниц" не найден в "%s" Read FAQ online', + 'xport-host-service' => 'Контроллер Xport требует параметры "host" и "srv" в URL. Read FAQ online', + 'mod-rewrite' => 'Модуль Rewrite для Apache не включен. Read FAQ online', + 'tpl-no-services-found' => 'Службы "%s" не найдены. Read FAQ online', + 'tpl-no-hosts-found' => 'Хосты "%s" не найдены. Read FAQ online', + 'no-templates-found' => 'Шаблоны "%s" не найдены. Read FAQ online', + 'not_authorized' => 'Вы не авторизованы для просмотра данного хоста/службы', + 'remote_user_missing' => 'Удалённый пользователь не указан. Проверка аутентификации отменена. Read FAQ online', + 'livestatus_socket_error' => 'Ошибка Livestatus сокета: %s (%s) Read FAQ online', + 'not_authorized_for_host_overview' => 'Вы не авторизованы для доступа к странице обзора хоста.', + 'xml-generic_error' => 'Не удаётся распарсить XML файл "%s".

    Ошибки XML:%s

    ', + 'gd-missing' => 'PHP GD functions are missing. More on www.php.net', +); diff --git a/share/pnp/application/lib/json.php b/share/pnp/application/lib/json.php new file mode 100644 index 0000000..0cddbdd --- /dev/null +++ b/share/pnp/application/lib/json.php @@ -0,0 +1,806 @@ + + * @author Matt Knapp + * @author Brett Stimmerman + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_SLICE', 1); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_STR', 2); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_ARR', 3); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_OBJ', 4); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_CMT', 5); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_LOOSE_TYPE', 16); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_SUPPRESS_ERRORS', 32); + +/** + * Converts to and from JSON format. + * + * Brief example of use: + * + * + * // create a new instance of Services_JSON + * $json = new Services_JSON(); + * + * // convert a complexe value to JSON notation, and send it to the browser + * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); + * $output = $json->encode($value); + * + * print($output); + * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] + * + * // accept incoming POST data, assumed to be in JSON notation + * $input = file_get_contents('php://input', 1000000); + * $value = $json->decode($input); + * + */ +class Services_JSON +{ + /** + * constructs a new JSON instance + * + * @param int $use object behavior flags; combine with boolean-OR + * + * possible values: + * - SERVICES_JSON_LOOSE_TYPE: loose typing. + * "{...}" syntax creates associative arrays + * instead of objects in decode(). + * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. + * Values which can't be encoded (e.g. resources) + * appear as NULL instead of throwing errors. + * By default, a deeply-nested resource will + * bubble up with an error, so all return values + * from encode() should be checked with isError() + */ + function Services_JSON($use = 0) + { + $this->use = $use; + } + + /** + * convert a string from one UTF-16 char to one UTF-8 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf16 UTF-16 character + * @return string UTF-8 character + * @access private + */ + function utf162utf8($utf16) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); + } + + $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); + + switch(true) { + case ((0x7F & $bytes) == $bytes): + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x7F & $bytes); + + case (0x07FF & $bytes) == $bytes: + // return a 2-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xC0 | (($bytes >> 6) & 0x1F)) + . chr(0x80 | ($bytes & 0x3F)); + + case (0xFFFF & $bytes) == $bytes: + // return a 3-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xE0 | (($bytes >> 12) & 0x0F)) + . chr(0x80 | (($bytes >> 6) & 0x3F)) + . chr(0x80 | ($bytes & 0x3F)); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + function utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + function encode($var) + { + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + $properties = array_map(array($this, 'name_value'), + array_keys($var), + array_values($var)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + // treat it like a regular array + $elements = array_map(array($this, 'encode'), $var); + + foreach($elements as $element) { + if(Services_JSON::isError($element)) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = get_object_vars($var); + + $properties = array_map(array($this, 'name_value'), + array_keys($vars), + array_values($vars)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) + ? 'null' + : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + function name_value($name, $value) + { + $encoded_value = $this->encode($value); + + if(Services_JSON::isError($encoded_value)) { + return $encoded_value; + } + + return $this->encode(strval($name)) . ':' . $encoded_value; + } + + /** + * reduce a string by removing leading and trailing comments and whitespace + * + * @param $str string string value to strip of comments and whitespace + * + * @return string string value stripped of comments and whitespace + * @access private + */ + function reduce_string($str) + { + $str = preg_replace(array( + + // eliminate single line comments in '// ...' form + '#^\s*//(.+)$#m', + + // eliminate multi-line comments in '/* ... */' form, at start of string + '#^\s*/\*(.+)\*/#Us', + + // eliminate multi-line comments in '/* ... */' form, at end of string + '#/\*(.+)\*/\s*$#Us' + + ), '', $str); + + // eliminate extraneous space + return trim($str); + } + + /** + * decodes a JSON string into appropriate variable + * + * @param string $str JSON-formatted string + * + * @return mixed number, boolean, string, array, or object + * corresponding to given JSON input string. + * See argument 1 to Services_JSON() above for object-output behavior. + * Note that decode() always returns strings + * in ASCII or UTF-8 format! + * @access public + */ + function decode($str) + { + $str = $this->reduce_string($str); + + switch (strtolower($str)) { + case 'true': + return true; + + case 'false': + return false; + + case 'null': + return null; + + default: + $m = array(); + + if (is_numeric($str)) { + // Lookie-loo, it's a number + + // This would work on its own, but I'm trying to be + // good about returning integers where appropriate: + // return (float)$str; + + // Return float or int, as appropriate + return ((float)$str == (integer)$str) + ? (integer)$str + : (float)$str; + + } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { + // STRINGS RETURNED IN UTF-8 FORMAT + $delim = substr($str, 0, 1); + $chrs = substr($str, 1, -1); + $utf8 = ''; + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c < $strlen_chrs; ++$c) { + + $substr_chrs_c_2 = substr($chrs, $c, 2); + $ord_chrs_c = ord($chrs{$c}); + + switch (true) { + case $substr_chrs_c_2 == '\b': + $utf8 .= chr(0x08); + ++$c; + break; + case $substr_chrs_c_2 == '\t': + $utf8 .= chr(0x09); + ++$c; + break; + case $substr_chrs_c_2 == '\n': + $utf8 .= chr(0x0A); + ++$c; + break; + case $substr_chrs_c_2 == '\f': + $utf8 .= chr(0x0C); + ++$c; + break; + case $substr_chrs_c_2 == '\r': + $utf8 .= chr(0x0D); + ++$c; + break; + + case $substr_chrs_c_2 == '\\"': + case $substr_chrs_c_2 == '\\\'': + case $substr_chrs_c_2 == '\\\\': + case $substr_chrs_c_2 == '\\/': + if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || + ($delim == "'" && $substr_chrs_c_2 != '\\"')) { + $utf8 .= $chrs{++$c}; + } + break; + + case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): + // single, escaped unicode character + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) + . chr(hexdec(substr($chrs, ($c + 4), 2))); + $utf8 .= $this->utf162utf8($utf16); + $c += 5; + break; + + case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): + $utf8 .= $chrs{$c}; + break; + + case ($ord_chrs_c & 0xE0) == 0xC0: + // characters U-00000080 - U-000007FF, mask 110XXXXX + //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 2); + ++$c; + break; + + case ($ord_chrs_c & 0xF0) == 0xE0: + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 3); + $c += 2; + break; + + case ($ord_chrs_c & 0xF8) == 0xF0: + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 4); + $c += 3; + break; + + case ($ord_chrs_c & 0xFC) == 0xF8: + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 5); + $c += 4; + break; + + case ($ord_chrs_c & 0xFE) == 0xFC: + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 6); + $c += 5; + break; + + } + + } + + return $utf8; + + } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { + // array, or object notation + + if ($str{0} == '[') { + $stk = array(SERVICES_JSON_IN_ARR); + $arr = array(); + } else { + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = array(); + } else { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = new stdClass(); + } + } + + array_push($stk, array('what' => SERVICES_JSON_SLICE, + 'where' => 0, + 'delim' => false)); + + $chrs = substr($str, 1, -1); + $chrs = $this->reduce_string($chrs); + + if ($chrs == '') { + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } else { + return $obj; + + } + } + + //print("\nparsing {$chrs}\n"); + + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c <= $strlen_chrs; ++$c) { + + $top = end($stk); + $substr_chrs_c_2 = substr($chrs, $c, 2); + + if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { + // found a comma that is not inside a string, array, etc., + // OR we've reached the end of the character list + $slice = substr($chrs, $top['where'], ($c - $top['where'])); + array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); + //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + // we are in an array, so just push an element onto the stack + array_push($arr, $this->decode($slice)); + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + // we are in an object, so figure + // out the property name and set an + // element in an associative array, + // for now + $parts = array(); + + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // "name":value pair + $key = $this->decode($parts[1]); + $val = $this->decode($parts[2]); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // name:value pair, where name is unquoted + $key = $parts[1]; + $val = $this->decode($parts[2]); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } + + } + + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { + // found a quote, and we are not inside a string + array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); + //print("Found start of string at {$c}\n"); + + } elseif (($chrs{$c} == $top['delim']) && + ($top['what'] == SERVICES_JSON_IN_STR) && + ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { + // found a quote, we're in a string, and it's not escaped + // we know that it's not escaped becase there is _not_ an + // odd number of backslashes at the end of the string so far + array_pop($stk); + //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '[') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-bracket, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); + //print("Found start of array at {$c}\n"); + + } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { + // found a right-bracket, and we're in an array + array_pop($stk); + //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '{') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-brace, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); + //print("Found start of object at {$c}\n"); + + } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { + // found a right-brace, and we're in an object + array_pop($stk); + //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($substr_chrs_c_2 == '/*') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a comment start, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); + $c++; + //print("Found start of comment at {$c}\n"); + + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { + // found a comment end, and we're in one now + array_pop($stk); + $c++; + + for ($i = $top['where']; $i <= $c; ++$i) + $chrs = substr_replace($chrs, ' ', $i, 1); + + //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } + + } + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + return $obj; + + } + + } + } + } + + /** + * @todo Ultimately, this should just call PEAR::isError() + */ + function isError($data, $code = null) + { + if (class_exists('pear')) { + return PEAR::isError($data, $code); + } elseif (is_object($data) && (get_class($data) == 'services_json_error' || + is_subclass_of($data, 'services_json_error'))) { + return true; + } + + return false; + } +} + +if (class_exists('PEAR_Error')) { + + class Services_JSON_Error extends PEAR_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + parent::PEAR_Error($message, $code, $mode, $options, $userinfo); + } + } + +} else { + + /** + * @todo Ultimately, this class shall be descended from PEAR_Error + */ + class Services_JSON_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + + } + } + +} + +?> diff --git a/share/pnp/application/lib/jsonwrapper.php b/share/pnp/application/lib/jsonwrapper.php new file mode 100644 index 0000000..29509de --- /dev/null +++ b/share/pnp/application/lib/jsonwrapper.php @@ -0,0 +1,6 @@ + diff --git a/share/pnp/application/lib/jsonwrapper_inner.php b/share/pnp/application/lib/jsonwrapper_inner.php new file mode 100644 index 0000000..e7a0e3f --- /dev/null +++ b/share/pnp/application/lib/jsonwrapper_inner.php @@ -0,0 +1,23 @@ +encode($arg); +} + +function json_decode($arg) +{ + global $services_json; + if (!isset($services_json)) { + $services_json = new Services_JSON(); + } + return $services_json->decode($arg); +} + +?> diff --git a/share/pnp/application/models/auth.php b/share/pnp/application/models/auth.php new file mode 100644 index 0000000..77f28d2 --- /dev/null +++ b/share/pnp/application/models/auth.php @@ -0,0 +1,154 @@ +config = new Config_Model; + $this->config->read_config(); + if($this->config->conf['auth_enabled'] == 1){ + $this->AUTH_ENABLED = TRUE; + $this->socketPath = $this->config->conf['livestatus_socket']; + } + + // Try to get the login of the user + if(isset($_SERVER['REMOTE_USER'])){ + $this->REMOTE_USER = $_SERVER['REMOTE_USER']; + } + if($this->REMOTE_USER === NULL && $this->config->conf['auth_multisite_enabled'] == 1) { + $MSAUTH = new Auth_Multisite_Model($this->config->conf['auth_multisite_htpasswd'], + $this->config->conf['auth_multisite_serials'], + $this->config->conf['auth_multisite_secret'], + $this->config->conf['auth_multisite_login_url']); + $this->REMOTE_USER = $MSAUTH->check(); + if($this->REMOTE_USER !== null) + return; + } + + if($this->AUTH_ENABLED === TRUE && $this->REMOTE_USER === NULL){ + throw new Kohana_exception("error.remote_user_missing"); + } + } + + public function __destruct() { + if($this->SOCKET !== NULL) { + socket_close($this->SOCKET); + $this->SOCKET = NULL; + } + } + + public function connect(){ + $this->getSocketDetails($this->socketPath); + $this->SOCKET = socket_create($this->socketDOMAIN, $this->socketTYPE, $this->socketPROTO); + if($this->SOCKET === FALSE) { + throw new Kohana_exception("error.livestatus_socket_error", socket_strerror(socket_last_error($this->SOCKET)), $this->socketPath); + } + if($this->socketDOMAIN === AF_UNIX){ + $result = @socket_connect($this->SOCKET, $this->socketPATH); + }else{ + $result = @socket_connect($this->SOCKET, $this->socketHOST, $this->socketPORT); + } + if(!$result) { + throw new Kohana_exception("error.livestatus_socket_error", socket_strerror(socket_last_error($this->SOCKET)), $this->socketPath); + } + + } + + private function queryLivestatus($query) { + if($this->SOCKET === NULL) { + $this->connect(); + } + @socket_write($this->SOCKET, $query."\nOutputFormat: json\n\n"); + // Read 16 bytes to get the status code and body size + $read = @socket_read($this->SOCKET,2048); + if(!$read) { + throw new Kohana_exception("error.livestatus_socket_error", socket_strerror(socket_last_error($this->SOCKET))); + } + # print Kohana::debug("read ". $read); + // Catch problem while reading + if($read === false) { + throw new Kohana_exception("error.livestatus_socket_error", socket_strerror(socket_last_error($this->SOCKET))); + } + + // Decode the json response + $obj = json_decode(utf8_encode($read)); + socket_close($this->SOCKET); + $this->SOCKET = NULL; + return $obj; + + } + + public function is_authorized($host = FALSE, $service = NULL){ + if($this->AUTH_ENABLED === FALSE){ + return TRUE; + } + + if($host == "pnp-internal"){ + return TRUE; + } + + if($service === NULL || $service == "_HOST_" || $service == "Host Perfdata"){ + $users = explode(",", $this->config->conf['allowed_for_all_hosts']); + if (in_array($this->REMOTE_USER, $users)) { + return TRUE; + } + $query = "GET hosts\nColumns: name\nFilter: name = $host\nAuthUser: ".$this->REMOTE_USER; + $result = $this->queryLivestatus($query); + }else{ + $users = explode(",", $this->config->conf['allowed_for_all_services']); + if (in_array($this->REMOTE_USER, $users)) { + return TRUE; + } + $query = "GET services\nColumns: host_name description\nFilter: host_name = $host\nFilter: description = $service\nAuthUser: ".$this->REMOTE_USER; + $result = $this->queryLivestatus($query); + } + + if(sizeof($result) > 0){ + return TRUE; + }else{ + return FALSE; + } + } + + + public function getSocketDetails($string=FALSE){ + + if(preg_match('/^unix:(.*)$/',$string,$match) ){ + $this->socketDOMAIN = AF_UNIX; + $this->socketTYPE = SOCK_STREAM; + $this->socketPATH = $match[1]; + $this->socketPROTO = 0; + return; + } + if(preg_match('/^tcp:([a-zA-Z0-9-\.]+):([0-9]+)$/',$string,$match) ){ + $this->socketDOMAIN = AF_INET; + $this->socketTYPE = SOCK_STREAM; + $this->socketHOST = $match[1]; + $this->socketPORT = $match[2]; + $this->socketPROTO = SOL_TCP; + return; + } + # Fallback + if(preg_match('/^\/.*$/',$string,$match) ){ + $this->socketDOMAIN = AF_UNIX; + $this->socketTYPE = SOCK_STREAM; + $this->socketPATH = $string; + $this->socketPROTO = 0; + return; + } + return FALSE; + } +} diff --git a/share/pnp/application/models/auth_multisite.php b/share/pnp/application/models/auth_multisite.php new file mode 100644 index 0000000..d4a3b41 --- /dev/null +++ b/share/pnp/application/models/auth_multisite.php @@ -0,0 +1,111 @@ +htpasswdPath = $htpasswdPath; + $this->serialsPath = $serialsPath; + $this->secretPath = $secretPath; + $this->loginUrl = $loginUrl; + + // When the auth.serial file exists, use this instead of the htpasswd + // for validating the cookie. The structure of the file is equal, so + // the same code can be used. + if(file_exists($this->serialsPath)) { + $this->authFile = 'serial'; + + } elseif(file_exists($this->htpasswdPath)) { + $this->authFile = 'htpasswd'; + + } else { + throw new Kohana_exception("error.auth_multisite_missing_htpasswd"); + } + + if(!file_exists($this->secretPath)) { + $this->redirectToLogin(); + } + } + + private function loadAuthFile($path) { + $creds = array(); + foreach(file($path) AS $line) { + if(strpos($line, ':') !== false) { + list($username, $secret) = explode(':', $line, 2); + $creds[$username] = rtrim($secret); + } + } + return $creds; + } + + private function loadSecret() { + return trim(file_get_contents($this->secretPath)); + } + + private function generateHash($username, $now, $user_secret) { + $secret = $this->loadSecret(); + return md5($username . $now . $user_secret . $secret); + } + + private function checkAuthCookie($cookieName) { + if(!isset($_COOKIE[$cookieName]) || $_COOKIE[$cookieName] == '') { + throw new Exception(); + } + + list($username, $issueTime, $cookieHash) = explode(':', $_COOKIE[$cookieName], 3); + + if($this->authFile == 'htpasswd') + $users = $this->loadAuthFile($this->htpasswdPath); + else + $users = $this->loadAuthFile($this->serialsPath); + + if(!isset($users[$username])) { + throw new Exception(); + } + $user_secret = $users[$username]; + + // Validate the hash + if($cookieHash != $this->generateHash($username, $issueTime, $user_secret)) { + throw new Exception(); + } + + // FIXME: Maybe renew the cookie here too + + return $username; + } + + private function checkAuth() { + // Loop all cookies trying to fetch a valid authentication + // cookie for this installation + foreach(array_keys($_COOKIE) AS $cookieName) { + if(substr($cookieName, 0, 5) != 'auth_') { + continue; + } + try { + $name = $this->checkAuthCookie($cookieName); + return $name; + } catch(Exception $e) {} + } + return ''; + } + + private function redirectToLogin() { + header('Location:' . $this->loginUrl . '?_origtarget=' . $_SERVER['REQUEST_URI']); + } + + public function check() { + $username = $this->checkAuth(); + if($username === '') { + $this->redirectToLogin(); + exit(0); + } + + return $username; + } +} + +?> diff --git a/share/pnp/application/models/config.php b/share/pnp/application/models/config.php new file mode 100644 index 0000000..44e3d12 --- /dev/null +++ b/share/pnp/application/models/config.php @@ -0,0 +1,88 @@ +get('h') != "" ) $conf['graph_height'] = intval($input->get('h')); + if($input->get('w') != "" ) $conf['graph_width'] = intval($input->get('w')); + if($input->get('graph_height') != "" ) $conf['graph_height'] = intval($input->get('graph_height')); + if($input->get('graph_width') != "" ) $conf['graph_width'] = intval($input->get('graph_width')); + $this->conf = $conf; + $this->views = $views; + $this->scheme = $scheme; + } +} diff --git a/share/pnp/application/models/data.php b/share/pnp/application/models/data.php new file mode 100644 index 0000000..38e049e --- /dev/null +++ b/share/pnp/application/models/data.php @@ -0,0 +1,1115 @@ +config = new Config_Model(); + $this->config->read_config(); + $this->auth = new Auth_Model(); + } + + /* + * Get All Special Templates + * + */ + public function getSpecialTemplates(){ + $conf = $this->config->conf; + $templates = array(); + if (is_dir($conf['special_template_dir'])){ + if ($dh = opendir($conf['special_template_dir'])) { + while (($file = readdir($dh)) !== false) { + if ($file == "." || $file == "..") + continue; + if (!preg_match("/(.*)\.php$/", $file, $template)) + continue; + $templates[] = $template[1]; + } + } + } + if(sizeof($templates) > 0){ + sort($templates); + return $templates; + }else{ + return FALSE; + } + } + + public function getFirstSpecialTemplate(){ + $templates = $this->getSpecialTemplates(); + if($templates === FALSE){ + return FALSE; + }else{ + return $templates[0]; + } + } + /* + * + * + */ + public function getHosts() { + $hosts = array(); + $conf = $this->config->conf; + $i = 0; + if (is_dir($conf['rrdbase'])) { + if ($dh = opendir($conf['rrdbase'])) { + while (($file = readdir($dh)) !== false) { + if ($file == "." || $file == ".." || $file == ".pnp-internal") + continue; + + if (is_file($conf['rrdbase'] . "/" . $file) ) + continue; + + if($this->auth->is_authorized($file) === FALSE) + continue; + + $stat = stat($conf['rrdbase'] . "/" . $file); + $age = (time() - $stat['mtime']); + $hosts[$i]['name'] = $file; + $hosts[$i]['sort'] = strtoupper($file); + if ($age < $conf['max_age']) { + $hosts[$i]['state'] = 'active'; + } else { + $hosts[$i]['state'] = 'inactive'; + } + $i++; + } + closedir($dh); + } else { + throw new Kohana_User_Exception('Perfdata Dir', "Can not open $path"); + } + } + if(sizeof($hosts)>0){ + # Obtain a list of columns + foreach ($hosts as $key => $row) { + $sort[$key] = $row['sort']; + } + # Sort the data with volume descending, edition ascending + # Add $data as the last parameter, to sort by the common key + array_multisort($sort, SORT_ASC, $hosts); + }else{ + throw new Kohana_Exception('error.perfdata-dir-empty', $conf['rrdbase'] ); + } + return $hosts; + } + + + /* + * + * + */ + function getRawServices($hostname) { + $services = array (); + $host = array(); + $conf = $this->config->conf; + $i = 0; + $path = $conf['rrdbase'] . $hostname; + if (is_dir($path)) { + if ($dh = opendir($path)) { + while ( ($file = readdir($dh) ) !== false) { + if ($file == "." || $file == "..") + continue; + + if (!preg_match("/(.*)\.xml$/", $file, $servicedesc)) + continue; + + $fullpath = $path . "/" . $file; + $stat = stat("$fullpath"); + $age = (time() - $stat['mtime']); + + $state = "active"; + if ($age > $conf['max_age']) { # 6Stunden + $state = "inactive"; + } + $services[$i]['state'] = $state; + $services[$i]['name'] = $servicedesc[1]; + $i++; + } + } + }else{ + throw new Kohana_Exception('error.perfdata-dir-for-host', $path, $hostname ); + } + if( is_array($services) && sizeof($services) > 0){ + # Obtain a list of columns + foreach ($services as $key => $row) { + $sort[$key] = $row['name']; + } + # Sort the data with volume descending, edition ascending + # Add $data as the last parameter, to sort by the common key + array_multisort($sort, SORT_STRING, $services); + }else{ + throw new Kohana_Exception('error.host-perfdata-dir-empty', $path, $hostname ); + } + return $services; + } + /* + * + * + */ + function getServices($hostname) { + $services = array (); + $host = array(); + $i = 0; + $service_list = $this->getRawServices($hostname); + foreach( $service_list as $s ){ + if(!$this->readXML($hostname, $s['name'], FALSE)){ + continue; + } + if($s['name'] == "_HOST_"){ + // Check authorization + if($this->auth->is_authorized((string) $this->XML->NAGIOS_AUTH_HOSTNAME, "_HOST_") === FALSE) + continue; + + $host[0]['name'] = "_HOST_"; + $host[0]['hostname'] = (string) $this->XML->NAGIOS_HOSTNAME; + $host[0]['state'] = $s['state']; + $host[0]['servicedesc'] = "Host Perfdata"; + $host[0]['is_multi'] = (string) $this->XML->DATASOURCE[0]->IS_MULTI[0]; + }else{ + // Check authorization + if($this->auth->is_authorized((string) $this->XML->NAGIOS_AUTH_HOSTNAME, (string) $this->XML->NAGIOS_AUTH_SERVICEDESC) === FALSE ) + continue; + + $services[$i]['name'] = $s['name']; + // Sorting check_multi + if( (string) $this->XML->NAGIOS_MULTI_PARENT == ""){ + $services[$i]['sort'] = strtoupper($s['name']); + }else{ + $services[$i]['sort'] = strtoupper((string) $this->XML->NAGIOS_MULTI_PARENT); + $services[$i]['sort'] .= (string) $this->XML->DATASOURCE[0]->IS_MULTI[0]; + $services[$i]['sort'] .= strtoupper($s['name']); + } + $services[$i]['state'] = $s['state']; + $services[$i]['hostname'] = (string) $this->XML->NAGIOS_DISP_HOSTNAME; + $services[$i]['servicedesc'] = (string) $this->XML->NAGIOS_DISP_SERVICEDESC; + $services[$i]['is_multi'] = (string) $this->XML->DATASOURCE[0]->IS_MULTI[0]; + } + $i++; + } + #print Kohana::debug($services); + if( is_array($services) && sizeof($services) > 0){ + # Obtain a list of columns + foreach ($services as $key => $row) { + $sort[$key] = $row['sort']; + } + # Sort the data with volume descending, edition ascending + # Add $data as the last parameter, to sort by the common key + array_multisort($sort, SORT_STRING, $services); + } + if(is_array($host) && sizeof($host) > 0 ){ + array_unshift($services, $host[0]); + } + return $services; + } + + /* + * + * + */ + public function getFirstService($hostname) { + $conf = $this->config->conf; + $services = $this->getServices($hostname); + foreach ($services as $srv) { + if ($srv['state'] == "active" ) { + break; + } + } + if(sizeof($srv) == 0){ + throw new Kohana_Exception('error.get-first-service', $hostname ); + } + return $srv['name']; + } + + /* + * + * + */ + public function getFirstHost() { + $conf = $this->config->conf; + $hosts = $this->getHosts(); + foreach ($hosts as $host) { + if ($host['state'] == "active" ) { + break; + } + } + if(sizeof($host) == 0){ + throw new Kohana_Exception('error.get-first-host'); + } + return $host['name']; + } + + /* + * + * + */ + public function readXML ($hostname, $servicedesc, $throw_exception=TRUE){ + $conf = $this->config->conf; + $xmlfile = $conf['rrdbase'].$hostname."/".$servicedesc.".xml"; + $xml = array(); + if (file_exists($xmlfile)) { + libxml_use_internal_errors(TRUE); + libxml_clear_errors(TRUE); + if(! $xml = simplexml_load_file($xmlfile) ){; + if( $throw_exception == TRUE ){ + $errors = '
    '; + foreach(libxml_get_errors() as $error) { + $errors .= $error->message."
    "; + } + throw new Kohana_Exception('error.xml-generic_error',$xmlfile, $errors); + }else{ + return FALSE; + } + } + $this->XML = array(); + $this->MACRO = array(); + $this->MACRO['AUTH_SERVICEDESC'] = ''; + $this->MACRO['AUTH_HOSTNAME'] = ''; + $this->DS = array(); + // Throw excaption without a valid structure version + if(!isset($xml->XML->VERSION) && $throw_exception == TRUE){ + throw new Kohana_Exception('error.xml-structure-without-version-tag',$xmlfile); + } + if(!isset($xml->XML->VERSION) && $throw_exception == FALSE){ + return FALSE; + } + foreach ( $xml as $key=>$val ){ + if(preg_match('/^NAGIOS_(.*)$/', $key, $match)){ + #print $match[1]." => ".$val."\n"; + $key = $match[1]; + $this->MACRO[$key] = (string) $val; + } + } + $i=0; + foreach ( $xml->DATASOURCE as $datasource ){ + foreach ( $datasource as $key=>$val){ + #print "$key => $val\n"; + #$$key[$i] = (string) $val; + $this->DS[$i][$key] = (string) $val; + } + $i++; + } + $this->XML = $xml; + return TRUE; + }else{ + throw new Kohana_Exception('error.xml-not-found', $xmlfile); + } + } + + /* + * + * + */ + public function buildDataStruct ($host = FALSE, $service = FALSE, $view = NULL, $source = NULL){ + if($host === FALSE && $service === FALSE){ + return FALSE; + } + $conf = $this->config->conf; + + /* + * Special templates without Host/Service + */ + if($host == '__special' ){ + // $service contains the template name + $this->includeTemplate($service,'special'); + }else{ + if( $this->readXML($host,$service) == FALSE ){ + throw new Kohana_Exception('error.xml-not-found', "Undefined error"); + return false; + } + $this->includeTemplate($this->DS[0]['TEMPLATE']); + } + if(isset($this->TIMERANGE['type']) && $this->TIMERANGE['type'] == "start-end"){ + $view = intval($view); + $i=0; + foreach( $this->RRD['def'] as $key=>$val){ + if( ! is_null($source) && $source != $key ){ + continue; + } + $tmp_struct = array(); + $tmp_struct['LEVEL'] = $i; + $tmp_struct['VIEW'] = $view; + $tmp_struct['TEMPLATE_FILE'] = $this->TEMPLATE_FILE;; + $tmp_struct['SOURCE'] = $key; + $tmp_struct['RRD_CALL'] = $this->TIMERANGE['cmd'] . " ". $this->RRD['opt'][$key] . " " . $this->RRD['def'][$key]; + $tmp_struct['TIMERANGE'] = $this->TIMERANGE; + $tmp_struct['GRAPH_WIDTH'] = $this->getGraphDimensions('width', $tmp_struct['RRD_CALL']); + $tmp_struct['GRAPH_HEIGHT'] = $this->getGraphDimensions('height', $tmp_struct['RRD_CALL']); + if(isset($this->RRD['ds_name'][$key]) ){ + $tmp_struct['ds_name'] = $this->RRD['ds_name'][$key]; + }elseif(array_key_exists($i, $this->DS)){ + $tmp_struct['ds_name'] = $this->DS[$i]['NAME']; + }else{ + $tmp_struct['ds_name'] = "UNDEF"; + } + $tmp_struct['MACRO'] = $this->MACRO; + if(isset($this->XML->XML->VERSION)){ + $tmp_struct['VERSION'] = pnp::xml_version_check( (string) $this->XML->XML->VERSION); + }else{ + $tmp_struct['VERSION'] = pnp::xml_version_check("0"); + } + $this->addToDataStruct($tmp_struct); + $i++; + } + return; + } + if( $view === ""){ + $v = 0; + foreach($this->config->views as $view_key=>$view_val){ + $i=0; + foreach( $this->RRD['def'] as $key=>$val){ + if( ! is_null($source) && $source != $key ){ + continue; + } + $tmp_struct = array(); + $tmp_struct['LEVEL'] = $i; + $tmp_struct['VIEW'] = $view_key; + $tmp_struct['TEMPLATE_FILE'] = $this->TEMPLATE_FILE;; + $tmp_struct['SOURCE'] = $key; + $tmp_struct['RRD_CALL'] = $this->TIMERANGE[$v]['cmd'] . " " . $this->RRD['opt'][$key] . " " . $this->RRD['def'][$key]; + $tmp_struct['GRAPH_WIDTH'] = $this->getGraphDimensions('width', $tmp_struct['RRD_CALL']); + $tmp_struct['GRAPH_HEIGHT'] = $this->getGraphDimensions('height', $tmp_struct['RRD_CALL']); + if(isset($this->RRD['ds_name'][$key]) ){ + $tmp_struct['ds_name'] = $this->RRD['ds_name'][$key]; + }elseif(array_key_exists($i, $this->DS)){ + $tmp_struct['ds_name'] = $this->DS[$i]['NAME']; + }else{ + $tmp_struct['ds_name'] = "UNDEF"; + } + $tmp_struct['TIMERANGE'] = $this->TIMERANGE[$v]; + $tmp_struct['MACRO'] = $this->MACRO; + if(isset($this->XML->XML->VERSION)){ + $tmp_struct['VERSION'] = pnp::xml_version_check( (string) $this->XML->XML->VERSION); + }else{ + $tmp_struct['VERSION'] = pnp::xml_version_check("0"); + } + $this->addToDataStruct($tmp_struct); + $i++; + } + $v++; + } + }else{ + $view = intval($view); + $i=0; + foreach( $this->RRD['def'] as $key=>$val){ + if( ! is_null($source) && $source != $key ){ + continue; + } + $tmp_struct = array(); + $tmp_struct['LEVEL'] = $i; + $tmp_struct['VIEW'] = $view; + $tmp_struct['TEMPLATE_FILE'] = $this->TEMPLATE_FILE;; + $tmp_struct['SOURCE'] = $key; + $tmp_struct['RRD_CALL'] = $this->TIMERANGE[$view]['cmd'] . " ". $this->RRD['opt'][$key] . " " . $this->RRD['def'][$key]; + $tmp_struct['TIMERANGE'] = $this->TIMERANGE[$view]; + $tmp_struct['GRAPH_WIDTH'] = $this->getGraphDimensions('width', $tmp_struct['RRD_CALL']); + $tmp_struct['GRAPH_HEIGHT'] = $this->getGraphDimensions('height', $tmp_struct['RRD_CALL']); + if(isset($this->RRD['ds_name'][$key]) ){ + $tmp_struct['ds_name'] = $this->RRD['ds_name'][$key]; + }elseif(array_key_exists($i, $this->DS)){ + $tmp_struct['ds_name'] = $this->DS[$i]['NAME']; + }else{ + $tmp_struct['ds_name'] = "UNDEF"; + } + $tmp_struct['MACRO'] = $this->MACRO; + if(isset($this->XML->XML->VERSION)){ + $tmp_struct['VERSION'] = pnp::xml_version_check( (string) $this->XML->XML->VERSION); + }else{ + $tmp_struct['VERSION'] = pnp::xml_version_check("0"); + } + $this->addToDataStruct($tmp_struct); + $i++; + } + } + } + + /* + * + * + */ + private function addToDataStruct ($data=FALSE) { + if($data === FALSE) + return FALSE; + + array_push($this->STRUCT, $data); + } + + /* + * + * + */ + private function includeTemplate($template=FALSE,$type='normal'){ + if($template===FALSE){ + return FALSE; + } + $this->RRD = array(); + /* + * Normal PNP Templates + */ + if($type == 'normal'){ + $template_file = $this->findTemplate( $template ); + $this->TEMPLATE_FILE = $template_file; + $hostname = $this->MACRO['HOSTNAME']; + $servicedesc = $this->MACRO['SERVICEDESC']; + $TIMERANGE = $this->TIMERANGE; + }elseif($type == 'special'){ + $template_file = $this->findTemplate( $template, $type ); + $TIMERANGE = $this->TIMERANGE; + } + $def = FALSE; + $opt = FALSE; + $ds_name = FALSE; + /* + * 0.4.x Template compatibility + */ + foreach($this->DS as $key=>$val ){ + $key++; + foreach(array_keys($val) as $tag){ + ${$tag}[$key] = $val[$tag]; + } + } + foreach($this->MACRO as $key=>$val ){ + ${"NAGIOS_".$key} = $val; + } + if(isset($RRDFILE[1])){ + $rrdfile = $RRDFILE[1]; + } + // Include template + if($template_file == FALSE){ + throw new Kohana_Exception('error.no-templates-found'); + }else{ + ob_start(); + include($template_file); + ob_end_clean(); + } + // Compatibility for very old Templates + if(!is_array($def) && $def != FALSE){ + $tmp[1] = $def; + $def = $tmp; + } + if(!is_array($opt) && $opt != FALSE){ + $tmp[1] = $opt; + $opt = $tmp; + } + if(!is_array($ds_name) && $ds_name != FALSE){ + $tmp[1] = $ds_name; + $ds_name = $tmp; + } + // + if($def != FALSE){ + $this->RRD['def'] = $this->array_reindex($def); + }else{ + throw new Kohana_Exception('error.template-without-def', $template_file); + } + if($opt != FALSE ){ + $this->RRD['opt'] = $this->array_reindex($opt); + }else{ + throw new Kohana_Exception('error.template-without-opt', $template_file); + } + if( $ds_name != FALSE ){ + $this->RRD['ds_name'] = $this->array_reindex($ds_name); + } + return TRUE; + } + + # + # + # + private function getGraphDimensions($search, $command){ + if($search == 'width'){ + if(preg_match_all('/(-w|--width|--width=)\s([0-9]+)\s/i',$command,$match)){ + $value = array_pop($match[2]); + return $value; + }else{ + return $this->config->conf['graph_width']; + } + } + if($search == 'height'){ + if(preg_match_all('/(-h|--height|--height=)\s([0-9]+)\s/i',$command,$match)){ + $value = array_pop($match[2]); + return $value; + }else{ + return $this->config->conf['graph_height']; + } + } + return FALSE; + } + # + # + # + private function array_reindex($data){ + $i=0; + foreach($data as $d){ + $tmp[$i] = $d; + $i++; + } + return $tmp; + } + + /* + * + * + */ + public function findTemplate($template,$type='normal'){ + $conf = $this->config->conf; + /* + * Normal templates + */ + if($type == 'normal'){ + // Build a list of directories to search for templates + $template_dirs = array(); + if(array_key_exists('template_dirs', $this->config->conf)){ + foreach($this->config->conf['template_dirs'] as $dir){ + $template_dirs[] = $dir; + } + } + foreach(Kohana::config('core.template_dirs') as $dir){ + $template_dirs[] = $dir; + } + #throw new Kohana_Exception(print_r($template_dirs,TRUE)); + foreach($template_dirs as $dir){ + $match = $this->findRecursiveTemplate($template,$dir); + if($match != FALSE){ + return $match; + } + } + /* + * Fallback to default templates + */ + foreach($template_dirs as $dir){ + $match = $this->findRecursiveTemplate('default',$dir); + if($match != FALSE){ + return $match; + } + } + return FALSE; + } + /* + * Special Templates + */ + if($type == 'special'){ + if (is_readable($conf['special_template_dir'] . '/' . $template . '.php')) { + $template_file = $conf['special_template_dir'].'/' . $template . '.php'; + }else{ + throw new Kohana_Exception("Special Template '$template' not found"); + } + return $template_file; + } + } + + /* + * + * + */ + function findRecursiveTemplate($template, $dir) { + if(!is_readable($dir)){ + return FALSE; + } + $template_file = ""; + $r_template_file = ""; + $r_template = ""; + $recursive = explode("_", $template); + if($this->config->conf['enable_recursive_template_search'] == 1){ + $i = 0; + foreach ($recursive as $value) { + if ($i == 0) { + $r_template = $value; + } else { + $r_template = $r_template . '_' . $value; + } + $file = $dir . '/' . $r_template . '.php'; + if (is_readable($file)) { + $r_template_file = $file; + } + $i++; + } + if($r_template_file != ""){ + return $r_template_file; + }else{ + return FALSE; + } + }else{ + $file = $dir . '/' . $template . '.php'; + if (is_readable($file)) { + return $file; + }else{ + return FALSE; + } + } + } + + public function getTimeRange($start=FALSE ,$end=FALSE ,$view="") { + if($end != FALSE){ + // we are in a custom timerange + if(!is_numeric($end)){ + $timestamp = strtotime($end); + if(!$timestamp){ + throw new Kohana_User_Exception('Wrong Format', "$end"); + }else{ + $end = $timestamp; + } + } + }else{ + $end = time(); + } + if($start != FALSE ){ + // we are in a custom timerange + if(!is_numeric($start)){ + $timestamp = strtotime($start); + if(!$timestamp){ + throw new Kohana_User_Exception('Wrong Format', "Start -> $start"); + }else{ + $start = $timestamp; + } + } + } + if($start && $end){ + $timerange['title'] = Kohana::lang('common.timerange-selector-link'); + $timerange['start'] = $start; + $timerange['f_start'] = date($this->config->conf['date_fmt'],$start); + $timerange['end'] = $end; + $timerange['f_end'] = date($this->config->conf['date_fmt'],$end); + $timerange['cmd'] = " --start $start --end $end "; + $timerange['type'] = "start-end"; + $this->TIMERANGE = $timerange; + return; + } + + $view=intval( pnp::clean($view) ); + if($view >= sizeof($this->config->views)){ + $view = 1; + } + + if(!$end){ + $end = time(); + }elseif(!is_numeric($end)){ + $timestamp = strtotime($end); + if(!$timestamp){ + throw new Kohana_User_Exception('Wrong Format', "$end"); + }else{ + $end = $timestamp; + } + }else{ + $end = $end; + } + + if(!$start){ + $start = ( $end - $this->config->views[$view]['start']); + }elseif(!is_numeric($start)){ + $timestamp = strtotime($start); + if(!$timestamp){ + throw new Kohana_User_Exception('Wrong Format', "$start"); + }else{ + $start = $timestamp; + } + }else{ + $start = pnp::clean($start); + } + + if($start >= $end){ + //Fixme i18n + throw new Kohana_User_Exception('Wrong Timerange', "start >= end"); + } + + $timerange['title'] = $this->config->views[$view]['title']; + $timerange['start'] = $start; + $timerange['f_start'] = date($this->config->conf['date_fmt'],$start); + $timerange['end'] = $end; + $timerange['f_end'] = date($this->config->conf['date_fmt'],$end); + $timerange['cmd'] = " --start $start --end $end "; + $timerange['type'] = "views"; + for ($i = 0; $i < sizeof($this->config->views); $i++) { + $timerange[$i]['title'] = $this->config->views[$i]['title']; + $timerange[$i]['start'] = $end - $this->config->views[$i]['start']; + $timerange[$i]['f_start'] = date($this->config->conf['date_fmt'],$end - $this->config->views[$i]['start']); + $timerange[$i]['end'] = $end; + $timerange[$i]['f_end'] = date($this->config->conf['date_fmt'],$end); + $timerange[$i]['cmd'] = " --start " . ($end - $this->config->views[$i]['start']) . " --end $end" ; + } + $this->TIMERANGE = $timerange; + } + + public function buildBasketStruct($basket,$view = NULL){ + if(is_array($basket) && sizeof($basket) > 0){ + if($view == ""){ + $views = array_keys($this->config->views); + }else{ + $views = array($view); + } + foreach($views as $view){ + foreach($basket as $item){ + # explode host::service::source + $slices = explode("::",$item); + if(sizeof($slices) == 2) + $this->buildDataStruct($slices[0], $slices[1], $view); + if(sizeof($slices) == 3) + $this->buildDataStruct($slices[0], $slices[1], $view, $slices[2]); + } + # break on custom time ranges + if(isset($this->TIMERANGE['type']) && $this->TIMERANGE['type'] == "start-end"){ + break; + } + } + } + } + + public function buildPageStruct($page,$view){ + $servicelist = array(); + $this->parse_page_cfg($page); + $hosts = $this->getHostsByPage(); + # No regex so we keep the order defined by config + if($this->PAGE_DEF['use_regex'] == 0){ + #Loop through graph definitions + foreach($this->PAGE_GRAPH as $graph){ + $hosts_to_search_for = explode(",", $graph['host_name']); + foreach($hosts_to_search_for as $host){ + if(in_array($host, $hosts)){ + $services = $this->getServices($host); + foreach($services as $service) { + // search for definition + $data = $this->filterServiceByPage($graph,$host,$service); + if($data){ + $servicelist[] = array( 'host' => $host, 'service' => $service['name'], 'source' => $data['source']); + + } + } + } + } + } + }else{ + foreach($hosts as $host){ + $services = $this->getServices($host); + foreach($services as $service) { + // search for definition + $data = $this->filterServiceByPage($this->PAGE_GRAPH,$host,$service); + if($data){ + $servicelist[] = array( 'host' => $host, 'service' => $service['name'], 'source' => $data['source']); + } + } + } + } + #print Kohana::debug($servicelist); + if(sizeof($servicelist) > 0 ){ + foreach($servicelist as $s){ + $this->buildDataStruct($s['host'],$s['service'],$view,$s['source']); + } + }else{ + $this->ERROR = "ERROR: ". Kohana::lang('error.no-data-for-page', $page.".cfg" ); + } + } + + + public function parse_page_cfg($page){ + $page_cfg = $this->config->conf['page_dir'].$page.".cfg"; + if(is_readable($page_cfg)){ + $data = file($page_cfg); + }else{ + throw new Kohana_Exception('error.page-not-readable', $page.".cfg" ); + } + $l = 0; + $line = ""; + $tag = ""; + $inside=0; + $this->PAGE_DEF['page_name'] = 'UNDEF'; + $this->PAGE_DEF['use_regex'] = 0; + $this->PAGE_GRAPH = array(); + $allowed_tags = array("page", "graph"); + foreach($data as $line){ + if(preg_match('/(^#|^;)/',$line)) { + continue; + } + + preg_match('/define\s+(\w+)\W+{/' ,$line, $tag); + if(isset($tag[1]) && in_array($tag[1],$allowed_tags)){ + $inside = 1; + $t = $tag[1]; + $l++; + continue; + } + if(preg_match('/\s?(\w+)\s+([^#]+)(#.*)?$/',$line, $key) && $inside == 1){ + $k=strtolower($key[1]); + $v=$key[2]; + if($t=='page'){ + $this->PAGE_DEF[$k] = trim($v); + }elseif($t=='graph'){ + $this->PAGE_GRAPH[$l][$k] = trim($v); + } + } + if(preg_match('/}/',$line)){ + $inside=0; + $t = ""; + continue; + } + } + } + + /* + * + */ + public function getHostsByPage(){ + $hosts = $this->getHosts(); + $new_hosts = array(); + foreach( $hosts as $host){ + if($host['state'] == "inactive"){ + continue; + } + if($tmp = $this->filterHostByPage($host['name'])){ + $new_hosts[] = $tmp; + } + } + return $new_hosts; + } + /* + * + */ + private function filterHostByPage($host){ + if(isset($this->PAGE_DEF['use_regex']) && $this->PAGE_DEF['use_regex'] == 1){ + // Search Host by regex + foreach( $this->PAGE_GRAPH as $g ){ + if(isset($g['host_name']) && preg_match('/'.$g['host_name'].'/',$host)){ + return $host; + } + } + }else{ + foreach( $this->PAGE_GRAPH as $g ){ + $hosts_to_search_for = explode(",", $g['host_name']); + if(isset($g['host_name']) && in_array($host ,$hosts_to_search_for) ){ + return $host; + } + } + } + return FALSE; + } + + private function filterServiceByPage($g,$host,$service){ + $data = array(); + if(isset($this->PAGE_DEF['use_regex']) && $this->PAGE_DEF['use_regex'] == 1){ + // Search Host by regex + foreach( $this->PAGE_GRAPH as $g ){ + if(isset($g['host_name']) && preg_match('/'.$g['host_name'].'/',$host)){ + if(isset($g['service_desc']) && preg_match('/'.$g['service_desc'].'/',$service['name'])){ + $data['service_desc'] = $g['service_desc']; + $data['host_name'] = $g['host_name']; + $data['source'] = NULL; + // if we only want a single image + if(isset($g['source'])){ + $this->readXML($host,$service['name']); + $this->includeTemplate($this->DS[0]['TEMPLATE']); + $source = intval($g['source']); + if(array_key_exists($source,$this->RRD['def'])){ + $data['source'] = $source; + } + } + return $data; + } + } + } + }else{ + $hosts_to_search_for = explode(",", $g['host_name']); + $services_to_search_for = explode(",", $g['service_desc']); + if(isset($g['host_name']) && in_array($host ,$hosts_to_search_for) ){ + if(isset($g['service_desc']) && in_array($service['name'] ,$services_to_search_for) ){ + $data['service_desc'] = $g['service_desc']; + $data['host_name'] = $g['host_name']; + $data['source'] = NULL; + // if we only want a single image + if(isset($g['source'])){ + $this->readXML($host,$service['name']); + $this->includeTemplate($this->DS[0]['TEMPLATE']); + $source = intval($g['source']); + if(array_key_exists($source,$this->RRD['def'])){ + $data['source'] = $source; + } + } + return $data; + } + } + } + return FALSE; + } + + /* + * + */ + public function getPages() { + $pages = array(); + if (is_dir($this->config->conf['page_dir'])) { + if ($dh = opendir($this->config->conf['page_dir'])) { + while (($file = readdir($dh)) !== false) { + if(preg_match('/(.*)\.cfg$/',basename($file),$page)){ + $pages[] = urlencode($page[1]); + } + } + closedir($dh); + } else { + die("Cannot open directory: $path"); + } + } + if(sizeof($pages)>0){ + + natsort($pages); + }else{ + return FALSE; + } + return $pages; + } + + /* + * + */ + public function getFirstPage(){ + $pages = $this->getPages(); + if(sizeof($pages) > 0 ){ + return urldecode($pages[0]); + }else{ + return FALSE; + } + } + + /* + * + */ + public function getPageDetails($page){ + $this->parse_page_cfg($page); + return $this->PAGE_DEF['page_name']; + } + + /* + * + */ + public function buildXport($host,$service){ + // FIXME add max rows to config + $this->XPORT = " -m 2000"; + $this->XPORT .= " --start=".$this->TIMERANGE['start']; + $this->XPORT .= " --end=".$this->TIMERANGE['end']; + $this->readXML($host,$service); + $count = 0; + $RRAs = array('MIN','MAX','AVERAGE'); + foreach($this->DS as $key=>$value){ + foreach($RRAs as $RRA){ + $this->XPORT .= sprintf(" DEF:%d%s=%s:%d:%s ",$count,$RRA,$value['RRDFILE'],$value['DS'],$RRA); + $this->XPORT .= sprintf(" XPORT:%d%s:%s_%s " ,$count,$RRA,$value['NAME'],$RRA); + } + $count++; + } + } + /* + * + */ + public function xml2csv($string){ + $xml = simplexml_load_string($string); + $csv = "timestamp"; + foreach($xml->meta->legend->entry as $key=>$value){ + $csv .= ";" . $value ; + } + $csv .= "\n"; + foreach($xml->data->row as $key=>$value){ + $csv .= (string) $value->t ; + foreach($value->v as $item){ + $csv .= ";".floatval((string) $item); + } + $csv .= "\n"; + } + return $csv; + } + + /* + * + * Used in Special Templates to gather data + */ + public function tplGetData ($hostname, $servicedesc, $throw_exception=TRUE){ + $conf = $this->config->conf; + $xmlfile = $conf['rrdbase'].$hostname."/".$servicedesc.".xml"; + $data = array(); + if (file_exists($xmlfile)) { + $xml = simplexml_load_file($xmlfile); + // Throw excaption without a valid structure version + if(!isset($xml->XML->VERSION) && $throw_exception == TRUE){ + throw new Kohana_Exception('error.xml-structure-without-version-tag',$xmlfile); + } + if(!isset($xml->XML->VERSION) && $throw_exception == FALSE){ + return FALSE; + } + foreach ( $xml as $key=>$val ){ + if(preg_match('/^NAGIOS_(.*)$/', $key, $match)){ + $key = $match[1]; + $data['MACRO'][$key] = (string) $val; + } + } + $i=0; + foreach ( $xml->DATASOURCE as $datasource ){ + foreach ( $datasource as $key=>$val){ + $data['DS'][$i][$key] = (string) $val; + } + $i++; + } + return $data; + }else{ + throw new Kohana_Exception('error.xml-not-found', $xmlfile); + } + } + /* + * + * Used in Special Templates to gather data + */ + public function tplGetServices ($hostregex=FALSE, $serviceregex = ''){ + if($hostregex === FALSE){ + return FALSE; + } + $hostregex = sprintf("/%s/",$hostregex); + $serviceregex = sprintf("/%s/",$serviceregex); + $hosts = $this->getHosts(); + $new_hosts = array(); + foreach( $hosts as $host){ + if(preg_match($hostregex,$host['name'])){ + $new_hosts[] = $host['name']; + } + } + + if(sizeof($new_hosts) == 0){ + throw new Kohana_Exception('error.tpl-no-hosts-found', $hostregex); + } + + $i = 0; + $new_services = array(); + foreach($new_hosts as $host){ + $services = $this->getRawServices($host); + if(sizeof($services) == 0){ + throw new Kohana_Exception('error.tpl-no-services-found', $serviceregex); + } + foreach($services as $service){ + if(preg_match($serviceregex, $service['name'])){ + $new_services[$i]['hostname'] = $host; + $new_services[$i]['host'] = $host; + $new_services[$i]['service_description'] = $service['name']; + $new_services[$i]['service'] = $service['name']; + $i++; + } + } + } + + if(sizeof($new_services) == 0){ + throw new Kohana_Exception('error.tpl-no-services-found', $serviceregex); + } + + return $new_services; + + } +} diff --git a/share/pnp/application/models/rrdtool.php b/share/pnp/application/models/rrdtool.php new file mode 100644 index 0000000..bca756f --- /dev/null +++ b/share/pnp/application/models/rrdtool.php @@ -0,0 +1,243 @@ +config = new Config_Model(); + $this->config->read_config(); + #print Kohana::debug($this->config->views); + } + + private function rrdtool_execute() { + $descriptorspec = array ( + 0 => array ("pipe","r"), // stdin is a pipe that the child will read from + 1 => array ("pipe","w"), // stdout is a pipe that the child will write to + 2 => array ("pipe","w") // stderr is a pipe that the child will write to + ); + + if(!isset($this->config->conf['rrdtool']) ) + return FALSE; + + if ( !is_executable($this->config->conf['rrdtool']) ) { + $data = "ERROR: ".$this->config->conf['rrdtool']." is not executable by PHP\n\n"; + return $data; + } + + $rrdtool = $this->config->conf['rrdtool'] . " - "; + $command = $this->RRD_CMD; + $process = proc_open($rrdtool, $descriptorspec, $pipes); + $debug = Array(); + $data = ""; + if (is_resource($process)) { + fwrite($pipes[0], $command); + fclose($pipes[0]); + stream_set_timeout($pipes[1],1); + $data = stream_get_contents($pipes[1]); + stream_set_timeout($pipes[2],1); + $stderr = stream_get_contents($pipes[2]); + $stdout_meta = stream_get_meta_data($pipes[1]); + if($stdout_meta['timed_out'] == 1){ + $data = "ERROR: Timeout while reading rrdtool data.\n\n"; + } + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + // Catch STDERR + if($stderr && strlen($stderr) >= 0 ){ + $data = "ERROR: STDERR => ".$stderr."\n\n"; + return $data; + } + // Catch STDOUT < 50 Characters + if($data && strlen($data) < 50 ){ + $data = "ERROR: STDOUT => ".$data."\n\n"; + return $data; + } + }else{ + $data = "ERROR: proc_open(".$rrdtool." ... failed"; + } + return $data; + + } + + public function doImage($RRD_CMD, $out='STDOUT') { + $conf = $this->config->conf; + # construct $command to rrdtool + if(isset($conf['RRD_DAEMON_OPTS']) && $conf['RRD_DAEMON_OPTS'] != '' ){ + $command = " graph --daemon=" . $conf['RRD_DAEMON_OPTS'] . " - "; + }else{ + $command = " graph - "; + } + + $width = 0; + $height = 0; + if ($out == 'PDF'){ + if($conf['pdf_graph_opt']){ + $command .= $conf['pdf_graph_opt']; + } + if (isset($conf['pdf_width']) && is_numeric($conf['pdf_width'])){ + $width = abs($conf['pdf_width']); + } + if (isset($conf['pdf_height']) && is_numeric($conf['pdf_height'])){ + $height = abs($conf['pdf_height']); + } + }else{ + if($conf['graph_opt']){ + $command .= $conf['graph_opt']; + } + if(is_numeric($conf['graph_width'])){ + $width = abs($conf['graph_width']); + } + if(is_numeric($conf['graph_height'])){ + $height = abs($conf['graph_height']); + } + } + + if ($width > 0){ + $command .= " --width=$width"; + } + if ($height > 0){ + $command .= " --height=$height"; + } + if ($height < 81 ){ + $command .= " --only-graph "; + } + + $command .= $RRD_CMD; + + # Force empty vertical label + if( ! preg_match_all('/(-l|--vertical-label)/i',$command,$match)){ + $command .= " --vertical-label=' ' "; + } + + $this->RRD_CMD = $command; + $data = $this->rrdtool_execute(); + if($data){ + return $data; + }else{ + return FALSE; + } + } + + /* + * + */ + public function doXport($RRD_CMD){ + $conf = $this->config->conf; + if(isset($conf['RRD_DAEMON_OPTS']) && $conf['RRD_DAEMON_OPTS'] != '' ){ + $command = " xport --daemon=" . $conf['RRD_DAEMON_OPTS']; + }else{ + $command = " xport "; + } + $command .= $RRD_CMD; + $this->RRD_CMD = $command; + $data = $this->rrdtool_execute(); + $data = preg_replace('/OK.*/','',$data); + if($data){ + return $data; + }else{ + return FALSE; + } + } + + public function streamImage($data = FALSE){ + if ( $data === FALSE ){ + header("Content-type: image/png"); + echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A + /wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kCCAoDKSKZ0rEAAAAZdEVYdENv + bW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADUlEQVQI12NgYGBgAAAABQABXvMqOgAAAABJ + RU5ErkJggg=='); + return; + } + if (preg_match('/^ERROR/', $data)) { + if(preg_match('/NOT_AUTHORIZED/', $data)){ + // TODO: i18n + $data .= "\n\nYou are not authorized to view this Image"; + // Set font size + $font_size = 3; + }else{ + $data .= $this->format_rrd_debug( $this->config->conf['rrdtool'] . $this->RRD_CMD) ; + // Set font size + $font_size = 1.5; + } + $ts=explode("\n",$data); + $width=0; + foreach ($ts as $k=>$string) { + $width=max($width,strlen($string)); + } + + $width = imagefontwidth($font_size)*$width; + if($width <= $this->config->conf['graph_width']+100){ + $width = $this->config->conf['graph_width']+100; + } + $height = imagefontheight($font_size)*count($ts); + if($height <= $this->config->conf['graph_height']+60){ + $height = $this->config->conf['graph_height']+60; + } + $el=imagefontheight($font_size); + $em=imagefontwidth($font_size); + // Create the image pallette + $img = imagecreatetruecolor($width,$height); + // Dark red background + $bg = imagecolorallocate($img, 0xAA, 0x00, 0x00); + imagefilledrectangle($img, 0, 0,$width ,$height , $bg); + // White font color + $color = imagecolorallocate($img, 255, 255, 255); + + foreach ($ts as $k=>$string) { + // Length of the string + $len = strlen($string); + // Y-coordinate of character, X changes, Y is static + $ypos_offset = 5; + $xpos_offset = 5; + // Loop through the string + for($i=0;$i<$len;$i++){ + // Position of the character horizontally + $xpos = $i * $em + $ypos_offset; + $ypos = $k * $el + $xpos_offset; + // Draw character + imagechar($img, $font_size, $xpos, $ypos, $string, $color); + // Remove character from string + $string = substr($string, 1); + } + } + header("Content-type: image/png"); + imagepng($img); + imagedestroy($img); + }else{ + header("Content-type: image/png"); + echo $data; + } + } + + public function saveImage($data = FALSE){ + $img = array(); + $img['file'] = tempnam($this->config->conf['temp'],"PNP"); + if(!$fh = fopen($img['file'],'w') ){ + throw new Kohana_Exception('save-rrd-image', $img['file']); + } + fwrite($fh, $data); + fclose($fh); + if (function_exists('imagecreatefrompng')) { + $image = imagecreatefrompng($img['file']); + imagepng($image, $img['file']); + list ($img['width'], $img['height'], $img['type'], $img['attr']) = getimagesize($img['file']); + }else{ + throw new Kohana_Exception('error.gd-missing'); + } + return $img; + } + + + private function format_rrd_debug($data) { + $data = preg_replace('/(HRULE|VDEF|DEF|CDEF|GPRINT|LINE|AREA|COMMENT)/',"\n\${1}", $data); + return $data; + } +} diff --git a/share/pnp/application/models/system.php b/share/pnp/application/models/system.php new file mode 100644 index 0000000..fa291ad --- /dev/null +++ b/share/pnp/application/models/system.php @@ -0,0 +1,14 @@ + ORD_u) { + $this->error('Illegal character in ASCII85Decode.'); + } + + $chn[$state++] = $ch - ORD_exclmark; + + if ($state == 5) { + $state = 0; + $r = 0; + for ($j = 0; $j < 5; ++$j) + $r = $r * 85 + $chn[$j]; + $out .= chr($r >> 24); + $out .= chr($r >> 16); + $out .= chr($r >> 8); + $out .= chr($r); + } + } + $r = 0; + + if ($state == 1) + $this->error('Illegal length in ASCII85Decode.'); + if ($state == 2) { + $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85; + $out .= chr($r >> 24); + } + else if ($state == 3) { + $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85; + $out .= chr($r >> 24); + $out .= chr($r >> 16); + } + else if ($state == 4) { + $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ; + $out .= chr($r >> 24); + $out .= chr($r >> 16); + $out .= chr($r >> 8); + } + + return $out; + } + + function encode($in) { + $this->error("ASCII85 encoding not implemented."); + } +} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php b/share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php new file mode 100644 index 0000000..596de48 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/filters/FilterASCII85_FPDI.php @@ -0,0 +1,33 @@ +fpdi =& $fpdi; + } + + function error($msg) { + $this->fpdi->error($msg); + } +} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/filters/FilterLZW.php b/share/pnp/application/vendor/fpdf/filters/FilterLZW.php new file mode 100644 index 0000000..5867603 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/filters/FilterLZW.php @@ -0,0 +1,154 @@ +error('LZW flavour not supported.'); + } + + $this->initsTable(); + + $this->data = $data; + $this->dataLength = strlen($data); + + // Initialize pointers + $this->bytePointer = 0; + $this->bitPointer = 0; + + $this->nextData = 0; + $this->nextBits = 0; + + $oldCode = 0; + + $string = ''; + $uncompData = ''; + + while (($code = $this->getNextCode()) != 257) { + if ($code == 256) { + $this->initsTable(); + $code = $this->getNextCode(); + + if ($code == 257) { + break; + } + + $uncompData .= $this->sTable[$code]; + $oldCode = $code; + + } else { + + if ($code < $this->tIdx) { + $string = $this->sTable[$code]; + $uncompData .= $string; + + $this->addStringToTable($this->sTable[$oldCode], $string[0]); + $oldCode = $code; + } else { + $string = $this->sTable[$oldCode]; + $string = $string.$string[0]; + $uncompData .= $string; + + $this->addStringToTable($string); + $oldCode = $code; + } + } + } + + return $uncompData; + } + + + /** + * Initialize the string table. + */ + function initsTable() { + $this->sTable = array(); + + for ($i = 0; $i < 256; $i++) + $this->sTable[$i] = chr($i); + + $this->tIdx = 258; + $this->bitsToGet = 9; + } + + /** + * Add a new string to the string table. + */ + function addStringToTable ($oldString, $newString='') { + $string = $oldString.$newString; + + // Add this new String to the table + $this->sTable[$this->tIdx++] = $string; + + if ($this->tIdx == 511) { + $this->bitsToGet = 10; + } else if ($this->tIdx == 1023) { + $this->bitsToGet = 11; + } else if ($this->tIdx == 2047) { + $this->bitsToGet = 12; + } + } + + // Returns the next 9, 10, 11 or 12 bits + function getNextCode() { + if ($this->bytePointer == $this->dataLength) { + return 257; + } + + $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff); + $this->nextBits += 8; + + if ($this->nextBits < $this->bitsToGet) { + $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff); + $this->nextBits += 8; + } + + $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet-9]; + $this->nextBits -= $this->bitsToGet; + + return $code; + } + + function encode($in) { + $this->error("LZW encoding not implemented."); + } +} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php b/share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php new file mode 100644 index 0000000..540c22c --- /dev/null +++ b/share/pnp/application/vendor/fpdf/filters/FilterLZW_FPDI.php @@ -0,0 +1,33 @@ +fpdi =& $fpdi; + } + + function error($msg) { + $this->fpdi->error($msg); + } +} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/font/courier.php b/share/pnp/application/vendor/fpdf/font/courier.php new file mode 100644 index 0000000..4c009f3 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/courier.php @@ -0,0 +1,7 @@ + diff --git a/share/pnp/application/vendor/fpdf/font/helvetica.php b/share/pnp/application/vendor/fpdf/font/helvetica.php new file mode 100644 index 0000000..8fa7683 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/helvetica.php @@ -0,0 +1,15 @@ +278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, + chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584, + ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667, + 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, + 'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833, + 'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556, + chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, + chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, + chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667, + chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556, + chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); +?> diff --git a/share/pnp/application/vendor/fpdf/font/helveticab.php b/share/pnp/application/vendor/fpdf/font/helveticab.php new file mode 100644 index 0000000..a8473c9 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/helveticab.php @@ -0,0 +1,15 @@ +278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, + chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584, + ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722, + 'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, + 'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889, + 'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556, + chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, + chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, + chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, + chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611, + chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556); +?> diff --git a/share/pnp/application/vendor/fpdf/font/helveticabi.php b/share/pnp/application/vendor/fpdf/font/helveticabi.php new file mode 100644 index 0000000..4137953 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/helveticabi.php @@ -0,0 +1,15 @@ +278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, + chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584, + ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722, + 'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, + 'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889, + 'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556, + chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, + chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, + chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, + chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611, + chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556); +?> diff --git a/share/pnp/application/vendor/fpdf/font/helveticai.php b/share/pnp/application/vendor/fpdf/font/helveticai.php new file mode 100644 index 0000000..d5bb6e0 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/helveticai.php @@ -0,0 +1,15 @@ +278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278, + chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584, + ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667, + 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944, + 'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833, + 'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556, + chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, + chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333, + chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667, + chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556, + chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); +?> diff --git a/share/pnp/application/vendor/fpdf/font/symbol.php b/share/pnp/application/vendor/fpdf/font/symbol.php new file mode 100644 index 0000000..b556ed8 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/symbol.php @@ -0,0 +1,15 @@ +250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, + chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>713,'#'=>500,'$'=>549,'%'=>833,'&'=>778,'\''=>439,'('=>333,')'=>333,'*'=>500,'+'=>549, + ','=>250,'-'=>549,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>549,'='=>549,'>'=>549,'?'=>444,'@'=>549,'A'=>722, + 'B'=>667,'C'=>722,'D'=>612,'E'=>611,'F'=>763,'G'=>603,'H'=>722,'I'=>333,'J'=>631,'K'=>722,'L'=>686,'M'=>889,'N'=>722,'O'=>722,'P'=>768,'Q'=>741,'R'=>556,'S'=>592,'T'=>611,'U'=>690,'V'=>439,'W'=>768, + 'X'=>645,'Y'=>795,'Z'=>611,'['=>333,'\\'=>863,']'=>333,'^'=>658,'_'=>500,'`'=>500,'a'=>631,'b'=>549,'c'=>549,'d'=>494,'e'=>439,'f'=>521,'g'=>411,'h'=>603,'i'=>329,'j'=>603,'k'=>549,'l'=>549,'m'=>576, + 'n'=>521,'o'=>549,'p'=>549,'q'=>521,'r'=>549,'s'=>603,'t'=>439,'u'=>576,'v'=>713,'w'=>686,'x'=>493,'y'=>686,'z'=>494,'{'=>480,'|'=>200,'}'=>480,'~'=>549,chr(127)=>0,chr(128)=>0,chr(129)=>0,chr(130)=>0,chr(131)=>0, + chr(132)=>0,chr(133)=>0,chr(134)=>0,chr(135)=>0,chr(136)=>0,chr(137)=>0,chr(138)=>0,chr(139)=>0,chr(140)=>0,chr(141)=>0,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0, + chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>750,chr(161)=>620,chr(162)=>247,chr(163)=>549,chr(164)=>167,chr(165)=>713,chr(166)=>500,chr(167)=>753,chr(168)=>753,chr(169)=>753,chr(170)=>753,chr(171)=>1042,chr(172)=>987,chr(173)=>603,chr(174)=>987,chr(175)=>603, + chr(176)=>400,chr(177)=>549,chr(178)=>411,chr(179)=>549,chr(180)=>549,chr(181)=>713,chr(182)=>494,chr(183)=>460,chr(184)=>549,chr(185)=>549,chr(186)=>549,chr(187)=>549,chr(188)=>1000,chr(189)=>603,chr(190)=>1000,chr(191)=>658,chr(192)=>823,chr(193)=>686,chr(194)=>795,chr(195)=>987,chr(196)=>768,chr(197)=>768, + chr(198)=>823,chr(199)=>768,chr(200)=>768,chr(201)=>713,chr(202)=>713,chr(203)=>713,chr(204)=>713,chr(205)=>713,chr(206)=>713,chr(207)=>713,chr(208)=>768,chr(209)=>713,chr(210)=>790,chr(211)=>790,chr(212)=>890,chr(213)=>823,chr(214)=>549,chr(215)=>250,chr(216)=>713,chr(217)=>603,chr(218)=>603,chr(219)=>1042, + chr(220)=>987,chr(221)=>603,chr(222)=>987,chr(223)=>603,chr(224)=>494,chr(225)=>329,chr(226)=>790,chr(227)=>790,chr(228)=>786,chr(229)=>713,chr(230)=>384,chr(231)=>384,chr(232)=>384,chr(233)=>384,chr(234)=>384,chr(235)=>384,chr(236)=>494,chr(237)=>494,chr(238)=>494,chr(239)=>494,chr(240)=>0,chr(241)=>329, + chr(242)=>274,chr(243)=>686,chr(244)=>686,chr(245)=>686,chr(246)=>384,chr(247)=>384,chr(248)=>384,chr(249)=>384,chr(250)=>384,chr(251)=>384,chr(252)=>494,chr(253)=>494,chr(254)=>494,chr(255)=>0); +?> diff --git a/share/pnp/application/vendor/fpdf/font/times.php b/share/pnp/application/vendor/fpdf/font/times.php new file mode 100644 index 0000000..b9be1b2 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/times.php @@ -0,0 +1,15 @@ +250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, + chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>408,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>180,'('=>333,')'=>333,'*'=>500,'+'=>564, + ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>564,'='=>564,'>'=>564,'?'=>444,'@'=>921,'A'=>722, + 'B'=>667,'C'=>667,'D'=>722,'E'=>611,'F'=>556,'G'=>722,'H'=>722,'I'=>333,'J'=>389,'K'=>722,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>556,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>722,'W'=>944, + 'X'=>722,'Y'=>722,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>469,'_'=>500,'`'=>333,'a'=>444,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778, + 'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>333,'s'=>389,'t'=>278,'u'=>500,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>480,'|'=>200,'}'=>480,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, + chr(132)=>444,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>889,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>444,chr(148)=>444,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>980, + chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>200,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>564,chr(173)=>333,chr(174)=>760,chr(175)=>333, + chr(176)=>400,chr(177)=>564,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>453,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>444,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, + chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>564,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>722,chr(222)=>556,chr(223)=>500,chr(224)=>444,chr(225)=>444,chr(226)=>444,chr(227)=>444,chr(228)=>444,chr(229)=>444,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500, + chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>564,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>500,chr(254)=>500,chr(255)=>500); +?> diff --git a/share/pnp/application/vendor/fpdf/font/timesb.php b/share/pnp/application/vendor/fpdf/font/timesb.php new file mode 100644 index 0000000..c3eb9fa --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/timesb.php @@ -0,0 +1,15 @@ +250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, + chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>555,'#'=>500,'$'=>500,'%'=>1000,'&'=>833,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570, + ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>930,'A'=>722, + 'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>778,'I'=>389,'J'=>500,'K'=>778,'L'=>667,'M'=>944,'N'=>722,'O'=>778,'P'=>611,'Q'=>778,'R'=>722,'S'=>556,'T'=>667,'U'=>722,'V'=>722,'W'=>1000, + 'X'=>722,'Y'=>722,'Z'=>667,'['=>333,'\\'=>278,']'=>333,'^'=>581,'_'=>500,'`'=>333,'a'=>500,'b'=>556,'c'=>444,'d'=>556,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>333,'k'=>556,'l'=>278,'m'=>833, + 'n'=>556,'o'=>500,'p'=>556,'q'=>556,'r'=>444,'s'=>389,'t'=>333,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>394,'|'=>220,'}'=>394,'~'=>520,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, + chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>667,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, + chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>300,chr(171)=>500,chr(172)=>570,chr(173)=>333,chr(174)=>747,chr(175)=>333, + chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>556,chr(182)=>540,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>330,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722, + chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>570,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>722,chr(222)=>611,chr(223)=>556,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556, + chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500); +?> diff --git a/share/pnp/application/vendor/fpdf/font/timesbi.php b/share/pnp/application/vendor/fpdf/font/timesbi.php new file mode 100644 index 0000000..161f630 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/timesbi.php @@ -0,0 +1,15 @@ +250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, + chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>389,'"'=>555,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570, + ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>832,'A'=>667, + 'B'=>667,'C'=>667,'D'=>722,'E'=>667,'F'=>667,'G'=>722,'H'=>778,'I'=>389,'J'=>500,'K'=>667,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>611,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>667,'W'=>889, + 'X'=>667,'Y'=>611,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>570,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778, + 'n'=>556,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>556,'v'=>444,'w'=>667,'x'=>500,'y'=>444,'z'=>389,'{'=>348,'|'=>220,'}'=>348,'~'=>570,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, + chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000, + chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>389,chr(159)=>611,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>266,chr(171)=>500,chr(172)=>606,chr(173)=>333,chr(174)=>747,chr(175)=>333, + chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>576,chr(182)=>500,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>300,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667, + chr(198)=>944,chr(199)=>667,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>570,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>611,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556, + chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>444,chr(254)=>500,chr(255)=>444); +?> diff --git a/share/pnp/application/vendor/fpdf/font/timesi.php b/share/pnp/application/vendor/fpdf/font/timesi.php new file mode 100644 index 0000000..de171fd --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/timesi.php @@ -0,0 +1,15 @@ +250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250, + chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>420,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>214,'('=>333,')'=>333,'*'=>500,'+'=>675, + ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>675,'='=>675,'>'=>675,'?'=>500,'@'=>920,'A'=>611, + 'B'=>611,'C'=>667,'D'=>722,'E'=>611,'F'=>611,'G'=>722,'H'=>722,'I'=>333,'J'=>444,'K'=>667,'L'=>556,'M'=>833,'N'=>667,'O'=>722,'P'=>611,'Q'=>722,'R'=>611,'S'=>500,'T'=>556,'U'=>722,'V'=>611,'W'=>833, + 'X'=>611,'Y'=>556,'Z'=>556,'['=>389,'\\'=>278,']'=>389,'^'=>422,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>278,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>444,'l'=>278,'m'=>722, + 'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>500,'v'=>444,'w'=>667,'x'=>444,'y'=>444,'z'=>389,'{'=>400,'|'=>275,'}'=>400,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500, + chr(132)=>556,chr(133)=>889,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>500,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>556,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>556,chr(148)=>556,chr(149)=>350,chr(150)=>500,chr(151)=>889,chr(152)=>333,chr(153)=>980, + chr(154)=>389,chr(155)=>333,chr(156)=>667,chr(157)=>350,chr(158)=>389,chr(159)=>556,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>275,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>675,chr(173)=>333,chr(174)=>760,chr(175)=>333, + chr(176)=>400,chr(177)=>675,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>523,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>611,chr(193)=>611,chr(194)=>611,chr(195)=>611,chr(196)=>611,chr(197)=>611, + chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>667,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>675,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722, + chr(220)=>722,chr(221)=>556,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500, + chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>675,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>444,chr(254)=>500,chr(255)=>444); +?> diff --git a/share/pnp/application/vendor/fpdf/font/zapfdingbats.php b/share/pnp/application/vendor/fpdf/font/zapfdingbats.php new file mode 100644 index 0000000..f2bdfd5 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/font/zapfdingbats.php @@ -0,0 +1,15 @@ +0,chr(1)=>0,chr(2)=>0,chr(3)=>0,chr(4)=>0,chr(5)=>0,chr(6)=>0,chr(7)=>0,chr(8)=>0,chr(9)=>0,chr(10)=>0,chr(11)=>0,chr(12)=>0,chr(13)=>0,chr(14)=>0,chr(15)=>0,chr(16)=>0,chr(17)=>0,chr(18)=>0,chr(19)=>0,chr(20)=>0,chr(21)=>0, + chr(22)=>0,chr(23)=>0,chr(24)=>0,chr(25)=>0,chr(26)=>0,chr(27)=>0,chr(28)=>0,chr(29)=>0,chr(30)=>0,chr(31)=>0,' '=>278,'!'=>974,'"'=>961,'#'=>974,'$'=>980,'%'=>719,'&'=>789,'\''=>790,'('=>791,')'=>690,'*'=>960,'+'=>939, + ','=>549,'-'=>855,'.'=>911,'/'=>933,'0'=>911,'1'=>945,'2'=>974,'3'=>755,'4'=>846,'5'=>762,'6'=>761,'7'=>571,'8'=>677,'9'=>763,':'=>760,';'=>759,'<'=>754,'='=>494,'>'=>552,'?'=>537,'@'=>577,'A'=>692, + 'B'=>786,'C'=>788,'D'=>788,'E'=>790,'F'=>793,'G'=>794,'H'=>816,'I'=>823,'J'=>789,'K'=>841,'L'=>823,'M'=>833,'N'=>816,'O'=>831,'P'=>923,'Q'=>744,'R'=>723,'S'=>749,'T'=>790,'U'=>792,'V'=>695,'W'=>776, + 'X'=>768,'Y'=>792,'Z'=>759,'['=>707,'\\'=>708,']'=>682,'^'=>701,'_'=>826,'`'=>815,'a'=>789,'b'=>789,'c'=>707,'d'=>687,'e'=>696,'f'=>689,'g'=>786,'h'=>787,'i'=>713,'j'=>791,'k'=>785,'l'=>791,'m'=>873, + 'n'=>761,'o'=>762,'p'=>762,'q'=>759,'r'=>759,'s'=>892,'t'=>892,'u'=>788,'v'=>784,'w'=>438,'x'=>138,'y'=>277,'z'=>415,'{'=>392,'|'=>392,'}'=>668,'~'=>668,chr(127)=>0,chr(128)=>390,chr(129)=>390,chr(130)=>317,chr(131)=>317, + chr(132)=>276,chr(133)=>276,chr(134)=>509,chr(135)=>509,chr(136)=>410,chr(137)=>410,chr(138)=>234,chr(139)=>234,chr(140)=>334,chr(141)=>334,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0, + chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>0,chr(161)=>732,chr(162)=>544,chr(163)=>544,chr(164)=>910,chr(165)=>667,chr(166)=>760,chr(167)=>760,chr(168)=>776,chr(169)=>595,chr(170)=>694,chr(171)=>626,chr(172)=>788,chr(173)=>788,chr(174)=>788,chr(175)=>788, + chr(176)=>788,chr(177)=>788,chr(178)=>788,chr(179)=>788,chr(180)=>788,chr(181)=>788,chr(182)=>788,chr(183)=>788,chr(184)=>788,chr(185)=>788,chr(186)=>788,chr(187)=>788,chr(188)=>788,chr(189)=>788,chr(190)=>788,chr(191)=>788,chr(192)=>788,chr(193)=>788,chr(194)=>788,chr(195)=>788,chr(196)=>788,chr(197)=>788, + chr(198)=>788,chr(199)=>788,chr(200)=>788,chr(201)=>788,chr(202)=>788,chr(203)=>788,chr(204)=>788,chr(205)=>788,chr(206)=>788,chr(207)=>788,chr(208)=>788,chr(209)=>788,chr(210)=>788,chr(211)=>788,chr(212)=>894,chr(213)=>838,chr(214)=>1016,chr(215)=>458,chr(216)=>748,chr(217)=>924,chr(218)=>748,chr(219)=>918, + chr(220)=>927,chr(221)=>928,chr(222)=>928,chr(223)=>834,chr(224)=>873,chr(225)=>828,chr(226)=>924,chr(227)=>924,chr(228)=>917,chr(229)=>930,chr(230)=>931,chr(231)=>463,chr(232)=>883,chr(233)=>836,chr(234)=>836,chr(235)=>867,chr(236)=>867,chr(237)=>696,chr(238)=>696,chr(239)=>874,chr(240)=>0,chr(241)=>874, + chr(242)=>760,chr(243)=>946,chr(244)=>771,chr(245)=>865,chr(246)=>771,chr(247)=>888,chr(248)=>967,chr(249)=>888,chr(250)=>831,chr(251)=>873,chr(252)=>927,chr(253)=>970,chr(254)=>918,chr(255)=>0); +?> diff --git a/share/pnp/application/vendor/fpdf/fpdf.php b/share/pnp/application/vendor/fpdf/fpdf.php new file mode 100644 index 0000000..51f5d59 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/fpdf.php @@ -0,0 +1,1732 @@ +_dochecks(); + //Initialization of properties + $this->page=0; + $this->n=2; + $this->buffer=''; + $this->pages=array(); + $this->PageSizes=array(); + $this->state=0; + $this->fonts=array(); + $this->FontFiles=array(); + $this->diffs=array(); + $this->images=array(); + $this->links=array(); + $this->InHeader=false; + $this->InFooter=false; + $this->lasth=0; + $this->FontFamily=''; + $this->FontStyle=''; + $this->FontSizePt=12; + $this->underline=false; + $this->DrawColor='0 G'; + $this->FillColor='0 g'; + $this->TextColor='0 g'; + $this->ColorFlag=false; + $this->ws=0; + //Standard fonts + $this->CoreFonts=array('courier'=>'Courier', 'courierB'=>'Courier-Bold', 'courierI'=>'Courier-Oblique', 'courierBI'=>'Courier-BoldOblique', + 'helvetica'=>'Helvetica', 'helveticaB'=>'Helvetica-Bold', 'helveticaI'=>'Helvetica-Oblique', 'helveticaBI'=>'Helvetica-BoldOblique', + 'times'=>'Times-Roman', 'timesB'=>'Times-Bold', 'timesI'=>'Times-Italic', 'timesBI'=>'Times-BoldItalic', + 'symbol'=>'Symbol', 'zapfdingbats'=>'ZapfDingbats'); + //Scale factor + if($unit=='pt') + $this->k=1; + elseif($unit=='mm') + $this->k=72/25.4; + elseif($unit=='cm') + $this->k=72/2.54; + elseif($unit=='in') + $this->k=72; + else + $this->Error('Incorrect unit: '.$unit); + //Page format + $this->PageFormats=array('a3'=>array(841.89,1190.55), 'a4'=>array(595.28,841.89), 'a5'=>array(420.94,595.28), + 'letter'=>array(612,792), 'legal'=>array(612,1008)); + if(is_string($format)) + $format=$this->_getpageformat($format); + $this->DefPageFormat=$format; + $this->CurPageFormat=$format; + //Page orientation + $orientation=strtolower($orientation); + if($orientation=='p' || $orientation=='portrait') + { + $this->DefOrientation='P'; + $this->w=$this->DefPageFormat[0]; + $this->h=$this->DefPageFormat[1]; + } + elseif($orientation=='l' || $orientation=='landscape') + { + $this->DefOrientation='L'; + $this->w=$this->DefPageFormat[1]; + $this->h=$this->DefPageFormat[0]; + } + else + $this->Error('Incorrect orientation: '.$orientation); + $this->CurOrientation=$this->DefOrientation; + $this->wPt=$this->w*$this->k; + $this->hPt=$this->h*$this->k; + //Page margins (1 cm) + $margin=28.35/$this->k; + $this->SetMargins($margin,$margin); + //Interior cell margin (1 mm) + $this->cMargin=$margin/10; + //Line width (0.2 mm) + $this->LineWidth=.567/$this->k; + //Automatic page break + $this->SetAutoPageBreak(true,2*$margin); + //Full width display mode + $this->SetDisplayMode('fullwidth'); + //Enable compression + $this->SetCompression(true); + //Set default PDF version number + $this->PDFVersion='1.3'; +} + +function SetMargins($left, $top, $right=null) +{ + //Set left, top and right margins + $this->lMargin=$left; + $this->tMargin=$top; + if($right===null) + $right=$left; + $this->rMargin=$right; +} + +function SetLeftMargin($margin) +{ + //Set left margin + $this->lMargin=$margin; + if($this->page>0 && $this->x<$margin) + $this->x=$margin; +} + +function SetTopMargin($margin) +{ + //Set top margin + $this->tMargin=$margin; +} + +function SetRightMargin($margin) +{ + //Set right margin + $this->rMargin=$margin; +} + +function SetAutoPageBreak($auto, $margin=0) +{ + //Set auto page break mode and triggering margin + $this->AutoPageBreak=$auto; + $this->bMargin=$margin; + $this->PageBreakTrigger=$this->h-$margin; +} + +function SetDisplayMode($zoom, $layout='continuous') +{ + //Set display mode in viewer + if($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom)) + $this->ZoomMode=$zoom; + else + $this->Error('Incorrect zoom display mode: '.$zoom); + if($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default') + $this->LayoutMode=$layout; + else + $this->Error('Incorrect layout display mode: '.$layout); +} + +function SetCompression($compress) +{ + //Set page compression + if(function_exists('gzcompress')) + $this->compress=$compress; + else + $this->compress=false; +} + +function SetTitle($title, $isUTF8=false) +{ + //Title of document + if($isUTF8) + $title=$this->_UTF8toUTF16($title); + $this->title=$title; +} + +function SetSubject($subject, $isUTF8=false) +{ + //Subject of document + if($isUTF8) + $subject=$this->_UTF8toUTF16($subject); + $this->subject=$subject; +} + +function SetAuthor($author, $isUTF8=false) +{ + //Author of document + if($isUTF8) + $author=$this->_UTF8toUTF16($author); + $this->author=$author; +} + +function SetKeywords($keywords, $isUTF8=false) +{ + //Keywords of document + if($isUTF8) + $keywords=$this->_UTF8toUTF16($keywords); + $this->keywords=$keywords; +} + +function SetCreator($creator, $isUTF8=false) +{ + //Creator of document + if($isUTF8) + $creator=$this->_UTF8toUTF16($creator); + $this->creator=$creator; +} + +function AliasNbPages($alias='{nb}') +{ + //Define an alias for total number of pages + $this->AliasNbPages=$alias; +} + +function Error($msg) +{ + //Fatal error + die('FPDF error: '.$msg); +} + +function Open() +{ + //Begin document + $this->state=1; +} + +function Close() +{ + //Terminate document + if($this->state==3) + return; + if($this->page==0) + $this->AddPage(); + //Page footer + $this->InFooter=true; + $this->Footer(); + $this->InFooter=false; + //Close page + $this->_endpage(); + //Close document + $this->_enddoc(); +} + +function AddPage($orientation='', $format='') +{ + //Start a new page + if($this->state==0) + $this->Open(); + $family=$this->FontFamily; + $style=$this->FontStyle.($this->underline ? 'U' : ''); + $size=$this->FontSizePt; + $lw=$this->LineWidth; + $dc=$this->DrawColor; + $fc=$this->FillColor; + $tc=$this->TextColor; + $cf=$this->ColorFlag; + if($this->page>0) + { + //Page footer + $this->InFooter=true; + $this->Footer(); + $this->InFooter=false; + //Close page + $this->_endpage(); + } + //Start new page + $this->_beginpage($orientation,$format); + //Set line cap style to square + $this->_out('2 J'); + //Set line width + $this->LineWidth=$lw; + $this->_out(sprintf('%.2F w',$lw*$this->k)); + //Set font + if($family) + $this->SetFont($family,$style,$size); + //Set colors + $this->DrawColor=$dc; + if($dc!='0 G') + $this->_out($dc); + $this->FillColor=$fc; + if($fc!='0 g') + $this->_out($fc); + $this->TextColor=$tc; + $this->ColorFlag=$cf; + //Page header + $this->InHeader=true; + $this->Header(); + $this->InHeader=false; + //Restore line width + if($this->LineWidth!=$lw) + { + $this->LineWidth=$lw; + $this->_out(sprintf('%.2F w',$lw*$this->k)); + } + //Restore font + if($family) + $this->SetFont($family,$style,$size); + //Restore colors + if($this->DrawColor!=$dc) + { + $this->DrawColor=$dc; + $this->_out($dc); + } + if($this->FillColor!=$fc) + { + $this->FillColor=$fc; + $this->_out($fc); + } + $this->TextColor=$tc; + $this->ColorFlag=$cf; +} + +function Header() +{ + //To be implemented in your own inherited class +} + +function Footer() +{ + //To be implemented in your own inherited class +} + +function PageNo() +{ + //Get current page number + return $this->page; +} + +function SetDrawColor($r, $g=null, $b=null) +{ + //Set color for all stroking operations + if(($r==0 && $g==0 && $b==0) || $g===null) + $this->DrawColor=sprintf('%.3F G',$r/255); + else + $this->DrawColor=sprintf('%.3F %.3F %.3F RG',$r/255,$g/255,$b/255); + if($this->page>0) + $this->_out($this->DrawColor); +} + +function SetFillColor($r, $g=null, $b=null) +{ + //Set color for all filling operations + if(($r==0 && $g==0 && $b==0) || $g===null) + $this->FillColor=sprintf('%.3F g',$r/255); + else + $this->FillColor=sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255); + $this->ColorFlag=($this->FillColor!=$this->TextColor); + if($this->page>0) + $this->_out($this->FillColor); +} + +function SetTextColor($r, $g=null, $b=null) +{ + //Set color for text + if(($r==0 && $g==0 && $b==0) || $g===null) + $this->TextColor=sprintf('%.3F g',$r/255); + else + $this->TextColor=sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255); + $this->ColorFlag=($this->FillColor!=$this->TextColor); +} + +function GetStringWidth($s) +{ + //Get width of a string in the current font + $s=(string)$s; + $cw=&$this->CurrentFont['cw']; + $w=0; + $l=strlen($s); + for($i=0;$i<$l;$i++) + $w+=$cw[$s[$i]]; + return $w*$this->FontSize/1000; +} + +function SetLineWidth($width) +{ + //Set line width + $this->LineWidth=$width; + if($this->page>0) + $this->_out(sprintf('%.2F w',$width*$this->k)); +} + +function Line($x1, $y1, $x2, $y2) +{ + //Draw a line + $this->_out(sprintf('%.2F %.2F m %.2F %.2F l S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k)); +} + +function Rect($x, $y, $w, $h, $style='') +{ + //Draw a rectangle + if($style=='F') + $op='f'; + elseif($style=='FD' || $style=='DF') + $op='B'; + else + $op='S'; + $this->_out(sprintf('%.2F %.2F %.2F %.2F re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op)); +} + +function AddFont($family, $style='', $file='') +{ + //Add a TrueType or Type1 font + $family=strtolower($family); + if($file=='') + $file=str_replace(' ','',$family).strtolower($style).'.php'; + if($family=='arial') + $family='helvetica'; + $style=strtoupper($style); + if($style=='IB') + $style='BI'; + $fontkey=$family.$style; + if(isset($this->fonts[$fontkey])) + return; + include($this->_getfontpath().$file); + if(!isset($name)) + $this->Error('Could not include font definition file'); + $i=count($this->fonts)+1; + $this->fonts[$fontkey]=array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'enc'=>$enc, 'file'=>$file); + if($diff) + { + //Search existing encodings + $d=0; + $nb=count($this->diffs); + for($i=1;$i<=$nb;$i++) + { + if($this->diffs[$i]==$diff) + { + $d=$i; + break; + } + } + if($d==0) + { + $d=$nb+1; + $this->diffs[$d]=$diff; + } + $this->fonts[$fontkey]['diff']=$d; + } + if($file) + { + if($type=='TrueType') + $this->FontFiles[$file]=array('length1'=>$originalsize); + else + $this->FontFiles[$file]=array('length1'=>$size1, 'length2'=>$size2); + } +} + +function SetFont($family, $style='', $size=0) +{ + //Select a font; size given in points + global $fpdf_charwidths; + + $family=strtolower($family); + if($family=='') + $family=$this->FontFamily; + if($family=='arial') + $family='helvetica'; + elseif($family=='symbol' || $family=='zapfdingbats') + $style=''; + $style=strtoupper($style); + if(strpos($style,'U')!==false) + { + $this->underline=true; + $style=str_replace('U','',$style); + } + else + $this->underline=false; + if($style=='IB') + $style='BI'; + if($size==0) + $size=$this->FontSizePt; + //Test if font is already selected + if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size) + return; + //Test if used for the first time + $fontkey=$family.$style; + if(!isset($this->fonts[$fontkey])) + { + //Check if one of the standard fonts + if(isset($this->CoreFonts[$fontkey])) + { + if(!isset($fpdf_charwidths[$fontkey])) + { + //Load metric file + $file=$family; + if($family=='times' || $family=='helvetica') + $file.=strtolower($style); + include($this->_getfontpath().$file.'.php'); + if(!isset($fpdf_charwidths[$fontkey])) + $this->Error('Could not include font metric file'); + } + $i=count($this->fonts)+1; + $name=$this->CoreFonts[$fontkey]; + $cw=$fpdf_charwidths[$fontkey]; + $this->fonts[$fontkey]=array('i'=>$i, 'type'=>'core', 'name'=>$name, 'up'=>-100, 'ut'=>50, 'cw'=>$cw); + } + else + $this->Error('Undefined font: '.$family.' '.$style); + } + //Select it + $this->FontFamily=$family; + $this->FontStyle=$style; + $this->FontSizePt=$size; + $this->FontSize=$size/$this->k; + $this->CurrentFont=&$this->fonts[$fontkey]; + if($this->page>0) + $this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt)); +} + +function SetFontSize($size) +{ + //Set font size in points + if($this->FontSizePt==$size) + return; + $this->FontSizePt=$size; + $this->FontSize=$size/$this->k; + if($this->page>0) + $this->_out(sprintf('BT /F%d %.2F Tf ET',$this->CurrentFont['i'],$this->FontSizePt)); +} + +function AddLink() +{ + //Create a new internal link + $n=count($this->links)+1; + $this->links[$n]=array(0, 0); + return $n; +} + +function SetLink($link, $y=0, $page=-1) +{ + //Set destination of internal link + if($y==-1) + $y=$this->y; + if($page==-1) + $page=$this->page; + $this->links[$link]=array($page, $y); +} + +function Link($x, $y, $w, $h, $link) +{ + //Put a link on the page + $this->PageLinks[$this->page][]=array($x*$this->k, $this->hPt-$y*$this->k, $w*$this->k, $h*$this->k, $link); +} + +function Text($x, $y, $txt) +{ + //Output a string + $s=sprintf('BT %.2F %.2F Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt)); + if($this->underline && $txt!='') + $s.=' '.$this->_dounderline($x,$y,$txt); + if($this->ColorFlag) + $s='q '.$this->TextColor.' '.$s.' Q'; + $this->_out($s); +} + +function AcceptPageBreak() +{ + //Accept automatic page break or not + return $this->AutoPageBreak; +} + +function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') +{ + //Output a cell + $k=$this->k; + if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak()) + { + //Automatic page break + $x=$this->x; + $ws=$this->ws; + if($ws>0) + { + $this->ws=0; + $this->_out('0 Tw'); + } + $this->AddPage($this->CurOrientation,$this->CurPageFormat); + $this->x=$x; + if($ws>0) + { + $this->ws=$ws; + $this->_out(sprintf('%.3F Tw',$ws*$k)); + } + } + if($w==0) + $w=$this->w-$this->rMargin-$this->x; + $s=''; + if($fill || $border==1) + { + if($fill) + $op=($border==1) ? 'B' : 'f'; + else + $op='S'; + $s=sprintf('%.2F %.2F %.2F %.2F re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op); + } + if(is_string($border)) + { + $x=$this->x; + $y=$this->y; + if(strpos($border,'L')!==false) + $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k); + if(strpos($border,'T')!==false) + $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k); + if(strpos($border,'R')!==false) + $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k); + if(strpos($border,'B')!==false) + $s.=sprintf('%.2F %.2F m %.2F %.2F l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k); + } + if($txt!=='') + { + if($align=='R') + $dx=$w-$this->cMargin-$this->GetStringWidth($txt); + elseif($align=='C') + $dx=($w-$this->GetStringWidth($txt))/2; + else + $dx=$this->cMargin; + if($this->ColorFlag) + $s.='q '.$this->TextColor.' '; + $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt))); + $s.=sprintf('BT %.2F %.2F Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2); + if($this->underline) + $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt); + if($this->ColorFlag) + $s.=' Q'; + if($link) + $this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link); + } + if($s) + $this->_out($s); + $this->lasth=$h; + if($ln>0) + { + //Go to next line + $this->y+=$h; + if($ln==1) + $this->x=$this->lMargin; + } + else + $this->x+=$w; +} + +function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false) +{ + //Output text with automatic or explicit line breaks + $cw=&$this->CurrentFont['cw']; + if($w==0) + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $s=str_replace("\r",'',$txt); + $nb=strlen($s); + if($nb>0 && $s[$nb-1]=="\n") + $nb--; + $b=0; + if($border) + { + if($border==1) + { + $border='LTRB'; + $b='LRT'; + $b2='LR'; + } + else + { + $b2=''; + if(strpos($border,'L')!==false) + $b2.='L'; + if(strpos($border,'R')!==false) + $b2.='R'; + $b=(strpos($border,'T')!==false) ? $b2.'T' : $b2; + } + } + $sep=-1; + $i=0; + $j=0; + $l=0; + $ns=0; + $nl=1; + while($i<$nb) + { + //Get next character + $c=$s[$i]; + if($c=="\n") + { + //Explicit line break + if($this->ws>0) + { + $this->ws=0; + $this->_out('0 Tw'); + } + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + $i++; + $sep=-1; + $j=$i; + $l=0; + $ns=0; + $nl++; + if($border && $nl==2) + $b=$b2; + continue; + } + if($c==' ') + { + $sep=$i; + $ls=$l; + $ns++; + } + $l+=$cw[$c]; + if($l>$wmax) + { + //Automatic line break + if($sep==-1) + { + if($i==$j) + $i++; + if($this->ws>0) + { + $this->ws=0; + $this->_out('0 Tw'); + } + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + } + else + { + if($align=='J') + { + $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0; + $this->_out(sprintf('%.3F Tw',$this->ws*$this->k)); + } + $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill); + $i=$sep+1; + } + $sep=-1; + $j=$i; + $l=0; + $ns=0; + $nl++; + if($border && $nl==2) + $b=$b2; + } + else + $i++; + } + //Last chunk + if($this->ws>0) + { + $this->ws=0; + $this->_out('0 Tw'); + } + if($border && strpos($border,'B')!==false) + $b.='B'; + $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill); + $this->x=$this->lMargin; +} + +function Write($h, $txt, $link='') +{ + //Output text in flowing mode + $cw=&$this->CurrentFont['cw']; + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $s=str_replace("\r",'',$txt); + $nb=strlen($s); + $sep=-1; + $i=0; + $j=0; + $l=0; + $nl=1; + while($i<$nb) + { + //Get next character + $c=$s[$i]; + if($c=="\n") + { + //Explicit line break + $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link); + $i++; + $sep=-1; + $j=$i; + $l=0; + if($nl==1) + { + $this->x=$this->lMargin; + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + } + $nl++; + continue; + } + if($c==' ') + $sep=$i; + $l+=$cw[$c]; + if($l>$wmax) + { + //Automatic line break + if($sep==-1) + { + if($this->x>$this->lMargin) + { + //Move to next line + $this->x=$this->lMargin; + $this->y+=$h; + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + $i++; + $nl++; + continue; + } + if($i==$j) + $i++; + $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link); + } + else + { + $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link); + $i=$sep+1; + } + $sep=-1; + $j=$i; + $l=0; + if($nl==1) + { + $this->x=$this->lMargin; + $w=$this->w-$this->rMargin-$this->x; + $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; + } + $nl++; + } + else + $i++; + } + //Last chunk + if($i!=$j) + $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link); +} + +function Ln($h=null) +{ + //Line feed; default value is last cell height + $this->x=$this->lMargin; + if($h===null) + $this->y+=$this->lasth; + else + $this->y+=$h; +} + +function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='') +{ + //Put an image on the page + if(!isset($this->images[$file])) + { + //First use of this image, get info + if($type=='') + { + $pos=strrpos($file,'.'); + if(!$pos) + $this->Error('Image file has no extension and no type was specified: '.$file); + $type=substr($file,$pos+1); + } + $type=strtolower($type); + if($type=='jpeg') + $type='jpg'; + $mtd='_parse'.$type; + if(!method_exists($this,$mtd)) + $this->Error('Unsupported image type: '.$type); + $info=$this->$mtd($file); + $info['i']=count($this->images)+1; + $this->images[$file]=$info; + } + else + $info=$this->images[$file]; + //Automatic width and height calculation if needed + if($w==0 && $h==0) + { + //Put image at 72 dpi + $w=$info['w']/$this->k; + $h=$info['h']/$this->k; + } + elseif($w==0) + $w=$h*$info['w']/$info['h']; + elseif($h==0) + $h=$w*$info['h']/$info['w']; + //Flowing mode + if($y===null) + { + if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak()) + { + //Automatic page break + $x2=$this->x; + $this->AddPage($this->CurOrientation,$this->CurPageFormat); + $this->x=$x2; + } + $y=$this->y; + $this->y+=$h; + } + if($x===null) + $x=$this->x; + $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i'])); + if($link) + $this->Link($x,$y,$w,$h,$link); +} + +function GetX() +{ + //Get x position + return $this->x; +} + +function SetX($x) +{ + //Set x position + if($x>=0) + $this->x=$x; + else + $this->x=$this->w+$x; +} + +function GetY() +{ + //Get y position + return $this->y; +} + +function SetY($y) +{ + //Set y position and reset x + $this->x=$this->lMargin; + if($y>=0) + $this->y=$y; + else + $this->y=$this->h+$y; +} + +function SetXY($x, $y) +{ + //Set x and y positions + $this->SetY($y); + $this->SetX($x); +} + +function Output($name='', $dest='') +{ + //Output PDF to some destination + if($this->state<3) + $this->Close(); + $dest=strtoupper($dest); + if($dest=='') + { + if($name=='') + { + $name='doc.pdf'; + $dest='I'; + } + else + $dest='F'; + } + switch($dest) + { + case 'I': + //Send to standard output + if(ob_get_length()) + $this->Error('Some data has already been output, can\'t send PDF file'); + if(php_sapi_name()!='cli') + { + //We send to a browser + header('Content-Type: application/pdf'); + if(headers_sent()) + $this->Error('Some data has already been output, can\'t send PDF file'); + header('Content-Length: '.strlen($this->buffer)); + header('Content-Disposition: inline; filename="'.$name.'"'); + header('Cache-Control: private, max-age=0, must-revalidate'); + header('Pragma: public'); + ini_set('zlib.output_compression','0'); + } + echo $this->buffer; + break; + case 'D': + //Download file + if(ob_get_length()) + $this->Error('Some data has already been output, can\'t send PDF file'); + header('Content-Type: application/x-download'); + if(headers_sent()) + $this->Error('Some data has already been output, can\'t send PDF file'); + header('Content-Length: '.strlen($this->buffer)); + header('Content-Disposition: attachment; filename="'.$name.'"'); + header('Cache-Control: private, max-age=0, must-revalidate'); + header('Pragma: public'); + ini_set('zlib.output_compression','0'); + echo $this->buffer; + break; + case 'F': + //Save to local file + $f=fopen($name,'wb'); + if(!$f) + $this->Error('Unable to create output file: '.$name); + fwrite($f,$this->buffer,strlen($this->buffer)); + fclose($f); + break; + case 'S': + //Return as a string + return $this->buffer; + default: + $this->Error('Incorrect output destination: '.$dest); + } + return ''; +} + +/******************************************************************************* +* * +* Protected methods * +* * +*******************************************************************************/ +function _dochecks() +{ + //Check availability of %F + if(sprintf('%.1F',1.0)!='1.0') + $this->Error('This version of PHP is not supported'); + //Check mbstring overloading + if(ini_get('mbstring.func_overload') & 2) + $this->Error('mbstring overloading must be disabled'); + //Disable runtime magic quotes + if(get_magic_quotes_runtime()) + @set_magic_quotes_runtime(0); +} + +function _getpageformat($format) +{ + $format=strtolower($format); + if(!isset($this->PageFormats[$format])) + $this->Error('Unknown page format: '.$format); + $a=$this->PageFormats[$format]; + return array($a[0]/$this->k, $a[1]/$this->k); +} + +function _getfontpath() +{ + if(!defined('FPDF_FONTPATH') && is_dir(dirname(__FILE__).'/font')) + define('FPDF_FONTPATH',dirname(__FILE__).'/font/'); + return defined('FPDF_FONTPATH') ? FPDF_FONTPATH : ''; +} + +function _beginpage($orientation, $format) +{ + $this->page++; + $this->pages[$this->page]=''; + $this->state=2; + $this->x=$this->lMargin; + $this->y=$this->tMargin; + $this->FontFamily=''; + //Check page size + if($orientation=='') + $orientation=$this->DefOrientation; + else + $orientation=strtoupper($orientation[0]); + if($format=='') + $format=$this->DefPageFormat; + else + { + if(is_string($format)) + $format=$this->_getpageformat($format); + } + if($orientation!=$this->CurOrientation || $format[0]!=$this->CurPageFormat[0] || $format[1]!=$this->CurPageFormat[1]) + { + //New size + if($orientation=='P') + { + $this->w=$format[0]; + $this->h=$format[1]; + } + else + { + $this->w=$format[1]; + $this->h=$format[0]; + } + $this->wPt=$this->w*$this->k; + $this->hPt=$this->h*$this->k; + $this->PageBreakTrigger=$this->h-$this->bMargin; + $this->CurOrientation=$orientation; + $this->CurPageFormat=$format; + } + if($orientation!=$this->DefOrientation || $format[0]!=$this->DefPageFormat[0] || $format[1]!=$this->DefPageFormat[1]) + $this->PageSizes[$this->page]=array($this->wPt, $this->hPt); +} + +function _endpage() +{ + $this->state=1; +} + +function _escape($s) +{ + //Escape special characters in strings + $s=str_replace('\\','\\\\',$s); + $s=str_replace('(','\\(',$s); + $s=str_replace(')','\\)',$s); + $s=str_replace("\r",'\\r',$s); + return $s; +} + +function _textstring($s) +{ + //Format a text string + return '('.$this->_escape($s).')'; +} + +function _UTF8toUTF16($s) +{ + //Convert UTF-8 to UTF-16BE with BOM + $res="\xFE\xFF"; + $nb=strlen($s); + $i=0; + while($i<$nb) + { + $c1=ord($s[$i++]); + if($c1>=224) + { + //3-byte character + $c2=ord($s[$i++]); + $c3=ord($s[$i++]); + $res.=chr((($c1 & 0x0F)<<4) + (($c2 & 0x3C)>>2)); + $res.=chr((($c2 & 0x03)<<6) + ($c3 & 0x3F)); + } + elseif($c1>=192) + { + //2-byte character + $c2=ord($s[$i++]); + $res.=chr(($c1 & 0x1C)>>2); + $res.=chr((($c1 & 0x03)<<6) + ($c2 & 0x3F)); + } + else + { + //Single-byte character + $res.="\0".chr($c1); + } + } + return $res; +} + +function _dounderline($x, $y, $txt) +{ + //Underline text + $up=$this->CurrentFont['up']; + $ut=$this->CurrentFont['ut']; + $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' '); + return sprintf('%.2F %.2F %.2F %.2F re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt); +} + +function _parsejpg($file) +{ + //Extract info from a JPEG file + $a=GetImageSize($file); + if(!$a) + $this->Error('Missing or incorrect image file: '.$file); + if($a[2]!=2) + $this->Error('Not a JPEG file: '.$file); + if(!isset($a['channels']) || $a['channels']==3) + $colspace='DeviceRGB'; + elseif($a['channels']==4) + $colspace='DeviceCMYK'; + else + $colspace='DeviceGray'; + $bpc=isset($a['bits']) ? $a['bits'] : 8; + //Read whole file + $f=fopen($file,'rb'); + $data=''; + while(!feof($f)) + $data.=fread($f,8192); + fclose($f); + return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data); +} + +function _parsepng($file) +{ + //Extract info from a PNG file + $f=fopen($file,'rb'); + if(!$f) + $this->Error('Can\'t open image file: '.$file); + //Check signature + if($this->_readstream($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) + $this->Error('Not a PNG file: '.$file); + //Read header chunk + $this->_readstream($f,4); + if($this->_readstream($f,4)!='IHDR') + $this->Error('Incorrect PNG file: '.$file); + $w=$this->_readint($f); + $h=$this->_readint($f); + $bpc=ord($this->_readstream($f,1)); + if($bpc>8) + $this->Error('16-bit depth not supported: '.$file); + $ct=ord($this->_readstream($f,1)); + if($ct==0) + $colspace='DeviceGray'; + elseif($ct==2) + $colspace='DeviceRGB'; + elseif($ct==3) + $colspace='Indexed'; + else + $this->Error('Alpha channel not supported: '.$file); + if(ord($this->_readstream($f,1))!=0) + $this->Error('Unknown compression method: '.$file); + if(ord($this->_readstream($f,1))!=0) + $this->Error('Unknown filter method: '.$file); + if(ord($this->_readstream($f,1))!=0) + $this->Error('Interlacing not supported: '.$file); + $this->_readstream($f,4); + $parms='/DecodeParms <>'; + //Scan chunks looking for palette, transparency and image data + $pal=''; + $trns=''; + $data=''; + do + { + $n=$this->_readint($f); + $type=$this->_readstream($f,4); + if($type=='PLTE') + { + //Read palette + $pal=$this->_readstream($f,$n); + $this->_readstream($f,4); + } + elseif($type=='tRNS') + { + //Read transparency info + $t=$this->_readstream($f,$n); + if($ct==0) + $trns=array(ord(substr($t,1,1))); + elseif($ct==2) + $trns=array(ord(substr($t,1,1)), ord(substr($t,3,1)), ord(substr($t,5,1))); + else + { + $pos=strpos($t,chr(0)); + if($pos!==false) + $trns=array($pos); + } + $this->_readstream($f,4); + } + elseif($type=='IDAT') + { + //Read image data block + $data.=$this->_readstream($f,$n); + $this->_readstream($f,4); + } + elseif($type=='IEND') + break; + else + $this->_readstream($f,$n+4); + } + while($n); + if($colspace=='Indexed' && empty($pal)) + $this->Error('Missing palette in '.$file); + fclose($f); + return array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'parms'=>$parms, 'pal'=>$pal, 'trns'=>$trns, 'data'=>$data); +} + +function _readstream($f, $n) +{ + //Read n bytes from stream + $res=''; + while($n>0 && !feof($f)) + { + $s=fread($f,$n); + if($s===false) + $this->Error('Error while reading stream'); + $n-=strlen($s); + $res.=$s; + } + if($n>0) + $this->Error('Unexpected end of stream'); + return $res; +} + +function _readint($f) +{ + //Read a 4-byte integer from stream + $a=unpack('Ni',$this->_readstream($f,4)); + return $a['i']; +} + +function _parsegif($file) +{ + //Extract info from a GIF file (via PNG conversion) + if(!function_exists('imagepng')) + $this->Error('GD extension is required for GIF support'); + if(!function_exists('imagecreatefromgif')) + $this->Error('GD has no GIF read support'); + $im=imagecreatefromgif($file); + if(!$im) + $this->Error('Missing or incorrect image file: '.$file); + imageinterlace($im,0); + $tmp=tempnam('.','gif'); + if(!$tmp) + $this->Error('Unable to create a temporary file'); + if(!imagepng($im,$tmp)) + $this->Error('Error while saving to temporary file'); + imagedestroy($im); + $info=$this->_parsepng($tmp); + unlink($tmp); + return $info; +} + +function _newobj() +{ + //Begin a new object + $this->n++; + $this->offsets[$this->n]=strlen($this->buffer); + $this->_out($this->n.' 0 obj'); +} + +function _putstream($s) +{ + $this->_out('stream'); + $this->_out($s); + $this->_out('endstream'); +} + +function _out($s) +{ + //Add a line to the document + if($this->state==2) + $this->pages[$this->page].=$s."\n"; + else + $this->buffer.=$s."\n"; +} + +function _putpages() +{ + $nb=$this->page; + if(!empty($this->AliasNbPages)) + { + //Replace number of pages + for($n=1;$n<=$nb;$n++) + $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]); + } + if($this->DefOrientation=='P') + { + $wPt=$this->DefPageFormat[0]*$this->k; + $hPt=$this->DefPageFormat[1]*$this->k; + } + else + { + $wPt=$this->DefPageFormat[1]*$this->k; + $hPt=$this->DefPageFormat[0]*$this->k; + } + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + for($n=1;$n<=$nb;$n++) + { + //Page + $this->_newobj(); + $this->_out('<_out('/Parent 1 0 R'); + if(isset($this->PageSizes[$n])) + $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageSizes[$n][0],$this->PageSizes[$n][1])); + $this->_out('/Resources 2 0 R'); + if(isset($this->PageLinks[$n])) + { + //Links + $annots='/Annots ['; + foreach($this->PageLinks[$n] as $pl) + { + $rect=sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]); + $annots.='<_textstring($pl[4]).'>>>>'; + else + { + $l=$this->links[$pl[4]]; + $h=isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt; + $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',1+2*$l[0],$h-$l[1]*$this->k); + } + } + $this->_out($annots.']'); + } + $this->_out('/Contents '.($this->n+1).' 0 R>>'); + $this->_out('endobj'); + //Page content + $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n]; + $this->_newobj(); + $this->_out('<<'.$filter.'/Length '.strlen($p).'>>'); + $this->_putstream($p); + $this->_out('endobj'); + } + //Pages root + $this->offsets[1]=strlen($this->buffer); + $this->_out('1 0 obj'); + $this->_out('<_out($kids.']'); + $this->_out('/Count '.$nb); + $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt)); + $this->_out('>>'); + $this->_out('endobj'); +} + +function _putfonts() +{ + $nf=$this->n; + foreach($this->diffs as $diff) + { + //Encodings + $this->_newobj(); + $this->_out('<>'); + $this->_out('endobj'); + } + foreach($this->FontFiles as $file=>$info) + { + //Font file embedding + $this->_newobj(); + $this->FontFiles[$file]['n']=$this->n; + $font=''; + $f=fopen($this->_getfontpath().$file,'rb',1); + if(!$f) + $this->Error('Font file not found'); + while(!feof($f)) + $font.=fread($f,8192); + fclose($f); + $compressed=(substr($file,-2)=='.z'); + if(!$compressed && isset($info['length2'])) + { + $header=(ord($font[0])==128); + if($header) + { + //Strip first binary header + $font=substr($font,6); + } + if($header && ord($font[$info['length1']])==128) + { + //Strip second binary header + $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6); + } + } + $this->_out('<_out('/Filter /FlateDecode'); + $this->_out('/Length1 '.$info['length1']); + if(isset($info['length2'])) + $this->_out('/Length2 '.$info['length2'].' /Length3 0'); + $this->_out('>>'); + $this->_putstream($font); + $this->_out('endobj'); + } + foreach($this->fonts as $k=>$font) + { + //Font objects + $this->fonts[$k]['n']=$this->n+1; + $type=$font['type']; + $name=$font['name']; + if($type=='core') + { + //Standard font + $this->_newobj(); + $this->_out('<_out('/BaseFont /'.$name); + $this->_out('/Subtype /Type1'); + if($name!='Symbol' && $name!='ZapfDingbats') + $this->_out('/Encoding /WinAnsiEncoding'); + $this->_out('>>'); + $this->_out('endobj'); + } + elseif($type=='Type1' || $type=='TrueType') + { + //Additional Type1 or TrueType font + $this->_newobj(); + $this->_out('<_out('/BaseFont /'.$name); + $this->_out('/Subtype /'.$type); + $this->_out('/FirstChar 32 /LastChar 255'); + $this->_out('/Widths '.($this->n+1).' 0 R'); + $this->_out('/FontDescriptor '.($this->n+2).' 0 R'); + if($font['enc']) + { + if(isset($font['diff'])) + $this->_out('/Encoding '.($nf+$font['diff']).' 0 R'); + else + $this->_out('/Encoding /WinAnsiEncoding'); + } + $this->_out('>>'); + $this->_out('endobj'); + //Widths + $this->_newobj(); + $cw=&$font['cw']; + $s='['; + for($i=32;$i<=255;$i++) + $s.=$cw[chr($i)].' '; + $this->_out($s.']'); + $this->_out('endobj'); + //Descriptor + $this->_newobj(); + $s='<$v) + $s.=' /'.$k.' '.$v; + $file=$font['file']; + if($file) + $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R'; + $this->_out($s.'>>'); + $this->_out('endobj'); + } + else + { + //Allow for additional types + $mtd='_put'.strtolower($type); + if(!method_exists($this,$mtd)) + $this->Error('Unsupported font type: '.$type); + $this->$mtd($font); + } + } +} + +function _putimages() +{ + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->images); + while(list($file,$info)=each($this->images)) + { + $this->_newobj(); + $this->images[$file]['n']=$this->n; + $this->_out('<_out('/Subtype /Image'); + $this->_out('/Width '.$info['w']); + $this->_out('/Height '.$info['h']); + if($info['cs']=='Indexed') + $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]'); + else + { + $this->_out('/ColorSpace /'.$info['cs']); + if($info['cs']=='DeviceCMYK') + $this->_out('/Decode [1 0 1 0 1 0 1 0]'); + } + $this->_out('/BitsPerComponent '.$info['bpc']); + if(isset($info['f'])) + $this->_out('/Filter /'.$info['f']); + if(isset($info['parms'])) + $this->_out($info['parms']); + if(isset($info['trns']) && is_array($info['trns'])) + { + $trns=''; + for($i=0;$i_out('/Mask ['.$trns.']'); + } + $this->_out('/Length '.strlen($info['data']).'>>'); + $this->_putstream($info['data']); + unset($this->images[$file]['data']); + $this->_out('endobj'); + //Palette + if($info['cs']=='Indexed') + { + $this->_newobj(); + $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal']; + $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>'); + $this->_putstream($pal); + $this->_out('endobj'); + } + } +} + +function _putxobjectdict() +{ + foreach($this->images as $image) + $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); +} + +function _putresourcedict() +{ + $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); + $this->_out('/Font <<'); + foreach($this->fonts as $font) + $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); + $this->_out('>>'); + $this->_out('/XObject <<'); + $this->_putxobjectdict(); + $this->_out('>>'); +} + +function _putresources() +{ + $this->_putfonts(); + $this->_putimages(); + //Resource dictionary + $this->offsets[2]=strlen($this->buffer); + $this->_out('2 0 obj'); + $this->_out('<<'); + $this->_putresourcedict(); + $this->_out('>>'); + $this->_out('endobj'); +} + +function _putinfo() +{ + $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION)); + if(!empty($this->title)) + $this->_out('/Title '.$this->_textstring($this->title)); + if(!empty($this->subject)) + $this->_out('/Subject '.$this->_textstring($this->subject)); + if(!empty($this->author)) + $this->_out('/Author '.$this->_textstring($this->author)); + if(!empty($this->keywords)) + $this->_out('/Keywords '.$this->_textstring($this->keywords)); + if(!empty($this->creator)) + $this->_out('/Creator '.$this->_textstring($this->creator)); + $this->_out('/CreationDate '.$this->_textstring('D:'.@date('YmdHis'))); +} + +function _putcatalog() +{ + $this->_out('/Type /Catalog'); + $this->_out('/Pages 1 0 R'); + if($this->ZoomMode=='fullpage') + $this->_out('/OpenAction [3 0 R /Fit]'); + elseif($this->ZoomMode=='fullwidth') + $this->_out('/OpenAction [3 0 R /FitH null]'); + elseif($this->ZoomMode=='real') + $this->_out('/OpenAction [3 0 R /XYZ null null 1]'); + elseif(!is_string($this->ZoomMode)) + $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']'); + if($this->LayoutMode=='single') + $this->_out('/PageLayout /SinglePage'); + elseif($this->LayoutMode=='continuous') + $this->_out('/PageLayout /OneColumn'); + elseif($this->LayoutMode=='two') + $this->_out('/PageLayout /TwoColumnLeft'); +} + +function _putheader() +{ + $this->_out('%PDF-'.$this->PDFVersion); +} + +function _puttrailer() +{ + $this->_out('/Size '.($this->n+1)); + $this->_out('/Root '.$this->n.' 0 R'); + $this->_out('/Info '.($this->n-1).' 0 R'); +} + +function _enddoc() +{ + $this->_putheader(); + $this->_putpages(); + $this->_putresources(); + //Info + $this->_newobj(); + $this->_out('<<'); + $this->_putinfo(); + $this->_out('>>'); + $this->_out('endobj'); + //Catalog + $this->_newobj(); + $this->_out('<<'); + $this->_putcatalog(); + $this->_out('>>'); + $this->_out('endobj'); + //Cross-ref + $o=strlen($this->buffer); + $this->_out('xref'); + $this->_out('0 '.($this->n+1)); + $this->_out('0000000000 65535 f '); + for($i=1;$i<=$this->n;$i++) + $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i])); + //Trailer + $this->_out('trailer'); + $this->_out('<<'); + $this->_puttrailer(); + $this->_out('>>'); + $this->_out('startxref'); + $this->_out($o); + $this->_out('%%EOF'); + $this->state=3; +} +//End of class +} + +//Handle special IE contype request +if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']=='contype') +{ + header('Content-Type: application/pdf'); + exit; +} + +?> diff --git a/share/pnp/application/vendor/fpdf/fpdf_tpl.php b/share/pnp/application/vendor/fpdf/fpdf_tpl.php new file mode 100644 index 0000000..d829ff1 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/fpdf_tpl.php @@ -0,0 +1,409 @@ +page <= 0) + $this->error("You have to add a page to fpdf first!"); + + if ($x == null) + $x = 0; + if ($y == null) + $y = 0; + if ($w == null) + $w = $this->w; + if ($h == null) + $h = $this->h; + + // Save settings + $this->tpl++; + $tpl =& $this->tpls[$this->tpl]; + $tpl = array( + 'o_x' => $this->x, + 'o_y' => $this->y, + 'o_AutoPageBreak' => $this->AutoPageBreak, + 'o_bMargin' => $this->bMargin, + 'o_tMargin' => $this->tMargin, + 'o_lMargin' => $this->lMargin, + 'o_rMargin' => $this->rMargin, + 'o_h' => $this->h, + 'o_w' => $this->w, + 'buffer' => '', + 'x' => $x, + 'y' => $y, + 'w' => $w, + 'h' => $h + ); + + $this->SetAutoPageBreak(false); + + // Define own high and width to calculate possitions correct + $this->h = $h; + $this->w = $w; + + $this->_intpl = true; + $this->SetXY($x+$this->lMargin, $y+$this->tMargin); + $this->SetRightMargin($this->w-$w+$this->rMargin); + + return $this->tpl; + } + + /** + * End Template + * + * This method ends a template and reset initiated variables on beginTemplate. + * + * @return mixed If a template is opened, the ID is returned. If not a false is returned. + */ + function endTemplate() { + if ($this->_intpl) { + $this->_intpl = false; + $tpl =& $this->tpls[$this->tpl]; + $this->SetXY($tpl['o_x'], $tpl['o_y']); + $this->tMargin = $tpl['o_tMargin']; + $this->lMargin = $tpl['o_lMargin']; + $this->rMargin = $tpl['o_rMargin']; + $this->h = $tpl['o_h']; + $this->w = $tpl['o_w']; + $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']); + + return $this->tpl; + } else { + return false; + } + } + + /** + * Use a Template in current Page or other Template + * + * You can use a template in a page or in another template. + * You can give the used template a new size like you use the Image()-method. + * All parameters are optional. The width or height is calculated automaticaly + * if one is given. If no parameter is given the origin size as defined in + * beginTemplate() is used. + * The calculated or used width and height are returned as an array. + * + * @param int $tplidx A valid template-Id + * @param int $_x The x-position + * @param int $_y The y-position + * @param int $_w The new width of the template + * @param int $_h The new height of the template + * @retrun array The height and width of the template + */ + function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0) { + if ($this->page <= 0) + $this->error("You have to add a page to fpdf first!"); + + if (!isset($this->tpls[$tplidx])) + $this->error("Template does not exist!"); + + if ($this->_intpl) { + $this->_res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx]; + } + + $tpl =& $this->tpls[$tplidx]; + $w = $tpl['w']; + $h = $tpl['h']; + + if ($_x == null) + $_x = 0; + if ($_y == null) + $_y = 0; + + $_x += $tpl['x']; + $_y += $tpl['y']; + + $wh = $this->getTemplateSize($tplidx, $_w, $_h); + $_w = $wh['w']; + $_h = $wh['h']; + + $tData = array( + 'x' => $this->x, + 'y' => $this->y, + 'w' => $_w, + 'h' => $_h, + 'scaleX' => ($_w/$w), + 'scaleY' => ($_h/$h), + 'tx' => $_x, + 'ty' => ($this->h-$_y-$_h), + 'lty' => ($this->h-$_y-$_h) - ($this->h-$h) * ($_h/$h) + ); + + $this->_out(sprintf("q %.4F 0 0 %.4F %.4F %.4F cm", $tData['scaleX'], $tData['scaleY'], $tData['tx']*$this->k, $tData['ty']*$this->k)); // Translate + $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); + + $this->lastUsedTemplateData = $tData; + + return array("w" => $_w, "h" => $_h); + } + + /** + * Get The calculated Size of a Template + * + * If one size is given, this method calculates the other one. + * + * @param int $tplidx A valid template-Id + * @param int $_w The width of the template + * @param int $_h The height of the template + * @return array The height and width of the template + */ + function getTemplateSize($tplidx, $_w=0, $_h=0) { + if (!$this->tpls[$tplidx]) + return false; + + $tpl =& $this->tpls[$tplidx]; + $w = $tpl['w']; + $h = $tpl['h']; + + if ($_w == 0 and $_h == 0) { + $_w = $w; + $_h = $h; + } + + if($_w==0) + $_w = $_h*$w/$h; + if($_h==0) + $_h = $_w*$h/$w; + + return array("w" => $_w, "h" => $_h); + } + + /** + * See FPDF/TCPDF-Documentation ;-) + */ + function SetFont($family, $style='', $size=0, $fontfile='') { + if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 3) { + $this->Error('More than 3 arguments for the SetFont method are only available in TCPDF.'); + } + /** + * force the resetting of font changes in a template + */ + if ($this->_intpl) + $this->FontFamily = ''; + + parent::SetFont($family, $style, $size, $fontfile); + + $fontkey = $this->FontFamily.$this->FontStyle; + + if ($this->_intpl) { + $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; + } else { + $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey]; + } + } + + /** + * See FPDF/TCPDF-Documentation ;-) + */ + function Image($file, $x, $y, $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0) { + if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 7) { + $this->Error('More than 7 arguments for the Image method are only available in TCPDF.'); + } + + parent::Image($file, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $ismask, $imgmask, $border); + if ($this->_intpl) { + $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file]; + } else { + $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file]; + } + } + + /** + * See FPDF-Documentation ;-) + * + * AddPage is not available when you're "in" a template. + */ + function AddPage($orientation='', $format='') { + if ($this->_intpl) + $this->Error('Adding pages in templates isn\'t possible!'); + parent::AddPage($orientation, $format); + } + + /** + * Preserve adding Links in Templates ...won't work + */ + function Link($x, $y, $w, $h, $link, $spaces=0) { + if (!is_subclass_of($this, 'TCPDF') && func_num_args() > 5) { + $this->Error('More than 7 arguments for the Image method are only available in TCPDF.'); + } + + if ($this->_intpl) + $this->Error('Using links in templates aren\'t possible!'); + parent::Link($x, $y, $w, $h, $link, $spaces); + } + + function AddLink() { + if ($this->_intpl) + $this->Error('Adding links in templates aren\'t possible!'); + return parent::AddLink(); + } + + function SetLink($link, $y=0, $page=-1) { + if ($this->_intpl) + $this->Error('Setting links in templates aren\'t possible!'); + parent::SetLink($link, $y, $page); + } + + /** + * Private Method that writes the form xobjects + */ + function _putformxobjects() { + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->tpls); + foreach($this->tpls AS $tplidx => $tpl) { + + $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + $this->_newobj(); + $this->tpls[$tplidx]['n'] = $this->n; + $this->_out('<<'.$filter.'/Type /XObject'); + $this->_out('/Subtype /Form'); + $this->_out('/FormType 1'); + $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', + // llx + $tpl['x'], + // lly + -$tpl['y'], + // urx + ($tpl['w']+$tpl['x'])*$this->k, + // ury + ($tpl['h']-$tpl['y'])*$this->k + )); + + if ($tpl['x'] != 0 || $tpl['y'] != 0) { + $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', + -$tpl['x']*$this->k*2, $tpl['y']*$this->k*2 + )); + } + + $this->_out('/Resources '); + + $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { + $this->_out('/Font <<'); + foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) + $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); + $this->_out('>>'); + } + if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || + isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) + { + $this->_out('/XObject <<'); + if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { + foreach($this->_res['tpl'][$tplidx]['images'] as $image) + $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); + } + if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { + foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) + $this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R'); + } + $this->_out('>>'); + } + $this->_out('>>'); + + $this->_out('/Length '.strlen($p).' >>'); + $this->_putstream($p); + $this->_out('endobj'); + } + } + + /** + * Overwritten to add _putformxobjects() after _putimages() + * + */ + function _putimages() { + parent::_putimages(); + $this->_putformxobjects(); + } + + function _putxobjectdict() { + parent::_putxobjectdict(); + + if (count($this->tpls)) { + foreach($this->tpls as $tplidx => $tpl) { + $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n'])); + } + } + } + + /** + * Private Method + */ + function _out($s) { + if ($this->state==2 && $this->_intpl) { + $this->tpls[$this->tpl]['buffer'] .= $s."\n"; + } else { + parent::_out($s); + } + } +} diff --git a/share/pnp/application/vendor/fpdf/fpdi.php b/share/pnp/application/vendor/fpdf/fpdi.php new file mode 100644 index 0000000..bd47686 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/fpdi.php @@ -0,0 +1,505 @@ +current_filename = $filename; + $fn =& $this->current_filename; + + if (!isset($this->parsers[$fn])) + $this->parsers[$fn] = new fpdi_pdf_parser($fn, $this); + $this->current_parser =& $this->parsers[$fn]; + + return $this->parsers[$fn]->getPageCount(); + } + + /** + * Import a page + * + * @param int $pageno pagenumber + * @return int Index of imported page - to use with fpdf_tpl::useTemplate() + */ + function importPage($pageno, $boxName='/CropBox') { + if ($this->_intpl) { + return $this->error('Please import the desired pages before creating a new template.'); + } + + $fn =& $this->current_filename; + + // check if page already imported + $pageKey = $fn.((int)$pageno).$boxName; + if (isset($this->_importedPages[$pageKey])) + return $this->_importedPages[$pageKey]; + + $parser =& $this->parsers[$fn]; + $parser->setPageno($pageno); + + $this->tpl++; + $this->tpls[$this->tpl] = array(); + $tpl =& $this->tpls[$this->tpl]; + $tpl['parser'] =& $parser; + $tpl['resources'] = $parser->getPageResources(); + $tpl['buffer'] = $parser->getContent(); + + if (!in_array($boxName, $parser->availableBoxes)) + return $this->Error(sprintf('Unknown box: %s', $boxName)); + $pageboxes = $parser->getPageBoxes($pageno); + + /** + * MediaBox + * CropBox: Default -> MediaBox + * BleedBox: Default -> CropBox + * TrimBox: Default -> CropBox + * ArtBox: Default -> CropBox + */ + if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) + $boxName = '/CropBox'; + if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox') + $boxName = '/MediaBox'; + + if (!isset($pageboxes[$boxName])) + return false; + $this->lastUsedPageBox = $boxName; + + $box = $pageboxes[$boxName]; + $tpl['box'] = $box; + + // To build an array that can be used by PDF_TPL::useTemplate() + $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl],$box); + + // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects() + $tpl['x'] = 0; + $tpl['y'] = 0; + + $page =& $parser->pages[$parser->pageno]; + + // handle rotated pages + $rotation = $parser->getPageRotation($pageno); + $tpl['_rotationAngle'] = 0; + if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) { + $steps = $angle / 90; + + $_w = $tpl['w']; + $_h = $tpl['h']; + $tpl['w'] = $steps % 2 == 0 ? $_w : $_h; + $tpl['h'] = $steps % 2 == 0 ? $_h : $_w; + + $tpl['_rotationAngle'] = $angle*-1; + } + + $this->_importedPages[$pageKey] = $this->tpl; + + return $this->tpl; + } + + function getLastUsedPageBox() { + return $this->lastUsedPageBox; + } + + function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0, $adjustPageSize=false) { + if ($adjustPageSize == true && is_null($_x) && is_null($_y)) { + $size = $this->getTemplateSize($tplidx, $_w, $_h); + $format = array($size['w'], $size['h']); + if ($format[0]!=$this->CurPageFormat[0] || $format[1]!=$this->CurPageFormat[1]) { + $this->w=$format[0]; + $this->h=$format[1]; + $this->wPt=$this->w*$this->k; + $this->hPt=$this->h*$this->k; + $this->PageBreakTrigger=$this->h-$this->bMargin; + $this->CurPageFormat=$format; + $this->PageSizes[$this->page]=array($this->wPt, $this->hPt); + } + } + + $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values + $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); + $this->_out('Q'); + return $s; + } + + /** + * Private method, that rebuilds all needed objects of source files + */ + function _putimportedobjects() { + if (is_array($this->parsers) && count($this->parsers) > 0) { + foreach($this->parsers AS $filename => $p) { + $this->current_parser =& $this->parsers[$filename]; + if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { + while(($n = key($this->_obj_stack[$filename])) !== null) { + $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->_obj_stack[$filename][$n][1]); + + $this->_newobj($this->_obj_stack[$filename][$n][0]); + + if ($nObj[0] == PDF_TYPE_STREAM) { + $this->pdf_write_value ($nObj); + } else { + $this->pdf_write_value ($nObj[1]); + } + + $this->_out('endobj'); + $this->_obj_stack[$filename][$n] = null; // free memory + unset($this->_obj_stack[$filename][$n]); + reset($this->_obj_stack[$filename]); + } + } + } + } + } + + + /** + * Private Method that writes the form xobjects + */ + function _putformxobjects() { + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->tpls); + foreach($this->tpls AS $tplidx => $tpl) { + $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + $this->_newobj(); + $cN = $this->n; // TCPDF/Protection: rem current "n" + + $this->tpls[$tplidx]['n'] = $this->n; + $this->_out('<<'.$filter.'/Type /XObject'); + $this->_out('/Subtype /Form'); + $this->_out('/FormType 1'); + + $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', + (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x'])*$this->k, + (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y'])*$this->k, + (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x'])*$this->k, + (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h']-$tpl['y'])*$this->k + )); + + $c = 1; + $s = 0; + $tx = 0; + $ty = 0; + + if (isset($tpl['box'])) { + $tx = -$tpl['box']['llx']; + $ty = -$tpl['box']['lly']; + + if ($tpl['_rotationAngle'] <> 0) { + $angle = $tpl['_rotationAngle'] * M_PI/180; + $c=cos($angle); + $s=sin($angle); + + switch($tpl['_rotationAngle']) { + case -90: + $tx = -$tpl['box']['lly']; + $ty = $tpl['box']['urx']; + break; + case -180: + $tx = $tpl['box']['urx']; + $ty = $tpl['box']['ury']; + break; + case -270: + $tx = $tpl['box']['ury']; + $ty = 0; + break; + } + } + } else if ($tpl['x'] != 0 || $tpl['y'] != 0) { + $tx = -$tpl['x']*2; + $ty = $tpl['y']*2; + } + + $tx *= $this->k; + $ty *= $this->k; + + if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) { + $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]', + $c, $s, -$s, $c, $tx, $ty + )); + } + + $this->_out('/Resources '); + + if (isset($tpl['resources'])) { + $this->current_parser =& $tpl['parser']; + $this->pdf_write_value($tpl['resources']); // "n" will be changed + } else { + $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { + $this->_out('/Font <<'); + foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) + $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R'); + $this->_out('>>'); + } + if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || + isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) + { + $this->_out('/XObject <<'); + if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { + foreach($this->_res['tpl'][$tplidx]['images'] as $image) + $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R'); + } + if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { + foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) + $this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R'); + } + $this->_out('>>'); + } + $this->_out('>>'); + } + + $nN = $this->n; // TCPDF: rem new "n" + $this->n = $cN; // TCPDF: reset to current "n" + $this->_out('/Length '.strlen($p).' >>'); + $this->_putstream($p); + $this->_out('endobj'); + $this->n = $nN; // TCPDF: reset to new "n" + } + + $this->_putimportedobjects(); + } + + /** + * Rewritten to handle existing own defined objects + */ + function _newobj($obj_id=false,$onlynewobj=false) { + if (!$obj_id) { + $obj_id = ++$this->n; + } + + //Begin a new object + if (!$onlynewobj) { + $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); + $this->_out($obj_id.' 0 obj'); + $this->_current_obj_id = $obj_id; // for later use with encryption + } + return $obj_id; + } + + /** + * Writes a value + * Needed to rebuild the source document + * + * @param mixed $value A PDF-Value. Structure of values see cases in this method + */ + function pdf_write_value(&$value) + { + if (is_subclass_of($this, 'TCPDF')) { + parent::pdf_write_value($value); + } + + switch ($value[0]) { + + case PDF_TYPE_TOKEN : + $this->_straightOut($value[1] . ' '); + break; + case PDF_TYPE_NUMERIC : + case PDF_TYPE_REAL : + if (is_float($value[1]) && $value[1] != 0) { + $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') .' '); + } else { + $this->_straightOut($value[1] . ' '); + } + break; + + case PDF_TYPE_ARRAY : + + // An array. Output the proper + // structure and move on. + + $this->_straightOut('['); + for ($i = 0; $i < count($value[1]); $i++) { + $this->pdf_write_value($value[1][$i]); + } + + $this->_out(']'); + break; + + case PDF_TYPE_DICTIONARY : + + // A dictionary. + $this->_straightOut('<<'); + + reset ($value[1]); + + while (list($k, $v) = each($value[1])) { + $this->_straightOut($k . ' '); + $this->pdf_write_value($v); + } + + $this->_straightOut('>>'); + break; + + case PDF_TYPE_OBJREF : + + // An indirect object reference + // Fill the object stack if needed + $cpfn =& $this->current_parser->filename; + + if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { + $this->_newobj(false,true); + $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); + $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! + } + $objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; + + $this->_out($objid.' 0 R'); + break; + + case PDF_TYPE_STRING : + + // A string. + $this->_straightOut('('.$value[1].')'); + + break; + + case PDF_TYPE_STREAM : + + // A stream. First, output the + // stream dictionary, then the + // stream data itself. + $this->pdf_write_value($value[1]); + $this->_out('stream'); + $this->_out($value[2][1]); + $this->_out('endstream'); + break; + case PDF_TYPE_HEX : + $this->_straightOut('<'.$value[1].'>'); + break; + + case PDF_TYPE_BOOLEAN : + $this->_straightOut($value[1] ? 'true ' : 'false '); + break; + + case PDF_TYPE_NULL : + // The null object. + + $this->_straightOut('null '); + break; + } + } + + + /** + * Modified so not each call will add a newline to the output. + */ + function _straightOut($s) { + if (!is_subclass_of($this, 'TCPDF')) { + if($this->state==2) + $this->pages[$this->page] .= $s; + else + $this->buffer .= $s; + } else { + if ($this->state == 2) { + if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { + // puts data before page footer + $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); + $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); + $this->setPageBuffer($this->page, $page.' '.$s."\n".$footer); + } else { + $this->setPageBuffer($this->page, $s, true); + } + } else { + $this->setBuffer($s); + } + } + } + + /** + * rewritten to close opened parsers + * + */ + function _enddoc() { + parent::_enddoc(); + $this->_closeParsers(); + } + + /** + * close all files opened by parsers + */ + function _closeParsers() { + if ($this->state > 2 && count($this->parsers) > 0) { + foreach ($this->parsers as $k => $_){ + $this->parsers[$k]->closeFile(); + $this->parsers[$k] = null; + unset($this->parsers[$k]); + } + return true; + } + return false; + } + +} diff --git a/share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php b/share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php new file mode 100644 index 0000000..008c766 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/fpdi2tcpdf_bridge.php @@ -0,0 +1,171 @@ +PDFVersion; + case 'k': + return $this->k; + default: + // Error handling + $this->Error('Cannot access protected property '.get_class($this).':$'.$name.' / Undefined property: '.get_class($this).'::$'.$name); + } + } + + function __set($name, $value) { + switch ($name) { + case 'PDFVersion': + $this->PDFVersion = $value; + break; + default: + // Error handling + $this->Error('Cannot access protected property '.get_class($this).':$'.$name.' / Undefined property: '.get_class($this).'::$'.$name); + } + } + + /** + * Encryption of imported data by FPDI + * + * @param array $value + */ + function pdf_write_value(&$value) { + switch ($value[0]) { + case PDF_TYPE_STRING : + if ($this->encrypted) { + $value[1] = $this->_unescape($value[1]); + $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]); + $value[1] = $this->_escape($value[1]); + } + break; + + case PDF_TYPE_STREAM : + if ($this->encrypted) { + $value[2][1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[2][1]); + } + break; + + case PDF_TYPE_HEX : + if ($this->encrypted) { + $value[1] = $this->hex2str($value[1]); + $value[1] = $this->_RC4($this->_objectkey($this->_current_obj_id), $value[1]); + + // remake hexstring of encrypted string + $value[1] = $this->str2hex($value[1]); + } + break; + } + } + + /** + * Unescapes a PDF string + * + * @param string $s + * @return string + */ + function _unescape($s) { + $out = ''; + for ($count = 0, $n = strlen($s); $count < $n; $count++) { + if ($s[$count] != '\\' || $count == $n-1) { + $out .= $s[$count]; + } else { + switch ($s[++$count]) { + case ')': + case '(': + case '\\': + $out .= $s[$count]; + break; + case 'f': + $out .= chr(0x0C); + break; + case 'b': + $out .= chr(0x08); + break; + case 't': + $out .= chr(0x09); + break; + case 'r': + $out .= chr(0x0D); + break; + case 'n': + $out .= chr(0x0A); + break; + case "\r": + if ($count != $n-1 && $s[$count+1] == "\n") + $count++; + break; + case "\n": + break; + default: + // Octal-Values + if (ord($s[$count]) >= ord('0') && + ord($s[$count]) <= ord('9')) { + $oct = ''. $s[$count]; + + if (ord($s[$count+1]) >= ord('0') && + ord($s[$count+1]) <= ord('9')) { + $oct .= $s[++$count]; + + if (ord($s[$count+1]) >= ord('0') && + ord($s[$count+1]) <= ord('9')) { + $oct .= $s[++$count]; + } + } + + $out .= chr(octdec($oct)); + } else { + $out .= $s[$count]; + } + } + } + } + return $out; + } + + /** + * Hexadecimal to string + * + * @param string $hex + * @return string + */ + function hex2str($hex) { + return pack('H*', str_replace(array("\r", "\n", ' '), '', $hex)); + } + + /** + * String to hexadecimal + * + * @param string $str + * @return string + */ + function str2hex($str) { + return current(unpack('H*', $str)); + } +} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php b/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php new file mode 100644 index 0000000..c5e37f6 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/fpdi_pdf_parser.php @@ -0,0 +1,384 @@ +fpdi =& $fpdi; + + parent::pdf_parser($filename); + + // resolve Pages-Dictonary + $pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']); + + // Read pages + $this->read_pages($this->c, $pages, $this->pages); + + // count pages; + $this->page_count = count($this->pages); + } + + /** + * Overwrite parent::error() + * + * @param string $msg Error-Message + */ + function error($msg) { + $this->fpdi->error($msg); + } + + /** + * Get pagecount from sourcefile + * + * @return int + */ + function getPageCount() { + return $this->page_count; + } + + + /** + * Set pageno + * + * @param int $pageno Pagenumber to use + */ + function setPageno($pageno) { + $pageno = ((int) $pageno) - 1; + + if ($pageno < 0 || $pageno >= $this->getPageCount()) { + $this->fpdi->error('Pagenumber is wrong!'); + } + + $this->pageno = $pageno; + } + + /** + * Get page-resources from current page + * + * @return array + */ + function getPageResources() { + return $this->_getPageResources($this->pages[$this->pageno]); + } + + /** + * Get page-resources from /Page + * + * @param array $obj Array of pdf-data + */ + function _getPageResources ($obj) { // $obj = /Page + $obj = $this->pdf_resolve_object($this->c, $obj); + + // If the current object has a resources + // dictionary associated with it, we use + // it. Otherwise, we move back to its + // parent object. + if (isset ($obj[1][1]['/Resources'])) { + $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Resources']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } else { + if (!isset ($obj[1][1]['/Parent'])) { + return false; + } else { + $res = $this->_getPageResources($obj[1][1]['/Parent']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } + } + } + + + /** + * Get content of current page + * + * If more /Contents is an array, the streams are concated + * + * @return string + */ + function getContent() { + $buffer = ''; + + if (isset($this->pages[$this->pageno][1][1]['/Contents'])) { + $contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']); + foreach($contents AS $tmp_content) { + $buffer .= $this->_rebuildContentStream($tmp_content).' '; + } + } + + return $buffer; + } + + + /** + * Resolve all content-objects + * + * @param array $content_ref + * @return array + */ + function _getPageContent($content_ref) { + $contents = array(); + + if ($content_ref[0] == PDF_TYPE_OBJREF) { + $content = $this->pdf_resolve_object($this->c, $content_ref); + if ($content[1][0] == PDF_TYPE_ARRAY) { + $contents = $this->_getPageContent($content[1]); + } else { + $contents[] = $content; + } + } else if ($content_ref[0] == PDF_TYPE_ARRAY) { + foreach ($content_ref[1] AS $tmp_content_ref) { + $contents = array_merge($contents,$this->_getPageContent($tmp_content_ref)); + } + } + + return $contents; + } + + + /** + * Rebuild content-streams + * + * @param array $obj + * @return string + */ + function _rebuildContentStream($obj) { + $filters = array(); + + if (isset($obj[1][1]['/Filter'])) { + $_filter = $obj[1][1]['/Filter']; + + if ($_filter[0] == PDF_TYPE_TOKEN) { + $filters[] = $_filter; + } else if ($_filter[0] == PDF_TYPE_ARRAY) { + $filters = $_filter[1]; + } + } + + $stream = $obj[2][1]; + + foreach ($filters AS $_filter) { + switch ($_filter[1]) { + case '/FlateDecode': + if (function_exists('gzuncompress')) { + $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : ''; + } else { + $this->error(sprintf('To handle %s filter, please compile php with zlib support.',$_filter[1])); + } + if ($stream === false) { + $this->error('Error while decompressing stream.'); + } + break; + case '/LZWDecode': + include_once('filters/FilterLZW_FPDI.php'); + $decoder = new FilterLZW_FPDI($this->fpdi); + $stream = $decoder->decode($stream); + break; + case '/ASCII85Decode': + include_once('filters/FilterASCII85_FPDI.php'); + $decoder = new FilterASCII85_FPDI($this->fpdi); + $stream = $decoder->decode($stream); + break; + case null: + $stream = $stream; + break; + default: + $this->error(sprintf('Unsupported Filter: %s',$_filter[1])); + } + } + + return $stream; + } + + + /** + * Get a Box from a page + * Arrayformat is same as used by fpdf_tpl + * + * @param array $page a /Page + * @param string $box_index Type of Box @see $availableBoxes + * @return array + */ + function getPageBox($page, $box_index) { + $page = $this->pdf_resolve_object($this->c,$page); + $box = null; + if (isset($page[1][1][$box_index])) + $box =& $page[1][1][$box_index]; + + if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { + $tmp_box = $this->pdf_resolve_object($this->c,$box); + $box = $tmp_box[1]; + } + + if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { + $b =& $box[1]; + return array('x' => $b[0][1]/$this->fpdi->k, + 'y' => $b[1][1]/$this->fpdi->k, + 'w' => abs($b[0][1]-$b[2][1])/$this->fpdi->k, + 'h' => abs($b[1][1]-$b[3][1])/$this->fpdi->k, + 'llx' => min($b[0][1], $b[2][1])/$this->fpdi->k, + 'lly' => min($b[1][1], $b[3][1])/$this->fpdi->k, + 'urx' => max($b[0][1], $b[2][1])/$this->fpdi->k, + 'ury' => max($b[1][1], $b[3][1])/$this->fpdi->k, + ); + } else if (!isset ($page[1][1]['/Parent'])) { + return false; + } else { + return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index); + } + } + + function getPageBoxes($pageno) { + return $this->_getPageBoxes($this->pages[$pageno-1]); + } + + /** + * Get all Boxes from /Page + * + * @param array a /Page + * @return array + */ + function _getPageBoxes($page) { + $boxes = array(); + + foreach($this->availableBoxes AS $box) { + if ($_box = $this->getPageBox($page,$box)) { + $boxes[$box] = $_box; + } + } + + return $boxes; + } + + /** + * Get the page rotation by pageno + * + * @param integer $pageno + * @return array + */ + function getPageRotation($pageno) { + return $this->_getPageRotation($this->pages[$pageno-1]); + } + + function _getPageRotation ($obj) { // $obj = /Page + $obj = $this->pdf_resolve_object($this->c, $obj); + if (isset ($obj[1][1]['/Rotate'])) { + $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } else { + if (!isset ($obj[1][1]['/Parent'])) { + return false; + } else { + $res = $this->_getPageRotation($obj[1][1]['/Parent']); + if ($res[0] == PDF_TYPE_OBJECT) + return $res[1]; + return $res; + } + } + } + + /** + * Read all /Page(es) + * + * @param object pdf_context + * @param array /Pages + * @param array the result-array + */ + function read_pages (&$c, &$pages, &$result) { + // Get the kids dictionary + $kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); + + if (!is_array($kids)) + $this->error('Cannot find /Kids in current /Page-Dictionary'); + foreach ($kids[1] as $v) { + $pg = $this->pdf_resolve_object ($c, $v); + if ($pg[1][1]['/Type'][1] === '/Pages') { + // If one of the kids is an embedded + // /Pages array, resolve it as well. + $this->read_pages ($c, $pg, $result); + } else { + $result[] = $pg; + } + } + } + + + + /** + * Get PDF-Version + * + * And reset the PDF Version used in FPDI if needed + */ + function getPDFVersion() { + parent::getPDFVersion(); + $this->fpdi->PDFVersion = max($this->fpdi->PDFVersion, $this->pdfVersion); + } + +} diff --git a/share/pnp/application/vendor/fpdf/license.txt b/share/pnp/application/vendor/fpdf/license.txt new file mode 100644 index 0000000..6107ee4 --- /dev/null +++ b/share/pnp/application/vendor/fpdf/license.txt @@ -0,0 +1,6 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software to use, copy, modify, distribute, sublicense, and/or sell +copies of the software, and to permit persons to whom the software is furnished +to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/pdf_context.php b/share/pnp/application/vendor/fpdf/pdf_context.php new file mode 100644 index 0000000..535636c --- /dev/null +++ b/share/pnp/application/vendor/fpdf/pdf_context.php @@ -0,0 +1,97 @@ +file =& $f; + if (is_string($this->file)) + $this->_mode = 1; + $this->reset(); + } + + // Optionally move the file + // pointer to a new location + // and reset the buffered data + + function reset($pos = null, $l = 100) { + if ($this->_mode == 0) { + if (!is_null ($pos)) { + fseek ($this->file, $pos); + } + + $this->buffer = $l > 0 ? fread($this->file, $l) : ''; + $this->length = strlen($this->buffer); + if ($this->length < $l) + $this->increase_length($l - $this->length); + } else { + $this->buffer = $this->file; + $this->length = strlen($this->buffer); + } + $this->offset = 0; + $this->stack = array(); + } + + // Make sure that there is at least one + // character beyond the current offset in + // the buffer to prevent the tokenizer + // from attempting to access data that does + // not exist + + function ensure_content() { + if ($this->offset >= $this->length - 1) { + return $this->increase_length(); + } else { + return true; + } + } + + // Forcefully read more data into the buffer + + function increase_length($l=100) { + if ($this->_mode == 0 && feof($this->file)) { + return false; + } else if ($this->_mode == 0) { + $totalLength = $this->length + $l; + do { + $this->buffer .= fread($this->file, $totalLength-$this->length); + } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); + + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/share/pnp/application/vendor/fpdf/pdf_parser.php b/share/pnp/application/vendor/fpdf/pdf_parser.php new file mode 100644 index 0000000..3e65d6b --- /dev/null +++ b/share/pnp/application/vendor/fpdf/pdf_parser.php @@ -0,0 +1,706 @@ +filename = $filename; + + $this->f = @fopen($this->filename, 'rb'); + + if (!$this->f) + $this->error(sprintf('Cannot open %s !', $filename)); + + $this->getPDFVersion(); + + $this->c = new pdf_context($this->f); + + // Read xref-Data + $this->xref = array(); + $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); + + // Check for Encryption + $this->getEncryption(); + + // Read root + $this->pdf_read_root(); + } + + /** + * Close the opened file + */ + function closeFile() { + if (isset($this->f) && is_resource($this->f)) { + fclose($this->f); + unset($this->f); + } + } + + /** + * Print Error and die + * + * @param string $msg Error-Message + */ + function error($msg) { + die('PDF-Parser Error: '.$msg); + } + + /** + * Check Trailer for Encryption + */ + function getEncryption() { + if (isset($this->xref['trailer'][1]['/Encrypt'])) { + $this->error('File is encrypted!'); + } + } + + /** + * Find/Return /Root + * + * @return array + */ + function pdf_find_root() { + if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { + $this->error('Wrong Type of Root-Element! Must be an indirect reference'); + } + + return $this->xref['trailer'][1]['/Root']; + } + + /** + * Read the /Root + */ + function pdf_read_root() { + // read root + $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); + } + + /** + * Get PDF-Version + * + * And reset the PDF Version used in FPDI if needed + */ + function getPDFVersion() { + fseek($this->f, 0); + preg_match('/\d\.\d/',fread($this->f,16),$m); + if (isset($m[0])) + $this->pdfVersion = $m[0]; + return $this->pdfVersion; + } + + /** + * Find the xref-Table + */ + function pdf_find_xref() { + $toRead = 1500; + + $stat = fseek ($this->f, -$toRead, SEEK_END); + if ($stat === -1) { + fseek ($this->f, 0); + } + $data = fread($this->f, $toRead); + + $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); + $data = substr($data, $pos); + + if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { + $this->error('Unable to find pointer to xref table'); + } + + return (int) $matches[1]; + } + + /** + * Read xref-table + * + * @param array $result Array of xref-table + * @param integer $offset of xref-table + */ + function pdf_read_xref(&$result, $offset) { + + fseek($this->f, $o_pos = $offset-20); // set some bytes backwards to fetch errorious docs + + $data = fread($this->f, 100); + + $xrefPos = strrpos($data, 'xref'); + + if ($xrefPos === false) { + fseek($this->f, $offset); + $c = new pdf_context($this->f); + $xrefStreamObjDec = $this->pdf_read_value($c); + + if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == PDF_TYPE_OBJDEC) { + $this->error(sprintf('This document (%s) probably uses a compression technique which is not supported by the free parser shipped with FPDI.', $this->filename)); + } else { + $this->error('Unable to find xref table.'); + } + } + + if (!isset($result['xref_location'])) { + $result['xref_location'] = $o_pos+$xrefPos; + $result['max_object'] = 0; + } + + $cylces = -1; + $bytesPerCycle = 100; + + fseek($this->f, $o_pos = $o_pos+$xrefPos+4); // set the handle directly after the "xref"-keyword + $data = fread($this->f, $bytesPerCycle); + + while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle*$cylces++, 0))) === false && !feof($this->f)) { + $data .= fread($this->f, $bytesPerCycle); + } + + if ($trailerPos === false) { + $this->error('Trailer keyword not found after xref table'); + } + + $data = substr($data, 0, $trailerPos); + + // get Line-Ending + preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for linebreaks + + $differentLineEndings = count(array_unique($m[0])); + if ($differentLineEndings > 1) { + $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY); + } else { + $lines = explode($m[0][1], $data); + } + + $data = $differentLineEndings = $m = null; + unset($data, $differentLineEndings, $m); + + $linesCount = count($lines); + + $start = 1; + + for ($i = 0; $i < $linesCount; $i++) { + $line = trim($lines[$i]); + if ($line) { + $pieces = explode(' ', $line); + $c = count($pieces); + switch($c) { + case 2: + $start = (int)$pieces[0]; + $end = $start+(int)$pieces[1]; + if ($end > $result['max_object']) + $result['max_object'] = $end; + break; + case 3: + if (!isset($result['xref'][$start])) + $result['xref'][$start] = array(); + + if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) { + $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null; + } + $start++; + break; + default: + $this->error('Unexpected data in xref table'); + } + } + } + + $lines = $pieces = $line = $start = $end = $gen = null; + unset($lines, $pieces, $line, $start, $end, $gen); + + fseek($this->f, $o_pos+$trailerPos+7); + + $c = new pdf_context($this->f); + $trailer = $this->pdf_read_value($c); + + $c = null; + unset($c); + + if (!isset($result['trailer'])) { + $result['trailer'] = $trailer; + } + + if (isset($trailer[1]['/Prev'])) { + $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); + } + + $trailer = null; + unset($trailer); + + return true; + } + + /** + * Reads an Value + * + * @param object $c pdf_context + * @param string $token a Token + * @return mixed + */ + function pdf_read_value(&$c, $token = null) { + if (is_null($token)) { + $token = $this->pdf_read_token($c); + } + + if ($token === false) { + return false; + } + + switch ($token) { + case '<': + // This is a hex string. + // Read the value, then the terminator + + $pos = $c->offset; + + while(1) { + + $match = strpos ($c->buffer, '>', $pos); + + // If you can't find it, try + // reading more data from the stream + + if ($match === false) { + if (!$c->increase_length()) { + return false; + } else { + continue; + } + } + + $result = substr ($c->buffer, $c->offset, $match - $c->offset); + $c->offset = $match + 1; + + return array (PDF_TYPE_HEX, $result); + } + + break; + case '<<': + // This is a dictionary. + + $result = array(); + + // Recurse into this function until we reach + // the end of the dictionary. + while (($key = $this->pdf_read_token($c)) !== '>>') { + if ($key === false) { + return false; + } + + if (($value = $this->pdf_read_value($c)) === false) { + return false; + } + + // Catch missing value + if ($value[0] == PDF_TYPE_TOKEN && $value[1] == '>>') { + $result[$key] = array(PDF_TYPE_NULL); + break; + } + + $result[$key] = $value; + } + + return array (PDF_TYPE_DICTIONARY, $result); + + case '[': + // This is an array. + + $result = array(); + + // Recurse into this function until we reach + // the end of the array. + while (($token = $this->pdf_read_token($c)) !== ']') { + if ($token === false) { + return false; + } + + if (($value = $this->pdf_read_value($c, $token)) === false) { + return false; + } + + $result[] = $value; + } + + return array (PDF_TYPE_ARRAY, $result); + + case '(' : + // This is a string + $pos = $c->offset; + + $openBrackets = 1; + do { + for (; $openBrackets != 0 && $pos < $c->length; $pos++) { + switch (ord($c->buffer[$pos])) { + case 0x28: // '(' + $openBrackets++; + break; + case 0x29: // ')' + $openBrackets--; + break; + case 0x5C: // backslash + $pos++; + } + } + } while($openBrackets != 0 && $c->increase_length()); + + $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); + $c->offset = $pos; + + return array (PDF_TYPE_STRING, $result); + + case 'stream': + $o_pos = ftell($c->file)-strlen($c->buffer); + $o_offset = $c->offset; + + $c->reset($startpos = $o_pos + $o_offset); + + $e = 0; // ensure line breaks in front of the stream + if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) + $e++; + if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) + $e++; + + if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { + $tmp_c = new pdf_context($this->f); + $tmp_length = $this->pdf_resolve_object($tmp_c,$this->actual_obj[1][1]['/Length']); + $length = $tmp_length[1][1]; + } else { + $length = $this->actual_obj[1][1]['/Length'][1]; + } + + if ($length > 0) { + $c->reset($startpos+$e,$length); + $v = $c->buffer; + } else { + $v = ''; + } + $c->reset($startpos+$e+$length+9); // 9 = strlen("endstream") + + return array(PDF_TYPE_STREAM, $v); + + default : + if (is_numeric ($token)) { + // A numeric token. Make sure that + // it is not part of something else. + if (($tok2 = $this->pdf_read_token ($c)) !== false) { + if (is_numeric ($tok2)) { + + // Two numeric tokens in a row. + // In this case, we're probably in + // front of either an object reference + // or an object specification. + // Determine the case and return the data + if (($tok3 = $this->pdf_read_token ($c)) !== false) { + switch ($tok3) { + case 'obj' : + return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); + case 'R' : + return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2); + } + // If we get to this point, that numeric value up + // there was just a numeric value. Push the extra + // tokens back into the stack and return the value. + array_push ($c->stack, $tok3); + } + } + + array_push ($c->stack, $tok2); + } + + if ($token === (string)((int)$token)) + return array (PDF_TYPE_NUMERIC, (int)$token); + else + return array (PDF_TYPE_REAL, (float)$token); + } else if ($token == 'true' || $token == 'false') { + return array (PDF_TYPE_BOOLEAN, $token == 'true'); + } else if ($token == 'null') { + return array (PDF_TYPE_NULL); + } else { + // Just a token. Return it. + return array (PDF_TYPE_TOKEN, $token); + } + } + } + + /** + * Resolve an object + * + * @param object $c pdf_context + * @param array $obj_spec The object-data + * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para + */ + function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { + // Exit if we get invalid data + if (!is_array($obj_spec)) { + $ret = false; + return $ret; + } + + if ($obj_spec[0] == PDF_TYPE_OBJREF) { + + // This is a reference, resolve it + if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) { + + // Save current file position + // This is needed if you want to resolve + // references while you're reading another object + // (e.g.: if you need to determine the length + // of a stream) + + $old_pos = ftell($c->file); + + // Reposition the file pointer and + // load the object header. + + $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); + + $header = $this->pdf_read_value($c); + + if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { + $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); + } + + // If we're being asked to store all the information + // about the object, we add the object ID and generation + // number for later use + $result = array(); + $this->actual_obj =& $result; + if ($encapsulate) { + $result = array ( + PDF_TYPE_OBJECT, + 'obj' => $obj_spec[1], + 'gen' => $obj_spec[2] + ); + } + + // Now simply read the object data until + // we encounter an end-of-object marker + while(1) { + $value = $this->pdf_read_value($c); + if ($value === false || count($result) > 4) { + // in this case the parser coudn't find an endobj so we break here + break; + } + + if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { + break; + } + + $result[] = $value; + } + + $c->reset($old_pos); + + if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { + $result[0] = PDF_TYPE_STREAM; + } + + return $result; + } + } else { + return $obj_spec; + } + } + + + + /** + * Reads a token from the file + * + * @param object $c pdf_context + * @return mixed + */ + function pdf_read_token(&$c) + { + // If there is a token available + // on the stack, pop it out and + // return it. + + if (count($c->stack)) { + return array_pop($c->stack); + } + + // Strip away any whitespace + + do { + if (!$c->ensure_content()) { + return false; + } + $c->offset += strspn($c->buffer, " \n\r\t", $c->offset); + } while ($c->offset >= $c->length - 1); + + // Get the first character in the stream + + $char = $c->buffer[$c->offset++]; + + switch ($char) { + + case '[': + case ']': + case '(': + case ')': + + // This is either an array or literal string + // delimiter, Return it + + return $char; + + case '<': + case '>': + + // This could either be a hex string or + // dictionary delimiter. Determine the + // appropriate case and return the token + + if ($c->buffer[$c->offset] == $char) { + if (!$c->ensure_content()) { + return false; + } + $c->offset++; + return $char . $char; + } else { + return $char; + } + + case '%': + + // This is a comment - jump over it! + + $pos = $c->offset; + while(1) { + $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); + if ($match === 0) { + if (!$c->increase_length()) { + return false; + } else { + continue; + } + } + + $c->offset = $m[0][1]+strlen($m[0][0]); + + return $this->pdf_read_token($c); + } + + default: + + // This is "another" type of token (probably + // a dictionary entry or a numeric value) + // Find the end and return it. + + if (!$c->ensure_content()) { + return false; + } + + while(1) { + + // Determine the length of the token + + $pos = strcspn($c->buffer, " %[]<>()\r\n\t/", $c->offset); + + if ($c->offset + $pos <= $c->length - 1) { + break; + } else { + // If the script reaches this point, + // the token may span beyond the end + // of the current buffer. Therefore, + // we increase the size of the buffer + // and try again--just to be safe. + + $c->increase_length(); + } + } + + $result = substr($c->buffer, $c->offset - 1, $pos + 1); + + $c->offset += $pos; + return $result; + } + } +} + +} diff --git a/share/pnp/application/views/basket_box.php b/share/pnp/application/views/basket_box.php new file mode 100644 index 0000000..ea8a72c --- /dev/null +++ b/share/pnp/application/views/basket_box.php @@ -0,0 +1,32 @@ +session->get('basket'); + +echo "
    \n"; +echo "
    \n"; +echo Kohana::lang('common.basket-box-header')."
    \n"; +echo "
    \n"; +echo "
    \n"; +if(is_array($basket) && sizeof($basket) > 0 ){ + foreach($basket as $key=>$item){ + echo "
  • ". + pnp::shorten($item)."
  • \n"; + } +} +if(is_array($basket) && sizeof($basket) > 0 ){ + echo "
    \n"; + echo "\n"; + echo "\n"; + echo "
    \n"; + #echo "\n"; +}else{ + echo "
    ".Kohana::lang('common.basket-empty')."
    \n"; +} +echo "
    \n"; +echo "
    \n"; +echo "

    \n"; +?> +
    diff --git a/share/pnp/application/views/color.php b/share/pnp/application/views/color.php new file mode 100644 index 0000000..d461b8b --- /dev/null +++ b/share/pnp/application/views/color.php @@ -0,0 +1,38 @@ +
    + + +
    +
    +
    + +
    +
    + scheme)) { + foreach( $this->scheme as $key => $colors ){ + print "

    \"" . $key . "\"

      "; + foreach($colors as $color){ + print "
    • " . "
    • \n"; + } + print "
    "; + } + print "

    "; + } ?> +
    +
    +
    + + + + +
    +
    +
    + +
    + +
    +
    diff --git a/share/pnp/application/views/color_box.php b/share/pnp/application/views/color_box.php new file mode 100644 index 0000000..1c4d342 --- /dev/null +++ b/share/pnp/application/views/color_box.php @@ -0,0 +1,15 @@ + +
    +
    + +
    +
    +\n"; +echo "\n"; +echo "\n"; +?> +
    +
    +

    + diff --git a/share/pnp/application/views/debug.php b/share/pnp/application/views/debug.php new file mode 100644 index 0000000..2681d16 --- /dev/null +++ b/share/pnp/application/views/debug.php @@ -0,0 +1,74 @@ +is_authorized === FALSE){ + print "

    Your are not authorized to view this site

    "; + return; +} +?> +
    + + +
    +
    + +
    + +
    +

    $this->data->STRUCT

    +
    +data->STRUCT);?>
    +	
    +
    +
    +

    $this->data->DS

    +
    +data->DS);?>
    +	
    +
    +
    +

    $this->data->MACRO

    +
    +data->MACRO);?>
    +	
    +
    +
    +

    $this->session->get()

    +
    +session->get());?>
    +	
    +
    +
    +
    +
    +
    + + + + + + +
    +
    +
    + + +
    + diff --git a/share/pnp/application/views/docs.php b/share/pnp/application/views/docs.php new file mode 100644 index 0000000..81114bc --- /dev/null +++ b/share/pnp/application/views/docs.php @@ -0,0 +1,31 @@ +
    + + +
    +
    +
    + +
    +
    +content)) { +echo $this->content; +} ?> +
    +
    +
    +
    + + + + +
    +
    +
    + +
    +
    +
    diff --git a/share/pnp/application/views/docs_box.php b/share/pnp/application/views/docs_box.php new file mode 100644 index 0000000..8a24fa7 --- /dev/null +++ b/share/pnp/application/views/docs_box.php @@ -0,0 +1,28 @@ + +
    +
    + +
    +
    +\n"; +echo "\n"; +echo "\n"; +foreach ( $this->doc_language as $lang ){ + echo " \n"; +} +?> +
    +
    +

    +

    +
    + +
    +
    +
    + toc ?> +
    +
    +

    + diff --git a/share/pnp/application/views/graph.php b/share/pnp/application/views/graph.php new file mode 100644 index 0000000..045aa2b --- /dev/null +++ b/share/pnp/application/views/graph.php @@ -0,0 +1,56 @@ +

    + + +
    + +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    + +
    +
    +
    diff --git a/share/pnp/application/views/graph_content.php b/share/pnp/application/views/graph_content.php new file mode 100644 index 0000000..337f938 --- /dev/null +++ b/share/pnp/application/views/graph_content.php @@ -0,0 +1,102 @@ + +\n"; + +if($this->is_authorized == FALSE){ + echo "
    \n"; + echo "

    \n"; + echo "Alert: ".Kohana::lang('error.not_authorized')."

    \n"; + echo "
    \n"; + return; +} + +if($this->data->ERROR != NULL){ + echo "
    \n"; + echo "

    \n"; + echo "Alert: ".$this->data->ERROR."

    \n"; + echo "
    \n"; + return; +} +$count = 0; +foreach($this->data->STRUCT as $key=>$value){ + if($value['LEVEL'] == 0){ + echo "Host: ".$value['MACRO']['DISP_HOSTNAME']. " Service: ".$value['MACRO']['DISP_SERVICEDESC']."

    \n"; + echo "".$value['TIMERANGE']['title']. " " .$value['TIMERANGE']['f_start']. " - " . $value['TIMERANGE']['f_end']. "\n"; + $count = 0; + } + if($value['VERSION'] != "valid" && $count == 0){ + $count++; + echo "

    \n"; + echo "
    \n"; + echo "

    ".$value['VERSION']."

    \n"; + echo "
    \n"; + echo "

    \n"; + } + + echo "
    "; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
    "; + echo Kohana::lang('common.datasource',$value['ds_name']).""; + echo nagios::SummaryLink($value['MACRO']['DISP_HOSTNAME'], + $value['TIMERANGE']['start'], + $value['TIMERANGE']['end']).""; + echo nagios::AvailLink($value['MACRO']['DISP_HOSTNAME'], + $value['MACRO']['DISP_SERVICEDESC'], + $value['TIMERANGE']['start'], + $value['TIMERANGE']['end']).""; + echo pnp::add_to_basket_icon( + $value['MACRO']['HOSTNAME'], + $value['MACRO']['SERVICEDESC'], + $value['SOURCE'] + ); + echo ""; + echo pnp::zoom_icon($value['MACRO']['HOSTNAME'], + $value['MACRO']['SERVICEDESC'], + $value['TIMERANGE']['start'], + $value['TIMERANGE']['end'], + $value['SOURCE'], + $value['VIEW'], + $value['GRAPH_WIDTH'], + $value['GRAPH_HEIGHT'])."
    \n"; + echo "
    \n"; + echo "

    \n"; +} +echo "\n"; +?> + diff --git a/share/pnp/application/views/graph_content_special.php b/share/pnp/application/views/graph_content_special.php new file mode 100644 index 0000000..375520a --- /dev/null +++ b/share/pnp/application/views/graph_content_special.php @@ -0,0 +1,53 @@ + +\n"; +$count = 0; +if($this->data->MACRO['TITLE']) + echo "".$this->data->MACRO['TITLE']."

    \n"; +if($this->data->MACRO['COMMENT']) + echo $this->data->MACRO['COMMENT']."

    \n"; + +foreach($this->data->STRUCT as $key=>$value){ + if($value['LEVEL'] == 0 ){ + echo "".$value['TIMERANGE']['title']. " " .$value['TIMERANGE']['f_start']. " - " . $value['TIMERANGE']['f_end']. "\n"; + $count = 0; + } + echo "

    "; + echo "\n"; + echo "\n"; + echo "\n"; + + echo "
    "; + echo Kohana::lang('common.datasource',$value['ds_name']).""; + echo pnp::zoom_icon_special($this->tpl, + $value['TIMERANGE']['start'], + $value['TIMERANGE']['end'], + $value['SOURCE'], + $value['VIEW'], + $value['GRAPH_WIDTH'], + $value['GRAPH_HEIGHT'])."
    \n"; + echo "
    \n"; + echo "

    \n"; +} +echo "\n"; +?> + diff --git a/share/pnp/application/views/graph_tiny.php b/share/pnp/application/views/graph_tiny.php new file mode 100644 index 0000000..dde26aa --- /dev/null +++ b/share/pnp/application/views/graph_tiny.php @@ -0,0 +1,19 @@ +

    +
    + + + + +
    +
    + + + +
    +
    +
    +
    \ No newline at end of file diff --git a/share/pnp/application/views/header.php b/share/pnp/application/views/header.php new file mode 100644 index 0000000..d4efaa1 --- /dev/null +++ b/share/pnp/application/views/header.php @@ -0,0 +1,4 @@ + +
    + +
    diff --git a/share/pnp/application/views/host_box.php b/share/pnp/application/views/host_box.php new file mode 100644 index 0000000..d612934 --- /dev/null +++ b/share/pnp/application/views/host_box.php @@ -0,0 +1,11 @@ +
    +Status Box
    + +$host['state']))."

    "; +} +} +?> + +
    diff --git a/share/pnp/application/views/icon_box.php b/share/pnp/application/views/icon_box.php new file mode 100644 index 0000000..34d99c1 --- /dev/null +++ b/share/pnp/application/views/icon_box.php @@ -0,0 +1,39 @@ + +
    +
    + +
    +
    + $this->start,'end' => $this->end, 'view' => $this->view), False); +if($this->config->conf['use_calendar']){ + echo ""; +} +if($this->config->conf['use_fpdf'] == 1 && ( $position == "graph" || $position == "special") ){ + echo "\n"; +} +if($this->config->conf['use_fpdf'] == 1 && $position == "basket"){ + echo "\n"; +} +if($this->config->conf['use_fpdf'] == 1 && $position == "page"){ + echo "page.$qsa."\">\n"; +} +if($this->config->conf['show_xml_icon'] == 1 && $position == "graph" && $xml_icon == TRUE){ + $qsa = pnp::addToUri(array(), False); + echo "\n"; +} +if($this->data->getFirstPage() && $this->isAuthorizedFor('pages') ){ + echo "\n"; +} + +echo "\n"; + +if($this->data->getFirstSpecialTemplate() ){ + echo "\n"; +} + +echo "\n"; +?> +
    +

    + diff --git a/share/pnp/application/views/kohana_error_page.php b/share/pnp/application/views/kohana_error_page.php new file mode 100644 index 0000000..490ed62 --- /dev/null +++ b/share/pnp/application/views/kohana_error_page.php @@ -0,0 +1,77 @@ + + + + + + + + +<?php echo $error ?> + + + + + + + + +

    + + +
    +
    +
    + +
    +
    +
    + +

    Please check the documentation for information about the following error.

    +

    + +

    file [line]:

    +

    + + +

    + + +

    + + +

    +
    +
    +
    + +
    + +
    + +
    + +
    +\n"; +echo "\n"; +echo "\n"; +?> +
    + +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    + + + diff --git a/share/pnp/application/views/logo_box.php b/share/pnp/application/views/logo_box.php new file mode 100644 index 0000000..fca461f --- /dev/null +++ b/share/pnp/application/views/logo_box.php @@ -0,0 +1,9 @@ + +
    + +
    + + diff --git a/share/pnp/application/views/mobile.php b/share/pnp/application/views/mobile.php new file mode 100644 index 0000000..1c1afdf --- /dev/null +++ b/share/pnp/application/views/mobile.php @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + +
    +
    +

    PNP4Nagios

    +Home +
    + + + + + + + + + +
    +
    +
    + + diff --git a/share/pnp/application/views/mobile_about.php b/share/pnp/application/views/mobile_about.php new file mode 100644 index 0000000..2f8bc29 --- /dev/null +++ b/share/pnp/application/views/mobile_about.php @@ -0,0 +1,3 @@ +
    +PNP4Nagios mobile interface based on jQuery Mobile +
    diff --git a/share/pnp/application/views/mobile_graph.php b/share/pnp/application/views/mobile_graph.php new file mode 100644 index 0000000..87f4193 --- /dev/null +++ b/share/pnp/application/views/mobile_graph.php @@ -0,0 +1,43 @@ +is_authorized == FALSE){ +?> +
    +
      +
    • Alert: 
    • +
    +
    + +
    + +data->STRUCT as $d){ + if($d['VIEW'] > $last_view){ # a new header begins + if($last_view != -1 ){ # close last div + print "
    \n"; + } + printf("
    %s
    \n", $d['TIMERANGE']['title'] ); + printf("
    %s\n", $d['ds_name']); + printf("
    \n", + $d['MACRO']['HOSTNAME'], + $d['MACRO']['SERVICEDESC'], + $d['VIEW'], + $d['SOURCE'] + ); + $last_view++; + }else{ + printf("
    %s
    \n", $d['ds_name']); + printf("
    \n", + $d['MACRO']['HOSTNAME'], + $d['MACRO']['SERVICEDESC'], + $d['VIEW'], + $d['SOURCE'] + ); + } +} +?> +
    + diff --git a/share/pnp/application/views/mobile_graph_special.php b/share/pnp/application/views/mobile_graph_special.php new file mode 100644 index 0000000..c7b4b6d --- /dev/null +++ b/share/pnp/application/views/mobile_graph_special.php @@ -0,0 +1,33 @@ +
    +data->MACRO['TITLE']) + echo "".$this->data->MACRO['TITLE']."

    \n"; +if($this->data->MACRO['COMMENT']) + echo $this->data->MACRO['COMMENT']."

    \n"; + +$last_view = -1; +foreach($this->data->STRUCT as $d){ + if($d['VIEW'] > $last_view){ # a new header begins + if($last_view != -1 ){ # close last div + print "

    \n"; + } + printf("
    %s
    \n", $d['TIMERANGE']['title'] ); + printf("
    %s\n", $d['ds_name']); + printf("
    \n", + $this->tpl, + $d['VIEW'], + $d['SOURCE'] + ); + $last_view++; + }else{ + printf("
    %s
    \n", $d['ds_name']); + printf("
    \n", + $this->tpl, + $d['VIEW'], + $d['SOURCE'] + ); + } +} +?> +
    diff --git a/share/pnp/application/views/mobile_home.php b/share/pnp/application/views/mobile_home.php new file mode 100644 index 0000000..7723a2a --- /dev/null +++ b/share/pnp/application/views/mobile_home.php @@ -0,0 +1,17 @@ +
    + +
    diff --git a/share/pnp/application/views/mobile_host.php b/share/pnp/application/views/mobile_host.php new file mode 100644 index 0000000..9eedbae --- /dev/null +++ b/share/pnp/application/views/mobile_host.php @@ -0,0 +1,30 @@ +is_authorized == FALSE){ +?> +
    +
      +
    • Alert: 
    • +
    +
    + + +
    +
      +$service){ + if($key == 0) + printf("
    • %s
    • \n", $service['hostname'] ); + + printf("
    • %s
    • ", + urlencode($service['hostname']), + urlencode($service['name']), + urlencode($service['hostname']), + urlencode($service['name']), + $service['servicedesc']); +} +?> +
    +
    diff --git a/share/pnp/application/views/mobile_overview.php b/share/pnp/application/views/mobile_overview.php new file mode 100644 index 0000000..e037b75 --- /dev/null +++ b/share/pnp/application/views/mobile_overview.php @@ -0,0 +1,14 @@ +
    +
      +%s\n", strtoupper(substr($host['name'], 0, 1)) ); + } + printf("
    • %s
    • ", $host['name'], $host['name']); + $l = substr($host['name'], 0, 1); +} +?> +
    +
    diff --git a/share/pnp/application/views/mobile_pages.php b/share/pnp/application/views/mobile_pages.php new file mode 100644 index 0000000..cead17f --- /dev/null +++ b/share/pnp/application/views/mobile_pages.php @@ -0,0 +1,10 @@ +
    +
      +data->getPageDetails($page); + printf("
    • %s
    • ", $page, $this->data->PAGE_DEF['page_name']); +} +?> +
    +
    diff --git a/share/pnp/application/views/mobile_search.php b/share/pnp/application/views/mobile_search.php new file mode 100644 index 0000000..e8573d1 --- /dev/null +++ b/share/pnp/application/views/mobile_search.php @@ -0,0 +1,24 @@ +isAuthorizedFor('host_search') ){ ?> + +
    + +
    +
    + + +
    +
    + +
    + + + +
    +
      +result as $host){ + printf("
    • %s
    • ", $host, $host); +} +?> +
    +
    diff --git a/share/pnp/application/views/mobile_special.php b/share/pnp/application/views/mobile_special.php new file mode 100644 index 0000000..786d109 --- /dev/null +++ b/share/pnp/application/views/mobile_special.php @@ -0,0 +1,9 @@ +
    +
      +%s", $template, $template); +} +?> +
    +
    diff --git a/share/pnp/application/views/multisite_box.php b/share/pnp/application/views/multisite_box.php new file mode 100644 index 0000000..13d64de --- /dev/null +++ b/share/pnp/application/views/multisite_box.php @@ -0,0 +1,17 @@ +
    +
    + +
    +
    +Host: ".html::specialchars(pnp::shorten($host))."
    \n"; +} +if(isset($service) && $service != "Host Perfdata"){ + echo "Service: ".html::specialchars(pnp::shorten($service))."\n"; +} +?> +
    +
    +

    + diff --git a/share/pnp/application/views/page.php b/share/pnp/application/views/page.php new file mode 100644 index 0000000..ac285c3 --- /dev/null +++ b/share/pnp/application/views/page.php @@ -0,0 +1,48 @@ +

    + + +
    + +
    +
    + +
    +
    +
    + + + + + + + + + + + + +
    +
    +
    + +
    +
    +
    diff --git a/share/pnp/application/views/pages_box.php b/share/pnp/application/views/pages_box.php new file mode 100644 index 0000000..d2297f4 --- /dev/null +++ b/share/pnp/application/views/pages_box.php @@ -0,0 +1,29 @@ +isAuthorizedFor('pages') ) { ?> +
    +
    + +
    + +session->get('pfilter'); +?> + +
    + " + ?> +
    + +
    +"; + $this->data->getPageDetails($page); + echo "data->PAGE_DEF['page_name']."\">".pnp::shorten($this->data->PAGE_DEF['page_name'])."
    \n"; + echo "\n"; +} +?> +
    +
    +

    + diff --git a/share/pnp/application/views/popup.php b/share/pnp/application/views/popup.php new file mode 100644 index 0000000..1b60236 --- /dev/null +++ b/share/pnp/application/views/popup.php @@ -0,0 +1,10 @@ +\n"; +} +?> +
    +data->STRUCT as $KEY=>$VAL){ + $source = $VAL['SOURCE']; + echo "
    \n"; + echo "\n"; + echo "
    diff --git a/share/pnp/application/views/search_box.php b/share/pnp/application/views/search_box.php new file mode 100644 index 0000000..b15c212 --- /dev/null +++ b/share/pnp/application/views/search_box.php @@ -0,0 +1,22 @@ +isAuthorizedFor('host_search') ){ ?> + + + +

    +
    + +
    +
    + +
    +
    +

    + + diff --git a/share/pnp/application/views/service_box.php b/share/pnp/application/views/service_box.php new file mode 100644 index 0000000..9ea1671 --- /dev/null +++ b/share/pnp/application/views/service_box.php @@ -0,0 +1,36 @@ +isAuthorizedFor('service_links') ) { ?> +

    +
    + +
    + +session->get('sfilter'); +?> + +
    + " + ?> +
    + +
    +\n"; + $path = pnp::addToUri( array('host' => $host, 'srv' => $service['name']) ); + echo pnp::add_to_basket_icon($host, + $service['name']); + + echo ""; + echo pnp::shorten($service['servicedesc']). + "
    \n"; + echo "\n"; +} +?> +
    +
    +

    + diff --git a/share/pnp/application/views/special_templates_box.php b/share/pnp/application/views/special_templates_box.php new file mode 100644 index 0000000..0c7140c --- /dev/null +++ b/share/pnp/application/views/special_templates_box.php @@ -0,0 +1,31 @@ +templates) && $this->isAuthorizedFor('service_links') ) { ?> +

    +
    + +
    + +session->get('spfilter'); +?> + +
    + " + ?> +
    + +
    +templates as $template){ + echo ""; + $path = pnp::addToUri( array('tpl' => $template) ); + echo "". + pnp::shorten($template). + "
    \n"; + echo "
    \n"; +} +?> +
    +
    +

    + diff --git a/share/pnp/application/views/status_box.php b/share/pnp/application/views/status_box.php new file mode 100644 index 0000000..4745c6b --- /dev/null +++ b/share/pnp/application/views/status_box.php @@ -0,0 +1,19 @@ +

    +
    + +
    +
    +Host: ". + html::anchor('graph'. + "?host=".$lhost, + html::specialchars(pnp::shorten($host))."
    ");?> +Service: " . + html::anchor('graph'. + "?host=".$lhost. + "&srv=".$lservice, + html::specialchars(pnp::shorten($service))."
    ");?> +Last Check: $timet
    "?> +
    +
    +

    + diff --git a/share/pnp/application/views/template.php b/share/pnp/application/views/template.php new file mode 100644 index 0000000..0cce888 --- /dev/null +++ b/share/pnp/application/views/template.php @@ -0,0 +1,221 @@ + + + + + + + +<?php if (isset($this->title)) echo html::specialchars($this->title) ?> + + +theme.'/jquery-ui.css') ?> + + + + + + + + + + + + + + + + diff --git a/share/pnp/application/views/timerange_box.php b/share/pnp/application/views/timerange_box.php new file mode 100644 index 0000000..f7cfd79 --- /dev/null +++ b/share/pnp/application/views/timerange_box.php @@ -0,0 +1,26 @@ +\n"; +echo "

    \n"; +echo Kohana::lang('common.timerange-box-header')."\n"; +echo "
    \n"; +echo "
    \n"; +$start = $this->session->get('start',''); +$end = $this->session->get('end',''); +$path = pnp::addToUri(array('start' => $start,'end' => $end)); +if($start && $end){ + echo "".Kohana::lang('common.timerange-selector-link')."
    \n"; +} +if($start && !$end){ + echo "".Kohana::lang('common.timerange-selector-link')."
    \n"; +} + +$path = pnp::addToUri(array('view' => '', 'start' => '', 'end' => '')); +echo "".Kohana::lang('common.timerange-selector-overview')."
    \n"; + +foreach($this->config->views as $key=>$view){ + $path = pnp::addToUri(array('view' => $key, 'start' => '', 'end' => '')); + echo "".$view['title']."
    \n"; +} +echo "
    \n"; +echo "

    \n"; +?> diff --git a/share/pnp/application/views/timerange_select.php b/share/pnp/application/views/timerange_select.php new file mode 100644 index 0000000..86ee344 --- /dev/null +++ b/share/pnp/application/views/timerange_select.php @@ -0,0 +1,37 @@ +config->conf['use_calendar']){ +$start = $this->session->get('start',''); +$end = $this->session->get('end',''); +?> + + +

    + diff --git a/share/pnp/application/views/widget_graph.sample.php b/share/pnp/application/views/widget_graph.sample.php new file mode 100644 index 0000000..24a0d3d --- /dev/null +++ b/share/pnp/application/views/widget_graph.sample.php @@ -0,0 +1,10 @@ + +
    +
    +Title +
    +
    +Content +
    +

    + diff --git a/share/pnp/application/views/widget_menu.sample.php b/share/pnp/application/views/widget_menu.sample.php new file mode 100644 index 0000000..6201301 --- /dev/null +++ b/share/pnp/application/views/widget_menu.sample.php @@ -0,0 +1,10 @@ + +

    +
    +Title +
    +
    +Content +
    +

    + diff --git a/share/pnp/application/views/zoom.php b/share/pnp/application/views/zoom.php new file mode 100644 index 0000000..78394eb --- /dev/null +++ b/share/pnp/application/views/zoom.php @@ -0,0 +1,129 @@ + + + + +theme.'/jquery-ui.css') ?> + + + + + + + + +

    +
    +
    + +
    +
    +

    data->TIMERANGE['f_start']?> --- data->TIMERANGE['f_end']?>

    +
    +url."\" >
    "; +if(!empty($tpl)){ + echo ""; +}else{ + echo ""; +} +$start_down = $this->data->TIMERANGE['start'] - intval(($this->data->TIMERANGE['end'] - $this->data->TIMERANGE['start']) / 2); +$path = pnp::addToUri( array('start' => $start_down)); +printf("\n", + $path, + "Move Start to ".date($this->config->conf['date_fmt'],$start_down), + url::base()."media/images/go-left.png", + 10 +); + +$start_up = $this->data->TIMERANGE['start'] + intval(($this->data->TIMERANGE['end'] - $this->data->TIMERANGE['start']) / 2); +$path = pnp::addToUri( array('start' => $start_up)); +printf("\n", + $path, + "Move Start to ".date($this->config->conf['date_fmt'],$start_up), + url::base()."media/images/go-right.png", + 60 +); + +$path = pnp::addToUri( array('end' => time() )); +printf("\n", + $path, + "Move End to ".date($this->config->conf['date_fmt'],time()), + url::base()."media/images/go-now.png", + 10 +); + +$end_up = $this->data->TIMERANGE['end'] + intval(($this->data->TIMERANGE['end'] - $this->data->TIMERANGE['start']) / 2); +$path = pnp::addToUri( array('end' => $end_up)); +printf("\n", + $path, + "Move End to ".date($this->config->conf['date_fmt'],$end_up), + url::base()."media/images/go-right.png", + 60 +); + +$end_down = $this->data->TIMERANGE['end'] - intval(($this->data->TIMERANGE['end'] - $this->data->TIMERANGE['start']) / 2); +$path = pnp::addToUri( array('end' => $end_down)); +printf("\n", + $path, + "Move End to ".date($this->config->conf['date_fmt'],$end_down), + url::base()."media/images/go-left.png", + 110 +); + + +?> +
    +
    +
    + + + diff --git a/share/pnp/application/views/zoom_header.php b/share/pnp/application/views/zoom_header.php new file mode 100644 index 0000000..43fb810 --- /dev/null +++ b/share/pnp/application/views/zoom_header.php @@ -0,0 +1,4 @@ +function Gzoom (url) { +GzoomWindow = window.open(url, "PNP4Nagios", "width=,height=,location=no,status=no,resizable=yes,scrollbars=yes"); +GzoomWindow.focus(); +} diff --git a/share/pnp/documents/_media/bulk-npcd.png b/share/pnp/documents/_media/bulk-npcd.png new file mode 100644 index 0000000000000000000000000000000000000000..00e4c2662bbbb27cde96d4d49ad838c4273349e5 GIT binary patch literal 82168 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 Jg@CT_{{v3kK7arK literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/bulk-npcdmod.png b/share/pnp/documents/_media/bulk-npcdmod.png new file mode 100644 index 0000000000000000000000000000000000000000..56d04c924c13b62b746562061776fd63036f54d3 GIT binary patch literal 87067 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 h_@YsgctzvB1(1&jlt{dfT@F3 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 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/mobile-graphs.png b/share/pnp/documents/_media/mobile-graphs.png new file mode 100644 index 0000000000000000000000000000000000000000..41797b47608cf788c8062bbed27f9895b08208b0 GIT binary patch literal 281741 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 z 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 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/mobile-home.png b/share/pnp/documents/_media/mobile-home.png new file mode 100644 index 0000000000000000000000000000000000000000..23208eae95723ac857a4afb05102bec791b3c7b7 GIT binary patch literal 143788 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 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/mobile-hostlist.png b/share/pnp/documents/_media/mobile-hostlist.png new file mode 100644 index 0000000000000000000000000000000000000000..32962117df0ac44e534a561807adea28c92b024e GIT binary patch literal 125986 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

    6&$i>P#ge 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 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/mobile-loading.png b/share/pnp/documents/_media/mobile-loading.png new file mode 100644 index 0000000000000000000000000000000000000000..7c106ad40e6894831b5f98b53f207e6f587b829f GIT binary patch literal 150565 zcmZ5{1yEc~)9&K#PSD^k3Bldn-2()7U3Bq4u%N*qxVy`uL4&)yyTc-v_rL!q_tsOj zXX{MW={|j?yJxzeiBM6JMnfh>1^@tPvN95C001-y0D$R2gnz$Nur&w)04M;m5~3Pj zP$!0PAjAGyq2seO#V==Pl$70K)fAFJ`~}VRBDpLDxb$iU`XqV+u;E}C88NX8OwUF0 z1b5H%H^|;ud&l{y&+&&$m~_b5%B1W5n6K+z#wR20HD7r@JA;f-fotZ&)uO70r>Ehc z3Pwgo(k|D#GLCOpFIS4&Xb7kX=v3%4+}84b(>b)x=msJXCeMwf*;l@{D_}r@aUE#ITv2W!AI^lnTgqEZjVXC~mJTAr9OSCJ0$%ik^^Sn`X*m@?V%BLHJ_7Kw+c{*MBP{{m|&>s=zsp`mWJ`fKG?5p`{gB z)f5}6LTxqZ)aBIm38B$pky+mVRo9P6y-+DBFc{t^#xCnWN|5xCH+z6ttYi0Jd008I3GzipBKBq=T_(K;>s$s@V{ zZPQJ{17_N)7wR2>yj5%0 zKgg{sW1|r>pg1u5*t5=c0A07)B#SE6EQTM-p9{jXYwGY{w!}w&n46y^Wp;PgkIg$< zIQZgwm>|9y=ILP~DH(bqyGX+jcY=$LE7z1yeYo0Gbt7}OxG2e$ZtQQA<@>lu7sEp( z9s6_AY=HL+qmW!4>PhI?Kl{1*qxexrdp}*5vadLFKR2b`N8fhI`YL;q($*!uMFSO@ zV}ftP5aAQNswX~PXR+S~?0NhE(@}qGEf3lwBqZ`o6Pyi}2WQqZTPSD<|M0#m{~|cu zklzy^GUnQ>_EEASQ<9i8+H1D|jD)5bEPYMu7iNoZG7eCjt1x6rB|40cTR>~g zgV|lt-5((W^Da*s>x~Xdu#>Qp@X+&Cf9)p*9E^)5X0;zrF^j48b`BLS1 zzE&fAkID#%*Kzdx zPG-}(8rINu_}imIf;yKqv@9D;!rOJ} z?oaugeo+!2M63LIty;u$!t@MzU49z^8~ci``M<$LL`Szxc<&2VaS}O@A*Jo-MVguR+e2dmIHnQHl2>b^CIgPN}*a;%N_W zP_m!|xVXCR4oQ>$;So|U$o9R_XxTm!mi^k~;4t!hRj0gL6CgmJV(b_Fd={3z^2eFr z;g3GKoRLz@jF@ygzF07ftk9Z}8d@OU@n`?%K`qVQoONh)`Iy9q+=-!D+35Ca@q<>l z`O>*Y$|>77Z&leK0UF&-w+OqndQ~#t6QqckLvLBU?$AtM3fW^DvV{@bGf!*D3W3`* z)>J`Z_2-^oY8xvyq!_gLjb9WaGkd6%imWculH3lQ4Hp6AH zom-pL&na`1k5%;5NtPT5>BhQ}_|#u&XcUPqgW^4OyT=b>E`&-;$eC*-Dx`gu^?y2~ zyL~Rsi&1MY(nxlef%SQEe7ZT5TT+MHFe!E?(P?|qesmifQ2M!g>qzdnf8NCq82-WW zhRqWQ{Juv05Net20TLFv>4q+BdCmfEWh-`N+ZL7u7}Cre`W3XlT^9AoPR4C^ZT3Nt zee#$;ZIU@UTRrkxQ~~f{4-6V>F{c##2uQZAY!hYexMD2&7I1fI2fP~^&?G*CUYKSH zm3Z0D#vfz>gT?(_*O-gk?$QN7;Nz-JF&?4tkdR_&@N2D_L-QUZaC3IP`p5h#nPDmA z#^ZQ;mHgMQzYTm&8~*w)Dq^yKw-Y+V7NElj_b6zMWdJbP7udJWu}4p5C>r`6hMK2n$8&sv!gA$dXdh@3VeOXc zhg9uUO>^6CM%AxUz`{F-$F<}RM$_FFXC9UsgNn*_Nq(VR*u42ouykQEUiX+Xug?XQ zWAcoV$N3*S6iO*KZDXFro@vN$5MU zVbVtm4aZB%Z1aVcdMSlou$I9dTO#;Sm^_I7Z}49sF*~95r?tb3?#aImhX>Z_vUp&C zw<(dOHe3sf*PP&Vmz?}&olcNVulW6XxP2ma5n|>n*w61}iOWa@`|=2E9MpHISmb^A zM}1WYvSS9ks*xHpHZK0L;&a~NGR#mksBP>=gCTemcd}R~z1!q=`StOk7lT644#?jk z3#S0u>=GS@Y8~;us0#SWEOY)lFOPNmRY~9wcQ!t0 zBxOi`T#(At)D)Y91ohCXTp@H^Qx1E+T$k$b@UX|Ns{JM?iilg(+gqh36|KZf*SaK% zlwWJj@7|Eh(b#=fv)2E`8whF8-aYeq+v{r?uf8Z3BWhZI^|?erjF*dAt)MXmX|N(D z1U-G{4&lTKG_6ovD!Kgnj7>9Eg>Y1>sY9o{onV{004-F_2f{gD+tZ_S2S3+99Sv)% z9%2WZ8tR_M3VV&K{wCMjj}?AxM*SdU5L$4$OxLvPk$yCYx=;(m0f`j${c%6liuoeu zq=9Nuzy#c&FG?i`JFxs*&RV9i5c0?V)R+=-kD4&?0ALs*U|7~>NCH}H!EE^3y-}nt zv5861KFViX2_xM#P5A0+cAN~CB{x`W)>=uoFt6x-lq|W$22dQ36H`0)1{F}VqN?>{ z%C6UAOm(qbomBXlkBZoGEh@||-4x@umx~xaVH~g}mixc;-kY%E6Z25gF_fflxx#5h z_;)75*0#3Fg}R?-`CYT;29wG{!@yXKWhk2i@G)k2LSDWWM>(M!jeZ()>Pv;ZG}-WvVww08qLXZqz?F?Oo3qOlOL%}{O3SJFT4R1s5&%KFA-~HN-!4Vb?c-+auz+;TZ=)|lnYD=_8m&Rb(*Z7L1A&t4e||(oC7Q(wYF$NE7x%fj-b_l5 ztabQU;J_l?IX2<`7~>`HWb5#`Po7p1Hk1RvG9X&9sLBn2$+|menAt_-j?MJb>(#eI zz5C^wJ%dV7j?Em+T;WJBSWM&|f(+cAhjX`!B!A6%5hdLb1g)b^kEh#`WNUtPd0+aK zob;FSbGdWVItw3WWkk)2I}!;y$2XG&Ya3`#^EYw_O(iG`>3WOvnY&Z7A;rdEIb8lt z{WPFje{`Z#;Rau!U#Hh-zs9`WkUogMg3$68WwM~V%bl&b6a6hX^D}CsI4oWAYv~?TE z^?HIEnRHaHTbC$N^nvz{zT9JklIZis_!!MS_)vjgSa|%UH%!Iz<%3*4HYVW?$0`Qk z+~C&MdoR_}9NH}gS#DTEMHQ=jvgwQeIw}c=O@12ap{==DMT^yVEc9=UjT! z5DS|u=JJEt&flgLMm#QeHF$P>6!-MwOT%ZFc&C^*;6kBcyVXwx{xdIzE-#S{sl#~jr6u^S^7-M#Q|YpKi*mAQ)!uWBrT+T~ z>XVgG%?xa~?8$)<_9q?*ITzo2H~BzVuh|in>7LzIhVEi=x2IA@>Q7Z_iXiu5M^fss zU9|5)^j-4pHJQUK9!fFYI-;4pGsa`YWYlbIVa4PDsi_kf666u2n@mPJG<(mr`a)^i zAA7w$U$vajj-FtCFTVV|aX^OwRKZ#M@2>+*wKo08Ek{#7GUM3{8>F^yur&y8;q<9T zvCfXZK!Wcx zsCc-h`lKXlgts@wIrbB?!nrLG+gT1Cs7wm3m?+5h9<7<`@WGIkUoPr#g@XTad1}=y z4JRZY#EngJjD&RQ02Vz$#5r(QDuK$GUbhAUL!mQZ{iAxFVhG+4VDRRgk7@>Fp}M{; zZ;*RN_|9Y_YGyp_``dl(XiL^{NXippdpl;)G+?JLR*%U7#Nv0%b{q>EvO1jU>d3_}Tm1KV(BU0R0F*+pl1NWCBD9#LTA(mO`qI)+#^vJ3iK{x5c z2l_0Zr9~Qe{!-RD{AKxAAusUB+HThTXhN%<-SPRGSL{uwL|xv^D9g+49R|wI{E`jB z=v7MmY6~a*n)WLflY+N|H^YQMP;4c9SsB;D+KU4)qI^+{RsTLwyr>s?8VYKSv)VE) ziUgCHP8s#5>Prq&(5$?bO3sRtTXhBp>ilAVt%WueNE4Mh3eM$v(2B9P^DUw&8`q-2+a%F{&&l zEwrNd2jlhY;rsj%Vm`ZO-|N5JcLTLfn_>;578o;^r>6Xk_U^ zw*jpiP+ccb9N+ zC#<}fPdjGa1>k9cXIf|NaA(5TO`r2(J_GmL*$ZWT%7(vDEO(qIU>3julSKoKnws%< zaLix%yY}U)wlS0`;VR66_&&Z0ofUAIC07%irSw(`r(VD@ul_ssZy_%wZt42$R44I_Qs!tMv zg+HB)MX?^~vVDK^fz@9(681KmoG|Lzpq?+coA=UeO`@EBAFb5e`Mtf|vrKY7h`s!2 zdwtd}DqnI{*VbmJGQ?v8LvkeWPX-fYJDzuLfAn7VYs-0iL`((ix91vU`LbzySZG9W z`$9d5RE^Vdhy{IcJ3QjxaAYWti@uiM>2SO*Q2q^GadwVUAkw0-c%U%r6}Pz4#B%xT zBUx*wokfBIdKeDPRnwTFpR`t9P2EFkMyw9z3R9iWhu#&6v9$b(5;WD3j93MQ+{YzW z=7fzPEVyvli4St3Y2-)v`e99l3gM5Le)6+JjN6+7YmC1X7e=f0q}xEIr<}7c9R3G` zB<}cSY>tcL+5?BLS2JeBI2+mySzN#ak)!RS2fnEJj*^m?W$Fi%7s&dV`k4_);Dcxr zzOnyn>N6sNI)>15@fCtqfP?=Bbdn06v^%jJ(G5`&M)|r~3COBf>=d(!p8nan(nmo)9{o&7yyriw((#rf&E+&D;awM@u3aKBB zeJ?|=2)wsSK4}WpH-&MS{pq^ZsW@3~)7}#`3<>*aHlQqFldMbmg zOl?}vam08rooIZK(q4>?-VlY)Cfl=0Nrd&qpcUdNzJQ%Nm}e}+FU&5#n$E;4hR$Wa z_r6X;zuMxAXN7*&R)=nM9S2{0WPk;@(RjWTqIbxGv*l2wfCpwCr9HnVliYks$A(y0 zSQOWX9h$*8Rl?W>l=W6S`Gpbdr-op#BD@%9xhMI}Cs!^Kog0=qNQi4$hK!%1=}Z1(F$NiqDNR+eZ$>8Qcz z4)d-4!HgeYQ=P9Eu6i+q2g!Vc_p{wwp+Pf9)a;oNk8y`WA)xO;lyYy)@?G9SZ!7UhFJ`UNr&;;r{!XW$1}6@E&)-duUdvWbf*>h&;q-6 zO>{=?I?z0?4##jUUz~Q$@LlfF|77{#QZsn__alz7ABF!svTe^#)*@}(zg^g#O|X<7 zHyqjZBX0EIQY}eDPjH1gYR2mWu3@m9yl+NQw2gq03?NPicoB+`^1bX4kTT8Wd*O-X z3EKGgCoTuN%z)QNxo!azZ0I0L#cTfuC8DnfKJ&*d1O_{p_SZzp#FG+!wFk{!LrlzS z%SEsl7O!|NjEw^)02O)4yPodCRaJM+#?HCQbrT}y93@}}Cs7^6-XLejn<EO{>c)jWFj9Zeyd%*jgABl29qGR{5Lo^bz@|ueF7p$Tlr@R@ zut@ySxtXp3gT=2Rl*r&(9zu%?$OifLh0hae(X&%{q)9X=cK&_WR|aIFp^@}620vf@ z7!5w3{lVHMrUaUY^W4G6dAONY9&sHPEXt2a6q*`mimp8}Ew6#6yLK7?#rHtzfb7>( zKZ3!J@O0q78+q>mMegD4aiQ}`;OCJ-Ii!I%Kgl)=s@R(1xraYj|DStkleQd!V#+qc5 z;gSC=7dZpDABHTcg@P_nYOo=_bPBE>ok=82+AW{laI;$XF*OHSpzI zmoa@j(0m~u9n~KfYhMginZcS!n^ z=@LdNo2T;l!)=&(prJF+zT4z9P8jIw>21=(3L9)AAeiL_%gXEDbDr_;XHa>r+)5W* zzgIIDRh^Npy2Htb>5DxM1PEAla-PXKJ1F1#DS8Qol(lI%Q>P7kHA0dc{p3g=6YlVmN>)Fd_CZDNU{!&%#>&8tUl3@LhGd zc{0h8rusR$XKWIt`tx05@|GMp){M`SOvv}1w7|z}S2OOl8*uzXSyRq!AkG zghZWDxt%mt)X%aJ;n|vU!4l9DfARQ7Qbt7hp=XbrGK%O~t9#aodky|Fta^7qtDFZ6r@M;;x8it0!6{F8yv*mE)Y0Vq~=YP(|#c&(cvrA9Pp_4+v~aC}0`oR>?>a$GXDi{T_C(8HVL zDkKSh<*nt0sgz&3#~h5Cxu^Js4> zilmXqoG0d!@p8$Z->8G!k^60TUVU~y;CjB~YfTlLzqbd<^cH@#wh9PyXR(B~ZGuwm zCW!hkQ#+On2U+jYaq$8IyG}Gx24F(!768(tUYy)-v?CQ}kX&xGPj4;43S}L^f)dur z6G$iL^u}u%$onMQsyVq_2y1_X=k^LmuwjuR`=!xO5Qv%`lqA6hfL6xEBif~Bf*%-E zm6mbjpN^a~!pICSWBM?ced)ciT{Hc1zh1?hd19*Q@6!!dLx|E!+nLAQKv0G72ar){ zccihnHtjIU8pUZ>2)LStWbm`<$eJ>h4cDmEHvabOnpO{g8q&@CZ9c|k;j(Y{V8s~N z3EjA(lz~a(XiV^4%k&{#cFh{LS8i^r@ZS?RR3Ve>gQBH>a0gy35(qdzsQ@4Cc{nRd zOZ##*Sw4*m$cLel&Sf3_`s~27amMcy{pEi7%@z6gB@Wv6o1Lv2OzttNpU3LT_pBvO z$9mjI80mjil%>+ZFc4UfkIrQLHLuf>2&MD z8{^$})_P2=5qCt%UXpmS;%lc`slHB6Fe<=nJrI*A_aq%R_*e~%9s3(wzW@8_{__X) zT$F8F0?r1^EUzbr#EG1~9tw|FzlX79WDz51%ruN78h;-WaLXzQ)b@ygZ#HxAHRrL| z{HG}K?kN5#tu9GGsib6qn#P0``w^?Zc4(+qk_-=s%u__Cs6E3@Q^U-n)5M!@`%PI!h|RN`q|?u1G5Z zx*0P6WmJzCiF{s(bga2_Cbvnb2#u=ZNgRfmt^3ACZhWdf1ulnee*o!#KPjItwH6M} ziKr6zlSxwV^hX&@ozw~LUqWP&G3Mi))sw0PO3lD+_?Nm(o6Ch;gI<9HK6I(aN(q3h zg}xd<;>H~_#`BBw@n?*jg9_X2ohxlui_JO4R9Bx2)bleMNUh7pdkTYy+DDvXyrUv2~^ zyJO9Wp{ptRlw5P8C}JzKV8Wm6tE zpaH@9oE>?f4jVbRe(XSdulK}-EJQqomXt&@GWve8x-e;aT%1l_4}%FuM(FIDjQO!Q z-Yb9ufRe0TdD#aS!*LGC#Jv5e9^9*mg>@mZ9r#)~8Y~hjMFi`u5wTQnfr7s#8$)~D zwpeW)uJ>!&9kn1tHEyW|f=(J?;9suO2wQ5vAcw*Ikrw@0{-;ZZLe79oiA}+kxS%}8 zz$b-Sq#!iqT^-N}0i&FS8oclRy7kzvch5||pG{A(m7Ta4kW4IZms6C&? z?276SY!MOTpO}_NS>FA7;Y2^WlN2 z<>0Dp2E~Hn?-cmy#H=WP+q9*RPaXUIP@0@aub!zDwxm8&D4 zg0lqejQ&i2d&1o%J8lh`W4Y>?R;FJ?-g90i4M-GvLEy2N*X1@?#e(Z_SBxrO&}4ww zwzbfKw`JOy9lti$w;^Hb{-i%vA z9KR!A`E{Sy{;)C~bKm2_3y30w@?&YIA~Sl0B7g&c2#kD7NZ@*7%w>#A9=ie+QL2!0yuHIjvyubinQX{84CP-0(vm1S@ZVK081@MXyz~{$bNxGzEq0R|b#| zK2zC-@3_2kL)~n@i{o)r7nt$ zo9yEWCW%jjq=&=$-h)#ZD$#ExP6ozH0okPy>+y31kjR{)?>YNoYFeR|-?^_kGuzl0 z_M266=;1UP6Wh=68-S$rWbPu(KG5i#DcPo!_Eh66)mxX}q7{M)pitCW%p9v5D9Zd1>!YQK_e;BiUG9`1X7FGhcNHo2NqPZA>a zY-m2d!TvMXk3t|Pqf`70on3sRUeu(+*14nRuBRkSIH3ymKc1^V=DG5kO|R_G3xgJj z=aF)?O+cZYnkiAI;V22e63T_vd$4?MZ{b0uRA+73!M^NQjn@Q#sE<&T{^-2!rWg-m zGhf9DIkXb*6TH@o2$G{UeG>RHi37}260%Y@cZ$ai*^vqT;a^kamPtxRMjXK>A&>W7 z)3MlZ8mlsWpE^sNpF2e@<+amHiB-uC_FI+im<&5tyr%ySf8a4>i@P(C>=D-fE%qf= zcZ9;KJCb4??z!cUr{_4;=x5;-!S_;J`ER+iz~i6cCJp&b)}H4}4A0XNC^T&!2yH&q zC=ma=2}@5IVQo`b1MZV@wK&=Ohz7%I6zy|iP4)P^-dHl&eUmhaUH`eRi^;p6i=(y! z<}J|6g0PD}x6*ufgw{ZA?Oo_a=)A0kQ#r+<9`{RRFhhWhY^=H0nsK|oI)y0Xl*mil zO#AAwV%{Jt2MT|GK1BXT+<1eSIAmEV!j)w5BgoW^Q(<6}v&={+$i0YmuLkEOW|=%} zX*@8wlc80lR^3ykr)-tbcX1o`Nq_nNj@|EbqTuLZQ+nq?r9)_SqYrFyq-7?s(2V1L z=p;5IKp=d1E&P|Td(xZJzM+bMCs=S>1L2=G#CInU0-eB3Yyf>QTGpVb9*QP$OwH%v ze9da16Ocd9R*q=~eS-7>KPv<_bFL{${H1NSOsn)}Z#POOcWEQr>p#W#nakPcPe!sz^B7@98Byd}w$}VN?q@9biP`Lv2 z`#5PZ&MN{nJdj8UMhFuZ4<7KHZzqq{MjN@^0j+@bCuxz^YztG2CrOe;W*aJ<>9X+Dbi`>49XJB6dP`iR3d9Wxw5J?C##~z$s>uz z@AXckJm$XyASZRhE;a~#d&F@Q;gcmicYAyf?0jZ>qkl9o<%>C;3&?w1Ei>5?s&5t7 zrC~ex1aVZ1xAGH|;(ydUnHpD?+qCUEnRQn@hsvrSe~l)?rKBTWHtbwCpwV4 z4%l4#Gg9l7<*X3TuB0o;AaPiclF?X8%OdsRi*K_p+>2m50ppzys)XC6I_!ir`%%oG zj{_6?m`c7d2KkDe!p+j~`*ub8DWr`vw!S*~AqDzam){)*V8?*w&awM7F13x z+JZVpF}*4-{@~ZlW6;Twi&P2Sg+pFE1wDuXwJf|av{j()LKF0^PHY4oVGl#9NeV+iE%RTcTJ zhN|y7LdfpVTvqx$(aa`^bQt=jBu7vlth{^|@aelNvOCYInLO zNqnIY&N>=CAu4?&(PhWg4|^c~)J6lD9G> zE9^vkb1PS~hdlV|12L{1Hd3^Iw2lQ#GaFlu-(xfF{hD8j+z4>#cG)5;kVDl)c+cNh zj#dOVB7+GfvKZxnh$_>ScBV<_QSa`{X#d~Yys~U(=Vif?^lGKuhGN0%!+SG zs$*$RP?+ZQ=)QRkoA%|r>YT#!kkw(FuBDtcd)`ywJ77K0dU|@-f17TEw{<8o89;+L zRGqDo+)J`^F1CN_cRqg#UN;h$k}&(g@ZS3MI18bJW)=YsW6%(hxYlmc2J5R;KVI%`8spZ;A_LaSS?OLwI+K;iM)8tkGRFJp0>*t83R|}YxIpG9bULW+ z*Pi^`TB!>d{L?~(FUB`9zB>EYkgy_bA(tL%1J;k-vF)Na_med;{8Apqz|G0TP2B+c zsFHI|SJI22+m9bfu!Kqm7ar+e1mvN~5n*2^l@tlM2PP=y^`+7n4WJ;KSu?Re|CfI6m z{E}OI_W95W%nS%^N0mJ#`x_0DG0GA^78Xg^|c~DZxP0DSIyMf7s6B zBsnS!0-yUfP5WF&U#>&82?uCB_fy)+0_V3hZPVdEXV|Iiy@7WwAPROYI@&l+C)(p~ zz^mSLaW)0R&?t zTxDPn*nl#5{%K&|4jpyhM+*U`n|6-W$1Ij_sfQd28>t&}dQUoh&d(wBd zd1y4PX31B1lwo}3WA0qsJz&8p71K=MOO9=coOZ*?Ucvo)!`+baxdkdR? zOZgvZ6Q<}7udPS(=$2nO|Ml>HU3uJiHXz4U@9c5Ds*#zQf4|2+tni#|l8e8H9O(A^ zV^Rsh|DUX0sNZ<=%=zp{w+XPKQosbBn8T>~^YZOd_ySti(+Q*jA$9TgyHeFzg znwBbS!7iSfy8g7qZd#Q79;hm|Dg+iz&dDUMPkKPcz&x=}LPFNds`$Z+yxrx?dUE== zum3qiK!|?gh(0qjH{4l{`e-o?KQuhPyxyOFr8fixeIW*NeJ$8G=P!tijZAhH50kxr zkhr|PboTbhaYO|OOgMHWI{wG@+g)SjV!B|ny!?VwkB}z_f{cPfhJ>`VyqiRRpOmDW zgiKBd96}_xD)!;g>qk>c3RUOhL2XBjwP1(h@ z4$tWg+>fGZ5g+e8bm1>v;OHwcuU&~p3#1?rySXNB$>H!h&)8euDoZ;xlp zH6NPj9*2^%$-8|09rS`HVjk^!`KnfnVzJ!#H$J}BF!1H!ftuIh1~vlK8uk%V<_-@y zV^d0Z`Hz9^NMuIXl3GUgWP!j`ScLGwV%6;e%dhP>F=(1KHYShhx`-XM@yH-JeX;B7 zxJ>|DAV+RsJSG;RY_~-fvBr@nk7_OlURGn03Om%I$|}Y6eW#dhJ=sEDOfoEQ^u`F@BdbxQ za44Gjf^eR&+`sZMCPah%<7Wx6Jna1ZdL87=CCm9v+=$2{cv+JT|LvslnRNr#H-DzT zxaR+!y-p#n6dgGlfx^UaHwTmQQZa;dz43W8xEndOtxAoSc&2SlQ!+2;dH!NZ4ywQg z++=N8ot*3`oG2s|?DaT8W@yIz917*Tt_M0wR-*CeJNXd|BaBc;!DAujzx_J!Wgzf* zit*9((ANS>?t=U4gB4L02^0r7Dt*wq5?cwmts+HcN67 zw6rW1;=C?qFmxcbqXtQfIexPL{I7Je zL6TFJa&qEkalzsHKxlD0BKOkDKMw-Kyn5UPz#%?7p2@nQ^a_cZQQTqOB~{WIo9WEV zGJkpefL@;ka|1O;;v8qiw0LbN@10rM@|iEDh>t5}PCac5xoN(F<#yt5DZa4oXeG0g60G6rrfgH^#Y=7`|rb;pgpaB z84Xza5l;gdj=2h_`z-Hx_*QOhHZ|uaTPp3LXqkWH9~X{H*jMlG8n88XxGveViKhgx z8@T(}LQy{mb z0!WC(%I~C9)>$+lC(C=o3{DmV22(|MlzW4|56khShZ@(GG9E8{G)~09C8Q4wghJN9 zw7N)*>Ae!b8rdQ5M!de1HhfV*Ad9Tb2Fi^%?ft!aKMgPuV}r6oud+|m>96HKnhtb# zZ`1wLE#+&hsi~=^rx*6Bp8K#3gQTLOk`n@pkmvXinS$0#Zg(rJc2tKl7VxR=ZWGdr zMDBF6vckO`Lzj5Bd$L3^yGwIM)J7`($Hkz3p%QUqncZ9-R$Qc)Ol{Lo&tLR{jXV61BI_l_7I7%3 z(SAuv#P`6{CDhYd>j$AVT|dO(u90Uv)DMU1i~DCO7q|%k3(FlKJ`V#*5z7;e;t;HH zXoTu1sGNT9#CEY^o5bMwd+Gdwft@Oi!p?Qs(Kb*+1z6dmsZGgHh%;nxLqVri1V%%H z2Eowry~v=h_^pqs+v23ui2(g_x&jAAM>&F2?yVWIpa_K(&Nv_=lk`jqc9)0@c5knk zrXP|Ru&N-Xl8Bw9+ZhW)-%Sgpgm(tqVCZ(hT^had2PAjWXLr??Eh+j#p|xpUg4XAM z|J{)_udaHSd4d6K38(?O0K#myoe!_==sn)#PJd1ZkY@mW7T*egzd>Z1`pA-T+wgYh zwX|jb6z;0&sx3q=*#A)bfLU3JmSbC+3~R%0`{ylBzr z&oH$}lm7fqZo@_J3W1C=1n(TBrZh%U=>q#}`31E-&PI|wJ9P`Yu)1Sory$5MJU6QG zZ5%MILxKU|L5A_EE4h|~wI;wyBor=1V6Rp#Jc#eBP8_)Xx<~Oz%h34AEuvhW#Rjn~ z#fpdB?|v;kbIYsMG?l@+h3AQ0yVI~;6u)v6PDHN^M1FjP0od0=2oi2AA)!d_V*5BK zJ(k7^1)5PyD}t>qos-u(8x^mK?ut5Wtz6C0^D^m0>L73RFLZ0N$6?XwP+xm-z7DMT z#bD@6AxI~0h_lsJ;#kLJNBJPH56)lJ@2p@5?uxgdM$2Atz#Ke}?kju!>!=$r{#3es zU@PxTbS^^|6MgatGIfUtQE?G#QnHM=gjqOb<{~2gC!og!)?xM5|KbtiQ+VJu)p6wY zeA0RJI%5RB{IIY|{|v~934l#Ht3^dZjw>7gMa|~ds342MkfiSYm9XC3@MgoV3UL4k zarJaQxjY5y?p6EC9-YtRNe`APw(VYe?lGE3BW0~&*D2$}2CO{oesL2u&0Pstb~L}q zG52Y#<)>2CI?*Z4PmF1GcW%pM1bz66;J53#itgvGxP4|+G_RehW$fN87?6okP@DLB zDFTp+gE*9>H85%VRNCtfeE&&rI}*6j9GC?jl%WexRoXV`E`u{hCw2Ahgqr+5ePK;G zs=YgeH0Xd>phrw}SHs9=J5NoR2aB5&1ZVX0D9uP}-27fD&X+nlK%)8Z&ZSr>+HMM$ zs@~mk8{5bhn)-i7m0d(&MDB9Qcv!3JhMd~#cx|peku1cLY)Axb%Hr(o=}ynwaUg6x z!84>5*<=7mWe)L)s6!{p@^TTolaF^!8SE`XVo9guvtE0F9~)-T!cfNeLdsE^zKo0v zCpqlg)V!pDz;`owbxVJrep)7eb-AKaDIg<5bD*!;!RKqLv|gDeaXfvT7?iZ{pd#s7ISz30Rk6DTx#G5fAUL<)@t9DJ; zO$8XGYno-gYc7ZW8X1XX$3OA2Y`1k;uIKixGnSq5OL~kunm#1Mizo3#6cm zIEn)ipRW?3PqZCAIMHu%{HZkvb559p*1&ZQRj0>1oTFr6tg>5lFRku zz@ap0tA|vZE;o7~tQV|&{jWX8BWX^94ypsKsU=-`Go(KH=(_7}F7hB6`N*IOXBn|# zSD6vpt5ATPaGoR^OSARRs?|-fEMfTH6s^x>y8^0L_`~)}S4X zg6>gafW`Dt`l(5??dpeX=!@Xj(yg0HN!efLyuy-DH_TDT!|Xr($n*mMz_G7r<-Xxzx2$$<(LwXAL=e4 z(OfDVSWMbgn>qSpN=UEjlknb1yH&o#iY(^H6C6MytXobH8yMRC5bo{@m-x4%O8kYW z8=avY&;M<3eq}X%Y1TXl3^oeLmGhYy6g^tf!W^t^lkVdSd`V{P_590qD9@c;(dgdt zFv7@~qTN{}F=+u8UFezy+}5UD;QCJ;rn7;wwIW2SHu`deU;v6t1R z(OcqRFT0FyXpL_r3n8zhb}y=GIn0I!pp;#5*f4r~TGBua6V*4X(%c{iWHw1cy)NLR=zzuFoGK&sOv1Zt1X zhgH|(7oz;N9O82>>RcpNUDR^>nE`2AhzM2fm+0Zh5L=VA zFXa0L!j}TRI?W`31Col%-_%Oq6PmfJr<=yQc6Ix<30?CO+#fjI*>X%VBwqV7Y%Oh` zZ$!f7`!&LUxP@ZsCiuDY6vb zc&p?`2EX9M(D1SI=_@j_9HvrEPUWCv%IYbcYh&H@TT(UFQKo`f(EA3*tkmb)aqsfM zHe(#+UvR{%K9T@u0!T=-hke2)zdC$2@Ca$QN}p`$(T|ghTrF}ky?ufEdTHHqGsSeVbwNrIPi~Y&$#Oc`);k8LeWK>V``C%nNylkld8f=X<*1^Pn%w^W z&m&_Vd5>9t3jCIyakW}rvpjwMJeBX@x(sbWyc})90AvZ@>JOAg$|eml{*Vak3qIab z+ns&&{l$~Ep4MhO&fj@9u{5Nd0iAE}2cPKaCI7Y-&*2>DB7Yk{xPD;JyL@%3@lf76 z+BEQ3S1F@*=XY|{{Q0E2W@`&}oh&~vC=Wb&p*OwS_PJ|6xN6reMvOf-J>+iQ(~FgY zCaCTUN$^W2c?QrNTwwpipzXy4i}ICQ$&GyfnE_5MY9j*s`#)9|R^B$C0JP+l>j^2+ z=(KYmP1V-ZeSmmi&E~>45+;e-l4_VLahtg4d$&W!^JpmjSB9gZyL8ZH13swn)AU1W zn$Wv1*aA)!Sx1+Wycg{65=T!6PF(R@-`dFgnZpyS#_(cKiKkJJPGLrid+tkX4+@EBK0RTn*qDzqarMUugWkSH{UDhuRn)QpID_JcRKwdY2Bp0*yO+tk z$R+V?L)%SB&32FY@IcV+M)WpmDG(9iEQr){d#+SEgl9p zHH|k(k^LEDBN?s=K(UQ)vF?UZrF)D;L+6sxUoO@&hYHKLDHMXYI8V$y(}#qnY25eI z<=j7zZ)b3T0?@)LQTg!;nyywRM}k_H8!wc*Wm5UH`8Rc1oNH}jq2a;NugOBgd6N80*<3~5&4sY;q zNa$V?5*Q*$l6A9?6oebrtE8c~emy}Dw{(ymDUsZNVs-P7CL%)dwq>5iYep{=LzL|~ z&K+vE$S2}o+%JNT!l&?3X^S*@ka|RHx16-+zXYf4rUb;@Ri^pWX!PD_AfQcsY8H+| z@oX{$qwdRPkC{pHPj9|1jikcxMTBw_Ihi#+H?a1MND5U~aoiVHQ;FLOnKxvqQ;C6> zjv>c&(7j^YNwGXe;O?(K!aR;PX_B5r1(*_KZL`|c?+*w*c%^+`&u&y&SlHx`mIXpy z>|T!+6#IoN_^xWIAs4Z(Dz+Kru+nt^9@bhJ$*EJNs7;f4nlc7lirxabv6Eucp9fCov)-E| z4pmOBS04Qbuj&PVh(C8wX{&911X1tTTG)LbW1RH<&YrmwNmQiBC3ePk2+>%-_TxnD zW>?-ll0>GfB2t{2%jvm`*}*ZPWkvZ49tWNkmcM`e{C;yD+_RVMPEBHw+u2FTV4WKf zY9}J|l~8Ex#e>;AN(U9A$6i(kNqR!dtMqI4%v*JH*|2goI3FY^VRwkNFPw@za>;-3 z@WXXZ&-}-VzMuMOl)eecBk(hQZ8R@H5AlB>ZBoGZ!>HFCBNjwRW~wK+GX2V~w`y|o z!=Pfd2{|HI>7;;;=KJ07FF3VfMqDL}3U;2M5d{#EFMkRTKfSC;*IT{!kXYKq{u6U1 z|9#>^w-OEgkYeL8p&|JAW@Y17ul0^o=2h2}?zjq4VL_ejA-b4VQjY$6xusvb4f=fKg=9E`#h zO(Enw;cRpt zZsrcgZy4U?_1A>glvpXb1I3+;VE^aIsaN!61>dmSiNOWgVGt#)_cW}B?v)@B3 z|MZU%Uyw4qvb;2uM?>~rJqs1_xo?)d;`?LOU*R{q_=`ZKLGjqe`+C`#vh>oz{tsgQ z$oDei)Ip_RAPnKHEAS@pD%o!@CE-V#*YITHd;AvaJR4=01UX0SY4?kF@YEl&s~3#R z%=pY91?x!?WpWuZPB$#|8BbTM+-BJ%eRKtB;U6y$WD9g_ov_br2uN7$LnE2h<%gNm z4T|R+5@RV+A7_@DZ-<6ab4m~Qt6QasKJh5c2q8J=deOr;@}lT1%hnsgi83M=Y}b|g z2P=fIIF)my^puOs!O(N~=Q(t(>GNY7x*lP6fuH$`Bm_UqB7;s2VEe-z;|~@f_o-fj zlV&B0RpVa~^Pp@Y8l!P6<0);XoF;#8exl_j3KbaaO#|U>n;EyaKa3QzTas{_F{Sop z3jI=1`g|JH;*}B9F6riS)osEGLPi*8^0AxMM>A* zyqFz-0Yn$ZDHx=A|0KhNAgsJRW?=jX9!V~s?>|uCyrCU0FV*04`T2BJJG`3}r!k%} zruAe?ef@R!ol#Lol5TM4=;Gx{X_V{dznt3|9_RJnl*VZ!@Er>&HT0516UdiEXJ zB_?m{zz*e)Ao4&=%kFB6ycyVo3HOaeett@SDu?wMcQ37GpH_@>xTLCxQJuV*U$|*7 z+@|KkaME(!2*l*mS;qTDvr|k{y#A|i$me`^cq0)>cW`A4OWz=ECEPHc?RbygLNa#u z5HW>y>9{l4%X#>$!|Empzfsz7_<%{Pd8-;1xkkL@M#&d0N)&)sbN)`x`n=#TO8G&b zsWhMw>d@z=GoSb3kQQ5$+-hFS+W%gQK)*K8M;p&?Tpc1wG@gUV??JRQsPd{5Gd@Yq zda!uUtt|9PdWzey{Wn_&wkcx!g{#~TUXIvoQ?IE>?L5@^}45-zlETDt!72G z>Pd}C9DMHQ}8VNs1ucV zn(o6S&S{S^Urn=LX+vtQYok0tTe+q|N{NVbYprL|G2{tx*nlL{!@Z_>;w;$!gIwWf zVAiZB2;V72Nh5y-63cb;pA{Pkw|0p=3LG;Zt>=8iOoBYHl1PHLO?^^6AMyt3%-u3g z56A27_#-oaz`s;xu=6lR3b}5}fj{AdCR_EU=|sWXiGFJ{D$Mfb2qeGW5Q*PFzI$k} z^(?FTDZ?kXd*9+3?u4eT5%*AjXJ+)|J8z;jNiye}9ergNzaYv){qBkEa^)-|U&lH3 z@5k0>iX<~xz@b5}xh%uI3dW}Y%(OPi8a=NP6*VFH`TV7cij~*sG#ThSrgr3;XcG>l zz=Jnb>(6S$Aq*~WJt~}8QGTN|f8Oq=nFM$r$!QxJ-xZPgbDNowSMX|82xs5n)Vr7M zl(74tW8*=6;zw=lt%j^Qql9nJj;}%G-cGblu90{kaq}|-X0 zF@$4JUl}jQlMK(KL`|*pIqrg)_x?)qH_7bk9FOT_{Tkow;O{h;bG$AK*k#3UV;S5# zIpPH{Q_0}```he-66R3QqN6*v(cu$|V03Ac5XhQ{?#n#`HhDvhNMs~ec$+4jYw`)b zvq4Ng8RR&HERL~|z4!Mr@$aQ_`O@dC?(6J=sXKnjge3Fwb2-ExPtEn_J>%H;>oRQ_ zXWl80hRA7{1Yl8mq{?}v?BCzLDYjb5Ezd1Z1rFls#|;5(UlBEIpSLCPsCqz-oF%kO z@?k!d#;cEazEPapOntCX`BYnL9KWcvm%03+XFNu1f@UJb#NHX#8EZr-E^;uw^(6;^ zd%^RKO-n$3IK<8SHAOCY$Wit4DqFh}Lh4uiNtLA)N%q{(sm&-be4c>DOYk+i>R?*^ z;|HmI()PF=lNV2)`V640-*r!+P1g|Agt#j1>bQ66;!!O;N0!X|f2fnaFu`6#p~okd zSLHg!20cf&f2xJbKS%CQ^5D0U^0@DHC?u?srtF?|0G1prQMTHbYbRl3fmp)^nw4rZ4{*mwYMX@Ac zFErAH^pl};Wo#^>0TrI_#AcjlT8UrK+46Rdt!HxhVh=>ci-!e`O9Ztyv6B*W^}kDK zpYX@vJQNu+7|0TXe|fDG0F^oKROK(kWBqgKyY3wSMCHqn-gfblI>V^i`=7iZUzY;E zCgoRk9kA7{=NSvi^3TSOVs}Hl@j_2GG6sVySq2|t!%ke6P6^#&3h22^7m6BHVqY@G z^SjpyY}U1z@mehXqV4K`uAZIVVxSR~*i1zimOm25#3dMV8RKBkLSKabT&cI^+1iM?t2V2P*y3xfu`$JkJsm(ufB zak<|$MpTsIlDM%Lli+D2A8x)ZyC#WI3iy?~Q9=Bt$LvS3;x=!NvK%A>-d4REvM7$l zY#xX8-k&`=-6*v+*^^u@tptr=`rRmS7+n>paV){+uY`Vm%X-vzXLBX(QGDK9!a&?l3g4cV3pkXsb*yWEOWkt}v>ysr#BTMlSY_NT9>@87HndF4(VKjT z*z~FTg#VX|a_>Bkqj$D(Cy#v`4(<~oblbwWrop-$e*XebplR}~ zi2m^?8Pawh8@O+C3FY5tHUuDIGEcJGS!N$2>NL8)&**y<)Kt_59!wuONb5H}bc@Z~ zO=JIv^Dh2QHf`z0X$aMvTXO4>pL!^JtCFjvk}PO7hPLW8v&Nl`a37tx0W!;va+I)4 z$y*Dq+6hwI9ko0^Fvr0SRd0`c{4rCE8ZYRb9$ro8yW~uLOt6v2XCDn)30(W7a_0po zy0f!@nieq{OgwGhqKImlIM8WhhTl&iW8yF0b`Qr7vMexqh<%m4;@`%Eqdi`Adr`Nx zjt2OGaAA(Ky>|)P)`qKN0YAAmn0h4Psk8DZF%o6qK|laW+X#kpgD zv}r5N`IGI$?V|j=2~ta_Enn3xi{quPbK|#O;D_KJ{dUtFe29XAGof3{8}fl%oBq%D z7tYC&fSt^1_TOTPsTs7JPrBzta6?TW9c`{TZ6&6gg@*imPU_{*!k@xxdVBkMeb(F1 z#hQoZD$_+^%V1x9*;Ce$c*J-&lcTCt&EOY8#;yHF6^%m;^`pe{>XFU+R$BSL+7)3 zU7xnO8eXv(Dswzgnv8IJ`l0me4Nk#zP48d|f@sVd z2pTr}lRNglQM*|C?MKClf08L8da7o{pfve$a{`1C*cCihVm(veQzqd!Ks3=f|NiVi z&*Dh=MhIumGDN!2PE9Jle z!x;)CR5O)ByD3@O0j}9L^dqE_I5^SNVC~}4;@fP!>n{^I3{BbzacrO>2OEp~v+=P= zj@$d;jY^3UVCEUKv*Wi-xE}^`w)39>i_qU>of@Nr-QLZTu?xIfCnQ!}Qf!fHtmJuq zx%?B~wxV~~C5=#m6;B~cJMmU9HK&80uf+F{dF6>xS{~0^{k|2Y8mi2;^p03V+tggJmpHk* z;AJ|6k~`(>eg@A(1#Y6Whob%Z)K=HIpdoJrH6t7NG8D)zf$txxOB7!k=6Y}|9+4ee zsp9v#k#-N|KZBTRd#WZ1D%csmeO@`6bdC~DeUAIGW5t_nr z=aDX+`_zqu;WjHmx)*v9T;NOD2RFH6F@zseG;wY_n+hQqYxYY7swPvUGNk0Y2cTbn z4_@y$?FE4B6nvKQ58M=+;3TMU`({-*v(TH@ zGu8x0)E2I%s8HhQ@y{5)O_yqHGxZ(N^|wF1c)zVB$oM$7X~uW^C2N71L2W|2pX9~) zB<`KK%BGbSG<@Q{i;0B&tr=W@IR1F{AA;QSUrk!=6!E{Xvev8dG|U2zjVdXmM=Z-T zZ8sl%d%0E}KcIdmC`hfh;nCV{1pVBoPORr4fB6~-j;`x)V z%-zg*QNmD-IN7<1hlGzxCS2cXCR1jO?3qp2chx`H&)H2;L>heM|D6=Wc_C-jryD4e zU#-iX*qS?%Fwn4wcH>v1;S5}qNV4gj3*P8u5!_s8Bz1UP17{`Y#Ds)M?A-L5r_#VV zrSN$-;j0X+KdG;Ad>&XU0%V^{!Sbq9^Ovvq3pa)3DJ|G*lZ^5tNWsKB2SxY27LPjF zva;d?K|0r@7>GEb;HN^O$K6j6!E*t*j=6=6 zxv4#M`(wNP;%jCzS#P>3{h+kfCz(CC!K3^=ef=It$7Kg=O4eIg;h8$gy;wdZPHyw# zupnIaAcGvKDW19A0m&DPDP@z52H)IxpMdH^D$lv9l@OQV2~=~GSWm9moE{oPFm_5; z(#1;DS_D%K)4k8J2~rzMI1x(I3J&)Hh^5QV1I*tw3ZZEk;pjVp6PBllk9NnY>9NKr( zWOZY`c(a5pQMXYrV{sHxLu70=@}6(x!T!%pndBxO*{;h=_=qjy685?eFXuB!tZ}RV z;hW7A8^)4h-^GS2jIJN=H@Jn}7?|&z@?&subsOWLY!xf5sLC}qJT-s|eN=3*syah@ zNPuIyJhdyS?Ec5Mu3R!%1PL3cS)SRaV10VNGhI>taJQj!_5w-WX z+$EUJ^D8cY6?0NrYu8KindMl+3sJX3S3R31MjX@_rV<@fA)2L4h)Q-|Ysw|))HwG2 zA>r+9zCZSd)#H@hE>zxgN_jDd`PTl%?WyveQ)+Le{{A~1#|}#6wH60Bg7i^ME|5MdA3 zYt$@F@FAy*;*Edy0xV0BM0P@1aXehUa|wm32#)!h(vw1W!&e_heIdzO&IWB+irV}0 z>O|5133#{FQV76R zSTJrl%fAKg+^rA$jY(!|6U;hBtx6{%KeYOqJ);>yGlnRKSe zLHSs|`y$?IBAB;$RqfjGEp{h!K)O(isTfu1Vba)4d8hPX%;2)Q{O?s;r2`LvX@8aN zv(dkPmB5RKSb~wdr#=Dk_*3cYE_<@at=uGc4i5LjTca~%7;7m^SW!Nv zmWk+@v6Mlx0xyj;uZ1qNxx^x#mhbOty=yaabMcDrR>%nI_r>ntSs-)=7NR{E~@qOH$*2qbE^$yhriHVC!h_2Ny2 zSSqE}ezQs=7rDT1EetYIa*X+vjT+I!P-+F7$K$?VQ90qlAefB31V_tG7!%p_=lJ_q zmsSypx#}s_ zvUxQ)m!V+fqh}BCneem4^pc8-32 zq*2;j!Gge12$j0|*fCjvoE_U|SAAb)unn1P)8H$26~0&QI>#<1JN@=vJg%suX}~1y zVr|NWAwqYIz=)CPoQ|no4Z$CKKK`v@ckg3`Wb0GvUBa#}yPGp>M_!$F_{Whk*3NIu z#kVChMF$~na*b=-!;n^X&rI^Gb(4AOO?c4MGVO3f$K^UALK z1FRHEu@4PvgxH2>+1)toZkbCX-UK>Lhq5~;Jx^-r&yoWIHZ9p^SOGlKRd&e3q0up7FtV*lBydxFpbwHf<<1h11z;19G* z{#3Zgd+#VLe?bO|Q;O`0n_C=nJh@nks$R!gx_7!I+k$?(2*S+IGsGQ=T38>EYXCp# zV)1Jq)Mj@a5;h()>)%24lN-C~xVZ2Y=(_n!C*6ned}%q%ht2e+IdHVu;_gn1IEy?2 z8=$}}%@{nq)XG0T5YdhAaV}QP&@LB2aeni-pb<2Gd1ImPthI&7uANaLim_dbB6BHN zXzqFM_^wq$z2mW~++pk9D(2C~CB9NeBpTeEvFsgYU^eQ z(}4pWZ+4nZ=bvo?8Vr}_; zI$9j0V}P%b>ovW(y7OZW+WmC;iZQj>T_;uU{po)1F5R}vL|n#-SrNEdxB!Q4M2WbW z%|FdPgV@>2JvJL{(Zjcvl};Xh*k!&<6UU~$&tzSG@&|NO)4h!8D?p-|c;?^8;dd`n z2=}HyDT%3eDbAN~W$E>%X9SqxLhqkz1i784K_@?phFx96f=Dv5i%-(q)dbt_NpDND z>^fZy&`2+tI3eX*ictIRl0+4-%xLvH$E;h5=t`U&Q*1i1%{Hj zrGE&Eo?palUNtukZ|z3M%^R`qlD4gt@cpc!<*Pb*823p;o?KS2c6MfoQ|%|K?<}oL zE4s^#UyODh9J^K|4%&W@LB|ZnI#1W|WD78m`Ofcu+X9_x_$&}5?3kEe>ab@f(*|h& z#pHlB(GWq%_M-FRq~Bdhz*NAR;LeB?bY^E>L$xgDCmA?)OIb)b;0R=h@#r-1g zg^`{#@13Gwq<(arFV1U}+&zyF90!?Jg5kia%z!_*)&U7(21DxkN?Dfqcl#ef7f((5 zGcoCH7?y_9ZPy!>z2*&GPyDdYORJPlEU^n;JFI$ZovluwW{W+G9cZ)3?q&NK4Dw^W zclY|DfNA}MLjf};1k{B7;avS=vEbPCTT4arc_t^F-E^B-HAY2Oskr2s3{2#MGAGZ< zR=oVy`7CJGI_(13Vh826ejy^RmJj>?Va$z4s-u0;@7YP!(PbsNNeb%@63U(n6f^bs zF*Z5Q8~-Tgz3zj^Gm_gyX_i6TN4AJ!VA|fOTos{EC>fP)MJP_5ClD* z3wlg_mQr>DrSIb9k{MRvcvbtz?NA}8C(sqMX)sH(cH$FhhAwjDt~;)~=PguiEsg&# zO6#}q{RHNs3l2J%T|xH8G71+zy4gcmF45Z;HaPRL8EsI^&g(7a38e~{S3ry_9-0+4 z!Xe%IHy5G8p>kA^BPclT%6}}zg~|du5Im`slfbQ1eLrlr5_fO=!U_=J*V7Kxwzt>{ zP0M+|H{D;iKH_A(`5A}flWx`R`~OPu5%n%n7X@RTdBelzQ*cwYPRLuF+N}VoY_^@g zWx33Yv~HYM$Dno0j{6k-Io>hJHB*JJQLU$XSeEwUJ5!#3SpJrdB@UHES1gl(lOf&w zjq1m2=t=tS?hb`!NrJ&ElcA=H(f+#w$So_J!LS+e3h6DmJ=5dHI!>~bNZ*;uDh#|G z6VxTEROO4+7;{)_J~?UKSPz9nI}a{j3;y~EnN~Qy2TPR?AxjO5n!(#YD(t&Q(h8bN zx%uO$aCa=4?`1O`(s-}`q>SitU6=@S+v{naSP|cWw|aFXEp7|8@OX9C;V<^g>&}(nME;o%Hxw<26 z91morn294;nV+%Tec57?%J5LSqkR)IV9v5AP0K7JGiPVxCE<9XLCzkdblwG9H(`p~ zXx*4vkD|Azk>ewP1e9YZ=WPD`TQi`&i@QrK#+zqJy&cV62ENHp=l?+m(CHB{rZF4q!z3W6!(CCqTYpMSer-kK?mJ~rU$0fVT z_)fGpXnEX?k}~#v3lPXQ7Y3TA>$V&ME*^*4@_2&&5p1p}Ig6wmH4LBSH)oT;k;_FhTdYdVFhf;ho6^+UW;2+tn_DxLr+R+oA0HvD(KTY{w0|DA+z zHf|e{TNmiLdG5d8J`w^bqgF?T|04OXsFI2%$J}aXyrT6F`^Vv3+udkyC?KE|O(oBN z-Ut|E*(E$w?RYZBXpv99@sEZ6WvH*%@k0nIValAxYAfOmMv^F|j zvzrNaT!qq+i8Z)L1nD)cjZ`j`nxPB;5}mNLXf>vGM5Vpd6~;PiwVt+h_aPhf#o1ir;<#~GV0 zgV%I6xR%pNIG(j>^PN?nYvSB?ic|@^MGm`Wgd%Cb=zJtj;pRM8d;Q& zPvtuPH9+%ae}}sfsH-O4-w$Dcsu9~@%Goz)>Y~v(a5F{ZxR=|oWgm?Nlv6ZzK`zFi z=wG8UEGb8JrhI8pcESJ4$=liL;J>99in;yPS{utFT~YDC1sUhxS2H!*#{1;?o|6F2 zRU)h5U&7bi#D@RXGJkUQas1KrJWOB4qxDA4VdTqG$X0vBQL((I!kRO3cfJjDHN#!s zHgOr_SZhft$PI%}lvE$cwlgK4GtD>W#2n1E2 zbPzNK&}R!cIOtb6lo@E9MIvF=|5J=MtlWbj;)ETrymG`nEsTcX>81*+c<8j zMs8wyv07g>c07njdjA$#qf1#NwNGhj8@Pt8#xb~}uEVbU+U&G_R_@bz%^H$%Zs{9< zSRG{nmu2Z1HE7HuYJO0#)uY6}(O5~RI#CYAN+AM9p+`UFD06DG9h%qFCcnfP4tZM( zBvzQ1U3!-t6`7$TT3F>A3r79=Q>yN>SLUL+j2~FlHJ+giQCdw1V&Gj6s>SGZL0cuc z*H6Y{YhL|y@je=_MCAFDQyu$Y%98%$MZwMkK#}d6p1^}sBYubLO1LJps>c=$XlLN$ z*=U=~MU@|*lV;;OKBnR!M$L&JxVcXY(&As&P!x|el(~)H94>Dw*kpbL``7jOQ6lSj ztOcDQpoS@Cu(N-zQ2}r;s!K2?WnXi$7iw^MeNB8-ct6zm4wIZyVu{_014Xh&g)hg5 z;_CsSVR@R?N~PYICAL>LE;$A}j33AD$PZkvUb4ttHlo=Oi+v ze60wGj~P|v15u#B^yxS7?rVGyX6M~Gel`k4-K8t&Dh0uzrzKz`dd|HvD8@Kv%3Jo= zw^6?%%}G&7AT!2Xq4f9o9X9WlegOMf%l4=LQDMgmSdn9A>Qky(FUT~ zC|+LFfB`McA!yip1hx~Thc4;zG<$A4ds?!j7c1E4ayFI)<24`igO(PRNn7YOm!O}I ztG6{C=yjGd4SLfi{Y|HJqjA%~xAmHMC3H*u&Xz*M&^IAH1-Q8g)g^qXSl<0XO~+c0 zRx$7$eHDGbVq29TQjK(N2Qjs{3t=<>EM z6>L2}7=rO9p;fiCD~Hj6n{7seopW>{}brHP}(WG_D$f_~^atcv%dX z0@iyRa*FI4Khpth{1OG#JQ$0G9YMN`()M49zVx3=>P66qXs8~p=nt>B>tKK71rtna+X{f6LH0H4TCOiN zPtLSYuiHSpS6E+5GfgoS9UnX`^n zsWE5_Q*3D6#G;3SG0j73i!1cX+Z--*%PP&lB}WFat_IV(6W85Cco7p1mB!9WyXs1v zd7ZAi%cqI@+`aJ;{WY6MQoby1Y%^LhapF$7MpJC1)V5d`^82`eGljluQumo*7Pj_H z>4=MU+24)cY9qfIKE0T^9< z^#)c4G}!G%!}VOoosK*nRF6*s4b{HSS9$9kYXc+`CsEEo!{qmS@^}&%tpc#If3IGc z7~TdF3}xHZ22l75--xk4(#IgWk>wYq1Jf+}u;^aD7<=z2J!AILQVTQdj1J^Tq^n~^ zfZ5RlaKDxJQO4H9YvUH$?4!y6zN?Z0v8b`qC84?3##uf|02QRc_{3Vpnb+bpQ<=Ge zY_zqfq1h#ubZx4>YouLp*&MtL+1zh+R8s$`E>$05R&Z3=cs3?lD_JIIhN&eg9oLIn znqbj4X!{KoC>%3cG-5BU+ZPntRl

    SdshpIxbU@+^aGnvoD>2%-;L;q-5!c+}O1a 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


    Q=O=Y+CLCu@rZ!5w8;- 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≪Wm6p|!ge8OVa3)^kenWoL8S@)o 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

    F&k1;J_$?)qA0 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 dm6%5f5qv-|S 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 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/nagiospowered-72x72.png b/share/pnp/documents/_media/nagiospowered-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..038f36d0c112c160fa67badd2f4026c9d72e42aa GIT binary patch literal 3954 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 NG}Uy`l`0m&{{t0AN(le} literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/pnp-preview-05-08-2009.png b/share/pnp/documents/_media/pnp-preview-05-08-2009.png new file mode 100644 index 0000000000000000000000000000000000000000..6b9a8d85c3a528b424efee391669d2a6ebb62600 GIT binary patch literal 148576 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 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/popup.png b/share/pnp/documents/_media/popup.png new file mode 100644 index 0000000000000000000000000000000000000000..088cf4291e4aaef4cc05582432aaa9cd558f7be9 GIT binary patch literal 148775 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

    qv#xojAR**&4FOt<2Xt@fA=E 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¥Pt3!%76psNkx-9nPJ|dI2 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 IO19De2j}I?fB*mh literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/srv_info.png b/share/pnp/documents/_media/srv_info.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9c153af869e323aabaa3aa5db3ddb2f468cb78 GIT binary patch literal 31102 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 Y3a`hZQ3~!jK66G*NlUR<-t5)?2heYb6951J literal 0 HcmV?d00001 diff --git a/share/pnp/documents/_media/synchronous.png b/share/pnp/documents/_media/synchronous.png new file mode 100644 index 0000000000000000000000000000000000000000..a5574f4f698d5f370c1562ce10586d435f9cbd49 GIT binary patch literal 49349 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Über PNP

    +
    + +
    + +

    Anforderungen an Plugins

    +
    + +

    + +PNP benötigt zwingend gültige Performancedaten von Nagios-Plugins. +

    + +

    +Was sind also diese Performancedaten? +

    + +

    +Die Ausgabe eines Nagios Plugins darf bis Nagios 2.x maximal eine Zeile betragen. Diese Ausgabe wird, wenn das Plugin Performancedaten liefert, in zwei Teile zerlegt. Als Trennzeichen dient dabei das Pipe “|” Symbol. +

    + +

    +Beispiel check_icmp : + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +daraus ergibt sich der Output auf der linken Seite des Pipe-Symbols + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0%
    + +

    + +und die Performancedaten + +

    +
      rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +Wie man unschwer erkennt, sind die Performancedaten auf die maschinelle Verarbeitung ausgelegt. Das Format ist in den + Developer Guidelines +festgelegt (einen Auszug davon gibt es an dieser Stelle), es soll aber hier noch einmal kurz erläutert werden. + +

    +
      rta=2.687ms;3000.000;5000.000;0;
    +   |    |  |    |         |     | |
    +   |----|--|----|---------|-----|-|----- * Label 
    +        |--|----|---------|-----|-|----- * Aktueller Wert
    +           |----|---------|-----|-|----- Einheit ( UOM = UNIT of Measurement ) 
    +                |---------|-----|-|----- Warning Schwellwert
    +                          |-----|-|----- Critical Schwellwert 
    +                                |-|----- Minimum Wert 
    +                                  |----- Maximum Wert
    +                                  
    + +

    +Mit * gekennzeichnete Werte müssen vorhanden sein. Alle anderen Werte sind optional. +

    + +

    +Mehrere Datenreihen werden durch Leerzeichen getrennt. Die eigentlichen Daten dürfen also keine Leerzeichen enthalten. Soll das Label Leerzeichen enthalten, so müssen diese in einfache Hochkomma eingeschlossen werden. +

    + +
    + +

    Benötigte Software

    +
    +
      +
    • Perl >= 5.x ohne besondere Module
      +
    • +
    • RRDtool ab 1.x; besser 1.2, aber nicht zwingend.
      +Achtung: wird RRDtool ohne Paket-Manager installiert, fehlen anschließend möglicherweise die dejavu-Fonts. Das äußert sich z.B. durch fehlende Schriften in den Grafiken
      +
    • +
    • PHP >= 5.1.6 für das Webfrontend basierend auf Kohana
      +
    • +
    • Nagios >= 2.x oder Icinga
      +
    • +
    • für Kohana muss außerdem das Modul “mod_rewrite” in der Web-Server-Konfiguration aktiviert sein. Einzelheiten sind in der Web-Server-Dokumentation der entsprechenden Distribution nachzulesen.
      +
    • +
    + +
    + +

    Lizenz

    +
    + +

    + +PNP ist unter der GPL 2 lizensiert. +

    + +
    + +

    Download

    +
    + +

    + +Die Entwicklung von PNP wird auf Sourceforge.Net organisiert. PNP ist dort unter dem Projektnamen “PNP4Nagios” registriert. +

    + +

    +Die jeweils aktuelle (stabile) Version findet ihr im Downloadbereich. +

    + +

    +Wer noch aktueller sein möchte, kann auch die jeweils letzte Entwickler-Version benutzen. +

    + +

    +Mit der Version 0.6.x wurde von SVN auf GIT zum Verwalten des Sourcecodes gewechselt. +

    + +

    +Die aktuelle Entwicklung ist jederzeit unter https://github.com/lingej/pnp4nagios einzusehen. Beim Klicken auf pnp4nagios-head.tar.gz wird ein Archiv mit der letzten Version heruntergeladen. +

    + +
    + +

    Support

    +
    + +

    + +VOR dem Stellen von Support-Anfragen sollte sichergestellt werden, dass die unter http://docs.pnp4nagios.org/de/pnp-0.6/verify genannten Punkte geprüft wurden. +

    + +

    +Die Entwickler und Helfer sind im Nagios-Portal unter http://www.nagios-portal.org vertreten. +Dort gibt es einen eigenen Bereich zum Thema PNP.
    + +Bei Support-Anfragen bitte das Betriebssystem und die PNP-Version angeben. Außerdem ist es wichtig, ob PNP aus den Sourcen erstellt oder ein vorgefertigtes Paket verwendet wurde. +

    + +

    +Erfolgreich gelöste Probleme bitte mit einem [solved] in der Betreffzeile des ersten Beitrags kennzeichnen. Auf diese Weise erleichtern wir anderen Benutzern das Finden von Lösungen zu einem Problem. +

    + +

    +Weiterhin können die Mailinglisten auf Sourceforge verwendet werden. Dort ist es jedoch üblich, Fragen auf Englisch zu stellen. +

    + +

    +pnp4nagios-users: Die Users-Liste für allgemeine Fragen zur Konfiguration. +

    + +

    +pnp4nagios-devel: Die Devel-Liste für Anregungen und Fehler Reports. +

    + +

    +pnp4nagios-checkins: Auf der Checkins-Liste werden Änderungen im SVN-Repository automatisch veröffentlicht. +

    + +
    + +

    Datenhaltung

    +
    + +

    + +Die Performance-Daten werden mit Hilfe von RRDtool in sogenannten Round-Robin-Datenbanken gespeichert, die wie ein Ringpuffer funktionieren. Das bedeutet, dass nach einer gewissen Zeit die ältesten Daten “hinten” herausfallen und “vorne” durch neue ersetzt werden. +

    + +

    +Verschiedene Zeitintervalle innerhalb der Datei sorgen für unterschiedliche Auflösungen. In der Standardeinstellung können die Daten für die letzten zwei Tage im Minutenabstand abgelegt werden, für zehn Tage im 5-Minutenabstand, für 90 Tage im 30-Minutenabstand und für 4 Jahre im 6-Stundenabstand. Die Vergrößerung des Intervalls bewirkt, dass auch die Daten über das jeweils größere Intervall hinweg gemittelt werden. Das führt automatisch dazu, dass Spitzen nicht mehr so deutlich zu sehen sind. Das ist kein Fehler von PNP, sondern eine Eigenheit von RRDtool. Dazu gibt es auch einen Artikel im Linux-Magazin. +

    + +

    +Durch die Speicherung in diesem Format ändert sich die Dateigröße nach dem Anlegen nicht mehr. Pro Datenreihe werden ca. 400 KB benötigt. +

    + +

    +Zurück zur Übersicht | PNP-Modi + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/advanced.html b/share/pnp/documents/de_DE/advanced.html new file mode 100644 index 0000000..5293e34 --- /dev/null +++ b/share/pnp/documents/de_DE/advanced.html @@ -0,0 +1,81 @@ + + + +

    Advanced

    +
    + +
    + +

    Verteilte Systeme

    +
    + +

    +Ist Nagios als verteiltes System implementiert, stellt sich die Frage, wo PNP installiert wird. +

    + +

    +Rein technisch ist diese Frage nicht wichtig. PNP kann auf den Slaves sowie auf dem Master-Server installiert sein. Oder nur auf dem Master? +

    + +

    +Wird PNP auf dem Master betrieben, ist jedoch bei der Übergabe der Daten via send_nsca von den Slave-Servern zum Master darauf zu achten, dass auch die Performance-Daten übergeben werden. Weiterhin kommt auf dem Master oft nicht das Original-Check-Command zum Einsatz. +

    + +

    +Damit nun aber PNP auf dem Master noch erkennen kann, welches Check-Command auf den Slaves die Daten ermittelt hat, reagiert process_perfdata.pl auf ein zusätzliches Feld am Ende der Performance-Daten. +

    +
    OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;; [check_icmp]
    + +

    +Findet PNP am Ende der Performance Daten einen in eckigen Klammern eingeschlossenen Text, so wird dieser als Check-Command und somit als PNP-Template verwendet. +

    + +

    +Die Nagios-Dokumentation zu diesem Thema ist hier zu finden. Das in der Doku verwendete Command ist leicht anzupassen. +

    + +

    +Aus +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$'
    +	}
    +
    + +

    +wird +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$ | $SERVICEPERFDATA$ [$SERVICECHECKCOMMAND$]'
    +	}
    +
    + +
    + +

    Das check_multi-Plugin

    +
    + +

    + +Das Plugin check_multi ist eines der ersten Plugins, das die Funktionen von Nagios 3.0 richtig ausschöpft. Check_Multi ist in der Lage, mehrere Nagios-Plugins auszuführen, aber für Nagios als einen Service darzustellen. Die Ausgabe von check_multi erfolgt über mehrere Zeilen, um die Masse an Informationen wieder darstellen zu können. +

    + +

    +Daraus ergaben sich jedoch einige Schwierigkeiten für PNP. PNP muss aus den Performance-Daten wieder die Daten der einzelnen Plugins ermitteln können. Zusammen mit Matthias Flacke, dem Entwickler von check_multi, haben wir jedoch recht schnell eine Möglichkeit gefunden, die Daten wieder sauber den einzelnen Plugins zuzuordnen. +

    + +

    + +

    + +

    +Zurück zur Übersicht | rrdcached-Unterstützung + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/config.html b/share/pnp/documents/de_DE/config.html new file mode 100644 index 0000000..8160faa --- /dev/null +++ b/share/pnp/documents/de_DE/config.html @@ -0,0 +1,423 @@ + + + +

    Konfiguration

    +
    + +

    + +Im Folgenden wird die Konfiguration der bereits erwähnten Arten der Performance-Daten Verarbeitung genauer erklärt. +

    + +

    +Die bevorzugte Methode der PNP-Entwickler ist der “Bulk Mode mit NPCD und npcdmod”. +

    + +
    + +

    Synchronous Mode

    +
    + +

    + +Der Synchronous-Mode ist die einfachste Art, den Datensammler process_perfdata.pl in Nagios zu integrieren. Hierbei wird bei jedem Ereignis ein gesondertes Command process-service-perfdata (bzw. process-host-perfdata) ausgeführt. +

    + +

    +Grundsätzlich ist in der nagios.cfg die Verarbeitung der Performance-Daten zu aktivieren. Bitte beachten Sie, dass diese Direktive wahrscheinlich bereits in der Konfigurationsdatei enthalten ist (Default ist “0”). + +

    +
     process_performance_data=1
    + +

    + +Für jeden Host und jeden Service, für den KEINE Performance-Daten verarbeitet werden sollen, ist die Verarbeitung der Performance-Daten explizit auszuschalten. +

    +
    +define service {
    +   ...
    +   process_perf_data 0
    +   ...
    +}
    +
    + +

    +Weiterhin ist es ab Nagios 3.x möglich, in der nagios.cfg das Exportieren der Environment-Variablen zu deaktivieren. Diese sind jedoch für den Synchronous-Mode zwingend erforderlich. Daher muss + +

    +
    enable_environment_macros=1
    + +

    + +ebenfalls in der nagios.cfg gesetzt sein. +

    + +

    +Zusätzlich wird das Kommando zum Verarbeiten der Performance-Daten in der nagios.cfg angegeben. + +

    +
     service_perfdata_command=process-service-perfdata
    + +

    + +Ab Nagios 3.x ist es durchaus sinnvoll, auch die Verarbeitung der Performance-Daten für Hosts einzuschalten. Nagios 3 führt durch die geänderte Hostcheck-Logik nun auch die Prüfung der Hosts regelmäßig aus. + +

    +
     host_perfdata_command=process-host-perfdata
    + +

    + +Die referenzierten Commands müssen natürlich auch Nagios bekannt gegeben werden. Wie man sieht, sind für den Aufruf von process_perfdata.pl so gut wie keine Optionen nötig. Einzig bei Performance-Daten der Host-Checks ist die Option -d ( DATATYPE ) nötig. Wenn Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die Definitionen in der Datei commands.cfg anpassen. +

    +
    +define command {
    +       command_name    process-service-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +}
    +
    +define command {
    +       command_name    process-host-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA
    +}
    +
    + +

    +HINWEIS: process_perfdata.pl kann nicht unter Kontrolle des ePN ( embedded Perl Nagios ) gestartet werden. Daher wird das Script explizit mit /usr/bin/perl aufgerufen. Wird ePN nicht verwendet oder wird Nagios 3.x verwendet, kann auf die Angabe von /usr/bin/perl verzichtet werden. +

    + +

    +zurück zur Übersicht | Funktion prüfen +

    + +
    + +

    Bulk Mode

    +
    + +

    + +Der Bulk-Mode ist etwas komplizierter als der Synchronous-Mode, reduziert die Last auf dem Nagios Server jedoch merklich, da nun nicht mehr für jeden Service bzw. Host zusätzlich der Datensammler process_perfdata.pl gestartet werden muss. +

    + +

    +Im Bulk-Mode schreibt Nagios die Daten in einem definierten Format in eine temporäre Datei. Diese Datei wiederum wird periodisch von process_perfdata.pl verarbeitet. Um den Start und den Intervall kümmert sich dabei Nagios selbst. +

    + +

    +Auch hier muss die Verarbeitung der Performance-Daten in der nagios.cfg eingeschaltet werden. + +

    +
     process_performance_data=1
    + +

    + +Zusätzlich werden einige neue Parameter benötigt. +

    +
    +#
    +# Service Performance-Daten
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# Host Performance-Daten ab Nagios 3.x
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    +Achtung: Die Template-Definitionen weichen von denen in der Original-nagios.cfg ab! +

    + +

    +Die Parameter und deren Bedeutung im Einzelnen: + +

    +
      +
    • service_perfdata_file Der Pfad zur temporären Datei, in der die Daten gesammelt werden sollen.
      +
    • +
    • service_perfdata_file_template Das Format der temporären Datei. Hier werden die Daten über Nagios-Macros definiert.
      +
    • +
    • service_perfdata_file_mode Die Option “a” definiert, dass an die Datei angehangen werden soll.
      +
    • +
    • service_perfdata_file_processing_interval Das Intervall beträgt 15 Sekunden
      +
    • +
    • service_perfdata_file_processing_command das Command, das im definierten Intervall aufgerufen werden soll.
      +
    • +
    + +

    + +Die verwendeten Commands müssen Nagios wiederum bekannt gegeben werden. Wenn Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die Definitionen in der Datei commands.cfg anpassen. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/service-perfdata
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/host-perfdata
    +}
    +
    +
    + +
    +

    HINWEIS:

    +
    Da process_perfdata.pl nun mehr Daten zu verarbeiten hat als im Default Mode, kommt es natürlich auch zu längeren Laufzeiten. Daher ist der TIMEOUT Wert in der etc/process_perfdata.cfg zu überprüfen und ggf. anzupassen.
    +
    + +
    + +

    +zurück zur Übersicht | Funktion prüfen +

    + +
    + +

    Bulk Mode with NPCD

    +
    + +

    + +Die Konfiguration ist identisch mit dem “Bulk Mode”, einzig das verwendete Command ist leicht abgewandelt. +

    + +

    +Auch hier muss die Verarbeitung der Performance-Daten in der nagios.cfg eingeschaltet werden. + +

    +
     process_performance_data=1
    + +

    + +Zusätzlich werden einige neue Parameter benötigt. +

    +
    +#
    +# Service Performance-Daten
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# Host Performance-Daten ab Nagios 3.x
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    +Achtung: Die Template-Definitionen weichen von denen in der Original-nagios.cfg ab! +

    + +

    +Die Parameter und deren Bedeutung im Einzelnen: + +

    +
      +
    • service_perfdata_file Der Pfad zur temporären Datei, in der die Daten gesammelt werden sollen.
      +
    • +
    • service_perfdata_file_template Das Format der temporären Datei. Hier werden die Daten über Nagios-Macros definiert.
      +
    • +
    • service_perfdata_file_mode Die Option “a” definiert, dass an die Datei angehangen werden soll.
      +
    • +
    • service_perfdata_file_processing_interval Das Intervall beträgt 15 Sekunden
      +
    • +
    • service_perfdata_file_processing_command das Command, das im definierten Intervall aufgerufen werden soll.
      +
    • +
    + +

    + +Die verwendeten Commands müssen Nagios wiederum bekannt gegeben werden. Wenn Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die Definitionen in der Datei commands.cfg anpassen. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/service-perfdata /usr/local/pnp4nagios/var/spool/service-perfdata.$TIMET$
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/host-perfdata /usr/local/pnp4nagios/var/spool/host-perfdata.$TIMET$
    +}
    +
    + +

    +Durch die Kommandos wird immer nach Ablauf des über service_perfdata_file_processing_interval eingestellten Intervalls die Datei service-perfdata nach var/spool/ verschoben. Dabei wird das Nagios-Macro $TIMET$ verwendet, an den Dateinamen angehängt, um zu verhindern, dass alte Dateien ungewollt überschrieben werden. Das Macro $TIMET$ enthält den aktuellen Zeitstempel in Unix-Time-Format ( Sekunden seit 1.1.1970 ). +

    + +

    +Somit sammeln sich Dateien im Verzeichnis /usr/local/pnp4nagios/var/spool/, die nun mit Hilfe des NPCD verarbeitet werden. +

    + +

    +NPCD überwacht das Spool-Verzeichnis und übergibt wiederum alle gefundenen Dateien an process_perfdata.pl. Damit ist die Verarbeitung der Performancedaten komplett von Nagios entkoppelt. Wir müssen nur noch den NPCD starten. + +

    +
     /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +Die Option -d veranlasst NPCD im Hintergund als Daemon seinen Dienst zu verrichten. +

    + +

    +Das Init Script für den NPCD wir während der Installation über “make install-init” installiert und kann somit auch für den Start verwendet werden. + +

    +
     /etc/init.d/npcd start
    + +

    + +In der Config-Datei des NPCD, der npcd.cfg, ist vor dem ersten Start zu prüfen, ob die Pfade zum Spool-Verzeichnis und zu process_perfdata.pl richtig gesetzt sind. +

    + +

    +Weitere Informationen zu NPCD findet ihr hier. +

    + +
    + +

    Bulk Mode with NPCD und npcdmod

    +
    + +

    + +Achtung +Beginnend mit Nagios 4 haben sich die internen Strukturen geändert, so dass der Start des Moduls fehlschlägt. Bisher gibt es keine Pläne, Nagios 4 zu unterstützen. Bitte wählen Sie einen der anderen Modi. +

    + +

    + Bei diesem Modus kommt das Eventbroker-Modul npcdmod.o zu Einsatz. Der Datenfluss ist jedoch identisch zum “Bulk Mode mit NPCD”. Die internen Perfdata-Routinen von Nagios, die über die “*_perf_data_*” Optionen in der nagios.cfg konfiguriert werden, kommen NICHT mehr zu Einsatz. Das Modul npcdmod.o kümmert sich um die für PNP nötige Aufbereitung der Daten. +

    + +

    +Vorteil: +

    +
      +
    • Die Perfdata-Routinen innerhalb von Nagios stehen wieder für andere Addons zur Verfügung.
      +
    • +
    • Die Konfiguration reduziert sich.
      +
    • +
    • Die bevorzugte Methode der PNP-Entwickler.
      +
    • +
    + +

    + +Anpassung in der nagios.cfg: +

    +
    +process_performance_data=1
    +broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +
    + +

    +Alle anderen auf dieser Seite gezeigten Optionen dürfen für diesen Modus NICHT mehr verwendet werden. +

    + +

    +Achtung: Wichtig sind in diesem Zusammenhang auch die event_broker_options bei einem von -1 abweichenden Wert. Für PNP müssen die Bits 2 und 3 gesetzt sein (0b01100; siehe auch http://www.nagios-wiki.de/nagios/ndo/eventbroker_optionen). +

    + +

    +Nach dem Neustart von Nagios werden Informationen zum Ladevorgang des Moduls protokolliert. +

    + +

    +Auszug aus den nagios.log + +

    +
    +[1277545053] npcdmod: Copyright (c) 2008-2009 Hendrik Baecker (andurin@process-zero.de) - http://www.pnp4nagios.org
    +[1277545053] npcdmod: /usr/local/pnp4nagios/etc/npcd.cfg initialized
    +[1277545053] npcdmod: spool_dir = '/usr/local/pnp4nagios/var/spool/'.
    +[1277545053] npcdmod: perfdata file '/usr/local/pnp4nagios/var/perfdata.dump'.
    +[1277545053] npcdmod: Ready to run to have some fun!
    +[1277545053] Event broker module '/usr/local/pnp4nagios/lib/npcdmod.o' initialized successfully.
    +
    + +
    + +

    Gearman Mode

    +
    + +

    + + +

    + +

    +PNP4Nagios kann seit Version 0.6.12 als Gearman-Worker betrieben werden. So sind große verteilte Nagios-Umgebungen auf Basis von mod_gearman realisierbar. Außerdem kann man dadurch Nagios und PNP4Nagios auf unterschiedliche Rechner verteilen. +

    + +

    +Benötigt wird eine fertig eingerichtete mod_gearman Installation wie von Sven Nierlein unter http://labs.consol.de/lang/en/nagios/mod-gearman/ beschrieben. +

    + +

    +In etc/process_perfdata.cfg gibt es einen gearman-Abschnitt: +

    +
     PREFORK = 1
    + GEARMAN_HOST = localhost:4730
    + REQUESTS_PER_CHILD = 10000
    + ENCRYPTION = 1
    + KEY = should_be_changed
    + #KEY_FILE = /usr/local/pnp4nagios/etc/secret.key
    + 
    + +

    +Dort ist mit PREFORK = <n> die Anzahl der zu startenden Kindprozessen anzugeben. +

    + +

    +GEARMAN_HOST = <host>:<port> definiert Rechner und Port, auf dem der gearman-Daemon die Daten bereitstellt. +Über REQUESTS_PER_CHILD = <n> kann die maximal zu verarbeitende Anzahl von Anforderungen pro Prozess eingestellt werden. +

    + +

    +ENCRYPTION = <1|0> stellt ein, ob Verschlüsselung benutzt werden soll. Die Standardeinstellung ist eine aktivierte Verschlüsselung (“1”) und das sollte nur in Ausnahmefällen verändert werden. +Dabei kann entweder über KEY = <Schlüssel> der zu benutzende Schlüssel definiert oder per KEY_FILE = <Schlüsseldatei> der Standort einer Schlüsseldatei angegeben werden. +

    + +

    + +/etc/init.d/pnp_gearman_worker enthält Verweise auf die Perl-Prozedur process_perfdata.pl sowie die Konfigurationsdatei process_perfdata.cfg. +

    + +

    + +Nach dem Start des PNP-Daemons per + +

    +
     /etc/init.d/pnp_gearman_worker start
    + +

    + +werden die Performance-Daten verarbeitet, die über den gearmand-Daemon auf dem Nagios-Rechner zur Verfügung gestellt werden. +

    + +

    +zurück zur Übersicht | Funktion prüfen + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/doc_complete.html b/share/pnp/documents/de_DE/doc_complete.html new file mode 100644 index 0000000..d1ca754 --- /dev/null +++ b/share/pnp/documents/de_DE/doc_complete.html @@ -0,0 +1,3369 @@ + + +
    + + + +

    Neues in PNP 0.6.x

    +
    + +

    +PNP 0.6.x Preview +

    + +

    +Die Arbeit an der Version 0.6.x ist in vollem Gange. +

    + +

    +Mit Version 0.6.x steigen wir von Subversion auf GIT um. Der Sourcecode ist bereits auf Sourceforge erhältlich. +

    + +

    +http://pnp4nagios.git.sourceforge.net +

    + +

    + +Bisher umgesetzte Funktionen: + +

    +
      +
    • Webfrontend basiert auf Kohana
      +
    • +
    • Webfrontend basiert auf jQuery Themes
      +
    • +
    • Javascript-Funktionen über jQuery Plugins
      +
    • +
    • process_perfdata.pl wird in der Lage sein, pro Datenreihe eine eigene RRD-Datenbank zu verwenden.
      +
    • +
    • Installer weiter verbessert. Angabe von Directory-Layouts über --with-layout
      +
    • +
    • RRDtool-Fehler werden als Bild dargestellt. Keine fehlenden Bilder mehr.
      +
    • +
    • PNP-Templates können keine internen Variablen mehr überschreiben.
      +
    • +
    • PNP-Templates der Version 0.4.x können weiter verwendet werden.
      +
    • +
    • PDF-Funktionen neu umgesetzt.
      +
    • +
    • Template default.php optimiert.
      +
    • +
    • Export aus den RRD-Datenbanken im XML,CSV und JSON Format über die RRDtool “xport” Funktion.
      +
    • +
    • Page-Funktionen neu umgesetzt.
      +
    • +
    • Fehlerseiten verweisen auf online FAQ-Artikel.
      +
    • +
    • Mouseover Popup im Nagios-Frontend über jQuery.clueTip Plugin
      +
    • +
    • Volle Unterstützung des rrdcached.
      +
    • +
    + +

    + +zurück zur Übersicht | Anforderungen + +

    + +
    + +
    +
    + + + +

    Über PNP

    +
    + +
    + +

    Anforderungen an Plugins

    +
    + +

    + +PNP benötigt zwingend gültige Performancedaten von Nagios-Plugins. +

    + +

    +Was sind also diese Performancedaten? +

    + +

    +Die Ausgabe eines Nagios Plugins darf bis Nagios 2.x maximal eine Zeile betragen. Diese Ausgabe wird, wenn das Plugin Performancedaten liefert, in zwei Teile zerlegt. Als Trennzeichen dient dabei das Pipe “|” Symbol. +

    + +

    +Beispiel check_icmp : + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +daraus ergibt sich der Output auf der linken Seite des Pipe-Symbols + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0%
    + +

    + +und die Performancedaten + +

    +
      rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +Wie man unschwer erkennt, sind die Performancedaten auf die maschinelle Verarbeitung ausgelegt. Das Format ist in den + Developer Guidelines +festgelegt (einen Auszug davon gibt es an dieser Stelle), es soll aber hier noch einmal kurz erläutert werden. + +

    +
      rta=2.687ms;3000.000;5000.000;0;
    +   |    |  |    |         |     | |
    +   |----|--|----|---------|-----|-|----- * Label 
    +        |--|----|---------|-----|-|----- * Aktueller Wert
    +           |----|---------|-----|-|----- Einheit ( UOM = UNIT of Measurement ) 
    +                |---------|-----|-|----- Warning Schwellwert
    +                          |-----|-|----- Critical Schwellwert 
    +                                |-|----- Minimum Wert 
    +                                  |----- Maximum Wert
    +                                  
    + +

    +Mit * gekennzeichnete Werte müssen vorhanden sein. Alle anderen Werte sind optional. +

    + +

    +Mehrere Datenreihen werden durch Leerzeichen getrennt. Die eigentlichen Daten dürfen also keine Leerzeichen enthalten. Soll das Label Leerzeichen enthalten, so müssen diese in einfache Hochkomma eingeschlossen werden. +

    + +
    + +

    Benötigte Software

    +
    +
      +
    • Perl >= 5.x ohne besondere Module
      +
    • +
    • RRDtool ab 1.x; besser 1.2, aber nicht zwingend.
      +Achtung: wird RRDtool ohne Paket-Manager installiert, fehlen anschließend möglicherweise die dejavu-Fonts. Das äußert sich z.B. durch fehlende Schriften in den Grafiken
      +
    • +
    • PHP >= 5.1.6 für das Webfrontend basierend auf Kohana
      +
    • +
    • Nagios >= 2.x oder Icinga
      +
    • +
    • für Kohana muss außerdem das Modul “mod_rewrite” in der Web-Server-Konfiguration aktiviert sein. Einzelheiten sind in der Web-Server-Dokumentation der entsprechenden Distribution nachzulesen.
      +
    • +
    + +
    + +

    Lizenz

    +
    + +

    + +PNP ist unter der GPL 2 lizensiert. +

    + +
    + +

    Download

    +
    + +

    + +Die Entwicklung von PNP wird auf Sourceforge.Net organisiert. PNP ist dort unter dem Projektnamen “PNP4Nagios” registriert. +

    + +

    +Die jeweils aktuelle (stabile) Version findet ihr im Downloadbereich. +

    + +

    +Wer noch aktueller sein möchte, kann auch die jeweils letzte Entwickler-Version benutzen. +

    + +

    +Mit der Version 0.6.x wurde von SVN auf GIT zum Verwalten des Sourcecodes gewechselt. +

    + +

    +Die aktuelle Entwicklung ist jederzeit unter https://github.com/lingej/pnp4nagios einzusehen. Beim Klicken auf pnp4nagios-head.tar.gz wird ein Archiv mit der letzten Version heruntergeladen. +

    + +
    + +

    Support

    +
    + +

    + +VOR dem Stellen von Support-Anfragen sollte sichergestellt werden, dass die unter http://docs.pnp4nagios.org/de/pnp-0.6/verify genannten Punkte geprüft wurden. +

    + +

    +Die Entwickler und Helfer sind im Nagios-Portal unter http://www.nagios-portal.org vertreten. +Dort gibt es einen eigenen Bereich zum Thema PNP.
    + +Bei Support-Anfragen bitte das Betriebssystem und die PNP-Version angeben. Außerdem ist es wichtig, ob PNP aus den Sourcen erstellt oder ein vorgefertigtes Paket verwendet wurde. +

    + +

    +Erfolgreich gelöste Probleme bitte mit einem [solved] in der Betreffzeile des ersten Beitrags kennzeichnen. Auf diese Weise erleichtern wir anderen Benutzern das Finden von Lösungen zu einem Problem. +

    + +

    +Weiterhin können die Mailinglisten auf Sourceforge verwendet werden. Dort ist es jedoch üblich, Fragen auf Englisch zu stellen. +

    + +

    +pnp4nagios-users: Die Users-Liste für allgemeine Fragen zur Konfiguration. +

    + +

    +pnp4nagios-devel: Die Devel-Liste für Anregungen und Fehler Reports. +

    + +

    +pnp4nagios-checkins: Auf der Checkins-Liste werden Änderungen im SVN-Repository automatisch veröffentlicht. +

    + +
    + +

    Datenhaltung

    +
    + +

    + +Die Performance-Daten werden mit Hilfe von RRDtool in sogenannten Round-Robin-Datenbanken gespeichert, die wie ein Ringpuffer funktionieren. Das bedeutet, dass nach einer gewissen Zeit die ältesten Daten “hinten” herausfallen und “vorne” durch neue ersetzt werden. +

    + +

    +Verschiedene Zeitintervalle innerhalb der Datei sorgen für unterschiedliche Auflösungen. In der Standardeinstellung können die Daten für die letzten zwei Tage im Minutenabstand abgelegt werden, für zehn Tage im 5-Minutenabstand, für 90 Tage im 30-Minutenabstand und für 4 Jahre im 6-Stundenabstand. Die Vergrößerung des Intervalls bewirkt, dass auch die Daten über das jeweils größere Intervall hinweg gemittelt werden. Das führt automatisch dazu, dass Spitzen nicht mehr so deutlich zu sehen sind. Das ist kein Fehler von PNP, sondern eine Eigenheit von RRDtool. Dazu gibt es auch einen Artikel im Linux-Magazin. +

    + +

    +Durch die Speicherung in diesem Format ändert sich die Dateigröße nach dem Anlegen nicht mehr. Pro Datenreihe werden ca. 400 KB benötigt. +

    + +

    +Zurück zur Übersicht | PNP-Modi + +

    + +
    + +
    +
    + + + +

    Die Kunst Daten zu sammeln

    +
    + +

    + +PNP unterstützt mehrere Arten, die Performance-Daten zu verarbeiten. Die einzelnen Modi unterscheiden sich durch ihre Komplexität und die zu erwartende Performance. +

    + +

    +Das folgende Bild zeigt die Verbindungen zwischen Nagios, PNP und RRDtool +

    + +

    +Nagios führt für jeden Host- und jeden Service, dessen Performance-Daten gesammelt werden sollen, einen Befehl aus. Abhängig vom gewählten Modus werden die Daten entweder direkt an ein Perl-Script übergeben oder in temporäre Dateien geschrieben und später verarbeitet. process_perfdata.pl legt die Datei in XML-Dateien ab und speichert sie mit Hilfe von RRDtool in RRD-Dateien.
    + +

    + +

    +Bevor Ihr euch auf einen Modus festlegt, lest euch alles durch und entscheidet selbst, welcher Weg für eure Installation der Beste ist. +

    + +
    + +

    Die Modi im Vergleich

    +
    + +
    + +

    Synchronous Mode

    +
    + +

    + +Der “Sync Mode” ist der einfachste und am leichtesten einzurichten. Nagios ruft für jeden Service (bzw. Host) zusätzlich das Perl-Script process_perfdata.pl auf, um die Daten zu verarbeiten. +

    + +

    +Der sync-Mode funktioniert sehr gut bis ca. 1000 Services in einem Intervall von 5 Minuten. +Dieser Modus belastet aber auch Nagios am meisten, daher ist es auch in kleinen Installationen ratsam, die weiteren Modi zu beachten. +

    + +
    + +

    Bulk Mode

    +
    + +

    +Im Bulk-Mode schreibt Nagios die benötigten Daten in eine temporäre Datei. Nach Ablauf einer definierten Zeit wird die Datei an einem Stück abgearbeitet und gelöscht. +

    + +

    +Die Anzahl der Aufrufe von process_perfdata.pl reduziert sich um ein Vielfaches. Abhängig von der Zeit und den gesammelten Daten werden wesentlich weniger Systemaufrufe ausgeführt. Dafür läuft process_perfdata.pl länger. +

    + +

    +Hinweis +Bei diesem Modus sollte man die Laufzeit von process_perfdata.pl im Auge behalten. So lange, wie process_perfdata.pl zum Verarbeiten der Daten benötigt, so lange kann Nagios keine Checks ausführen. +

    + +

    +Auszug aus var/perfdata.log: + +

    +
    +2007-10-18 12:05:01 [21138] 71 Lines processed
    +2007-10-18 12:05:01 [21138] .../spool/service-perfdata-1192701894-PID-21138 deleted
    +2007-10-18 12:05:01 [21138] PNP exiting (runtime 0.060969s) ...
    +
    + +

    +71 Zeilen wurden in 0,06 Sekunden verarbeitet. Das ist das Datenvolumen bei ca. 2000 Services und der Verarbeitung im 10-Sekunden-Intervall. Wir haben Nagios also genau für 0.06 Sekunden blockiert. +

    + +
    + +

    Bulk Mode mit NPCD

    +
    + +

    + +Dies ist aus Nagios-Sicht die sauberste Art der Verarbeitung. Nagios wird nicht blockiert. +

    + +

    +Nagios benutzt wieder eine temporäre Datei, um die Daten zu speichern, und führt nach Ablauf der Zeit wieder ein Command aus. Jedoch wird die Datei nicht sofort von Process_perfdata.pl verarbeitet, sondern in ein spool-Verzeichnis verschoben. Da das Verschieben einer Datei im gleichen Filesystem so gut wie keine Zeit beansprucht, ist Nagios sofort wieder in der Lage, wichtige Arbeiten auszuführen. +

    + +

    +Der NPCD ( Nagios Performance C Daemon ) überwacht nun das Verzeichnis auf neue Dateien und übergibt diese an process_perfdata.pl. Die Verarbeitung der Performancedaten ist also komplett von Nagios entkoppelt. NPCD wiederum ist in der Lage, zum Verarbeiten der Daten mehrere Threads zu starten. +

    + +
    + +

    Bulk Mode mit npcdmod

    +
    + +

    + +Achtung +Beginnend mit Nagios 4 haben sich die internen Strukturen geändert, so dass der Start des Moduls fehlschlägt. Bisher gibt es keine Pläne Nagios 4 zu unterstützen. Bitte wählen Sie einen der anderen Modi. +

    + +

    +In diesem Szenario kommt npcdmod.o, ein NEB-Modul, zum Einsatz. +Diese Modul reduziert die Konfiguration des “Bulk Mode mit NPCD” auf zwei Zeilen in der nagios.cfg. +

    + +

    +Dieser Modus ist gleichzusetzen mit dem “Bulk Mode mit NPCD”. Es ist auch genau der gleiche Ablauf und die gleiche Performance. +

    + +
    + +

    Gearman Mode

    +
    + +

    + +

    + +

    +PNP4Nagios kann seit Version 0.6.12 als Gearman Worker betrieben werden. So sind große verteilte Nagios Umgebungen auf Basis von mod_gearman realisierbar. +

    + +

    +Benötigt wird eine fertig eingerichtete mod_gearman Installation wie von Sven Nierlein unter http://labs.consol.de/lang/en/nagios/mod-gearman/ beschrieben. +

    + +
    + +

    Die Entscheidung

    +
    + +

    + +Welchen der beschriebenen Wege ihr verwendet, hängt also stark von der Größe der Nagios-Installation ab. +

    + +

    +Die verwendeten Begriffe werden euch aber in der Dokumentation immer wieder über den Weg laufen. +

    + +

    +Zurück zur Übersicht | Installation + +

    + +
    + +
    +
    + + + +

    Upgrade auf Version 0.6.x

    +
    + +

    + +Das Web-Frontend ist komplett neu geschrieben worden und basiert nun auf dem PHP MVC Framework Kohana. Somit ergeben sich grundlegend andere Abhängigkeiten, die dringend vor der Installation geprüft werden müssen. +

    + +

    +Anmerkung: Ein Upgrade läuft zuerst wie eine Neuinstallation. Anschließend sind einige Anpassungen durchzuführen, die weiter unten beschrieben sind. +

    + +

    +PNP 0.4.x wurde ohne weitere Angabe von Optionen beim Aufruf von ./configure unterhalb einer Nagios-Installation unter /usr/local/nagios installiert. +

    + +

    +PNP 0.6.x wird bei Angabe keiner weiteren Optionen unter /usr/local/pnp4nagios installiert, ist also wie Nagios als eigenständige Applikation zu sehen. +

    + +

    +Anmerkung: Es reicht aus, die *.rrd-Dateien vom alten ins neue Verzeichnis zu kopieren. Sie enthalten die eigentlichen Daten. Die *.xml-Dateien werden jedes Mal neu angelegt, wenn Performance-Daten verarbeitet werden, denn sie enthalten lediglich Meta-Informationen. Außerdem hat sich die interne Struktur geändert, so dass sie sowieso nicht nutzbar sind. +

    + +
    + +

    Vergleich der Struktur

    +
    + +

    + +Summary einer Installation von PNP 0.4.14 +

    +
    +./configure
    +...
    +*** Configuration summary for pnp 0.4.14 05-02-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/nagios
    +  HTML Dir:                         /usr/local/nagios/share/pnp
    +  Config Dir:                       /usr/local/nagios/etc/pnp
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/nagios/share/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/nagios/var/spool/perfdata/
    +
    + +

    +Summary einer Installation von 0.6.0 +

    +
    +./configure
    +...
    +*** Configuration summary for pnp4nagios-0.6.0 07-30-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    + +

    +Aus diesen Infos ergeben sich die zu ändernden Parameter und somit die Upgrade-Strategie. +

    + +
    + +

    Anpassungen

    +
    + +

    + +Die Vorlagen der action_url-Definitionen haben sich verändert. Statt ”/nagios/pnp” ist ”/pnp4nagios” einzutragen und statt “index.php” wird nun “graph” benutzt +

    +
    define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    + +

    +Ähnliches gilt für die Preview-Popup-Funktion +

    +
    define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    + +

    + +Achtung: Es ist kein Fehler, dass die Zeichenketten vor und nach “class” jeweils nur ein Apostroph enthalten. +

    + +

    +Anders als in der 0.4.x Dokumentation vermerkt gelten die Templates für Nagios 2.x und 3.x. Der einzige Unterschied besteht darin, dass die action_url-Direktive in Nagios 2.x nicht in der Service-Definition, sondern in eigenen serviceextinfo-Definitionen verfügbar ist. +

    + +

    +Innerhalb der PHP-Dateien im templates-Verzeichnis müssen alle Variablen vor der ersten Benutzung initialisiert werden, z.B. +

    +
    $lower = ""
    + +

    + +Das gilt auch für Variablen, an die früher “angehängt” werden konnte, ohne sie vorher zu initialisieren. Daher wird aus + +

    +
    foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    + +nun + +

    +
    +$def[1] = "";
    +foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    +
    + +Konstanten in Template-Dateien funktionieren nicht mehr, so dass diese in Variablen umzuwandeln sind. Aus +

    +
    define("_WARNRULE", '#FFFF00');
    + +

    +wird dann z.B. +

    +
     $WARNRULE = '#FFFF00';
    + +

    +Man sollte daran denken, alle Vorkommen in der Datei zu ändern ;-). +

    + +
    + +

    Upgrade Szenario mit NPCD

    +
    +
      +
    1. Planen des neuen Aufbaus.
      +
    2. +
    3. Testinstallation durchführen und sich mit dem neuen System vertraut machen.
      +
    4. +
    5. Backup erstellen.
      +
    6. +
    7. PNP 0.6.x nach /usr/local/pnp4nagios installieren.
      +
    8. +
    9. make install-config
      +
    10. +
    11. make install-webconf
      +
    12. +
    13. Apache reload.
      +
    14. +
    15. Apache-Config testen.
      +
        +
      1. Aufruf /pnp4nagios muss ein leeres Perfdata-Verzeichnis melden.
        +
      2. +
      +
    16. +
    17. /usr/local/pnp4nagios/etc/npcd.cfg aus der npcd.cfg-sample erstellen.
      +
        +
      1. Pfade überprüfen und ggf. Änderungen der 0.4.x nachziehen.
        +
      2. +
      +
    18. +
    19. Alle Pfade zur neuen Installation in der nagios.cfg anpassen.
      +
    20. +
    21. Alle Pfade in den Command-Definitionen anpassen.
      +
    22. +
    23. npcd über /etc/init.d/npcd stop anhalten.
      +
    24. +
    25. make install-init installiert das neue Init Script für den npcd.
      +
    26. +
    27. Nagios anhalten.
      +
    28. +
    29. /usr/local/nagios/share/perfdata nach /usr/local/pnp4nagios/var/perfdata kopieren. Achtung: Auf Permissions achten.
      +
    30. +
    31. /etc/init.d/npcd start
      +
    32. +
    33. /etc/init.d/nagios start
      +
    34. +
    + +
    + +
    +
    + + + +

    Installation

    +
    + +

    + +Im Folgenden wird die Installation von PNP beschrieben. Dabei wird davon ausgegangen, dass Nagios aus den Sourcen übersetzt und im Verzeichnis /usr/local/nagios installiert wurde.
    + +Achtung: Die Beschreibung bezieht sich auf die Developer-Version PNP 0.6.0.
    + +Bitte vergessen Sie nicht, dass PNP nach der Installation noch konfiguriert werden muss. +

    + +
    + +

    Make und Co

    +
    + +

    + +Die Installation von PNP wird wie bei Nagios auch über Makefiles gesteuert. Dabei wird durch den Aufruf von ./configure das System analysiert und die ermittelten Werte in Makefiles übernommen. +

    + +

    +Als User root wird PNP in /usr/local/src entpackt. + +

    +
    +tar -xvzf pnp4nagios-HEAD.tar.gz
    +cd pnp4nagios
    +
    + +

    +Im Verzeichnis pnp4nagios wird nun ./configure aufgerufen. +

    +
    +./configure
    +
    + +

    + +Hinweis: Ohne weitere Optionen werden als Benutzer und Gruppe “nagios” verwendet. Bei abweichenden Werten sind die Parameter ”--with-nagios-user” und ”--with-nagios-group” zu benutzen. Im Falle von Icinga könnte der Aufruf so aussehen + +

    +
    +./configure --with-nagios-user=icinga --with-nagios-group=icinga
    +
    + +

    +Es laufen einige Zeilen über den Bildschirm. Wichtig ist die Ausgabe zum Schluss. +

    +
    +*** Configuration summary for pnp4nagios-0.6.2 23-12-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.2.12
    +  RRDs Perl Modules:                FOUND (Version 1.2012)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    +
    +  Review the options above for accuracy.  If they look okay,
    +  type 'make all' to compile.
    + +

    +Die angezeigten Pfade sollten nun geprüft werden. Falls die gezeigten Werte nicht passen, kann durch einen erneuten Aufruf von ./configure mit den passenden Optionen Abhilfe geschaffen werden.
    + +ACHTUNG: Nachdem es immer wieder Schwierigkeiten gibt: “Location of rrdtool binary” bedeutet inkl. Namen des Binary! Bei Bedarf kann man das beim ./configure als Parameter angeben: + +

    +
     ./configure --with-rrdtool=/usr/local/rrdtool-1.2.xx/bin/rrdtool
    +
     ./configure --help 
    + +

    + +zeigt, welche Optionen möglich sind.
    +
    + +Ein +

    +
    make all
    + +

    +kompiliert nun die in C geschriebenen Komponenten wie NPCD +

    +
    make install
    + +

    +kopiert alles an die richtige Stelle im Filesystem. Die Pfade wurden ja beim ./configure bereits gezeigt. +

    + +

    +Nach der Installation der Programm- und HTML-Dateien wird mit +

    +
    make install-webconf
    + +

    +eine Konfigurationsdatei in das Konfigurationsverzeichnis des Apache-Web-Servers kopiert. +

    + +

    +Optional kann noch +

    +
    make install-config
    + +

    +aufgerufen werden. Damit werden Config-Files für process_perfdata.pl und npcd nach etc/pnp kopiert. +

    + +

    +Wird das INIT Script für den NPCD benötigt, so sorgt +

    +
    make install-init
    + +

    +für die Installation nach /etc/init.d +

    + +

    +Zusammenfassen lassen sich diese einzelnen Commands durch +

    +
    make fullinstall
    + +

    +Hinweis: Wie oben schon beschrieben wird standardmässig mit den Nagios-Einstellungen installiert. Wird Icinga genutzt, muss in der Datei ”/etc/apache2/conf.d/pnp4nagios.conf” der Pfad zum AuthUserFile angepasst werden (Pfad evtl. je nach Distri anpassen): +

    +
    +#       AuthUserFile /usr/local/nagios/etc/htpasswd.users
    +        AuthUserFile /usr/local/icinga/etc/htpasswd.users
    +
    + +

    +Achtung: Nach dem Kopieren der Konfigurationsdatei für den Web-Server bzw. Ändern des AuthUserFile ist ein Restart des Web-Servers notwendig (service httpd restart bzw. /etc/init.d/apache2 restart). +

    + +
    + +

    Update

    +
    + +

    + +Das Update einer 0.6.x-Version funktioniert (fast) genauso wie die Installation. Bitte beachten Sie, dass Sie beim ”./configure” die gleichen Optionen wie bei der Erstinstallation benutzen! +Bitte prüfen Sie außerdem, ob Sie Änderungen im Verzeichnis share/templates.dist vorgenommen haben. Eigene Templates sollten im Ordner share/templates abgelegt werden.
    + +Achtung: Wenn Sie in der Datei config.php Änderungen vorgenommen haben, sollten Sie diese Datei sichern, bevor sie bei einem “make install-config” überschrieben wird. +

    + +

    +Sie können die Schritte make install-webconf und make install-init überspringen, denn zwischen den 0.6.x-Versionen gab es an dieser Stelle keine Änderungen. +

    + +
    + +

    Die Komponenten

    +
    + +

    + +Nach der Installation sind einige Komponenten von PNP an die passenden Stellen im Dateisystem kopiert worden. +

    + +

    +Im Folgenden sind dies die PHP-Files für das Web-Frontend unter + +

    +
     /usr/local/pnp4nagios/share
    + +

    + +Der Datensammler process_perfdata.pl in + +

    +
     /usr/local/pnp4nagios/libexec
    + +

    + +Beispiel-Config-Files mit der Dateierweiterung -sample in + +

    +
     /usr/local/pnp4nagios/etc
    + +

    + +Die Config-Datei config.php für das Web-Frontend in + +

    +
     /usr/local/pnp4nagios/etc
    + +

    +Zurück zur Übersicht | Konfiguration + +

    + +
    + +
    +
    + + + +

    Konfiguration

    +
    + +

    + +Im Folgenden wird die Konfiguration der bereits erwähnten Arten der Performance-Daten Verarbeitung genauer erklärt. +

    + +

    +Die bevorzugte Methode der PNP-Entwickler ist der “Bulk Mode mit NPCD und npcdmod”. +

    + +
    + +

    Synchronous Mode

    +
    + +

    + +Der Synchronous-Mode ist die einfachste Art, den Datensammler process_perfdata.pl in Nagios zu integrieren. Hierbei wird bei jedem Ereignis ein gesondertes Command process-service-perfdata (bzw. process-host-perfdata) ausgeführt. +

    + +

    +Grundsätzlich ist in der nagios.cfg die Verarbeitung der Performance-Daten zu aktivieren. Bitte beachten Sie, dass diese Direktive wahrscheinlich bereits in der Konfigurationsdatei enthalten ist (Default ist “0”). + +

    +
     process_performance_data=1
    + +

    + +Für jeden Host und jeden Service, für den KEINE Performance-Daten verarbeitet werden sollen, ist die Verarbeitung der Performance-Daten explizit auszuschalten. +

    +
    +define service {
    +   ...
    +   process_perf_data 0
    +   ...
    +}
    +
    + +

    +Weiterhin ist es ab Nagios 3.x möglich, in der nagios.cfg das Exportieren der Environment-Variablen zu deaktivieren. Diese sind jedoch für den Synchronous-Mode zwingend erforderlich. Daher muss + +

    +
    enable_environment_macros=1
    + +

    + +ebenfalls in der nagios.cfg gesetzt sein. +

    + +

    +Zusätzlich wird das Kommando zum Verarbeiten der Performance-Daten in der nagios.cfg angegeben. + +

    +
     service_perfdata_command=process-service-perfdata
    + +

    + +Ab Nagios 3.x ist es durchaus sinnvoll, auch die Verarbeitung der Performance-Daten für Hosts einzuschalten. Nagios 3 führt durch die geänderte Hostcheck-Logik nun auch die Prüfung der Hosts regelmäßig aus. + +

    +
     host_perfdata_command=process-host-perfdata
    + +

    + +Die referenzierten Commands müssen natürlich auch Nagios bekannt gegeben werden. Wie man sieht, sind für den Aufruf von process_perfdata.pl so gut wie keine Optionen nötig. Einzig bei Performance-Daten der Host-Checks ist die Option -d ( DATATYPE ) nötig. Wenn Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die Definitionen in der Datei commands.cfg anpassen. +

    +
    +define command {
    +       command_name    process-service-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +}
    +
    +define command {
    +       command_name    process-host-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA
    +}
    +
    + +

    +HINWEIS: process_perfdata.pl kann nicht unter Kontrolle des ePN ( embedded Perl Nagios ) gestartet werden. Daher wird das Script explizit mit /usr/bin/perl aufgerufen. Wird ePN nicht verwendet oder wird Nagios 3.x verwendet, kann auf die Angabe von /usr/bin/perl verzichtet werden. +

    + +

    +zurück zur Übersicht | Funktion prüfen +

    + +
    + +

    Bulk Mode

    +
    + +

    + +Der Bulk-Mode ist etwas komplizierter als der Synchronous-Mode, reduziert die Last auf dem Nagios Server jedoch merklich, da nun nicht mehr für jeden Service bzw. Host zusätzlich der Datensammler process_perfdata.pl gestartet werden muss. +

    + +

    +Im Bulk-Mode schreibt Nagios die Daten in einem definierten Format in eine temporäre Datei. Diese Datei wiederum wird periodisch von process_perfdata.pl verarbeitet. Um den Start und den Intervall kümmert sich dabei Nagios selbst. +

    + +

    +Auch hier muss die Verarbeitung der Performance-Daten in der nagios.cfg eingeschaltet werden. + +

    +
     process_performance_data=1
    + +

    + +Zusätzlich werden einige neue Parameter benötigt. +

    +
    +#
    +# Service Performance-Daten
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# Host Performance-Daten ab Nagios 3.x
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    +Achtung: Die Template-Definitionen weichen von denen in der Original-nagios.cfg ab! +

    + +

    +Die Parameter und deren Bedeutung im Einzelnen: + +

    +
      +
    • service_perfdata_file Der Pfad zur temporären Datei, in der die Daten gesammelt werden sollen.
      +
    • +
    • service_perfdata_file_template Das Format der temporären Datei. Hier werden die Daten über Nagios-Macros definiert.
      +
    • +
    • service_perfdata_file_mode Die Option “a” definiert, dass an die Datei angehangen werden soll.
      +
    • +
    • service_perfdata_file_processing_interval Das Intervall beträgt 15 Sekunden
      +
    • +
    • service_perfdata_file_processing_command das Command, das im definierten Intervall aufgerufen werden soll.
      +
    • +
    + +

    + +Die verwendeten Commands müssen Nagios wiederum bekannt gegeben werden. Wenn Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die Definitionen in der Datei commands.cfg anpassen. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/service-perfdata
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/host-perfdata
    +}
    +
    +
    + +
    +

    HINWEIS:

    +
    Da process_perfdata.pl nun mehr Daten zu verarbeiten hat als im Default Mode, kommt es natürlich auch zu längeren Laufzeiten. Daher ist der TIMEOUT Wert in der etc/process_perfdata.cfg zu überprüfen und ggf. anzupassen.
    +
    + +
    + +

    +zurück zur Übersicht | Funktion prüfen +

    + +
    + +

    Bulk Mode with NPCD

    +
    + +

    + +Die Konfiguration ist identisch mit dem “Bulk Mode”, einzig das verwendete Command ist leicht abgewandelt. +

    + +

    +Auch hier muss die Verarbeitung der Performance-Daten in der nagios.cfg eingeschaltet werden. + +

    +
     process_performance_data=1
    + +

    + +Zusätzlich werden einige neue Parameter benötigt. +

    +
    +#
    +# Service Performance-Daten
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# Host Performance-Daten ab Nagios 3.x
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    +Achtung: Die Template-Definitionen weichen von denen in der Original-nagios.cfg ab! +

    + +

    +Die Parameter und deren Bedeutung im Einzelnen: + +

    +
      +
    • service_perfdata_file Der Pfad zur temporären Datei, in der die Daten gesammelt werden sollen.
      +
    • +
    • service_perfdata_file_template Das Format der temporären Datei. Hier werden die Daten über Nagios-Macros definiert.
      +
    • +
    • service_perfdata_file_mode Die Option “a” definiert, dass an die Datei angehangen werden soll.
      +
    • +
    • service_perfdata_file_processing_interval Das Intervall beträgt 15 Sekunden
      +
    • +
    • service_perfdata_file_processing_command das Command, das im definierten Intervall aufgerufen werden soll.
      +
    • +
    + +

    + +Die verwendeten Commands müssen Nagios wiederum bekannt gegeben werden. Wenn Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die Definitionen in der Datei commands.cfg anpassen. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/service-perfdata /usr/local/pnp4nagios/var/spool/service-perfdata.$TIMET$
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/host-perfdata /usr/local/pnp4nagios/var/spool/host-perfdata.$TIMET$
    +}
    +
    + +

    +Durch die Kommandos wird immer nach Ablauf des über service_perfdata_file_processing_interval eingestellten Intervalls die Datei service-perfdata nach var/spool/ verschoben. Dabei wird das Nagios-Macro $TIMET$ verwendet, an den Dateinamen angehängt, um zu verhindern, dass alte Dateien ungewollt überschrieben werden. Das Macro $TIMET$ enthält den aktuellen Zeitstempel in Unix-Time-Format ( Sekunden seit 1.1.1970 ). +

    + +

    +Somit sammeln sich Dateien im Verzeichnis /usr/local/pnp4nagios/var/spool/, die nun mit Hilfe des NPCD verarbeitet werden. +

    + +

    +NPCD überwacht das Spool-Verzeichnis und übergibt wiederum alle gefundenen Dateien an process_perfdata.pl. Damit ist die Verarbeitung der Performancedaten komplett von Nagios entkoppelt. Wir müssen nur noch den NPCD starten. + +

    +
     /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +Die Option -d veranlasst NPCD im Hintergund als Daemon seinen Dienst zu verrichten. +

    + +

    +Das Init Script für den NPCD wir während der Installation über “make install-init” installiert und kann somit auch für den Start verwendet werden. + +

    +
     /etc/init.d/npcd start
    + +

    + +In der Config-Datei des NPCD, der npcd.cfg, ist vor dem ersten Start zu prüfen, ob die Pfade zum Spool-Verzeichnis und zu process_perfdata.pl richtig gesetzt sind. +

    + +

    +Weitere Informationen zu NPCD findet ihr hier. +

    + +
    + +

    Bulk Mode with NPCD und npcdmod

    +
    + +

    + +Achtung +Beginnend mit Nagios 4 haben sich die internen Strukturen geändert, so dass der Start des Moduls fehlschlägt. Bisher gibt es keine Pläne, Nagios 4 zu unterstützen. Bitte wählen Sie einen der anderen Modi. +

    + +

    + Bei diesem Modus kommt das Eventbroker-Modul npcdmod.o zu Einsatz. Der Datenfluss ist jedoch identisch zum “Bulk Mode mit NPCD”. Die internen Perfdata-Routinen von Nagios, die über die “*_perf_data_*” Optionen in der nagios.cfg konfiguriert werden, kommen NICHT mehr zu Einsatz. Das Modul npcdmod.o kümmert sich um die für PNP nötige Aufbereitung der Daten. +

    + +

    +Vorteil: +

    +
      +
    • Die Perfdata-Routinen innerhalb von Nagios stehen wieder für andere Addons zur Verfügung.
      +
    • +
    • Die Konfiguration reduziert sich.
      +
    • +
    • Die bevorzugte Methode der PNP-Entwickler.
      +
    • +
    + +

    + +Anpassung in der nagios.cfg: +

    +
    +process_performance_data=1
    +broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +
    + +

    +Alle anderen auf dieser Seite gezeigten Optionen dürfen für diesen Modus NICHT mehr verwendet werden. +

    + +

    +Achtung: Wichtig sind in diesem Zusammenhang auch die event_broker_options bei einem von -1 abweichenden Wert. Für PNP müssen die Bits 2 und 3 gesetzt sein (0b01100; siehe auch http://www.nagios-wiki.de/nagios/ndo/eventbroker_optionen). +

    + +

    +Nach dem Neustart von Nagios werden Informationen zum Ladevorgang des Moduls protokolliert. +

    + +

    +Auszug aus den nagios.log + +

    +
    +[1277545053] npcdmod: Copyright (c) 2008-2009 Hendrik Baecker (andurin@process-zero.de) - http://www.pnp4nagios.org
    +[1277545053] npcdmod: /usr/local/pnp4nagios/etc/npcd.cfg initialized
    +[1277545053] npcdmod: spool_dir = '/usr/local/pnp4nagios/var/spool/'.
    +[1277545053] npcdmod: perfdata file '/usr/local/pnp4nagios/var/perfdata.dump'.
    +[1277545053] npcdmod: Ready to run to have some fun!
    +[1277545053] Event broker module '/usr/local/pnp4nagios/lib/npcdmod.o' initialized successfully.
    +
    + +
    + +

    Gearman Mode

    +
    + +

    + + +

    + +

    +PNP4Nagios kann seit Version 0.6.12 als Gearman-Worker betrieben werden. So sind große verteilte Nagios-Umgebungen auf Basis von mod_gearman realisierbar. Außerdem kann man dadurch Nagios und PNP4Nagios auf unterschiedliche Rechner verteilen. +

    + +

    +Benötigt wird eine fertig eingerichtete mod_gearman Installation wie von Sven Nierlein unter http://labs.consol.de/lang/en/nagios/mod-gearman/ beschrieben. +

    + +

    +In etc/process_perfdata.cfg gibt es einen gearman-Abschnitt: +

    +
     PREFORK = 1
    + GEARMAN_HOST = localhost:4730
    + REQUESTS_PER_CHILD = 10000
    + ENCRYPTION = 1
    + KEY = should_be_changed
    + #KEY_FILE = /usr/local/pnp4nagios/etc/secret.key
    + 
    + +

    +Dort ist mit PREFORK = <n> die Anzahl der zu startenden Kindprozessen anzugeben. +

    + +

    +GEARMAN_HOST = <host>:<port> definiert Rechner und Port, auf dem der gearman-Daemon die Daten bereitstellt. +Über REQUESTS_PER_CHILD = <n> kann die maximal zu verarbeitende Anzahl von Anforderungen pro Prozess eingestellt werden. +

    + +

    +ENCRYPTION = <1|0> stellt ein, ob Verschlüsselung benutzt werden soll. Die Standardeinstellung ist eine aktivierte Verschlüsselung (“1”) und das sollte nur in Ausnahmefällen verändert werden. +Dabei kann entweder über KEY = <Schlüssel> der zu benutzende Schlüssel definiert oder per KEY_FILE = <Schlüsseldatei> der Standort einer Schlüsseldatei angegeben werden. +

    + +

    + +/etc/init.d/pnp_gearman_worker enthält Verweise auf die Perl-Prozedur process_perfdata.pl sowie die Konfigurationsdatei process_perfdata.cfg. +

    + +

    + +Nach dem Start des PNP-Daemons per + +

    +
     /etc/init.d/pnp_gearman_worker start
    + +

    + +werden die Performance-Daten verarbeitet, die über den gearmand-Daemon auf dem Nagios-Rechner zur Verfügung gestellt werden. +

    + +

    +zurück zur Übersicht | Funktion prüfen + +

    + +
    + +
    +
    + + + +

    Prüfen der Installation

    +
    + +

    + +Wenn bis jetzt alles sauber funktioniert hat, kann PNP zum ersten Mal im Browser aufgerufen werden. +Bei der Installation mit den Standardeinstellungen erfolgt der Aufruf über http://<Servername>/pnp4nagios/. +

    + +

    +Beim ersten Aufruf sieht man die Seite “PNP4Nagios Environment Tests”, die verschiedene Tests von notwendigen Komponenten enthält. Offenkundig sollten alle Tests erfolgreich verlaufen, bevor es weitergehen kann. Bitte beachten Sie die Hinweise auf der Seite.
    + +

    + +

    +Sind alle Tests erfolgreich verlaufen, so kann die Datei pnp4nagios/share/install.php gelöscht oder umbenannt werden. Erst dann ist das Webinterface erreichbar. +

    + +

    +Alternativ kann eine Datei pnp4nagios/share/install.ignore angelegt werden, um den Aufruf des Installers nach weiteren Updates zu ignorieren. +

    + +

    +Ohne weitere Optionen sucht PNP nach RRD- und XML-Dateien in pnp4nagios/var/perfdata/ und zeigt alle Graphen des ersten Hosts in der Übersicht an. +

    + +

    +ACHTUNG: Direkt nach dem (Neu-)Start von Nagios nach dem Aktivieren der Verarbeitung von Performance-Daten wird der Aufruf im Browser zu Fehlermeldungen führen, weil zunächst Performance-Daten gesammelt und in den RRD-Dateien abgelegt werden müssen. Abhängig vom Check-Intervall kann es einige Zeit dauern, bis die ersten Graphen angezeigt werden können. +

    + +
    + +

    Logfile

    +
    + +

    + +Während der Installation wurde durch den Aufruf von make install-config ein Beispiel-Config-File etc/process_perfdata.cfg-sample erzeugt. Die Werte in der sample-Datei entsprechen den Default-Werten, die auch in process_perfdata.pl fest hinterlegt sind, daher ist die process_perfdata.cfg für den Betrieb nicht zwingend notwendig. +

    + +

    +Die Datei process_perfdata.cfg-sample kann somit als Vorlage für die process_perfdata.cfg dienen, die immer dann notwendig ist, wenn vom Standard abweichende Werte eingestellt werden sollen. +

    + +

    +In der process_perfdata.cfg lässt sich das Verhalten von process_perfdata.pl vielfach beeinflussen. +

    + +

    +Die wichtigsten Optionen für die Inbetriebnahme sind LOG_LEVEL und LOG_FILE. Im laufenden Betrieb sollte der Log-Level immer auf 0 gesetzt sein, um die Performance von process_perfdata.pl nicht durch unnötiges Schreiben von Logfiles zu beeinträchtigen. +

    + +

    +Während der Inbetriebnahme sollte man jedoch den LOG_LEVEL auf “2” setzen, um zu sehen, was process_perfdata.pl bei der Verarbeitung der Performance-Daten so alles anstellt. +

    + +

    +Spätestens bei Support Anfragen im Forum oder auf den Mailinglisten werden wir sowohl nach Auszügen aus dem perfdata.log als auch nach der Ausgabe des verify_pnp_config-Scripts fragen. Es empfiehlt sich also, diese Angaben gleich mitzuliefern ;-). +

    + +
    + +

    Was aber wenn nicht ?

    +
    + +

    + +Einige grundlegende Einstellungen sind zu prüfen. +

    + +

    +1. Sind RRD- und XML-Files erzeugt worden ? +

    + +

    +process_perfdata.pl legt für jeden Host unter var/perfdata ein neues Verzeichnis an. In diesem Verzeichnis wird wiederum für jeden Service eine RRD-Datenbank und ein XML-File erstellt. Für den Host-Check lautet der Dateinamen _HOST_.xml bzw. _HOST_.rrd.
    + +Falls Graphen urplötzlich nicht mehr weitergeführt werden, dann hilft vielleicht ein Blick in die betroffene XML-Datei. Dort gibt es u.a. die Tags <RC> und <TXT>. <RC> zeigt den Return-Code des RRDtool-Updates der RRD-Datei, <TXT> eine textuelle Beschreibung.
    + +Allerdings liefern nicht alle Checks Performance-Daten, das gilt u.a. für “check_ping”, die Alternative “check_icmp” dagegen erzeugt Daten (ab Nagios-Plugin-Version 1.4.12 liefert auch check_ping Performance-Daten).
    + +Teilweise muss man zusätzliche Optionen aktivieren, damit Performance-Daten ausgegeben werden. Evtl. kann das auch durch ein Wrapper-Script geändert werden.
    + +In den Detailinformationen zu jedem Host/Service gibt es das Feld “Performance-Data”. Wenn dort keine Daten stehen, dann werden im jeweiligen Verzeichnis keine Dateien erzeugt und PNP kann deshalb auch keine grafischen Auswertungen liefern!
    + +Das folgende Bild zeigt die Informationen zu einem “PING”-Service. Das blaue Feld enthält den vom Plugin gelieferten Text, das rote die Performance-Daten, die Nagios erkannt hat.
    + +Informationen zu "PING" +

    + +

    +2. Hat Nagios process_perfdata.pl aufgerufen ? +

    + +

    +In der Config-Datei für process_perfdata.pl, der etc/process_perfdata.cfg lässt sich der Debug-Level erhöhen. Die Verarbeitung der Daten wird nun in var/perfdata.log bzw. im Syslog protokolliert. +

    + +

    +3. Grafiken werden ohne Text angezeigt ? +

    + +

    +siehe Anforderungen +

    + +

    +4. Einige Graphen werden angezeigt, andere melden den Fehler “parser error: Input is not proper UTF-8” oder etwas ähnliches. Bitte prüfen Sie, ob die Daten “spezielle” Zeichen enthalten, die nicht im ASCII-Zeichensatz vorhanden sind (Umlaute, etc). Versuchen Sie, in process_perfdata.cfg den Wert von XML_ENC auf ISO-8859-1 oder einen anderen passenden Wert zu setzen. Warten Sie, bis die xml-Datei neu erzeugt wurde und probieren Sie es nochmal. +

    + +

    +5. Bei aktiviertem npcdmod-Modul muss der Wert von event_broker_options in der nagios.cfg ggf. angepasst werden. Hinweise gibt es hier. +

    + +

    +6. verify_pnp_config +Das Perl-Script verify_pnp_config.pl ermöglicht die Prüfung von Konfigurationseinstellungen und zeigt, ob Performance-Daten vorhanden sind. +

    + +

    +7. Es scheint zu funktionieren, aber es bleiben einige Dateien Spool-Verzeichnis stehen (/usr/local/pnp4nagios/var/spool/<perfdata_filename>-PID-<process_perfdata_pid>). Wenn process_perdata.pl nicht in das Zielverzeichnis (/usr/local/pnp4nagios/share/perfdata/<host>) schreiben kann, wird es anhalten und die Quelldatei nicht löschen. Das erhöht die Größe des Spool-Verzeichnisses und die Verarbeitung der Performance-Daten verlangsamen. Dieses Problem kann auftreten, wenn Sie Verzeichnisse aus einer vorherigen Installation kopiert und/oder manuell Verzeichnisse angelegt haben und dabei die falschen Benutzer/Berechtigungen verwendet haben. +

    + +

    +zurück zur Übersicht | verify_pnp_config.pl + +

    + +
    + +
    +
    + + + +

    verify_pnp_config

    +
    + +

    + +Bei Problemen kann das Perl-Script verify_pnp_config von http://verify.pnp4nagios.org helfen die aktuelle Nagios/Icinga Konfiguration zu prüfen und entsprechend Hinweise zur Lösung liefern. +

    + +

    +Bei Support Anfragen sollte immer die Ausgabe dieses Scripts mit angegeben werden, da die Entwickler sich so einen besseren Überblick über das verwendete System machen können. +

    + +

    +Feedback, Verbesserungsvorschläge oder Patches bitte per Mail an support@pnp4nagios.org +

    + +
    + +

    Download

    +
    + +

    + +Das Verify Script ist unter http://verify.pnp4nagios.org verfügbar. +

    +
    +wget http://verify.pnp4nagios.org/verify_pnp_config
    +
    + +
    + +

    Test

    +
    + +

    + +Das Verify Script benötigt drei Optionen um die Funktion von PNP4Nagios zu prüfen +

    +
    +lenny:~# perl verify_pnp_config
    +
    +verify_pnp_config -m|--mode=[sync|bulk|bulk+npcd|npcdmod]
    +                 -c|--config=[path to nagios.cfg]
    +                 -p|--pnpcfg=[path to PNP config dir]
    +
    + +

    +Die wichtigste Infos ist der zu prüfende Modus, welcher mit der Option --mode angegeben wird.
    + +Weitere Infos über die einzelnen Modi und deren Konfiguration unter "Welcher Modus ist für mich richtig ?" und "Konfiguration" +

    + +

    +Weiterhin ist der Pfad zur Nagios Config Datei (nagios.cfg) über die Option --config zu übergeben. Auf einem Icinga System ist es entsprechend der Pfad zur icinga.cfg. +

    + +

    +Über --pnpcfg wird der Pfad zum etc Verzeichnis der PNP4Nagios Installation übergeben.
    + +

    + +

    +Beim Aufruf von perl verify_pnp_config werden die verfügbaren Optionen ausgegeben. +

    +
    +lenny:~# perl verify_pnp_config --mode npcdmod --config=/usr/local/nagios/etc/nagios.cfg --pnpcfg=/usr/local/pnp4nagios/etc
    +[INFO]  ========== Starting Environment Checks ============
    +[INFO]  My version is: verify_pnp_config-0.6.14-R.31
    +[INFO]  Reading /usr/local/nagios/etc/nagios.cfg
    +[OK  ]  Running product is 'nagios'
    +[OK  ]  object_cache_file is defined
    +[OK  ]  object_cache_file=/usr/local/nagios/var/objects.cache
    +[INFO]  Reading /usr/local/nagios/var/objects.cache
    +[OK  ]  resource_file is defined
    +[OK  ]  resource_file=/usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/process_perfdata.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/pnp4nagios_release
    +[OK  ]  Found PNP4Nagios version "0.6.14"
    +[OK  ]  Effective User is 'nagios'
    +[OK  ]  User nagios exists with ID '1000'
    +[OK  ]  Effective group is 'nagios'
    +[OK  ]  Group nagios exists with ID '1000'
    +[INFO]  ========== Checking npcdmod Mode Config  ============
    +[OK  ]  process_performance_data is 1 compared with '/1/'
    +[OK  ]  event_broker_options is defined
    +[OK  ]  event_broker_options=-1
    +[OK  ]  event_broker_option bits 2 and 3 enabled (12)
    +[OK  ]  broker_module is defined
    +[OK  ]  broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  npcdmod.o config file is /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg used by npcdmod.o is readable
    +[OK  ]  npcd daemon is running
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg is used by npcd and readable
    +[OK  ]  npcd and npcdmod.o are using the same config file (/usr/local/pnp4nagios/etc/npcd.cfg)
    +[INFO]  Nagios config looks good so far
    +[INFO]  ========== Checking config values ============
    +[INFO]  Reading /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  Script /usr/local/pnp4nagios/libexec/process_perfdata.pl is executable
    +[INFO]  ========== Starting global checks ============
    +[OK  ]  status_file is defined
    +[OK  ]  status_file=/dev/shm/status.dat
    +[INFO]  Reading /dev/shm/status.dat
    +[INFO]  ==== Starting rrdtool checks ====
    +[OK  ]  RRDTOOL is defined
    +[OK  ]  RRDTOOL=/usr/bin/rrdtool
    +[OK  ]  /usr/bin/rrdtool is executable
    +[OK  ]  RRDtool 1.3.1  Copyright 1997-2008 by Tobias Oetiker <tobi@oetiker.ch>
    +[OK  ]  USE_RRDs is defined
    +[OK  ]  USE_RRDs=1
    +[OK  ]  Perl RRDs modules are loadable
    +[INFO]  ==== Starting directory checks ====
    +[OK  ]  RRDPATH is defined
    +[OK  ]  RRDPATH=/usr/local/pnp4nagios/var/perfdata
    +[OK  ]  Perfdata directory '/usr/local/pnp4nagios/var/perfdata' exists
    +[WARN]  62 hosts/services are not providing performance data
    +[WARN]  'process_perf_data 1' is set for 43 hosts/services which are not providing performance data!
    +[WARN]  'process_perf_data 0' is set for 27 of your hosts/services
    +[OK  ]  'process_perf_data 1' is set for 243 of your hosts/services
    +[INFO]  ==== System sizing ====
    +[OK  ]  269 hosts/service objects defined
    +[INFO]  ==== Check statistics ====
    +[WARN]  Warning: 3, Critical: 0
    +[WARN]  Checks finished...
    +
    + +
    + +

    Performance data

    +
    + +

    +Beginnend mit 0.6.19-R.37 (2013-02-17) akzeptiert das Skript die Option--object (oder -o) gefolgt von einer Zeichenkette, die einen Host und/oder einen Service angibt. Für diese/s Objekt(e) werden die Performance-Daten angegeben (falls vorhanden). Die Daten werden von eckigen Klammern begrenzt, gefolgt vom Wert der Direktive process_performance_data (ppd=n). +

    + +

    +host = Performance-Informationen für den Host host zeigen
    + +;service = Performance-Informationen für Service service zeigen
    + +host;service = Performance-Informationen für Service service auf Host host zeigen +

    + +

    +Die Zeichenketten werden als reguläre Ausdrücke angesehen (Perl-Syntax). + +

    + +
    + +
    +
    + + + +

    Das Nagios Web Frontend

    +
    + +

    + +PNP soll natürlich schnell erreichbar sein. Man möchte nicht lange nach den richtigen Graphen suchen. +

    + +

    +Nagios selbst bietet die Möglichkeit, externe URLs über die sogenannte Extended Info Config einzubinden. +Da es in diesem Bereich eine Änderung zwischen Nagios 2.x und der Version 3.0 gibt, wird anschließend auf beide Versionen getrennt eingegangen. +

    + +
    + +

    Nagios 2.x

    +
    + +

    + +Bis Nagios 2.x erfolgt die Einbindung externer URLs in das Nagios-Web-Interface über die Extended-Info-Objekte. Für PNP verwenden wir die Option action_url, um das PNP-Web-Frontend mit den passenden Optionen aufzurufen. +

    +
    +define serviceextinfo {
    +   name                  srv-pnp
    +   action_url            /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register              0
    +}
    +
    + +

    +Dieses Template kann nun über “use srv-pnp” in der serviceextinfo-Definition verwendet werden. Wenn Sie die Schnellstart-Installationsanleitungen benutzt haben, können Sie beispielsweise in der Datei localhost.cfg die Definitionen wie folgt erweitern: +

    +
    +define serviceextinfo {
    +   use                     srv-pnp   ; Name of service templates to use
    +   host_name               localhost
    +   service_description     load
    +}
    +
    + +
    + +

    Nagios 3.x

    +
    + +

    + +Seit Nagios 3.0 ist die Direktive action_url in die Host- bzw. Service-Definition verschoben worden. Die serviceextinfo- und hostextinfo-Definitionen sind entfallen. Damit wird die Definition der URLs zum PNP-Interface wesentlich vereinfacht. +

    + +

    +Zuerst definieren wir zwei Nagios-Templates. Falls Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die folgenden Zeilen der Datei templates.cfg hinzufügen: +

    +
    +define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    +
    + +

    +Diese beiden Templates können nun über “use srv-pnp” in der Service-Definition oder “use host-pnp” in der Host-Definition verwendet werden. Wenn Sie die Schnellstart-Installationsanleitungen benutzt haben, können Sie beispielsweise in der Datei localhost.cfg die Definitionen wie folgt erweitern: + +

    +
    define host{
    +        use                     linux-server,host-pnp    ; Name of host templates to use
    +                                                         ; This host definition will inherit all variables that are defined
    +                                                         ; in (or inherited by) the linux-server host template definition.
    +        host_name               localhost
    +        alias                   localhost
    +        address                 127.0.0.1
    +        }
    +
    +
    define service{
    +        use                     local-service,srv-pnp   ; Name of service templates to use
    +        host_name               localhost
    +        service_description     PING
    +        check_command           check_ping!100.0,20%!500.0,60%
    +        }
    +
    + +

    + +Die Links auf die richtigen URLs werden automagisch erstellt. +

    + +
    + +

    Preview Popup

    +
    + +

    + +Außerdem gibt es die Möglichkeit, die Graphen bereits in der Statusübersicht beim Überfahren des “Action Url Icons” mit der Maus einzublenden. +

    + +

    +Ermöglicht wird dies durch die CGI Includes, die es uns erlauben, Javascript-Code an geeigneter Stelle im Seitenkopf der Statusübersicht einzubinden ( status.cgi ). +

    + +

    +In den PNP-Quellen ist die Datei contrib/ssi/status-header.ssi bereits enthalten, die verwendeten URLs müssen aber unter Umständen angepasst werden. Wir gehen hier davon aus, dass PNP über /pnpnagios/index.php erreichbar ist. +

    + +

    +Die besagte Datei muss in das Verzeichnis /usr/local/nagios/share/ssi/ kopiert werden und darf NICHT ausführbar sein. Nagios würde die Datei sonst wirklich wie ein CGI behandeln und ausführen, was aber in diesem Fall zu Fehlern führen würde. Die Apache-Admins mögen bitte “Nagios SSI” nicht mit “Apache SSI” in Verbindung bringen. Beides hat nichts miteinander zu tun. +

    + +

    +Die action_url ist entsprechend anzupassen: +

    +
    +define host {
    +   name       host-pnp
    +   register   0
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +}
    +
    +define service {
    +   name       srv-pnp
    +   register   0
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +}
    +
    + +

    +Nach einem Restart von Nagios (nach Anpassung der Definitionen) sieht das Ergebnis ungefähr so aus:
    + + +

    + +

    +Zurück zur Übersicht | Konfiguration Web-Frontend + +

    + +
    + +
    +
    + + + +

    PNP Web Frontend

    +
    + +

    + +Das Verhalten des PNP-Web-Frontend lässt sich über die Config-Datei etc/config.php beeinflussen. +Diese Datei wird bei Updates von PNP immer wieder überschrieben, da die meisten Pfade und Optionen bereits durch ./configure ermittelt werden. +

    + +

    +Eigene Anpassungen sollten daher in der Datei etc/config_local.php erfolgen. Sollte die Datei noch nicht existieren, kann die config.php als Vorlage verwendet werden. +

    + +
    + +

    etc/pnp/config.php

    +
    + +

    + +Im folgenden die wichtigsten Parameter: +

    + +

    +Der Pfad zum RRDtool-Binary. Wird von ./configure ermittelt. + +

    +
     $conf['rrdtool'] = "/usr/bin/rrdtool";
    +
    + +

    +Höhe und Breite der RRD-Graphen + +

    +
     $conf['graph_width'] = "500";
    + $conf['graph_height'] = "100";
    +
    + +

    + +Bildschirmdimensionen ändern sich, Blattgrößen nicht. Um unterschiedliche Einstellungen zu ermöglichen, können für die Generierung von PDF-Dateien eigene Werte definiert werden. Wenn diese Variablen nicht definiert sind, werden die Werte der Graphen benutzt. +Höhe und Breite der RRD-Graphen bei PDFs + +

    +
     $conf['pdf_width'] = "675";
    + $conf['pdf_height'] = "100";
    +
    + +

    + +Zusätzliche Optionen, die bei jedem Aufruf von RRDTool mit übergeben werden. Beispielsweise --slope-mode, um die Graphen etwas zu glätten. + +

    +
     $conf['graph_opt'] = "";
    +
    + +

    + +Der Pfad zu den von process_perfdata.pl erstellten RRD- und XML-Dateien + +

    +
     $conf['rrdbase'] = "/usr/local/pnp4nagios/var/perfdata/";
    +
    + +

    + +Pfad zu den Config-Files für die Pages. + +

    +
     $conf['page_dir'] = "/usr/local/pnp4nagios/etc/pages/";
    +
    + +

    +Wert in Sekunden, nachdem die PNP-Seiten neu geladen werden sollen. + +

    +
     $conf['refresh'] = "90";
    +
    + +

    + +Maximales Alter der RRD-Files in Sekunden. Nach Erreichen dieses Wertes werden Links zu den Graphen als “inactive” gekennzeichnet. + +

    +
     $conf['max_age'] = 60*60*6;
    +
    + +

    + +Basis-URL zu den Nagios CGIs. + +

    +
     $conf['nagios_base'] = "/nagios/cgi-bin";
    +
    + +

    +Liste von Usern, für die Links zu den Services des aktuellen Hosts angezeigt werden sollen. + +

    +
     $conf['allowed_for_service_links'] = "EVERYONE";
    +
    + +

    +Liste von Usern, für die das Host-Suchfeld angezeigt werden soll. + +

    +
     $conf['allowed_for_host_search'] = "EVERYONE";
    +
    + +

    +Wird PNP nur mit der Angabe eines Hosts ( index.php?host=<myserver> ) aufgerufen, so wird eine Übersicht aller Services angezeigt, wenn der User in dieser Liste enthalten ist. + +

    +
     $conf['allowed_for_host_overview'] = "EVERYONE";
    +
    + +

    +Das Array $views[] legt fest, welche Zeitspannen die RRD-Graphen dargestellen sollen. Der Titel und die Anzahl der Graphen kann somit hier zentral definiert werden. +

    +
    +$views[] = array('title' => 'One Hour',  'start' => (60*60) );
    +$views[] = array('title' => '4 Hours',   'start' => (60*60*4) );
    +$views[] = array('title' => '25 Hours',  'start' => (60*60*25) );
    +$views[] = array('title' => 'One Week',  'start' => (60*60*25*7) );
    +$views[] = array('title' => 'One Month', 'start' => (60*60*24*32) );
    +$views[] = array('title' => 'One Year',  'start' => (60*60*24*380) );
    +
    + +

    +Sie können hier auch weitere Views definieren, sollten aber dabei berücksichtigen, dass im Normalfall ALLE definierten Views angezeigt werden. +

    + +

    +zurück zur Übersicht | Timeranges + +

    + +
    + +
    +
    + + + +

    Timeranges

    +
    + +

    + +In der Übersicht zeigt PNP fünf Zeitbereiche, die frei in der config.php definiert werden können. +

    + +

    +Es gibt aber auch die Möglichkeit, die Zeitbereiche über die URL zu beeinflussen. Dies ist hilfreich, wenn z.B. automatisch PDF-Dokumente erstellt werden sollen +

    + +

    +Die Zeitbereiche werden über die Optionen start und end definiert. +

    + +

    +Beispiel: + +

    +
     pnp4nagios/graph?host=<hostname>&srv=<servicedesc>&start=-1week
    +
     pnp4nagios/graph?host=<hostname>&srv=<servicedesc>&start=2011102322:50:00&end=2011102409:50:00
    + +

    + +Der Startzeitpunkt der Graphen wird somit, ausgehend vom aktuellen Datum, um eine Woche nach hinten verschoben. Der Endzeitpunkt bleibt auf dem aktuellen Zeitstempel. Aber auch end lässt sich über diesen Weg beeinflussen, wobei beide Optionen auch einzeln manipuliert werden dürfen. +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    start end view Ergebnis
    Alle Ansichten enden mit der aktuellen Zeit
    x Alle Ansichten beginnen mit dem angegebenen Datum
    x Alle Ansichten enden mit dem angegebenen Datum
    x x Eine Ansicht zwischen den beiden Zeitangaben
    x Eine Ansicht endet mit der aktuellen Zeit
    x x Eine Ansicht beginnt mit dem angegebenen Datum
    x x Eine Ansicht endet mit dem angegebenen Datum
    + +

    + +Beispiele zur Datumsangabe: + +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Format Beschreibung
    2009W04 4. KW 2009
    1.5.2009 1. Mai 2009
    -1 day Einen Tag zurück
    -3 weeks 3 Wochen zurück
    -1 year Ein Jahr zurück
    yesterday Gestern
    2011102322:50:00 23.10.2011 ab 22:50:00 Uhr
    + +

    + +zurück zur Übersicht | Pages + +

    + +
    + +
    +
    + + + +

    Pages

    +
    + +

    + +„pages“ bieten die Möglichkeit, Grafiken von verschiedenen Hosts/Services auf einer Seite zusammenzufassen. Auf diese Weise können z.B. die Übertragungsraten der Netzwerk-Interfaces aller Tape-Libraries dargestellt werden. Innerhalb der Definitionen sind reguläre Ausdrücke möglich, so dass – entsprechende Namen vorausgesetzt - mit wenig Aufwand viel erreicht werden kann. +Das Verzeichnis, das in config.php durch den Konfigurationseintrag „$conf['page_dir']“ angegeben wurde, enthält ein oder mehrere Dateien mit der Endung „.cfg“. +

    + +

    +Kommentare beginnen mit einem '#' und sind auch innerhalb einer Zeile möglich. +Jede Datei enthält eine „page“-Definition, die neben dem Namen der Seite festlegt, ob die nachfolgenden Grafikdefinitionen reguläre Ausdrücke enthalten.
    + +Die Bezeichnung hinter page_name erscheint in der Liste der verfügbaren Seiten und wird als Titel im Browser angezeigt. +Achtung: “host_name” und “service_desc” beziehen sich auf die Namen der Dateien im perfdata-Ordner, nicht auf die Nagios-Bezeichnungen. Leerzeichen werden durch Unterstriche (“_”) ersetzt. +

    +
    define  page  {
    +        use_regex 1		# 0 = keine regulären Ausdrücke, 1 = reguläre Ausdrücke
    +        page_name Test-Seite	# Beschreibung der Seite
    +}
    + +

    +Danach folgen ein oder mehrere „graph“-Definitionen: +

    +
    define graph {
    +        host_name       host1,host2,host3
    +        service_desc    Current_Load
    +}
    + +

    + +Achtung: Damit die oben gezeigte Liste von Host-Namen funktioniert, muss use_regex 0 gesetzt sein! +

    +
    define graph {
    +        host_name       host4
    +        service_desc    Current_Users
    +}
    + +

    +Und jetzt mit regulären Ausdrücken. Zuerst alle Hosts, deren Name mit „Tape“ beginnen: + +

    +
    define graph {
    +        host_name       ^Tape
    +        service_desc    Traffic
    +}
    + +

    +alle Hosts, deren Namen mit “00” enden + +

    +
    define graph {
    +        host_name       00$
    +        service_desc    Load
    +}
    + +

    +alle Services des localhost, deren Namen ein „a“ oder „o“ enthalten: + +

    +
    define graph {
    +        host_name       localhost
    +        service_desc    a|o
    +}
    + +

    +alle Services, die im Namen nach einem „_“ (mindestens) drei Ziffern haben auf allen Hosts, deren Namen mit „UX“ beginnen: + +

    +
    define graph {
    +        host_name       ^UX
    +        service_desc    _\d{3}
    +}
    + +

    +In einigen Fällen möchten Sie vielleicht die Anzeige auf einen Graphen beschränken. Um dies zu erreichen, können Sie die optionale Direktive “source” benutzen, gefolgt von einer Zahl, die die Position in der RRD-Datei angibt. Die Zählung beginnt ab 0 + +

    +
    define graph {
    +       host_name       host1,host2,host3
    +       service_desc    PING
    +       source          1
    +}
    + +

    +zurück zur Übersicht | Datenexport + +

    + +
    + +
    +
    + + + +

    Datenexport

    +
    + +

    + +PNP bietet über den xport Controller Zugriff auf die RRD-Daten. Dabei kann das Ausgabeformat gewählt werden. Zur Zeit sind die Formate xml, json und csv realisiert. +

    + +

    +Aufgerufen wird der Controller über die URL + +

    +
    /pnp4nagios/xport/<format>?host=<hostname>&srv=<servicedesc>
    + +

    + +wobei <format> durch das jeweils gewünschte Format zu ersetzen ist. +

    + +

    +Sie können außerdem wget benutzen, um Bilder zu erzeugen und diese in regelmäßigen Reports einzufügen. Ein Beispiel: +

    +
    wget -O image.png 'http://<user>:<pass>@<nagios-server>/pnp4nagios/image?host=<hostname>&srv=<service>&view=2&source=0'
    + +

    +view=<n> begrenzt den Graphen auf die Zeitperiode, die in config.php definiert ist
    + +source=<n> zeigt nur eine Data-Source, wenn mehrere in der RRD-Datei vorhanden sind +

    + +

    +Anstatt view können Sie auch start und/oder end benutzen, um die Zeitspanne anzugeben. Details finden Sie in den "time ranges". +

    + +

    +zurück zur Übersicht | Templates + +

    + +
    + +
    +
    + + + +

    Was sind Templates ?

    +
    + +

    + +PNP benutzt Templates, um das Aussehen der RRD-Graphen zu beeinflussen. +

    + +

    +Dabei bestimmt das verwendete check_command, welches Template zur Darstellung herangezogen wird. Im Folgenden wird beschrieben, wo Templates gespeichert werden und wie die Entscheidung für das “richtige” Template getroffen wird. +

    + +
    + +

    Wann wird welches Template verwendet ?

    +
    + +

    + +Templates werden an zwei Stellen im Dateisystem gespeichert. + +

    +
      +
    • share/templates.dist - für Templates, die im PNP-Paket bereits enthalten sind.
      +
    • +
    • share/templates - für selbst erstellte Templates. Diese werden bei Updates nicht verändert.
      +
    • +
    + +

    + +Weiterhin können seit Version 0.6.5 weitere Template Verzeichnisse in der Config Datei pnp4nagios/etc/config.php hinzugefügt werden. +

    + +

    +Soll der Graph für den Service “http” auf Host “localhost” angezeigt werden, so sucht PNP zuerst nach der XML-Datei perfdata/localhost/http.xml und liest diese ein. Diese XML-Dateien werden automatisch erstellt und enthalten Informationen zum jeweiligen Host und Service. Weiterhin enthält der Kopf Informationen über das Plugin und die Performance-Daten. Im folgenden Beispiel erkennt man anhand des XML-Tags <TEMPLATE>, welches PNP-Template für diesen Graphen verwendet werden soll. +

    + +

    +/localhost/http.xml + +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>2</DS>
    +    <NAME>size</NAME>
    +    <UNIT>B</UNIT>
    +    <ACT>263</ACT>
    +    <WARN></WARN>
    +    <CRIT></CRIT>
    +    <MIN>0</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +...
    +</NAGIOS>
    + +

    +PNP hängt .php an und sucht nun nach einem Template mit dem Namen check_http.php in folgender Reihenfolge: + +

    +
      +
    1. templates/check_http.php
      +
    2. +
    3. templates.dist/check_http.php
      +
    4. +
    5. templates/default.php
      +
    6. +
    7. templates.dist/default.php
      +
    8. +
    + +

    + +Das Template default.php nimmt somit eine Sonderstellung ein und wird immer verwendet, wenn vorher kein anderes Template gefunden wird. +

    + +
    + +

    Eigene Templates erstellen

    +
    + +

    + +PNP-Templates sind PHP-Dateien, die zur Laufzeit von PNP über die PHP-Funktion include() eingebunden werden. +Dies bedeutet, dass jeder PHP-Code in Templates interpretiert wird. Daher ist die Manipulation aller Werte über PHP möglich. +

    + +

    +PNP-Templates müssen folgende Eigenschaften besitzen: +

    +
      +
    1. Templates müssen gültigen PHP-Code enthalten.
      +
    2. +
    3. Templates dürfen keine Ausgabe erzeugen.
      +
    4. +
    5. innerhalb der Templates werden die zwei Arrays $opt[] und $def[] gefüllt.
      +
    6. +
    + +

    + +Die beiden PHP-Arrays $opt[] und $def[] zusammen bilden den Aufruf von 'rrdtool graph'. Somit sind alle Optionen möglich, die RRDtool bietet. Die Optionen von RRDtool sind auf der RRDtool Homepage genauestens beschrieben. +

    + +

    +Wenn beide Arrays mehrere Datensätze enthalten, so wird für jeden Datensatz ein Graph erstellt. +

    + +

    +Weiterhin stehen innerhalb der Templates die Daten aus dem zugehörigen XML-File zur Verfügung, die zum Erstellen der Graphen wieder verwendet werden können. +

    + +

    +Am Beispiel des recht einfachen Templates response.php lassen sich die wichtigsten Optionen recht gut beschreiben. +

    +
    <?php
    +#
    +$opt[1] = "--title \"Response Time For $hostname / $servicedesc\" ";
    +#
    +$def[1] =  "DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE " ;
    +$def[1] .= "AREA:var1#00FF00:\"Response Times \" " ;
    +$def[1] .= "LINE1:var1#000000 " ;
    +$def[1] .= "GPRINT:var1:LAST:\"%3.4lg %s$UNIT[1] LAST \" ";
    +$def[1] .= "GPRINT:var1:MAX:\"%3.4lg %s$UNIT[1] MAX \" ";
    +$def[1] .= "GPRINT:var1:AVERAGE:\"%3.4lg %s$UNIT[1] AVERAGE \" ";
    +?>
    + +

    +$opt[1] = ”--title …” setzt RRDtool-Optionen für den ersten Datensatz im Array. Hier ist das der Titel des Graphen. +Wie man sieht, werden eingebettete Anführungszeichen durch einen Backslash (\) maskiert. +Die beiden Variablen $hostname und $servicedesc sind durch den Aufruf von PNP ermittelt worden und stehen nun auch im Template zur Verfügung. +

    + +

    +$def[1] = “DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE ”; definiert, welche Daten aus welchem RRD-File gelesen werden sollen. $RRDFILE[1] enthält den Pfad zur RRD-Datei dieses Services. $DS[1] verweist auf die Datenreihe eins aus der RRD-Datei. +

    + +

    +$def[1] .= “AREA:var1#00FF00:\”Response Times \” ”; durch den Operator ”.=” werden weitere Daten an das Array $def[1] angehängt. Gezeichnet wird eine Fläche (AREA) mit den Daten der Variable var1. Die Farbe wird im HEX-Code #00FF00 definiert. Als Beschriftung wird “Response Times” verwendet. +

    + +

    +$def[1] .= “LINE1:var1#000000 ”; Als Abschluss der eben gezeichneten Fläche wird eine Linie (LINE1) in Schwarz (#000000) gezeichnet. +

    + +

    + +$def[1] .= “GPRINT:var1:LAST:\”%3.4lg %s$UNIT[1] LAST \” ”;
    + +$def[1] .= “GPRINT:var1:MAX:\”%3.4lg %s$UNIT[1] MAX \” ”;
    + +$def[1] .= “GPRINT:var1:AVERAGE:\”%3.4lg %s$UNIT[1] AVERAGE \” ”;
    +

    + +

    +Die drei GPRINT Zeilen bilden die Legende des Graphen. Die aktuellen Werte werden dabei über die printf Syntax formatiert. +

    + +
    + +

    Verfügbare Variablen

    +
    + +

    + +PNP speichert über den Datensammler process_perfdata.pl zur Laufzeit nicht nur Performancedaten, sondern auch weitere von Nagios exportierte Werte. Diese Werte werden in der jeweils für den Service gültigen XML-Datei gespeichert. +

    + +

    +Im ersten Teil der XML-Datei werden die Performancedaten in ihre Einzelteile zerlegt gespeichert. +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +...
    +</NAGIOS>
    + +

    +Das Feld <DS> bezeichnet die DataSource und dient der Identifizierung der Datenreihen innerhalb der RRD-Dateien, ist aber auch der Schlüssel der folgenden Arrays. +

    + +

    +Im Array $UNIT[1] ist somit die Einheit der ersten Datenreihe gespeichert. +

    + +

    +Die XML-Datei enthält jedoch noch weitere Informationen. Wird process_perdata.pl im sync-Mode verwendet, so sind alle verfügbaren Makros mit den aktuellen Werten verfügbar. Der folgende Ausschnitt ist jedoch zu Gunsten der Lesbarkeit gekürzt. +

    +
    <NAGIOS>
    +...
    +  <NAGIOS_SERVICENOTIFICATIONID>8418</NAGIOS_SERVICENOTIFICATIONID>
    +  <NAGIOS_SERVICENOTIFICATIONNUMBER>0</NAGIOS_SERVICENOTIFICATIONNUMBER>
    +  <NAGIOS_SERVICEOUTPUT>HTTP OK HTTP/1.1 200 OK - 10087 bytes in 0.125 seconds</NAGIOS_SERVICEOUTPUT>
    +  <NAGIOS_SERVICEPERCENTCHANGE>0.00</NAGIOS_SERVICEPERCENTCHANGE>
    +  <NAGIOS_SERVICEPERFDATA>time=0.124811s;;;0.000000 size=10087B;;;0</NAGIOS_SERVICEPERFDATA>
    +  <NAGIOS_SERVICEPERFDATAFILE></NAGIOS_SERVICEPERFDATAFILE>
    +  <NAGIOS_SERVICEPROBLEMID>0</NAGIOS_SERVICEPROBLEMID>
    +  <NAGIOS_SERVICESTATE>OK</NAGIOS_SERVICESTATE>
    +  <NAGIOS_SERVICESTATEID>0</NAGIOS_SERVICESTATEID>
    +  <NAGIOS_SERVICESTATETYPE>HARD</NAGIOS_SERVICESTATETYPE>
    +  <NAGIOS_SHORTDATETIME>27-12-2007 13:51:23</NAGIOS_SHORTDATETIME>
    +...
    +</NAGIOS>
    + +

    +Die einzelnen XML-Felder sind als Variablen in den PNP-Templates verwendbar, wobei jedes Feld als Variable gleichen Namens verfügbar ist. +

    + +

    +Aus <NAGIOS_SERVICEOUTPUT> wird die Variable $NAGIOS_SERVICEOUTPUT. +

    + +

    +zurück zur Übersicht | Custom Templates + +

    + +
    + +
    +
    + + + +

    Custom Templates

    +
    + +

    + +Wie bereits unter ”Was sind Templates ?” beschrieben, ist die Darstellung der Graphen abhängig vom verwendeten Check-Command. +

    + +

    +Es gibt jedoch Situationen, in denen dieses Verhalten übersteuert werden muss, zum Beispiel dann wenn allgemeingültige Commands definiert wurden. +

    + +

    +PNP, speziell process_perfdata.pl, sucht zur Laufzeit für jedes check_command im Verzeichnis etc/check_commands nach einer Config-Datei (<check_command>.cfg) und liest diese, wenn vorhanden, ein. +Folgende Optionen können darin definiert werden: +

    + +
    + +

    CUSTOM_TEMPLATE

    +
    + +

    +Geht man von folgendem Beispiel einer Nagios command-Definition aus: + +

    +
    +define command {
    +  command_name check_nrpe
    +  command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ -a "$ARG2$"
    +}
    +
    + +

    +Die Folge wäre, dass immer das Template check_nrpe.php verwendet werden würde, auch wenn auf dem zu überwachenden Server via NRPE ein ganz anderes Plugin aufgerufen wurde. +

    + +

    +Da unser Beispiel-Command check_nrpe lautet, wird nach etc/check_commands/check_nrpe.cfg gesucht. +

    + +

    +Eine Beispiel-Config wird bereits während der Installation mit der Dateierweiterung .cfg-sample in etc/check_commands gespeichert. +

    +
    +# check_command check_nrpe!load!-w 4,4,4 -c 5,5,5
    +# ________0__________|       |       |
    +# ________1__________________|       |
    +# ________2__________________________|
    +#
    +CUSTOM_TEMPLATE = 1
    +
    + +

    +CUSTOM_TEMPLATE = 1 sorgt dafür, dass nur der Inhalt von $ARG1$ als Template-Name verwendet wird. Da in diesem Beispiel $ARG1$ mit dem Wert “load” gefüllt ist, ergibt sich als Template-Name “load.php” +

    + +

    +CUSTOM_TEMPLATE = 0,1 ergibt → “check_nrpe_load.php” +

    + +

    +CUSTOM_TEMPLATE = 1,0 ergibt → “load_check_nrpe.php” +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    DATATYPE

    +
    + +

    + +Über die Option “DATATYPE” kann beeinflusst werden, mit welchem Datentyp die RRD-Datenbank angelegt werden soll. +Default ist in diesem Fall “GAUGE”. Für fortlaufende Werte wird aber hier der Datentyp COUNTER benötigt. +Normalerweise sollten Plugin-Entwickler für Daten von Typ Counter die Einheit “c” verwenden. Dies ist jedoch nicht immer der Fall. +

    + +

    +Alle Datenreihen auf Typ COUNTER einstellen. + +

    +
    DATATYPE = COUNTER
    + +

    +Einzelnen Datenreihen spezielle Datentypen zuweisen + +

    +
    DATATYPE = GAUGE,GAUGE,COUNTER,COUNTER
    + +

    +Weitere Datentypen sind in der RRDTool-Dokumentation unter rrdcreate erklärt. +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    USE_MIN_ON_CREATE und USE_MAX_ON_CREATE

    +
    + +

    + +In einigen wenigen Situationen ist es notwendig, die für RRDTool gültigen Daten zu begrenzen. +

    + +

    +RRD-Datenbanken lassen sich mit definierten Minimum- und Maximum-Werten anlegen. +Weitere Infos unter http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +

    + +

    +Berücksichtigen des Maximum-Wertes aus den Performance-Daten + +

    +
    USE_MAX_ON_CREATE = 1
    + +

    +Berücksichtigen des Minimum-Wertes aus den Performance-Daten + +

    +
    USE_MIN_ON_CREATE = 1
    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    RRD_STORAGE_TYPE

    +
    +
    RRD_STORAGE_TYPE = SINGLE
    + +

    + +Die Option RRD_STORAGE_TYPE definiert die Art der Datenhaltung. +

    + +

    +Mögliche Werte sind MULTIPLE und SINGLE +

    + +

    +SINGLE: Eine RRD-Datenbank pro Service +

    + +

    +MULTIPLE: Ein oder mehrere RRD-Datenbanken pro Service. Für jede Datenreihe wird eine eigene RRD-Datenbank erstellt. +

    + +

    +ACHTUNG: Daten werden nicht automatisch migriert!
    + +Ein Konvertierungs-Script finden Sie hier. +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    RRD_HEARTBEAT

    +
    + +

    + +Gültig ab PNP 0.6.1 +

    +
    RRD_HEARTBEAT = 305
    + +

    +Nach <RRD_HEARTBEAT> Sekunden erwartet RRDtool neue Daten. +

    + +

    +Mehr dazu unter http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    Hints on Template Names

    +
    + +

    + +In den meisten Situationen, kann man erwünsche Template Namen relativ einfach, durch die Verwendung geeignter command Objekt Definitionen, erhalten. +

    + +

    +Man betrachte folgendes Beispiel: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$
    +}
    +
    + +

    + +mit commands wie diesem: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load -w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    +Selbst wenn man “CUSTOM_TEMPLATE = 1” benutz, würde man template Namen wie diesen “_usr_lib_nagios_plugins_check_load_-w_4,4,4_-c_5,5,5” erhalten, was höchst unerwünscht ist, insbesondere wegen den darin enthaltenen Parametern. +

    + +

    +Lösung 1: Die Parameter in eigenständige $ARGn$ auslagern +

    + +

    +Eine einfache Lösung ist die Verwendung der folgenden command Objekt Definition: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +mit commands wie diesem: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +(man beachte das hinzugekommene “!”) +

    + +

    +Dies funktioniert selbst dann, wann $ARG2$ leer bleibt. +

    + +

    +Selbstverständlich müsste man immer noch “CUSTOM_TEMPLATE = 1” setzen. +

    + +

    + +Lösung 2: Den remote executor in der command Objekt Definition verstecken +

    + +

    +Eine andere Lösung ist es, den remote excutor in den jeweiligen command Objekt Definitionen zu verstekcne. +

    + +

    +Anstatt folgender Definition: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +würde man dies für jeden fern auszuführenden command definieren: + +

    +
    +define command {
    +  command_name check_load_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ /usr/lib/nagios/plugins/check_load $ARG1$
    +}
    +
    + +

    + +mit commands wie diesem: + +

    +
    +  …
    +  check_load_by_ssh!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +Natürlich darf “CUSTOM_TEMPLATE = 1” bei dieser Lösung nicht mehr gesetzt werden. +

    + +

    + +Welche der obigen Lösungen verwendet wird, ist weitgehend Geschmacksache. +

    + +

    +zurück zur Übersicht | PNP in verteilten Umgebungen + +

    + +
    + +
    +
    + + + +

    Advanced

    +
    + +
    + +

    Verteilte Systeme

    +
    + +

    +Ist Nagios als verteiltes System implementiert, stellt sich die Frage, wo PNP installiert wird. +

    + +

    +Rein technisch ist diese Frage nicht wichtig. PNP kann auf den Slaves sowie auf dem Master-Server installiert sein. Oder nur auf dem Master? +

    + +

    +Wird PNP auf dem Master betrieben, ist jedoch bei der Übergabe der Daten via send_nsca von den Slave-Servern zum Master darauf zu achten, dass auch die Performance-Daten übergeben werden. Weiterhin kommt auf dem Master oft nicht das Original-Check-Command zum Einsatz. +

    + +

    +Damit nun aber PNP auf dem Master noch erkennen kann, welches Check-Command auf den Slaves die Daten ermittelt hat, reagiert process_perfdata.pl auf ein zusätzliches Feld am Ende der Performance-Daten. +

    +
    OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;; [check_icmp]
    + +

    +Findet PNP am Ende der Performance Daten einen in eckigen Klammern eingeschlossenen Text, so wird dieser als Check-Command und somit als PNP-Template verwendet. +

    + +

    +Die Nagios-Dokumentation zu diesem Thema ist hier zu finden. Das in der Doku verwendete Command ist leicht anzupassen. +

    + +

    +Aus +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$'
    +	}
    +
    + +

    +wird +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$ | $SERVICEPERFDATA$ [$SERVICECHECKCOMMAND$]'
    +	}
    +
    + +
    + +

    Das check_multi-Plugin

    +
    + +

    + +Das Plugin check_multi ist eines der ersten Plugins, das die Funktionen von Nagios 3.0 richtig ausschöpft. Check_Multi ist in der Lage, mehrere Nagios-Plugins auszuführen, aber für Nagios als einen Service darzustellen. Die Ausgabe von check_multi erfolgt über mehrere Zeilen, um die Masse an Informationen wieder darstellen zu können. +

    + +

    +Daraus ergaben sich jedoch einige Schwierigkeiten für PNP. PNP muss aus den Performance-Daten wieder die Daten der einzelnen Plugins ermitteln können. Zusammen mit Matthias Flacke, dem Entwickler von check_multi, haben wir jedoch recht schnell eine Möglichkeit gefunden, die Daten wieder sauber den einzelnen Plugins zuzuordnen. +

    + +

    + +

    + +

    +Zurück zur Übersicht | rrdcached-Unterstützung + +

    + +
    + +
    +
    + + + +

    RRDtool Cache Daemon

    +
    + +

    + +In großen Installationen wird man über kurz oder lang feststellen, dass die Verarbeitung der Performance-Daten eine recht hohe I/O-Last zur Folge hat. RRDtool muss extrem viele Updates auf Disk schreiben, kann dabei jedoch den Disk-Cache nicht optimal ausnutzen. +

    + +

    +Eine Optimierung stellt das Sammeln und Sortieren der Daten dar. Es ist für das System effektiver, viele Updates im Block in eine RRD-Datenbank zu schreiben. Der Disk-Cache kann dabei effektiver genutzt werden. +

    + +

    +In der aktuellen RRDtool-Version ( SVN trunk 1550+ ) ist der rrdcached enthalten, der genau diese Situation verbessern soll. +

    + +

    +An dieser Stelle möchte ich mich bei Florian octo Forster, Kevin Brintnall und Tobi Oetiker bedanken. Die Entwicklung dieses Daemons wurde vorbildlich auf der rrd-developers Mailingliste koordiniert. +

    + +
    + +

    Arbeitsweise

    +
    + +

    + +Der rrdcached arbeitet als Daemon im Hintergrund und öffnet einen UNIX- oder TCP-Socket, auf dem er auf Anfragen von rrdtool wartet. Aufgrund von Sicherheitsbedenken ist es in neueren Versionen von rrdcached aber nicht mehr möglich absolute Pfadangaben (wie bei pnp4nagios üblich) bei Netzwerkzugriffen zu verwenden, daher ist derzeit nur Nutzung von UNIX-Sockets möglich. +

    + +
    + +

    rrdcached

    +
    + +

    + +Der rrdcached kennt einige wichtige Optionen, die beim Start übergeben werden. +

    + +

    +Option -l definiert den Socket, auf dem der rrdcached Requests annimmt. Der Default-UDP-Port ist 42217, der Default-UNIX-Socket /tmp/rrdcached.sock. +

    +
    +-l unix:/pfad/zum/rrdcached.sock
    +-l /pfad/zum/rrdcached.sock
    +-l 127.0.0.1
    +-l 127.0.0.1:8888
    +
    + +

    +Option -P gibt die für die nachfolgenden Sockets (mit -l spezifiziert) erlaubten Befehle an, welche auf die RRD-Datenbanken angewendet werden können. +

    +
    -P FLUSH,PENDING
    + +

    +Option -s erlaubt es die Gruppenzugehörigkeit der nachfolgenden UNIX-Sockets zu ändern. +

    +
    -s nagios
    + +

    +Option -m setzt die Zugriffsrechte für die nachfolgenden UNIX-Sockets auf die (in oktal) angegebenen Werte. +

    +
    -m 0660
    + +

    +Option -w bestimmt den Intervall in Sekunden, in dem die Daten auf Disk geschrieben werden sollen. +

    +
    -w 1800
    + +

    +Option -z definiert einen Delay, der die über die Option -w definierten Schreibzyklen in einen zufälligen Bereich [0-delay] verteilt, um gleichzeitige Schreibzugriffe zu verhindern. Der Wert der Option -z darf nicht größer gewählt werden als -w. +

    +
    -z 1800
    + +

    +Option -p definiert ein PID File +

    +
    -p /var/run/rrdcached.pid
    + +

    +Option -j definiert den Pfad zu einem Journal-Verzeichnis. Dort werden alle Aufträge protokolliert und ggf. beim nächsten Start nachgefahren, falls der rrdcached-Daemon abstürzt. +

    +
    -j /var/cache/rrdcached
    + +

    +Daraus ergibt sich beispielsweise ein Aufruf von rrdached mit folgenden Parametern +

    +
     rrdcached -w 1800 -z 1800 -p /tmp/rrdcached.pid -j /tmp -s nagios -m 0660 -l unix:/tmp/rrdcached.sock
    + +
    + +

    rrdtool

    +
    + +

    + +RRDtool selbst wird die Existenz des Daemons über die Option --daemon=<socket> mitgeteilt. + +

    +
     rrdtool --daemon=unix:/tmp/rrdcached.sock update ...
    + +

    + +Dies muss natürlich mit den Startoptionen des rrdcached übereinstimmen! +

    + +
    + +

    Integration in PNP

    +
    + +

    + +Da zwei Bestandteile von PNP auf den rrdcached vorbereitet werden müssen, ergeben sich Änderungen in zwei Config-Files. Außerdem muß der User unter welchem der Webserver läuft zur Gruppe unter der Nagios läuft hinzugefügt werden. +

    + +

    +1. Anpassen der process_perfdata.cfg für den Datensammler process_perfdata.pl +

    +
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +RRD_DAEMON_OPTS = unix:/var/run/rrdcached.sock
    +
    + +

    +2. Anpassen der config_local.php (bzw. config.php) für das Webinterface +

    +
    +#
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +# $conf['RRD_DAEMON_OPTS'] = 'unix:/tmp/rrdcached.sock';
    +$conf['RRD_DAEMON_OPTS'] = 'unix:/var/run/rrdcached.sock';
    +
    + +

    +Die passenden Optionen sind bereits in den Beispieldateien enthalten. +

    + +

    +zurück zur Übersicht | migrieren von RRD-Dateien + +

    + +
    + +
    +
    + + + +

    NPCD

    +
    + +

    + +NPCD (Nagios-Perfdata-C-Daemon) wurde geschrieben, um die asynchrone Bearbeitung von Nagios Performance-Daten zu ermöglichen. +

    + +
    + +

    Einleitung

    +
    + +

    + +In großen Nagios-Installationen kann es zu nicht akzeptierbaren Verspätungen seitens der Checks kommen. Das bedeutet, dass Nagios einen Check zum Zeitpunkt x ausführen soll, diesen aber erst y Sekunden später tatsächlich ausführt. +

    + +

    +Wenn man dem Nagios-Daemon mitteilt, dass man nach jedem einzelnen Check auch die Performance-Daten verarbeiten möchte, so geht dies bis zu einem bestimmten Grad gut, ab einer gewissen Anzahl von Checks pro Sekunde allerdings kommt man relativ schnell zu den sog. Latency-Problemen. +

    + +

    +Um die Anzahl der Aktionen pro Check zu verringern, kann man nun PNP im Bulk-Mode verwenden, wobei die Performance-Daten zunächst vom Nagios-Prozess gesammelt und anschließend ebenfalls vom Nagios-Prozess selbst verarbeitet werden. +

    + +

    +Man kann aber auch dem Nagios-Prozess mitteilen, dass die Verarbeitung der Performance-Daten lediglich durch das Verschieben der Dateien in ein Spool-Verzeichnis geschehen soll, welches für den Nagios-Prozess selbst eine sehr schnelle Aktion ist und die Performance nicht nennenswert beeinflusst und somit dem Core mehr Zeit für seine eigentliche Arbeit lässt: weitere Checks ausführen, Alamierungen bereitstellen, etc. +

    + +
    + +

    Wie NPCD arbeitet

    +
    + +

    + +Wie bereits erwähnt, ist die Arbeit der Performance-Daten-Verarbeitung durch das schnelle Verschieben der Datei bereits erledigt, aber das bringt die Performance-Daten noch nicht in die RRD-Datenbank. +

    + +

    +Um den Transport der Performance-Daten-Dateien kümmert sich nun der NPCD-Daemon, unabhängig vom Nagios-Prozess, indem er regelmäßig in das Spool-Verzeichnis guckt und für jede dort gefundene Datei eine Aktion ausführt. +

    + +

    +Nachdem NPCD gestartet wurde, erstellt er sich eine Liste von Dateinamen des Spool-Verzeichnisses und startet für jede gefundene Datei einen Thread zur weiteren Verarbeitung mit Hilfe des perfdata_file_run_cmd und dem optionalen perfdata_file_run_cmd_arg als zusätzlichem Argument. +

    + +

    +Da das Format der Performance-Daten-Dateien dem Format der 'normalen' PNP-Bulk-Modus-Dateien gleicht, kann NPCD nun für jede gefundene Datei also process_perfdata.pl im Bulk Modus aufrufen. +

    + +
    + +

    Vor- und Nachteile

    +
    + +

    + +Pro: +

    +
      +
    • bessere Performance für Nagios
      +
        +
      • aufgrund der vom Nagios-Prozess getrennten Verarbeitung der Performance-Daten hat Nagios mehr Zeit für die wichtigen Dinge
        +
      • +
      +
    • +
    • kein Datenverlust
      +
        +
      • solange Nagios Performance-Daten-Dateien im Spool-Verzeichnis ablegt, gehen keine Daten verloren. Selbst wenn der NPCD mal nicht laufen sollte (Bsp. nach Neustart des Systems), werden die Dateien nach Wiederanlauf in chronologischer Reihenfolge bearbeitet ($TIMET$ Makro beim verschieben ins Spool-Verzeichnis)
        +
      • +
      +
    • +
    + +

    + +Kontra: +

    +
      +
    • Keine Echtzeitverarbeitung der Performance-Daten
      +
        +
      • aufgrund des Rhythmusses, wann Nagios die Performance-Daten-Dateien verschiebt (service_perfdata_file_processing_interval)
        +
      • +
      • nach jedem Lauf durch alle Dateien des Spool-Verzeichnisses wartet NPCD 10 Sekunden lang auf neue Dateien
        +
      • +
      +
    • +
    + +
    + +

    NPCD Config

    +
    + +

    + +NPCD muss zwangsläufig über eine Konfigurationsdatei gesteuert werden. Eine Beispielkonfiguration liegt der PNP-Installation als npcd.cfg-sample bei. +

    + +

    +Nach Umbenennen der -sample Datei zu npcd.cfg kann NPCD nun wie folgt gestartet werden: +

    +
    /usr/local/pnp4nagios/bin/npcd -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +oder + +

    +
    /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +um NPCD im Hintergrund als Daemon laufen zu lassen. +

    + +

    +Hinweis: +Die -sample Datei sollte in jedem Fall in npcd.cfg umbenannt werden, da sie sonst bei einem Update von PNP überschrieben werden könnte. +

    + +
    + +

    npcd.cfg-sample

    +
    + +

    + +Dies sind die essentiellen Konfigurationsdirektiven für NPCD: +

    +
    # Privilege Options
    +user = nagios
    +group = nagios
    +
    +# Logging Options
    +log_type = syslog
    +log_file = /usr/local/pnp4nagios/var/npcd.log
    +max_logfile_size = 10485760
    +log_level=0
    +
    +# Processing Options
    +perfdata_spool_dir = /usr/local/pnp4nagios/var/spool/perfdata/
    +perfdata_file_run_cmd = /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +perfdata_file_run_cmd_args = -b
    +
    +# Thread Options
    +npcd_max_threads=5
    +
    +# greedy options
    +use_load_threshold = 0
    +load_threshold = 10.0
    +
    +# Process Options
    +pid_file=/var/run/npcd.pid
    +
    + +
    + +

    Die Direktiven

    +
    +
      +
    • Privilege-Optionen
      +
        +
      • user <username>
        +
          +
        • NPCD versucht die Userberechtigung zu diesem User zu wechseln.
          +
        • +
        • Default: nagios
          +
        • +
        +
      • +
      • group <groupname>
        +
          +
        • NPCD versucht die Gruppenberechtigung zu dieser Gruppe zu wechseln.
          +
        • +
        • Default: nagios
          +
        • +
        +
      • +
      +
    • +
    • Logging-Optionen
      +
        +
      • log_type <syslog> oder <file>
        +
          +
        • Log-Type, den NPCD zum Loggen verwenden wird
          +
        • +
        • Default: syslog
          +
        • +
        +
      • +
      • log_file </pfad/zu/datei>
        +
          +
        • Falls log_type = file wird diese Logdatei verwendet
          +
        • +
        • Default: /usr/local/pnp4nagios/var/npcd.log
          +
        • +
        +
      • +
      • max_logfile_size <bytes>
        +
          +
        • NPCD wird nach Erreichen der hier angegebenen Dateigröße eigenständig eine Logrotation durchführen
          +
        • +
        • Default: 10485760 = 10 MByte
          +
        • +
        +
      • +
      • log_level <integer>
        +
          +
        • Wie viel soll aufgezeichnet werden, möglich ist:
          +
            +
          • 0 = Kein Log - außer Fehlern
            +
          • +
          • 1 = wenig Log - etwas mehr Aufzeichnen
            +
          • +
          • 2 = Mehr Log (aktuell ALLES)
            +
          • +
          • -1 = DEBUG Mode - Es wird alles aufgezeichnet und die Bearbeitung wird verlangsamt
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      +
    • +
    • Bearbeitungs-Optionen
      +
        +
      • perfdata_spool_dir </path/to/spool/dir/>
        +
          +
        • Das Verzeichnis, in das Nagios die Dateien verschiebt
          +
        • +
        • Default: /usr/local/pnp4nagios/var/spool/
          +
        • +
        +
      • +
      • perfdata_file_run_cmd </path/to/bin/filename>
        +
          +
        • Das Programm, welches Nagios für jede Datei aufrufen soll
          +
        • +
        • Default: /usr/local/pnp4nagios/libexec/process_perfdata.pl
          +
        • +
        +
      • +
      • perfdata_file_run_cmd_args <option>
        +
          +
        • Das Argument, welches optional an perfdata_file_run_cmd angehängt wird
          +
        • +
        • Default: ”-b”
          +
        • +
        • :!: Die Kommandozeile wird nach folgendem Schema aufgebaut:
          <perfdata_file_run_cmd> <perfdata_file_run_cmd_args> <filename_from_perfdata_spool_dir>
          +
          +
        • +
        +
      • +
      +
    • +
    • Thread-Optionen
      +
        +
      • npcd_max_threads <integer value>
        +
          +
        • Anzahl der maximal zu startenden parallelen Threads
          +
        • +
        • Default: 5
          +
        • +
        +
      • +
      +
    • +
    • Greedy-Optionen
      +
        +
      • use_load_threshold <0 oder 1>
        +
          +
        • definiert, ob NPCD bei Erreichen des load_thresholds die Anzahl der Threads begrenzen soll
          +
            +
          • 0 = ausschalten (weitere Threads starten)
            +
          • +
          • 1 = einschalten
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      • load_threshold <float value>
        +
          +
        • wenn use_load_threshold auf 1 gesetzt ist, werden bei Erreichen dieses load limits keine neuen Threads gestartet
          +
        • +
        • Default: 10.0
          +
        • +
        +
      • +
      +
    • +
    • Process-Optionen
      +
        +
      • pid_file </path/to/pid.file>
        +
          +
        • Pfad zum PID File
          +
        • +
        • Default: /var/run/npcd.pid
          +
        • +
        +
      • +
      +
    • +
    + +

    + +zurück zur Übersicht | Wrapper-Script + +

    + +
    + +
    +
    + +

    +check_procs ist ein Beispiel für ein Plugin, das keine Performance-Daten ausgibt: +

    +
    ./check_procs -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'
    + +

    +Mit dem folgenden Wrapper-Script kann das geändert werden +

    + +

    +check_procs.sh + +

    +
    #!/bin/bash
    +LINE=`/usr/local/nagios/libexec/check_procs $*`
    +RC=$?
    +COUNT=`echo $LINE | awk '{print $3}'`
    +PROCS=`expr $COUNT - 1`
    +LINE=`echo $LINE | sed "s/: $COUNT /: $PROCS /"`
    +echo $LINE \| procs=$PROCS
    +exit $RC
    + +

    +Nun wird die Zahl zusammen mit einer Bezeichnung ausgegeben. + +

    +
    ./check_procs.sh -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'| procs=2
    + +
    +
    + + + + + + + +
    2.6. Performance-Daten
    + +

    + +'Bezeichnung'=Wert[UOM];[warn];[crit];[min];[max] +

    + +

    +Anmerkungen: + +

    +
      +
    1. Leerzeichen trennen Listen von Bezeichnung/Werte-Paaren
      +
    2. +
    3. Bezeichnungen können beliebige Zeichen enthalten
      +
    4. +
    5. die Bezeichnung muss in Apostrophe eingeschlossen sein, wenn diese Gleichheitszeichen (=), Apostroph (') oder Leerzeichen ( ) enthält, ansonsten sind die Apostrophe optional
      +
    6. +
    7. die Länge der Bezeichnung ist beliebig, aber idealerweise sind die ersten 19 Zeichen eindeutig (aufgrund einer Beschränkung in RRD). Bitte beachten Sie, dass es eine Längenbegrenzung bei der Menge von Daten gibt, die von NRPE an Nagios geliefert werden kann
      +
    8. +
    9. um ein Apostroph darzustellen, nutzen Sie zwei einzelne Apostrophe
      +
    10. +
    11. warn, crit, min und/oder max können leer sein (z.B. wenn der Schwellwert nicht definiert ist oder wenn min oder max nicht zutreffen). Nachfolgende, nicht gefüllte Semikola können entfallen
      +
    12. +
    13. min und max sind nicht erforderlich, wenn UOM = %
      +
    14. +
    15. Wert, min und max sind aus der Klasse [-0-9.] (Ziffern, Minuszeichen und Dezimalpunkt). Alle müssen das gleiche UOM benutzen
      +
    16. +
    17. warn und crit sind im “Range”-Format (siehe Abschnitt 2.5 der Original-Dokumentation). Alle müssen das gleiche UOM benutzen.
      +
    18. +
    19. UOM (unit of measurement, Maßeinheit) ist eins von:
      +
        +
      • keine Einheit angegeben - angenommen wird eine Zahl (int oder float) von Dingen (z.B. Benutzer, Prozesse, Load)
        +
      • +
      • s - Sekunden (auch us, ms)
        +
      • +
      • % - Prozent
        +
      • +
      • B - Bytes (auch KB, MB, TB; GB?)
        +
      • +
      • c - ein fortlaufender Zähler (z.B. Bytes, die über ein Interface übertragen werden)
        +
      • +
      +
    20. +
    + +

    + +Es bleibt Drittanbietern überlassen, aus den Performance-Daten Graphen zu erzeugen.| +

    + +

    +Quelle: http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN201 + +

    + +
    diff --git a/share/pnp/documents/de_DE/dwnld.html b/share/pnp/documents/de_DE/dwnld.html new file mode 120000 index 0000000..bc99189 --- /dev/null +++ b/share/pnp/documents/de_DE/dwnld.html @@ -0,0 +1 @@ +en_US/dwnld.html \ No newline at end of file diff --git a/share/pnp/documents/de_DE/install.html b/share/pnp/documents/de_DE/install.html new file mode 100644 index 0000000..11b8970 --- /dev/null +++ b/share/pnp/documents/de_DE/install.html @@ -0,0 +1,208 @@ + + + +

    Installation

    +
    + +

    + +Im Folgenden wird die Installation von PNP beschrieben. Dabei wird davon ausgegangen, dass Nagios aus den Sourcen übersetzt und im Verzeichnis /usr/local/nagios installiert wurde.
    + +Achtung: Die Beschreibung bezieht sich auf die Developer-Version PNP 0.6.0.
    + +Bitte vergessen Sie nicht, dass PNP nach der Installation noch konfiguriert werden muss. +

    + +
    + +

    Make und Co

    +
    + +

    + +Die Installation von PNP wird wie bei Nagios auch über Makefiles gesteuert. Dabei wird durch den Aufruf von ./configure das System analysiert und die ermittelten Werte in Makefiles übernommen. +

    + +

    +Als User root wird PNP in /usr/local/src entpackt. + +

    +
    +tar -xvzf pnp4nagios-HEAD.tar.gz
    +cd pnp4nagios
    +
    + +

    +Im Verzeichnis pnp4nagios wird nun ./configure aufgerufen. +

    +
    +./configure
    +
    + +

    + +Hinweis: Ohne weitere Optionen werden als Benutzer und Gruppe “nagios” verwendet. Bei abweichenden Werten sind die Parameter ”--with-nagios-user” und ”--with-nagios-group” zu benutzen. Im Falle von Icinga könnte der Aufruf so aussehen + +

    +
    +./configure --with-nagios-user=icinga --with-nagios-group=icinga
    +
    + +

    +Es laufen einige Zeilen über den Bildschirm. Wichtig ist die Ausgabe zum Schluss. +

    +
    +*** Configuration summary for pnp4nagios-0.6.2 23-12-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.2.12
    +  RRDs Perl Modules:                FOUND (Version 1.2012)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    +
    +  Review the options above for accuracy.  If they look okay,
    +  type 'make all' to compile.
    + +

    +Die angezeigten Pfade sollten nun geprüft werden. Falls die gezeigten Werte nicht passen, kann durch einen erneuten Aufruf von ./configure mit den passenden Optionen Abhilfe geschaffen werden.
    + +ACHTUNG: Nachdem es immer wieder Schwierigkeiten gibt: “Location of rrdtool binary” bedeutet inkl. Namen des Binary! Bei Bedarf kann man das beim ./configure als Parameter angeben: + +

    +
     ./configure --with-rrdtool=/usr/local/rrdtool-1.2.xx/bin/rrdtool
    +
     ./configure --help 
    + +

    + +zeigt, welche Optionen möglich sind.
    +
    + +Ein +

    +
    make all
    + +

    +kompiliert nun die in C geschriebenen Komponenten wie NPCD +

    +
    make install
    + +

    +kopiert alles an die richtige Stelle im Filesystem. Die Pfade wurden ja beim ./configure bereits gezeigt. +

    + +

    +Nach der Installation der Programm- und HTML-Dateien wird mit +

    +
    make install-webconf
    + +

    +eine Konfigurationsdatei in das Konfigurationsverzeichnis des Apache-Web-Servers kopiert. +

    + +

    +Optional kann noch +

    +
    make install-config
    + +

    +aufgerufen werden. Damit werden Config-Files für process_perfdata.pl und npcd nach etc/pnp kopiert. +

    + +

    +Wird das INIT Script für den NPCD benötigt, so sorgt +

    +
    make install-init
    + +

    +für die Installation nach /etc/init.d +

    + +

    +Zusammenfassen lassen sich diese einzelnen Commands durch +

    +
    make fullinstall
    + +

    +Hinweis: Wie oben schon beschrieben wird standardmässig mit den Nagios-Einstellungen installiert. Wird Icinga genutzt, muss in der Datei ”/etc/apache2/conf.d/pnp4nagios.conf” der Pfad zum AuthUserFile angepasst werden (Pfad evtl. je nach Distri anpassen): +

    +
    +#       AuthUserFile /usr/local/nagios/etc/htpasswd.users
    +        AuthUserFile /usr/local/icinga/etc/htpasswd.users
    +
    + +

    +Achtung: Nach dem Kopieren der Konfigurationsdatei für den Web-Server bzw. Ändern des AuthUserFile ist ein Restart des Web-Servers notwendig (service httpd restart bzw. /etc/init.d/apache2 restart). +

    + +
    + +

    Update

    +
    + +

    + +Das Update einer 0.6.x-Version funktioniert (fast) genauso wie die Installation. Bitte beachten Sie, dass Sie beim ”./configure” die gleichen Optionen wie bei der Erstinstallation benutzen! +Bitte prüfen Sie außerdem, ob Sie Änderungen im Verzeichnis share/templates.dist vorgenommen haben. Eigene Templates sollten im Ordner share/templates abgelegt werden.
    + +Achtung: Wenn Sie in der Datei config.php Änderungen vorgenommen haben, sollten Sie diese Datei sichern, bevor sie bei einem “make install-config” überschrieben wird. +

    + +

    +Sie können die Schritte make install-webconf und make install-init überspringen, denn zwischen den 0.6.x-Versionen gab es an dieser Stelle keine Änderungen. +

    + +
    + +

    Die Komponenten

    +
    + +

    + +Nach der Installation sind einige Komponenten von PNP an die passenden Stellen im Dateisystem kopiert worden. +

    + +

    +Im Folgenden sind dies die PHP-Files für das Web-Frontend unter + +

    +
     /usr/local/pnp4nagios/share
    + +

    + +Der Datensammler process_perfdata.pl in + +

    +
     /usr/local/pnp4nagios/libexec
    + +

    + +Beispiel-Config-Files mit der Dateierweiterung -sample in + +

    +
     /usr/local/pnp4nagios/etc
    + +

    + +Die Config-Datei config.php für das Web-Frontend in + +

    +
     /usr/local/pnp4nagios/etc
    + +

    +Zurück zur Übersicht | Konfiguration + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/mobile.html b/share/pnp/documents/de_DE/mobile.html new file mode 100644 index 0000000..4885f57 --- /dev/null +++ b/share/pnp/documents/de_DE/mobile.html @@ -0,0 +1,89 @@ + + + +

    Mobile UI

    +
    + +

    + +Mit PNP4Nagios 0.6.14 ist ein Webinterface für mobile Endgeräte in PNP4Nagios integriert worden. +

    + +

    +Das Design wurde mit jQuery Mobile realisiert und ist somit mit den aktuellen mobilen Browsern kompatibel. Auf der Liste der unterstützten Geräte sind die einzelnen Browser aufgeführt und nach Grad der Unterstützung klassifiziert. +

    + +
    + +

    Landing Page

    +
    + +

    + +Das Webinterface wurde so gestaltet, dass die üblichen Links auf das klassische Interface abgefangen und auf die entsprechende mobile Seite umgeleitet werden. Somit können weiterhin innerhalb der Nagios-Mails Links zu PNP-Graphen eingebunden werden, die je nach Endgerät auf die passende Seite verweisen. + +

    + + + + + + + + + + + + + +
    Classic Mobile
    /pnp4nagios/graph /pnp4nagios/mobile
    /pnp4nagios/graph?host=localhost /pnp4nagios/mobile/host/localhost
    /pnp4nagios/graph?host=localhost&srv=ping /pnp4nagios/mobile/graph/localhost/ping
    + +
    + +

    Browser-Erkennung

    +
    + +

    + +Browser werden anhand ihres “User-Agent”-Strings als mobile Browser erkannt. +Die Erkennung kann in der Datei pnp4nagios/etc/config_local.php beeinflusst werden. +

    +
    +$conf['mobile_devices'] = 'iPhone|iPod|iPad|android';
    +
    + +

    +Die Option 'mobile_devices' beinhaltet einen regulären Ausdruck, welcher mit dem “User Agent” des Browsers verglichen wird. +

    + +

    +Der “User Agent” eines Browsers wird im Webserver-Access-Log protokolliert und sieht für ein iOS-Device in etwa wie folgt aus. +

    +
    +"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7"
    +
    + +
    + +

    Screenshots

    +
    + +

    + +Screenshot aufgenommen mit einem iPhone und iOS 4.2 + +

    + + + + + + + + + + +
     Home Screen Homescreen  Loading... Loading …
     Hosts Liste Liste aller Hosts  Liste aller services Liste aller Services eines Hosts
     Graphen Graphen eines Services
    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/modes.html b/share/pnp/documents/de_DE/modes.html new file mode 100644 index 0000000..833104a --- /dev/null +++ b/share/pnp/documents/de_DE/modes.html @@ -0,0 +1,152 @@ + + + +

    Die Kunst Daten zu sammeln

    +
    + +

    + +PNP unterstützt mehrere Arten, die Performance-Daten zu verarbeiten. Die einzelnen Modi unterscheiden sich durch ihre Komplexität und die zu erwartende Performance. +

    + +

    +Das folgende Bild zeigt die Verbindungen zwischen Nagios, PNP und RRDtool +

    + +

    +Nagios führt für jeden Host- und jeden Service, dessen Performance-Daten gesammelt werden sollen, einen Befehl aus. Abhängig vom gewählten Modus werden die Daten entweder direkt an ein Perl-Script übergeben oder in temporäre Dateien geschrieben und später verarbeitet. process_perfdata.pl legt die Datei in XML-Dateien ab und speichert sie mit Hilfe von RRDtool in RRD-Dateien.
    + +

    + +

    +Bevor Ihr euch auf einen Modus festlegt, lest euch alles durch und entscheidet selbst, welcher Weg für eure Installation der Beste ist. +

    + +
    + +

    Die Modi im Vergleich

    +
    + +
    + +

    Synchronous Mode

    +
    + +

    + +Der “Sync Mode” ist der einfachste und am leichtesten einzurichten. Nagios ruft für jeden Service (bzw. Host) zusätzlich das Perl-Script process_perfdata.pl auf, um die Daten zu verarbeiten. +

    + +

    +Der sync-Mode funktioniert sehr gut bis ca. 1000 Services in einem Intervall von 5 Minuten. +Dieser Modus belastet aber auch Nagios am meisten, daher ist es auch in kleinen Installationen ratsam, die weiteren Modi zu beachten. +

    + +
    + +

    Bulk Mode

    +
    + +

    +Im Bulk-Mode schreibt Nagios die benötigten Daten in eine temporäre Datei. Nach Ablauf einer definierten Zeit wird die Datei an einem Stück abgearbeitet und gelöscht. +

    + +

    +Die Anzahl der Aufrufe von process_perfdata.pl reduziert sich um ein Vielfaches. Abhängig von der Zeit und den gesammelten Daten werden wesentlich weniger Systemaufrufe ausgeführt. Dafür läuft process_perfdata.pl länger. +

    + +

    +Hinweis +Bei diesem Modus sollte man die Laufzeit von process_perfdata.pl im Auge behalten. So lange, wie process_perfdata.pl zum Verarbeiten der Daten benötigt, so lange kann Nagios keine Checks ausführen. +

    + +

    +Auszug aus var/perfdata.log: + +

    +
    +2007-10-18 12:05:01 [21138] 71 Lines processed
    +2007-10-18 12:05:01 [21138] .../spool/service-perfdata-1192701894-PID-21138 deleted
    +2007-10-18 12:05:01 [21138] PNP exiting (runtime 0.060969s) ...
    +
    + +

    +71 Zeilen wurden in 0,06 Sekunden verarbeitet. Das ist das Datenvolumen bei ca. 2000 Services und der Verarbeitung im 10-Sekunden-Intervall. Wir haben Nagios also genau für 0.06 Sekunden blockiert. +

    + +
    + +

    Bulk Mode mit NPCD

    +
    + +

    + +Dies ist aus Nagios-Sicht die sauberste Art der Verarbeitung. Nagios wird nicht blockiert. +

    + +

    +Nagios benutzt wieder eine temporäre Datei, um die Daten zu speichern, und führt nach Ablauf der Zeit wieder ein Command aus. Jedoch wird die Datei nicht sofort von Process_perfdata.pl verarbeitet, sondern in ein spool-Verzeichnis verschoben. Da das Verschieben einer Datei im gleichen Filesystem so gut wie keine Zeit beansprucht, ist Nagios sofort wieder in der Lage, wichtige Arbeiten auszuführen. +

    + +

    +Der NPCD ( Nagios Performance C Daemon ) überwacht nun das Verzeichnis auf neue Dateien und übergibt diese an process_perfdata.pl. Die Verarbeitung der Performancedaten ist also komplett von Nagios entkoppelt. NPCD wiederum ist in der Lage, zum Verarbeiten der Daten mehrere Threads zu starten. +

    + +
    + +

    Bulk Mode mit npcdmod

    +
    + +

    + +Achtung +Beginnend mit Nagios 4 haben sich die internen Strukturen geändert, so dass der Start des Moduls fehlschlägt. Bisher gibt es keine Pläne Nagios 4 zu unterstützen. Bitte wählen Sie einen der anderen Modi. +

    + +

    +In diesem Szenario kommt npcdmod.o, ein NEB-Modul, zum Einsatz. +Diese Modul reduziert die Konfiguration des “Bulk Mode mit NPCD” auf zwei Zeilen in der nagios.cfg. +

    + +

    +Dieser Modus ist gleichzusetzen mit dem “Bulk Mode mit NPCD”. Es ist auch genau der gleiche Ablauf und die gleiche Performance. +

    + +
    + +

    Gearman Mode

    +
    + +

    + +

    + +

    +PNP4Nagios kann seit Version 0.6.12 als Gearman Worker betrieben werden. So sind große verteilte Nagios Umgebungen auf Basis von mod_gearman realisierbar. +

    + +

    +Benötigt wird eine fertig eingerichtete mod_gearman Installation wie von Sven Nierlein unter http://labs.consol.de/lang/en/nagios/mod-gearman/ beschrieben. +

    + +
    + +

    Die Entscheidung

    +
    + +

    + +Welchen der beschriebenen Wege ihr verwendet, hängt also stark von der Größe der Nagios-Installation ab. +

    + +

    +Die verwendeten Begriffe werden euch aber in der Dokumentation immer wieder über den Weg laufen. +

    + +

    +Zurück zur Übersicht | Installation + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/new-features.html b/share/pnp/documents/de_DE/new-features.html new file mode 100644 index 0000000..cd7d20d --- /dev/null +++ b/share/pnp/documents/de_DE/new-features.html @@ -0,0 +1,67 @@ + + + +

    Neues in PNP 0.6.x

    +
    + +

    +PNP 0.6.x Preview +

    + +

    +Die Arbeit an der Version 0.6.x ist in vollem Gange. +

    + +

    +Mit Version 0.6.x steigen wir von Subversion auf GIT um. Der Sourcecode ist bereits auf Sourceforge erhältlich. +

    + +

    +http://pnp4nagios.git.sourceforge.net +

    + +

    + +Bisher umgesetzte Funktionen: + +

    +
      +
    • Webfrontend basiert auf Kohana
      +
    • +
    • Webfrontend basiert auf jQuery Themes
      +
    • +
    • Javascript-Funktionen über jQuery Plugins
      +
    • +
    • process_perfdata.pl wird in der Lage sein, pro Datenreihe eine eigene RRD-Datenbank zu verwenden.
      +
    • +
    • Installer weiter verbessert. Angabe von Directory-Layouts über --with-layout
      +
    • +
    • RRDtool-Fehler werden als Bild dargestellt. Keine fehlenden Bilder mehr.
      +
    • +
    • PNP-Templates können keine internen Variablen mehr überschreiben.
      +
    • +
    • PNP-Templates der Version 0.4.x können weiter verwendet werden.
      +
    • +
    • PDF-Funktionen neu umgesetzt.
      +
    • +
    • Template default.php optimiert.
      +
    • +
    • Export aus den RRD-Datenbanken im XML,CSV und JSON Format über die RRDtool “xport” Funktion.
      +
    • +
    • Page-Funktionen neu umgesetzt.
      +
    • +
    • Fehlerseiten verweisen auf online FAQ-Artikel.
      +
    • +
    • Mouseover Popup im Nagios-Frontend über jQuery.clueTip Plugin
      +
    • +
    • Volle Unterstützung des rrdcached.
      +
    • +
    + +

    + +zurück zur Übersicht | Anforderungen + +

    + +
    diff --git a/share/pnp/documents/de_DE/npcd.html b/share/pnp/documents/de_DE/npcd.html new file mode 100644 index 0000000..8d0a79b --- /dev/null +++ b/share/pnp/documents/de_DE/npcd.html @@ -0,0 +1,323 @@ + + + +

    NPCD

    +
    + +

    + +NPCD (Nagios-Perfdata-C-Daemon) wurde geschrieben, um die asynchrone Bearbeitung von Nagios Performance-Daten zu ermöglichen. +

    + +
    + +

    Einleitung

    +
    + +

    + +In großen Nagios-Installationen kann es zu nicht akzeptierbaren Verspätungen seitens der Checks kommen. Das bedeutet, dass Nagios einen Check zum Zeitpunkt x ausführen soll, diesen aber erst y Sekunden später tatsächlich ausführt. +

    + +

    +Wenn man dem Nagios-Daemon mitteilt, dass man nach jedem einzelnen Check auch die Performance-Daten verarbeiten möchte, so geht dies bis zu einem bestimmten Grad gut, ab einer gewissen Anzahl von Checks pro Sekunde allerdings kommt man relativ schnell zu den sog. Latency-Problemen. +

    + +

    +Um die Anzahl der Aktionen pro Check zu verringern, kann man nun PNP im Bulk-Mode verwenden, wobei die Performance-Daten zunächst vom Nagios-Prozess gesammelt und anschließend ebenfalls vom Nagios-Prozess selbst verarbeitet werden. +

    + +

    +Man kann aber auch dem Nagios-Prozess mitteilen, dass die Verarbeitung der Performance-Daten lediglich durch das Verschieben der Dateien in ein Spool-Verzeichnis geschehen soll, welches für den Nagios-Prozess selbst eine sehr schnelle Aktion ist und die Performance nicht nennenswert beeinflusst und somit dem Core mehr Zeit für seine eigentliche Arbeit lässt: weitere Checks ausführen, Alamierungen bereitstellen, etc. +

    + +
    + +

    Wie NPCD arbeitet

    +
    + +

    + +Wie bereits erwähnt, ist die Arbeit der Performance-Daten-Verarbeitung durch das schnelle Verschieben der Datei bereits erledigt, aber das bringt die Performance-Daten noch nicht in die RRD-Datenbank. +

    + +

    +Um den Transport der Performance-Daten-Dateien kümmert sich nun der NPCD-Daemon, unabhängig vom Nagios-Prozess, indem er regelmäßig in das Spool-Verzeichnis guckt und für jede dort gefundene Datei eine Aktion ausführt. +

    + +

    +Nachdem NPCD gestartet wurde, erstellt er sich eine Liste von Dateinamen des Spool-Verzeichnisses und startet für jede gefundene Datei einen Thread zur weiteren Verarbeitung mit Hilfe des perfdata_file_run_cmd und dem optionalen perfdata_file_run_cmd_arg als zusätzlichem Argument. +

    + +

    +Da das Format der Performance-Daten-Dateien dem Format der 'normalen' PNP-Bulk-Modus-Dateien gleicht, kann NPCD nun für jede gefundene Datei also process_perfdata.pl im Bulk Modus aufrufen. +

    + +
    + +

    Vor- und Nachteile

    +
    + +

    + +Pro: +

    +
      +
    • bessere Performance für Nagios
      +
        +
      • aufgrund der vom Nagios-Prozess getrennten Verarbeitung der Performance-Daten hat Nagios mehr Zeit für die wichtigen Dinge
        +
      • +
      +
    • +
    • kein Datenverlust
      +
        +
      • solange Nagios Performance-Daten-Dateien im Spool-Verzeichnis ablegt, gehen keine Daten verloren. Selbst wenn der NPCD mal nicht laufen sollte (Bsp. nach Neustart des Systems), werden die Dateien nach Wiederanlauf in chronologischer Reihenfolge bearbeitet ($TIMET$ Makro beim verschieben ins Spool-Verzeichnis)
        +
      • +
      +
    • +
    + +

    + +Kontra: +

    +
      +
    • Keine Echtzeitverarbeitung der Performance-Daten
      +
        +
      • aufgrund des Rhythmusses, wann Nagios die Performance-Daten-Dateien verschiebt (service_perfdata_file_processing_interval)
        +
      • +
      • nach jedem Lauf durch alle Dateien des Spool-Verzeichnisses wartet NPCD 10 Sekunden lang auf neue Dateien
        +
      • +
      +
    • +
    + +
    + +

    NPCD Config

    +
    + +

    + +NPCD muss zwangsläufig über eine Konfigurationsdatei gesteuert werden. Eine Beispielkonfiguration liegt der PNP-Installation als npcd.cfg-sample bei. +

    + +

    +Nach Umbenennen der -sample Datei zu npcd.cfg kann NPCD nun wie folgt gestartet werden: +

    +
    /usr/local/pnp4nagios/bin/npcd -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +oder + +

    +
    /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +um NPCD im Hintergrund als Daemon laufen zu lassen. +

    + +

    +Hinweis: +Die -sample Datei sollte in jedem Fall in npcd.cfg umbenannt werden, da sie sonst bei einem Update von PNP überschrieben werden könnte. +

    + +
    + +

    npcd.cfg-sample

    +
    + +

    + +Dies sind die essentiellen Konfigurationsdirektiven für NPCD: +

    +
    # Privilege Options
    +user = nagios
    +group = nagios
    +
    +# Logging Options
    +log_type = syslog
    +log_file = /usr/local/pnp4nagios/var/npcd.log
    +max_logfile_size = 10485760
    +log_level=0
    +
    +# Processing Options
    +perfdata_spool_dir = /usr/local/pnp4nagios/var/spool/perfdata/
    +perfdata_file_run_cmd = /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +perfdata_file_run_cmd_args = -b
    +
    +# Thread Options
    +npcd_max_threads=5
    +
    +# greedy options
    +use_load_threshold = 0
    +load_threshold = 10.0
    +
    +# Process Options
    +pid_file=/var/run/npcd.pid
    +
    + +
    + +

    Die Direktiven

    +
    +
      +
    • Privilege-Optionen
      +
        +
      • user <username>
        +
          +
        • NPCD versucht die Userberechtigung zu diesem User zu wechseln.
          +
        • +
        • Default: nagios
          +
        • +
        +
      • +
      • group <groupname>
        +
          +
        • NPCD versucht die Gruppenberechtigung zu dieser Gruppe zu wechseln.
          +
        • +
        • Default: nagios
          +
        • +
        +
      • +
      +
    • +
    • Logging-Optionen
      +
        +
      • log_type <syslog> oder <file>
        +
          +
        • Log-Type, den NPCD zum Loggen verwenden wird
          +
        • +
        • Default: syslog
          +
        • +
        +
      • +
      • log_file </pfad/zu/datei>
        +
          +
        • Falls log_type = file wird diese Logdatei verwendet
          +
        • +
        • Default: /usr/local/pnp4nagios/var/npcd.log
          +
        • +
        +
      • +
      • max_logfile_size <bytes>
        +
          +
        • NPCD wird nach Erreichen der hier angegebenen Dateigröße eigenständig eine Logrotation durchführen
          +
        • +
        • Default: 10485760 = 10 MByte
          +
        • +
        +
      • +
      • log_level <integer>
        +
          +
        • Wie viel soll aufgezeichnet werden, möglich ist:
          +
            +
          • 0 = Kein Log - außer Fehlern
            +
          • +
          • 1 = wenig Log - etwas mehr Aufzeichnen
            +
          • +
          • 2 = Mehr Log (aktuell ALLES)
            +
          • +
          • -1 = DEBUG Mode - Es wird alles aufgezeichnet und die Bearbeitung wird verlangsamt
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      +
    • +
    • Bearbeitungs-Optionen
      +
        +
      • perfdata_spool_dir </path/to/spool/dir/>
        +
          +
        • Das Verzeichnis, in das Nagios die Dateien verschiebt
          +
        • +
        • Default: /usr/local/pnp4nagios/var/spool/
          +
        • +
        +
      • +
      • perfdata_file_run_cmd </path/to/bin/filename>
        +
          +
        • Das Programm, welches Nagios für jede Datei aufrufen soll
          +
        • +
        • Default: /usr/local/pnp4nagios/libexec/process_perfdata.pl
          +
        • +
        +
      • +
      • perfdata_file_run_cmd_args <option>
        +
          +
        • Das Argument, welches optional an perfdata_file_run_cmd angehängt wird
          +
        • +
        • Default: ”-b”
          +
        • +
        • :!: Die Kommandozeile wird nach folgendem Schema aufgebaut:
          <perfdata_file_run_cmd> <perfdata_file_run_cmd_args> <filename_from_perfdata_spool_dir>
          +
          +
        • +
        +
      • +
      +
    • +
    • Thread-Optionen
      +
        +
      • npcd_max_threads <integer value>
        +
          +
        • Anzahl der maximal zu startenden parallelen Threads
          +
        • +
        • Default: 5
          +
        • +
        +
      • +
      +
    • +
    • Greedy-Optionen
      +
        +
      • use_load_threshold <0 oder 1>
        +
          +
        • definiert, ob NPCD bei Erreichen des load_thresholds die Anzahl der Threads begrenzen soll
          +
            +
          • 0 = ausschalten (weitere Threads starten)
            +
          • +
          • 1 = einschalten
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      • load_threshold <float value>
        +
          +
        • wenn use_load_threshold auf 1 gesetzt ist, werden bei Erreichen dieses load limits keine neuen Threads gestartet
          +
        • +
        • Default: 10.0
          +
        • +
        +
      • +
      +
    • +
    • Process-Optionen
      +
        +
      • pid_file </path/to/pid.file>
        +
          +
        • Pfad zum PID File
          +
        • +
        • Default: /var/run/npcd.pid
          +
        • +
        +
      • +
      +
    • +
    + +

    + +zurück zur Übersicht | Wrapper-Script + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/pages.html b/share/pnp/documents/de_DE/pages.html new file mode 100644 index 0000000..b518764 --- /dev/null +++ b/share/pnp/documents/de_DE/pages.html @@ -0,0 +1,93 @@ + + + +

    Pages

    +
    + +

    + +„pages“ bieten die Möglichkeit, Grafiken von verschiedenen Hosts/Services auf einer Seite zusammenzufassen. Auf diese Weise können z.B. die Übertragungsraten der Netzwerk-Interfaces aller Tape-Libraries dargestellt werden. Innerhalb der Definitionen sind reguläre Ausdrücke möglich, so dass – entsprechende Namen vorausgesetzt - mit wenig Aufwand viel erreicht werden kann. +Das Verzeichnis, das in config.php durch den Konfigurationseintrag „$conf['page_dir']“ angegeben wurde, enthält ein oder mehrere Dateien mit der Endung „.cfg“. +

    + +

    +Kommentare beginnen mit einem '#' und sind auch innerhalb einer Zeile möglich. +Jede Datei enthält eine „page“-Definition, die neben dem Namen der Seite festlegt, ob die nachfolgenden Grafikdefinitionen reguläre Ausdrücke enthalten.
    + +Die Bezeichnung hinter page_name erscheint in der Liste der verfügbaren Seiten und wird als Titel im Browser angezeigt. +Achtung: “host_name” und “service_desc” beziehen sich auf die Namen der Dateien im perfdata-Ordner, nicht auf die Nagios-Bezeichnungen. Leerzeichen werden durch Unterstriche (“_”) ersetzt. +

    +
    define  page  {
    +        use_regex 1		# 0 = keine regulären Ausdrücke, 1 = reguläre Ausdrücke
    +        page_name Test-Seite	# Beschreibung der Seite
    +}
    + +

    +Danach folgen ein oder mehrere „graph“-Definitionen: +

    +
    define graph {
    +        host_name       host1,host2,host3
    +        service_desc    Current_Load
    +}
    + +

    + +Achtung: Damit die oben gezeigte Liste von Host-Namen funktioniert, muss use_regex 0 gesetzt sein! +

    +
    define graph {
    +        host_name       host4
    +        service_desc    Current_Users
    +}
    + +

    +Und jetzt mit regulären Ausdrücken. Zuerst alle Hosts, deren Name mit „Tape“ beginnen: + +

    +
    define graph {
    +        host_name       ^Tape
    +        service_desc    Traffic
    +}
    + +

    +alle Hosts, deren Namen mit “00” enden + +

    +
    define graph {
    +        host_name       00$
    +        service_desc    Load
    +}
    + +

    +alle Services des localhost, deren Namen ein „a“ oder „o“ enthalten: + +

    +
    define graph {
    +        host_name       localhost
    +        service_desc    a|o
    +}
    + +

    +alle Services, die im Namen nach einem „_“ (mindestens) drei Ziffern haben auf allen Hosts, deren Namen mit „UX“ beginnen: + +

    +
    define graph {
    +        host_name       ^UX
    +        service_desc    _\d{3}
    +}
    + +

    +In einigen Fällen möchten Sie vielleicht die Anzeige auf einen Graphen beschränken. Um dies zu erreichen, können Sie die optionale Direktive “source” benutzen, gefolgt von einer Zahl, die die Position in der RRD-Datei angibt. Die Zählung beginnt ab 0 + +

    +
    define graph {
    +       host_name       host1,host2,host3
    +       service_desc    PING
    +       source          1
    +}
    + +

    +zurück zur Übersicht | Datenexport + +

    + +
    diff --git a/share/pnp/documents/de_DE/perfdata_format.html b/share/pnp/documents/de_DE/perfdata_format.html new file mode 100644 index 0000000..7488ebf --- /dev/null +++ b/share/pnp/documents/de_DE/perfdata_format.html @@ -0,0 +1,62 @@ + + + + + + + +
    2.6. Performance-Daten
    + +

    + +'Bezeichnung'=Wert[UOM];[warn];[crit];[min];[max] +

    + +

    +Anmerkungen: + +

    +
      +
    1. Leerzeichen trennen Listen von Bezeichnung/Werte-Paaren
      +
    2. +
    3. Bezeichnungen können beliebige Zeichen enthalten
      +
    4. +
    5. die Bezeichnung muss in Apostrophe eingeschlossen sein, wenn diese Gleichheitszeichen (=), Apostroph (') oder Leerzeichen ( ) enthält, ansonsten sind die Apostrophe optional
      +
    6. +
    7. die Länge der Bezeichnung ist beliebig, aber idealerweise sind die ersten 19 Zeichen eindeutig (aufgrund einer Beschränkung in RRD). Bitte beachten Sie, dass es eine Längenbegrenzung bei der Menge von Daten gibt, die von NRPE an Nagios geliefert werden kann
      +
    8. +
    9. um ein Apostroph darzustellen, nutzen Sie zwei einzelne Apostrophe
      +
    10. +
    11. warn, crit, min und/oder max können leer sein (z.B. wenn der Schwellwert nicht definiert ist oder wenn min oder max nicht zutreffen). Nachfolgende, nicht gefüllte Semikola können entfallen
      +
    12. +
    13. min und max sind nicht erforderlich, wenn UOM = %
      +
    14. +
    15. Wert, min und max sind aus der Klasse [-0-9.] (Ziffern, Minuszeichen und Dezimalpunkt). Alle müssen das gleiche UOM benutzen
      +
    16. +
    17. warn und crit sind im “Range”-Format (siehe Abschnitt 2.5 der Original-Dokumentation). Alle müssen das gleiche UOM benutzen.
      +
    18. +
    19. UOM (unit of measurement, Maßeinheit) ist eins von:
      +
        +
      • keine Einheit angegeben - angenommen wird eine Zahl (int oder float) von Dingen (z.B. Benutzer, Prozesse, Load)
        +
      • +
      • s - Sekunden (auch us, ms)
        +
      • +
      • % - Prozent
        +
      • +
      • B - Bytes (auch KB, MB, TB; GB?)
        +
      • +
      • c - ein fortlaufender Zähler (z.B. Bytes, die über ein Interface übertragen werden)
        +
      • +
      +
    20. +
    + +

    + +Es bleibt Drittanbietern überlassen, aus den Performance-Daten Graphen zu erzeugen.| +

    + +

    +Quelle: http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN201 + +

    diff --git a/share/pnp/documents/de_DE/rrd_convert.html b/share/pnp/documents/de_DE/rrd_convert.html new file mode 100644 index 0000000..682eec6 --- /dev/null +++ b/share/pnp/documents/de_DE/rrd_convert.html @@ -0,0 +1,84 @@ + + + +

    RRD_STORAGE_TYPE = MULTIPLE

    +
    + +

    + +Verfügbar ab PNP 0.6.3 +

    + +

    +Mit PNP-Version 0.6 ist es möglich, die Performance-Daten nicht in einer einzelnen RRD-Datenbank (SINGLE), sondern in mehreren RRD Datenbanken (MULTIPLE) zu speichern. +

    + +

    +Nach dem Anlegen eines RRD-Files ist es nicht mehr möglich, dieses um eine Datasource (DS) zu erweitern. Daraus ergeben sich Probleme für Nagios-Plugins, die im Laufe der Zeit die Anzahl der Datenreihen dynamisch ändern. +

    + +

    +Ein Beispiel wäre check_disk, wenn man pauschal alle verfügbaren Filesysteme in einem Service überwacht. Kommt ein Filesystem hinzu, so kann die RRD-Datenbank nicht mehr aktualisiert werden. Die Struktur der neuen Daten passt einfach nicht mehr zur RRD-Struktur. +

    + +

    +PNP arbeitet per Default mit der Option RRD_STORAGE_TYPE = SINGLE, welche in der process_perfdata.cfg definiert ist. +

    + +

    +Diese Einstellung sollte nicht global verändert werden, da PNP nach der Umstellung auf MULTIPLE sofort beginnt, neue RRD-Files anzulegen. Alte Daten gehen damit sofort verloren! +

    + +

    +Weiterhin ist es im Hinblick auf die Performance nicht sinnvoll, global mit RRD_STORAGE_TYPE = MULTIPLE zu arbeiten. Die Anzahl der RRD-Datenbanken und somit auch der Disk-I/O während der Updates vervielfacht sich. Entsprechend sollte man mit Bedacht wählen, welche Nagios-Check-Commands mit welcher Einstellung behandelt werden sollen. +

    + +

    +Im Abschnitt Custom Templates ist beschrieben, wie die Einstellungen vorgenommen werden können. +

    + +
    + +

    Ein Konverter

    +
    + +

    + +Das Script libexec/rrd_convert.pl dient zum Umschalten des RRD_STORAGE_TYPE auf MULTIPLE und zum gleichzeitigen migrieren der RRD-Datenbanken. +

    + +

    +Maßgeblich ist dabei wie immer bei PNP das Nagios-Check-Command. +

    +
    rrd_convert.pl --check_command=<nagios_check_command> | --list_commands [ --dry-run ] [ --tmp_dir=<temp-dir> ]
    +[[ --no_structure_check ]]
    + +

    +Das Script erwartet über die Option --check-command= das Check-Command, nach dem gesucht werden soll. +

    + +

    +rrd_convert.pl wird nun alle PNP-XML-Dateien nach diesem Command durchsuchen und eine Statistik ausgeben. +

    + +

    +Nach Bestätigung durch den User beginnt das Konvertieren der einzelnen RRD-Datenbanken, wobei der aktuelle Ablauf angezeigt wird. Das Script endet, wenn Sie <ENTER> drücken, also geben Sie bitte einen Buchstaben ein. +

    + +

    +Die Option --dry-run sorgt dafür, dass die RRD-Datenbanken zwar konvertiert, jedoch in /tmp/rrd_convert in separaten Verzeichnissen je Host gespeichert werden. So kann man sich einen Überblick über die zu erwartende Laufzeit und das Datenvolumen verschaffen. +

    + +

    +Wenn Sie das temporäre Verzeichnis ändern möchten, dann können Sie das mit Hilfe der Option --tmp_dir=<alternatives TMP-Directory> tun. + +Ab und zu passt die Anzahl der Datasources in den RRD-Dateien nicht zu der Anzahl in den XML-Dateien. Das passiert z.B. dann, wenn Plugins plötzlich eine andere Zahl von Datenreihen liefern (siehe oben check_disk). Mit der Option --no_structure_check'' werden auch diese RRD-Dateien konvertiert. +

    + +

    +back to contents | NPCD-Details + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/rrdcached.html b/share/pnp/documents/de_DE/rrdcached.html new file mode 100644 index 0000000..131ebf6 --- /dev/null +++ b/share/pnp/documents/de_DE/rrdcached.html @@ -0,0 +1,153 @@ + + + +

    RRDtool Cache Daemon

    +
    + +

    + +In großen Installationen wird man über kurz oder lang feststellen, dass die Verarbeitung der Performance-Daten eine recht hohe I/O-Last zur Folge hat. RRDtool muss extrem viele Updates auf Disk schreiben, kann dabei jedoch den Disk-Cache nicht optimal ausnutzen. +

    + +

    +Eine Optimierung stellt das Sammeln und Sortieren der Daten dar. Es ist für das System effektiver, viele Updates im Block in eine RRD-Datenbank zu schreiben. Der Disk-Cache kann dabei effektiver genutzt werden. +

    + +

    +In der aktuellen RRDtool-Version ( SVN trunk 1550+ ) ist der rrdcached enthalten, der genau diese Situation verbessern soll. +

    + +

    +An dieser Stelle möchte ich mich bei Florian octo Forster, Kevin Brintnall und Tobi Oetiker bedanken. Die Entwicklung dieses Daemons wurde vorbildlich auf der rrd-developers Mailingliste koordiniert. +

    + +
    + +

    Arbeitsweise

    +
    + +

    + +Der rrdcached arbeitet als Daemon im Hintergrund und öffnet einen UNIX- oder TCP-Socket, auf dem er auf Anfragen von rrdtool wartet. Aufgrund von Sicherheitsbedenken ist es in neueren Versionen von rrdcached aber nicht mehr möglich absolute Pfadangaben (wie bei pnp4nagios üblich) bei Netzwerkzugriffen zu verwenden, daher ist derzeit nur Nutzung von UNIX-Sockets möglich. +

    + +
    + +

    rrdcached

    +
    + +

    + +Der rrdcached kennt einige wichtige Optionen, die beim Start übergeben werden. +

    + +

    +Option -l definiert den Socket, auf dem der rrdcached Requests annimmt. Der Default-UDP-Port ist 42217, der Default-UNIX-Socket /tmp/rrdcached.sock. +

    +
    +-l unix:/pfad/zum/rrdcached.sock
    +-l /pfad/zum/rrdcached.sock
    +-l 127.0.0.1
    +-l 127.0.0.1:8888
    +
    + +

    +Option -P gibt die für die nachfolgenden Sockets (mit -l spezifiziert) erlaubten Befehle an, welche auf die RRD-Datenbanken angewendet werden können. +

    +
    -P FLUSH,PENDING
    + +

    +Option -s erlaubt es die Gruppenzugehörigkeit der nachfolgenden UNIX-Sockets zu ändern. +

    +
    -s nagios
    + +

    +Option -m setzt die Zugriffsrechte für die nachfolgenden UNIX-Sockets auf die (in oktal) angegebenen Werte. +

    +
    -m 0660
    + +

    +Option -w bestimmt den Intervall in Sekunden, in dem die Daten auf Disk geschrieben werden sollen. +

    +
    -w 1800
    + +

    +Option -z definiert einen Delay, der die über die Option -w definierten Schreibzyklen in einen zufälligen Bereich [0-delay] verteilt, um gleichzeitige Schreibzugriffe zu verhindern. Der Wert der Option -z darf nicht größer gewählt werden als -w. +

    +
    -z 1800
    + +

    +Option -p definiert ein PID File +

    +
    -p /var/run/rrdcached.pid
    + +

    +Option -j definiert den Pfad zu einem Journal-Verzeichnis. Dort werden alle Aufträge protokolliert und ggf. beim nächsten Start nachgefahren, falls der rrdcached-Daemon abstürzt. +

    +
    -j /var/cache/rrdcached
    + +

    +Daraus ergibt sich beispielsweise ein Aufruf von rrdached mit folgenden Parametern +

    +
     rrdcached -w 1800 -z 1800 -p /tmp/rrdcached.pid -j /tmp -s nagios -m 0660 -l unix:/tmp/rrdcached.sock
    + +
    + +

    rrdtool

    +
    + +

    + +RRDtool selbst wird die Existenz des Daemons über die Option --daemon=<socket> mitgeteilt. + +

    +
     rrdtool --daemon=unix:/tmp/rrdcached.sock update ...
    + +

    + +Dies muss natürlich mit den Startoptionen des rrdcached übereinstimmen! +

    + +
    + +

    Integration in PNP

    +
    + +

    + +Da zwei Bestandteile von PNP auf den rrdcached vorbereitet werden müssen, ergeben sich Änderungen in zwei Config-Files. Außerdem muß der User unter welchem der Webserver läuft zur Gruppe unter der Nagios läuft hinzugefügt werden. +

    + +

    +1. Anpassen der process_perfdata.cfg für den Datensammler process_perfdata.pl +

    +
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +RRD_DAEMON_OPTS = unix:/var/run/rrdcached.sock
    +
    + +

    +2. Anpassen der config_local.php (bzw. config.php) für das Webinterface +

    +
    +#
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +# $conf['RRD_DAEMON_OPTS'] = 'unix:/tmp/rrdcached.sock';
    +$conf['RRD_DAEMON_OPTS'] = 'unix:/var/run/rrdcached.sock';
    +
    + +

    +Die passenden Optionen sind bereits in den Beispieldateien enthalten. +

    + +

    +zurück zur Übersicht | migrieren von RRD-Dateien + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/start.html b/share/pnp/documents/de_DE/start.html new file mode 100644 index 0000000..6e5e38b --- /dev/null +++ b/share/pnp/documents/de_DE/start.html @@ -0,0 +1,199 @@ + + + +

    Dokumentation

    +
    +
    + +
    +
    PNP4Nagios Broker Module npcdmod.o ist nicht kompatibel mit Nagios Core 4.x
    +
    + +
    + +

    + +

    +

    + +

    + +Theme "smoothness" +

    + +

    +PNP ist ein Addon für Nagios, das es ermöglicht, die von Nagios Plugins gelieferten Performancedaten zu analysieren und automatisch in RRD Datenbanken zu speichern. +

    + +

    + +Während der Entwicklung von PNP haben wir Wert auf eine einfache Installation und auf wenig Aufwand im laufenden Betrieb gelegt. Ein Administrator hat besseres zu tun als Graphing Tools zu konfigurieren. +

    + +

    +Um diese Aufgabe zu erfüllen, setzen wir bewusst auf Standards. PNP verarbeitet nur Performancedaten, die sich strikt an die Developer Guidelines für Nagios Plugins halten. Mit dieser Einschränkung wollen wir bewusst die Arbeit der Nagios Plugin Developer honorieren, die sich für die Einhaltung der Richtlinien einsetzen. +

    + +

    +Für alle, die nun noch neugierig sind, steht die folgende Dokumentation bereit, um den Einstieg in PNP zu erleichtern. +

    + +

    +komplette Dokumentation auf "einer" Seite +

    + +
    + +

    Dokumentation

    +
    + + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/timeranges.html b/share/pnp/documents/de_DE/timeranges.html new file mode 100644 index 0000000..f9a6123 --- /dev/null +++ b/share/pnp/documents/de_DE/timeranges.html @@ -0,0 +1,96 @@ + + + +

    Timeranges

    +
    + +

    + +In der Übersicht zeigt PNP fünf Zeitbereiche, die frei in der config.php definiert werden können. +

    + +

    +Es gibt aber auch die Möglichkeit, die Zeitbereiche über die URL zu beeinflussen. Dies ist hilfreich, wenn z.B. automatisch PDF-Dokumente erstellt werden sollen +

    + +

    +Die Zeitbereiche werden über die Optionen start und end definiert. +

    + +

    +Beispiel: + +

    +
     pnp4nagios/graph?host=<hostname>&srv=<servicedesc>&start=-1week
    +
     pnp4nagios/graph?host=<hostname>&srv=<servicedesc>&start=2011102322:50:00&end=2011102409:50:00
    + +

    + +Der Startzeitpunkt der Graphen wird somit, ausgehend vom aktuellen Datum, um eine Woche nach hinten verschoben. Der Endzeitpunkt bleibt auf dem aktuellen Zeitstempel. Aber auch end lässt sich über diesen Weg beeinflussen, wobei beide Optionen auch einzeln manipuliert werden dürfen. +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    start end view Ergebnis
    Alle Ansichten enden mit der aktuellen Zeit
    x Alle Ansichten beginnen mit dem angegebenen Datum
    x Alle Ansichten enden mit dem angegebenen Datum
    x x Eine Ansicht zwischen den beiden Zeitangaben
    x Eine Ansicht endet mit der aktuellen Zeit
    x x Eine Ansicht beginnt mit dem angegebenen Datum
    x x Eine Ansicht endet mit dem angegebenen Datum
    + +

    + +Beispiele zur Datumsangabe: + +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Format Beschreibung
    2009W04 4. KW 2009
    1.5.2009 1. Mai 2009
    -1 day Einen Tag zurück
    -3 weeks 3 Wochen zurück
    -1 year Ein Jahr zurück
    yesterday Gestern
    2011102322:50:00 23.10.2011 ab 22:50:00 Uhr
    + +

    + +zurück zur Übersicht | Pages + +

    + +
    diff --git a/share/pnp/documents/de_DE/tpl.html b/share/pnp/documents/de_DE/tpl.html new file mode 100644 index 0000000..99c6aee --- /dev/null +++ b/share/pnp/documents/de_DE/tpl.html @@ -0,0 +1,243 @@ + + + +

    Was sind Templates ?

    +
    + +

    + +PNP benutzt Templates, um das Aussehen der RRD-Graphen zu beeinflussen. +

    + +

    +Dabei bestimmt das verwendete check_command, welches Template zur Darstellung herangezogen wird. Im Folgenden wird beschrieben, wo Templates gespeichert werden und wie die Entscheidung für das “richtige” Template getroffen wird. +

    + +
    + +

    Wann wird welches Template verwendet ?

    +
    + +

    + +Templates werden an zwei Stellen im Dateisystem gespeichert. + +

    +
      +
    • share/templates.dist - für Templates, die im PNP-Paket bereits enthalten sind.
      +
    • +
    • share/templates - für selbst erstellte Templates. Diese werden bei Updates nicht verändert.
      +
    • +
    + +

    + +Weiterhin können seit Version 0.6.5 weitere Template Verzeichnisse in der Config Datei pnp4nagios/etc/config.php hinzugefügt werden. +

    + +

    +Soll der Graph für den Service “http” auf Host “localhost” angezeigt werden, so sucht PNP zuerst nach der XML-Datei perfdata/localhost/http.xml und liest diese ein. Diese XML-Dateien werden automatisch erstellt und enthalten Informationen zum jeweiligen Host und Service. Weiterhin enthält der Kopf Informationen über das Plugin und die Performance-Daten. Im folgenden Beispiel erkennt man anhand des XML-Tags <TEMPLATE>, welches PNP-Template für diesen Graphen verwendet werden soll. +

    + +

    +/localhost/http.xml + +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>2</DS>
    +    <NAME>size</NAME>
    +    <UNIT>B</UNIT>
    +    <ACT>263</ACT>
    +    <WARN></WARN>
    +    <CRIT></CRIT>
    +    <MIN>0</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +...
    +</NAGIOS>
    + +

    +PNP hängt .php an und sucht nun nach einem Template mit dem Namen check_http.php in folgender Reihenfolge: + +

    +
      +
    1. templates/check_http.php
      +
    2. +
    3. templates.dist/check_http.php
      +
    4. +
    5. templates/default.php
      +
    6. +
    7. templates.dist/default.php
      +
    8. +
    + +

    + +Das Template default.php nimmt somit eine Sonderstellung ein und wird immer verwendet, wenn vorher kein anderes Template gefunden wird. +

    + +
    + +

    Eigene Templates erstellen

    +
    + +

    + +PNP-Templates sind PHP-Dateien, die zur Laufzeit von PNP über die PHP-Funktion include() eingebunden werden. +Dies bedeutet, dass jeder PHP-Code in Templates interpretiert wird. Daher ist die Manipulation aller Werte über PHP möglich. +

    + +

    +PNP-Templates müssen folgende Eigenschaften besitzen: +

    +
      +
    1. Templates müssen gültigen PHP-Code enthalten.
      +
    2. +
    3. Templates dürfen keine Ausgabe erzeugen.
      +
    4. +
    5. innerhalb der Templates werden die zwei Arrays $opt[] und $def[] gefüllt.
      +
    6. +
    + +

    + +Die beiden PHP-Arrays $opt[] und $def[] zusammen bilden den Aufruf von 'rrdtool graph'. Somit sind alle Optionen möglich, die RRDtool bietet. Die Optionen von RRDtool sind auf der RRDtool Homepage genauestens beschrieben. +

    + +

    +Wenn beide Arrays mehrere Datensätze enthalten, so wird für jeden Datensatz ein Graph erstellt. +

    + +

    +Weiterhin stehen innerhalb der Templates die Daten aus dem zugehörigen XML-File zur Verfügung, die zum Erstellen der Graphen wieder verwendet werden können. +

    + +

    +Am Beispiel des recht einfachen Templates response.php lassen sich die wichtigsten Optionen recht gut beschreiben. +

    +
    <?php
    +#
    +$opt[1] = "--title \"Response Time For $hostname / $servicedesc\" ";
    +#
    +$def[1] =  "DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE " ;
    +$def[1] .= "AREA:var1#00FF00:\"Response Times \" " ;
    +$def[1] .= "LINE1:var1#000000 " ;
    +$def[1] .= "GPRINT:var1:LAST:\"%3.4lg %s$UNIT[1] LAST \" ";
    +$def[1] .= "GPRINT:var1:MAX:\"%3.4lg %s$UNIT[1] MAX \" ";
    +$def[1] .= "GPRINT:var1:AVERAGE:\"%3.4lg %s$UNIT[1] AVERAGE \" ";
    +?>
    + +

    +$opt[1] = ”--title …” setzt RRDtool-Optionen für den ersten Datensatz im Array. Hier ist das der Titel des Graphen. +Wie man sieht, werden eingebettete Anführungszeichen durch einen Backslash (\) maskiert. +Die beiden Variablen $hostname und $servicedesc sind durch den Aufruf von PNP ermittelt worden und stehen nun auch im Template zur Verfügung. +

    + +

    +$def[1] = “DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE ”; definiert, welche Daten aus welchem RRD-File gelesen werden sollen. $RRDFILE[1] enthält den Pfad zur RRD-Datei dieses Services. $DS[1] verweist auf die Datenreihe eins aus der RRD-Datei. +

    + +

    +$def[1] .= “AREA:var1#00FF00:\”Response Times \” ”; durch den Operator ”.=” werden weitere Daten an das Array $def[1] angehängt. Gezeichnet wird eine Fläche (AREA) mit den Daten der Variable var1. Die Farbe wird im HEX-Code #00FF00 definiert. Als Beschriftung wird “Response Times” verwendet. +

    + +

    +$def[1] .= “LINE1:var1#000000 ”; Als Abschluss der eben gezeichneten Fläche wird eine Linie (LINE1) in Schwarz (#000000) gezeichnet. +

    + +

    + +$def[1] .= “GPRINT:var1:LAST:\”%3.4lg %s$UNIT[1] LAST \” ”;
    + +$def[1] .= “GPRINT:var1:MAX:\”%3.4lg %s$UNIT[1] MAX \” ”;
    + +$def[1] .= “GPRINT:var1:AVERAGE:\”%3.4lg %s$UNIT[1] AVERAGE \” ”;
    +

    + +

    +Die drei GPRINT Zeilen bilden die Legende des Graphen. Die aktuellen Werte werden dabei über die printf Syntax formatiert. +

    + +
    + +

    Verfügbare Variablen

    +
    + +

    + +PNP speichert über den Datensammler process_perfdata.pl zur Laufzeit nicht nur Performancedaten, sondern auch weitere von Nagios exportierte Werte. Diese Werte werden in der jeweils für den Service gültigen XML-Datei gespeichert. +

    + +

    +Im ersten Teil der XML-Datei werden die Performancedaten in ihre Einzelteile zerlegt gespeichert. +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +...
    +</NAGIOS>
    + +

    +Das Feld <DS> bezeichnet die DataSource und dient der Identifizierung der Datenreihen innerhalb der RRD-Dateien, ist aber auch der Schlüssel der folgenden Arrays. +

    + +

    +Im Array $UNIT[1] ist somit die Einheit der ersten Datenreihe gespeichert. +

    + +

    +Die XML-Datei enthält jedoch noch weitere Informationen. Wird process_perdata.pl im sync-Mode verwendet, so sind alle verfügbaren Makros mit den aktuellen Werten verfügbar. Der folgende Ausschnitt ist jedoch zu Gunsten der Lesbarkeit gekürzt. +

    +
    <NAGIOS>
    +...
    +  <NAGIOS_SERVICENOTIFICATIONID>8418</NAGIOS_SERVICENOTIFICATIONID>
    +  <NAGIOS_SERVICENOTIFICATIONNUMBER>0</NAGIOS_SERVICENOTIFICATIONNUMBER>
    +  <NAGIOS_SERVICEOUTPUT>HTTP OK HTTP/1.1 200 OK - 10087 bytes in 0.125 seconds</NAGIOS_SERVICEOUTPUT>
    +  <NAGIOS_SERVICEPERCENTCHANGE>0.00</NAGIOS_SERVICEPERCENTCHANGE>
    +  <NAGIOS_SERVICEPERFDATA>time=0.124811s;;;0.000000 size=10087B;;;0</NAGIOS_SERVICEPERFDATA>
    +  <NAGIOS_SERVICEPERFDATAFILE></NAGIOS_SERVICEPERFDATAFILE>
    +  <NAGIOS_SERVICEPROBLEMID>0</NAGIOS_SERVICEPROBLEMID>
    +  <NAGIOS_SERVICESTATE>OK</NAGIOS_SERVICESTATE>
    +  <NAGIOS_SERVICESTATEID>0</NAGIOS_SERVICESTATEID>
    +  <NAGIOS_SERVICESTATETYPE>HARD</NAGIOS_SERVICESTATETYPE>
    +  <NAGIOS_SHORTDATETIME>27-12-2007 13:51:23</NAGIOS_SHORTDATETIME>
    +...
    +</NAGIOS>
    + +

    +Die einzelnen XML-Felder sind als Variablen in den PNP-Templates verwendbar, wobei jedes Feld als Variable gleichen Namens verfügbar ist. +

    + +

    +Aus <NAGIOS_SERVICEOUTPUT> wird die Variable $NAGIOS_SERVICEOUTPUT. +

    + +

    +zurück zur Übersicht | Custom Templates + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/tpl_custom.html b/share/pnp/documents/de_DE/tpl_custom.html new file mode 100644 index 0000000..6be07ef --- /dev/null +++ b/share/pnp/documents/de_DE/tpl_custom.html @@ -0,0 +1,326 @@ + + + +

    Custom Templates

    +
    + +

    + +Wie bereits unter ”Was sind Templates ?” beschrieben, ist die Darstellung der Graphen abhängig vom verwendeten Check-Command. +

    + +

    +Es gibt jedoch Situationen, in denen dieses Verhalten übersteuert werden muss, zum Beispiel dann wenn allgemeingültige Commands definiert wurden. +

    + +

    +PNP, speziell process_perfdata.pl, sucht zur Laufzeit für jedes check_command im Verzeichnis etc/check_commands nach einer Config-Datei (<check_command>.cfg) und liest diese, wenn vorhanden, ein. +Folgende Optionen können darin definiert werden: +

    + +
    + +

    CUSTOM_TEMPLATE

    +
    + +

    +Geht man von folgendem Beispiel einer Nagios command-Definition aus: + +

    +
    +define command {
    +  command_name check_nrpe
    +  command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ -a "$ARG2$"
    +}
    +
    + +

    +Die Folge wäre, dass immer das Template check_nrpe.php verwendet werden würde, auch wenn auf dem zu überwachenden Server via NRPE ein ganz anderes Plugin aufgerufen wurde. +

    + +

    +Da unser Beispiel-Command check_nrpe lautet, wird nach etc/check_commands/check_nrpe.cfg gesucht. +

    + +

    +Eine Beispiel-Config wird bereits während der Installation mit der Dateierweiterung .cfg-sample in etc/check_commands gespeichert. +

    +
    +# check_command check_nrpe!load!-w 4,4,4 -c 5,5,5
    +# ________0__________|       |       |
    +# ________1__________________|       |
    +# ________2__________________________|
    +#
    +CUSTOM_TEMPLATE = 1
    +
    + +

    +CUSTOM_TEMPLATE = 1 sorgt dafür, dass nur der Inhalt von $ARG1$ als Template-Name verwendet wird. Da in diesem Beispiel $ARG1$ mit dem Wert “load” gefüllt ist, ergibt sich als Template-Name “load.php” +

    + +

    +CUSTOM_TEMPLATE = 0,1 ergibt → “check_nrpe_load.php” +

    + +

    +CUSTOM_TEMPLATE = 1,0 ergibt → “load_check_nrpe.php” +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    DATATYPE

    +
    + +

    + +Über die Option “DATATYPE” kann beeinflusst werden, mit welchem Datentyp die RRD-Datenbank angelegt werden soll. +Default ist in diesem Fall “GAUGE”. Für fortlaufende Werte wird aber hier der Datentyp COUNTER benötigt. +Normalerweise sollten Plugin-Entwickler für Daten von Typ Counter die Einheit “c” verwenden. Dies ist jedoch nicht immer der Fall. +

    + +

    +Alle Datenreihen auf Typ COUNTER einstellen. + +

    +
    DATATYPE = COUNTER
    + +

    +Einzelnen Datenreihen spezielle Datentypen zuweisen + +

    +
    DATATYPE = GAUGE,GAUGE,COUNTER,COUNTER
    + +

    +Weitere Datentypen sind in der RRDTool-Dokumentation unter rrdcreate erklärt. +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    USE_MIN_ON_CREATE und USE_MAX_ON_CREATE

    +
    + +

    + +In einigen wenigen Situationen ist es notwendig, die für RRDTool gültigen Daten zu begrenzen. +

    + +

    +RRD-Datenbanken lassen sich mit definierten Minimum- und Maximum-Werten anlegen. +Weitere Infos unter http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +

    + +

    +Berücksichtigen des Maximum-Wertes aus den Performance-Daten + +

    +
    USE_MAX_ON_CREATE = 1
    + +

    +Berücksichtigen des Minimum-Wertes aus den Performance-Daten + +

    +
    USE_MIN_ON_CREATE = 1
    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    RRD_STORAGE_TYPE

    +
    +
    RRD_STORAGE_TYPE = SINGLE
    + +

    + +Die Option RRD_STORAGE_TYPE definiert die Art der Datenhaltung. +

    + +

    +Mögliche Werte sind MULTIPLE und SINGLE +

    + +

    +SINGLE: Eine RRD-Datenbank pro Service +

    + +

    +MULTIPLE: Ein oder mehrere RRD-Datenbanken pro Service. Für jede Datenreihe wird eine eigene RRD-Datenbank erstellt. +

    + +

    +ACHTUNG: Daten werden nicht automatisch migriert!
    + +Ein Konvertierungs-Script finden Sie hier. +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    RRD_HEARTBEAT

    +
    + +

    + +Gültig ab PNP 0.6.1 +

    +
    RRD_HEARTBEAT = 305
    + +

    +Nach <RRD_HEARTBEAT> Sekunden erwartet RRDtool neue Daten. +

    + +

    +Mehr dazu unter http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +

    + +

    +Diese Option hat nur Einfluss, wenn die RRD Datenbank neu erstellt wird. +

    + +
    + +

    Hints on Template Names

    +
    + +

    + +In den meisten Situationen, kann man erwünsche Template Namen relativ einfach, durch die Verwendung geeignter command Objekt Definitionen, erhalten. +

    + +

    +Man betrachte folgendes Beispiel: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$
    +}
    +
    + +

    + +mit commands wie diesem: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load -w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    +Selbst wenn man “CUSTOM_TEMPLATE = 1” benutz, würde man template Namen wie diesen “_usr_lib_nagios_plugins_check_load_-w_4,4,4_-c_5,5,5” erhalten, was höchst unerwünscht ist, insbesondere wegen den darin enthaltenen Parametern. +

    + +

    +Lösung 1: Die Parameter in eigenständige $ARGn$ auslagern +

    + +

    +Eine einfache Lösung ist die Verwendung der folgenden command Objekt Definition: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +mit commands wie diesem: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +(man beachte das hinzugekommene “!”) +

    + +

    +Dies funktioniert selbst dann, wann $ARG2$ leer bleibt. +

    + +

    +Selbstverständlich müsste man immer noch “CUSTOM_TEMPLATE = 1” setzen. +

    + +

    + +Lösung 2: Den remote executor in der command Objekt Definition verstecken +

    + +

    +Eine andere Lösung ist es, den remote excutor in den jeweiligen command Objekt Definitionen zu verstekcne. +

    + +

    +Anstatt folgender Definition: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +würde man dies für jeden fern auszuführenden command definieren: + +

    +
    +define command {
    +  command_name check_load_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ /usr/lib/nagios/plugins/check_load $ARG1$
    +}
    +
    + +

    + +mit commands wie diesem: + +

    +
    +  …
    +  check_load_by_ssh!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +Natürlich darf “CUSTOM_TEMPLATE = 1” bei dieser Lösung nicht mehr gesetzt werden. +

    + +

    + +Welche der obigen Lösungen verwendet wird, ist weitgehend Geschmacksache. +

    + +

    +zurück zur Übersicht | PNP in verteilten Umgebungen + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/tpl_helper.html b/share/pnp/documents/de_DE/tpl_helper.html new file mode 100644 index 0000000..a6dfe81 --- /dev/null +++ b/share/pnp/documents/de_DE/tpl_helper.html @@ -0,0 +1,246 @@ + + + +

    Template Helper Functions

    +
    + +

    + +Helper-Funktionen sind dazu gedacht, die Templates zu vereinfachen und Fehler abzufangen. +

    + +
    + +

    rrd::def

    +
    + +

    + +string rrd::def ( $vname, $rrdfile, $ds, [ $cf='AVERAGE' ] ) +

    +
    $def = rrd::def('var1', $RRDFILE[0], $DS[0], 'MAX');
    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html +

    + +
    + +

    rrd::cdef

    +
    + +

    + +string rrd::cdef ( $vname, $rpn, ) +

    +
    $def = rrd::cdef('var1_bits', 'var1,8,*' );
    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html +

    + +
    + +

    rrd::vdef

    +
    + +

    + +string rrd::vdef ( $vname, $rpn, ) +

    +
    $def = rrd::vdef('var1_avg', 'var1,AVERAGE' );
    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html +

    + +
    + +

    rrd::line[1-3]

    +
    + +

    + +string rrd::line[1-3] ( $vname, $color, [ $text ], [ $stack ] ) +

    +
    $def .= rrd::line1('var1', #ff00ff );
    + +

    +Eine einfache Linie, ein Pixel breit, ohne Label-Text +

    +
    $def .= rrd::line3('var1', '#ff00ff', 'Load' );
    + +

    +Eine Linie, drei Pixel breit, und dem Label “Load” +

    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html +

    + +
    + +

    rrd::area

    +
    + +

    + +string rrd::area ( $vname, $color, [ $text ], [ $stack ] ) +

    +
    $def .= rrd::area('var1', '#ff00ff', 'Load' );
    + +

    +Eine Fläche mit dem Label “Load” +

    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html +

    + +
    + +

    rrd::gprint

    +
    + +

    + +string rrd::gprint ( $vname, $cf, [ $text ] ) +

    +
    $def .= rrd::gprint('var1', 'MAX', '%4.2lf %s Max' );
    +
    $def .= rrd::gprint('var1', array('MIN', 'MAX', 'AVERAGE'), '%4.2lf %s' );
    + +

    +Ist $cf ein Array, so wird automatisch eine Legende formatiert ausgegeben. +

    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html +

    + +
    + +

    rrd::color

    +
    + +

    + +string rrd::color ( $num [, $num ]) +

    + +

    +Liefert eine Farbe aus der HTML-Farbtabelle. Als zweites (optionales) Argument kann man einen Alpha-Wert angeben, der die Transparenz der Farbe festlegt. +

    + +

    +Beginnend mit PNP 0.6.18 akzeptiert die Funktion ein drittes Argument, das auf Farbschemadefinitionen in config.php verweist (oder in config_local.php, die bei Updates nicht überschrieben wird). Dort finden Sie das Array $scheme[], z.B. +

    +
    $scheme['Reds'] = array (...)
    + +

    +Im Template definieren Sie +

    +
    $schema = $this->config->scheme['Reds']
    +...
    +rrd:color ($key, '', $schema);
    + +

    +Aus diese Weise wählen Sie den Wert von $scheme['Reds'][$key]. Falls $key nicht innerhalb des Arrays liegt oder der Name nicht korrekt ist (case-sensitiv), dann wird die Standardpalette verwendet. +

    + +
    + +

    rrd::gradient

    +
    + +

    + +string rrd::gradient ( $vname, [$start_color], [$end_color], [$label], [$steps], [$lower] ) +

    + +

    +Erzeugt einen Farbverlauf von $start_color nach $end_color +

    +
    $def .= rrd::gradient('var1', '#ff0000', '#ffff00' );
    + +

    + +Beispiel +

    + +
    + +

    rrd::cut

    +
    + +

    + +string rrd::cut ( $text, $length ) +

    +
    $label = rrd::cut($LABEL[0], 18);
    + +

    +Schneidet einen Text auf eine gegebene Länge $length ab oder füllt wenn nötig auf $length auf. +Diese Funktion ist hilfreich, wenn die Legende ausgerichtet werden soll, aber die Länge des Labels nicht bekannt ist. +

    + +
    + +

    rrd::ticker

    +
    + +

    + +string rrd::ticker ( $vname, $warning, $critical, [$fraction], [$opacity], [$color_OK], [$color_WARN], [$color_CRIT] ) +

    + +

    +Erzeugt einen farbigen Balken am oberen Rand des Graphen, der je nach OK, WARNING & CRITICAL unterschiedliche Farben annimmt +

    +
    $def .= rrd::ticker( "var1", $WARN[0], $CRIT[0] );
    + +

    + +Beispiel +

    + +
    + +

    rrd::alerter

    +
    + +

    + +string rrd::alerter ( $vname, $label, $warning, $critical, [$opacity], [$unit], [$color_OK], [$color_WARN], [$color_CRIT], [$line_col] ) +

    + +

    +Erzeugt Areas, die entsprechend der Werte OK, WARNING & CRITICAL unterschiedliche Farben annehmen +

    +
    $def .= rrd::alerter( "var1", $LABEL[0], $WARN[0], $CRIT[0], "FF", $UNIT[0] );
    + +

    +Beispiel +

    + +
    + +

    rrd::alerter_gr

    +
    + +

    + +string rrd::alerter_gr ( $vname, $label, $warning, $critical, [$opacity], [$unit], [$color_OK], [$color_WARN], [$color_CRIT], [$line_col], [$start_color] ) +

    + +

    +Erzeugt Gradienten, die entsprechend der Werte OK, WARNING & CRITICAL unterschiedliche Farben annehmen +

    +
    $def .= rrd::alerter_gr( "var1", $LABEL[0], $WARN[0], $CRIT[0], "FF", $UNIT[0] );
    + +

    +Beispiel + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/tpl_helper_pnp.html b/share/pnp/documents/de_DE/tpl_helper_pnp.html new file mode 100644 index 0000000..52b2ef5 --- /dev/null +++ b/share/pnp/documents/de_DE/tpl_helper_pnp.html @@ -0,0 +1,91 @@ + + + +

    PNP Helper Functions

    +
    + +

    + +PNP-Helper-Funktionen sind dazu gedacht, die Erstellung von Templates zu vereinfachen. Im Gegensatz zu den rrd-Helper-Funktionen rufen sie keine existierenden RRDtool-Funktionen auf. +

    + +
    + +

    pnp::adjust_unit

    +
    + +

    + +(string,number,string,number) pnp::adjust_unit ( $value, $base=1000, $format='%.3lf' ) +

    + +

    +Der Zweck dieser Funktion ist die “Normalisierung” von großen Zahlen. Moderne Festplatten haben Größen von mehreren GB oder TB erreicht und wenn Sie auf Zahlen wie 1521073648234 schauen, dann fangen Sie an, die Ziffern zu zählen, also wäre es schön, diese Zahlen in ein “handliches” Format zu verwandeln. Das Gleiche gilt für Netzwerkverkehr. +

    + +

    +An die Funktion werden bis zu drei Parameter übergeben und in jedem Fall ein Array mit vier Elementen zurückgeliefert. + +

    +
      +
    • Der erste übergebene Parameter ist der Wert (ggf. inklusive die “UOM”)
      +
    • +
    • Der zweite Parameter ist optional (Default “1000”, z.B. für “Traffic”), bzw. “1024” (z.B. Festplattengrößen)
      +
    • +
    • Der dritte Parameter ist optional (Default '%.3lf') und gibt das Format des zurückzugebenden Wertes an
      +
    • +
    +
    $size = pnp::adjust_unit(1521073648234,1024,'%7.3lf');
    + +

    +Bitte beachten Sie, dass “$size” ein Array ist, das aus vier Feldern besteht: +

    +
     $size[0] := "  1.383 T"
    + +

    +enthält den formatierten Wert inkl. der Einheit +

    +
     $size[1] := "1.383"
    + +

    +enthält den formatierten Wert (ohne führende Leerzeichen) +

    +
     $size[2] := "T"
    + +

    +enthält die Einheit +

    +
     $size[3] := "1099511627776"
    + +

    +enthält den Divisor +

    + +

    +Angenommen das Plugin “check_disk” liefert “MB” als UOM, dann können Sie diese Einheit ebenfalls übergeben + +

    +
    $disk = pnp::adjust_unit("1524MB",1024,'%7.3lf');
    + +

    + +liefert als Ergebnis u.a. +$disk[0] := “1.448 GB” +

    + +

    +
    + +“altes” check_disk-Template mit der %s Direktive
    + +

    + +

    +
    + +“neues” check_disk-Template mit pnp::adjust_unit + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/tpl_special.html b/share/pnp/documents/de_DE/tpl_special.html new file mode 100644 index 0000000..7ce7ee9 --- /dev/null +++ b/share/pnp/documents/de_DE/tpl_special.html @@ -0,0 +1,188 @@ + + + +

    Special Templates

    +
    + +

    + +“Special Templates” dienen zum Zusammenfassen von Daten beliebiger Hosts und Services und sind somit nicht direkt mit einem Host oder Service verknüpft. +

    + +

    +Oftmals ist es gewünscht Daten verschiedener Services in einem Graphen darzustellen. Immer wenn die "Pages" nicht genügen, können die Special Templates ins Spiel kommen. +

    + +
    + +

    Grundlagen

    +
    + +

    + +“Special Templates” werden in pnp4nagios/share/templates.special gesucht und müssen die Dateiendung .php besitzen. +

    + +

    +Aufgerufen werden “Special Templates” über den Controller “special” unter + +

    +
    http://<your-nagios-server>/pnp4nagios/special?tpl=<template>
    + +

    + +<template> ist entsprechend durch das jeweilige Template ohne die Dateiendung .php zu ersetzen. +

    + +

    +Ein entsprechender Link erscheint im PNP-Interface, wenn mindestens ein “Special Template” gefunden wurde. +

    + +
    + +

    Beispiel

    +
    + +

    + +Aufgabe ist die Antwortzeiten aller Webserver mit dem Hostnamen websrv01, websrv02 und websrv03 in einem Graphen anzuzeigen. Die Daten sollen aus dem Service “HTTP” stammen. +

    + +

    +Step 1: Anlegen eines Templates “websrv_response_times.php” unter pnp4nagios/share/templates.special +

    + +

    +“Special Templates” beginnen immer mit der Definition des Titels und eines Kommentars. +

    +
    $this->MACRO['TITLE']   = "HTTP Response Times";
    +$this->MACRO['COMMENT'] = "HTTP Response Times for all Cluster Nodes";
    + +

    +Step 2: Eine Liste aller in Frage kommenden Hosts/Services erstellen. PNP stellt hierfür die Funktion tplGetServices() bereit. +

    + +

    +tplGetServices() erwartet zwei Parameter. +

    + +

    +Parameter 1 ist ein regulärer Ausdruck auf den zu suchenden Host, Parameter 2 ist entsprechend ein regulärer Ausdruck für den Service. +

    +
    $services = $this->tplGetServices("websrv","HTTP");
    + +

    +$services enthält nun ein Array aller gefundenen Services. +

    + +

    +Um die Entwicklung der Templates zu erleichtern und Einblick in die Datenstrukturen zu erhalten, kann man Kohana durch Auslösen einer Exception zum Abbrechen der Verarbeitung zwingen. +

    + +

    +Um Einblick in die Daten von $services zu erhalten, genügt die folgende Zeile. +

    +
    throw new Kohana_exception(print_r($services,TRUE));
    + +

    +Ausgabe bei Aufruf von pnp4nagios/special?tpl=websrv_response_times +

    +
    +Array ( 
    +  [0] => Array ( 
    +     [host] => websrv01 
    +     [service] => HTTP 
    +  ) 
    +  [1] => Array ( 
    +     [host] => websrv02
    +     [service] => HTTP 
    +  ) 
    +  [2] => Array ( 
    +     [host] => websrv03
    +     [service] => HTTP 
    +  ) 
    +)
    +
    + +

    +Die Variable $services enthält somit ein Array aller gefundenen Services, in diesem Fall also drei Hosts mit dem Service “HTTP” +

    + +

    +Step 3: Durchlaufen des Array $services und erstellen der Graph-Definitionen. +

    +
    foreach($services as $key=>$val){
    +    $data      = $this->tplGetData($val['host'],$val['service']);
    +    $hostname  = rrd::cut($data['MACRO']['HOSTNAME'], 15);
    +    $def[0]   .= rrd::def("var$key" , $data['DS'][0]['RRDFILE'], $data['DS'][0]['DS'] );
    +    $def[0]   .= rrd::line1("var$key", rrd::color($key), $hostname);
    +    $def[0]   .= rrd::gprint("var$key", array("MAX", "AVERAGE"));
    +}
    + +

    +Die Funktion tplGetData() wird innerhalb der Schleife verwendet, um das jeweilige XML-File einzulesen. Die Daten werden als Array zurückgeliefert und stehen nun in $data zur Verfügung. +

    + +

    +In diesem Beispiel kommen weitere kleine PNP-Helfer zum Einsatz, zu erkennen am Präfix rrd::. +

    + +

    +Die Funktion rrd::cut() schneidet einen String auf eine bestimmte Länge oder füllt auf diese Länge auf. Dies ist hilfreich, um die Legende auszurichten. +

    + +

    +Die Funktion rrd::gprint() erzeugt die Legende unter dem Graphen. +

    + +

    +Die Funktion rrd::color() liefert eine Farbe aus einer fest definierten Farbliste zurück. +

    + +

    +Mehr Informationen zu den PNP-Helper-Funktionen finden Sie hier. + +

    +
    <?php
    +#
    +# Special Template websrv_response_times.php
    +#
    +$this->MACRO['TITLE']   = "HTTP Response Times";
    +$this->MACRO['COMMENT'] = "HTTP Response Times for all Cluster Nodes";
    +#
    +# Get a List of Services by regex 
    +# Option 1 = 'Host Regex'
    +# Option 2 = 'Service Regex'
    +#
    +$services = $this->tplGetServices("websrv","HTTP");
    +#throw new Kohana_exception(print_r($services,TRUE));
    +#
    +# The Datasource Name for Graph 0
    +$ds_name[0] = "Response Times";
    +$opt[0]     = "--title \"Response Times\"";
    +$def[0]     = "";
    +#
    +# Iterate through the list of hosts
    +foreach($services as $key=>$val){
    +    #
    +    # get the data for a given Host/Service
    +    $data = $this->tplGetData($val['host'],$val['service']);
    +    #
    +    # Throw an exception to debug the content of $a
    +    # Just to get Infos about the Array Structure
    +    #
    +    #throw new Kohana_exception(print_r($a,TRUE));
    +    $hostname   = rrd::cut($data['MACRO']['HOSTNAME']);
    +    $def[0]    .= rrd::def("var$key" , $data['DS'][0]['RRDFILE'], $data['DS'][0]['DS'] );
    +    $def[0]    .= rrd::line1("var$key", rrd::color($key), $hostname);
    +    $def[0]    .= rrd::gprint("var$key", array("MAX", "AVERAGE"));
    +}
    +?>
    + +

    +Zurück zur Übersicht + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/upgrade.html b/share/pnp/documents/de_DE/upgrade.html new file mode 100644 index 0000000..37d32b6 --- /dev/null +++ b/share/pnp/documents/de_DE/upgrade.html @@ -0,0 +1,218 @@ + + + +

    Upgrade auf Version 0.6.x

    +
    + +

    + +Das Web-Frontend ist komplett neu geschrieben worden und basiert nun auf dem PHP MVC Framework Kohana. Somit ergeben sich grundlegend andere Abhängigkeiten, die dringend vor der Installation geprüft werden müssen. +

    + +

    +Anmerkung: Ein Upgrade läuft zuerst wie eine Neuinstallation. Anschließend sind einige Anpassungen durchzuführen, die weiter unten beschrieben sind. +

    + +

    +PNP 0.4.x wurde ohne weitere Angabe von Optionen beim Aufruf von ./configure unterhalb einer Nagios-Installation unter /usr/local/nagios installiert. +

    + +

    +PNP 0.6.x wird bei Angabe keiner weiteren Optionen unter /usr/local/pnp4nagios installiert, ist also wie Nagios als eigenständige Applikation zu sehen. +

    + +

    +Anmerkung: Es reicht aus, die *.rrd-Dateien vom alten ins neue Verzeichnis zu kopieren. Sie enthalten die eigentlichen Daten. Die *.xml-Dateien werden jedes Mal neu angelegt, wenn Performance-Daten verarbeitet werden, denn sie enthalten lediglich Meta-Informationen. Außerdem hat sich die interne Struktur geändert, so dass sie sowieso nicht nutzbar sind. +

    + +
    + +

    Vergleich der Struktur

    +
    + +

    + +Summary einer Installation von PNP 0.4.14 +

    +
    +./configure
    +...
    +*** Configuration summary for pnp 0.4.14 05-02-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/nagios
    +  HTML Dir:                         /usr/local/nagios/share/pnp
    +  Config Dir:                       /usr/local/nagios/etc/pnp
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/nagios/share/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/nagios/var/spool/perfdata/
    +
    + +

    +Summary einer Installation von 0.6.0 +

    +
    +./configure
    +...
    +*** Configuration summary for pnp4nagios-0.6.0 07-30-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    + +

    +Aus diesen Infos ergeben sich die zu ändernden Parameter und somit die Upgrade-Strategie. +

    + +
    + +

    Anpassungen

    +
    + +

    + +Die Vorlagen der action_url-Definitionen haben sich verändert. Statt ”/nagios/pnp” ist ”/pnp4nagios” einzutragen und statt “index.php” wird nun “graph” benutzt +

    +
    define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    + +

    +Ähnliches gilt für die Preview-Popup-Funktion +

    +
    define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    + +

    + +Achtung: Es ist kein Fehler, dass die Zeichenketten vor und nach “class” jeweils nur ein Apostroph enthalten. +

    + +

    +Anders als in der 0.4.x Dokumentation vermerkt gelten die Templates für Nagios 2.x und 3.x. Der einzige Unterschied besteht darin, dass die action_url-Direktive in Nagios 2.x nicht in der Service-Definition, sondern in eigenen serviceextinfo-Definitionen verfügbar ist. +

    + +

    +Innerhalb der PHP-Dateien im templates-Verzeichnis müssen alle Variablen vor der ersten Benutzung initialisiert werden, z.B. +

    +
    $lower = ""
    + +

    + +Das gilt auch für Variablen, an die früher “angehängt” werden konnte, ohne sie vorher zu initialisieren. Daher wird aus + +

    +
    foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    + +nun + +

    +
    +$def[1] = "";
    +foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    +
    + +Konstanten in Template-Dateien funktionieren nicht mehr, so dass diese in Variablen umzuwandeln sind. Aus +

    +
    define("_WARNRULE", '#FFFF00');
    + +

    +wird dann z.B. +

    +
     $WARNRULE = '#FFFF00';
    + +

    +Man sollte daran denken, alle Vorkommen in der Datei zu ändern ;-). +

    + +
    + +

    Upgrade Szenario mit NPCD

    +
    +
      +
    1. Planen des neuen Aufbaus.
      +
    2. +
    3. Testinstallation durchführen und sich mit dem neuen System vertraut machen.
      +
    4. +
    5. Backup erstellen.
      +
    6. +
    7. PNP 0.6.x nach /usr/local/pnp4nagios installieren.
      +
    8. +
    9. make install-config
      +
    10. +
    11. make install-webconf
      +
    12. +
    13. Apache reload.
      +
    14. +
    15. Apache-Config testen.
      +
        +
      1. Aufruf /pnp4nagios muss ein leeres Perfdata-Verzeichnis melden.
        +
      2. +
      +
    16. +
    17. /usr/local/pnp4nagios/etc/npcd.cfg aus der npcd.cfg-sample erstellen.
      +
        +
      1. Pfade überprüfen und ggf. Änderungen der 0.4.x nachziehen.
        +
      2. +
      +
    18. +
    19. Alle Pfade zur neuen Installation in der nagios.cfg anpassen.
      +
    20. +
    21. Alle Pfade in den Command-Definitionen anpassen.
      +
    22. +
    23. npcd über /etc/init.d/npcd stop anhalten.
      +
    24. +
    25. make install-init installiert das neue Init Script für den npcd.
      +
    26. +
    27. Nagios anhalten.
      +
    28. +
    29. /usr/local/nagios/share/perfdata nach /usr/local/pnp4nagios/var/perfdata kopieren. Achtung: Auf Permissions achten.
      +
    30. +
    31. /etc/init.d/npcd start
      +
    32. +
    33. /etc/init.d/nagios start
      +
    34. +
    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/verify.html b/share/pnp/documents/de_DE/verify.html new file mode 100644 index 0000000..6b8946e --- /dev/null +++ b/share/pnp/documents/de_DE/verify.html @@ -0,0 +1,133 @@ + + + +

    Prüfen der Installation

    +
    + +

    + +Wenn bis jetzt alles sauber funktioniert hat, kann PNP zum ersten Mal im Browser aufgerufen werden. +Bei der Installation mit den Standardeinstellungen erfolgt der Aufruf über http://<Servername>/pnp4nagios/. +

    + +

    +Beim ersten Aufruf sieht man die Seite “PNP4Nagios Environment Tests”, die verschiedene Tests von notwendigen Komponenten enthält. Offenkundig sollten alle Tests erfolgreich verlaufen, bevor es weitergehen kann. Bitte beachten Sie die Hinweise auf der Seite.
    + +

    + +

    +Sind alle Tests erfolgreich verlaufen, so kann die Datei pnp4nagios/share/install.php gelöscht oder umbenannt werden. Erst dann ist das Webinterface erreichbar. +

    + +

    +Alternativ kann eine Datei pnp4nagios/share/install.ignore angelegt werden, um den Aufruf des Installers nach weiteren Updates zu ignorieren. +

    + +

    +Ohne weitere Optionen sucht PNP nach RRD- und XML-Dateien in pnp4nagios/var/perfdata/ und zeigt alle Graphen des ersten Hosts in der Übersicht an. +

    + +

    +ACHTUNG: Direkt nach dem (Neu-)Start von Nagios nach dem Aktivieren der Verarbeitung von Performance-Daten wird der Aufruf im Browser zu Fehlermeldungen führen, weil zunächst Performance-Daten gesammelt und in den RRD-Dateien abgelegt werden müssen. Abhängig vom Check-Intervall kann es einige Zeit dauern, bis die ersten Graphen angezeigt werden können. +

    + +
    + +

    Logfile

    +
    + +

    + +Während der Installation wurde durch den Aufruf von make install-config ein Beispiel-Config-File etc/process_perfdata.cfg-sample erzeugt. Die Werte in der sample-Datei entsprechen den Default-Werten, die auch in process_perfdata.pl fest hinterlegt sind, daher ist die process_perfdata.cfg für den Betrieb nicht zwingend notwendig. +

    + +

    +Die Datei process_perfdata.cfg-sample kann somit als Vorlage für die process_perfdata.cfg dienen, die immer dann notwendig ist, wenn vom Standard abweichende Werte eingestellt werden sollen. +

    + +

    +In der process_perfdata.cfg lässt sich das Verhalten von process_perfdata.pl vielfach beeinflussen. +

    + +

    +Die wichtigsten Optionen für die Inbetriebnahme sind LOG_LEVEL und LOG_FILE. Im laufenden Betrieb sollte der Log-Level immer auf 0 gesetzt sein, um die Performance von process_perfdata.pl nicht durch unnötiges Schreiben von Logfiles zu beeinträchtigen. +

    + +

    +Während der Inbetriebnahme sollte man jedoch den LOG_LEVEL auf “2” setzen, um zu sehen, was process_perfdata.pl bei der Verarbeitung der Performance-Daten so alles anstellt. +

    + +

    +Spätestens bei Support Anfragen im Forum oder auf den Mailinglisten werden wir sowohl nach Auszügen aus dem perfdata.log als auch nach der Ausgabe des verify_pnp_config-Scripts fragen. Es empfiehlt sich also, diese Angaben gleich mitzuliefern ;-). +

    + +
    + +

    Was aber wenn nicht ?

    +
    + +

    + +Einige grundlegende Einstellungen sind zu prüfen. +

    + +

    +1. Sind RRD- und XML-Files erzeugt worden ? +

    + +

    +process_perfdata.pl legt für jeden Host unter var/perfdata ein neues Verzeichnis an. In diesem Verzeichnis wird wiederum für jeden Service eine RRD-Datenbank und ein XML-File erstellt. Für den Host-Check lautet der Dateinamen _HOST_.xml bzw. _HOST_.rrd.
    + +Falls Graphen urplötzlich nicht mehr weitergeführt werden, dann hilft vielleicht ein Blick in die betroffene XML-Datei. Dort gibt es u.a. die Tags <RC> und <TXT>. <RC> zeigt den Return-Code des RRDtool-Updates der RRD-Datei, <TXT> eine textuelle Beschreibung.
    + +Allerdings liefern nicht alle Checks Performance-Daten, das gilt u.a. für “check_ping”, die Alternative “check_icmp” dagegen erzeugt Daten (ab Nagios-Plugin-Version 1.4.12 liefert auch check_ping Performance-Daten).
    + +Teilweise muss man zusätzliche Optionen aktivieren, damit Performance-Daten ausgegeben werden. Evtl. kann das auch durch ein Wrapper-Script geändert werden.
    + +In den Detailinformationen zu jedem Host/Service gibt es das Feld “Performance-Data”. Wenn dort keine Daten stehen, dann werden im jeweiligen Verzeichnis keine Dateien erzeugt und PNP kann deshalb auch keine grafischen Auswertungen liefern!
    + +Das folgende Bild zeigt die Informationen zu einem “PING”-Service. Das blaue Feld enthält den vom Plugin gelieferten Text, das rote die Performance-Daten, die Nagios erkannt hat.
    + +Informationen zu "PING" +

    + +

    +2. Hat Nagios process_perfdata.pl aufgerufen ? +

    + +

    +In der Config-Datei für process_perfdata.pl, der etc/process_perfdata.cfg lässt sich der Debug-Level erhöhen. Die Verarbeitung der Daten wird nun in var/perfdata.log bzw. im Syslog protokolliert. +

    + +

    +3. Grafiken werden ohne Text angezeigt ? +

    + +

    +siehe Anforderungen +

    + +

    +4. Einige Graphen werden angezeigt, andere melden den Fehler “parser error: Input is not proper UTF-8” oder etwas ähnliches. Bitte prüfen Sie, ob die Daten “spezielle” Zeichen enthalten, die nicht im ASCII-Zeichensatz vorhanden sind (Umlaute, etc). Versuchen Sie, in process_perfdata.cfg den Wert von XML_ENC auf ISO-8859-1 oder einen anderen passenden Wert zu setzen. Warten Sie, bis die xml-Datei neu erzeugt wurde und probieren Sie es nochmal. +

    + +

    +5. Bei aktiviertem npcdmod-Modul muss der Wert von event_broker_options in der nagios.cfg ggf. angepasst werden. Hinweise gibt es hier. +

    + +

    +6. verify_pnp_config +Das Perl-Script verify_pnp_config.pl ermöglicht die Prüfung von Konfigurationseinstellungen und zeigt, ob Performance-Daten vorhanden sind. +

    + +

    +7. Es scheint zu funktionieren, aber es bleiben einige Dateien Spool-Verzeichnis stehen (/usr/local/pnp4nagios/var/spool/<perfdata_filename>-PID-<process_perfdata_pid>). Wenn process_perdata.pl nicht in das Zielverzeichnis (/usr/local/pnp4nagios/share/perfdata/<host>) schreiben kann, wird es anhalten und die Quelldatei nicht löschen. Das erhöht die Größe des Spool-Verzeichnisses und die Verarbeitung der Performance-Daten verlangsamen. Dieses Problem kann auftreten, wenn Sie Verzeichnisse aus einer vorherigen Installation kopiert und/oder manuell Verzeichnisse angelegt haben und dabei die falschen Benutzer/Berechtigungen verwendet haben. +

    + +

    +zurück zur Übersicht | verify_pnp_config.pl + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/verify_pnp_config.html b/share/pnp/documents/de_DE/verify_pnp_config.html new file mode 100644 index 0000000..f59d6cd --- /dev/null +++ b/share/pnp/documents/de_DE/verify_pnp_config.html @@ -0,0 +1,153 @@ + + + +

    verify_pnp_config

    +
    + +

    + +Bei Problemen kann das Perl-Script verify_pnp_config von http://verify.pnp4nagios.org helfen die aktuelle Nagios/Icinga Konfiguration zu prüfen und entsprechend Hinweise zur Lösung liefern. +

    + +

    +Bei Support Anfragen sollte immer die Ausgabe dieses Scripts mit angegeben werden, da die Entwickler sich so einen besseren Überblick über das verwendete System machen können. +

    + +

    +Feedback, Verbesserungsvorschläge oder Patches bitte per Mail an support@pnp4nagios.org +

    + +
    + +

    Download

    +
    + +

    + +Das Verify Script ist unter http://verify.pnp4nagios.org verfügbar. +

    +
    +wget http://verify.pnp4nagios.org/verify_pnp_config
    +
    + +
    + +

    Test

    +
    + +

    + +Das Verify Script benötigt drei Optionen um die Funktion von PNP4Nagios zu prüfen +

    +
    +lenny:~# perl verify_pnp_config
    +
    +verify_pnp_config -m|--mode=[sync|bulk|bulk+npcd|npcdmod]
    +                 -c|--config=[path to nagios.cfg]
    +                 -p|--pnpcfg=[path to PNP config dir]
    +
    + +

    +Die wichtigste Infos ist der zu prüfende Modus, welcher mit der Option --mode angegeben wird.
    + +Weitere Infos über die einzelnen Modi und deren Konfiguration unter "Welcher Modus ist für mich richtig ?" und "Konfiguration" +

    + +

    +Weiterhin ist der Pfad zur Nagios Config Datei (nagios.cfg) über die Option --config zu übergeben. Auf einem Icinga System ist es entsprechend der Pfad zur icinga.cfg. +

    + +

    +Über --pnpcfg wird der Pfad zum etc Verzeichnis der PNP4Nagios Installation übergeben.
    + +

    + +

    +Beim Aufruf von perl verify_pnp_config werden die verfügbaren Optionen ausgegeben. +

    +
    +lenny:~# perl verify_pnp_config --mode npcdmod --config=/usr/local/nagios/etc/nagios.cfg --pnpcfg=/usr/local/pnp4nagios/etc
    +[INFO]  ========== Starting Environment Checks ============
    +[INFO]  My version is: verify_pnp_config-0.6.14-R.31
    +[INFO]  Reading /usr/local/nagios/etc/nagios.cfg
    +[OK  ]  Running product is 'nagios'
    +[OK  ]  object_cache_file is defined
    +[OK  ]  object_cache_file=/usr/local/nagios/var/objects.cache
    +[INFO]  Reading /usr/local/nagios/var/objects.cache
    +[OK  ]  resource_file is defined
    +[OK  ]  resource_file=/usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/process_perfdata.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/pnp4nagios_release
    +[OK  ]  Found PNP4Nagios version "0.6.14"
    +[OK  ]  Effective User is 'nagios'
    +[OK  ]  User nagios exists with ID '1000'
    +[OK  ]  Effective group is 'nagios'
    +[OK  ]  Group nagios exists with ID '1000'
    +[INFO]  ========== Checking npcdmod Mode Config  ============
    +[OK  ]  process_performance_data is 1 compared with '/1/'
    +[OK  ]  event_broker_options is defined
    +[OK  ]  event_broker_options=-1
    +[OK  ]  event_broker_option bits 2 and 3 enabled (12)
    +[OK  ]  broker_module is defined
    +[OK  ]  broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  npcdmod.o config file is /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg used by npcdmod.o is readable
    +[OK  ]  npcd daemon is running
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg is used by npcd and readable
    +[OK  ]  npcd and npcdmod.o are using the same config file (/usr/local/pnp4nagios/etc/npcd.cfg)
    +[INFO]  Nagios config looks good so far
    +[INFO]  ========== Checking config values ============
    +[INFO]  Reading /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  Script /usr/local/pnp4nagios/libexec/process_perfdata.pl is executable
    +[INFO]  ========== Starting global checks ============
    +[OK  ]  status_file is defined
    +[OK  ]  status_file=/dev/shm/status.dat
    +[INFO]  Reading /dev/shm/status.dat
    +[INFO]  ==== Starting rrdtool checks ====
    +[OK  ]  RRDTOOL is defined
    +[OK  ]  RRDTOOL=/usr/bin/rrdtool
    +[OK  ]  /usr/bin/rrdtool is executable
    +[OK  ]  RRDtool 1.3.1  Copyright 1997-2008 by Tobias Oetiker <tobi@oetiker.ch>
    +[OK  ]  USE_RRDs is defined
    +[OK  ]  USE_RRDs=1
    +[OK  ]  Perl RRDs modules are loadable
    +[INFO]  ==== Starting directory checks ====
    +[OK  ]  RRDPATH is defined
    +[OK  ]  RRDPATH=/usr/local/pnp4nagios/var/perfdata
    +[OK  ]  Perfdata directory '/usr/local/pnp4nagios/var/perfdata' exists
    +[WARN]  62 hosts/services are not providing performance data
    +[WARN]  'process_perf_data 1' is set for 43 hosts/services which are not providing performance data!
    +[WARN]  'process_perf_data 0' is set for 27 of your hosts/services
    +[OK  ]  'process_perf_data 1' is set for 243 of your hosts/services
    +[INFO]  ==== System sizing ====
    +[OK  ]  269 hosts/service objects defined
    +[INFO]  ==== Check statistics ====
    +[WARN]  Warning: 3, Critical: 0
    +[WARN]  Checks finished...
    +
    + +
    + +

    Performance data

    +
    + +

    +Beginnend mit 0.6.19-R.37 (2013-02-17) akzeptiert das Skript die Option--object (oder -o) gefolgt von einer Zeichenkette, die einen Host und/oder einen Service angibt. Für diese/s Objekt(e) werden die Performance-Daten angegeben (falls vorhanden). Die Daten werden von eckigen Klammern begrenzt, gefolgt vom Wert der Direktive process_performance_data (ppd=n). +

    + +

    +host = Performance-Informationen für den Host host zeigen
    + +;service = Performance-Informationen für Service service zeigen
    + +host;service = Performance-Informationen für Service service auf Host host zeigen +

    + +

    +Die Zeichenketten werden als reguläre Ausdrücke angesehen (Perl-Syntax). + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/webfe.html b/share/pnp/documents/de_DE/webfe.html new file mode 100644 index 0000000..179e717 --- /dev/null +++ b/share/pnp/documents/de_DE/webfe.html @@ -0,0 +1,149 @@ + + + +

    Das Nagios Web Frontend

    +
    + +

    + +PNP soll natürlich schnell erreichbar sein. Man möchte nicht lange nach den richtigen Graphen suchen. +

    + +

    +Nagios selbst bietet die Möglichkeit, externe URLs über die sogenannte Extended Info Config einzubinden. +Da es in diesem Bereich eine Änderung zwischen Nagios 2.x und der Version 3.0 gibt, wird anschließend auf beide Versionen getrennt eingegangen. +

    + +
    + +

    Nagios 2.x

    +
    + +

    + +Bis Nagios 2.x erfolgt die Einbindung externer URLs in das Nagios-Web-Interface über die Extended-Info-Objekte. Für PNP verwenden wir die Option action_url, um das PNP-Web-Frontend mit den passenden Optionen aufzurufen. +

    +
    +define serviceextinfo {
    +   name                  srv-pnp
    +   action_url            /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register              0
    +}
    +
    + +

    +Dieses Template kann nun über “use srv-pnp” in der serviceextinfo-Definition verwendet werden. Wenn Sie die Schnellstart-Installationsanleitungen benutzt haben, können Sie beispielsweise in der Datei localhost.cfg die Definitionen wie folgt erweitern: +

    +
    +define serviceextinfo {
    +   use                     srv-pnp   ; Name of service templates to use
    +   host_name               localhost
    +   service_description     load
    +}
    +
    + +
    + +

    Nagios 3.x

    +
    + +

    + +Seit Nagios 3.0 ist die Direktive action_url in die Host- bzw. Service-Definition verschoben worden. Die serviceextinfo- und hostextinfo-Definitionen sind entfallen. Damit wird die Definition der URLs zum PNP-Interface wesentlich vereinfacht. +

    + +

    +Zuerst definieren wir zwei Nagios-Templates. Falls Sie die Schnellstart-Installationsanleitungen für Nagios benutzt haben, können Sie die folgenden Zeilen der Datei templates.cfg hinzufügen: +

    +
    +define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    +
    + +

    +Diese beiden Templates können nun über “use srv-pnp” in der Service-Definition oder “use host-pnp” in der Host-Definition verwendet werden. Wenn Sie die Schnellstart-Installationsanleitungen benutzt haben, können Sie beispielsweise in der Datei localhost.cfg die Definitionen wie folgt erweitern: + +

    +
    define host{
    +        use                     linux-server,host-pnp    ; Name of host templates to use
    +                                                         ; This host definition will inherit all variables that are defined
    +                                                         ; in (or inherited by) the linux-server host template definition.
    +        host_name               localhost
    +        alias                   localhost
    +        address                 127.0.0.1
    +        }
    +
    +
    define service{
    +        use                     local-service,srv-pnp   ; Name of service templates to use
    +        host_name               localhost
    +        service_description     PING
    +        check_command           check_ping!100.0,20%!500.0,60%
    +        }
    +
    + +

    + +Die Links auf die richtigen URLs werden automagisch erstellt. +

    + +
    + +

    Preview Popup

    +
    + +

    + +Außerdem gibt es die Möglichkeit, die Graphen bereits in der Statusübersicht beim Überfahren des “Action Url Icons” mit der Maus einzublenden. +

    + +

    +Ermöglicht wird dies durch die CGI Includes, die es uns erlauben, Javascript-Code an geeigneter Stelle im Seitenkopf der Statusübersicht einzubinden ( status.cgi ). +

    + +

    +In den PNP-Quellen ist die Datei contrib/ssi/status-header.ssi bereits enthalten, die verwendeten URLs müssen aber unter Umständen angepasst werden. Wir gehen hier davon aus, dass PNP über /pnpnagios/index.php erreichbar ist. +

    + +

    +Die besagte Datei muss in das Verzeichnis /usr/local/nagios/share/ssi/ kopiert werden und darf NICHT ausführbar sein. Nagios würde die Datei sonst wirklich wie ein CGI behandeln und ausführen, was aber in diesem Fall zu Fehlern führen würde. Die Apache-Admins mögen bitte “Nagios SSI” nicht mit “Apache SSI” in Verbindung bringen. Beides hat nichts miteinander zu tun. +

    + +

    +Die action_url ist entsprechend anzupassen: +

    +
    +define host {
    +   name       host-pnp
    +   register   0
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +}
    +
    +define service {
    +   name       srv-pnp
    +   register   0
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +}
    +
    + +

    +Nach einem Restart von Nagios (nach Anpassung der Definitionen) sieht das Ergebnis ungefähr so aus:
    + + +

    + +

    +Zurück zur Übersicht | Konfiguration Web-Frontend + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/webfe_cfg.html b/share/pnp/documents/de_DE/webfe_cfg.html new file mode 100644 index 0000000..56a9ec5 --- /dev/null +++ b/share/pnp/documents/de_DE/webfe_cfg.html @@ -0,0 +1,142 @@ + + + +

    PNP Web Frontend

    +
    + +

    + +Das Verhalten des PNP-Web-Frontend lässt sich über die Config-Datei etc/config.php beeinflussen. +Diese Datei wird bei Updates von PNP immer wieder überschrieben, da die meisten Pfade und Optionen bereits durch ./configure ermittelt werden. +

    + +

    +Eigene Anpassungen sollten daher in der Datei etc/config_local.php erfolgen. Sollte die Datei noch nicht existieren, kann die config.php als Vorlage verwendet werden. +

    + +
    + +

    etc/pnp/config.php

    +
    + +

    + +Im folgenden die wichtigsten Parameter: +

    + +

    +Der Pfad zum RRDtool-Binary. Wird von ./configure ermittelt. + +

    +
     $conf['rrdtool'] = "/usr/bin/rrdtool";
    +
    + +

    +Höhe und Breite der RRD-Graphen + +

    +
     $conf['graph_width'] = "500";
    + $conf['graph_height'] = "100";
    +
    + +

    + +Bildschirmdimensionen ändern sich, Blattgrößen nicht. Um unterschiedliche Einstellungen zu ermöglichen, können für die Generierung von PDF-Dateien eigene Werte definiert werden. Wenn diese Variablen nicht definiert sind, werden die Werte der Graphen benutzt. +Höhe und Breite der RRD-Graphen bei PDFs + +

    +
     $conf['pdf_width'] = "675";
    + $conf['pdf_height'] = "100";
    +
    + +

    + +Zusätzliche Optionen, die bei jedem Aufruf von RRDTool mit übergeben werden. Beispielsweise --slope-mode, um die Graphen etwas zu glätten. + +

    +
     $conf['graph_opt'] = "";
    +
    + +

    + +Der Pfad zu den von process_perfdata.pl erstellten RRD- und XML-Dateien + +

    +
     $conf['rrdbase'] = "/usr/local/pnp4nagios/var/perfdata/";
    +
    + +

    + +Pfad zu den Config-Files für die Pages. + +

    +
     $conf['page_dir'] = "/usr/local/pnp4nagios/etc/pages/";
    +
    + +

    +Wert in Sekunden, nachdem die PNP-Seiten neu geladen werden sollen. + +

    +
     $conf['refresh'] = "90";
    +
    + +

    + +Maximales Alter der RRD-Files in Sekunden. Nach Erreichen dieses Wertes werden Links zu den Graphen als “inactive” gekennzeichnet. + +

    +
     $conf['max_age'] = 60*60*6;
    +
    + +

    + +Basis-URL zu den Nagios CGIs. + +

    +
     $conf['nagios_base'] = "/nagios/cgi-bin";
    +
    + +

    +Liste von Usern, für die Links zu den Services des aktuellen Hosts angezeigt werden sollen. + +

    +
     $conf['allowed_for_service_links'] = "EVERYONE";
    +
    + +

    +Liste von Usern, für die das Host-Suchfeld angezeigt werden soll. + +

    +
     $conf['allowed_for_host_search'] = "EVERYONE";
    +
    + +

    +Wird PNP nur mit der Angabe eines Hosts ( index.php?host=<myserver> ) aufgerufen, so wird eine Übersicht aller Services angezeigt, wenn der User in dieser Liste enthalten ist. + +

    +
     $conf['allowed_for_host_overview'] = "EVERYONE";
    +
    + +

    +Das Array $views[] legt fest, welche Zeitspannen die RRD-Graphen dargestellen sollen. Der Titel und die Anzahl der Graphen kann somit hier zentral definiert werden. +

    +
    +$views[] = array('title' => 'One Hour',  'start' => (60*60) );
    +$views[] = array('title' => '4 Hours',   'start' => (60*60*4) );
    +$views[] = array('title' => '25 Hours',  'start' => (60*60*25) );
    +$views[] = array('title' => 'One Week',  'start' => (60*60*25*7) );
    +$views[] = array('title' => 'One Month', 'start' => (60*60*24*32) );
    +$views[] = array('title' => 'One Year',  'start' => (60*60*24*380) );
    +
    + +

    +Sie können hier auch weitere Views definieren, sollten aber dabei berücksichtigen, dass im Normalfall ALLE definierten Views angezeigt werden. +

    + +

    +zurück zur Übersicht | Timeranges + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/de_DE/wrapper.html b/share/pnp/documents/de_DE/wrapper.html new file mode 100644 index 0000000..b6cb42a --- /dev/null +++ b/share/pnp/documents/de_DE/wrapper.html @@ -0,0 +1,30 @@ + +

    +check_procs ist ein Beispiel für ein Plugin, das keine Performance-Daten ausgibt: +

    +
    ./check_procs -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'
    + +

    +Mit dem folgenden Wrapper-Script kann das geändert werden +

    + +

    +check_procs.sh + +

    +
    #!/bin/bash
    +LINE=`/usr/local/nagios/libexec/check_procs $*`
    +RC=$?
    +COUNT=`echo $LINE | awk '{print $3}'`
    +PROCS=`expr $COUNT - 1`
    +LINE=`echo $LINE | sed "s/: $COUNT /: $PROCS /"`
    +echo $LINE \| procs=$PROCS
    +exit $RC
    + +

    +Nun wird die Zahl zusammen mit einer Bezeichnung ausgegeben. + +

    +
    ./check_procs.sh -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'| procs=2
    diff --git a/share/pnp/documents/de_DE/xport.html b/share/pnp/documents/de_DE/xport.html new file mode 100644 index 0000000..08c4f47 --- /dev/null +++ b/share/pnp/documents/de_DE/xport.html @@ -0,0 +1,43 @@ + + + +

    Datenexport

    +
    + +

    + +PNP bietet über den xport Controller Zugriff auf die RRD-Daten. Dabei kann das Ausgabeformat gewählt werden. Zur Zeit sind die Formate xml, json und csv realisiert. +

    + +

    +Aufgerufen wird der Controller über die URL + +

    +
    /pnp4nagios/xport/<format>?host=<hostname>&srv=<servicedesc>
    + +

    + +wobei <format> durch das jeweils gewünschte Format zu ersetzen ist. +

    + +

    +Sie können außerdem wget benutzen, um Bilder zu erzeugen und diese in regelmäßigen Reports einzufügen. Ein Beispiel: +

    +
    wget -O image.png 'http://<user>:<pass>@<nagios-server>/pnp4nagios/image?host=<hostname>&srv=<service>&view=2&source=0'
    + +

    +view=<n> begrenzt den Graphen auf die Zeitperiode, die in config.php definiert ist
    + +source=<n> zeigt nur eine Data-Source, wenn mehrere in der RRD-Datei vorhanden sind +

    + +

    +Anstatt view können Sie auch start und/oder end benutzen, um die Zeitspanne anzugeben. Details finden Sie in den "time ranges". +

    + +

    +zurück zur Übersicht | Templates + +

    + +
    diff --git a/share/pnp/documents/en_US/about.html b/share/pnp/documents/en_US/about.html new file mode 100644 index 0000000..b0c74db --- /dev/null +++ b/share/pnp/documents/en_US/about.html @@ -0,0 +1,186 @@ + + + +

    About PNP

    +
    + +
    + +

    System requirements

    +
    + +

    + +PNP mandatory requires valid performance data of nagios plugins. +

    + +

    +So what is this performance data? +

    + +

    +The output of a nagios plugin up to nagios 2.x is limited to one line. When the plugin produces performance data, it is divided into two parts. The pipe symbol (“|”) is used as a delimiter. +

    + +

    +Example check_icmp : + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +resulting in the text on the left side of the pipe symbol + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0%
    + +

    + +and the performance data + +

    +
      rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +Performance data is designed for automatic processing. The format is specified within the Developer Guidelines (you'll find an excerpt here) but should be exemplified here nonetheless: + +

    +
      rta=2.687ms;3000.000;5000.000;0;
    +   |    |  |    |         |     | |
    +   |----|--|----|---------|-----|-|----- * label 
    +        |--|----|---------|-----|-|----- * current value
    +           |----|---------|-----|-|----- unit ( UOM = UNIT of Measurement ) 
    +                |---------|-----|-|----- warning threshold
    +                          |-----|-|----- critical threshold 
    +                                |-|----- minimum value 
    +                                  |----- maximum value
    +                                  
    + +

    +Value marked with * are mandatory. All other values are optional. +

    + +

    +Several data series are separated by blanks. The actual data must not contains any blanks. If the label contains blanks, it has to be surrounded by single quotes. +

    + +
    + +

    Required Software

    +
    +
      +
    • Perl >= 5.x without additional modules
      +
    • +
    • RRDtool >= 1.x, better 1.2 but not compulsory
      +Attention: installing RRDtool without a packet manager might lead to missing dejavu fonts. If you see graphs without text then this may be the cause.
      +
    • +
    • PHP >= 5.1.6 for the Webfrontend based on Kohana
      +
    • +
    • Nagios >= 2.x or Icinga
      +
    • +
    • Kohana needs the module “mod_rewrite” to be enabled. For details please have a look at the documentation of your web-server specific to your distribution.
      +
    • +
    + +
    + +

    License

    +
    + +

    + +PNP is licensed under GPL 2 +

    + +
    + +

    Download

    +
    + +

    + +Development of PNP is organized using Sourceforge.Net. PNP is registered under “PNP4nagios”. +

    + +

    +The current stable version of 0.6.x can be found in the download area: Sourceforge Download +

    + +

    +Starting with PNP 0.6.x the source code repository was switched from SVN to GIT. +

    + +

    +The current development can be viewed anytime at https://github.com/lingej/pnp4nagios. Clicking on pnp4nagios-head.tar.gz will download an archive containing the latest version. +
    + +

    + +
    + +

    Support

    +
    + +

    + +PRIOR to support questions please make sure that you have verified certain things described under verify your installation.
    +
    + +

    + +

    +The developers and helpers are present on a separate board at http://www.nagios-portal.org and will be informed about new postings in the PNP-section. Postings in english will be answered as well.
    + +After registering as a user please fill in the profile regarding operating system and PNP version used. Please mention if you used a package or compiled the sources. +Please mark successfully solved threads by adding ”[solved]” to the title as it helps other users to find a solution for their problem. +

    + +

    +The mailing lists on Sourceforge can be used to request support (and are limited to english): +

    + +

    +pnp4nagios-users: users list for general questions regarding configuration. Please state your operating system and PNP version +

    + +

    +pnp4nagios-devel: devel list for suggestions and error reports. Please state your operating system and PNP version +

    + +

    +pnp4nagios-checkins: the checkin list automatically contains changes to the SVN repository +

    + +
    + +

    Storage

    +
    + +

    + +Performance data will be stored in Round Robin Databases using RRDtool. That means that after some time the oldest data will be dropped at the “end” and it will be replaced by new values “at the beginning”. +

    + +

    +Various intervals provide for different resolutions. Using the defaults allows to store the data with a resolution of one minute for the last two days, five minutes resolution for ten days, 30 minutes resolution for 90 days and 6 hours resolution for four years. The increasing interval causes averaging of the data which leads to smaller max values. This not an error of PNP. +

    + +

    +Using this storage format the size of the files will stay the same over time. Per datasource you will need approx. 400 KB. +

    + +
    + +

    Statistics and links to Sourceforge

    +
    + +

    + +back to contents | PNP modes + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/advanced.html b/share/pnp/documents/en_US/advanced.html new file mode 100644 index 0000000..33e7737 --- /dev/null +++ b/share/pnp/documents/en_US/advanced.html @@ -0,0 +1,73 @@ + + + +

    Distributed Systems

    +
    + +

    +If Nagios is implemented as a distributed system you have to decide where PNP should be installed. +

    + +

    +From a technical view this question is not important. PNP can be installed on the slave(s) as well as on the master server. Or only on the master? +

    + +

    +If PNP is running on the master you have to make sure that data passed via send_nsca from the slave server(s) contains performance data. Often another check command is used on the master. +

    + +

    +To help PNP on the master to recognize which check command was used on the slave to collect the information process_perfdata.pl responds to an additional field at the end of the performance data. +

    +
    OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;; [check_icmp]
    + +

    +If PNP finds a string enclosed in brackets at the end of performance data it will be recognized as check command and will be used as PNP template. +

    + +

    +Nagios documentation related to this topic can be found +here. The command used in the documentation can be adapted easily. +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$'
    +	}
    +
    + +

    +should be changed to +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$ | $SERVICEPERFDATA$ [$SERVICECHECKCOMMAND$]'
    +	}
    +
    + +
    + +

    check_multi plugin

    +
    + +

    + +The plugin check_multi is one of the first plugins which uses new features of Nagios 3.x. Check_multi can execute multiple Nagios plugins but returns only results like a single service. The output of check_multi comprises of several lines to be able to display the amount of information. +

    + +

    +This results in some difficulties for PNP which has to extract the information of several plugins from the performance data. Together with Matthias Flacke, developer of check_multi, we have found a solution to assign the data to the appropriate plugins. +

    + +

    + +

    + +

    +back to contents | support of rrdcached + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/config.html b/share/pnp/documents/en_US/config.html new file mode 100644 index 0000000..bf48d4d --- /dev/null +++ b/share/pnp/documents/en_US/config.html @@ -0,0 +1,395 @@ + + + +

    Configuration

    +
    + +

    + +The configuration of the already mentioned modes of performance data processing will be described in more detail. +

    + +
    + +

    Synchronous Mode

    +
    + +

    + + The synchronous mode is the simplest way to integrate the data collector process_perfdata.pl into nagios. Every event will trigger an execution of process-service-perfdata. +

    + +

    +Initially you have to enable processing of performance data in nagios.cfg. Please note that this directive might already exist in the config file. Default is “0”. + +

    +
     process_performance_data=1
    + +

    + +Data processing has to be disabled in the definition of every host or service whose performance data should NOT be processed. +

    +
    +define service {
    +   ...
    +   process_perf_data 0
    +   ...
    +}
    +
    + +

    +Since Nagios 3.x it is possible to deactivate the export of environment variables (as part of optimizing the system for maximum performance). Unfortunately this directive has to be enabled to use the synchronous mode. So either you use the default value (which means that the export is enabled) or you define the variable in nagios.cfg +

    +
    enable_environment_macros=1
    + +

    +Additionally the command to process performance data is to be specified in nagios.cfg + +

    +
     service_perfdata_command=process-service-perfdata
    + +

    + +Starting with Nagios 3.0 it may be useful to enable processing of performance data for hosts as well. Due to changed host check logic Nagios 3 now performs regularly scheduled host checks. + +

    +
     host_perfdata_command=process-host-perfdata
    + +

    + +Nagios has to be notified about the referenced commands as well. If you used the quickstart installation guides for Nagios you can modify the definitions in commands.cfg. +You can see that calling process_perfdata.pl doesn't require any arguments apart from specifing the option -d ( DATATYPE ) if you want to process performance data resulting from host checks. +

    +
    +define command {
    +       command_name    process-service-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +}
    +
    +define command {
    +       command_name    process-host-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA
    +}
    +
    + +

    +Note process_perfdata.pl cannot be started under control of ePN ( embedded Perl Nagios ). Therefore the script is explicitly called using /usr/bin/perl ( or where you perl binary is located ). If you use Nagios 3.x or do not use ePN there is no need to specify /usr/bin/perl. +

    + +
    + +

    Bulk Mode

    +
    + +

    + +Bulk mode is a bit more complicated than the synchronous mode but reduces the load on the nagios server significantly because the data collector process_perfdata.pl is not invoked for every service/host check. +

    + +

    +In bulk mode Nagios writes the data to a temporary file in a defined format. This file is processed by process_perfdata.pl at certain intervals. Nagios will take care for starting and running it periodically. +

    + +

    +Processing of performance data has to be enabled in nagios.cfg + +

    +
     process_performance_data=1
    + +

    + +Additionally some new directives are required +

    +
    +#
    +# service performance data
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# host performance data starting with Nagios 3.0
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    + +Attention: Please note that these template definitions differ from the ones delivered in nagios.cfg! +

    + +

    +The directives and their meaning: + +

    +
      +
    • service_perfdata_file path to the temporary file which should contain the performance data.
      +
    • +
    • service_perfdata_file_template format of the temporary file. Data will be defined using Nagios macros.
      +
    • +
    • service_perfdata_file_mode option “a” specifies that data is to be appended to the file.
      +
    • +
    • service_perfdata_file_processing_interval the interval is 15 seconds
      +
    • +
    • service_perfdata_file_processing_command the command to be called during the interval.
      +
    • +
    + +

    + +The used commands have to be announced to Nagios. If you used the quickstart installation guides for Nagios you can modify the definitions in commands.cfg. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/service-perfdata
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/host-perfdata
    +}
    +
    +
    + +
    +

    NOTE:

    +
    +Because there is more data to process than in synchronous mode process_perfdata.pl will take longer to do this so you should check the TIMEOUT value in etc/process_perfdata.cfg and adjust it appropriately.
    +
    + +
    + +
    + +

    Bulk Mode with NPCD

    +
    + +

    + + The configuration is identical to the Bulk Mode except for the used command. +Processing of performance data has to be enabled in nagios.cfg + +

    +
     process_performance_data=1
    + +

    + +Additionally some new directives are required +

    +
    +#
    +# service performance data
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# host performance data starting with Nagios 3.0
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    + +Attention: Please note that these template definitions differ from the ones delivered in nagios.cfg! +

    + +

    +The directives and their meaning: + +

    +
      +
    • service_perfdata_file path to the temporary file which should contain the performance data.
      +
    • +
    • service_perfdata_file_template format of the temporary file. Data will be defined using Nagios macros.
      +
    • +
    • service_perfdata_file_mode option “a” specifies that data is to be appended to the file.
      +
    • +
    • service_perfdata_file_processing_interval the interval is 15 seconds
      +
    • +
    • service_perfdata_file_processing_command the command to be called during the interval.
      +
    • +
    + +

    + +The used commands have to be announced to Nagios. If you used the quickstart installation guides for Nagios you can modify the definitions in commands.cfg. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/service-perfdata /usr/local/pnp4nagios/var/spool/service-perfdata.$TIMET$
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/host-perfdata /usr/local/pnp4nagios/var/spool/host-perfdata.$TIMET$
    +}
    +
    + +

    +Using these commands the file service-perfdata will be moved to var/spool/ after the interval specified in service_perfdata_file_processing_interval has passed. The Nagios macro $TIMET$ is appended to the filename to avoid overwriting of old files unintentionally. The macro $TIMET$ contains the current timestamp in time_t format (seconds since the UNIX epoch). +

    + +

    +In the directory /usr/local/pnp4nagios/var/spool/ files are gathered to be processed by NPCD. +

    + +

    +NPCD monitors the spool directory and passes the file names to process_perfdata.pl. This way processing of performance data is completely decoupled from nagios. +

    + +

    +Before starting NPCD you have to check the paths to the spool directory and to process_perfdata.pl specified in the config file npcd.cfg. +The only thing that remains is to start NPCD. + +

    +
     /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +The option -d starts NPCD as a daemon in the background. +

    + +
    + +

    Bulk Mode with NPCD and npcdmod

    +
    + +

    + +Attention +Starting with Nagios 4 the internal structures have changed so the start of the module will fail. So far there are no plans to support Nagios 4. Please select any other of the modes. +

    + +

    + This mode uses the event broker module npcdmod.o. The flow of data is identical to “bulk mode with NPCD”. The internal perfdata routines of Nagios activated by the “*_perf_data_*” directives in nagios.cfg are *NOT* used anymore. The module npcdmod.o takes over the task of processing the data required by PNP. +

    + +

    +Pro: +

    +
      +
    • The perfdata routines can now be used for other addons.
      +
    • +
    • The configuration is easier.
      +
    • +
    • It is the preferred mode of the PNP developers.
      +
    • +
    + +

    + +Adjustments in nagios.cfg: +

    +
    +process_performance_data=1
    +broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +
    + +

    +All other directives mentioned on this page must NOT be used. +

    + +

    +Attention: If you have changed the value of event_broker_options from -1 to another value then please note that PNP needs the bits 2 and 3 set (0b01100). Make sure that the resultung value has these bits set because otherwise there will be no performance data to process. +

    + +

    +After restarting Nagios information regarding the start of the module will be logged. +

    + +

    +Excerpt from nagios.log + +

    +
    +[1277545053] npcdmod: Copyright (c) 2008-2009 Hendrik Baecker (andurin@process-zero.de) - http://www.pnp4nagios.org
    +[1277545053] npcdmod: /usr/local/pnp4nagios/etc/npcd.cfg initialized
    +[1277545053] npcdmod: spool_dir = '/usr/local/pnp4nagios/var/spool/'.
    +[1277545053] npcdmod: perfdata file '/usr/local/pnp4nagios/var/perfdata.dump'.
    +[1277545053] npcdmod: Ready to run to have some fun!
    +[1277545053] Event broker module '/usr/local/pnp4nagios/lib/npcdmod.o' initialized successfully.
    +
    + +
    + +

    Gearman Mode

    +
    + +

    + + +

    + +

    +Since version 0.6.12 PNP4Nagios can be driven as a gearman worker. This way large Nagios environments are possible using mod_gearman. Nagios and PNP4Nagios can be run on different machines. +

    + +

    +You need a mod_gearman environment up and running like described by Sven Nierlein on http://labs.consol.de/lang/en/nagios/mod-gearman/. +

    + +

    +You'll find a section on gearman in etc/process_perfdata.cfg: + +

    +
    PREFORK = 1
    +GEARMAN_HOST = localhost:4730
    +REQUESTS_PER_CHILD = 10000
    +ENCRYPTION = 1
    +KEY = should_be_changed
    +#KEY_FILE = /usr/local/pnp4nagios/etc/secret.key
    + +

    + +Using PREFORK = <n> you specify the number of child processes. +

    + +

    +GEARMAN_HOST = <host>:<port> specifies host and port of the server running the gearman daemon providing the data. +

    + +

    +REQUEST_PER_CHILD = <n> enables you to define the number of requests processed per process. +

    + +

    +ENCRYPTION = <n> specifies whether to use encryption (“1”) or not. Default is an activated encyrption which should be changed only in special cases. You can either use KEY = <key phrase> or 'KEYFILE =<key file> to specify the location of a file containing the key phrase. + +etc/init.d/pnp_gearman_worker start contains links to the perl script process_perfdata.pl and the config file process_perfdata.cfg''. +

    + +

    +After starting the daemon process using + +

    +
     /etc/init.d/pnp_gearmon_worker start
    + +

    + +the performance data will be processed which is provided by the gearmand daemon on the Nagios server. +

    + +

    +back to contents | checking the functionality + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/doc_complete.html b/share/pnp/documents/en_US/doc_complete.html new file mode 100644 index 0000000..e9c2506 --- /dev/null +++ b/share/pnp/documents/en_US/doc_complete.html @@ -0,0 +1,3744 @@ + + +
    + + + +

    New in PNP 0.6.x

    +
    + +

    +PNP 0.6.x Preview +

    + +

    +The work on the new version 0.6.x is in full progress. +

    + +

    +Starting with version 0.6.x we switch from subversion to GIT. The sourcecode is already available on sourceforge. +

    + +

    + +Functions implemented already +

    +
      +
    • Webfrontend based on Kohana
      +
    • +
    • Webfrontend based on jQuery Themes
      +
    • +
    • Javascript-functions using jQuery plugins
      +
    • +
    • process_perfdata.pl will be able to use one RRD database per datasource
      +
    • +
    • improved installer. Specification of directory layouts using --with-layout
      +
    • +
    • RRDtool errors are now displayed as images. no more missing images
      +
    • +
    • PNP templates cannot overwrite internal variables anymore
      +
    • +
    • PNP templates of version 0.4.x can still be used
      +
    • +
    • PDF functions recoded
      +
    • +
    • Template default.php optimized
      +
    • +
    • Export from RRD databases into XML, CSV and JSON format using the RRDtool “xport” function
      +
    • +
    • Page functions recoded
      +
    • +
    • Error pages links to online FAQ
      +
    • +
    • Mouseover Popup in Nagios frontend via jQuery.clueTip plugin
      +
    • +
    • Full support of rrdcached
      +
    • +
    + +

    +back to contents | system requirements + +

    + +
    + +
    +
    + + + +

    About PNP

    +
    + +
    + +

    System requirements

    +
    + +

    + +PNP mandatory requires valid performance data of nagios plugins. +

    + +

    +So what is this performance data? +

    + +

    +The output of a nagios plugin up to nagios 2.x is limited to one line. When the plugin produces performance data, it is divided into two parts. The pipe symbol (“|”) is used as a delimiter. +

    + +

    +Example check_icmp : + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +resulting in the text on the left side of the pipe symbol + +

    +
     OK - 127.0.0.1: rta 2.687ms, lost 0%
    + +

    + +and the performance data + +

    +
      rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;;
    + +

    + +Performance data is designed for automatic processing. The format is specified within the Developer Guidelines (you'll find an excerpt here) but should be exemplified here nonetheless: + +

    +
      rta=2.687ms;3000.000;5000.000;0;
    +   |    |  |    |         |     | |
    +   |----|--|----|---------|-----|-|----- * label 
    +        |--|----|---------|-----|-|----- * current value
    +           |----|---------|-----|-|----- unit ( UOM = UNIT of Measurement ) 
    +                |---------|-----|-|----- warning threshold
    +                          |-----|-|----- critical threshold 
    +                                |-|----- minimum value 
    +                                  |----- maximum value
    +                                  
    + +

    +Value marked with * are mandatory. All other values are optional. +

    + +

    +Several data series are separated by blanks. The actual data must not contains any blanks. If the label contains blanks, it has to be surrounded by single quotes. +

    + +
    + +

    Required Software

    +
    +
      +
    • Perl >= 5.x without additional modules
      +
    • +
    • RRDtool >= 1.x, better 1.2 but not compulsory
      +Attention: installing RRDtool without a packet manager might lead to missing dejavu fonts. If you see graphs without text then this may be the cause.
      +
    • +
    • PHP >= 5.1.6 for the Webfrontend based on Kohana
      +
    • +
    • Nagios >= 2.x or Icinga
      +
    • +
    • Kohana needs the module “mod_rewrite” to be enabled. For details please have a look at the documentation of your web-server specific to your distribution.
      +
    • +
    + +
    + +

    License

    +
    + +

    + +PNP is licensed under GPL 2 +

    + +
    + +

    Download

    +
    + +

    + +Development of PNP is organized using Sourceforge.Net. PNP is registered under “PNP4nagios”. +

    + +

    +The current stable version of 0.6.x can be found in the download area: Sourceforge Download +

    + +

    +Starting with PNP 0.6.x the source code repository was switched from SVN to GIT. +

    + +

    +The current development can be viewed anytime at https://github.com/lingej/pnp4nagios. Clicking on pnp4nagios-head.tar.gz will download an archive containing the latest version. +
    + +

    + +
    + +

    Support

    +
    + +

    + +PRIOR to support questions please make sure that you have verified certain things described under verify your installation.
    +
    + +

    + +

    +The developers and helpers are present on a separate board at http://www.nagios-portal.org and will be informed about new postings in the PNP-section. Postings in english will be answered as well.
    + +After registering as a user please fill in the profile regarding operating system and PNP version used. Please mention if you used a package or compiled the sources. +Please mark successfully solved threads by adding ”[solved]” to the title as it helps other users to find a solution for their problem. +

    + +

    +The mailing lists on Sourceforge can be used to request support (and are limited to english): +

    + +

    +pnp4nagios-users: users list for general questions regarding configuration. Please state your operating system and PNP version +

    + +

    +pnp4nagios-devel: devel list for suggestions and error reports. Please state your operating system and PNP version +

    + +

    +pnp4nagios-checkins: the checkin list automatically contains changes to the SVN repository +

    + +
    + +

    Storage

    +
    + +

    + +Performance data will be stored in Round Robin Databases using RRDtool. That means that after some time the oldest data will be dropped at the “end” and it will be replaced by new values “at the beginning”. +

    + +

    +Various intervals provide for different resolutions. Using the defaults allows to store the data with a resolution of one minute for the last two days, five minutes resolution for ten days, 30 minutes resolution for 90 days and 6 hours resolution for four years. The increasing interval causes averaging of the data which leads to smaller max values. This not an error of PNP. +

    + +

    +Using this storage format the size of the files will stay the same over time. Per datasource you will need approx. 400 KB. +

    + +
    + +

    Statistics and links to Sourceforge

    +
    + +

    + +back to contents | PNP modes + +

    + +
    + +
    +
    + + + +

    The art of collecting data

    +
    + +

    + +PNP supports several modes to process performance data. The modes differ in complexity and the performance to be expected. +

    + +

    +The following image shows the connections between Nagios, PNP and RRDtool
    + +

    + +

    +Nagios invokes a command for every host and every service whose performance data should be processed. Depending on the mode you choose the data will be passed to process_perfdata.pl or will be written to temporary files and processed at a later time. process_perfdata.pl writes the data to XML files and stores them in RRD files using RRDtool.
    + +

    + +

    +Before you choose a mode please read the documentation and decide which way will be the best for installation. +

    + +
    + +

    The modes in comparison

    +
    + +
    + +

    Synchronous Mode

    +
    + +

    + +The “synchronous mode” is the simplest and easiest to set up. Nagios will call the perl script process_perfdata.pl for every service and host, respectively, to process the data. The synchronous mode will work very good up to about 1.000 services in a 5 minute interval. +

    + +
    + +

    Bulk Mode

    +
    + +

    + +In bulk mode Nagios writes the necessary data to a temporary file. After expiration of a defined time the file will be processed in one piece and deleted afterwards. +

    + +

    +The number of calls of process_perfdata.pl will be reduced to a fraction. Depending on time and the amount of collected data there will be much less system calls. Instead, process_perfdata.pl will run longer. +

    + +

    +Note +Using this mode you should keep an eye on the runtime of process_perfdata.pl. While it is running to process data nagios will not execute any checks. +

    + +

    +snippet of var/perfdata.log: + +

    +
    +2007-10-18 12:05:01 [21138] 71 Lines processed
    +2007-10-18 12:05:01 [21138] .../spool/service-perfdata-1192701894-PID-21138 deleted
    +2007-10-18 12:05:01 [21138] PNP exiting (runtime 0.060969s) ...
    +
    + +

    +71 lines were processed in 0.06 seconds. This will be the data volume of about 2000 services und processing using a 10 second interval. It means we blocked nagios for exactly 0.06 seconds. +

    + +
    + +

    Bulk Mode with NPCD

    +
    + +

    + +Viewing from Nagios this is the best way of processing because Nagios will not be blocked. +

    + +

    +Nagios again uses a temporary file to store the data and executes a command after expiration of a certain time. Instead of immediate processing by process_perfdata.pl the file is moved to a spool directory. As moving a file inside the same filesystem nearly takes no time nagios is able to execute crucial work immediately. +

    + +

    +The NPCD daemon (Nagios Performance C Daemon) will monitor the directory for new files and will pass the names to process_perfdata.pl. Processing of performance data is decoupled completely from nagios. NPCD itself is able to start multiple thread for processing the data. +

    + +
    + +

    Bulk Mode with npcdmod

    +
    + +

    + +Attention +Starting with Nagios 4 the internal structures have changed so the start of the module will fail. So far there are no plans to support Nagios 4. Please select any other of the modes. +

    + +

    + This scenario includes npcdmod.o, an NEB-module. +This module reduces the configuration of the “Bulk Mode with NPCD” to a mere two lines in nagios.cfg +

    + +

    +This mode is similar to “Bulk Mode with NPCD” and it is exactly the same functionality and the same performance. +

    + +
    + +

    Gearman Mode

    +
    + +

    + + +

    + +

    +Since version 0.6.12 PNP4Nagios can be driven as a gearman worker. This way large Nagios environments are possible using mod_gearman. Nagios and PNP4Nagios can be run on different machines. +

    + +

    +You need a mod_gearman environment up and running like described by Sven Nierlein on http://labs.consol.de/lang/en/nagios/mod-gearman/. +

    + +
    + +

    The decision

    +
    + +

    +Which mode you choose will depend on the size of your Nagios installation. You will find theses terms throughout the documentation. +

    + +

    +back to contents | installation + +

    + +
    + +
    +
    + + + +

    PNP 0.6.x Downloads

    +
    + +
    + +

    Current stable PNP Version

    +
    + +

    + +Changes can be tracked on pnp4nagios.git.sourceforge.net +

    + +

    +The current Version is pnp4nagios-0.6.22.tar.gz +

    + +
    + +

    Latest Devel Version

    +
    + +

    + + pnp4nagios-head.tar.gz +

    + +

    +This is allways the latest GIT HEAD Version +

    +
    + +

    + +Last Update: Wed Jul 30 06:30:01 CEST 2014 +

    + +
    + +

    ChangeLog

    +
    + +

    + +pnp-0.6.?? ??/??/2013 +

    +
      +
    • Bugfix: Fixed some more XSS issues
      +
    • +
    • Bugfix: Fixed PHP issue while running on PHP 5.6 ( Reported by Sven Nierlein )
      +
    • +
    + +

    + +pnp-0.6.22 04/06/2014 +

    +
      +
    • Bugfix: Fixed livestatus socket parsing ( Pekka Panula )
      +
    • +
    • Bugfix: Update check_mssql_health.php ( Miriam Zenk )
      +
    • +
    • Feature: Add “version=tiny” to got get a stripped down version of graph ( Ricardo Bartels )
      +
    • +
    • feature: Add STDIN Mode to process_perfdata.pl ( Robert Steininger )
      +
    • +
    • Bugfix: XSS issue fixed by Mikael Falkvidd. This issue was detected by Peter Österberg at Hexbit AB in a security assessment of op5 Monitor 6.3 on assignment by op5 AB.
      +
    • +
    + +

    + +pnp-0.6.21 03/24/2013 +

    +
      +
    • Feature: Helper functions rrd::alerter and rrd:alerter_gr both supports treshold detection (Martin Schirrmacher)
      +
    • +
    • Update: jQuery Mobile update to 1.3.0 ( was broken in 0.6.20 )
      +
    • +
    + +

    + +pnp-0.6.20 03/03/2013 +

    +
      +
    • Feature: Support check_mk Multisite Cookie Auth ( Lars Michelsen )
      +
    • +
    • Feature: Allow RRD unknown values ( Simon Meggle )
      +
    • +
    • feature: Interactive delete mode added to check_rrds.pl ( Simon Meggle )
      +
    • +
    • Bugfix: Allow multiple gearman servers ( Craig Barraclough )
      +
    • +
    • Bugfix: Fixed Graph Search ( Stefan Triep )
      +
    • +
    • Update: jQuery update to 1.8.1
      +
    • +
    • Update: jQueryUI update to 1.8.23
      +
    • +
    + +

    + +pnp-0.6.19 09/01/2012 +

    +
      +
    • Feature: Parameter “width” added to popup controller ( Andreas Doehler )
      +
    • +
    • Fix: simplify/improve apache rules ( Christoph Anton Mitterer )
      +
    • +
    • Fix: Check for missing PHP GD functions
      +
    • +
    • Bugfix: socketDOMAIN changed to AF_INET while using livstatus tcp socket ( Rene Koch )
      +
    • +
    + +

    + +pnp-0.6.18 06/28/2012 +

    +
      +
    • Bugfix: Fixed STORAGE_TYPE and CUSTOM_TEMPLATE vars used in custom templates
      +
    • +
    • Bugfix: Blank screen on PHP 5.4 fixed
      +
    • +
    • Feature: Allow multiple gearman job servers
      +
    • +
    • Feature: New helper function rrd::debug()
      +
    • +
    • Feature: New templates check_jmx4perl_*.php
      +
    • +
    + +

    + +pnp-0.6.17 03/25/2012 +

    +
      +
    • Bugfix: Fixed rrd_convert.pl while running with --dry-run
      +
    • +
    • Bugfix: logging.c include missing header files ( Lars Vogdt )
      +
    • +
    • Bugfix: Check if pnp4nagios/etc/rra.cfg is readable
      +
    • +
    • Bugfix: rrd_convert.pl use XML tag TEMPLATE instead of CHECKCOMMAND to selects RRDs ( Sven Velt )
      +
    • +
    • Feature: npcdmod.o increase perfdata buffer and log discarded perfdata ( Birger Schmidt )
      +
    • +
    • Feature: rrd_modify.pl to change number of data sources of an RRD file
      +
    • +
    • Feature: New template check_apachestatus_auto.php
      +
    • +
    • Feature: Implement etc/config.d to place config snippets ( Lars Michelsen )
      +
    • +
    + +

    + +pnp-0.6.16 11/21/2011 +

    +
      +
    • Bugfix: Fixed single quoted check_multi labels (Reported by Matthias Flacke)
      +
    • +
    • Bugfix: Append missing slash to perfdata_spool_dir ( Reported by Juergen-Michael Radtke )
      +
    • +
    • Bugfix: Fixed jQuery-ui multisite theme
      +
    • +
    • Feature: PDF margins are now adjustable via config.php ( Thomas Witzenrath )
      +
    • +
    • Feature: Support for PDF size 'letter' added ( Robert Becht )
      +
    • +
    + +

    + +pnp-0.6.15 09/15/2011 +

    +
      +
    • Bugfix: Fixed Overview link (reported by Stefan Triep)
      +
    • +
    • Bugfix: Fixed zoom popup (reported by Rudolf Labuschagne)
      +
    • +
    • Bugfix: Fixed double urlencode() (reported by Mathias Kettner)
      +
    • +
    • Feature: “Clear basket” button added (suggested by Stefan Triep)
      +
    • +
    • Feature: New helper function “rrd::alerter_gr()” ( committed by Stefan Trip )
      +
    • +
    + +

    + +pnp-0.6.14 08/05/2011 +

    +
      +
    • Feature: Webinterface for mobile devices based on jQuery Mobile
      +( http://jquerymobile.com/ )
      +
    • +
    • Feature: Zoom based on jQuery plugin imgAreaSelect
      +( http://odyniec.net/projects/imgareaselect/ )
      +
    • +
    • Feature: New template check_mssql_health.php
      +
    • +
    • Bugfix: Fixed popups to work under nginx ( Joram Agten )
      +
    • +
    • Bugfix: Helper rrd::vdef() fixed
      +
    • +
    • Update: jQuery update to 1.6.2
      +
    • +
    • Update: jQuery-ui update to 1.8.14
      +
    • +
    + +

    + +pnp-0.6.13 05/19/2011 +

    +
      +
    • Feature: New option --ignore-hosts added to check_pnp_rrds.pl ( by Jochen Bern )
      +
    • +
    • Feature: New options zgraph_width and zgraph_height in config.php ( Mike Liebsch )
      +
    • +
    • Bugfix: rrd_convert.pl: parse_xml_filename() regex fix
      +
    • +
    • Info: Version used by OMD-0.48 OMD
      +
    • +
    + +

    + +pnp-0.6.12 04/22/2011 +

    +
      +
    • Feature: mod_gearman support added
      +
    • +
    • Feature: rrd_convert.pl is now able to convert all RRDs from RRD_STORAGE_TYPE=SINGLE to RRD_STORAGE_TYPE=MULTIPLE
      +
    • +
    • Feature: New template check_gearman.php
      +
    • +
    • Feature: Install process_perfdata.cfg and npcd.cfg by default
      +
    • +
    • Bugfix: rrd_convert.pl is now able to parse xml dumps created by rrdtool 1.4.x
      +
    • +
    • Bugfix: process_perfdata.pl default timeout value set to 15 seconds
      +
    • +
    + +

    + +pnp-0.6.11 01/15/2011 +

    +
      +
    • Bugfix: urldecoding fixed
      +
    • +
    • Bugfix: Zoom in/out is working again ( Reported by Thorben Soehl )
      +
    • +
    • Featue: npcd.cfg - New option perfdata_file_processing_interval used by npcdmod
      +
    • +
    • Info: Version used by OMD-0.46 OMD
      +
    • +
    + +

    + +pnp-0.6.10 12/15/2010 + +

    +
      +
    • Feature: Add RRDTool Option --only-graph if graph height is below 32px to create thumbnails
      +
    • +
    • Feature: RRDTool Option --width and --height is now allowed in templates
      +
    • +
    • Feature: RRDTool DS Type for UOM of “c” changed from COUNTER to DERIVE
      +
    • +
    • Feature: Pass query string from special controller to image controller ( Matthew Garrett )
      +
    • +
    • Feature: Authorisation against mk_livestatus API added
      +
    • +
    • Feature: Sample nginx webserver config added ( by evax@users.sourceforge.net )
      +
    • +
    • Feature: Kohana backport to support PHP 5.1.6 ( Kudos to Andreas Ericsson )
      +
    • +
    • Bugfix: Sort list of special templates
      +
    • +
    • Bugfix: Urlencode hostname and service description ( Reported by Yannick )
      +
    • +
    • Bugfix: corrected warning/critical thresholds in ticker/alerter functions
      +
    • +
    + +

    + +pnp-0.6.7 09/27/2010 + +

    +
      +
    • Bugfix: Page config parser fix (Beau Gunderson)
      +
    • +
    • Bugfix: Zoom window size fixed (Report by Rudolf Labuschagne)
      +
    • +
    • Bugfix: Fixed undefined offset while using 'ds_name' in templates (Reported by Vladimir Bilik)
      +
    • +
    • Bugfix: Npcdmod respects process_perf_data option used in hosts and services definitions ( Reported by Wolfgang Barth )
      +
    • +
    • Template: New Template check_nagiostats.php used with check_nagiostats written by Jochen Bern
      +
    • +
    + +

    + +pnp-0.6.6 08/07/2010 + +

    +
      +
    • Bugfix: Fixed max amount of graphs per template
      +
    • +
    • Bugfix: Autodetect PNP base URL
      +
    • +
    • Bugfix: Too short npcdmod perfdata_template to take perfdata + overhead, increased +1024byte
      +
    • +
    • Bugfix: Ignore files in var/perfdata and check for empty directories
      +
    • +
    • Bugfix: Reducing memory usage while parsing page config (Laurent Freval)
      +
    • +
    + +

    + +pnp-0.6.5 07/09/2010 + +

    +
      +
    • Feature: Special Templates are back tpl_special
      +
    • +
    • Feature: New rrdtool helper functions makes template design easier tpl_helper
      +
    • +
    • Feature: config.php → 'recursive_template_search' is enabled by default
      +
    • +
    • Feature: config.php → 'template_dirs' is now an array of directorys to search for PNP templates
      +
    • +
    + +

    + +pnp-0.6.4 06/03/2010 + +

    +
      +
    • Update: jQuery Update to 1.4.2
      +
    • +
    • Update: jQuery-ui Update to 1.8
      +
    • +
    • Feature: New configure Option --with-base-url
      +
    • +
    • Template: New template check_ntp_time.php (Mathias Kettner)
      +
    • +
    • Feature: New i18n files for fr_FR (Yannig Parre)
      +
    • +
    • Feature: New jQuery Theme 'multisite'
      +
    • +
    + +

    + +pnp-0.6.3 03/16/2010 + +

    +
      +
    • Feature: New helper script libexec/rrd_convert.pl → rrd_convert
      +
    • +
    • Bugfix: Ignore old XML files while building the service list
      +
    • +
    • Template: New template check_hpasm.php
      +
    • +
    • Bugfix: Installer now checks for json_decode()
      +
    • +
    • Workaround: Allow “trailing unfilled semicolons”. Workaround for nsclient++
      +
    • +
    • Template: Updates for check_openmanage.php, check_hp_bladecenter.php and check_dell_baldecenter.php ( Trond Hasle Amundsen )”
      +
    • +
    + +

    + +pnp-0.6.2 12/23/2009 + +

    +
      +
    • Feature: XML_WRITE_DELAY option added to process_perfdata.cfg as suggested by Mathias Kettner
      +
    • +
    • Feature: New template integer.php
      +
    • +
    • Update: FPDI update to 1.3.1
      +
    • +
    • Feature: PNP will now work with lighttpd and php-cgi
      +
    • +
    • Template: check_mk-ps.perf.php added ( by Mathias Kettner )
      +
    • +
    • Feature: PNP will now work without mod_rewrite → webfe
      +
    • +
    • Bugfix: Wrong pdf link used on site 'pages' and 'basket'
      +
    • +
    • Bugfix: Incorrect group permissions on spool directory
      +
    • +
    + +

    + +pnp-0.6.1 11/22/2009 + +

    +
      +
    • Feature: RRD heartbeat per check_command → tpl_custom
      +
    • +
    • Feature: New config.php option pdf_graph_opt
      +
    • +
    • Feature: Recognize the 'background_pdf' option in page definitions → pages
      +
    • +
    • Feature: Recognize the 'source' option in page definitions → pages
      +
    • +
    • Feature: Array $TIMERANGE now available for templates → timeranges
      +
    • +
    • Bugfix: ./configure --sysconfdir no longer ignored
      +
    • +
    • Feature: Store internal runtime statistics on a per minute base
      +
    • +
    • Feature: Added two widgets views/widget_menu.php and views/widget_graph.php
      +
    • +
    + +

    + +pnp-0.6.0 10/30/2009 + +

    +
      +
    • Webfrontend based on Kohana
      +
    • +
    • Webfrontend based on jQuery Themes
      +
    • +
    • Javascript-functions using jQuery plugins
      +
    • +
    • process_perfdata.pl will be able to use one RRD database per datasource
      +
    • +
    • improved installer. Specification of directory layouts using --with-layout
      +
    • +
    • RRDtool errors are now displayed as images. no more missing images
      +
    • +
    • PNP templates cannot overwrite internal variables anymore
      +
    • +
    • PNP templates of version 0.4.x can still be used
      +
    • +
    • PDF functions recoded
      +
    • +
    • Template default.php optimized
      +
    • +
    • Export from RRD databases into XML, CSV and JSON format using the RRDtool “xport” function
      +
    • +
    • Page functions recoded
      +
    • +
    • Error pages links to online FAQ
      +
    • +
    • Mouseover Popup in Nagios frontend via jQuery.clueTip plugin
      +
    • +
    • Full support of rrdcached
      +
    • +
    + +
    + +
    +
    + + + +

    Upgrade to version 0.6.x

    +
    + +

    + +The web-frontend has been completely rewritten and is now based on the PHP MVC framework Kohana. This leads to changed dependencies which must be checked prior to installation. +

    + +

    +Note: At first an upgrade is like a new installation. Afterwards some changes should be made which are described further down. +

    + +

    +Without specifying any options during ./configure PNP 0.4.x was installed below an existing Nagios-Installation at /usr/local/nagios. +

    + +

    +Without specifying any options during ./configure PNP 0.6.x will be installed in a separate directory at /usr/local/pnp4nagios, i.e. it should be viewed as an independent application. +

    + +

    +Note: It is sufficient to copy the *.rrd files from the old to the new location. They contain the data The *.xml files are recreated every time new performance data arrives as they contain meta information. The internal structure of the xml files has changed so you wouldn't be able to use them either way. +

    + +
    + +

    Comparison of the structure

    +
    + +

    + +Summary of a PNP 0.4.14 installation +

    +
    +./configure
    +...
    +*** Configuration summary for pnp 0.4.14 05-02-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/nagios
    +  HTML Dir:                         /usr/local/nagios/share/pnp
    +  Config Dir:                       /usr/local/nagios/etc/pnp
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/nagios/share/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/nagios/var/spool/perfdata/
    +
    + +

    +Summary of a PNP 0.6.0 installation +

    +
    +./configure
    +...
    +*** Configuration summary for pnp4nagios-0.6.0 07-30-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    + +

    +Looking at these lines result in the parameters to be changed and the upgrade strategy. +

    + +
    + +

    Adjustments

    +
    + +

    + +The templates of the action_url definitions have changed. Instead of ”/nagios/pnp” the URL should be ”/pnp4nagios” and instead of “index.php” now “graph” will be used. +

    +
    define host {
    +  name       host-pnp
    +  register   0
    +  action_url /pnp4nagios/graph?host=$HOSTNAME$
    +}
    +
    +define service {
    +  name       srv-pnp
    +  register   0
    +  action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +}
    + +

    +The definitions for the preview popup function are similar + +

    +
    define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    + +

    + +Attention: It is not an error that the strings in front and after “class” contain only one quote. +

    + +

    +Other than described in the 0.4.x documentation these templates can be used for Nagios 2.x and 3.x. +

    + +

    +The variables in the files in the templates folder have to be initialised before first use. Example +

    +
    $lower = ""
    + +

    + +Earlier you were able to append to variables which weren't initialised before first use. Example: + +

    +
    foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    + +Now you have to change that to + +

    +
    +$def[1] = "";
    +foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    + +
    + +Constants in template files don't work anymore, so that they have to be converted to variables. +

    +
    define("_WARNRULE", '#FFFF00');
    + +

    +may be changed to +

    +
     $WARNRULE = '#FFFF00';
    + +

    +Please keep in mind that all occurrences have to be changed ;-). +

    + +
    + +

    Upgrade scenario using NPCD

    +
    +
      +
    1. planning the new setup
      +
    2. +
    3. perform test installation and acquaint oneself with the new system
      +
    4. +
    5. create backup of the old installation
      +
    6. +
    7. install PNP 0.6.x at /usr/local/pnp4nagios
      +
    8. +
    9. make install-config
      +
    10. +
    11. make install-webconf
      +
    12. +
    13. reload Apache
      +
    14. +
    15. test Apache-config
      +
        +
      1. call of /pnp4nagios has to report an empty perfdata directory
        +
      2. +
      +
    16. +
    17. create /usr/local/pnp4nagios/etc/npcd.cfg from npcd.cfg-sample
      +
        +
      1. check paths and adapt changes from 0.4.x if necessary
        +
      2. +
      +
    18. +
    19. adjust all paths in nagios.cfg to the new PNP installation
      +
    20. +
    21. adjust all paths in the command definitions
      +
    22. +
    23. stop npcd using /etc/init.d/npcd stop
      +
    24. +
    25. make install-init installs the new init script for npcd
      +
    26. +
    27. /etc/init.d/nagios stop
      +
    28. +
    29. copy /usr/local/nagios/share/perfdata to /usr/local/pnp4nagios/var/perfdata. Attention: check the permissions
      +
    30. +
    31. /etc/init.d/npcd start
      +
    32. +
    33. /etc/init.d/nagios start
      +
    34. +
    + +
    + +
    +
    + + + +

    Installation

    +
    + +

    +The installation of PNP will be described in more detail. It is expected that nagios was compiled from source and is located in /usr/local/nagios.
    + +Attention: The description applies to the developer version PNP 0.6.0.
    + +Please note that PNP has to be configured after the installation. +

    + +
    + +

    Make and more

    +
    + +

    +The installation of PNP is controlled by makefiles. The system is analyzed after invocation of ./configure and the detected values are tranferred to makefiles. +

    + +

    +Please unpack PNP as user root: + +

    +
    +tar -xvzf pnp4nagios-HEAD.tar.gz
    +cd pnp4nagios
    +
    + +

    +./configure is to be called from the directory pnp4nagios. +

    +
    +./configure
    +
    + +

    + +Note: Without specifying any options user and group will be “nagios”. If you have different values then please use the parameters ”--with-nagios-user” and ”--with-nagios-group”, respectively. Using Icinga the call might be + +

    +
    +./configure --with-nagios-user=icinga --with-nagios-group=icinga
    +
    + +

    + +Some lines run across the screen. The output at the end is important. +

    +
    +*** Configuration summary for pnp4nagios-0.6.2 23-12-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.2.12
    +  RRDs Perl Modules:                FOUND (Version 1.2012)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    +
    +  Review the options above for accuracy.  If they look okay,
    +  type 'make all' to compile.
    + +

    +The paths shown should be checked. If the displayed values aren't correct you can change them calling ./configure with appropriate options.
    + +Attention: “Location of rrdtool binary” means path including name of binary! If necessary it can be specified using the following syntax: + +

    +
     ./configure --with-rrdtool=/usr/local/rrdtool-1.2.xx/bin/rrdtool
    +
     ./configure --help 
    + +

    + +shows the supported options.
    +
    + +

    + +

    +Invoking +

    +
     make all
    + +

    + +compiles the components like NPCD which are written in C + +

    +
     make install
    + +

    + +copies everything to the right places in the file system. The paths were already shows during ./configure. +

    + +

    +After the installation of the program and HTML files you can copy a sample Apache configuration file to your web-server config directory + +

    +
     make install-webconf
    + +

    + +You can call + +

    +
     make install-config
    + +

    + +optionally. This way config files for process_perfdata.pl and npcd are copied to etc/pnp. +

    + +

    +To install the NPCD Init script call + +

    +
     make install-init
    + +

    + +All these steps are combined in + +

    +
     make fullinstall
    + +

    + +Note: As already stated the Nagios settings will be used per default. If you are using Icinga the file '/etc/apache2/conf.d/pnp4nagios.conf' has to be edited to change the path to AuthUserFile (the path may differ between distributions): + +

    +
    #       AuthUserFile /usr/local/nagios/etc/htpasswd.users
    +        AuthUserFile /usr/local/icinga/etc/htpasswd.users
    + +

    +Attention: After copying the configuration file for the web server you have to restart the web server (service httpd restart or /etc/init.d/apache2 restart, respectively). +

    + +
    + +

    Update

    +
    + +

    + +The update of a 0.6.x version works (nearly) the same way as an installation. Please note that you have to call ./configure with the same options you used during the first installation. +Please check if you changed anything in the folder share/templates.dist. Own templates should be placed in share/templates to avoid being overwritten.
    + +Attention: If you changed config.php then you should save this file before it is overwritten when you execute make install-config. +

    + +

    +You can skip make install-webconf and make install-init because nothing changed between 0.6.x versions. +

    + +
    + +

    The components

    +
    + +

    + +After installation the components of PNP were copied to the appropriate places in the file system. These are +

    + +

    +the PHP-Files for the web-frontend below + +

    +
     /usr/local/pnp4nagios/share
    + +

    + +the data collector process_perfdata.pl in + +

    +
     /usr/local/pnp4nagios/libexec
    + +

    + +sample config files with the suffix -sample in + +

    +
     /usr/local/pnpnagios/etc
    + +

    + +the config file config.php for the web frontend in + +

    +
     /usr/local/pnp4nagios/etc
    + +

    + +back to contents | configuration + +

    + +
    + +
    +
    + + + +

    Configuration

    +
    + +

    + +The configuration of the already mentioned modes of performance data processing will be described in more detail. +

    + +
    + +

    Synchronous Mode

    +
    + +

    + + The synchronous mode is the simplest way to integrate the data collector process_perfdata.pl into nagios. Every event will trigger an execution of process-service-perfdata. +

    + +

    +Initially you have to enable processing of performance data in nagios.cfg. Please note that this directive might already exist in the config file. Default is “0”. + +

    +
     process_performance_data=1
    + +

    + +Data processing has to be disabled in the definition of every host or service whose performance data should NOT be processed. +

    +
    +define service {
    +   ...
    +   process_perf_data 0
    +   ...
    +}
    +
    + +

    +Since Nagios 3.x it is possible to deactivate the export of environment variables (as part of optimizing the system for maximum performance). Unfortunately this directive has to be enabled to use the synchronous mode. So either you use the default value (which means that the export is enabled) or you define the variable in nagios.cfg +

    +
    enable_environment_macros=1
    + +

    +Additionally the command to process performance data is to be specified in nagios.cfg + +

    +
     service_perfdata_command=process-service-perfdata
    + +

    + +Starting with Nagios 3.0 it may be useful to enable processing of performance data for hosts as well. Due to changed host check logic Nagios 3 now performs regularly scheduled host checks. + +

    +
     host_perfdata_command=process-host-perfdata
    + +

    + +Nagios has to be notified about the referenced commands as well. If you used the quickstart installation guides for Nagios you can modify the definitions in commands.cfg. +You can see that calling process_perfdata.pl doesn't require any arguments apart from specifing the option -d ( DATATYPE ) if you want to process performance data resulting from host checks. +

    +
    +define command {
    +       command_name    process-service-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +}
    +
    +define command {
    +       command_name    process-host-perfdata
    +       command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA
    +}
    +
    + +

    +Note process_perfdata.pl cannot be started under control of ePN ( embedded Perl Nagios ). Therefore the script is explicitly called using /usr/bin/perl ( or where you perl binary is located ). If you use Nagios 3.x or do not use ePN there is no need to specify /usr/bin/perl. +

    + +
    + +

    Bulk Mode

    +
    + +

    + +Bulk mode is a bit more complicated than the synchronous mode but reduces the load on the nagios server significantly because the data collector process_perfdata.pl is not invoked for every service/host check. +

    + +

    +In bulk mode Nagios writes the data to a temporary file in a defined format. This file is processed by process_perfdata.pl at certain intervals. Nagios will take care for starting and running it periodically. +

    + +

    +Processing of performance data has to be enabled in nagios.cfg + +

    +
     process_performance_data=1
    + +

    + +Additionally some new directives are required +

    +
    +#
    +# service performance data
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# host performance data starting with Nagios 3.0
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    + +Attention: Please note that these template definitions differ from the ones delivered in nagios.cfg! +

    + +

    +The directives and their meaning: + +

    +
      +
    • service_perfdata_file path to the temporary file which should contain the performance data.
      +
    • +
    • service_perfdata_file_template format of the temporary file. Data will be defined using Nagios macros.
      +
    • +
    • service_perfdata_file_mode option “a” specifies that data is to be appended to the file.
      +
    • +
    • service_perfdata_file_processing_interval the interval is 15 seconds
      +
    • +
    • service_perfdata_file_processing_command the command to be called during the interval.
      +
    • +
    + +

    + +The used commands have to be announced to Nagios. If you used the quickstart installation guides for Nagios you can modify the definitions in commands.cfg. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/service-perfdata
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /usr/local/pnp4nagios/libexec/process_perfdata.pl --bulk=/usr/local/pnp4nagios/var/host-perfdata
    +}
    +
    +
    + +
    +

    NOTE:

    +
    +Because there is more data to process than in synchronous mode process_perfdata.pl will take longer to do this so you should check the TIMEOUT value in etc/process_perfdata.cfg and adjust it appropriately.
    +
    + +
    + +
    + +

    Bulk Mode with NPCD

    +
    + +

    + + The configuration is identical to the Bulk Mode except for the used command. +Processing of performance data has to be enabled in nagios.cfg + +

    +
     process_performance_data=1
    + +

    + +Additionally some new directives are required +

    +
    +#
    +# service performance data
    +#
    +service_perfdata_file=/usr/local/pnp4nagios/var/service-perfdata
    +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$
    +service_perfdata_file_mode=a
    +service_perfdata_file_processing_interval=15
    +service_perfdata_file_processing_command=process-service-perfdata-file
    +
    +#
    +# host performance data starting with Nagios 3.0
    +# 
    +host_perfdata_file=/usr/local/pnp4nagios/var/host-perfdata
    +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$
    +host_perfdata_file_mode=a
    +host_perfdata_file_processing_interval=15
    +host_perfdata_file_processing_command=process-host-perfdata-file
    +
    + +

    + +Attention: Please note that these template definitions differ from the ones delivered in nagios.cfg! +

    + +

    +The directives and their meaning: + +

    +
      +
    • service_perfdata_file path to the temporary file which should contain the performance data.
      +
    • +
    • service_perfdata_file_template format of the temporary file. Data will be defined using Nagios macros.
      +
    • +
    • service_perfdata_file_mode option “a” specifies that data is to be appended to the file.
      +
    • +
    • service_perfdata_file_processing_interval the interval is 15 seconds
      +
    • +
    • service_perfdata_file_processing_command the command to be called during the interval.
      +
    • +
    + +

    + +The used commands have to be announced to Nagios. If you used the quickstart installation guides for Nagios you can modify the definitions in commands.cfg. +

    +
    +define command{
    +       command_name    process-service-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/service-perfdata /usr/local/pnp4nagios/var/spool/service-perfdata.$TIMET$
    +}
    +
    +define command{
    +       command_name    process-host-perfdata-file
    +       command_line    /bin/mv /usr/local/pnp4nagios/var/host-perfdata /usr/local/pnp4nagios/var/spool/host-perfdata.$TIMET$
    +}
    +
    + +

    +Using these commands the file service-perfdata will be moved to var/spool/ after the interval specified in service_perfdata_file_processing_interval has passed. The Nagios macro $TIMET$ is appended to the filename to avoid overwriting of old files unintentionally. The macro $TIMET$ contains the current timestamp in time_t format (seconds since the UNIX epoch). +

    + +

    +In the directory /usr/local/pnp4nagios/var/spool/ files are gathered to be processed by NPCD. +

    + +

    +NPCD monitors the spool directory and passes the file names to process_perfdata.pl. This way processing of performance data is completely decoupled from nagios. +

    + +

    +Before starting NPCD you have to check the paths to the spool directory and to process_perfdata.pl specified in the config file npcd.cfg. +The only thing that remains is to start NPCD. + +

    +
     /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +The option -d starts NPCD as a daemon in the background. +

    + +
    + +

    Bulk Mode with NPCD and npcdmod

    +
    + +

    + +Attention +Starting with Nagios 4 the internal structures have changed so the start of the module will fail. So far there are no plans to support Nagios 4. Please select any other of the modes. +

    + +

    + This mode uses the event broker module npcdmod.o. The flow of data is identical to “bulk mode with NPCD”. The internal perfdata routines of Nagios activated by the “*_perf_data_*” directives in nagios.cfg are *NOT* used anymore. The module npcdmod.o takes over the task of processing the data required by PNP. +

    + +

    +Pro: +

    +
      +
    • The perfdata routines can now be used for other addons.
      +
    • +
    • The configuration is easier.
      +
    • +
    • It is the preferred mode of the PNP developers.
      +
    • +
    + +

    + +Adjustments in nagios.cfg: +

    +
    +process_performance_data=1
    +broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +
    + +

    +All other directives mentioned on this page must NOT be used. +

    + +

    +Attention: If you have changed the value of event_broker_options from -1 to another value then please note that PNP needs the bits 2 and 3 set (0b01100). Make sure that the resultung value has these bits set because otherwise there will be no performance data to process. +

    + +

    +After restarting Nagios information regarding the start of the module will be logged. +

    + +

    +Excerpt from nagios.log + +

    +
    +[1277545053] npcdmod: Copyright (c) 2008-2009 Hendrik Baecker (andurin@process-zero.de) - http://www.pnp4nagios.org
    +[1277545053] npcdmod: /usr/local/pnp4nagios/etc/npcd.cfg initialized
    +[1277545053] npcdmod: spool_dir = '/usr/local/pnp4nagios/var/spool/'.
    +[1277545053] npcdmod: perfdata file '/usr/local/pnp4nagios/var/perfdata.dump'.
    +[1277545053] npcdmod: Ready to run to have some fun!
    +[1277545053] Event broker module '/usr/local/pnp4nagios/lib/npcdmod.o' initialized successfully.
    +
    + +
    + +

    Gearman Mode

    +
    + +

    + + +

    + +

    +Since version 0.6.12 PNP4Nagios can be driven as a gearman worker. This way large Nagios environments are possible using mod_gearman. Nagios and PNP4Nagios can be run on different machines. +

    + +

    +You need a mod_gearman environment up and running like described by Sven Nierlein on http://labs.consol.de/lang/en/nagios/mod-gearman/. +

    + +

    +You'll find a section on gearman in etc/process_perfdata.cfg: + +

    +
    PREFORK = 1
    +GEARMAN_HOST = localhost:4730
    +REQUESTS_PER_CHILD = 10000
    +ENCRYPTION = 1
    +KEY = should_be_changed
    +#KEY_FILE = /usr/local/pnp4nagios/etc/secret.key
    + +

    + +Using PREFORK = <n> you specify the number of child processes. +

    + +

    +GEARMAN_HOST = <host>:<port> specifies host and port of the server running the gearman daemon providing the data. +

    + +

    +REQUEST_PER_CHILD = <n> enables you to define the number of requests processed per process. +

    + +

    +ENCRYPTION = <n> specifies whether to use encryption (“1”) or not. Default is an activated encyrption which should be changed only in special cases. You can either use KEY = <key phrase> or 'KEYFILE =<key file> to specify the location of a file containing the key phrase. + +etc/init.d/pnp_gearman_worker start contains links to the perl script process_perfdata.pl and the config file process_perfdata.cfg''. +

    + +

    +After starting the daemon process using + +

    +
     /etc/init.d/pnp_gearmon_worker start
    + +

    + +the performance data will be processed which is provided by the gearmand daemon on the Nagios server. +

    + +

    +back to contents | checking the functionality + +

    + +
    + +
    +
    + + + +

    Checking the installation

    +
    + +

    + +If everything went well until now you can try to call PNP using your web browser. +When using the installation with default values PNP should be called using http://<server name>/pnp4nagios/. +The first time you will see a page “PNP4Nagios Environment Tests” which includes different checks of necessary components. Obviously all checks have to be passed successfully before you can proceed. Please follow the instructions given on that page.
    + +

    + +

    +If all tests have passed *successfully* the file pnp4nagios/share/install.php can be deleted or renamed. Not till then the web interface is reachable. +

    + +

    +Alternatively you can create a file called pnp4nagios/share/install.ignore which will prevent the call of the installer after further updates. +

    + +

    +If you receive the message “PHP magic_quotes_gpc is deprecated” then please locate your php.ini and set the value to Off. +

    + +

    +Called without any arguments PNP looks for RRD and XML files in pnp4nagios/var/perfdata and shows all graphs of the first host. +

    + +

    +ATTENTION: Immediately after (re-)starting Nagios after you enabled the processing of performance data you will get error messages in your browser because performance data has to be collected and stored in RRD files. Depending on the check interval you are using you have to wait some time before you can view the first graphs. +

    + +
    + +

    Debug Logfile

    +
    + +

    + +Calling make install-config during installation will create a sample config file etc/process_perfdata.cfg-sample. The values in the sample file will correspond to the defaults used by process_perfdata.pl so normally you do not have a file called process_perfdata.cfg while running the procedure.
    + +However you can influence the way process_perfdata.pl works by changing options which have to be specified in process_perfdata.cfg. +

    + +

    +The most important options launching PNP are LOG_LEVEL and LOG_FILE. We recommend setting the LOG_LEVEL value to “2” so you can track what process_perfdata.pl will do. +Most likely we will ask for excerpts from perfdata.log if you open a support request on the mailing lists as well as the output of the verify_pnp_config script so please provide them ;-). +

    + +

    +During normal operation the debug level should be set to 0 to avoid performance issues due to unnecessary entries in the log file. +

    + +
    + +

    Something went wrong

    +
    + +

    + +Some basic settings should be checked +

    + +

    +1. Have any RRD and XML files been created? +process_perfdata.pl will create a new directory under pnp/perfdata for every host. In this directory an RRD database and an XML file will be created for every service. The host data will be stored in _HOST_.xml and _HOST_.rrd respectively.
    + +If graphing stops out of a sudden then open the appropriate XML file. There are two tags called <RC> and <TXT>. <RC> shows the return code of the RRDtool update and <TXT> a textual description.
    + +Sometimes you have to specify additional options so that performance data is produced. In some cases a wrapper script might help.
    + +However not all checks provide performance data. That applies - among others - to “check_ping” in contrast to “check_icmp” which does provide data (starting with Nagios plugin version 1.4.12 check_ping does provide performance data).
    + +Using the web interface the detail information of hosts/services shows a field “Performance Data”. If it is empty there is no data available so no files are written to the appropriate directory and that is why PNP does not provide you with graphs!
    + +The following image shows the information of a “PING” service. The output of the plugin is surrounded by a blue border, the performance data by a red one.
    + +status information +

    + +

    +2. Has nagios called process_perfdata.pl? +In the config file for process_perfdata.pl (etc/process_perfdata.cfg) you can increase the debug level. Data processing will be logged in var/perfdata.log. +

    + +

    +3. Graphs are shown without text? +Have a look at the requirements. +

    + +

    +4. Some graphs are shown, others report the error “parser error: Input is not proper UTF-8” or something similar. Please check if your data contains “special” characters not present in the ASCII set. Try to set XML_ENC in process_perfdata.cfg to ISO-8859-1 or something appropriate. Wait until the xml file is newly created and retry. +

    + +

    +5. Using the npcdmod module the value of the nagios.cfg directive event_broker_options may have to be adapted if it was modified. You'll find some details here. +

    + +

    +6. You can use the script verify_pnp_config.pl after installation to check your settings and if performance data is present. +

    + +

    +7. Things look OK, but some files are being left in the spool directory (/usr/local/pnp4nagios/var/spool/<perfdata_filename>-PID-<process_perfdata_pid>). If process_perdata.pl is not able to write to the destination directory (/usr/local/pnp4nagios/share/perfdata/<host>), it will stop and not remove the file. That will increase the size of the spool directory and slow down performance data processing. This problem is likely to occur if you have copied directories from a previous installation and/or manually created directories and left them with wrong permissions or wrong ownership. +

    + +

    +back to contents | verify_pnp_config.pl + +

    + +
    + +
    +
    + + + +

    verify_pnp_config

    +
    + +

    + +In case of problems there is a script called verify_pnp_config.pl located on http://verify.pnp4nagios.org. It enables you to check the configuration settings as well as performance data of hosts or services. It can be used prior and during runtime of PNP. +

    + +
    + +

    Download

    +
    +
    +wget http://verify.pnp4nagios.org/verify_pnp_config
    +
    + +
    + +

    Test

    +
    + +

    + +The verify script is located on http://verify.pnp4nagios.org and needs three start options +

    +
      +
    • --mode One of the modes described on modes
      +
    • +
    • --config Location of nagios.cfg or icinga.cfg
      +
    • +
    • --pnpcfg Path to PNP´s etc directory
      +
    • +
    + +

    + +Calling perl verify_pnp_config will show the available options. +

    + +

    +The following is a sample run + +

    +
    +lenny:~# perl verify_pnp_config --mode npcdmod --config=/usr/local/nagios/etc/nagios.cfg --pnpcfg=/usr/local/pnp4nagios/etc
    +[INFO]  ========== Starting Environment Checks ============
    +[INFO]  My version is: verify_pnp_config-0.6.14-R.31
    +[INFO]  Reading /usr/local/nagios/etc/nagios.cfg
    +[OK  ]  Running product is 'nagios'
    +[OK  ]  object_cache_file is defined
    +[OK  ]  object_cache_file=/usr/local/nagios/var/objects.cache
    +[INFO]  Reading /usr/local/nagios/var/objects.cache
    +[OK  ]  resource_file is defined
    +[OK  ]  resource_file=/usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/process_perfdata.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/pnp4nagios_release
    +[OK  ]  Found PNP4Nagios version "0.6.14"
    +[OK  ]  Effective User is 'nagios'
    +[OK  ]  User nagios exists with ID '1000'
    +[OK  ]  Effective group is 'nagios'
    +[OK  ]  Group nagios exists with ID '1000'
    +[INFO]  ========== Checking npcdmod Mode Config  ============
    +[OK  ]  process_performance_data is 1 compared with '/1/'
    +[OK  ]  event_broker_options is defined
    +[OK  ]  event_broker_options=-1
    +[OK  ]  event_broker_option bits 2 and 3 enabled (12)
    +[OK  ]  broker_module is defined
    +[OK  ]  broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  npcdmod.o config file is /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg used by npcdmod.o is readable
    +[OK  ]  npcd daemon is running
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg is used by npcd and readable
    +[OK  ]  npcd and npcdmod.o are using the same config file (/usr/local/pnp4nagios/etc/npcd.cfg)
    +[INFO]  Nagios config looks good so far
    +[INFO]  ========== Checking config values ============
    +[INFO]  Reading /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  Script /usr/local/pnp4nagios/libexec/process_perfdata.pl is executable
    +[INFO]  ========== Starting global checks ============
    +[OK  ]  status_file is defined
    +[OK  ]  status_file=/dev/shm/status.dat
    +[INFO]  Reading /dev/shm/status.dat
    +[INFO]  ==== Starting rrdtool checks ====
    +[OK  ]  RRDTOOL is defined
    +[OK  ]  RRDTOOL=/usr/bin/rrdtool
    +[OK  ]  /usr/bin/rrdtool is executable
    +[OK  ]  RRDtool 1.3.1  Copyright 1997-2008 by Tobias Oetiker <tobi@oetiker.ch>
    +[OK  ]  USE_RRDs is defined
    +[OK  ]  USE_RRDs=1
    +[OK  ]  Perl RRDs modules are loadable
    +[INFO]  ==== Starting directory checks ====
    +[OK  ]  RRDPATH is defined
    +[OK  ]  RRDPATH=/usr/local/pnp4nagios/var/perfdata
    +[OK  ]  Perfdata directory '/usr/local/pnp4nagios/var/perfdata' exists
    +[WARN]  62 hosts/services are not providing performance data
    +[WARN]  'process_perf_data 1' is set for 43 hosts/services which are not providing performance data!
    +[WARN]  'process_perf_data 0' is set for 27 of your hosts/services
    +[OK  ]  'process_perf_data 1' is set for 243 of your hosts/services
    +[INFO]  ==== System sizing ====
    +[OK  ]  269 hosts/service objects defined
    +[INFO]  ==== Check statistics ====
    +[WARN]  Warning: 3, Critical: 0
    +[WARN]  Checks finished...
    +
    + +
    + +

    Performance data

    +
    + +

    +Starting with 0.6.19-R.37 (2013-02-17) the script will accept the option --object (or -o) followed by a string to specify a host name and/or service description to additionally show performance data (if any) of the object(s) found. The data is enclosed in brackets, followed by the value of the directive process_performance_data (ppd=n). +

    + +

    +host = show performance information for host host
    + +;service = show performance information for service service
    + +host;service = show performance information for service service on host host +

    + +

    +The strings are taken as regular expressions (perl syntax). + +

    + +
    + +
    +
    + + + +

    Nagios web frontend

    +
    + +

    +Of course PNP should be easily accessible. You do not want to search long for the right graph. +

    + +

    +Nagios itself features external URLs using so called extended info configs. Due to changes between Nagios 2.x and Nagios 3.x both versions are described. +

    + +
    + +

    Nagios 2.x

    +
    + +

    + +With Nagios 2.x the integration of external URLs into the nagios web interface is made using Extended Info Objects for services. For PNP we use the directive action_url to call the PNP web frontend with the appropriate options. +

    +
    +define serviceextinfo {
    +   host_name             localhost
    +   service_description   load
    +   action_url            /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +}
    +
    + +

    +You have to specify an additional Extended Info Definition for every service. +

    + +
    + +

    Nagios 3.x

    +
    + +

    + +Since nagios 3.0 the action_url-directive has be moved to the host or service definition. This way the definition of URLs to the PNP-interface has been simplified. The serviceextinfo and hostextinfo definitions are deprecated. +

    + +

    +First two nagios templates are defined. If you used the Nagios quickstart installation guides you can append these lines to templates.cfg: +

    +
    +define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    +
    + +

    +These two templates can now be included via “use srv-pnp” or “use host-pnp” for services and hosts respectively. If you used the quickstart installation guide you might for example edit the file localhost.cfg and add the template to the host or service definition as follows: +

    +
    define host{
    +        use                     linux-server,host-pnp    ; Name of host templates to use
    +                                                         ; This host definition will inherit all variables that are defined
    +                                                         ; in (or inherited by) the linux-server host template definition.
    +        host_name               localhost
    +        alias                   localhost
    +        address                 127.0.0.1
    +        }
    +
    +
    define service{
    +        use                     local-service,srv-pnp   ; Name of service template to use
    +        host_name               localhost
    +        service_description     PING
    +        check_command           check_ping!100.0,20%!500.0,60%
    +        }
    +
    + +

    + +The links to the correct URLs are created automagically.
    +
    + +

    + +

    +Tips: if you want to open the PNP window in your main frame (on the right of the menu) instead of a new page, just set action_url_target=main in your nagios cgi.cfg +

    + +
    + +

    Popups

    +
    + +

    +You can integrate PNP into Nagios in a way that you have current graphs without clicking any icons. This can be accomplished using the CGI Includes which allow us to include JavaScript code in the status detail view ( status.cgi ). +

    + +

    +Prerequisites: +

    +
      +
    • PNP is installed and running
      +
    • +
    • the file status-header.ssi from the contrib/ssi/ folder of the PNP package was copied to /usr/local/nagios/share/ssi/.
      +Attention: This file must NOT be executable. Otherwise it will be treated as a CGI which will result in an error.
      +*Note to Apache admins*: Apache ssi and Nagios ssi only have a similar name.
      +
    • +
    • the appropriate service definition(s) has/have been modified. Please note that until Nagios 2.x you have to modify the serviceextinfo definition (which is deprecated starting with Nagios 3).
      +
    • +
    + +

    + +Definition: + +

    +
    +define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    +
    + +

    + +After a restart of Nagios (after modifying the definitions) the result might look like this:
    + + +

    + +

    +back to contents | config options + +

    + +
    + +
    +
    + + + +

    PNP Web Frontend

    +
    + +

    + +The behaviour of the PNP Web-Frontend can be controlled through the config file etc/config.php. This file will be overwritten during updates of PNP as the paths and options are detected during ./configure. +

    + +

    +Own adjustments should be made in etc/config_local.php. If this file does not exist the file config.php can be taken as a guideline. +

    + +
    + +

    etc/config.php

    +
    + +

    + +Following the most important parameters: +

    + +

    +The path to the RRDtool binary. Will be detected by ./configure + +

    +
     $conf['rrdtool'] = "/usr/bin/rrdtool";
    + +

    + +Height and width of the RRD graphs + +

    +
     $conf['graph_width'] = "500";
    + $conf['graph_height'] = "100";
    + +

    + +Screen sizes may vary, pages sizes won't. The following two directives enable you to specify different sizes for the creation of PDFs. If they aren't specified the values of the graph sizes are taken. + +

    +
     $conf['pdf_width'] = "675";
    + $conf['pdf_height'] = "100";
    + +

    + +Additional options passed with every call of RRDTool, for example --slope-mode to smooth the graphs + +

    +
     $conf['graph_opt'] = "";
    + +

    + +The path to the RRD and XML files created by process_perfdata.pl + +

    +
     $conf['rrdbase'] = "/usr/local/pnp4nagios/var/perfdata/";
    + +

    + +The path to the config file for the pages. + +

    +
     $conf['page_dir'] = "/usr/local/pnp4nagios/etc/pages/";
    +
    + +

    +PNP pages will be refreshed every n seconds + +

    +
     $conf['refresh'] = "90";
    +
    + +

    +Max. age of RRD files in seconds. After reaching this value links to the graphs will be marked as inactive + +

    +
     $conf['max_age'] = 60*60*6;
    +
    + +

    + +Base URL to the Nagios CGIs + +

    +
     $conf['nagios_base'] = "/nagios/cgi-bin";
    +
    + +

    + +List of users who are allowed to view links to the services of the current host + +

    +
     $conf['allowed_for_service_links'] = "EVERYONE";
    +
    + +

    +List of users who can view/access the host search field + +

    +
     $conf['allowed_for_host_search'] = "EVERYONE";
    +
    + +

    +If PNP is called with a host only ( index.php?host=<myserver> ), the defined user is shown an overview of all services related to this host + +

    +
     $conf['allowed_for_host_overview'] = "EVERYONE";
    +
    + +

    +The periods of time the RRD graphs will show are determined using the array $views[]. The title and number of graphs can be specified globally in this place +

    +
    +$views[] = array('title' => 'One Hour',  'start' => (60*60) );
    +$views[] = array('title' => '4 Hours',   'start' => (60*60*4) );
    +$views[] = array('title' => '25 Hours',  'start' => (60*60*25) );
    +$views[] = array('title' => 'One Week',  'start' => (60*60*25*7) );
    +$views[] = array('title' => 'One Month', 'start' => (60*60*24*32) );
    +$views[] = array('title' => 'One Year',  'start' => (60*60*24*380) );
    +
    + +

    +You can add more views ($views[5], …) but please keep in mind that under normal circumstances ALL views you defined are shown. +

    + +

    +back to contents | timeranges + +

    + +
    + +
    +
    + + + +

    Timeranges

    +
    + +

    + +In the overview PNP shows five timeranges which can be defined in config.php. +

    + +

    +Additionally you can influence the timeranges via the URL. This can be useful to automatically create PDF documents. The ranges can be defined using the options “start” and “end”. +

    + +

    +Example: + +

    +
     pnp4nagios/graph?host=<hostname>&srv=<servicedesc>&start=-1week
    + +

    + +The graph will start one week prior to the current date and time. It will end at the current timestamp. + +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    start end view result
    all views ending at current timestamp
    x all views starting at defined date
    x all views ending at defined date
    x x one view between the two dates
    x one view ending at current timestamp
    x x one view starting at defined date
    x x one view ending at defined date
    + +

    +Examples of different specifications + +

    + + + + + + + + + + + + + + + + + + + + + + +
    format description
    2009W04 4. week of 2009
    1.5.2009 May, 1st 2009
    -1 day one day back
    -3 weeks 3 weeks back
    -1 year one year back
    yesterday yesterday
    + +

    +back to contents | pages + +

    + +
    + +
    +
    + + + +

    Pages

    +
    + +

    + +“pages” provide the opportunity to collect graphs of different hosts/services on one page. That way - as an example - you can display the traffic rates of all tape libraries. Regular expressions are possible so you can accomplish a lot with only few definitions - provided that you have appropriate names. +The directory specified using “$conf['page_dir']” contains one or more file with the extension ”.cfg”. +

    + +

    +Comments start with a hash-sign (#) and are possible within lines as well. Each file contains a “page” definition which specifies the name of the page and it determines whether the following graph definition contains regular expressions or not.
    + +The description behind page_name appears in the list of available pages and will be used as title of the browser window. Attention: “host_name” and “service_desc” refer to the name of the file in the perfdata directory, not to the definition in Nagios. Blanks are replaced by underscores (_). +

    +
    define page {
    +       use_regex 1		# 0 = use no regular expressions, 1 = use regular expressions
    +       page_name test-page	# page description
    +}
    + +

    +One or more “graph” definitions follow: +

    +
    define graph {
    +       host_name       host1,host2,host3
    +       service_desc    Current_Load
    +}
    + +

    + +Attention: The list of host name will only work if you use regex 0! +

    +
    define graph {
    +       host_name       host4
    +       service_desc    Current_Users
    +}
    + +

    +And now some definitions with regular expressions. At first all hosts whose names are starting with “Tape”: + +

    +
    define graph {
    +       host_name       ^Tape
    +       service_desc    Traffic
    +}
    + +

    +all hosts whose names are ending with “00”: + +

    +
    define graph {
    +       host_name       00$
    +       service_desc    Load
    +}
    + +

    +all services of localhost whose names contain “a” or “o”, respectively: + +

    +
    define graph {
    +       host_name       localhost
    +       service_desc    a|o
    +}
    + +

    +all services whose names contain an underscore followed by (at least) three digits on all hosts whose names start with “UX”: + +

    +
    define graph {
    +       host_name       ^UX
    +       service_desc    _\d{3}
    +}
    + +

    +In some cases you may want to limit the display to just one graph. To accomplish this you can use the optional directive “source” followed by a number specifying the position within the RRD file starting at 0 + +

    +
    define graph {
    +       host_name       host1,host2,host3
    +       service_desc    PING
    +       source          1
    +}
    + +

    +back to contents | data export + +

    + +
    + +
    +
    + + + +

    Data export

    +
    + +

    + +PNP provides access to RRD data using the xport controller. The output format can be specified. At the moment the formats xml, json and csv are supported. +

    + +

    +The controller can be called using the URL + +

    +
    /pnp4nagios/xport/<format>?host=<hostname>&srv=<servicedesc>
    + +

    + +whereas <format> has to be replaced with the desired format. +

    + +

    + +You can also use wget to generate images and place them in periodic reports. One example may be: +

    +
    wget -O image.png 'http://<user>:<pass>@<nagios-server>/pnp4nagios/image?host=<hostname>&srv=<service>&view=2&source=0'
    + +

    +view=<n> limits the graph to the timeperiod specified in config.php
    + +source=<n> only shows one data source if you have more than one in your RRD file +

    + +

    +Instead of view you can use start and/or end to specify the time period. For details please look at "time ranges". +

    + +

    +back to contents | templates + +

    + +
    + +
    +
    + + + +

    What are templates?

    +
    + +

    + +PNP uses templates to influence the appearance of RRD graphs. +

    + +

    +The selected check_command determines which template will be used to control the graph. Following will be described where templates are stored and how the decision for the “right” template is made. +

    + +
    + +

    What template will be used when?

    +
    + +

    + +Templates are stored at two places in the file system. + +

    +
      +
    • share/templates.dist - for templates included in the PNP package
      +
    • +
    • share/templates - for custom made templates which are not changed during updates
      +
    • +
    + +

    + +If the graph for the service “http” on host “localhost” should be shown, PNP will look for the XML file perfdata/localhost/http.xml and read its contents. The XML files are created automatically and contain information about the particular host and service. The header contains information about the plugin and the performance data. The XML tag <TEMPLATE> identifies which PNP template will be used for this graph. +

    + +

    +/localhost/http.xml + +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>2</DS>
    +    <NAME>size</NAME>
    +    <UNIT>B</UNIT>
    +    <ACT>263</ACT>
    +    <WARN></WARN>
    +    <CRIT></CRIT>
    +    <MIN>0</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +...
    +</NAGIOS>
    + +

    +PNP will append .php to the string and therefore look for a template with the name check_http.php in the following sequence: + +

    +
      +
    1. templates/check_http.php
      +
    2. +
    3. templates.dist/check_http.php
      +
    4. +
    5. templates/default.php
      +
    6. +
    7. templates.dist/default.php
      +
    8. +
    + +

    + +The template default.php takes an exceptional position as it is used every time no other applicable template is found. +

    + +
    + +

    Creating own templates

    +
    + +

    + +PNP templates are PHP files which are included during execution of PNP using the PHP function include(). This means that every PHP code in templates will be interpreted so manipulation of all values is possible. +

    + +

    +PNP template must have the following characteristics: + +

    +
      +
    1. templates must contain valid PHP code.
      +
    2. +
    3. templates must not create any output.
      +
    4. +
    5. the two arrays $opt[] and $def[] have to be filled
      +
    6. +
    + +

    + +These two arrays are used to call 'rrdtool graph' so every option is possible that RRDtool supports. All options of RRDtool are described very thoroughly on the RRDtool Homepage. +

    + +

    +If both arrays contain more than one set of data graphs will be created for every set. +

    + +

    +Inside the templates the data from the related XML files can be used. +

    + +

    +Using the relatively simple template response.php we will describe the most important options. +

    +
    <?php
    +#
    +$opt[1] = "--title \"Response Time For $hostname / $servicedesc\" ";
    +#
    +$def[1] =  "DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE " ;
    +$def[1] .= "AREA:var1#00FF00:\"Response Times \" " ;
    +$def[1] .= "LINE1:var1#000000 " ;
    +$def[1] .= "GPRINT:var1:LAST:\"%3.4lg %s$UNIT[1] LAST \" ";
    +$def[1] .= "GPRINT:var1:MAX:\"%3.4lg %s$UNIT[1] MAX \" ";
    +$def[1] .= "GPRINT:var1:AVERAGE:\"%3.4lg %s$UNIT[1] AVERAGE \" ";
    +?>
    + +

    +Note: as the number (1) and the letter “L” look alike in this listing: the format ”%3.4lg” contains a small letter. +

    + +

    +$opt[1] = ”--title … sets RRDtool options for the first set of data, here the title as you can see. Embedded quotes are masked using a backslash (\). The variables $hostname and $servicedesc were determined through the call of PNP and are available for the template as well. +

    + +

    +$def[1] = “DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE ”; defines which data is to be read from which RRD file. $RRDFILE[1] contains the path to the RRD file of this service. $DS[1] refers to the first data series from the RRD file. +

    + +

    +$def[1] .= “AREA:var1#00FF00:\”Response Times \” ”; the operator ”.=” appends more data to the array $def[1]. An area will be drawn using data from the variable var1. The color is defined in HEX notation #00FF00 (red, green, blue). The label is “Response Times”. +

    + +

    +$def[1] .= “LINE1:var1#000000 ”; As completion of the just drawn area a line (LINE1) will be drawn in black (#000000). +

    + +

    +$def[1] .= “GPRINT:var1:LAST:\”%3.4lg %s$UNIT[1] LAST \” ”;
    + +$def[1] .= “GPRINT:var1:MAX:\”%3.4lg %s$UNIT[1] MAX \” ”;
    + +$def[1] .= “GPRINT:var1:AVERAGE:\”%3.4lg %s$UNIT[1] AVERAGE \” ”;
    +

    + +

    +The three GPRINT lines build up the caption for the graph. The current values are formatted using the printf syntax. +

    + +
    + +

    Available variables

    +
    + +

    + +Using the data collector process_perfdata.pl PNP stores not only performance data but other values exported by Nagios. These values are stored in the XML file associated to the appropriate service. +

    + +

    +In the first part of the XML file the performance data is stored in separate components. +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +....
    +</NAGIOS>
    + +

    +The field <DS> designates the data source and is used to identify the data series of the RRD files and is the key of the following arrays as well. +

    + +

    +The array $UNIT[1] contains the unit of measurement of the first data series. +

    + +

    +The XML file contains other information. When process_perfdata.pl is used in default mode all available macros are at hand with the current values. For the benefit of readability the following lines show only an extract. +

    +
    <NAGIOS>
    +...
    +  <NAGIOS_SERVICENOTIFICATIONID>8418</NAGIOS_SERVICENOTIFICATIONID>
    +  <NAGIOS_SERVICENOTIFICATIONNUMBER>0</NAGIOS_SERVICENOTIFICATIONNUMBER>
    +  <NAGIOS_SERVICEOUTPUT>HTTP OK HTTP/1.1 200 OK - 10087 bytes in 0.125 seconds</NAGIOS_SERVICEOUTPUT>
    +  <NAGIOS_SERVICEPERCENTCHANGE>0.00</NAGIOS_SERVICEPERCENTCHANGE>
    +  <NAGIOS_SERVICEPERFDATA>time=0.124811s;;;0.000000 size=10087B;;;0</NAGIOS_SERVICEPERFDATA>
    +  <NAGIOS_SERVICEPERFDATAFILE></NAGIOS_SERVICEPERFDATAFILE>
    +  <NAGIOS_SERVICEPROBLEMID>0</NAGIOS_SERVICEPROBLEMID>
    +  <NAGIOS_SERVICESTATE>OK</NAGIOS_SERVICESTATE>
    +  <NAGIOS_SERVICESTATEID>0</NAGIOS_SERVICESTATEID>
    +  <NAGIOS_SERVICESTATETYPE>HARD</NAGIOS_SERVICESTATETYPE>
    +  <NAGIOS_SHORTDATETIME>27-12-2007 13:51:23</NAGIOS_SHORTDATETIME>
    +...
    +</NAGIOS>
    + +

    +The various XML fields can be used as variables in the PNP templates. Each field is available as a variable with the same name. +

    + +

    +The value of the field <NAGIOS_SERVICEOUTPUT> is available as the variable $NAGIOS_SERVICEOUTPUT. +

    + +

    +back to contents | custom templates + +

    + +
    + +
    +
    + + + +

    Custom Templates

    +
    + +

    + +As already described under ”What are templates ?” the appearance of graphs depends on the check command used. +

    + +

    +There are situations where this behaviour must be overruled, for example when universal commands have been defined. +

    + +

    +PNP, especially process_perfdata.pl, will search for a config file (<check_command>;.cfg) in the etc/check_commands directory and read its contents (if available). +The following options can be defined in it: +

    + +
    + +

    CUSTOM_TEMPLATE

    +
    + +

    + +Outgoing from the following example of a Nagios command-definition: + +

    +
    +define command {
    +  command_name check_nrpe
    +  command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ -a "$ARG2$"
    +}
    +
    + +

    +This would lead to a call of the check_nrpe.php template even when the monitored host would use a completely different plugin which is called via NRPE. +

    + +

    +As our example command is called check_nrpe it will be searched for etc/check_commands/check_nrpe.cfg. +

    + +

    +During installation a sample config file with the extension .cfg-sample is copied to etc/check_commands. +

    +
    +# check_command check_nrpe!load!-w 4,4,4 -c 5,5,5
    +# ________0__________|       |       |
    +# ________1__________________|       |
    +# ________2__________________________|
    +#
    +CUSTOM_TEMPLATE = 1
    +
    + +

    +CUSTOM_TEMPLATE = 1 assures that only the contents of $ARG1$ will be used as a template name. As $ARG1$ contains “load” in this example the template name would result in “load.php”. +

    + +

    +CUSTOM_TEMPLATE = 0,1 results in → “check_nrpe_load.php” +

    + +

    +CUSTOM_TEMPLATE = 1,0 results in → “load_check_nrpe.php” +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    DATATYPE

    +
    + +

    + +The option “DATATYPE” controls the datatype which is used during creation of the RRD database. Default is “GAUGE”. For consecutive values the type should be “COUNTER”. Plugin-developers should use the unit “c” for counters but this is not always the case. +

    + +

    +To set all datasources to COUNTER + +

    +
    DATATYPE = COUNTER
    + +

    +Setting datasources to different types + +

    +
    DATATYPE = GAUGE,GAUGE,COUNTER,COUNTER
    + +

    +More datatypes are explained in the RRDTool documentation found at rrdcreate. +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    USE_MIN_ON_CREATE and USE_MAX_ON_CREATE

    +
    + +

    + +In a few situations it might be necessary to limit the values which are valid for RRDTool. +

    + +

    +RRD databases can be created with fixed minimum and maximum values. You will find further details at http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html. +

    + +

    +Account for the maximum value taken from the performance data + +

    +
    USE_MAX_ON_CREATE = 1
    + +

    +Account for the minimum value taken from the performance data + +

    +
    USE_MIN_ON_CREATE = 1
    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    RRD_STORAGE_TYPE

    +
    +
    RRD_STORAGE_TYPE = SINGLE
    + +

    + +The option RRD_STORAGE_TYPE defines the kind of data storage. +

    + +

    +Possible values are MULTIPLE and SINGLE, respectively. +

    + +

    +SINGLE: A RRD database per service +

    + +

    +MULTIPLE: One or more RRD databases per service. Each datasource will be stored in a separate RRD database. +

    + +

    +ATTENTION: The data will not be migrated automatically! +You will find a conversion script here. +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    RRD_HEARTBEAT

    +
    + +

    + +Starting with PNP 0.6.1 +

    +
    RRD_HEARTBEAT = 305
    + +

    +After <RRD_HEARTBEAT> seconds RRDtool expects new data. +

    + +

    +More information at http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    Hints on Template Names

    +
    + +

    + +In most situations, one can easily get desired template names, by using suitable command object definitions. +

    + +

    +Consider the followng example: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$
    +}
    +
    + +

    + +with commands like: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load -w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    +Even when using “CUSTOM_TEMPLATE = 1” one would end up in template names like “_usr_lib_nagios_plugins_check_load_-w_4,4,4_-c_5,5,5”, which is highly undesired, especially because of the parameters in it. +

    + +

    +Solution 1: Split parameters into separate $ARGn$ +

    + +

    +A simple solution is to use the following command object definition: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +with commands like: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +(notice the additional “!”) +

    + +

    +This even works, when $ARG2$ is let empty. +

    + +

    +Of course one would still need to set “CUSTOM_TEMPLATE = 1”. +

    + +

    + +Solution 2: Hide the remote executor inside the command object definition +

    + +

    +Another way is to “hide” the remote excutor in the respective command object definitions. +

    + +

    +Instead of defining: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +one would define the following for every command to be remotely executed: + +

    +
    +define command {
    +  command_name check_load_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ /usr/lib/nagios/plugins/check_load $ARG1$
    +}
    +
    + +

    + +with commands like: + +

    +
    +  …
    +  check_load_by_ssh!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +Of course one must not set “CUSTOM_TEMPLATE = 1” in this way. +

    + +

    + +Which of above two solutions one follows is largely a matter of taste. +

    + +

    +back to contents | PNP in distributed environments + +

    + +
    + +
    +
    + + + +

    Distributed Systems

    +
    + +

    +If Nagios is implemented as a distributed system you have to decide where PNP should be installed. +

    + +

    +From a technical view this question is not important. PNP can be installed on the slave(s) as well as on the master server. Or only on the master? +

    + +

    +If PNP is running on the master you have to make sure that data passed via send_nsca from the slave server(s) contains performance data. Often another check command is used on the master. +

    + +

    +To help PNP on the master to recognize which check command was used on the slave to collect the information process_perfdata.pl responds to an additional field at the end of the performance data. +

    +
    OK - 127.0.0.1: rta 2.687ms, lost 0% | rta=2.687ms;3000.000;5000.000;0; pl=0%;80;100;; [check_icmp]
    + +

    +If PNP finds a string enclosed in brackets at the end of performance data it will be recognized as check command and will be used as PNP template. +

    + +

    +Nagios documentation related to this topic can be found +here. The command used in the documentation can be adapted easily. +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$'
    +	}
    +
    + +

    +should be changed to +

    +
    +define command{
    +	command_name	submit_check_result
    +	command_line	/usr/local/nagios/libexec/eventhandlers/submit_check_result $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$ | $SERVICEPERFDATA$ [$SERVICECHECKCOMMAND$]'
    +	}
    +
    + +
    + +

    check_multi plugin

    +
    + +

    + +The plugin check_multi is one of the first plugins which uses new features of Nagios 3.x. Check_multi can execute multiple Nagios plugins but returns only results like a single service. The output of check_multi comprises of several lines to be able to display the amount of information. +

    + +

    +This results in some difficulties for PNP which has to extract the information of several plugins from the performance data. Together with Matthias Flacke, developer of check_multi, we have found a solution to assign the data to the appropriate plugins. +

    + +

    + +

    + +

    +back to contents | support of rrdcached + +

    + +
    + +
    +
    + + + +

    RRDtool Cache Daemon

    +
    + +

    + +In large installations sooner or later one will recognize that processing the performance data will result in a relatively high I/O load. RRDtool has to do very much disk updates but cannot use the disk cache in an optimal way. +

    + +

    +One improvement is made by collecting and sorting the data. It is more effective to write many updates to an RRD database in one block. The disk cache can be used more effectively that way. +

    + +

    +The current RRDtool ( SVN trunk 1550+ ) contains rrdcached which should improve exactly this situation. +

    + +

    +At this point I'd like to thank Florian octo Forster, Kevin Brintnall and Tobi Oetiker. The development of this daemon has been coordinated exemplary on the rrd-developers mailing list. +

    + +
    + +

    Mode of operation

    +
    + +

    + +The rrdcached is working as a daemon in the background and opens a UNIX or TCP socket to wait for requests of rrdtool. Due to security reasons newer versions of rrdcached cannot use absolute paths for network access anymore so the only possible way are unix sockets. +

    + +
    + +

    rrdcached

    +
    + +

    + +rrdcached recognizes some important options which are passed during startup. +

    + +

    +Option -l defines the socket the daemon will listen for update requests. The default TCP port will be 42217. +

    +
    +-l unix:/path/to/rrdcached.sock
    +-l /path/to/rrdcached.sock
    +-l 127.0.0.1
    +-l 127.0.0.1:8888
    +
    + +

    +Option -P specifies which commands are usable with the RRD data bases + +

    +
    -P FLUSH,PENDING
    + +

    +Option -s allows to change the group ownership of the unix socket +

    +
    -s nagios
    + +

    +Option -m sets the permissions of the unix socket in the usual octal format +

    +
    -m 0660
    + +

    +Option -w specifies the interval (in seconds) the data will be written to disk. +

    +
    -w 1800
    + +

    +Option -z defines a maximum delay which will be used to spread the write cycles over a certain range [0-delay] to avoid parallel write accesses. The value of option -z must not be larger than -w. +

    +
    -z 1800
    + +

    +Option -p defines a PID file +

    +
    -p /var/run/rrdcached.pid
    + +

    +Option -j defines the path to a journaling directory. All requests will be logged there so that they can be processed after a restart in case the daemon crashes. +

    +
    -j /var/cache/rrdcached
    + +

    +These options may result in a call of rrdcached with the following parameters +

    +
     rrdcached -w 1800 -z 1800 -p /tmp/rrdcached.pid -j /tmp  -s nagios -m 0660 -l unix:/tmp/rrdcached.sock
    + +
    + +

    rrdtool

    +
    + +

    + +RRDtool itself will be informed about the daemon using the option --daemon=<socket>. + +

    +
     rrdtool --daemon=unix:/tmp/rrdcached.sock update ...
    + +

    + +Of course this has to correspond with the options of rrdcached! +

    + +
    + +

    Integration into PNP

    +
    + +

    + +Because two components of PNP have to prepared for the use of rrdcached there are changes in two config files. +

    + +

    +1. Adjustment of process_perfdata.cfg for the data collector process_perfdata.pl +

    +
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +RRD_DAEMON_OPTS = unix:/var/run/rrdcached.sock
    +
    + +

    +2. Adjustment of config_local.php (or config.php) for the web interface +

    +
    +#
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +# $conf['RRD_DAEMON_OPTS'] = 'unix:/tmp/rrdcached.sock';
    +$conf['RRD_DAEMON_OPTS'] = 'unix:/var/run/rrdcached.sock';
    +
    + +

    +The sample files contain the relevant options. +

    + +

    +back to contents | migrating RRD files + +

    + +
    + +
    +
    + + + +

    NPCD

    +
    + +

    + +NPCD (Nagios-Perfdata-C-Daemon) was written to provide an asynchronous mode to handle performance data with nagios. +

    + +
    + +

    Introduction

    +
    + +

    + +In large nagios installations, your average check latency may increase to a non-acceptable high value. This means that Nagios should do a check at time x but actually does it y seconds later. +

    + +

    +If you tell the Nagios core that you want to process the performance data after every single check this is doing well for a certain amount of checks but above this limit you will run into latency problems. +

    + +

    +To reduce the number of actions for each check you can use the Bulk Mode which gathers performance data for some time and then lets the Nagios core execute the <host|service>_perfdata_file_processing_command or you can tell Nagios to just move the perfdata_files to a spool directory. +

    + +

    +This move is a very fast action for the Nagios core and the core will be done with the processing of performance data and can continue to do what it should do: execute other checks, sending notifications, and so on. +

    + +
    + +

    How it works

    +
    + +

    + +As mentioned above the Nagios process has finished its work with moving the performance data file to a spool directory but this won't bring the data into the RRD files. +

    + +

    +For this task you can start npcd to have a look at the defined spool directory and start an action for every file which is found. +

    + +

    +After NPCD starts running it will build a list of filenames found in perfdata_spool_dir and starts new threads for every filename and executes the perfdata_file_run_cmd with the optional perfdata_file_run_cmd_arg as an additional argument. +

    + +

    +Since the perfdata files in the spool dir are in the same format as for the 'normal' bulk mode NPCD should execute process_perfdata.pl in Bulk Mode. +

    + +
    + +

    Advantages / Disadvantages

    +
    + +

    + +Pro: +

    +
      +
    • Performance improvements for Nagios
      +
        +
      • because the performance data processing is detached from the Nagios core it has more time for its own work.
        +
      • +
      +
    • +
    • no lost data
      +
        +
      • as long as Nagios writes perfdata files to the spool dir your data won't get lost if NPCD dies or you forgot to start it after a system reboot. NPCD will start with the first file found (they are sorted by the $TIME_T$ macro in chronological order) and update your RRD Files.
        +
      • +
      +
    • +
    + +

    + +Con: +

    +
      +
    • no real time processing of performance data
      +
        +
      • since there is a delay in writing the performance data files by Nagios (service_perfdata_file_processing_interval)
        +
      • +
      • another delay exists within NPCD which waits for up to 10 seconds after each directory scanning
        +
      • +
      +
    • +
    + +
    + +

    NPCD Config

    +
    + +

    + +You have to control NPCD with its own configuration file like the rolled out npcd.cfg-sample file. +

    + +

    +Just rename it to npcd.cfg to start NPCD like this: +

    +
    /usr/local/pnp4nagios/bin/npcd -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +or + +

    +
    /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +to run in Daemon Mode (background). +

    + +

    +Hint: +If you decide to not rename the config file, it might be overwritten by a future update of PNP. +

    + +
    + +

    npcd.cfg-sample

    +
    + +

    + +These are the essential configuration directives for NPCD: +

    +
    # Privilege Options
    +user = nagios
    +group = nagios
    +
    +# Logging Options
    +log_type = syslog
    +log_file = /usr/local/pnp4nagios/var/npcd.log
    +max_logfile_size = 10485760
    +log_level=0
    +
    +# Processing Options
    +perfdata_spool_dir = /usr/local/pnp4nagios/var/spool/
    +perfdata_file_run_cmd = /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +perfdata_file_run_cmd_args = -b
    +
    +# Thread Options
    +npcd_max_threads=5
    +
    +# greedy options
    +use_load_threshold = 0
    +load_threshold = 10.0
    +
    +# Process Options
    +pid_file=/var/run/npcd.pid
    +
    + +
    + +

    The directives

    +
    +
      +
    • Privilege Options
      +
        +
      • user <username>
        +
          +
        • NPCD tries to drop 'root' privileges to switch to this user.
          +
        • +
        • default: nagios
          +
        • +
        +
      • +
      • group <groupname>
        +
          +
        • NPCD tries to drop 'root' privileges to switch to this group.
          +
        • +
        • Default: nagios
          +
        • +
        +
      • +
      +
    • +
    • Logging Options
      +
        +
      • log_type <syslog> or <file>
        +
          +
        • Log type that is uses by NPCD
          +
        • +
        • Default: syslog
          +
        • +
        +
      • +
      • log_file </path/to/filename>
        +
          +
        • if log_type = file this will be the logfile used
          +
        • +
        • Default: /usr/local/pnp4nagios/var/npcd.log
          +
        • +
        +
      • +
      • max_logfile_size <bytes>
        +
          +
        • NPCD will rotate the logfile if the filesize of the current log is above this limit
          +
        • +
        • Default: 10485760 = 10 MByte
          +
        • +
        +
      • +
      • log_level <integer>
        +
          +
        • how much to log, possible values:
          +
            +
          • 0 = No Log - except errors
            +
          • +
          • 1 = small Log - some more output
            +
          • +
          • 2 = more Log (actual ALL log messages)
            +
          • +
          • -1 = DEBUG Mode - ALL Logs and slower processing for debugging purposes
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      +
    • +
    • Processing Options
      +
        +
      • perfdata_spool_dir </path/to/spool/dir/>
        +
          +
        • The directory where the perfdata file should be found
          +
        • +
        • Default: /usr/local/pnp4nagios/var/spool/
          +
        • +
        +
      • +
      • perfdata_file_run_cmd </path/to/bin/filename>
        +
          +
        • This is the script/binary that NPCD will execute
          +
        • +
        • Default: /usr/local/pnp4nagios/libexec/process_perfdata.pl
          +
        • +
        +
      • +
      • perfdata_file_run_cmd_args <option>
        +
          +
        • The argument added to the perfdata_file_run_cmd
          +
        • +
        • Default: ”-b”
          +
        • +
        • :!: The command line will be created like this:
          <perfdata_file_run_cmd> <perfdata_file_run_cmd_args> <filename_from_perfdata_spool_dir>
          +
          +
        • +
        +
      • +
      +
    • +
    • Thread Options
      +
        +
      • npcd_max_threads <integer value>
        +
          +
        • Defines how many parallel threads should be started
          +
        • +
        • Default: 5
          +
        • +
        +
      • +
      +
    • +
    • Greedy Options
      +
        +
      • use_load_threshold <0 or 1>
        +
          +
        • defines if NPCD should _not_ start new threads if your system load is too high
          +
            +
          • 0 = disable
            +
          • +
          • 1 = enable
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      • load_threshold <float value>
        +
          +
        • if use_load_threshold is set to 1 this load limit must not be exceeded
          +
        • +
        • Default: 10.0
          +
        • +
        +
      • +
      +
    • +
    • Process Options
      +
        +
      • pid_file </path/to/pid.file>
        +
          +
        • the path to the PID File
          +
        • +
        • Default: /var/run/npcd.pid
          +
        • +
        +
      • +
      +
    • +
    + +

    + +back to contents | wrapper script + +

    + +
    + +
    +
    + +

    +check_procs is an example for a plugin which doesn't deliver performance data: +

    +
    ./check_procs -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'
    + +

    +This can be changed with the following wrapper script +

    + +

    +check_procs.sh + +

    +
    #!/bin/bash
    +LINE=`/usr/local/nagios/libexec/check_procs $*`
    +RC=$?
    +COUNT=`echo $LINE | awk '{print $3}'`
    +PROCS=`expr $COUNT - 1`
    +LINE=`echo $LINE | sed "s/: $COUNT /: $PROCS /"`
    +echo $LINE \| procs=$PROCS
    +exit $RC
    + +

    +Now you'll get the number together with the required label + +

    +
    ./check_procs.sh -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'| procs=2
    + +
    +
    + +

    +2.6. Performance data +

    + +

    +Performance data is defined by Nagios as “everything after the | of the plugin output” - please refer to Nagios documentation for information on capturing this data to logfiles. However, it is the responsibility of the plugin writer to ensure the performance data is in a “Nagios plugins” format. This is the expected format: +

    + +

    +'label'=value[UOM];[warn];[crit];[min];[max] +

    + +

    +Notes: + +

    +
      +
    1. space separated list of label/value pairs
      +
    2. +
    3. label can contain any characters
      +
    4. +
    5. the single quotes for the label are optional. Required if spaces, = or ' are in the label
      +
    6. +
    7. label length is arbitrary, but ideally the first 19 characters are unique (due to a limitation in RRD). Be aware of a limitation in the amount of data that NRPE returns to Nagios
      +
    8. +
    9. to specify a quote character, use two single quotes
      +
    10. +
    11. warn, crit, min/ or max/ may be null (for example, if the threshold is not defined or min and max do not apply). Trailing unfilled semicolons can be dropped
      +
    12. +
    13. min and max are not required if UOM=%
      +
    14. +
    15. value, min and max in class [-0-9.]. Must all be the same UOM
      +
    16. +
    17. warn and crit are in the range format (see Section 2.5). Must be the same UOM
      +
    18. +
    19. UOM (unit of measurement) is one of:
      +
        +
      • no unit specified - assume a number (int or float) of things (eg, users, processes, load averages)
        +
      • +
      • s - seconds (also us, ms)
        +
      • +
      • % - percentage
        +
      • +
      • B - bytes (also KB, MB, TB, GB?)
        +
      • +
      • c - a continous counter (such as bytes transmitted on an interface)
        +
      • +
      +
    20. +
    + +

    + +It is up to third party programs to convert the Nagios plugins performance data into graphs. +

    + +

    +Origin: http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN201 + +

    + +
    diff --git a/share/pnp/documents/en_US/dwnld.html b/share/pnp/documents/en_US/dwnld.html new file mode 100644 index 0000000..b4aba76 --- /dev/null +++ b/share/pnp/documents/en_US/dwnld.html @@ -0,0 +1,478 @@ + + + +

    PNP 0.6.x Downloads

    +
    + +
    + +

    Current stable PNP Version

    +
    + +

    + +Changes can be tracked on pnp4nagios.git.sourceforge.net +

    + +

    +The current Version is pnp4nagios-0.6.22.tar.gz +

    + +
    + +

    Latest Devel Version

    +
    + +

    + + pnp4nagios-head.tar.gz +

    + +

    +This is allways the latest GIT HEAD Version +

    +
    + +

    + +Last Update: Wed Jul 30 12:30:45 CEST 2014 +

    + +
    + +

    ChangeLog

    +
    + +

    + +pnp-0.6.?? ??/??/2013 +

    + +

    +pnp-0.6.24 07/30/2013 +

    +
      +
    • Bugfix: Fixed some more XSS issues
      +
    • +
    • Bugfix: Fixed PHP issue while running on PHP 5.6 ( Reported by Sven Nierlein )
      +
    • +
    + +

    + +pnp-0.6.22 06/04/2014 +

    +
      +
    • Bugfix: Fixed livestatus socket parsing ( Pekka Panula )
      +
    • +
    • Bugfix: Update check_mssql_health.php ( Miriam Zenk )
      +
    • +
    • Feature: Add “version=tiny” to got get a stripped down version of graph ( Ricardo Bartels )
      +
    • +
    • feature: Add STDIN Mode to process_perfdata.pl ( Robert Steininger )
      +
    • +
    • Bugfix: XSS issue fixed by Mikael Falkvidd. This issue was detected by Peter Österberg at Hexbit AB in a security assessment of op5 Monitor 6.3 on assignment by op5 AB.
      +
    • +
    + +

    + +pnp-0.6.21 03/24/2013 +

    +
      +
    • Feature: Helper functions rrd::alerter and rrd:alerter_gr both supports treshold detection (Martin Schirrmacher)
      +
    • +
    • Update: jQuery Mobile update to 1.3.0 ( was broken in 0.6.20 )
      +
    • +
    + +

    + +pnp-0.6.20 03/03/2013 +

    +
      +
    • Feature: Support check_mk Multisite Cookie Auth ( Lars Michelsen )
      +
    • +
    • Feature: Allow RRD unknown values ( Simon Meggle )
      +
    • +
    • feature: Interactive delete mode added to check_rrds.pl ( Simon Meggle )
      +
    • +
    • Bugfix: Allow multiple gearman servers ( Craig Barraclough )
      +
    • +
    • Bugfix: Fixed Graph Search ( Stefan Triep )
      +
    • +
    • Update: jQuery update to 1.8.1
      +
    • +
    • Update: jQueryUI update to 1.8.23
      +
    • +
    + +

    + +pnp-0.6.19 09/01/2012 +

    +
      +
    • Feature: Parameter “width” added to popup controller ( Andreas Doehler )
      +
    • +
    • Fix: simplify/improve apache rules ( Christoph Anton Mitterer )
      +
    • +
    • Fix: Check for missing PHP GD functions
      +
    • +
    • Bugfix: socketDOMAIN changed to AF_INET while using livstatus tcp socket ( Rene Koch )
      +
    • +
    + +

    + +pnp-0.6.18 06/28/2012 +

    +
      +
    • Bugfix: Fixed STORAGE_TYPE and CUSTOM_TEMPLATE vars used in custom templates
      +
    • +
    • Bugfix: Blank screen on PHP 5.4 fixed
      +
    • +
    • Feature: Allow multiple gearman job servers
      +
    • +
    • Feature: New helper function rrd::debug()
      +
    • +
    • Feature: New templates check_jmx4perl_*.php
      +
    • +
    + +

    + +pnp-0.6.17 03/25/2012 +

    +
      +
    • Bugfix: Fixed rrd_convert.pl while running with --dry-run
      +
    • +
    • Bugfix: logging.c include missing header files ( Lars Vogdt )
      +
    • +
    • Bugfix: Check if pnp4nagios/etc/rra.cfg is readable
      +
    • +
    • Bugfix: rrd_convert.pl use XML tag TEMPLATE instead of CHECKCOMMAND to selects RRDs ( Sven Velt )
      +
    • +
    • Feature: npcdmod.o increase perfdata buffer and log discarded perfdata ( Birger Schmidt )
      +
    • +
    • Feature: rrd_modify.pl to change number of data sources of an RRD file
      +
    • +
    • Feature: New template check_apachestatus_auto.php
      +
    • +
    • Feature: Implement etc/config.d to place config snippets ( Lars Michelsen )
      +
    • +
    + +

    + +pnp-0.6.16 11/21/2011 +

    +
      +
    • Bugfix: Fixed single quoted check_multi labels (Reported by Matthias Flacke)
      +
    • +
    • Bugfix: Append missing slash to perfdata_spool_dir ( Reported by Juergen-Michael Radtke )
      +
    • +
    • Bugfix: Fixed jQuery-ui multisite theme
      +
    • +
    • Feature: PDF margins are now adjustable via config.php ( Thomas Witzenrath )
      +
    • +
    • Feature: Support for PDF size 'letter' added ( Robert Becht )
      +
    • +
    + +

    + +pnp-0.6.15 09/15/2011 +

    +
      +
    • Bugfix: Fixed Overview link (reported by Stefan Triep)
      +
    • +
    • Bugfix: Fixed zoom popup (reported by Rudolf Labuschagne)
      +
    • +
    • Bugfix: Fixed double urlencode() (reported by Mathias Kettner)
      +
    • +
    • Feature: “Clear basket” button added (suggested by Stefan Triep)
      +
    • +
    • Feature: New helper function “rrd::alerter_gr()” ( committed by Stefan Trip )
      +
    • +
    + +

    + +pnp-0.6.14 08/05/2011 +

    +
      +
    • Feature: Webinterface for mobile devices based on jQuery Mobile
      +( http://jquerymobile.com/ )
      +
    • +
    • Feature: Zoom based on jQuery plugin imgAreaSelect
      +( http://odyniec.net/projects/imgareaselect/ )
      +
    • +
    • Feature: New template check_mssql_health.php
      +
    • +
    • Bugfix: Fixed popups to work under nginx ( Joram Agten )
      +
    • +
    • Bugfix: Helper rrd::vdef() fixed
      +
    • +
    • Update: jQuery update to 1.6.2
      +
    • +
    • Update: jQuery-ui update to 1.8.14
      +
    • +
    + +

    + +pnp-0.6.13 05/19/2011 +

    +
      +
    • Feature: New option --ignore-hosts added to check_pnp_rrds.pl ( by Jochen Bern )
      +
    • +
    • Feature: New options zgraph_width and zgraph_height in config.php ( Mike Liebsch )
      +
    • +
    • Bugfix: rrd_convert.pl: parse_xml_filename() regex fix
      +
    • +
    • Info: Version used by OMD-0.48 OMD
      +
    • +
    + +

    + +pnp-0.6.12 04/22/2011 +

    +
      +
    • Feature: mod_gearman support added
      +
    • +
    • Feature: rrd_convert.pl is now able to convert all RRDs from RRD_STORAGE_TYPE=SINGLE to RRD_STORAGE_TYPE=MULTIPLE
      +
    • +
    • Feature: New template check_gearman.php
      +
    • +
    • Feature: Install process_perfdata.cfg and npcd.cfg by default
      +
    • +
    • Bugfix: rrd_convert.pl is now able to parse xml dumps created by rrdtool 1.4.x
      +
    • +
    • Bugfix: process_perfdata.pl default timeout value set to 15 seconds
      +
    • +
    + +

    + +pnp-0.6.11 01/15/2011 +

    +
      +
    • Bugfix: urldecoding fixed
      +
    • +
    • Bugfix: Zoom in/out is working again ( Reported by Thorben Soehl )
      +
    • +
    • Featue: npcd.cfg - New option perfdata_file_processing_interval used by npcdmod
      +
    • +
    • Info: Version used by OMD-0.46 OMD
      +
    • +
    + +

    + +pnp-0.6.10 12/15/2010 + +

    +
      +
    • Feature: Add RRDTool Option --only-graph if graph height is below 32px to create thumbnails
      +
    • +
    • Feature: RRDTool Option --width and --height is now allowed in templates
      +
    • +
    • Feature: RRDTool DS Type for UOM of “c” changed from COUNTER to DERIVE
      +
    • +
    • Feature: Pass query string from special controller to image controller ( Matthew Garrett )
      +
    • +
    • Feature: Authorisation against mk_livestatus API added
      +
    • +
    • Feature: Sample nginx webserver config added ( by evax@users.sourceforge.net )
      +
    • +
    • Feature: Kohana backport to support PHP 5.1.6 ( Kudos to Andreas Ericsson )
      +
    • +
    • Bugfix: Sort list of special templates
      +
    • +
    • Bugfix: Urlencode hostname and service description ( Reported by Yannick )
      +
    • +
    • Bugfix: corrected warning/critical thresholds in ticker/alerter functions
      +
    • +
    + +

    + +pnp-0.6.7 09/27/2010 + +

    +
      +
    • Bugfix: Page config parser fix (Beau Gunderson)
      +
    • +
    • Bugfix: Zoom window size fixed (Report by Rudolf Labuschagne)
      +
    • +
    • Bugfix: Fixed undefined offset while using 'ds_name' in templates (Reported by Vladimir Bilik)
      +
    • +
    • Bugfix: Npcdmod respects process_perf_data option used in hosts and services definitions ( Reported by Wolfgang Barth )
      +
    • +
    • Template: New Template check_nagiostats.php used with check_nagiostats written by Jochen Bern
      +
    • +
    + +

    + +pnp-0.6.6 08/07/2010 + +

    +
      +
    • Bugfix: Fixed max amount of graphs per template
      +
    • +
    • Bugfix: Autodetect PNP base URL
      +
    • +
    • Bugfix: Too short npcdmod perfdata_template to take perfdata + overhead, increased +1024byte
      +
    • +
    • Bugfix: Ignore files in var/perfdata and check for empty directories
      +
    • +
    • Bugfix: Reducing memory usage while parsing page config (Laurent Freval)
      +
    • +
    + +

    + +pnp-0.6.5 07/09/2010 + +

    +
      +
    • Feature: Special Templates are back tpl_special
      +
    • +
    • Feature: New rrdtool helper functions makes template design easier tpl_helper
      +
    • +
    • Feature: config.php → 'recursive_template_search' is enabled by default
      +
    • +
    • Feature: config.php → 'template_dirs' is now an array of directorys to search for PNP templates
      +
    • +
    + +

    + +pnp-0.6.4 06/03/2010 + +

    +
      +
    • Update: jQuery Update to 1.4.2
      +
    • +
    • Update: jQuery-ui Update to 1.8
      +
    • +
    • Feature: New configure Option --with-base-url
      +
    • +
    • Template: New template check_ntp_time.php (Mathias Kettner)
      +
    • +
    • Feature: New i18n files for fr_FR (Yannig Parre)
      +
    • +
    • Feature: New jQuery Theme 'multisite'
      +
    • +
    + +

    + +pnp-0.6.3 03/16/2010 + +

    +
      +
    • Feature: New helper script libexec/rrd_convert.pl → rrd_convert
      +
    • +
    • Bugfix: Ignore old XML files while building the service list
      +
    • +
    • Template: New template check_hpasm.php
      +
    • +
    • Bugfix: Installer now checks for json_decode()
      +
    • +
    • Workaround: Allow “trailing unfilled semicolons”. Workaround for nsclient++
      +
    • +
    • Template: Updates for check_openmanage.php, check_hp_bladecenter.php and check_dell_baldecenter.php ( Trond Hasle Amundsen )”
      +
    • +
    + +

    + +pnp-0.6.2 12/23/2009 + +

    +
      +
    • Feature: XML_WRITE_DELAY option added to process_perfdata.cfg as suggested by Mathias Kettner
      +
    • +
    • Feature: New template integer.php
      +
    • +
    • Update: FPDI update to 1.3.1
      +
    • +
    • Feature: PNP will now work with lighttpd and php-cgi
      +
    • +
    • Template: check_mk-ps.perf.php added ( by Mathias Kettner )
      +
    • +
    • Feature: PNP will now work without mod_rewrite → webfe
      +
    • +
    • Bugfix: Wrong pdf link used on site 'pages' and 'basket'
      +
    • +
    • Bugfix: Incorrect group permissions on spool directory
      +
    • +
    + +

    + +pnp-0.6.1 11/22/2009 + +

    +
      +
    • Feature: RRD heartbeat per check_command → tpl_custom
      +
    • +
    • Feature: New config.php option pdf_graph_opt
      +
    • +
    • Feature: Recognize the 'background_pdf' option in page definitions → pages
      +
    • +
    • Feature: Recognize the 'source' option in page definitions → pages
      +
    • +
    • Feature: Array $TIMERANGE now available for templates → timeranges
      +
    • +
    • Bugfix: ./configure --sysconfdir no longer ignored
      +
    • +
    • Feature: Store internal runtime statistics on a per minute base
      +
    • +
    • Feature: Added two widgets views/widget_menu.php and views/widget_graph.php
      +
    • +
    + +

    + +pnp-0.6.0 10/30/2009 + +

    +
      +
    • Webfrontend based on Kohana
      +
    • +
    • Webfrontend based on jQuery Themes
      +
    • +
    • Javascript-functions using jQuery plugins
      +
    • +
    • process_perfdata.pl will be able to use one RRD database per datasource
      +
    • +
    • improved installer. Specification of directory layouts using --with-layout
      +
    • +
    • RRDtool errors are now displayed as images. no more missing images
      +
    • +
    • PNP templates cannot overwrite internal variables anymore
      +
    • +
    • PNP templates of version 0.4.x can still be used
      +
    • +
    • PDF functions recoded
      +
    • +
    • Template default.php optimized
      +
    • +
    • Export from RRD databases into XML, CSV and JSON format using the RRDtool “xport” function
      +
    • +
    • Page functions recoded
      +
    • +
    • Error pages links to online FAQ
      +
    • +
    • Mouseover Popup in Nagios frontend via jQuery.clueTip plugin
      +
    • +
    • Full support of rrdcached
      +
    • +
    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/install.html b/share/pnp/documents/en_US/install.html new file mode 100644 index 0000000..48b8332 --- /dev/null +++ b/share/pnp/documents/en_US/install.html @@ -0,0 +1,213 @@ + + + +

    Installation

    +
    + +

    +The installation of PNP will be described in more detail. It is expected that nagios was compiled from source and is located in /usr/local/nagios.
    + +Attention: The description applies to the developer version PNP 0.6.0.
    + +Please note that PNP has to be configured after the installation. +

    + +
    + +

    Make and more

    +
    + +

    +The installation of PNP is controlled by makefiles. The system is analyzed after invocation of ./configure and the detected values are tranferred to makefiles. +

    + +

    +Please unpack PNP as user root: + +

    +
    +tar -xvzf pnp4nagios-HEAD.tar.gz
    +cd pnp4nagios
    +
    + +

    +./configure is to be called from the directory pnp4nagios. +

    +
    +./configure
    +
    + +

    + +Note: Without specifying any options user and group will be “nagios”. If you have different values then please use the parameters ”--with-nagios-user” and ”--with-nagios-group”, respectively. Using Icinga the call might be + +

    +
    +./configure --with-nagios-user=icinga --with-nagios-group=icinga
    +
    + +

    + +Some lines run across the screen. The output at the end is important. +

    +
    +*** Configuration summary for pnp4nagios-0.6.2 23-12-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.2.12
    +  RRDs Perl Modules:                FOUND (Version 1.2012)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    +
    +  Review the options above for accuracy.  If they look okay,
    +  type 'make all' to compile.
    + +

    +The paths shown should be checked. If the displayed values aren't correct you can change them calling ./configure with appropriate options.
    + +Attention: “Location of rrdtool binary” means path including name of binary! If necessary it can be specified using the following syntax: + +

    +
     ./configure --with-rrdtool=/usr/local/rrdtool-1.2.xx/bin/rrdtool
    +
     ./configure --help 
    + +

    + +shows the supported options.
    +
    + +

    + +

    +Invoking +

    +
     make all
    + +

    + +compiles the components like NPCD which are written in C + +

    +
     make install
    + +

    + +copies everything to the right places in the file system. The paths were already shows during ./configure. +

    + +

    +After the installation of the program and HTML files you can copy a sample Apache configuration file to your web-server config directory + +

    +
     make install-webconf
    + +

    + +You can call + +

    +
     make install-config
    + +

    + +optionally. This way config files for process_perfdata.pl and npcd are copied to etc/pnp. +

    + +

    +To install the NPCD Init script call + +

    +
     make install-init
    + +

    + +All these steps are combined in + +

    +
     make fullinstall
    + +

    + +Note: As already stated the Nagios settings will be used per default. If you are using Icinga the file '/etc/apache2/conf.d/pnp4nagios.conf' has to be edited to change the path to AuthUserFile (the path may differ between distributions): + +

    +
    #       AuthUserFile /usr/local/nagios/etc/htpasswd.users
    +        AuthUserFile /usr/local/icinga/etc/htpasswd.users
    + +

    +Attention: After copying the configuration file for the web server you have to restart the web server (service httpd restart or /etc/init.d/apache2 restart, respectively). +

    + +
    + +

    Update

    +
    + +

    + +The update of a 0.6.x version works (nearly) the same way as an installation. Please note that you have to call ./configure with the same options you used during the first installation. +Please check if you changed anything in the folder share/templates.dist. Own templates should be placed in share/templates to avoid being overwritten.
    + +Attention: If you changed config.php then you should save this file before it is overwritten when you execute make install-config. +

    + +

    +You can skip make install-webconf and make install-init because nothing changed between 0.6.x versions. +

    + +
    + +

    The components

    +
    + +

    + +After installation the components of PNP were copied to the appropriate places in the file system. These are +

    + +

    +the PHP-Files for the web-frontend below + +

    +
     /usr/local/pnp4nagios/share
    + +

    + +the data collector process_perfdata.pl in + +

    +
     /usr/local/pnp4nagios/libexec
    + +

    + +sample config files with the suffix -sample in + +

    +
     /usr/local/pnpnagios/etc
    + +

    + +the config file config.php for the web frontend in + +

    +
     /usr/local/pnp4nagios/etc
    + +

    + +back to contents | configuration + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/mobile.html b/share/pnp/documents/en_US/mobile.html new file mode 100644 index 0000000..ca29775 --- /dev/null +++ b/share/pnp/documents/en_US/mobile.html @@ -0,0 +1,89 @@ + + + +

    Mobile UI

    +
    + +

    + +Starting with PNP4Nagios 0.6.14 a web interface for mobile devices is integrated into PNP4Nagios. +

    + +

    +The design was realised using jQuery Mobile and hence is compatible to current mobile browsers. The list of the supported devices shows a graded browser support chart. +

    + +
    + +

    Landing Page

    +
    + +

    + +The web interface was designed to intercept the calls to the classical interface and to redirect them to the appropriate mobile page. This way links to PNP graphs inside Nagios mails don't have to be changed and point to the correct page depending on the device type.. + +

    + + + + + + + + + + + + + +
    Classic Mobile
    /pnp4nagios/graph /pnp4nagios/mobile
    /pnp4nagios/graph?host=localhost /pnp4nagios/mobile/host/localhost
    /pnp4nagios/graph?host=localhost&srv=ping /pnp4nagios/mobile/graph/localhost/ping
    + +
    + +

    Browser recognition

    +
    + +

    + +Browsers are recognised as mobile browsers by analysing the “user agent” string. +The recognition can be influenced by changing pnp4nagios/etc/config_local.php. +

    +
    +$conf['mobile_devices'] = 'iPhone|iPod|iPad|android';
    +
    + +

    +The option 'mobile_devices' contains a regular expression which is compared with the “user agent” string of the browser. +

    + +

    +The “user agent” string of a browser is logged in the web server access log. An entry for an iOS device looks similar to the following. +

    +
    +"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7"
    +
    + +
    + +

    Screenshots

    +
    + +

    + +Screenshot taken with an iPhone and iOS 4.2 + +

    + + + + + + + + + + +
     Home Screen Homescreen  Loading... Loading …
     Hosts Liste List of all hosts  Liste aller services List of all services of a host
     Graphen Graph of a service
    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/modes.html b/share/pnp/documents/en_US/modes.html new file mode 100644 index 0000000..dd80475 --- /dev/null +++ b/share/pnp/documents/en_US/modes.html @@ -0,0 +1,145 @@ + + + +

    The art of collecting data

    +
    + +

    + +PNP supports several modes to process performance data. The modes differ in complexity and the performance to be expected. +

    + +

    +The following image shows the connections between Nagios, PNP and RRDtool
    + +

    + +

    +Nagios invokes a command for every host and every service whose performance data should be processed. Depending on the mode you choose the data will be passed to process_perfdata.pl or will be written to temporary files and processed at a later time. process_perfdata.pl writes the data to XML files and stores them in RRD files using RRDtool.
    + +

    + +

    +Before you choose a mode please read the documentation and decide which way will be the best for installation. +

    + +
    + +

    The modes in comparison

    +
    + +
    + +

    Synchronous Mode

    +
    + +

    + +The “synchronous mode” is the simplest and easiest to set up. Nagios will call the perl script process_perfdata.pl for every service and host, respectively, to process the data. The synchronous mode will work very good up to about 1.000 services in a 5 minute interval. +

    + +
    + +

    Bulk Mode

    +
    + +

    + +In bulk mode Nagios writes the necessary data to a temporary file. After expiration of a defined time the file will be processed in one piece and deleted afterwards. +

    + +

    +The number of calls of process_perfdata.pl will be reduced to a fraction. Depending on time and the amount of collected data there will be much less system calls. Instead, process_perfdata.pl will run longer. +

    + +

    +Note +Using this mode you should keep an eye on the runtime of process_perfdata.pl. While it is running to process data nagios will not execute any checks. +

    + +

    +snippet of var/perfdata.log: + +

    +
    +2007-10-18 12:05:01 [21138] 71 Lines processed
    +2007-10-18 12:05:01 [21138] .../spool/service-perfdata-1192701894-PID-21138 deleted
    +2007-10-18 12:05:01 [21138] PNP exiting (runtime 0.060969s) ...
    +
    + +

    +71 lines were processed in 0.06 seconds. This will be the data volume of about 2000 services und processing using a 10 second interval. It means we blocked nagios for exactly 0.06 seconds. +

    + +
    + +

    Bulk Mode with NPCD

    +
    + +

    + +Viewing from Nagios this is the best way of processing because Nagios will not be blocked. +

    + +

    +Nagios again uses a temporary file to store the data and executes a command after expiration of a certain time. Instead of immediate processing by process_perfdata.pl the file is moved to a spool directory. As moving a file inside the same filesystem nearly takes no time nagios is able to execute crucial work immediately. +

    + +

    +The NPCD daemon (Nagios Performance C Daemon) will monitor the directory for new files and will pass the names to process_perfdata.pl. Processing of performance data is decoupled completely from nagios. NPCD itself is able to start multiple thread for processing the data. +

    + +
    + +

    Bulk Mode with npcdmod

    +
    + +

    + +Attention +Starting with Nagios 4 the internal structures have changed so the start of the module will fail. So far there are no plans to support Nagios 4. Please select any other of the modes. +

    + +

    + This scenario includes npcdmod.o, an NEB-module. +This module reduces the configuration of the “Bulk Mode with NPCD” to a mere two lines in nagios.cfg +

    + +

    +This mode is similar to “Bulk Mode with NPCD” and it is exactly the same functionality and the same performance. +

    + +
    + +

    Gearman Mode

    +
    + +

    + + +

    + +

    +Since version 0.6.12 PNP4Nagios can be driven as a gearman worker. This way large Nagios environments are possible using mod_gearman. Nagios and PNP4Nagios can be run on different machines. +

    + +

    +You need a mod_gearman environment up and running like described by Sven Nierlein on http://labs.consol.de/lang/en/nagios/mod-gearman/. +

    + +
    + +

    The decision

    +
    + +

    +Which mode you choose will depend on the size of your Nagios installation. You will find theses terms throughout the documentation. +

    + +

    +back to contents | installation + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/new-features.html b/share/pnp/documents/en_US/new-features.html new file mode 100644 index 0000000..915a6bd --- /dev/null +++ b/share/pnp/documents/en_US/new-features.html @@ -0,0 +1,61 @@ + + + +

    New in PNP 0.6.x

    +
    + +

    +PNP 0.6.x Preview +

    + +

    +The work on the new version 0.6.x is in full progress. +

    + +

    +Starting with version 0.6.x we switch from subversion to GIT. The sourcecode is already available on sourceforge. +

    + +

    + +Functions implemented already +

    +
      +
    • Webfrontend based on Kohana
      +
    • +
    • Webfrontend based on jQuery Themes
      +
    • +
    • Javascript-functions using jQuery plugins
      +
    • +
    • process_perfdata.pl will be able to use one RRD database per datasource
      +
    • +
    • improved installer. Specification of directory layouts using --with-layout
      +
    • +
    • RRDtool errors are now displayed as images. no more missing images
      +
    • +
    • PNP templates cannot overwrite internal variables anymore
      +
    • +
    • PNP templates of version 0.4.x can still be used
      +
    • +
    • PDF functions recoded
      +
    • +
    • Template default.php optimized
      +
    • +
    • Export from RRD databases into XML, CSV and JSON format using the RRDtool “xport” function
      +
    • +
    • Page functions recoded
      +
    • +
    • Error pages links to online FAQ
      +
    • +
    • Mouseover Popup in Nagios frontend via jQuery.clueTip plugin
      +
    • +
    • Full support of rrdcached
      +
    • +
    + +

    +back to contents | system requirements + +

    + +
    diff --git a/share/pnp/documents/en_US/npcd.html b/share/pnp/documents/en_US/npcd.html new file mode 100644 index 0000000..7458788 --- /dev/null +++ b/share/pnp/documents/en_US/npcd.html @@ -0,0 +1,323 @@ + + + +

    NPCD

    +
    + +

    + +NPCD (Nagios-Perfdata-C-Daemon) was written to provide an asynchronous mode to handle performance data with nagios. +

    + +
    + +

    Introduction

    +
    + +

    + +In large nagios installations, your average check latency may increase to a non-acceptable high value. This means that Nagios should do a check at time x but actually does it y seconds later. +

    + +

    +If you tell the Nagios core that you want to process the performance data after every single check this is doing well for a certain amount of checks but above this limit you will run into latency problems. +

    + +

    +To reduce the number of actions for each check you can use the Bulk Mode which gathers performance data for some time and then lets the Nagios core execute the <host|service>_perfdata_file_processing_command or you can tell Nagios to just move the perfdata_files to a spool directory. +

    + +

    +This move is a very fast action for the Nagios core and the core will be done with the processing of performance data and can continue to do what it should do: execute other checks, sending notifications, and so on. +

    + +
    + +

    How it works

    +
    + +

    + +As mentioned above the Nagios process has finished its work with moving the performance data file to a spool directory but this won't bring the data into the RRD files. +

    + +

    +For this task you can start npcd to have a look at the defined spool directory and start an action for every file which is found. +

    + +

    +After NPCD starts running it will build a list of filenames found in perfdata_spool_dir and starts new threads for every filename and executes the perfdata_file_run_cmd with the optional perfdata_file_run_cmd_arg as an additional argument. +

    + +

    +Since the perfdata files in the spool dir are in the same format as for the 'normal' bulk mode NPCD should execute process_perfdata.pl in Bulk Mode. +

    + +
    + +

    Advantages / Disadvantages

    +
    + +

    + +Pro: +

    +
      +
    • Performance improvements for Nagios
      +
        +
      • because the performance data processing is detached from the Nagios core it has more time for its own work.
        +
      • +
      +
    • +
    • no lost data
      +
        +
      • as long as Nagios writes perfdata files to the spool dir your data won't get lost if NPCD dies or you forgot to start it after a system reboot. NPCD will start with the first file found (they are sorted by the $TIME_T$ macro in chronological order) and update your RRD Files.
        +
      • +
      +
    • +
    + +

    + +Con: +

    +
      +
    • no real time processing of performance data
      +
        +
      • since there is a delay in writing the performance data files by Nagios (service_perfdata_file_processing_interval)
        +
      • +
      • another delay exists within NPCD which waits for up to 10 seconds after each directory scanning
        +
      • +
      +
    • +
    + +
    + +

    NPCD Config

    +
    + +

    + +You have to control NPCD with its own configuration file like the rolled out npcd.cfg-sample file. +

    + +

    +Just rename it to npcd.cfg to start NPCD like this: +

    +
    /usr/local/pnp4nagios/bin/npcd -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +or + +

    +
    /usr/local/pnp4nagios/bin/npcd -d -f /usr/local/pnp4nagios/etc/npcd.cfg
    + +

    + +to run in Daemon Mode (background). +

    + +

    +Hint: +If you decide to not rename the config file, it might be overwritten by a future update of PNP. +

    + +
    + +

    npcd.cfg-sample

    +
    + +

    + +These are the essential configuration directives for NPCD: +

    +
    # Privilege Options
    +user = nagios
    +group = nagios
    +
    +# Logging Options
    +log_type = syslog
    +log_file = /usr/local/pnp4nagios/var/npcd.log
    +max_logfile_size = 10485760
    +log_level=0
    +
    +# Processing Options
    +perfdata_spool_dir = /usr/local/pnp4nagios/var/spool/
    +perfdata_file_run_cmd = /usr/local/pnp4nagios/libexec/process_perfdata.pl
    +perfdata_file_run_cmd_args = -b
    +
    +# Thread Options
    +npcd_max_threads=5
    +
    +# greedy options
    +use_load_threshold = 0
    +load_threshold = 10.0
    +
    +# Process Options
    +pid_file=/var/run/npcd.pid
    +
    + +
    + +

    The directives

    +
    +
      +
    • Privilege Options
      +
        +
      • user <username>
        +
          +
        • NPCD tries to drop 'root' privileges to switch to this user.
          +
        • +
        • default: nagios
          +
        • +
        +
      • +
      • group <groupname>
        +
          +
        • NPCD tries to drop 'root' privileges to switch to this group.
          +
        • +
        • Default: nagios
          +
        • +
        +
      • +
      +
    • +
    • Logging Options
      +
        +
      • log_type <syslog> or <file>
        +
          +
        • Log type that is uses by NPCD
          +
        • +
        • Default: syslog
          +
        • +
        +
      • +
      • log_file </path/to/filename>
        +
          +
        • if log_type = file this will be the logfile used
          +
        • +
        • Default: /usr/local/pnp4nagios/var/npcd.log
          +
        • +
        +
      • +
      • max_logfile_size <bytes>
        +
          +
        • NPCD will rotate the logfile if the filesize of the current log is above this limit
          +
        • +
        • Default: 10485760 = 10 MByte
          +
        • +
        +
      • +
      • log_level <integer>
        +
          +
        • how much to log, possible values:
          +
            +
          • 0 = No Log - except errors
            +
          • +
          • 1 = small Log - some more output
            +
          • +
          • 2 = more Log (actual ALL log messages)
            +
          • +
          • -1 = DEBUG Mode - ALL Logs and slower processing for debugging purposes
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      +
    • +
    • Processing Options
      +
        +
      • perfdata_spool_dir </path/to/spool/dir/>
        +
          +
        • The directory where the perfdata file should be found
          +
        • +
        • Default: /usr/local/pnp4nagios/var/spool/
          +
        • +
        +
      • +
      • perfdata_file_run_cmd </path/to/bin/filename>
        +
          +
        • This is the script/binary that NPCD will execute
          +
        • +
        • Default: /usr/local/pnp4nagios/libexec/process_perfdata.pl
          +
        • +
        +
      • +
      • perfdata_file_run_cmd_args <option>
        +
          +
        • The argument added to the perfdata_file_run_cmd
          +
        • +
        • Default: ”-b”
          +
        • +
        • :!: The command line will be created like this:
          <perfdata_file_run_cmd> <perfdata_file_run_cmd_args> <filename_from_perfdata_spool_dir>
          +
          +
        • +
        +
      • +
      +
    • +
    • Thread Options
      +
        +
      • npcd_max_threads <integer value>
        +
          +
        • Defines how many parallel threads should be started
          +
        • +
        • Default: 5
          +
        • +
        +
      • +
      +
    • +
    • Greedy Options
      +
        +
      • use_load_threshold <0 or 1>
        +
          +
        • defines if NPCD should _not_ start new threads if your system load is too high
          +
            +
          • 0 = disable
            +
          • +
          • 1 = enable
            +
          • +
          +
        • +
        • Default: 0
          +
        • +
        +
      • +
      • load_threshold <float value>
        +
          +
        • if use_load_threshold is set to 1 this load limit must not be exceeded
          +
        • +
        • Default: 10.0
          +
        • +
        +
      • +
      +
    • +
    • Process Options
      +
        +
      • pid_file </path/to/pid.file>
        +
          +
        • the path to the PID File
          +
        • +
        • Default: /var/run/npcd.pid
          +
        • +
        +
      • +
      +
    • +
    + +

    + +back to contents | wrapper script + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/pages.html b/share/pnp/documents/en_US/pages.html new file mode 100644 index 0000000..17bbc00 --- /dev/null +++ b/share/pnp/documents/en_US/pages.html @@ -0,0 +1,91 @@ + + + +

    Pages

    +
    + +

    + +“pages” provide the opportunity to collect graphs of different hosts/services on one page. That way - as an example - you can display the traffic rates of all tape libraries. Regular expressions are possible so you can accomplish a lot with only few definitions - provided that you have appropriate names. +The directory specified using “$conf['page_dir']” contains one or more file with the extension ”.cfg”. +

    + +

    +Comments start with a hash-sign (#) and are possible within lines as well. Each file contains a “page” definition which specifies the name of the page and it determines whether the following graph definition contains regular expressions or not.
    + +The description behind page_name appears in the list of available pages and will be used as title of the browser window. Attention: “host_name” and “service_desc” refer to the name of the file in the perfdata directory, not to the definition in Nagios. Blanks are replaced by underscores (_). +

    +
    define page {
    +       use_regex 1		# 0 = use no regular expressions, 1 = use regular expressions
    +       page_name test-page	# page description
    +}
    + +

    +One or more “graph” definitions follow: +

    +
    define graph {
    +       host_name       host1,host2,host3
    +       service_desc    Current_Load
    +}
    + +

    + +Attention: The list of host name will only work if you use regex 0! +

    +
    define graph {
    +       host_name       host4
    +       service_desc    Current_Users
    +}
    + +

    +And now some definitions with regular expressions. At first all hosts whose names are starting with “Tape”: + +

    +
    define graph {
    +       host_name       ^Tape
    +       service_desc    Traffic
    +}
    + +

    +all hosts whose names are ending with “00”: + +

    +
    define graph {
    +       host_name       00$
    +       service_desc    Load
    +}
    + +

    +all services of localhost whose names contain “a” or “o”, respectively: + +

    +
    define graph {
    +       host_name       localhost
    +       service_desc    a|o
    +}
    + +

    +all services whose names contain an underscore followed by (at least) three digits on all hosts whose names start with “UX”: + +

    +
    define graph {
    +       host_name       ^UX
    +       service_desc    _\d{3}
    +}
    + +

    +In some cases you may want to limit the display to just one graph. To accomplish this you can use the optional directive “source” followed by a number specifying the position within the RRD file starting at 0 + +

    +
    define graph {
    +       host_name       host1,host2,host3
    +       service_desc    PING
    +       source          1
    +}
    + +

    +back to contents | data export + +

    + +
    diff --git a/share/pnp/documents/en_US/perfdata_format.html b/share/pnp/documents/en_US/perfdata_format.html new file mode 100644 index 0000000..4dc7025 --- /dev/null +++ b/share/pnp/documents/en_US/perfdata_format.html @@ -0,0 +1,61 @@ + +

    +2.6. Performance data +

    + +

    +Performance data is defined by Nagios as “everything after the | of the plugin output” - please refer to Nagios documentation for information on capturing this data to logfiles. However, it is the responsibility of the plugin writer to ensure the performance data is in a “Nagios plugins” format. This is the expected format: +

    + +

    +'label'=value[UOM];[warn];[crit];[min];[max] +

    + +

    +Notes: + +

    +
      +
    1. space separated list of label/value pairs
      +
    2. +
    3. label can contain any characters
      +
    4. +
    5. the single quotes for the label are optional. Required if spaces, = or ' are in the label
      +
    6. +
    7. label length is arbitrary, but ideally the first 19 characters are unique (due to a limitation in RRD). Be aware of a limitation in the amount of data that NRPE returns to Nagios
      +
    8. +
    9. to specify a quote character, use two single quotes
      +
    10. +
    11. warn, crit, min/ or max/ may be null (for example, if the threshold is not defined or min and max do not apply). Trailing unfilled semicolons can be dropped
      +
    12. +
    13. min and max are not required if UOM=%
      +
    14. +
    15. value, min and max in class [-0-9.]. Must all be the same UOM
      +
    16. +
    17. warn and crit are in the range format (see Section 2.5). Must be the same UOM
      +
    18. +
    19. UOM (unit of measurement) is one of:
      +
        +
      • no unit specified - assume a number (int or float) of things (eg, users, processes, load averages)
        +
      • +
      • s - seconds (also us, ms)
        +
      • +
      • % - percentage
        +
      • +
      • B - bytes (also KB, MB, TB, GB?)
        +
      • +
      • c - a continous counter (such as bytes transmitted on an interface)
        +
      • +
      +
    20. +
    + +

    + +It is up to third party programs to convert the Nagios plugins performance data into graphs. +

    + +

    +Origin: http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN201 + +

    diff --git a/share/pnp/documents/en_US/rrd_convert.html b/share/pnp/documents/en_US/rrd_convert.html new file mode 100644 index 0000000..714ef22 --- /dev/null +++ b/share/pnp/documents/en_US/rrd_convert.html @@ -0,0 +1,88 @@ + + + +

    RRD_STORAGE_TYPE = MULTIPLE

    +
    + +

    + +available starting with PNP 0.6.3 +

    + +

    +Since PNP version 0.6 it is possible to store performance data into multiple RRD databases instead of a single RRD database. +

    + +

    +After creation of an RRD file you cannot alter the number of data sources. This may lead to problems if Nagios plugins change the number of data sources dynamically. +

    + +

    +An example might be check_disk if you monitor all available file systems using one service. If a file system is added the RRD database cannot be updated anymore because the internal would be changed. +

    + +

    +Per default PNP uses the option RRD_STORAGE_TYPE = SINGLE which is defined in process_perfdata.pl and might be changed using the config file process_perfdata.cfg. +This setting should not be changed globally because PNP will start creating new RRD files immediately after changing to MULTIPLE. Old data will get lost! +

    + +

    +Additionally it is not advisable to activate RRD_STORAGE_TYPE = MULTIPLE globally in regard to performance. The number of RRD databases and the disk I/O will increase significantly. That means that you should carefully select which Nagios check commands should be altered. +

    + +

    +The section Custom Templates contains information about how the settings should be altered. +

    + +
    + +

    A converter

    +
    + +

    + +The script libexec/rrd_convert.pl will be used to switch RRD_STORAGE_TYPE to MULTIPLE and to migrate the RRD databases. +

    + +

    +Significant as always with PNP is the Nagios check command. +

    +
    rrd_convert.pl --check_command=<nagios_check_command> | --list_commands [ --dry-run ] [ --tmp_dir=<temp-directory ]
    +[ --no_structure_check ]
    + +

    +You have to specify at least one of ”--check_command” or ”--list_commands”, respectively. +Using the open --check-command= you tell the script which check command should be searched for. +

    + +

    +rrd_convert.pl will now browse all PNP XML files for this command and output some statistics. +

    + +

    +After confirmation from the user the conversion of the appropriate RRD databases will start displaying the progress. Pressing <ENTER> as an answer will terminate the script so please enter a letter. +

    + +

    +If you are unsure then use --list_commands to get a list of the check commands used in the XML files. +

    + +

    +The option --dry-run will convert the RRD databases but they will be stored in /tmp/rrd_convert in separate folders per host instead. This way you'll get a feeling about the runtime and the amount of data. +

    + +

    +If you want to change the temporary directory you can use --tmp_dir=<alternative temp dir>. +

    + +

    +Sometimes the number of datasources in the RRD files doesn't match the number in the XML files. This might happen if a plugin suddenly returns more datasources than usual (like check_disk as mentioned above). Using the option --no_structure_check these RRD files will be converted as well. +

    + +

    +back to contents | NPCD details + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/rrdcached.html b/share/pnp/documents/en_US/rrdcached.html new file mode 100644 index 0000000..0cb66b9 --- /dev/null +++ b/share/pnp/documents/en_US/rrdcached.html @@ -0,0 +1,154 @@ + + + +

    RRDtool Cache Daemon

    +
    + +

    + +In large installations sooner or later one will recognize that processing the performance data will result in a relatively high I/O load. RRDtool has to do very much disk updates but cannot use the disk cache in an optimal way. +

    + +

    +One improvement is made by collecting and sorting the data. It is more effective to write many updates to an RRD database in one block. The disk cache can be used more effectively that way. +

    + +

    +The current RRDtool ( SVN trunk 1550+ ) contains rrdcached which should improve exactly this situation. +

    + +

    +At this point I'd like to thank Florian octo Forster, Kevin Brintnall and Tobi Oetiker. The development of this daemon has been coordinated exemplary on the rrd-developers mailing list. +

    + +
    + +

    Mode of operation

    +
    + +

    + +The rrdcached is working as a daemon in the background and opens a UNIX or TCP socket to wait for requests of rrdtool. Due to security reasons newer versions of rrdcached cannot use absolute paths for network access anymore so the only possible way are unix sockets. +

    + +
    + +

    rrdcached

    +
    + +

    + +rrdcached recognizes some important options which are passed during startup. +

    + +

    +Option -l defines the socket the daemon will listen for update requests. The default TCP port will be 42217. +

    +
    +-l unix:/path/to/rrdcached.sock
    +-l /path/to/rrdcached.sock
    +-l 127.0.0.1
    +-l 127.0.0.1:8888
    +
    + +

    +Option -P specifies which commands are usable with the RRD data bases + +

    +
    -P FLUSH,PENDING
    + +

    +Option -s allows to change the group ownership of the unix socket +

    +
    -s nagios
    + +

    +Option -m sets the permissions of the unix socket in the usual octal format +

    +
    -m 0660
    + +

    +Option -w specifies the interval (in seconds) the data will be written to disk. +

    +
    -w 1800
    + +

    +Option -z defines a maximum delay which will be used to spread the write cycles over a certain range [0-delay] to avoid parallel write accesses. The value of option -z must not be larger than -w. +

    +
    -z 1800
    + +

    +Option -p defines a PID file +

    +
    -p /var/run/rrdcached.pid
    + +

    +Option -j defines the path to a journaling directory. All requests will be logged there so that they can be processed after a restart in case the daemon crashes. +

    +
    -j /var/cache/rrdcached
    + +

    +These options may result in a call of rrdcached with the following parameters +

    +
     rrdcached -w 1800 -z 1800 -p /tmp/rrdcached.pid -j /tmp  -s nagios -m 0660 -l unix:/tmp/rrdcached.sock
    + +
    + +

    rrdtool

    +
    + +

    + +RRDtool itself will be informed about the daemon using the option --daemon=<socket>. + +

    +
     rrdtool --daemon=unix:/tmp/rrdcached.sock update ...
    + +

    + +Of course this has to correspond with the options of rrdcached! +

    + +
    + +

    Integration into PNP

    +
    + +

    + +Because two components of PNP have to prepared for the use of rrdcached there are changes in two config files. +

    + +

    +1. Adjustment of process_perfdata.cfg for the data collector process_perfdata.pl +

    +
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +RRD_DAEMON_OPTS = unix:/var/run/rrdcached.sock
    +
    + +

    +2. Adjustment of config_local.php (or config.php) for the web interface +

    +
    +#
    +# EXPERIMENTAL rrdcached Support
    +# Use only with rrdtool svn revision 1511+
    +#
    +# $conf['RRD_DAEMON_OPTS'] = 'unix:/tmp/rrdcached.sock';
    +$conf['RRD_DAEMON_OPTS'] = 'unix:/var/run/rrdcached.sock';
    +
    + +

    +The sample files contain the relevant options. +

    + +

    +back to contents | migrating RRD files + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/start.html b/share/pnp/documents/en_US/start.html new file mode 100644 index 0000000..5448b40 --- /dev/null +++ b/share/pnp/documents/en_US/start.html @@ -0,0 +1,194 @@ + + + +

    Documentation

    +
    +
    + +
    +
    PNP4Nagios Broker Module npcdmod.o is not compatible with Nagios Core 4.x
    +
    + +
    + +

    +Theme "smoothness" +

    + +

    +PNP is an addon to Nagios which analyzes performance data provided by plugins and stores them automatically into RRD-databases (Round Robin Databases, see RRD Tool). +

    + +

    +During development of PNP we set value on easy installation and little maintenance while running it. An administrator should do other things than configure graphing tools. +

    + +

    +To achieve this task we focused on using standards. PNP only processes performance data built according to the Developer Guidelines for nagios plugins. With this limitation we want to honour the work of Nagios Plugin Developers who stick to the guidelines. +

    + +

    +For all of those who are still curious the following documentation is made which should help to ease the access to PNP. +

    + +

    +complete documentation on "one" page +

    + +
    + +

    Documentation

    +
    + + + + + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/timeranges.html b/share/pnp/documents/en_US/timeranges.html new file mode 100644 index 0000000..8ce035d --- /dev/null +++ b/share/pnp/documents/en_US/timeranges.html @@ -0,0 +1,87 @@ + + + +

    Timeranges

    +
    + +

    + +In the overview PNP shows five timeranges which can be defined in config.php. +

    + +

    +Additionally you can influence the timeranges via the URL. This can be useful to automatically create PDF documents. The ranges can be defined using the options “start” and “end”. +

    + +

    +Example: + +

    +
     pnp4nagios/graph?host=<hostname>&srv=<servicedesc>&start=-1week
    + +

    + +The graph will start one week prior to the current date and time. It will end at the current timestamp. + +

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    start end view result
    all views ending at current timestamp
    x all views starting at defined date
    x all views ending at defined date
    x x one view between the two dates
    x one view ending at current timestamp
    x x one view starting at defined date
    x x one view ending at defined date
    + +

    +Examples of different specifications + +

    + + + + + + + + + + + + + + + + + + + + + + +
    format description
    2009W04 4. week of 2009
    1.5.2009 May, 1st 2009
    -1 day one day back
    -3 weeks 3 weeks back
    -1 year one year back
    yesterday yesterday
    + +

    +back to contents | pages + +

    + +
    diff --git a/share/pnp/documents/en_US/tpl.html b/share/pnp/documents/en_US/tpl.html new file mode 100644 index 0000000..29b45ac --- /dev/null +++ b/share/pnp/documents/en_US/tpl.html @@ -0,0 +1,240 @@ + + + +

    What are templates?

    +
    + +

    + +PNP uses templates to influence the appearance of RRD graphs. +

    + +

    +The selected check_command determines which template will be used to control the graph. Following will be described where templates are stored and how the decision for the “right” template is made. +

    + +
    + +

    What template will be used when?

    +
    + +

    + +Templates are stored at two places in the file system. + +

    +
      +
    • share/templates.dist - for templates included in the PNP package
      +
    • +
    • share/templates - for custom made templates which are not changed during updates
      +
    • +
    + +

    + +If the graph for the service “http” on host “localhost” should be shown, PNP will look for the XML file perfdata/localhost/http.xml and read its contents. The XML files are created automatically and contain information about the particular host and service. The header contains information about the plugin and the performance data. The XML tag <TEMPLATE> identifies which PNP template will be used for this graph. +

    + +

    +/localhost/http.xml + +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>2</DS>
    +    <NAME>size</NAME>
    +    <UNIT>B</UNIT>
    +    <ACT>263</ACT>
    +    <WARN></WARN>
    +    <CRIT></CRIT>
    +    <MIN>0</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +...
    +</NAGIOS>
    + +

    +PNP will append .php to the string and therefore look for a template with the name check_http.php in the following sequence: + +

    +
      +
    1. templates/check_http.php
      +
    2. +
    3. templates.dist/check_http.php
      +
    4. +
    5. templates/default.php
      +
    6. +
    7. templates.dist/default.php
      +
    8. +
    + +

    + +The template default.php takes an exceptional position as it is used every time no other applicable template is found. +

    + +
    + +

    Creating own templates

    +
    + +

    + +PNP templates are PHP files which are included during execution of PNP using the PHP function include(). This means that every PHP code in templates will be interpreted so manipulation of all values is possible. +

    + +

    +PNP template must have the following characteristics: + +

    +
      +
    1. templates must contain valid PHP code.
      +
    2. +
    3. templates must not create any output.
      +
    4. +
    5. the two arrays $opt[] and $def[] have to be filled
      +
    6. +
    + +

    + +These two arrays are used to call 'rrdtool graph' so every option is possible that RRDtool supports. All options of RRDtool are described very thoroughly on the RRDtool Homepage. +

    + +

    +If both arrays contain more than one set of data graphs will be created for every set. +

    + +

    +Inside the templates the data from the related XML files can be used. +

    + +

    +Using the relatively simple template response.php we will describe the most important options. +

    +
    <?php
    +#
    +$opt[1] = "--title \"Response Time For $hostname / $servicedesc\" ";
    +#
    +$def[1] =  "DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE " ;
    +$def[1] .= "AREA:var1#00FF00:\"Response Times \" " ;
    +$def[1] .= "LINE1:var1#000000 " ;
    +$def[1] .= "GPRINT:var1:LAST:\"%3.4lg %s$UNIT[1] LAST \" ";
    +$def[1] .= "GPRINT:var1:MAX:\"%3.4lg %s$UNIT[1] MAX \" ";
    +$def[1] .= "GPRINT:var1:AVERAGE:\"%3.4lg %s$UNIT[1] AVERAGE \" ";
    +?>
    + +

    +Note: as the number (1) and the letter “L” look alike in this listing: the format ”%3.4lg” contains a small letter. +

    + +

    +$opt[1] = ”--title … sets RRDtool options for the first set of data, here the title as you can see. Embedded quotes are masked using a backslash (\). The variables $hostname and $servicedesc were determined through the call of PNP and are available for the template as well. +

    + +

    +$def[1] = “DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE ”; defines which data is to be read from which RRD file. $RRDFILE[1] contains the path to the RRD file of this service. $DS[1] refers to the first data series from the RRD file. +

    + +

    +$def[1] .= “AREA:var1#00FF00:\”Response Times \” ”; the operator ”.=” appends more data to the array $def[1]. An area will be drawn using data from the variable var1. The color is defined in HEX notation #00FF00 (red, green, blue). The label is “Response Times”. +

    + +

    +$def[1] .= “LINE1:var1#000000 ”; As completion of the just drawn area a line (LINE1) will be drawn in black (#000000). +

    + +

    +$def[1] .= “GPRINT:var1:LAST:\”%3.4lg %s$UNIT[1] LAST \” ”;
    + +$def[1] .= “GPRINT:var1:MAX:\”%3.4lg %s$UNIT[1] MAX \” ”;
    + +$def[1] .= “GPRINT:var1:AVERAGE:\”%3.4lg %s$UNIT[1] AVERAGE \” ”;
    +

    + +

    +The three GPRINT lines build up the caption for the graph. The current values are formatted using the printf syntax. +

    + +
    + +

    Available variables

    +
    + +

    + +Using the data collector process_perfdata.pl PNP stores not only performance data but other values exported by Nagios. These values are stored in the XML file associated to the appropriate service. +

    + +

    +In the first part of the XML file the performance data is stored in separate components. +

    +
    <NAGIOS>
    +  <DATASOURCE>
    +    <TEMPLATE>check_http</TEMPLATE>
    +    <DS>1</DS>
    +    <NAME>time</NAME>
    +    <UNIT>s</UNIT>
    +    <ACT>0.006721</ACT>
    +    <WARN>1.000000</WARN>
    +    <CRIT>2.000000</CRIT>
    +    <MIN>0.000000</MIN>
    +    <MAX></MAX>
    +  </DATASOURCE>
    +....
    +</NAGIOS>
    + +

    +The field <DS> designates the data source and is used to identify the data series of the RRD files and is the key of the following arrays as well. +

    + +

    +The array $UNIT[1] contains the unit of measurement of the first data series. +

    + +

    +The XML file contains other information. When process_perfdata.pl is used in default mode all available macros are at hand with the current values. For the benefit of readability the following lines show only an extract. +

    +
    <NAGIOS>
    +...
    +  <NAGIOS_SERVICENOTIFICATIONID>8418</NAGIOS_SERVICENOTIFICATIONID>
    +  <NAGIOS_SERVICENOTIFICATIONNUMBER>0</NAGIOS_SERVICENOTIFICATIONNUMBER>
    +  <NAGIOS_SERVICEOUTPUT>HTTP OK HTTP/1.1 200 OK - 10087 bytes in 0.125 seconds</NAGIOS_SERVICEOUTPUT>
    +  <NAGIOS_SERVICEPERCENTCHANGE>0.00</NAGIOS_SERVICEPERCENTCHANGE>
    +  <NAGIOS_SERVICEPERFDATA>time=0.124811s;;;0.000000 size=10087B;;;0</NAGIOS_SERVICEPERFDATA>
    +  <NAGIOS_SERVICEPERFDATAFILE></NAGIOS_SERVICEPERFDATAFILE>
    +  <NAGIOS_SERVICEPROBLEMID>0</NAGIOS_SERVICEPROBLEMID>
    +  <NAGIOS_SERVICESTATE>OK</NAGIOS_SERVICESTATE>
    +  <NAGIOS_SERVICESTATEID>0</NAGIOS_SERVICESTATEID>
    +  <NAGIOS_SERVICESTATETYPE>HARD</NAGIOS_SERVICESTATETYPE>
    +  <NAGIOS_SHORTDATETIME>27-12-2007 13:51:23</NAGIOS_SHORTDATETIME>
    +...
    +</NAGIOS>
    + +

    +The various XML fields can be used as variables in the PNP templates. Each field is available as a variable with the same name. +

    + +

    +The value of the field <NAGIOS_SERVICEOUTPUT> is available as the variable $NAGIOS_SERVICEOUTPUT. +

    + +

    +back to contents | custom templates + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/tpl_custom.html b/share/pnp/documents/en_US/tpl_custom.html new file mode 100644 index 0000000..08a1a52 --- /dev/null +++ b/share/pnp/documents/en_US/tpl_custom.html @@ -0,0 +1,323 @@ + + + +

    Custom Templates

    +
    + +

    + +As already described under ”What are templates ?” the appearance of graphs depends on the check command used. +

    + +

    +There are situations where this behaviour must be overruled, for example when universal commands have been defined. +

    + +

    +PNP, especially process_perfdata.pl, will search for a config file (<check_command>;.cfg) in the etc/check_commands directory and read its contents (if available). +The following options can be defined in it: +

    + +
    + +

    CUSTOM_TEMPLATE

    +
    + +

    + +Outgoing from the following example of a Nagios command-definition: + +

    +
    +define command {
    +  command_name check_nrpe
    +  command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ -a "$ARG2$"
    +}
    +
    + +

    +This would lead to a call of the check_nrpe.php template even when the monitored host would use a completely different plugin which is called via NRPE. +

    + +

    +As our example command is called check_nrpe it will be searched for etc/check_commands/check_nrpe.cfg. +

    + +

    +During installation a sample config file with the extension .cfg-sample is copied to etc/check_commands. +

    +
    +# check_command check_nrpe!load!-w 4,4,4 -c 5,5,5
    +# ________0__________|       |       |
    +# ________1__________________|       |
    +# ________2__________________________|
    +#
    +CUSTOM_TEMPLATE = 1
    +
    + +

    +CUSTOM_TEMPLATE = 1 assures that only the contents of $ARG1$ will be used as a template name. As $ARG1$ contains “load” in this example the template name would result in “load.php”. +

    + +

    +CUSTOM_TEMPLATE = 0,1 results in → “check_nrpe_load.php” +

    + +

    +CUSTOM_TEMPLATE = 1,0 results in → “load_check_nrpe.php” +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    DATATYPE

    +
    + +

    + +The option “DATATYPE” controls the datatype which is used during creation of the RRD database. Default is “GAUGE”. For consecutive values the type should be “COUNTER”. Plugin-developers should use the unit “c” for counters but this is not always the case. +

    + +

    +To set all datasources to COUNTER + +

    +
    DATATYPE = COUNTER
    + +

    +Setting datasources to different types + +

    +
    DATATYPE = GAUGE,GAUGE,COUNTER,COUNTER
    + +

    +More datatypes are explained in the RRDTool documentation found at rrdcreate. +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    USE_MIN_ON_CREATE and USE_MAX_ON_CREATE

    +
    + +

    + +In a few situations it might be necessary to limit the values which are valid for RRDTool. +

    + +

    +RRD databases can be created with fixed minimum and maximum values. You will find further details at http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html. +

    + +

    +Account for the maximum value taken from the performance data + +

    +
    USE_MAX_ON_CREATE = 1
    + +

    +Account for the minimum value taken from the performance data + +

    +
    USE_MIN_ON_CREATE = 1
    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    RRD_STORAGE_TYPE

    +
    +
    RRD_STORAGE_TYPE = SINGLE
    + +

    + +The option RRD_STORAGE_TYPE defines the kind of data storage. +

    + +

    +Possible values are MULTIPLE and SINGLE, respectively. +

    + +

    +SINGLE: A RRD database per service +

    + +

    +MULTIPLE: One or more RRD databases per service. Each datasource will be stored in a separate RRD database. +

    + +

    +ATTENTION: The data will not be migrated automatically! +You will find a conversion script here. +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    RRD_HEARTBEAT

    +
    + +

    + +Starting with PNP 0.6.1 +

    +
    RRD_HEARTBEAT = 305
    + +

    +After <RRD_HEARTBEAT> seconds RRDtool expects new data. +

    + +

    +More information at http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html +

    + +

    +This option has effect only during creation of the RRD database. +

    + +
    + +

    Hints on Template Names

    +
    + +

    + +In most situations, one can easily get desired template names, by using suitable command object definitions. +

    + +

    +Consider the followng example: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$
    +}
    +
    + +

    + +with commands like: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load -w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    +Even when using “CUSTOM_TEMPLATE = 1” one would end up in template names like “_usr_lib_nagios_plugins_check_load_-w_4,4,4_-c_5,5,5”, which is highly undesired, especially because of the parameters in it. +

    + +

    +Solution 1: Split parameters into separate $ARGn$ +

    + +

    +A simple solution is to use the following command object definition: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +with commands like: + +

    +
    +  …
    +  check_command check_by_ssh!/usr/lib/nagios/plugins/check_load!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +(notice the additional “!”) +

    + +

    +This even works, when $ARG2$ is let empty. +

    + +

    +Of course one would still need to set “CUSTOM_TEMPLATE = 1”. +

    + +

    + +Solution 2: Hide the remote executor inside the command object definition +

    + +

    +Another way is to “hide” the remote excutor in the respective command object definitions. +

    + +

    +Instead of defining: + +

    +
    +define command {
    +  command_name check_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ $ARG1$ $ARG2$
    +}
    +
    + +

    + +one would define the following for every command to be remotely executed: + +

    +
    +define command {
    +  command_name check_load_by_ssh
    +  command_line /usr/bin/ssh $HOSTADDRESS$ /usr/lib/nagios/plugins/check_load $ARG1$
    +}
    +
    + +

    + +with commands like: + +

    +
    +  …
    +  check_load_by_ssh!-w 4,4,4 -c 5,5,5
    +  …
    +
    + +

    + +Of course one must not set “CUSTOM_TEMPLATE = 1” in this way. +

    + +

    + +Which of above two solutions one follows is largely a matter of taste. +

    + +

    +back to contents | PNP in distributed environments + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/tpl_helper.html b/share/pnp/documents/en_US/tpl_helper.html new file mode 100644 index 0000000..f88eb93 --- /dev/null +++ b/share/pnp/documents/en_US/tpl_helper.html @@ -0,0 +1,247 @@ + + + +

    Template Helper Functions

    +
    + +

    + +Helper functions are meant to simplify the creation of templates and trap errors +

    + +
    + +

    rrd::def

    +
    + +

    + +string rrd::def ( $vname, $rrdfile, $ds, [ $cf='AVERAGE' ] ) +

    +
    $def = rrd::def('var1', $RRDFILE[0], $DS[0], 'MAX');
    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html +

    + +
    + +

    rrd::cdef

    +
    + +

    + +string rrd::cdef ( $vname, $rpn, ) +

    +
    $def = rrd::cdef('var1_bits', 'var1,8,*' );
    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html +

    + +
    + +

    rrd::vdef

    +
    + +

    + +string rrd::vdef ( $vname, $rpn, ) +

    +
    $def = rrd::vdef('var1_avg', 'var1,AVERAGE' );
    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_data.en.html +

    + +
    + +

    rrd::line[1-3]

    +
    + +

    + +string rrd::line[1-3] ( $vname, $color, [ $text ], [ $stack ] ) +

    +
    $def .= rrd::line1('var1', #ff00ff );
    + +

    +Draws a simple line one pixel wide without label +

    +
    $def .= rrd::line3('var1', '#ff00ff', 'Load' );
    + +

    +Draws a line three pixels wide with label “Load” +

    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html +

    + +
    + +

    rrd::area

    +
    + +

    + +string rrd::area ( $vname, $color, [ $text ], [ $stack ] ) +

    +
    $def .= rrd::area('var1', '#ff00ff', 'Load' );
    + +

    +Draws an area with label “Load” +

    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html +

    + +
    + +

    rrd::gprint

    +
    + +

    + +string rrd::gprint ( $vname, $cf, [ $text ] ) +

    +
    $def .= rrd::gprint('var1', 'MAX', '%4.2lf %s Max' );
    +
    $def .= rrd::gprint('var1', array('MIN', 'MAX', 'AVERAGE'), '%4.2lf %s' );
    + +

    +If $cf is an array the legend will be formatted automatically +

    + +

    +http://oss.oetiker.ch/rrdtool/doc/rrdgraph_graph.en.html +

    + +
    + +

    rrd::color

    +
    + +

    + +string rrd::color ( $num [, $num]) +

    + +

    +Returns a color from the HTML color table. The second (optional) argument allows to specify an alpha value used to set the transparency of the selected color. +

    + +

    +Starting with PNP 0.6.18 the function accepts a third argument which refers to colour scheme definitions in config.php (or config_local.php which is update safe). There you can find the array $scheme[], e.g. +

    +
    $scheme['Reds'] = array (...)
    + +

    +Within the template you define +

    +
    $schema = $this->config->scheme['Reds'];
    +...
    +rrd::color ($key, '', $schema);
    + +

    +This way you select the value taken from $scheme['Reds'][$key]. If $key is not within the array or you misspelled the name (case sensitive) then the default colour palette is used. +

    + +
    + +

    rrd::gradient

    +
    + +

    + +string rrd::gradient ( $vname, [$start_color], [$end_color], [$label], [$steps], [$lower] ) +

    + +

    +Creates a color gradient from $start_color to $end_color +

    +
    $def .= rrd::gradient('var1', '#ff0000', '#ffff00' );
    + +

    + +Example +

    + +
    + +

    rrd::cut

    +
    + +

    + +string rrd::cut ( $text, $length ) +

    +
    $label = rrd::cut($LABEL[0], 18);
    + +

    +Cuts a text to a given length $length or fills it up to $length if needed.
    + +This function is helpful if legend needs to be justified but length of label is unknown. +

    + +
    + +

    rrd::ticker

    +
    + +

    + +string rrd::ticker ( $vname, $warning, $critical, [$fraction], [$opacity], [$color_OK], [$color_WARN], [$color_CRIT] ) +

    + +

    +Creates a colorized bar at the top of the chart which shows different colors depending on states OK, WARNING & CRITICAL +

    +
    $def .= rrd::ticker( "var1", $WARN[0], $CRIT[0] );
    + +

    + +Example +

    + +
    + +

    rrd::alerter

    +
    + +

    + +string rrd::alerter ( $vname, $label, $warning, $critical, [$opacity], [$unit], [$color_OK], [$color_WARN], [$color_CRIT], [$line_col] ) +

    + +

    +Creates colorized areas, which show different colors depending on states OK, WARNING & CRITICAL +

    +
    $def .= rrd::alerter( "var1", $LABEL[0], $WARN[0], $CRIT[0], "FF", $UNIT[0] );
    + +

    +Example +

    + +
    + +

    rrd::alerter_gr

    +
    + +

    + +string rrd::alerter_gr ( $vname, $label, $warning, $critical, [$opacity], [$unit], [$color_OK], [$color_WARN], [$color_CRIT], [$line_col], [$start_color] ) +

    + +

    +Creates colorized gradients, which show different colors depending on states OK, WARNING & CRITICAL +

    +
    $def .= rrd::alerter_gr( "var1", $LABEL[0], $WARN[0], $CRIT[0], "FF", $UNIT[0] );
    + +

    +Example + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/tpl_helper_pnp.html b/share/pnp/documents/en_US/tpl_helper_pnp.html new file mode 100644 index 0000000..74bacde --- /dev/null +++ b/share/pnp/documents/en_US/tpl_helper_pnp.html @@ -0,0 +1,90 @@ + + + +

    PNP Helper Functions

    +
    + +

    + +PNP Helper functions are meant to simplify the creation of templates. In contrast to the rrd helper functions they don't call existing RRDtool functions. +

    + +
    + +

    pnp::adjust_unit

    +
    + +

    + +(string,number,string,number) pnp::adjust_unit ( $value, $base=1000, $format='%.3lf' ) +

    + +

    +The purpose of this function is to “normalize” large numbers. Modern hard disks have reached sizes of several GB or TB and looking at numbers like 1521073648234 you begin to count the digits so it would be more convienient to translate the value. The same applies to network traffic. +

    + +

    +The function takes up to three parameters and returns an array with four elements in any case. +

    +
      +
    • The first parameter to be passed is the number (including an “UOM”, if applicable)
      +
    • +
    • The second parameter is optional and defaults to “1000” (e.g. traffic), but might be “1024” (e.g. disk size) as well
      +
    • +
    • The third parameter is optional, defaults to '%.3lf', and specifies the format of the value to be returned
      +
    • +
    +
    $size = pnp::adjust_unit(1521073648234,1024,'%7.3lf');
    + +

    +Please note that “$size” is an array consisting of four fields: +

    +
     $size[0] := "  1.383 T"
    + +

    +contains the formatted value including the unit +

    +
     $size[1] := "1.383"
    + +

    +contains the formatted number +

    +
     $size[2] := "T"
    + +

    +contains the unit +

    +
     $size[3] := "1099511627776"
    + +

    +contains the divisor +

    + +

    +Assuming check_disk returns “MB” as UOM you can append that as well + +

    +
    $disk = pnp::adjust_unit("1524MB",1024,'%7.3lf');
    + +

    + +will result in +$disk[0] := “1.448 GB” +

    + +

    +
    + +“old” check_disk template with %s directive
    + +

    + +

    +
    + +“new” check_disk template with pnp::adjust_unit + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/tpl_special.html b/share/pnp/documents/en_US/tpl_special.html new file mode 100644 index 0000000..958df3c --- /dev/null +++ b/share/pnp/documents/en_US/tpl_special.html @@ -0,0 +1,187 @@ + + + +

    Special templates

    +
    + +

    + +“special templates” (starting with PNP 0.6.5) are used to combine data from arbitrary hosts and services and thus are not connected directly to a host or service. +

    + +

    +Often it is desired to show data from several services in one graph. Every time the "pages" will not be sufficient the special templates may come into play. +

    + +
    + +

    Basics

    +
    + +

    + +“Special templates” will be searched in pnp4nagios/share/templates.special and must have the extension .php. +

    + +

    +They are called via the controller “special” using + +

    +
    http://<your-nagios-server>/pnp4nagios/special?tpl=<template>
    + +

    + +<template> is to be replaced with the particular template without the extension .php. +

    + +

    +An appropriate link will be shown in the PNP interface if at least one “special template” was found. +

    + +
    + +

    Example

    +
    + +

    + +The task is to show the response times of all web servers with hostnames websrv, websrv02, and websrv03 in one graph. The data is provided by the service “HTTP”. +

    + +

    +Step 1: create a template “websrv_response_times.php” in the folder pnp4nagios/share/templates.special +

    + +

    +“Special templates” always start with the definition of a title and a comment. +

    +
    $this->MACRO['TITLE']   = "HTTP Response Times";
    +$this->MACRO['COMMENT'] = "HTTP Response Times for all Cluster Nodes";
    + +

    +Step 2: create a list of all hosts/services which come into question. PNP provides a function tplGetServices() to accomplish this task. +

    + +

    +tplGetServices() expects two parameters. +

    + +

    +Parameter 1 is a regular expression for the host(s), parameter 2 a regular expression for the service(s). +

    +
    $services = $this->tplGetServices("websrv","HTTP");
    + +

    +$services now is an array with all services found. +

    + +

    +To ease template development and to give an insight on the data structures you can force Kohana to stop processing using an exception. +

    + +

    +To show the data of $services you just need the following line: +

    +
    throw new Kohana_exception(print_r($services,TRUE));
    + +

    +Output of pnp4nagios/special?tpl=websrv_response_times +

    +
    +Array ( 
    +  [0] => Array ( 
    +     [host] => websrv01 
    +     [service] => HTTP 
    +  ) 
    +  [1] => Array ( 
    +     [host] => websrv02
    +     [service] => HTTP 
    +  ) 
    +  [2] => Array ( 
    +     [host] => websrv03
    +     [service] => HTTP 
    +  ) 
    +)
    +
    + +

    +The variable $services contains an array with all services found, in this case three hosts with the service “HTTP”. +

    + +

    +Step 3: Iterating the array $services and creating the graph definitions +

    +
    foreach($services as $key=>$val){
    +    $data      = $this->tplGetData($val['host'],$val['service']);
    +    $hostname  = rrd::cut($data['MACRO']['HOSTNAME'], 15);
    +    $def[0]   .= rrd::def("var$key" , $data['DS'][0]['RRDFILE'], $data['DS'][0]['DS'] );
    +    $def[0]   .= rrd::line1("var$key", rrd::color($key), $hostname);
    +    $def[0]   .= rrd::gprint("var$key", array("MAX", "AVERAGE"));
    +}
    + +

    +Inside the loop the function tplGetData is used to read the particular XML file. The data is returned as an array called $data. +

    + +

    +In this example some other little PNP helpers are used recognisable by the extension rrd::. +

    + +

    +The function rrd::cut() cuts a string to a specific length or fills up to this length. This might be helpful to align the legend. +

    + +

    +The function rrd::gprint() creates the legend below the graph. +

    + +

    +The function rrd::color() returns a colour from a predefined list of colours. +

    + +

    +You will find more information on the PNP helpers here. +

    +
    <?php
    +#
    +# Special Template websrv_response_times.php
    +#
    +$this->MACRO['TITLE']   = "HTTP Response Times";
    +$this->MACRO['COMMENT'] = "HTTP Response Times for all Cluster Nodes";
    +#
    +# Get a List of Services by regex 
    +# Option 1 = 'Host Regex'
    +# Option 2 = 'Service Regex'
    +#
    +$services = $this->tplGetServices("websrv","HTTP");
    +#throw new Kohana_exception(print_r($services,TRUE));
    +#
    +# The Datasource Name for Graph 0
    +$ds_name[0] = "Response Times";
    +$opt[0]     = "--title \"Response Times\"";
    +$def[0]     = "";
    +#
    +# Iterate through the list of hosts
    +foreach($services as $key=>$val){
    +    #
    +    # get the data for a given Host/Service
    +    $data = $this->tplGetData($val['host'],$val['service']);
    +    #
    +    # Throw an exception to debug the content of $a
    +    # Just to get Infos about the Array Structure
    +    #
    +    #throw new Kohana_exception(print_r($a,TRUE));
    +    $hostname   = rrd::cut($data['MACRO']['HOSTNAME']);
    +    $def[0]    .= rrd::def("var$key" , $data['DS'][0]['RRDFILE'], $data['DS'][0]['DS'] );
    +    $def[0]    .= rrd::line1("var$key", rrd::color($key), $hostname);
    +    $def[0]    .= rrd::gprint("var$key", array("MAX", "AVERAGE"));
    +}
    +?>
    + +

    +back to contents + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/upgrade.html b/share/pnp/documents/en_US/upgrade.html new file mode 100644 index 0000000..4bbce5b --- /dev/null +++ b/share/pnp/documents/en_US/upgrade.html @@ -0,0 +1,220 @@ + + + +

    Upgrade to version 0.6.x

    +
    + +

    + +The web-frontend has been completely rewritten and is now based on the PHP MVC framework Kohana. This leads to changed dependencies which must be checked prior to installation. +

    + +

    +Note: At first an upgrade is like a new installation. Afterwards some changes should be made which are described further down. +

    + +

    +Without specifying any options during ./configure PNP 0.4.x was installed below an existing Nagios-Installation at /usr/local/nagios. +

    + +

    +Without specifying any options during ./configure PNP 0.6.x will be installed in a separate directory at /usr/local/pnp4nagios, i.e. it should be viewed as an independent application. +

    + +

    +Note: It is sufficient to copy the *.rrd files from the old to the new location. They contain the data The *.xml files are recreated every time new performance data arrives as they contain meta information. The internal structure of the xml files has changed so you wouldn't be able to use them either way. +

    + +
    + +

    Comparison of the structure

    +
    + +

    + +Summary of a PNP 0.4.14 installation +

    +
    +./configure
    +...
    +*** Configuration summary for pnp 0.4.14 05-02-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/nagios
    +  HTML Dir:                         /usr/local/nagios/share/pnp
    +  Config Dir:                       /usr/local/nagios/etc/pnp
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/nagios/share/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/nagios/var/spool/perfdata/
    +
    + +

    +Summary of a PNP 0.6.0 installation +

    +
    +./configure
    +...
    +*** Configuration summary for pnp4nagios-0.6.0 07-30-2009 ***
    +
    +  General Options:
    +  -------------------------         -------------------
    +  Nagios user/group:                nagios nagios
    +  Install directory:                /usr/local/pnp4nagios
    +  HTML Dir:                         /usr/local/pnp4nagios/share
    +  Config Dir:                       /usr/local/pnp4nagios/etc
    +  Location of rrdtool binary:       /usr/bin/rrdtool Version 1.3.1
    +  RRDs Perl Modules:                FOUND (Version 1.3001)
    +  RRD Files stored in:              /usr/local/pnp4nagios/var/perfdata
    +  process_perfdata.pl Logfile:      /usr/local/pnp4nagios/var/perfdata.log
    +  Perfdata files (NPCD) stored in:  /usr/local/pnp4nagios/var/spool
    +
    +  Web Interface Options:  -------------------------         -------------------
    +  HTML URL:                         http://localhost/pnp4nagios/
    +  Apache Config File:               /etc/apache2/conf.d/pnp4nagios.conf
    +
    + +

    +Looking at these lines result in the parameters to be changed and the upgrade strategy. +

    + +
    + +

    Adjustments

    +
    + +

    + +The templates of the action_url definitions have changed. Instead of ”/nagios/pnp” the URL should be ”/pnp4nagios” and instead of “index.php” now “graph” will be used. +

    +
    define host {
    +  name       host-pnp
    +  register   0
    +  action_url /pnp4nagios/graph?host=$HOSTNAME$
    +}
    +
    +define service {
    +  name       srv-pnp
    +  register   0
    +  action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +}
    + +

    +The definitions for the preview popup function are similar + +

    +
    define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    + +

    + +Attention: It is not an error that the strings in front and after “class” contain only one quote. +

    + +

    +Other than described in the 0.4.x documentation these templates can be used for Nagios 2.x and 3.x. +

    + +

    +The variables in the files in the templates folder have to be initialised before first use. Example +

    +
    $lower = ""
    + +

    + +Earlier you were able to append to variables which weren't initialised before first use. Example: + +

    +
    foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    + +Now you have to change that to + +

    +
    +$def[1] = "";
    +foreach ($DS as $i) {
    +    $def[1] .= "DEF:var$i=$rrdfile:$DS[$i]:AVERAGE " ;
    + +

    + +
    + +Constants in template files don't work anymore, so that they have to be converted to variables. +

    +
    define("_WARNRULE", '#FFFF00');
    + +

    +may be changed to +

    +
     $WARNRULE = '#FFFF00';
    + +

    +Please keep in mind that all occurrences have to be changed ;-). +

    + +
    + +

    Upgrade scenario using NPCD

    +
    +
      +
    1. planning the new setup
      +
    2. +
    3. perform test installation and acquaint oneself with the new system
      +
    4. +
    5. create backup of the old installation
      +
    6. +
    7. install PNP 0.6.x at /usr/local/pnp4nagios
      +
    8. +
    9. make install-config
      +
    10. +
    11. make install-webconf
      +
    12. +
    13. reload Apache
      +
    14. +
    15. test Apache-config
      +
        +
      1. call of /pnp4nagios has to report an empty perfdata directory
        +
      2. +
      +
    16. +
    17. create /usr/local/pnp4nagios/etc/npcd.cfg from npcd.cfg-sample
      +
        +
      1. check paths and adapt changes from 0.4.x if necessary
        +
      2. +
      +
    18. +
    19. adjust all paths in nagios.cfg to the new PNP installation
      +
    20. +
    21. adjust all paths in the command definitions
      +
    22. +
    23. stop npcd using /etc/init.d/npcd stop
      +
    24. +
    25. make install-init installs the new init script for npcd
      +
    26. +
    27. /etc/init.d/nagios stop
      +
    28. +
    29. copy /usr/local/nagios/share/perfdata to /usr/local/pnp4nagios/var/perfdata. Attention: check the permissions
      +
    30. +
    31. /etc/init.d/npcd start
      +
    32. +
    33. /etc/init.d/nagios start
      +
    34. +
    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/verify.html b/share/pnp/documents/en_US/verify.html new file mode 100644 index 0000000..90aa790 --- /dev/null +++ b/share/pnp/documents/en_US/verify.html @@ -0,0 +1,115 @@ + + + +

    Checking the installation

    +
    + +

    + +If everything went well until now you can try to call PNP using your web browser. +When using the installation with default values PNP should be called using http://<server name>/pnp4nagios/. +The first time you will see a page “PNP4Nagios Environment Tests” which includes different checks of necessary components. Obviously all checks have to be passed successfully before you can proceed. Please follow the instructions given on that page.
    + +

    + +

    +If all tests have passed *successfully* the file pnp4nagios/share/install.php can be deleted or renamed. Not till then the web interface is reachable. +

    + +

    +Alternatively you can create a file called pnp4nagios/share/install.ignore which will prevent the call of the installer after further updates. +

    + +

    +If you receive the message “PHP magic_quotes_gpc is deprecated” then please locate your php.ini and set the value to Off. +

    + +

    +Called without any arguments PNP looks for RRD and XML files in pnp4nagios/var/perfdata and shows all graphs of the first host. +

    + +

    +ATTENTION: Immediately after (re-)starting Nagios after you enabled the processing of performance data you will get error messages in your browser because performance data has to be collected and stored in RRD files. Depending on the check interval you are using you have to wait some time before you can view the first graphs. +

    + +
    + +

    Debug Logfile

    +
    + +

    + +Calling make install-config during installation will create a sample config file etc/process_perfdata.cfg-sample. The values in the sample file will correspond to the defaults used by process_perfdata.pl so normally you do not have a file called process_perfdata.cfg while running the procedure.
    + +However you can influence the way process_perfdata.pl works by changing options which have to be specified in process_perfdata.cfg. +

    + +

    +The most important options launching PNP are LOG_LEVEL and LOG_FILE. We recommend setting the LOG_LEVEL value to “2” so you can track what process_perfdata.pl will do. +Most likely we will ask for excerpts from perfdata.log if you open a support request on the mailing lists as well as the output of the verify_pnp_config script so please provide them ;-). +

    + +

    +During normal operation the debug level should be set to 0 to avoid performance issues due to unnecessary entries in the log file. +

    + +
    + +

    Something went wrong

    +
    + +

    + +Some basic settings should be checked +

    + +

    +1. Have any RRD and XML files been created? +process_perfdata.pl will create a new directory under pnp/perfdata for every host. In this directory an RRD database and an XML file will be created for every service. The host data will be stored in _HOST_.xml and _HOST_.rrd respectively.
    + +If graphing stops out of a sudden then open the appropriate XML file. There are two tags called <RC> and <TXT>. <RC> shows the return code of the RRDtool update and <TXT> a textual description.
    + +Sometimes you have to specify additional options so that performance data is produced. In some cases a wrapper script might help.
    + +However not all checks provide performance data. That applies - among others - to “check_ping” in contrast to “check_icmp” which does provide data (starting with Nagios plugin version 1.4.12 check_ping does provide performance data).
    + +Using the web interface the detail information of hosts/services shows a field “Performance Data”. If it is empty there is no data available so no files are written to the appropriate directory and that is why PNP does not provide you with graphs!
    + +The following image shows the information of a “PING” service. The output of the plugin is surrounded by a blue border, the performance data by a red one.
    + +status information +

    + +

    +2. Has nagios called process_perfdata.pl? +In the config file for process_perfdata.pl (etc/process_perfdata.cfg) you can increase the debug level. Data processing will be logged in var/perfdata.log. +

    + +

    +3. Graphs are shown without text? +Have a look at the requirements. +

    + +

    +4. Some graphs are shown, others report the error “parser error: Input is not proper UTF-8” or something similar. Please check if your data contains “special” characters not present in the ASCII set. Try to set XML_ENC in process_perfdata.cfg to ISO-8859-1 or something appropriate. Wait until the xml file is newly created and retry. +

    + +

    +5. Using the npcdmod module the value of the nagios.cfg directive event_broker_options may have to be adapted if it was modified. You'll find some details here. +

    + +

    +6. You can use the script verify_pnp_config.pl after installation to check your settings and if performance data is present. +

    + +

    +7. Things look OK, but some files are being left in the spool directory (/usr/local/pnp4nagios/var/spool/<perfdata_filename>-PID-<process_perfdata_pid>). If process_perdata.pl is not able to write to the destination directory (/usr/local/pnp4nagios/share/perfdata/<host>), it will stop and not remove the file. That will increase the size of the spool directory and slow down performance data processing. This problem is likely to occur if you have copied directories from a previous installation and/or manually created directories and left them with wrong permissions or wrong ownership. +

    + +

    +back to contents | verify_pnp_config.pl + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/verify_pnp_config.html b/share/pnp/documents/en_US/verify_pnp_config.html new file mode 100644 index 0000000..a25f0b3 --- /dev/null +++ b/share/pnp/documents/en_US/verify_pnp_config.html @@ -0,0 +1,132 @@ + + + +

    verify_pnp_config

    +
    + +

    + +In case of problems there is a script called verify_pnp_config.pl located on http://verify.pnp4nagios.org. It enables you to check the configuration settings as well as performance data of hosts or services. It can be used prior and during runtime of PNP. +

    + +
    + +

    Download

    +
    +
    +wget http://verify.pnp4nagios.org/verify_pnp_config
    +
    + +
    + +

    Test

    +
    + +

    + +The verify script is located on http://verify.pnp4nagios.org and needs three start options +

    +
      +
    • --mode One of the modes described on modes
      +
    • +
    • --config Location of nagios.cfg or icinga.cfg
      +
    • +
    • --pnpcfg Path to PNP´s etc directory
      +
    • +
    + +

    + +Calling perl verify_pnp_config will show the available options. +

    + +

    +The following is a sample run + +

    +
    +lenny:~# perl verify_pnp_config --mode npcdmod --config=/usr/local/nagios/etc/nagios.cfg --pnpcfg=/usr/local/pnp4nagios/etc
    +[INFO]  ========== Starting Environment Checks ============
    +[INFO]  My version is: verify_pnp_config-0.6.14-R.31
    +[INFO]  Reading /usr/local/nagios/etc/nagios.cfg
    +[OK  ]  Running product is 'nagios'
    +[OK  ]  object_cache_file is defined
    +[OK  ]  object_cache_file=/usr/local/nagios/var/objects.cache
    +[INFO]  Reading /usr/local/nagios/var/objects.cache
    +[OK  ]  resource_file is defined
    +[OK  ]  resource_file=/usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/nagios/etc/resource.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/process_perfdata.cfg
    +[INFO]  Reading /usr/local/pnp4nagios/etc/pnp4nagios_release
    +[OK  ]  Found PNP4Nagios version "0.6.14"
    +[OK  ]  Effective User is 'nagios'
    +[OK  ]  User nagios exists with ID '1000'
    +[OK  ]  Effective group is 'nagios'
    +[OK  ]  Group nagios exists with ID '1000'
    +[INFO]  ========== Checking npcdmod Mode Config  ============
    +[OK  ]  process_performance_data is 1 compared with '/1/'
    +[OK  ]  event_broker_options is defined
    +[OK  ]  event_broker_options=-1
    +[OK  ]  event_broker_option bits 2 and 3 enabled (12)
    +[OK  ]  broker_module is defined
    +[OK  ]  broker_module=/usr/local/pnp4nagios/lib/npcdmod.o config_file=/usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  npcdmod.o config file is /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg used by npcdmod.o is readable
    +[OK  ]  npcd daemon is running
    +[OK  ]  /usr/local/pnp4nagios/etc/npcd.cfg is used by npcd and readable
    +[OK  ]  npcd and npcdmod.o are using the same config file (/usr/local/pnp4nagios/etc/npcd.cfg)
    +[INFO]  Nagios config looks good so far
    +[INFO]  ========== Checking config values ============
    +[INFO]  Reading /usr/local/pnp4nagios/etc/npcd.cfg
    +[OK  ]  Script /usr/local/pnp4nagios/libexec/process_perfdata.pl is executable
    +[INFO]  ========== Starting global checks ============
    +[OK  ]  status_file is defined
    +[OK  ]  status_file=/dev/shm/status.dat
    +[INFO]  Reading /dev/shm/status.dat
    +[INFO]  ==== Starting rrdtool checks ====
    +[OK  ]  RRDTOOL is defined
    +[OK  ]  RRDTOOL=/usr/bin/rrdtool
    +[OK  ]  /usr/bin/rrdtool is executable
    +[OK  ]  RRDtool 1.3.1  Copyright 1997-2008 by Tobias Oetiker <tobi@oetiker.ch>
    +[OK  ]  USE_RRDs is defined
    +[OK  ]  USE_RRDs=1
    +[OK  ]  Perl RRDs modules are loadable
    +[INFO]  ==== Starting directory checks ====
    +[OK  ]  RRDPATH is defined
    +[OK  ]  RRDPATH=/usr/local/pnp4nagios/var/perfdata
    +[OK  ]  Perfdata directory '/usr/local/pnp4nagios/var/perfdata' exists
    +[WARN]  62 hosts/services are not providing performance data
    +[WARN]  'process_perf_data 1' is set for 43 hosts/services which are not providing performance data!
    +[WARN]  'process_perf_data 0' is set for 27 of your hosts/services
    +[OK  ]  'process_perf_data 1' is set for 243 of your hosts/services
    +[INFO]  ==== System sizing ====
    +[OK  ]  269 hosts/service objects defined
    +[INFO]  ==== Check statistics ====
    +[WARN]  Warning: 3, Critical: 0
    +[WARN]  Checks finished...
    +
    + +
    + +

    Performance data

    +
    + +

    +Starting with 0.6.19-R.37 (2013-02-17) the script will accept the option --object (or -o) followed by a string to specify a host name and/or service description to additionally show performance data (if any) of the object(s) found. The data is enclosed in brackets, followed by the value of the directive process_performance_data (ppd=n). +

    + +

    +host = show performance information for host host
    + +;service = show performance information for service service
    + +host;service = show performance information for service service on host host +

    + +

    +The strings are taken as regular expressions (perl syntax). + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/webfe.html b/share/pnp/documents/en_US/webfe.html new file mode 100644 index 0000000..36ed83e --- /dev/null +++ b/share/pnp/documents/en_US/webfe.html @@ -0,0 +1,149 @@ + + + +

    Nagios web frontend

    +
    + +

    +Of course PNP should be easily accessible. You do not want to search long for the right graph. +

    + +

    +Nagios itself features external URLs using so called extended info configs. Due to changes between Nagios 2.x and Nagios 3.x both versions are described. +

    + +
    + +

    Nagios 2.x

    +
    + +

    + +With Nagios 2.x the integration of external URLs into the nagios web interface is made using Extended Info Objects for services. For PNP we use the directive action_url to call the PNP web frontend with the appropriate options. +

    +
    +define serviceextinfo {
    +   host_name             localhost
    +   service_description   load
    +   action_url            /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +}
    +
    + +

    +You have to specify an additional Extended Info Definition for every service. +

    + +
    + +

    Nagios 3.x

    +
    + +

    + +Since nagios 3.0 the action_url-directive has be moved to the host or service definition. This way the definition of URLs to the PNP-interface has been simplified. The serviceextinfo and hostextinfo definitions are deprecated. +

    + +

    +First two nagios templates are defined. If you used the Nagios quickstart installation guides you can append these lines to templates.cfg: +

    +
    +define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    +
    + +

    +These two templates can now be included via “use srv-pnp” or “use host-pnp” for services and hosts respectively. If you used the quickstart installation guide you might for example edit the file localhost.cfg and add the template to the host or service definition as follows: +

    +
    define host{
    +        use                     linux-server,host-pnp    ; Name of host templates to use
    +                                                         ; This host definition will inherit all variables that are defined
    +                                                         ; in (or inherited by) the linux-server host template definition.
    +        host_name               localhost
    +        alias                   localhost
    +        address                 127.0.0.1
    +        }
    +
    +
    define service{
    +        use                     local-service,srv-pnp   ; Name of service template to use
    +        host_name               localhost
    +        service_description     PING
    +        check_command           check_ping!100.0,20%!500.0,60%
    +        }
    +
    + +

    + +The links to the correct URLs are created automagically.
    +
    + +

    + +

    +Tips: if you want to open the PNP window in your main frame (on the right of the menu) instead of a new page, just set action_url_target=main in your nagios cgi.cfg +

    + +
    + +

    Popups

    +
    + +

    +You can integrate PNP into Nagios in a way that you have current graphs without clicking any icons. This can be accomplished using the CGI Includes which allow us to include JavaScript code in the status detail view ( status.cgi ). +

    + +

    +Prerequisites: +

    +
      +
    • PNP is installed and running
      +
    • +
    • the file status-header.ssi from the contrib/ssi/ folder of the PNP package was copied to /usr/local/nagios/share/ssi/.
      +Attention: This file must NOT be executable. Otherwise it will be treated as a CGI which will result in an error.
      +*Note to Apache admins*: Apache ssi and Nagios ssi only have a similar name.
      +
    • +
    • the appropriate service definition(s) has/have been modified. Please note that until Nagios 2.x you have to modify the serviceextinfo definition (which is deprecated starting with Nagios 3).
      +
    • +
    + +

    + +Definition: + +

    +
    +define host {
    +   name       host-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_
    +   register   0
    +}
    +
    +define service {
    +   name       srv-pnp
    +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=$SERVICEDESC$
    +   register   0
    +}
    +
    + +

    + +After a restart of Nagios (after modifying the definitions) the result might look like this:
    + + +

    + +

    +back to contents | config options + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/webfe_cfg.html b/share/pnp/documents/en_US/webfe_cfg.html new file mode 100644 index 0000000..a1d8704 --- /dev/null +++ b/share/pnp/documents/en_US/webfe_cfg.html @@ -0,0 +1,136 @@ + + + +

    PNP Web Frontend

    +
    + +

    + +The behaviour of the PNP Web-Frontend can be controlled through the config file etc/config.php. This file will be overwritten during updates of PNP as the paths and options are detected during ./configure. +

    + +

    +Own adjustments should be made in etc/config_local.php. If this file does not exist the file config.php can be taken as a guideline. +

    + +
    + +

    etc/config.php

    +
    + +

    + +Following the most important parameters: +

    + +

    +The path to the RRDtool binary. Will be detected by ./configure + +

    +
     $conf['rrdtool'] = "/usr/bin/rrdtool";
    + +

    + +Height and width of the RRD graphs + +

    +
     $conf['graph_width'] = "500";
    + $conf['graph_height'] = "100";
    + +

    + +Screen sizes may vary, pages sizes won't. The following two directives enable you to specify different sizes for the creation of PDFs. If they aren't specified the values of the graph sizes are taken. + +

    +
     $conf['pdf_width'] = "675";
    + $conf['pdf_height'] = "100";
    + +

    + +Additional options passed with every call of RRDTool, for example --slope-mode to smooth the graphs + +

    +
     $conf['graph_opt'] = "";
    + +

    + +The path to the RRD and XML files created by process_perfdata.pl + +

    +
     $conf['rrdbase'] = "/usr/local/pnp4nagios/var/perfdata/";
    + +

    + +The path to the config file for the pages. + +

    +
     $conf['page_dir'] = "/usr/local/pnp4nagios/etc/pages/";
    +
    + +

    +PNP pages will be refreshed every n seconds + +

    +
     $conf['refresh'] = "90";
    +
    + +

    +Max. age of RRD files in seconds. After reaching this value links to the graphs will be marked as inactive + +

    +
     $conf['max_age'] = 60*60*6;
    +
    + +

    + +Base URL to the Nagios CGIs + +

    +
     $conf['nagios_base'] = "/nagios/cgi-bin";
    +
    + +

    + +List of users who are allowed to view links to the services of the current host + +

    +
     $conf['allowed_for_service_links'] = "EVERYONE";
    +
    + +

    +List of users who can view/access the host search field + +

    +
     $conf['allowed_for_host_search'] = "EVERYONE";
    +
    + +

    +If PNP is called with a host only ( index.php?host=<myserver> ), the defined user is shown an overview of all services related to this host + +

    +
     $conf['allowed_for_host_overview'] = "EVERYONE";
    +
    + +

    +The periods of time the RRD graphs will show are determined using the array $views[]. The title and number of graphs can be specified globally in this place +

    +
    +$views[] = array('title' => 'One Hour',  'start' => (60*60) );
    +$views[] = array('title' => '4 Hours',   'start' => (60*60*4) );
    +$views[] = array('title' => '25 Hours',  'start' => (60*60*25) );
    +$views[] = array('title' => 'One Week',  'start' => (60*60*25*7) );
    +$views[] = array('title' => 'One Month', 'start' => (60*60*24*32) );
    +$views[] = array('title' => 'One Year',  'start' => (60*60*24*380) );
    +
    + +

    +You can add more views ($views[5], …) but please keep in mind that under normal circumstances ALL views you defined are shown. +

    + +

    +back to contents | timeranges + +

    + +
    + \ No newline at end of file diff --git a/share/pnp/documents/en_US/wrapper.html b/share/pnp/documents/en_US/wrapper.html new file mode 100644 index 0000000..367e4b1 --- /dev/null +++ b/share/pnp/documents/en_US/wrapper.html @@ -0,0 +1,30 @@ + +

    +check_procs is an example for a plugin which doesn't deliver performance data: +

    +
    ./check_procs -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'
    + +

    +This can be changed with the following wrapper script +

    + +

    +check_procs.sh + +

    +
    #!/bin/bash
    +LINE=`/usr/local/nagios/libexec/check_procs $*`
    +RC=$?
    +COUNT=`echo $LINE | awk '{print $3}'`
    +PROCS=`expr $COUNT - 1`
    +LINE=`echo $LINE | sed "s/: $COUNT /: $PROCS /"`
    +echo $LINE \| procs=$PROCS
    +exit $RC
    + +

    +Now you'll get the number together with the required label + +

    +
    ./check_procs.sh -a ndo2db -w 1: -c 0:
    +PROCS OK: 2 processes with args 'ndo2db'| procs=2
    diff --git a/share/pnp/documents/en_US/xport.html b/share/pnp/documents/en_US/xport.html new file mode 100644 index 0000000..53634ca --- /dev/null +++ b/share/pnp/documents/en_US/xport.html @@ -0,0 +1,44 @@ + + + +

    Data export

    +
    + +

    + +PNP provides access to RRD data using the xport controller. The output format can be specified. At the moment the formats xml, json and csv are supported. +

    + +

    +The controller can be called using the URL + +

    +
    /pnp4nagios/xport/<format>?host=<hostname>&srv=<servicedesc>
    + +

    + +whereas <format> has to be replaced with the desired format. +

    + +

    + +You can also use wget to generate images and place them in periodic reports. One example may be: +

    +
    wget -O image.png 'http://<user>:<pass>@<nagios-server>/pnp4nagios/image?host=<hostname>&srv=<service>&view=2&source=0'
    + +

    +view=<n> limits the graph to the timeperiod specified in config.php
    + +source=<n> only shows one data source if you have more than one in your RRD file +

    + +

    +Instead of view you can use start and/or end to specify the time period. For details please look at "time ranges". +

    + +

    +back to contents | templates + +

    + +
    diff --git a/share/pnp/documents/images/smileys/delete.gif b/share/pnp/documents/images/smileys/delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..d668348b9194ea410fe5768a808599e787874c5d GIT binary patch literal 1421 zcmeH`YfsY$7{yPy$gPZ0Dl%532xEXuk-`MT1y{h!gfNGQOc9uq0?Q_mXtJ$)HtSD27V#Wq4x^h!4MPL*i3ZqD^HvVi3q}D|KS%or)Cg(d-wl$3xeVl@C2`iL4Se< zKuKuhEh=r2sPyQ({V#}qedF>GS2wBy#qSkokz zCiyhwKvM#mT20e#G`*Il*U_{m&G^!cKg|TFyFzI0Q<@8-xp30#B26S|qG&#z<`2;P zL0U+qmq-8Bd`~ZzEGa1|nHavWf0;wtJkp*e?M2d+kgilcS~D^7D>GK7*H+Q1O1}b90>&Ifb6LT^_xsP0(57`DMpmGsxs+zI)z`99FgF9&>O{ zJe9h&XH{07|9Y?bs>HrhABR-avD$0>rIEkHcXcdJUb!JzQLFPSIA1Bs(EJcvd$sRM zXx`}BGolS)UB2IL=WQ*Q-q`>9QF>$P5mf_LisHxhq8xd*)df#C^X#fKBJbi}h1|m+ zaGBiiBM$^3%SK+-o4sn^qPIeEeOuY1Ng1ouE56~-K+{jLSGHs?$Zp?@R6eVB=y2T~ zbJ*`4m|XY*$`Nx@tSB}-7dGU7WU8}s2i;8DbXW8AtA?)|cOE}gkXg)mRU&oKo79)N zj1Mm~o=ztpy(%~(#tt%WjQ3{y4CoRBndV$sd4`oseR;a2w=&o^B4{p%yPY?F!tuMB zlpMS0!H0!ui<0uz)9W4^Ni8AZj3s*|6*%Q@G=MZepvm=^QFJ)Vm>bNV6K$5T~ul2U^lbxTpB-t~`Y;j;#wNT7qfhCS@szysGbK~9{e`7OqcxKex(WtLi z`-Bz*aROu+277FV&Z)0eyErp-%A7UR_2Y#W-*82<=L~)`k|;BIX%E)SG%P$$p1G%6 WbZaqp-lmuq!NlW`jB9L!jsF1Sof;ef literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/fixme.gif b/share/pnp/documents/images/smileys/fixme.gif new file mode 100644 index 0000000000000000000000000000000000000000..b66ea99d658a1568bbc75564fd1d8266246c3835 GIT binary patch literal 1435 zcmd^;>rWE~6va;|NENUJDpaTlN(>^~%H}4xx&amxZAcMNBFKHAPu>SNCu1n5|St+#vnNk(j-V%BF*l#*!~T&q{!NUtWC&HMfO(g%S3c^bY2Du zc0#cSihU^DjT3vJkfB13iX*5!hT3w}oOZoYfm)U8jSJ|gM%P7j)#HH{J=b9k(0 z3$`v$C+IfFe%S@f16c3EYUg8EdSUIs#68emke&Bodj#qRJp|dqV@x~){SNvA^aRuc z>IFRo{Rv}xkf|e#`asV?{h$}1m!JWV0b~Td0+~Q&7c#q&nN4PQ8uXw+KE0kvul?!u zEE<|iLm$)7Cp09OFo)A{7!5C^VWH`E42>?Q(Ks5F&{z_Ut)#JJvaBb|2C{6VH(B)d zyT8YF(_6cLkjv%9XV-0SeI8u6C_zd+gsczT60})(nZNHvpn9kDmZ6?q@_#Y3R%u+Hg zAH>243uD9~BK<4wYUb4jM-dZ_LitTsM&n&vVk6_!7Qbe__=wzuUEIWl{I| zRTlFjixQmKT}Kf3>nidt1ddOi+`PenK1W|KEDRfdx@YRiFE-zo&TTtX7`S-v%h1-G zINAEXEasii;zVZue5p5^uVXUVS;wTg=+ru3wpf#!JN-^P;FT*&$z=-#mA>gEk$SH+ z+`vO~j^a}OjEsi(zR2)_0||y*JA-N9Ucvx>l*oNR~z(O)pZl zOiL2QO9D>>dQ|e~#O62pq^S?iiQBAhAMg=}Npw?PLUf|?Ey&sEf;x@*^p?X$r_zuetcrvdU`$saJ#SrJ~HO*cH3EF1A^2PAxq(mXy-vyVN{0d?`W-dhz zX0|B@>(aJ{?)Qv-6VWYNHh!yA79=qb)sN`s)i$IgK9{o%9`Z)cCfq{o6L%Y37j$Yw3tSLu;wYQ>TAs=jBP*FkflM?zCbCrVb+sjSbO~t9>%IUtM${ Pu}&Z@V%kj=CI)K&O7cC% literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_biggrin.gif b/share/pnp/documents/images/smileys/icon_biggrin.gif new file mode 100644 index 0000000000000000000000000000000000000000..d3527723c6d8a0ddfa7ca0bfe1ab8fce0055918c GIT binary patch literal 172 zcmZ?wbhEHbgxLc6$23b2ZD19|4%af-@@>3F2nzSlmGt}{{R2@|NpQ5 zKLsg(0L7myj0_CC3_2h#$P5OS$PJ#HS#x(>T`Hg?&Q{P6{IT@*|fe Qt&nb$oR(_V$-rO@0AZ~_>i_@% literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_confused.gif b/share/pnp/documents/images/smileys/icon_confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c49e06983f1fff4bc0834b4d86ce39b8a36a914 GIT binary patch literal 171 zcmZ?wbhEHbZXiyV-#U P9L#x)b-Z(h7#XYqI2k)k literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_cool.gif b/share/pnp/documents/images/smileys/icon_cool.gif new file mode 100644 index 0000000000000000000000000000000000000000..cead0306c0e38e57bdb0cc85a407b995dcbdc656 GIT binary patch literal 172 zcmZ?wbhEHb+|z`)C(1LA_rU|@;d;3=6kcSq>7bCTj>1sqIsoCSRx)8`fJ$~w+{ zJX`yX^?~=R4m2(o_)+HS{ItMiUIk0)fwE>-?dDgxjscmQ{AM&TEaGA7z8`VSO88#> SHjRW8(oK@nQq4LU7_0%kd_$xF literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_cry.gif b/share/pnp/documents/images/smileys/icon_cry.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d54b1f994bb20c2a17c6e9e53edb39e0444b380 GIT binary patch literal 498 zcmZ?wbhEHbivPL&TtkAL9RpmA^bD98ftnS6varfA2r%e?3<5cWfi*@! zrOPq0Pa{O{R3VSL)CLZwJI;bVj@ow|9P^f2{b_KV;g#sD#JTIhK{X4eRSZoFOA4&E zE?xGWjgRM;Ia^8kzR>%TOS23r6eRl<`~6;g|7yg@*31^DX`|+%tO&MH1Y{u#11keN z5Hhd|DyTR-@tBu#X^wBxK7*WjP8?uWTo6?pKs7*@va%&Sa#%9C1z8HDof#;_rJ&H~ zFsWx*ry9h3B%L5>ZUqL1B|!6=oIFuX25Dyj%JU{%Vn~@hA!8Mj(`_aU6Ueh0) literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_doubt.gif b/share/pnp/documents/images/smileys/icon_doubt.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd7903b1916153b048ab996bef81125c97179b9a GIT binary patch literal 990 zcmcgrT}YEr7=FIZ>YJ@LPgZ7DQ;H1w5xUV5SwAzS5HXX=E;O`2ghmLZYm(J;MNocV ztVN(@*hP?r=3mAX?FUOs?B8lxxiw2m6Se$!JDb{7*S#0-dCqyy^FGgc;cSbKjf_gy zK!YNHo`K$g-hp~SA3-kA7f>Il8FU}?Bau2lPSCG98ZW1xIW!naZ{f0o?x4Q{^fiR~ zHRORjRwa*C$nB6v3h7%I4Q`+ZpiWRLXduE}26_bQSNFAPJ&lmtK*Jg2291``h=~T) z(!eUu<5+qM>H&?}=`QF6XlNIW9HHR@^kaMf$66Y@=>AYcza4TXJnfP6O-GGzKMbc& z+y?8bhWq_pdJbygitAjLx%mVdN}&Xc{q7H}^1`hIUgIT(yCo-pYv~6McZp zSua7aVK5lLXF|mD{|RQ+DzKd8O#u5?Znx}2v33T_E$8YiFQ<4QNKzSXpBz%mAt`1* z6e2TMGxJ%%sNB(%Um6DldDFw1pv6=v3P16&c%GINBaUmI-O%}nYkOZq`c-{>O($A#k0 zp9|*3K^e{RzO%eBfOnqDPISMjcLFM}fH$}S#Uz@_f_LTDln-h-ce*498#AZ39Cz>w zzLK!#&;^dC+IqRFfX*kuRb}Z1(b1fYotE*k=^jwS*ZlAPpCEMHPsvA*)!wT2Pe5!$ zy%>1?T3T~~SRdG0oE~4YbXGuCXqT>VUSPbv(sm`YbitB2x1$rg3Qk(q%q+}FuG^Af z)oxaw5^rVdx2;JIxlvkW*(xYf{T!mBTvxav+@2j3p?6$>;mr4Nw{sI)w$Q%0B+PQZ z=)_`aZ(2i1(JakM{|0MU3kt;b8BMbis(H~L6GkG)!6D3dZopxnjhTyXoU_N{{S0DVN3u3 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_doubt2.gif b/share/pnp/documents/images/smileys/icon_doubt2.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb4b70b662f3102fc515a4e1a0598d892088de77 GIT binary patch literal 992 zcmcgrT}YEr7=E^yezWD~X_T0iiIzb>Qa73sOIvA02wB+AMTS;H&pBnfjU9oGN}vX2K{WLNeBJNr;$W@i$Oc+HioJ}U!rJ8 zNnVH(b>eun_zIU5d4JUZ2K#xE}ih&N5w*_Jc=zA`CK;t&@>1lWs z4KMdT-b7D9y`Tv@-37e>jqN1g3HpAJzHJ@qZ=i{bo)0(ams9M9_hBM^jiwfO9>mi} zZi5Zf!}I}= zXqa9IocNR2tFy|rR{3^pJkAQ-T!k5;xdE;SsF)$as#z6Tkg`=!+0^ps)Sh4F>lN*rx1^mGcNT<+rmiSkGO?JP5b7x8tNpjxImg6pd zAyAU+K32~0bXz}H9^U;VvaTxU5W3p3u){Q2HPZtM1e*Wd{}U{k43hEDV}-x!{}T}I zph-|)ySl&4C^V_>S#mOLi$cPWEa{0ZnXAsQ*H&D~tDLuR&aITp9^)C)%HWdxtj4rl zvno|_R=AO;*}O6B?$1dX#C+H<4v9`^>ec)mT=7Gvrx zEnZ;Vv%lF^8lqel+HCG=hf!GTC`(7X*?cMVlp{g~XL;+Ir8O?8Bh}ctcV4V!G_8G$ iDK0cyKALL`2})ly*L9#T6m!%uOS2AVuDx&?$$tQ?cwh+t literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_eek.gif b/share/pnp/documents/images/smileys/icon_eek.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d3978106a2da37441ed17c9d05383b367570d46 GIT binary patch literal 170 zcmZ?wbhEHbd`4m;$l6XN^_D8SRJJ2FugV_ z;@-1W`~Ak%x7W!T7_8VEVD?C1V$(vmHm-x7t|ENQXTMbHG-$9e9m-TqP;V|s+-sI@ SDB66dp*Gz_Y_|#%gEasOPe3vN literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_evil.gif b/share/pnp/documents/images/smileys/icon_evil.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab1aa8e123fe263608d06126ce08c560ad419f97 GIT binary patch literal 236 zcmZ?wbhEHbgxLc6$23bKgaO@B*VYC4FCTM|KGy!A1Lx~^8f$G|7kJ& z%VnN6ZQB2*4FCVX1}P;4DE?$&WMB|r&;e-z*~!3~slec{BxBNqoiq9;sWfXDwJwx! zTfpypu*1~B&zIRcFi`x-!pOiN%b)||f$U^p%}h}5a*XWD2sb-X$e}K^frar-lVFcywmLVPpS#r! z1_#Bw>()y8Q=}6Xa7!$m)>9ItA-k>bRM`by3r4aoDCD!-THXQ zaD}Q`!Ef~@t%4VS^H`jpHe@qRnmW&T1rN_M_11z^Th4v=m-`t@{9)jl*%hj`?X=?-ZjNo`;ps^KL(j#_kB9f=ec)+o_WSBO9dIBL z0HfeX@EiCOoCkmT7y;+NQSdAHJIvfePJ)YVvAGac7vmmg`}khptdC9k)cHX!lyC@4 zor_F3mG8rxhL*m@=imo0UQX4{88A`H)LAA)Z30@RpTl7Ka&*wm^hN#|(XvmKSCt$C z-+-UMWCzC)?bD%Mc>=}|4T5R`Gk28PXKFvVbU}NoM{3b#5E+0r1-=G#Cwq^HDlWD% zbCa|BiGzun*btNldfEp502hjwxyyHmP5YTT!+0sbU^#h-pCJeWNdW(*4*y4GIkN!> zz`OEpr4v{mUkP+|iL%_?8<5v*uIq63^or|juF8%6BZsQQZn56h*061LY4a}AzTk~5 zjZ$IxQB$5|wFbpic4>#?gIO|4`8#EA(+P`X#F$@OX4oU!tM{HXnT@9m8;)%~AeXGQ zc=B4?4Mpqs7gWf{Hwn^GTH0Q7I9%wIPLl)om5{B)ZpX5v@qFitYM~gOM=vpYtLJLS Tn{#<4Zy&twE*=Y4II;ULF^Tel literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_idea.gif b/share/pnp/documents/images/smileys/icon_idea.gif new file mode 100644 index 0000000000000000000000000000000000000000..a40ae0d7e8c870d3675c8975e3a6bb0a059f11ff GIT binary patch literal 176 zcmZ?wbhEHbgxLc6$23b2ZD19|4%af-@@?!ukgRQ4FCU4{{R2@|EEBy z*B}*Op!k!8k%57iK?lSGnZdvkyTOw)YwnKFWkE{fYz4;!=ddvOIHYqKtO`15eTQk+ zwr{=ctfC9V1Rm6}I;$2M@y*$pa`Z}#oqrI+!z(?kVh8VTo6X#$!E$I32lMi<45x(( UGxi&cHs4b?vq7goSdhUQ00}uk)&Kwi literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_kaddi.gif b/share/pnp/documents/images/smileys/icon_kaddi.gif new file mode 100644 index 0000000000000000000000000000000000000000..1410f7f1e1d73a5a776f5f3ff93501d0f7964128 GIT binary patch literal 991 zcmeH`-Ahve7{(v>s?n zQ3T2$m=t&uR8SZ=#EGIIeGq6tUpQeqo!QK#IIF|c)^&e^FE77~=ec@+@E!}b_z!i6 z5Ydau1cSj*AeTVyKGXr^2cbSj_8GKcopTN)H7pN~i+O(f@Uz~z9R3Ub CNYFX} literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_lol.gif b/share/pnp/documents/images/smileys/icon_lol.gif new file mode 100644 index 0000000000000000000000000000000000000000..374ba150fb238d6a33605bb26e86d4449625a46c GIT binary patch literal 336 zcmZ?wbhEHbgxLc6$23b2ZD19|4%af-@@>3F2n!7!vFtG{{R2@|NpQ5 zKLsg(0LA~@ey$E)D;vwK1$ZJE z)->GK{b0hvv^Z;7;HB1zIS=v}c`BF7qB`mkh55UYFL448CX~YJS?+%vC0^DXyTAT=mC2Y$ux)_YXI57TebiI literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_mrgreen.gif b/share/pnp/documents/images/smileys/icon_mrgreen.gif new file mode 100644 index 0000000000000000000000000000000000000000..b54cd0f9469ae025d7b709f03432eebc30a615b8 GIT binary patch literal 349 zcmZ?wbhEHbF%wyNW~cLKD&UCI$nR5;ND%aoaG8jR+sH5 z;LGade6U~GQPko`gGJNAq7#;kr@G#2#;~znnVhs^*T0km#>C~4JR&=FdsEeR+|3R= Q;9xFbtmB<4#K>R`0GZ1@LjV8( literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_question.gif b/share/pnp/documents/images/smileys/icon_question.gif new file mode 100644 index 0000000000000000000000000000000000000000..9d072265bb9d7d5d4eeaaa9aadb44a49a60e5fe3 GIT binary patch literal 248 zcmZ?wbhEHbgxLc6~q5?4F69u{F}@0e+$F^zrz3jO@4oyp}v#>2=1R{ z`2YX-`F#xhd<^^7GyH$bps&p^e-cpewY&^Nd^p4X4Gi!1Fzlbske>!pj|LQfvM@3* zNHOSu#6fm4u$C@R>vD+fTM_1WrjSFOYeSph9VW&ehisimT`Ynp-iELv_k~jmS4OEzz h1Q^5k8{BNVn8hT-nI{@Cu+CwP)wEG_S5{=O1_1NkQKJ9= literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_razz.gif b/share/pnp/documents/images/smileys/icon_razz.gif new file mode 100644 index 0000000000000000000000000000000000000000..29da2a2fccc79981bc54db7513ca6d2374592f9d GIT binary patch literal 176 zcmZ?wbhEHb^3h|5y0`zsdjqAOHXV zwXw1B|EEADAfWh@g^_`Qk3k2-0hz(T5_`c@GHdRQt4o8V#Kj6YnC2W7^l?<@Q2(%O z^|TpzE=L6K%vq%4Qv0AgI88 ZPHWn(3w4)`M4Rs!oY|mbDlEug4FCb$KH>lX literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_redface.gif b/share/pnp/documents/images/smileys/icon_redface.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad7628320c3d15756c84794c8c0523f1072da640 GIT binary patch literal 650 zcmZ?wbhEHb&Qw$Gs7{2#K|NnmWcSgp)ZKdDmF#NyN{%1+%|LxoV z&6x4L*vr+`_5YJ6|9^e`f9A~pR}4QI8vg%z`Rh8vzsC$emo5AMNBH0A=KudDKaP*T z>0!pe!0`X+%wGqqfegj}+zPv3R$%UgcxPlMx(u7qxxxfZd?$&YQ;PGndxWo3ZY ziH`8-T?`B&DNk$k=JGRs=w-6FQO@h2ko&aap$ji#VOF!1O><{wyHRCMkfx2Ai?Slv zYA%q~j0}tnyg^Qv|J?fJ`y}Jo`B}5IcZU0i%+^)m>vp{!Bqu6#)+xQyYu&8=mRY(7 z)}5aCNL5gG*%{+AHF>K87ridk_T^KXg3qiu^$yZP~SpxtUz5smy literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_rolleyes.gif b/share/pnp/documents/images/smileys/icon_rolleyes.gif new file mode 100644 index 0000000000000000000000000000000000000000..d7f5f2f4b18f8a141c7a5dd1e09ff106a2f9fa1e GIT binary patch literal 485 zcmZ?wbhEHbgxLc6$23bKgaO@B*Xvz|NqTp_`ikW|G&xq{~!PVSNQ)^ zpx|qe3NTRo&+X?L671|4;A*62z|05~RQ$=p%EiFTpaW6>GM0fQZi6Rh*4!PT(*&f% z*$TRZ<}@?I^CYG*?eW$Pd$isBan+(fO1gn0b6dW=x%w~q}~tKE&`I~ zWZ+_80zw8BmJOU2m9Ux1yJ3o3D&v+$ZG#t4ZLVMy3?Qu_ZQMY+8CYaDcq&S-H42Fh z{c)CE%Sn@EnS+n-#i)qLlhWcv5Vs)dU<2w9+u*4hy}}}Vq4ah~j;>ScENX^v3nduQ d4TmZP8gAjeGaoDCD!-THXQ zaD}Q`!Ef~@t%4VS^H`jpHe@qRnmW&T1rN_M_11z^Th4v=m-`t@{9)jl*%hj`TPpfq~*r7Dfi3RXQLZ$W8{LbFtQ6X_ bzp&cMhN-Bq*@!WoHQrEDOU*@Dk--`OET>q6 literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_smile.gif b/share/pnp/documents/images/smileys/icon_smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b1f6d30449c976f49a4ff4f55558156a7084732 GIT binary patch literal 174 zcmZ?wbhEHb3F2nzSlmGt}{tp7jjg5`} z|9}1eDNqRrDE?$&WMJT9&;fBkW-zcsU+|R7ntLO3**QsZu>uaJIn9DTj_MrhAC|2y zn^DM@#l<(@zDcWq`B+oyDaGR~0+SdoFXD`_(PqAxy<2o0Q>0^(jhH~$tb+>(~Mkip?iSJVU!i155M;PsyygH$s=4lN1*#;9#25Ea>CN&heak$?CEh zA7(bsN;gxLc6$23bKgaNIF2n!7!vD80{0DM@;NRr`CxMLP|FjsU zO`B$HZ2T{m`TzgdAk{j*8D$QDUE*nK$ z7w|KG>@aokb7%R&!0WI`LE+V`jZbtHGVEq^HDzd8gshBhJhWk{9N&@6Gj#R{?N7d_ u@Ss3Q_U6Qmr`{j;vSH$AZf0`Va5JoNi_%bKV4KJmrQFw{HdRBB!5RP#AxjVd literal 0 HcmV?d00001 diff --git a/share/pnp/documents/images/smileys/icon_wink.gif b/share/pnp/documents/images/smileys/icon_wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..d1482880421dde677d3302940aa875ff22a11b06 GIT binary patch literal 170 zcmZ?wbhEHba9D@n#Zhbsv zutHU>;J1F0R>6zE2`tV}8xE^#?@bGklrZsUYAp!;dbG*vY{CM88Jk-qvwbqQUtQFY Pm?x1IA$CiJiNP8Goi0B( literal 0 HcmV?d00001 diff --git a/share/pnp/index.php.in b/share/pnp/index.php.in new file mode 100644 index 0000000..b4cc9ce --- /dev/null +++ b/share/pnp/index.php.in @@ -0,0 +1,148 @@ + + + + + + + + +Installation + + + + + + + +

    PNP4Nagios Environment Tests

    + +

    The following options are determined by "configure". If any of the tests have failed, consult the documentation for more information on how to correct the problem.

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PNP4Nagios Version@PKG_NAME@-@PKG_VERSION@
    Prefix@prefix@
    Configure Arguments./configure @ac_configure_args@
    RRD Storage@PERFDATA_DIR@ is readable.@PERFDATA_DIR@ is not readable.
    RRDtool Binary@RRDTOOL@ is executable by PHP@RRDTOOL@ is not executable by PHP
    PHP GD extensionPassPHP GD extension not available
    PHP function proc_open()PassPHP function proc_open not available/enabled
    PHP zlib extensionPassPHP zlib extension not available
    PHP session extensionPassPHP session extension not available
    PHP JSON extensionPassPHP JSON extension not available
    PHP magic_quotes_gpcOffPHP magic_quotes_gpc is deprecated
    PHP socket extensionPassPHP socket extension not available
    Apache Rewrite ModulePassApache mod_rewrite is not enabled
    Apache Rewrite ModuleNot running within Apache mod_php
    +
    + +

    Kohana Environment Tests

    + +

    The following tests have been run to determine if Kohana will work in your environment. If any of the tests have failed, consult the documentation for more information on how to correct the problem.

    + +
    + + + +=')): ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PHP VersionKohana requires PHP 5.1 or newer, this version is .
    System DirectoryThe configured system directory
    ('')
    does not exist or does not contain required files.
    Application DirectoryThe configured application directory
    ('')
    does not exist or does not contain required files.
    Reflection EnabledPassPHP reflection is either not loaded or not compiled in.
    Iconv Extension LoadedPassThe iconv extension is not loaded.
    Mbstring Not OverloadedThe mbstring extension is overloading PHP's native string functions.Pass
    URI DeterminationPassNeither $_SERVER['REQUEST_URI'] or $_SERVER['PHP_SELF'] is available.
    + +
    + 0): ?> +

    @PKG_NAME@ may not work correctly with your environment. Remove or rename the file on your own risk.

    + +

    Your environment passed all requirements. Remove or rename the file now.

    + +
    + +
    + + + diff --git a/share/pnp/media/css/autocomplete.css b/share/pnp/media/css/autocomplete.css new file mode 100644 index 0000000..d0f1005 --- /dev/null +++ b/share/pnp/media/css/autocomplete.css @@ -0,0 +1,6 @@ +.autocomplete-w1 { background:url(shadow.png) no-repeat bottom right; position:absolute; top:0px; left:0px; margin:6px 0 0 6px; /* IE6 fix: */ _background:none; _margin:1px 0 0 0; } +.autocomplete { border:1px solid #999; background:#FFF; cursor:default; text-align:left; max-height:350px; overflow:auto; margin:-6px 6px 6px -6px; /* IE6 specific: */ _height:350px; _margin:0; _overflow-x:hidden; } +.autocomplete .selected { background:#F0F0F0; } +.autocomplete div { padding:2px 5px; white-space:nowrap; } +.autocomplete strong { font-weight:normal; color:#3399FF; } + diff --git a/share/pnp/media/css/border-h.gif b/share/pnp/media/css/border-h.gif new file mode 100644 index 0000000000000000000000000000000000000000..a2aa5b0d09bf7215199dbf9a291b34b11d0352d4 GIT binary patch literal 72 zcmZ?wbhEHbWMg1tSjfQe|Nnmm1_m=TGay6ppOkY^YGO%hib8p2NrpmVR$@g?eqxGV XW?ou8gAPy~14tJG6LU)|D}yxvaY_|= literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/border-v.gif b/share/pnp/media/css/border-v.gif new file mode 100644 index 0000000000000000000000000000000000000000..4bfd55564099537d38d4112f550b8974744de3ca GIT binary patch literal 72 zcmZ?wbhEHbWMp7tSjfQe|Nnmm1_m=TGay6ppOkY^YGO%hib8p2NrpmVR$@g?eqxGV XW?ou8gAPy~14tJG6LU)|D}yxvaW)ls literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/common.css b/share/pnp/media/css/common.css new file mode 100644 index 0000000..c375548 --- /dev/null +++ b/share/pnp/media/css/common.css @@ -0,0 +1,206 @@ +body { + font-family: sans-serif; + font-size: 11px; + margin: 0px; + background-color: #ffffff; + color: #000000; + height: 100%; +} + +table.body { + border-spacing: 0px; +} + +a { + color: #0000cc; +} + +a:hover, a:visited, a:active { + color: #880000; +} + +a.active { color: #88cc00; } + +.gh { + min-height: 150px; +} + + +img.icon { + width: 32px; + height: 32px; +} + +div.graph { + background: url(../images/1x1.gif); +} + +div.right { + width: 260px; + margin-top: 4px; + padding: 4px; +} + +div.left { + padding: 4px 4px 4px 4px; + margin: 4px 4px 4px 0px; +} + +.cb { + clear: both; +} + +.cl { + clear: left; +} + +.cr { + clear: right; +} + +img { + border: none; +} + +input.textbox { + width: 97%; +} + +.b1 { + border: solid #FE880F; + border-width: 1px; +} +.b0 { + border-width: 0px; +} +.w32 { + width: 32%; +} +.w66 { + width: 66%; +} +.w90 { + width: 90%; +} +.w99 { + width: 99%; +} +.w98 { + width: 98%; +} +.w100 { + width: 100%; +} + +.p2 { + padding: 2px; +} +.p4 { + padding: 4px; +} +.multi0 { + padding-left:14px; + background: url(../images/int.gif) no-repeat left; +} +.multi1 { + padding-left:14px; +} +.multi2 { + padding-left:14px; + margin-left:8px; +} +a.active { + background: url(../images/int.gif) no-repeat left; +} +a.inactive { + background: url(../images/int2.gif) no-repeat left; +} +div.header { + margin-top: 2px; + padding: 2px; + background-color: #c5d8d1; +} + +div.pagebody { + display: block; + float: left; + padding: 4px; +} + +div.logo { + padding: 6px; + text-align: center; + vertical-align: center; +} + +ul { + line-height:1.5em; + list-style-type:square; + margin:0 0 0.5em 1.5em; + padding:0; +} + +img.medialeft { + border: 0; + float: left; + margin: 0 1.5em 0 0; +} + +img.mediaright { + border: 0; + float: right; + margin: 0 0 0 1.5em; +} + +h1,h2,h3,h4,h5 { + border-bottom: 1px solid; + clear: left; + margin: 0 0 1em 0; + padding: 0.5em 0 0 0; +} + +/* code blocks by indention */ +pre.code, pre.file { + width: auto !important; + width: 98%; + padding: 0.5em; + border: 1px dashed; + border-left: 3px solid; + overflow: auto; +} + +#basket_items { + list-style-type: none; margin: 0; padding: 0; +} + +#basket_items li { + margin: 0px 2px 2px 2px; height: 16px; +} + +img.ui-datepicker-trigger { + position:relative; + bottom:-6px; +} + +.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } +.ui-timepicker-div dl { text-align: left; } +.ui-timepicker-div dl dt { height: 25px; } +.ui-timepicker-div dl dd { margin: -25px 10px 10px 65px; } +.ui-timepicker-div td { font-size: 90%; } +.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; } + +ul.colorscheme{ + list-style: none; + padding: 2px; + /*margin: 2px auto;*/ +} + +li.colorscheme { + float: left; +} +span.colorscheme { + border: 1px solid #C0C0C0; + display:inline-block; + width: 30px; + height: 30px; +} diff --git a/share/pnp/media/css/images/ajax-loader.png b/share/pnp/media/css/images/ajax-loader.png new file mode 100644 index 0000000000000000000000000000000000000000..811a2cdd1b492c47faf85c1206ad6606521eb6e4 GIT binary patch literal 503 zcmeAS@N?(olHy`uVBq!ia0vp^${@_b3?$!tUzY`>n2Vh}LpV4%Za?&Y0OT43_=LFr z|Ns9ZDd7Dck0hX8fs!DgJ6C3d)qYMwA5Sr=f?F`h}-_x&BOOZ@XQnE}c<_xEZu zoIX1zlA-v_?sD-1ZfECkmVe(>o?xwNmGDbK;?2MR41rRzXA2bX{on66#ob*wrsMPf z`i=nRm=4)s4z4?=xi7SyIo*As^~h=O3#~U!U4D?`wnG2XC7uMQrY5F@nOn9v%usT4 zc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPAEg{v+u2}(t{7puX=A(aKG z`a!A1`K3k4z=%sz23b{L-^Aq1JP;qO z-q+X4Gq1QLF)umQ)5TT^Xo6m5W{Q=$frY8Dg{g^?frWvgp^KZNxsipFqp^##k(sHh zxvLpWuSMv>2~2MaLa!-Ky`ZF!TL84#CABECEH%ZgC_h&L>}9J=+-@<#X&zK> z3U0R;~ffC;SG&XwqMVf^ch~>^Yvx!tm1jqY457ni}SVjYVq%taI-#D(4G9|(WxaX8>%?0 zEnMtZ3AiXPE9g4;pNVTjo8X=Vv9Bv!*uMofb@+W(Ul1LCXEFch9S5!T3|b`D#=Epi z8!X$`Q#^T}SV3DB&kn}5KMpmXj4}KwX0EWLVYv=t|Er^U4l+M8P6%CCB3I7rXTtng z(ro%`J;}32*E3kFzD&w~E`3 zu1)(le}&!cgTHxZ+{t1VE?exk>B-DH*~0fXyl=eG&%n&E;IvbH^`pPBpaRF!)z4*} HQ$iB}ksr6J literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/images/icons-18-black.png b/share/pnp/media/css/images/icons-18-black.png new file mode 100644 index 0000000000000000000000000000000000000000..71268bdf70f4a925e511d68be966e536449455a1 GIT binary patch literal 2138 zcma)7X;@Ni8YVSG+|qD~TtKr;&0KKQF%1_!6+}L%$D&`?WD3x~r= zNJtghJKS)a2#m0l$TXh2Gv?X<~74 zF_lUU3OGsh_y7MLa&vQmigY?XhDHNQAoTR5B>;1v8Q>Oh1LC%}Ho#vhmdb!;03K*e z8UQA?NE;v>AOSZrnGAFS#6F%r04db~T>-fO3Ctx`0x41xDgU2IrMJ?vh_j{%hyoct zI08uhzhU@40qji*R{%%;4WO%702ct10I066=5o2cy%Q4?z#bO<9kM%NI;rgmXIjAtMcGQw*nwMK95Y7ab>eIfowEs@r zqi}Y+lDYQXt5=1J%Efo zQSoKC$S^m@@Hqs*82);ZjKm z$4ij@TIU4l=)I+w+)B$k>SDXvort4n5`@%Hkt&Bc}txX>-AG%B8M4p@6mzHEaVaAElVwaSt*tI3-qCz(ZGvZv2jh=zTd!4*4+MbWA`A zWUjsXKt`Gr?mt8n?B32*YA<_7z?#v5B8Sr_$i@C?Un+^Bb0sV&!QZF5sB#(07g z*kfa1dZpCfn2|N{&xfHQD`Ll!|L9};vyoQQ(4wKm>;A`yW94-ZnPT-j|DGvr5@3aPw&Q=T+W))RIw>s z_S{Oy(oCD+#4N2UXc4UvH zJb(4QuN{OT3x&QRS*Q2wTiR4y$~fb}z-&$bC9f6alVR`-@@b zfY0CnQ-5k?mnL$ju&I^x&Su<5`+=QNL$<2k?l?u1u^p7x>>ER_EMl|SCx3RU{s@mP zI!*tz_ORlps8+b~rzfw4^TY90H4WsmrJdVkVku3Zw+q*4E$Wdw!#~Vi%hoB2?`pas zYoc{CcpB2PN&WLuW64&7?>;X?4c(rVx{p1}dzp&H*!Ie)hgr|@GTuG*804Uk`>djR zpu44N`6Rbv-YVGPaEiH@F32vA+MI2_4uxddjnmfb2`nJPfOJ8IipRZ`z0m zhg4`|GT>13t|X3rwPl?MjW0nq`9TV_-g|CBGPT@i%hPtfyyc))uiN+6I<)UFV(evufvsVYW=a;8V y>$()$`)dyAo?yDz(m!?&*Bm?0fp_ZpuB5QO+Xk{qI0O7oKpt*5*L%)^Y5xRlaH=!_ literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/images/icons-18-white.png b/share/pnp/media/css/images/icons-18-white.png new file mode 100644 index 0000000000000000000000000000000000000000..dadc6af58703dc34132c8756ab74b125278ca1ea GIT binary patch literal 2207 zcma)7do+~m8XqCU6ob^B*}^dPrWr|-+lVra%TVJovu*cVt_{h|NcK46(oC5!nUF}e zgxn%yqhz*gxuqh)xU`8a6d_5Qj{TOi&f4po^T+wE^?l#-KHu|ue!u5^*ZMx5BiUxB z98wMff$SvN5}hFsNhpYwppxL;!IrfG4@m}rM1?}3BNGne5QqfU@i^6L^BV>S2Sp-L zd3iaD#iCFsBoc{0AmH(M91f?etBXRR5C{Yu4hLM&1~3*D7P`B;Yinx(rKqSVGcz+e zIXN^m)WgH$|DpePThJ3I{#^)UfPpPh5Ch8JW8muFOAdzvjDZ>uFc=IFtgfzRXJ>D@ z0!c6wm-MqXTRL7z$9fn#|11fP$?Ua4#dpd%*kwOlL9$ zqWB-s{9gdBzk>J;KLG%xpy;niN=gF4rT;?xH-Ihe9{UQQwE$ENbE7AKp6nT0HwFX( zQ~G*IyclC|fTRl3%9VMH9_YsmjX14A4Gj;3;Pej~>KhoqxH;hTA*x>sC=o%-Xg_)& z#4;elKTyLulpYuzL8mb^j!_IFYbK2#knK(+q9rvXVcuPqF+$umuzEYXv{vdDw<@nG zj3%F}Rg8RSRU#J-&w@lIRZVPe%Dk$0hsLk|rX8uD&X=v_Gf@*QeMAvhl>p8>%p&+=L_pvRO_ z{4~5U2d|}MOX0Qn6b8+x4=ohHjqDH^&OJJLw;%4i2#Y+6s>CXcWA-n`cF@ULSKDoS+TgQXySu!%L`d>Q>ehCS~OxlF9;*xNHDl4$uSM72)4_!G*Oyfj3@ zU8K81voaOqd-Floo!#x22ATJ1r%HvsPL?j|I+`u#N~ykO5(e55t5+jdAd}t^Z^X9< zs%-qiSP1=>sOm?vAAc~bzbB7sD;v8(!W1e7f8O-F`Q{*Z0@qib{@6Z5-Rer$FsY!j zU}AwZea`aZM`|WHAbILgWv4fPZhz%VBUFOPMRs$b!5h!(hg7NC{EwCk^ahplX)Yuc zrN^VI<|ZN!H9A{ix$vA&C8p=+*x_elB5ifIUiw>IUPpg$o|fnP)i$%|N5nD9%2N2D z*{FNQrepY=42&1NSj-^(L(DbihUjeonm+tGFl^#d$lnv|+XsUZ2`t!7t&5F!jv|e}!4V|t~ZjeH;bHwW? z-0CpeE*t&a`k>yVeQL?=THfJAM1VE<6Ws)WAIsvhK$Br6QQiwuMw6wu+_YT{Jn%r58)5m;cNVjl0O4!k(YEvR_&}q_CWb7Y<3+Jb&R;66e~&;n-h|XPD*a z!PbhWc9c6oJ7r(N{R-NHk1>zL&Iz$%O6==ik%@g`mb>#l(cH2dCiN_DVxcmB&(KjeXXz!q|F!qcV#Rs zDwCbtmNDZRKqt*>ujQ{hh1dvGtcREl$Vb~q_MV9|*|Hx!qNOkb%I&q@Rc;c?Gt-gsXqkuWr(-L#fE@sV-Rc!XDYl0QM(wBV( zeChX&kIJaz(k4Ydd8046{`cRv%!F6>51PhF-p$;WR&POQ2R|VQ$%;&@AowQ!1@2Y+ A!vFvP literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/images/icons-36-black.png b/share/pnp/media/css/images/icons-36-black.png new file mode 100644 index 0000000000000000000000000000000000000000..8c35ae3fb03fcd68f24f106a50eb1d0c512dc798 GIT binary patch literal 4011 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/imgareaselect-default.css b/share/pnp/media/css/imgareaselect-default.css new file mode 100644 index 0000000..f4fe341 --- /dev/null +++ b/share/pnp/media/css/imgareaselect-default.css @@ -0,0 +1,41 @@ +/* + * imgAreaSelect default style + */ + +.imgareaselect-border1 { + background: url(border-v.gif) repeat-y left top; +} + +.imgareaselect-border2 { + background: url(border-h.gif) repeat-x left top; +} + +.imgareaselect-border3 { + background: url(border-v.gif) repeat-y right top; +} + +.imgareaselect-border4 { + background: url(border-h.gif) repeat-x left bottom; +} + +.imgareaselect-border1, .imgareaselect-border2, +.imgareaselect-border3, .imgareaselect-border4 { + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-handle { + background-color: #fff; + border: solid 1px #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-outer { + background-color: #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-selection { +} \ No newline at end of file diff --git a/share/pnp/media/css/mobile.css b/share/pnp/media/css/mobile.css new file mode 100644 index 0000000..63f5d07 --- /dev/null +++ b/share/pnp/media/css/mobile.css @@ -0,0 +1,10 @@ +div.timerange { + margin-top: 2px; + padding: 2px; + font-size: 16px; +} +div.datasource { + padding: 2px; + font-size: 14px; +} + diff --git a/share/pnp/media/css/shadow.png b/share/pnp/media/css/shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..a2561df971728d988424100c74c817916eca1979 GIT binary patch literal 3403 zcmeAS@N?(olHy`uVBq!ia0y~yV738bR}L1Sh{z?w93Z7#;u=xnT$Gwvl9`{U5R#dj z$`F!Ks$i<%mYSqsWME*TU}$J%1Vly(x&~$j21QvmX+Ul4C7!;n>{pmr1x4l8+mz-4 zg*Xd5B8wRqxP?HN@zUM8KR`j2bVpxD28NCO+HqZdXMAQjaPeGm)a##I4DP>8^|Q}*osX?x zu(w4E^8SQ>2<4nWJ;;$Ch1?$dLgm)?6;Yr9_CdHMW*W(@x+ip*R06EH_T4pml(Y0_%+Z_b^VZki z+Ig-L)GH{z-FHJSJv;l^O{dMW8|Geryoiy(edpWebG3Q>oX-o7q}^hCpz*y@X6IS? ZpGWQ1{0Pup3+%oyc)I$ztaD0e0swh%>OlYi literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-bg_flat_0_aaaaaa_40x100.png b/share/pnp/media/css/ui-lightness/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-bg_flat_75_ffffff_40x100.png b/share/pnp/media/css/ui-lightness/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-bg_glass_55_fbf9ee_1x400.png b/share/pnp/media/css/ui-lightness/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/share/pnp/media/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-bg_glass_75_dadada_1x400.png b/share/pnp/media/css/ui-lightness/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/share/pnp/media/css/ui-lightness/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-icons_2e83ff_256x240.png b/share/pnp/media/css/ui-lightness/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-icons_454545_256x240.png b/share/pnp/media/css/ui-lightness/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 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 k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/images/ui-icons_888888_256x240.png b/share/pnp/media/css/ui-lightness/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 zcmd^?`8yPD_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3RqU$@Wfh}nb?QCTyjovo2=)B^qQB=#XMCF_n=?1Jbh>5sptJM?}}{I zHzR=-V_TFXKM0P+&lrh3TPr)c<8EmLl3g~EY}W@od*0X6Ljv>L(67bjz58EDypsu&ddu2a@@x)`5aA^S^DxkW8rs_vKtu8N8(o0 z#Nf}*Ch4&iw866BiW!_r4*HRsHn%80xlBW<`IOcXDu%LQam7$Ge$q#1415XvN>cnS zk_qU%P}4fO0v>J{Zw9o*)JF-CPA!KcpFR1Pn(l@*bKh=1_!ZRWb?FoG5a22cVG<$5 z0|%Qj7p@n}=Hrkk`BkD99I57h7_+lQ-AZ-?fETz5E~q(= z!!d%~_yivn82d_pX#M+Y`|`-F^s6-{6}S!?_mFzr<=n>M{{PUq7g-N`hqOcY-y_m= zc#xZEqMPgqc5cu{ag@Tdli5@JlV{xH8J%TA}P<$=Qej`5Hq>_Gzk+NDFM{b*SA6Yydp9VOs1VgIYAcj@1BIt< zXz@=NF2DLCC>`r|^h-z5@eIEh>Vnjh+|-6M@nuC!oc*856_8#_6jL|rKLYu=)Ew4+ z*XiJVgHrKl?=0wjQ)aeNu2^jkUW>@Hei_S;nuA%RRe49V`VM;8SxUBxpZPe>l9ZA{YS(NU; zhnP(vSd1kYiV^KQ02>XpH6u}Xk)wrk`+SxNxC73cSAefm+V!<`c^b#A9NaTn45bEq zkRYp$U%h-|^9P*syb!eKG!QC-$;IS9MdE^@-`WRSzTp+8M9zqJCUsoPC-3Tr+qbkO z$o;ra-wGjC64H8m{(*FVitg+LQKH+96D4!FREFb|Scex)lw()`rHV$WMdUJNe3E}`->+?@(FDYcZt1#>wXwgHzQ6{p% zTY#PF?iBGE7<=u*`SFt0Lw0HX!oh85UlzQH{;k~&JH?kPJzdQX=gAmX40n@#()wBu zSllJ`lX^ZF9!&n2{1443>o2BzK(6sGDQ?n~RYk_ih&{?TJNBH*Eq`73g$F~WrJz{` zce}LL0;S^ZMb&nKyWR#(_t{VguBs~LOSLX&q*$M&haRh5HO5G%C&MvDmi{a@PM;Zq z)h;XzD;Cshu#GG)RsptBTJvnQHC(-#7@G7B`iqJMl=F%g zD7I#-8sWBC_kJC!{tU)rGSX-nt`B$M86ARc$^oIWRNOCMU!X+%PKM$X`mI~kxxaKB znBMvsb8nZ)0}JBmidn3FUeG@ZcdpwZy_4oi*b{&c?T^HaVC|`tnlo?1SjRKLNPk{gDWT+_1fio|Ic{5kU=X{rvm3 zZIZ6BO4vMQdqO`~Ef~j4Z?cQ(+Ff$wxGAlyMBqd}_S__(_xM@v-fTM;$Q^HhR@PU= zE|8KP1IM4s;)*-+Z@m25>p^N(PgHJsq+a!8`ezsTQ3Np0+k4Mtdkgu z^}tg`-YMQKuuO>dsJQkgyjabt1)2OM)|R(}hto4zSIj5V;^@PYtIwI&4#+%;&Kf)o z7)jrDgZ%f?x$UCa=&~<9SHq{ZhxKx!b+ft~!I?(H$&BMOox4KuOo95gl<%5AIg+is zd=%?6ZOr(k=S0U?!*k{1h5q3O_ZrYo5Hq#Sl|1?L+WU%}6JI(orD)*qq-300E63z? z#iM){^ff?RwehBsE3Uh)}m z74!C`a^?2x1@?-i<#cI?a=RcP4Xx$88l&B!g`Nm)Fo$Fcf!VX@0y$z7EVz~OXbALP zyfX0m-nf+4I&E=bsAjk~l_2g3i}1e%qO!KkQ@Ij*%HbGO)w=i^^5FvkHIIee`4l@J zN(eR%MpMiipJjP0Cxd|&4n@b?>6{Ue05+A0q?xd^oCpYNXpePmO#{q`vISfX)oT82 zc+d5gPn5-?9wBmlt3pk*z*hj`X#ycn4?KJY!|++>4l2@t>FhVEjPeFAhW%k5Vkm2~ zbcy`#HFb1XOYOKAcKGGN*GG%skMBnYSL@4d#@wS$CLny@9vSEwSCUSW;OHk%_<>T$ z7HwfvT&)@WQFkIm_dH-5Csjc|H+OBX6;F-rR3wuTudV;|_Oc(#-}UUgloD_-!aH>L z-NF)hJ|F-%gI?Y8Jvo7qXRG7UV5l2_yAHF93IhsP-b`cH*wlEz^Qi99$$*D?10PGQ zCkYPA5Hltd=c+>(bWIfjJP@1Obe?Gx$=qVDe)rPM+5sw)!8F3K7T{OMLFj_+>SX>F zTT-48YC1?q1IV|?OSG8?IGXAN;&q~nz?z0#i+qM9P~U@BNG1FyO9#kvk>T>G=#)_^ zj!fMlH{X;+ONmr!LsJx(j*b2&WMpJ+s&cN;7Tyu8gf>RT2kOR+DBzZr7=m-v-UheM zgj$|(0HN;F)qrlz6$FyVsy6e02`M!$<1L&Bz z+b!=_(#ur8?I=h&thJP2c+^S%)lEi*8fSaPs>Or&i1kF^p9QX&8C;)E+S__7fCh{W zSpW930L|8eV$Pa=LO*oao@VWHUr>MSl`x%iydJaFA!rB6u0`Jo5337p0UZNmSb{=o z*%W(>6W|^!F&8DUAC~&Vo2D?gE{V0S3{B;atoXLUNo9J? z0AWHot1HHimnr%xGf~-qSOO6>z*MtHe(EIN3<7@k-U&gFD+Xq}Ua*o~(!1kApC zO+-7O=jP#uq4B~*JwPs<`_;tw%;J3m{g-9xU(RBU&q^x&eSc@Ik<8NR$i0+>JBKgT zPqjfRC3Q3V=4q|BVK-yVuyUMByvXqR1a4^k&=*MqJ_v2b7I+El z1&0}s^tJ?^uXsz@oZ9j4x^n+$X$>D_nE$4#I-;EJG6wc;Jy@i$hSA&JVNoE;;UpDo l!Q;r<<-MKrq~`aIaqoP9xRgPV&EKy+z~U_0tkM({{ePlYU?u&Z`mr_kcwz5Nh&g=McJ3E!;CE1E0ryV5Ro;>nvty8 zA{omJnn+{p4952Let*87zvA;auXFF~{<`_uPA4&sV%P>LMpp1PTBEIL*yWZ2%{t3Pe;FXZ3XmxI8(D_g57_$Zil~sY6d4T}-hu9_Wqp4C0AMO{-e2$W~1A}=8 z?24)=?B)4HUDo_oXckN%okP)HFJjaB4*3_SNpKaf;yPT}KqfS{2x7`d{0xbPErH%h zh`mQJ03DaATP9aP!}a4$fY#``NI~M6&RljED)8z}hhWxrNbxIBlTxG^j z!X>$3AQQ&I%_5mRECOjaGwR-GHmde})^)t-3_~aFM1G_L#mpCNdcLqr(RKjv3R}(z zG2^yBftMYh;H3a#-slaj|5$BX9+{PTv&NtR*P-L?l21FGTG`$H9~##p%VE!uR>=NG zc&auxVl!1_lP%uX71AJvlz(wLYl?63oLd~dqjZRrU#UEWw8J6Yn-7L~T$$tjeAQiW z9$XG5Hu>rxFBnzgd6ho#^gE5pY>U$dTCRN85Y1tQQ0=Pn{?7OJ10x9Xk!>P2f(f^f zILd}5--N;Po4*25F|J3ywIv+R@rfcYNj}R-sXrH2TFAiK{jFGG(ru1p=w$wR;IXQwAX*S~oiEK{g;kZPW;YE|!QY|g^2`dMS{&1Fr zkf?!sj~m)xO3v`hh4KQRJ&&Q!=X1HNq8T_Sg2P^B&rZX{VQUNc9O(K+B_Z4hiTH7M zW7K5Y!Ec5xD~B9zFlKUWG_Rd)xTK7U#hRGhp51T++e6oS{gT^?3s~>V4?6{zchhc_ z3UBb_W2U+~guMsG-g=@#aWPSFypk)5jIUTxFiM zycGZzbxQuCTnvH*kv=E=LsRnltLbhgm$=ttS1IzU0)1t~4(XE>bHVwJpAPKOqoI-# zrdc{yo0R7Qx%~ZQl{UPa?gmxo#ZWM|vNHNxl@8NLksfn5Ek>C${w=x~pekl%gfwaLwWspL{af)?f zTOBmhTyU&3;}QeF&VLwhJ>Dezu>~P zc+$aFxKDWKj-CmD(v`}uH|ts*SefX@lyrc<%~WE6tHU#dv;y+LlA@cTgl8J!u@@u6 z@@fvJdC)1TvBa$QT@ck`rUxF**7w4Yh0!vZUsGu%Lm(cl(l#QPpmoOH3JC>FMe07G zq0kl#K+GLndyoOx8{t9g8JiLs#`pH8JWqR_ZM%J!Yr>cp>95<^#=FWQfzPm%q;5B+ z0>}ul8+l+gRaHV$$tsq5|MU;?AJ~m-XNxjW3U6JH2k`tOXAqi)yGI@^uA&dQ% zZCJIe7{qK>+p_F)Sqy-GC!x-5MgogsP6lwiUH`N^a7*LKPdO{!4L^_^;goe*e}3s( z0i~~@V#)#L*W~2F?}&N*IQ)0a4Z1$uTU)p7^Mq&IM6K6d*$vpX2+L*+$9vY0=7?$b zxdD4R`8~74HMWsx#*goNSp#(_;z`UT-GuGxoUl-){JNk1rf)aSKE!W`#m`t#v6V!u zgn>fufpkVprL(KqSkhl*Z+yRQosF)bEiV<#K8hOr>yQ1@7Xg>g3EjKwLB7)(9$3%X z$G30OD&Z2Nh{;v5!}oF4fUu0TM%&2F-6aS1+fqu3cn;K4k4-#kkB|BO?bZtcTygp+ zB|R0)0x`)UVEm;Fwx~Vt*6ZV3k5Xcj6_=(X2y*8M&NGz^?Jr>Jutu8idcHpesED^^ znM9MV2AcX%oppm45TS9yYBtteX?1liAe($}l8Mrk|YY*cFUp@Yl5_|Ih%+ z5^dz*^BpQ&l8;Le-Z+E?J1_|}dtK>`0HCSg@u z*e9pUpX4zkcJ~*%3c8N=D_*8f&2puu6>riMeA#MG3E+*kYt|0Dnl;U^u0x`IJLnY* zjELAyFaL6=ihd=uwgnc)F;a_ZKEBsA_UuVc$NS1$GwozcE)2-hGS_c!*V9@%u`#?lhbMR;p$MXpbUS7*AsAt5?3(xQtcatZ zK;B-KhX__vb(?F4Q0GloBJ>|QvdJoM?lDbgsR3iM@a;Z3?cA&4wtslYkr80ETZHkc z9*>q7Q7<0~XHK7PK#yo@cBi@smopq(-%`e-KH4Qx-~rbHu}dW58QqJ{;3Inef@=x4 zI)BgQYXff|j7xg1Qx_M8s)u`0@M0d&aKAfD6qe?B3THxh84PWrQX5xII()>h>b|f$ zpKR+*4#vbnsS3H{v&>IrrO}Xrp{O`p?Q{I%z{XPHRAc7mQ~rVVZ80t_sel;~R{!fE znoWNU9=P1`jx=A?#Ye1fm8**6`|yK3jKQSofyZy4XkM$FK?NExjqO&YVea7N(7$X$ zbR{k3PT@a2CJt_@Dead-55GO?f3gVr{BdM(wXV#1%q{YCJlyB~k-m;m1@SZyhI$5p z9ViBGQ5QzVRGUDbbtaN^E&{f(lI64ub2s){aFm!11riDV*6MFh58H{nU5}0{$^Hi; zJVW(-UYp)>>|Lx|%+y^DwKhz`tPS-85#6Rh0)ckL)U$^na{7 z@VVG(5^ui@Hf1odF537(mlR>ZBhjf%rT+ zPUdZ~CgvIZM_wUkJAw%w}x9jc8!TL)0!EfOi*AMUgP00QdmWDhdxHH4HGc<~J zIVYb|Vj$~E#d*)1>gzKQFOMaAy}BVVo}IK&7ZMB zx!9l*+ek@g>FsKVCTu!A+bt50<5zR%LvhtB47 zphLoLmz-;H4@2#)g8=!k#zLI#UMqFnH)&}~tj#&gW_Q99mQw+L7dU5Tu)W%;@9Qi9 z>QGi--TSZnR2z4)8B5wJy^vu$s+IRc0ll#|LNt!?I`me%fGty24eDN4Xl+O{(+NPj z1ygVh>zf*$Pk&fEX-3AP^1w$s1y_e7lBxzgSu6?iXt=l939t1dNMV&Hw?hI}<+!vx zKuXRw@aAWBEW)iT2xma>qG11B|GnfLf43m`S%SD z3d3^-2o=m;T`_XFO4d`JiOd4T*vl!w_t?SMNPGOr712xew$!m3PP4`3g2iVGiU!9* z&w=GY2O}!evGB%RQa5rA7s5%`YA&A$+(`a%B< z)4%^Wyf-xKA)KjJ=y>(k$Cki3nVk)wxAEYIGA3p>sG^i;f$cIw3$H&^I7dNHU=sw$d)j7 zh|(sSuhT>1EWU{wVQLz{XV1iYPIvxnNv=>Vu3kdkB_SVNJ(KJiSF;#9T-Gc6A9!kU z?a4i1-1H;R$hx=;;1@G7Jsm?|a=U>2b+qZz`aN9sgsIyFSp6r%%!9oq%tbmjY#K7P z-Gux{jUMaKw>DF`W{3tTZ|SIDqX6v)w4@1rITXmow6pv9GTr+NsJ`V>Zv++iD5MFK z@5#Rx6sk|u-Qs__;w5Q)X2-Ad+QXxzHC&)U-n+`G@G_e77|5&TV3EucN^AXqK{AmK pCn+FvZU>f5ukGw-)qi%3dglGbB=rNWkH7i=^YbXv3KMkH{{f&jC-?vW literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-lightness/jquery-ui.css b/share/pnp/media/css/ui-lightness/jquery-ui.css new file mode 100644 index 0000000..ebede8f --- /dev/null +++ b/share/pnp/media/css/ui-lightness/jquery-ui.css @@ -0,0 +1,563 @@ +/*! + * jQuery UI CSS Framework 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.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:before, .ui-helper-clearfix:after { content: ""; display: table; } +.ui-helper-clearfix:after { clear: both; } +.ui-helper-clearfix { zoom: 1; } +.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 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * 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 .ui-widget { font-size: 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, .ui-widget-header .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; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .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; } +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .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; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .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,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .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, .ui-widget-header .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* 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-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.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-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-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; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*! + * jQuery UI Resizable 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px; 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: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; 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;}/*! + * jQuery UI Selectable 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/*! + * jQuery UI Accordion 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.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 .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 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; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/*! + * jQuery UI Autocomplete 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.23 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/*! + * jQuery UI Button 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/*! + * jQuery UI Dialog 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.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 { position: relative; 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 .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/*! + * jQuery UI Slider 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.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; background-position: 0 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; }/*! + * jQuery UI Tabs 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.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 { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/*! + * jQuery UI Datepicker 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.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 { 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 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%; font-size:0em; } + +/* 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 { + 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*/ +}/*! + * jQuery UI Progressbar 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; overflow: hidden; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/share/pnp/media/css/ui-multisite/images/contentframe_background.jpg b/share/pnp/media/css/ui-multisite/images/contentframe_background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c8f85a194df266aaca360e1fba13a6bfd43a73db GIT binary patch literal 98551 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

    <*efrzAAi2^<62?( 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

    DL&)TRlTw; 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 DSH>_4 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-bg_flat_75_6da1b8_40x100.png b/share/pnp/media/css/ui-multisite/images/ui-bg_flat_75_6da1b8_40x100.png new file mode 100755 index 0000000000000000000000000000000000000000..26c1753b86a799c5fd98708db6413e7361d18138 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*Fsaj7L$B>N1x91EQ8x$BA9GB=X z%t^HFJW$ZgSI_w_>ig$D`PuR8eq5`XRxQw4L1l`U(T=%Sr7qeQ=nw`^S3j3^P6z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-bg_glass_65_88b9ce_1x400.png b/share/pnp/media/css/ui-multisite/images/ui-bg_glass_65_88b9ce_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..7e4f13c56ce7159242144202193b9abcfd3439a7 GIT binary patch literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq+C2*978O6-=1H{+YlhYa&f2S zul(ku7Z0qZ93CEQP>vAV^h{MbOy{!^AEOh;{?xl=Iu5Hh>@K)8`+Cm7YuUg5&J;K# atj_v_v(xqL{h2`X7(8A5T-G@yGywoEpe$nm literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-bg_glass_75_6da1b8_1x400.png b/share/pnp/media/css/ui-multisite/images/ui-bg_glass_75_6da1b8_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..5f6e63ecb1ed2b93b60dba7d2b35cbd75f4154c4 GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour2IWy978O6-=1H{+mIm8eDU7( z-5d5NOS(C1V(e2q@P|XlhSTzM(8aE-xNE|mS+kyP&-ty`A)w|W6}U}9dD)f~U*_fn m{#>y{^7i}lCcdAKv3^|7nfLL|lm$Se89ZJ6T-G@yGywpS%rj;H literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-bg_glass_75_94cde6_1x400.png b/share/pnp/media/css/ui-multisite/images/ui-bg_glass_75_94cde6_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..6615adeddd3ce6038917f0d51945042d62af7822 GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAGVZ#9R3S1u8sU978O6-(K0s*W@73^6-D! z!*?1TB2!HE)xUfkk(lI~b7e+DtJo*5dlO~OUVrDOCh7P5wmXBR#Cv0@sQzEe{A%W` zIl270wCwJVteuM{r9b@@b3sw!l~Zd}e)JD5M%MB;z3IpIyz@3$xJ; cZ~jcy?^z;SsvLXoEzk`Np00i_>zopr029?mp8x;= literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-bg_highlight-soft_75_274554_1x100.png b/share/pnp/media/css/ui-multisite/images/ui-bg_highlight-soft_75_274554_1x100.png new file mode 100755 index 0000000000000000000000000000000000000000..1514e63a767249361de784799231bcdfffbba375 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l((mgV~E7mtNj~!8yt9;b@k74 zO*zx~wx#L%{ui1HEa!@mdKI;Vst0Kl>>&;S4c literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-bg_highlight-soft_75_6da1b8_1x100.png b/share/pnp/media/css/ui-multisite/images/ui-bg_highlight-soft_75_6da1b8_1x100.png new file mode 100755 index 0000000000000000000000000000000000000000..8f1a78905e146262f672cbb1e38f37b64419dcc9 GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l&7bQV~E7mtNj}}8ypyz``_4i zcUv@^t`X|Ko}a_I(b9>7J@Ixw*8}&0u1SlwoZ$4@IZ4S{Ou}E*`%9 zKPdOkfrN+ZlHSt7(uY{3{#;wiJb&Ugx1>W4qtrSDm(4hFaaY-$3p3x|sIU3`%J?Qj YcLn#R=pC)AfTl5cy85}Sb4q9e0MP_2(*OVf literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-icons_000000_256x240.png b/share/pnp/media/css/ui-multisite/images/ui-icons_000000_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..7c211aa089a197902b68105e8bdc3834fe770203 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-icons_222222_256x240.png b/share/pnp/media/css/ui-multisite/images/ui-icons_222222_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..b273ff111d219c9b9a8b96d57683d0075fb7871a GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-icons_2e83ff_256x240.png b/share/pnp/media/css/ui-multisite/images/ui-icons_2e83ff_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..09d1cdc856c292c4ab6dd818c7543ac0828bd616 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-multisite/images/ui-icons_454545_256x240.png b/share/pnp/media/css/ui-multisite/images/ui-icons_454545_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..59bd45b907c4fd965697774ce8c5fc6b2fd9c105 GIT binary patch literal 4369 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 DSH>_4 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-bg_flat_75_ffffff_40x100.png b/share/pnp/media/css/ui-redmond/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-bg_glass_55_fbf9ee_1x400.png b/share/pnp/media/css/ui-redmond/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-bg_glass_65_ffffff_1x400.png b/share/pnp/media/css/ui-redmond/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-bg_glass_75_dadada_1x400.png b/share/pnp/media/css/ui-redmond/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/share/pnp/media/css/ui-redmond/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-icons_2e83ff_256x240.png b/share/pnp/media/css/ui-redmond/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-icons_454545_256x240.png b/share/pnp/media/css/ui-redmond/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 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 k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/images/ui-icons_888888_256x240.png b/share/pnp/media/css/ui-redmond/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-redmond/jquery-ui.css b/share/pnp/media/css/ui-redmond/jquery-ui.css new file mode 100644 index 0000000..da30a19 --- /dev/null +++ b/share/pnp/media/css/ui-redmond/jquery-ui.css @@ -0,0 +1,563 @@ +/*! + * jQuery UI CSS Framework 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.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:before, .ui-helper-clearfix:after { content: ""; display: table; } +.ui-helper-clearfix:after { clear: both; } +.ui-helper-clearfix { zoom: 1; } +.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 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } +.ui-widget-header a { color: #ffffff; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; } +.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.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-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -khtml-border-top-left-radius: 5px; border-top-left-radius: 5px; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -khtml-border-top-right-radius: 5px; border-top-right-radius: 5px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -khtml-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; -khtml-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*! + * jQuery UI Resizable 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px; 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: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; 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;}/*! + * jQuery UI Selectable 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/*! + * jQuery UI Accordion 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.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 .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 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; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/*! + * jQuery UI Autocomplete 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.23 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/*! + * jQuery UI Button 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/*! + * jQuery UI Dialog 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.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 { position: relative; 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 .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/*! + * jQuery UI Slider 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.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; background-position: 0 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; }/*! + * jQuery UI Tabs 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.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 { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/*! + * jQuery UI Datepicker 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.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 { 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 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%; font-size:0em; } + +/* 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 { + 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*/ +}/*! + * jQuery UI Progressbar 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; overflow: hidden; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/share/pnp/media/css/ui-smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/share/pnp/media/css/ui-smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/share/pnp/media/css/ui-smoothness/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/share/pnp/media/css/ui-smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/share/pnp/media/css/ui-smoothness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-bg_glass_75_dadada_1x400.png b/share/pnp/media/css/ui-smoothness/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/share/pnp/media/css/ui-smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-icons_2e83ff_256x240.png b/share/pnp/media/css/ui-smoothness/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-icons_454545_256x240.png b/share/pnp/media/css/ui-smoothness/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 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 k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/images/ui-icons_888888_256x240.png b/share/pnp/media/css/ui-smoothness/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/css/ui-smoothness/jquery-ui.css b/share/pnp/media/css/ui-smoothness/jquery-ui.css new file mode 100644 index 0000000..8230384 --- /dev/null +++ b/share/pnp/media/css/ui-smoothness/jquery-ui.css @@ -0,0 +1,563 @@ +/*! + * jQuery UI CSS Framework 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.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:before, .ui-helper-clearfix:after { content: ""; display: table; } +.ui-helper-clearfix:after { clear: both; } +.ui-helper-clearfix { zoom: 1; } +.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 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* 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_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.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-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*! + * jQuery UI Resizable 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px; 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: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; 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;}/*! + * jQuery UI Selectable 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/*! + * jQuery UI Accordion 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.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 .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 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; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/*! + * jQuery UI Autocomplete 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.23 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/*! + * jQuery UI Button 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/*! + * jQuery UI Dialog 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.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 { position: relative; 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 .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/*! + * jQuery UI Slider 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.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; background-position: 0 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; }/*! + * jQuery UI Tabs 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.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 { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/*! + * jQuery UI Datepicker 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.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 { 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 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%; font-size:0em; } + +/* 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 { + 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*/ +}/*! + * jQuery UI Progressbar 1.8.23 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; overflow: hidden; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/share/pnp/media/images/1x1.gif b/share/pnp/media/images/1x1.gif new file mode 100644 index 0000000000000000000000000000000000000000..f191b280ce91e6cb8c387735c10ef9bc5da6c83b GIT binary patch literal 42 ocmZ?wbhEHbWMp7uXkY+=|Ns9h{$ybUF?B!$NQQxl(S^Yp0J!f4_W%F@ literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/add.png b/share/pnp/media/images/add.png new file mode 100644 index 0000000000000000000000000000000000000000..ade93b9bf11e28f3ef26789a5679493dae71e9db GIT binary patch literal 1447 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 N002ovPDHLkV1oARR!aZ? literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/color.png b/share/pnp/media/images/color.png new file mode 100644 index 0000000000000000000000000000000000000000..c8799753a020f83107ed24b16d085542615ef062 GIT binary patch literal 11493 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 Ch&4z6 literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/de_DE.png b/share/pnp/media/images/de_DE.png new file mode 100755 index 0000000000000000000000000000000000000000..bf04e9268ae9814812366919982b39086cc2ef31 GIT binary patch literal 3793 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 V-swNf#i0NI002ovPDHLkV1f``J8b{} literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/en_US.png b/share/pnp/media/images/en_US.png new file mode 100755 index 0000000000000000000000000000000000000000..767835b96a7ec2b5e9907d74663261b6fec995a8 GIT binary patch literal 9270 zcmV-6B+1)}P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBVAv`IukRA@u(dwE=z$GLXep5&abX_^{sjH#`sZE9#wny-mQMG#l^ z9c14ZS5y!bca4IAD4-~aEDFkwh^Xwlh%Cw?3J566%d5EW3d(YwYn~UEsOjm~bN)Dg zd@sMtS)ZA?=AOA{=AQAr_x}Iy?H&jY4*pesNy&GmrKb%E)3UNMlZuLJlluC4lj@op zld`f3lM=>>c!gVGQe9oc^b3;vdb;EC+Pr zvYr1e`JFp=Zd!NuwS<;7*|o-&cC^c`52FWn9z2Ek^$h^BYqxNv>l!+`d+1(8*VP+% z{A^H4zyJ6-I=gS6y{iWuvL5AHi))^40X-yBHNKmCV@7nPolZ)v}VigS%9t2~dgih5MmT*QS-?WnuhhVtrq#@7+T zB`RuhuKp4$lCknjD66W&sj6C>VxH4g=Oxr$XvM|m4vBDa*;$-D*MPe>?_%g#KZg3A zW2m)N-OG+nSUDD zj2Fl)s>G$Xt9aN8w07MnW1=G)<=yVM_uinM|Cj)4>)Pd~$GL$myGCSv1 zTPJR_Bkwd{!9C(GajUrvw^~|pr=^YY0+(@{Q|fwa7p}EaicQ@pD{n?_@kQ3rh|IzU z6qa4Uh2}2Y7meUF>woYFLpN`u`1tYVKT0}0C}_-urjGk(YMPOHyZ~t@OOSS=7)R(o zRdF6&JrB^*d7TxMGd-W_MNBV3dS(fSd>guNK0;k{CywRtn-lpsnpq^}JDz(A7u)2J z-F%30j+&z<3y{t9%A683vg4ZQHfI;3g>Fk$F`BXp8CQU2;!<`Y(~58*rwBE9WhfT{ z$gaZith2259FApHqo}MAowB7&d8I($Ffc#J*yO{8SIP`g~%*8!*Gd|o_4Yr>Di@HC!{c(&PIy# zRECq8|7dmz(n;uu2&d=Z_>nA}IhKnCcF2XJIcPeXjh6I0w9wxy!s*$#B;trB=0DH8 zRTMx@Mk!K`6eA&32%`d3=Pu*!Z7R^`z_VKqAg`)H^GSYl^cY%+>xIS0ICyaBI|)a| zCS@dLl;A+Z2@*Yxw(i?#YQK&&_Ih-}F+{~5N7UhCh)q1fAykLX>yL2uVmlJpps4tC z=E*>G+)>1*W}>3*61r|YMoCp8Vv{ow6_<{vgmfHCI)Ot(D$6TM%0PAUahyv`M;%em z@6RV@(4T=?rq{+FLmg3*bP{LN3s7(*A4zeUh>gp_@$5>pUcQOvebn_&C{+&q)~o_t zNKV7Wq*Po;Okr8cxPGb(RhgL?ZxJ3j^1YAtM8!8n#%E$rR5DU2!H(-3!m`_lC!sx2 zi3mNIhP_d#2#ZeP+&K&Roo6`P)QRZCW7r*;fUtw92#rocL~JU`Yn#z?zaK@FjR-rC zsz{GX#lF}y>|^*4{Y7b6s5zOB+Ke339;2U9t>fsZ&B({O^jw@fnv1&QMX1dxM{a5X z4(?Au%)xY&o;r^koIc>n_w2@Pbd{b)LwqtC4jz(l?m#T64=3PKegXP#-GQvFt%-y` z{sC#_Z~lGU?)`_ahQ_30XXqj9Wy2GXgY8k?FW zkqHVvjF6}#1dDw8;}Ap1rLfbYIa-3k;;<_s0U<0iXnz8>?>>NoF)3)OX~O+$cX0pe zP2A%eeYfj6?osL8lik8yuGjavZ{acZ#+CD3h>JOnxWgxLv7rNfPbt;MeYkPqBI?u9 zQ57DAny?7e?TbKFSU76q63~675>Id3l(cnEPmlcH{_VYSB>a;Xq<=d0*T4KCySPeT zd9f2=u}9z&7(qm0%g+7q35vi04$HE-%gEtS4rZf$0{1J@2)|v?Bv*>^^BqXdK8=9A zG4Krx$CiLl_%dA(&Md0I>DtRUl$MW;{-FqEr(EG0{nqb|-N=&%eW)m{MK*OuXBP=j zG4*kS)0Ulw%J2xB*|i5}cZcCjPzX+kgrf0CI&L?%VCWI&^>A6;-Lh*ReDL0QlKt5W z!vFHYd+&{}zIa7`ol96`!f~we-GjB;!m(~!7}nAscQhaJ`vW-Negiux#nrwc*x=9f zt$VS_FAQ15_2}WZ1=X$io+Q`$24my4Jy_=x0{>kxsA}lO)%(DaoCCvWY>Q2!3TdK+4o-%et*o!Uno&A$NI|$;-re)z`|p4C1Hu!&8n3isy`S8J z1eUJ$qjW#LVhQ7yk(@|hzJ5D) zh8;p|S`N1Ej$!_taQ6a}bI+$FFh+c8!g_%3ayDsta6Jn$T9+ zfE#UH=zsVG_pkThQgI0ib_C<-a&KgLdZWO5Epk_{Ly7+mG-sT|BiU6+feC&?!WCo( zxr3AbfV%UIF9>rWD}L__!b`k2%NKb0!gDoiowcp0(po4H)vL3D;-^0ay z6BaU0WO6<_?+qfKL)dH6Za6Mk$Mnr`Ub>N_0+3O74&4uj5J#ylUcCdZ%QjJx-h3)(`m`CEFu_usyrUm{HX>eG!3Dzvrj_Hm|Hj?}%crIFt-E>pEw%~-vCY*HN zfb_*{acH48iX!9iu=^_RbjwgvRD#+(?zW0baiz2zZH1@lR^mZt4~IR;34Vh@qTGKE z^kQ(Z4}%o7pe&?)*ps-^(oKxp24_mncF`KRtqy?r){Vo~j-BGn^m(3J;o!a*HYDP{F_7t@ zl&%kKTvlQ!v1{>qByuzzWoI0nw-WKro+zM#yxq_y32ES2ANn3YK|c=`gU=L)hyGql zu}^XI6u&_#rlA3Dvq+Su42kdn=dcj;5H-3er?s`U=Y7Q-ekI{weDI!9&Z!1@L+2yT z-+eH$T?!*R4;a|G!@y=Kw(N>Uedm4T@^rFb#a0+H&e)#mbj@8>AUrW2=ewWc(6Mrk zf^{&kUIs&cFW^A($BJvv$o+0mL^9^uEQ719Yt5Yp zUCYJHw}9jpBQW|HDq8MhKZm%9{c>nqEQX%-QfSUyzz$i7gyW^CZ0zC+5CbhE7dSh3 z;0TwuE7_;eb*u>ONm-E7-`mlHfqRe9f9D?h@7-6p5*`pDEI>c!ZvVYuyzZCc9xBrB zJ_LBwyxh>(^Zti#NO;0mj^!pMKE<<0T)j{IJ)~% z>dT;S?FI|ZTN4L&=rXU>{MDGh!Vk9W3|-5GFt%F)OAb?g8#iJJrM#Z$KCt8*pRQ{U z2UjngDXHdC#Ibk37x#)PP#+qN%Aio3-Mb%Ed&5w3@-aasL721n=q@{f9sNP{JC@6O=TJUF6gB=RsrcLd>H!P35^Yj>kVc&b1i^PEgZx z!8AQ*XqYX+3g1wiEU(3$L+LPe^u$a(d#LH!V!ECk3~iSnfZNaP)90`;=m4~>+@PlK zfN3maj+q-&bR1yivYhAYT504yZfi%bk3SBY+aSrr0_hf3IAU&rl(}X&VrGf7x&Ht} zzBh2x+!`l|C`+rJu@fi$kg(qL2})n78p+3fqmKzQ%(0Nl=WN?`6xX(M2yenv4Qn>q z6{Sd1e;K zlgh9_maYM^Ri`6*_MD!v)0N*QJaLYd{PVAMFh*%QzMEx%#cP7$zF`lCEG0y#%rKY_ zRc#X1v4e%{8m!(Lh526FF^fc1Noc0QJi2z6q2~z4Wm~a&`(aot@`b9dD?7X2E6 z^D$`_2~%+urx&9+Js*j-u1L`~KoKQ$%FG<4rlu$xMhQt5lY9v~K>_pE{IB9lIU-6) zw%FJd1zI}Do;DpPCrv@Yq)CWZSAU!E_;DkZR&I-wuLwxQR2?Ub{c09I`%(?R`>Q(s zGR27Vc^v{Gk7Hdxtfa_PG;AC7hzam~N4g zA&QNR=^8QJgmKJg!u%2#HZUYfE#yw0fy~KMkU4P@PJTCu{>dns{3C?9Kq+OMYLuVr z9)z*;8hlE!zxk`Cgin=bz}9^`>g3OnRoMv*)5Z8&#RyZi>`BZDD%$o4K9q+xZh9iq zDmd4j@!f124r6D0Gt(Bc=PpHhVI#V(55RXv6sAnmgUK`B0mBA#Ns7dUo3F2jJRNQ1%$beMY143G%48g$I8lK~-{AzM`ohhp zKkl6p9y3yD)wWRi`k(|%qy$ENp@OkrYvH%V=<(B_!XddXFdmE7?#34rH1XMZRs3;+ z4*fb9KT!)dZkrJplY@n;gE5hkpD@D`Q#2j$w;2|gqG5|wTlOK8yDn!Z56qsb33qj4 z95S##j)4gZ^z~7suZto<(m;n{T?HvUlGi19ZAwpL4zg#>M5dZ5PEMUdQY81?1PQ`_ zVls)of#ZzNBjVKGHHS5nmA+Ncl#lt7GCm_llh9}-ReU;rDn9+wRE+sj1;6=H6=TLL zOa4!pXVf33NbaX!OyM_E@tZ%ZVJz{xzo_B&U(LiH|L-jP>6_X3^LN_#kBQp&W`a6q zd^a1;YP#5^GZ*PP#>m$sK@Ckp9eL`rkv)4l@@CFJ9*1X+$~0svPemprm`TaK1czzn z6amK5e^Lt5{|*!~?wxa3dBRspR?bW1M%*-*xp>2p+dcDnE4U7OQ9*gb%-NgE%~EL% zHk-GKY2Gk*UBNVh8w;`7(6?T~HGDbDo%szn7M9e+=3IWvg=^ypM@x4sm}8E$lV>4H zWfqPos~}5R89AJ5S!{HcvXIh5`X{4cvI_EvoGDX~P2?!Q8(AcjP5fAT3BOC!c!$#B z0a>Y}qFUb3a~qdBnfL0QiR&>WkBC>`m9ZzI)P-jJE z+!<;pP@9H=>1xO!j;N|2Y4&Usd#pgk_F$Cy2T3ULQ=rsO#O*@q_F)J=QNnmd9;Uy{ zI~*2ynWs814C%i9J)@Q0*h`NbH%6&2BvRf=yK#L)JnCtgtP78$>GLq^=_=v`Uc|-Y zyc8Zr1oK2H{0&6yzC$<_7Ry_Oe8^~9POx)A#Kdp7w2t;X=-m3>mI&I7mg6J!dAD9yR38nt`HOvq^Y1;-^mKnrsYN(dk#y zp5_{!!R>Sy56pfTuk+HkG`|b1aI1&!kGnL0r)5QT2il!Sy($OR%!chXM zI+8zz5Uv7>{0EqJP=LfkRMfHgTNT8*EW@3eE9j+RF5PJXqNgY$lWT2``b^}_nS~;C z4epjSaEMwt#?Ta9MP(RcSArxI<$ zyeS0Fz_>^EiQ=MOupMBhJ>zw3ePeUahi{&Tg@kvJa5NjePgNVCs+5>2r6sxA2w{8( z{b6(?r)eXC(hHxag?%I(%D6D5MbICnq5+@DGqBgn8C^N2IEOi<&(tH;(G}4us>ssN zK(3|+HyoNMMs^4xb`yJzY_Z?a7U70AOt&U%5yo#szA$399^-8np)xidgAZtE z=E%HRT7@Id^KgKQDx2HHJRKe6YYXTilbim888dL$)C^q(rP44QBw;a{r5{}imShQ8Jpp#*DA~|V41%rfutimkxxG&ATD-yWH~x3%qwhX`(*&=IgQdZ~?B|c=D3t z!1L$4L43-)VGVkzhtWLs4ddM~+ zSz|pyA14`3)>cQNl_lhboWuNG>3I%MpE!K2>PXC|9nBM7TcVMFrV&rYs1nkqqHy@;eJgTdM{U#=F6Bcv$YU39!!0b=6KaO5uyR{6iuhFNiFoe7-@vnHl=frv_CDeoE$)Rm$GFYy=IT(i z*$?}ioO{N8{q+xxcw$-FYvm|EWMGL%eRD+VTX3^)fhYqj!iI6y3|mTZk@{xXM>o*G z9_#ey!&=J?v$ec1!)P;RnEFy8UT|^`!KE$*;X7w*k><7p@m!7y&F2y{vm-B_-> zF-G>18!LrL+Ry@FCid8Fz8LPN?l9E%!Yq=VWwrw|O}9c>(+e)kcJnN(Abg9D)Y9BI zB6Ml8u`ok{1qqXE9^I34<7m%{r?Qa`6Yh}pk#IbwYI99o9!Fvom5W?KfaVSbpZ?FCm# z_y>fSx+9LZt9(lf6k5_sN#qfkL>#S=agHvK4{t5oc}KNoOB_wY9++w3%Q9KE#SWGq zK*Ih|w_@1bhlYJ`nt+$_Hp7Q@a6XCPt076+oX1c3THwh;DorkBoh_|zZ!JIj)3`sU z1%+Kb#f$91kZ6?bibN^jc9aC~N8zshDB2x?VxlM{3dKA<#cqv+i_IEnvQka6ZBVxi zB!Z!C9zd@UM?W#_` zVp3d}KIL;JLAd2o)7ux~T$cWL@$C8bex7k3%lW93FK8Zh-o#@*Lwqd1fk*P2#4SAI zMb=%uUJc!S1P117F=y`g(6SCWFE1g_H(cl-zdyZxT`KNPKdq^%mX0ffkGQt+ zP(Q@G*}BSrt5?=0!L#9T^v9m^=ofUHJXri^VL?-=-RAh-R3%Cv|j)(1(@LInF67Yl;32WO0 zL(49RZV(9ulBgg{*wSyyIM%Jpcn$L{m|?hrx0&lXLO4<@FH7^f;_TUS^81YV*OyNo z==mt_;K5Ld@I&6FKX^=V;`6vQz(e$aSn)}?_IwZKFW-ZiMyp8B54sMl%svQuY>cjG zkS&Lu>1r(U-b;fYE%O{(w*+CY6*xqVoNaG|JO>-(5;;UBk!Wd#B<{rI;$1c32wex!hV4){TaQ`Bp1iRPz|p*V zgzSq76A#n)jOXQrxOl(xk+z10k-VUTkDlXh<_(t8bZvZ~ zZpvpE^EUTusn0Sdzh4pm@@!6;c*0RuE?XEA3CP$v;6-L9QC*t)1X!J0BbE+^~>WqNe7{`4nO!Oq_P|{)rdo!X=EHw$lw@94jSxZHu)M;fAK$ z)CWVj$`?5)lyHod1x}D)Cdp>II3tUMkGnV`o{B7qguC;KX~7sobIW~f^o!%Aoj1#6 z*{sXRF_8XX)+NBYS(mZ1NF!X>+0LTFna5d>4ThCl6dV`%w*1E*e>3yvKY#DDFJ7C! zFQoj_;a(W`S)ks;r8V4xJW3D9W>WmW-TxjcZMjYpLqMI8}OM)=} z%R%dXY~ra)*U}p%&VHa2Ao3~Nsx@@~tuA)9-nZT=hT}4}# z@9cJU-_hf;)c3Z7>-x(kCbp5k9`Q3x^7wMhm@%WoJG2*4eajU?TV(p^qYu7h;^beB z8eu*|O?9ocrFo#U^Sr$-F7rcOU0uWe9-N&;`hqYI509{wUS45d9?Qa(@EbQ*XS&Xk z`=;NG=^o3LNcqKgixw;jQ$R2%&bLKZo;lICoEs$r?2@%ya*EGtb%KAZluh*^cn~Qd_Ty3^fZPdp<|914~kAFXo?H}G~ynHhJqf#DD z_}SR8WBW;N3C)`y*B<|p1#4p0|DWT`qr?}8 zFFs_*rfiF24>9`FSnH1whlr<$!^Dw?1lf{J*`^AHYt#pEf0_6O@onNL@fz{HhXmP@ z&6kL865`_i#v$Ih&J zy_?laWmv6NaX-{X*3};!JJ0Qy8~XkJ#PQ?D&ynk8aw`|A2kG#&U!FK|Y9kuUdJ?H& zBv%;H2NVkhWHTA0QYqweIn-)3l*?t*>vgnSEwpT?-)uBcEEdgriESaDH$K(*jGj%W z(?cN?3gu6oJo#&Ksvg9xIzJqZL;|T|Y50LJgo$VzX>x8S5(tOG2m}JAEzqA#I*kf_ zF#OFXT7>$Fbu$(-zQ(t1J!YO2|2A!G(O!Z!WGh2GN~IE-`NQ*WwTkNl1cGc&v38i^}LWwCY9Tv zI6uu_M>Ltmn}1)y2h+w+tgi>Kvb>Dh*;%Zttms(;{C?w8gWL_~L68sfX>HAiD0v0# z_pPouR-kH-D9}r7$+OfOF^k%vT7@%S)J;n84-BmoYUp1?AP} z^I>{=+SG%5P_4^{JnL<7agiFVnLW}>V{y;T&0&0e++cow-t67UU#nGFGijVY?Z$iW z`AyBKX4co&jb>i27YWvb>Pj|b*Ws5B;`ewwMl03q?c2A_SQ<(PV}~}Rzv_4=ziddC zY&K6@1(PF^tN0o)G>p?sN!++`!^FSp^waUx;CjM<+du5;}y@ix~l zas1;n_B~(5)6X>U%y%02*7@QC`BlR+Gc$%??_7);cmhHEbUBKz&Tr%JViHfgQwB#C zQ+R42i6?HR7<&?rU);iDC%3WhHyP|Zlfet$Z{Ym-K2|+_M8Z8>NwgoxulGi0sLphq zAw|~URx*vV!6c5ZW$~(?2;_)7UR`7B%i`!<4oCl;!`OHZf10Y}o#h7Jyj|m&(?_R$ z2ZKQ${eBP8R(BV_axUHVZPR(GvwwMM32vSt@*&Q5C>W07-AEQ=!2(_vLPZPS0>&2e z_}M}czniaMKG8y>-AAzA#cZjKZfAggZ-8!hfKI26cK6OMe!bH=7o2aaYENgWpzm;% z>lvO4m*RPxik9$3tc26V8<7%zl`_UR8^~0<_n|624Al|Hwb5kEcLs`8 zJOjg{xOnl`oHDAa3Y4T?3aOYY`Rl0VJ z2ZJ}`dg{`q*1A1Z3B}>qz1LR_I6S-iR-G7r=l*T}{$T8Ph@rzTUgcYG z{7_D$QJXa+7+ZY5tX5+?*Y=vmmIl@yYrRj7zV4s;n@8OGJxYzIY5T6juXr8aPvY+| ze)2mxychFmyq}KQ+B2e4uYb4IY%P*gd3Sz$c&~o0-ERAAABJ7K22}@~H`=R4yPd9` zBP)K{SNsO*JLAzl*Xgsgz1!`y*ZDnpk;J2af4Z(+zy1i%o@W{B1osV;Yp3qjmj99b8PS+7rZmPFGchyFU?j12ODa^xk&1PU z6`GZ+!A6G&<;cpNs1{SB+8UBJ`y1-DyZ`MU-|zQ1KJVxId7eL>1kYX0TABu$003yY zx;Rjv3Ri`O8kGA4Wie1$>_>8T0Dz)IV=OdV#&l6>R?NCX^QUlICYS24vCTpZV{{m31j^s^tk%shai zJKI#Xh9+An9<>wG8|a?2z^QO!iyZd73n#G^nFTQ=ZXo>BPa!KqMs8in?8tvN*0y8p ziQtgF0K3b5ycXnVjm_4z*AK7G9cXVam+#LY78jq%%BmD?h*UVwD5^&07PSt^#uGT$ zqQQ^)CUO3)eWev0vny^^q~+6OF;KCuX0y;l0M!ZId5b-}(4=o2#C^N@8(8=zT%?rsL0H zYv99MA?;d#I>B%%Hj3P=W@|$=Pkhx|I=Ul*O?rH{GduVd?09byk1Bv!C2iyMXPl&( zYiu-6&9UQlWnVMsNuz1&eDbqd{K5{O9yPpDFiFTkq_CSSDwzFPMq{GY^Q}8yM^|&C zv_juEKXQKqy%OM}f%FxQo%cQIJq4_w%#QK+_D^N$p2#E+25Wj4c%(a) zI_mLx%Xt?G#r@)gjAgz=G+Hh`lmD98U4A#HOW!cWg=Ak|H;1Sv3QM?>r+V3XHtXg( zbSI-<>~mEfwmcA+878Y^qh@*D*YoO!H=(Rh=Q$kqOk9DT<$)a;VpCFet$VYDiBiFf z+T$Cuo`1WXtFcN;3t^a@wl&o>g;OP-6$d(tHAGD>)x(vFI6c-Nzg&A$_qiGmDfJ zI9Q%jnce0vT1t_~2~(UB?m%oy+MKATRx`U)QL~P4kXUIwC^t&XHJQpiT-)g28Mk-x2TLJsA~#gwjxHQl~4Cwxl}YV@;!b91vUhEz>%HliR-h z+z%AvLuIMExISStQdeQyEwkG^|Jf@a#7Tu%EJZ{bR`YpF3EiB`T7B^hLH9H$KE<0! zN`Rf7!KXg*9H|*@HW}^1McUC$|D`(?WUxio3I9CAW0F-zF)-6rKaOy_cbv9yq&lnX z>Vx{5^Z_Z2TSzs3SWHz;dm?YV%#CTuzkFQ!3v#mT*~DOmwMJ5p_EJYhn)$ct$fKPZ z;?^{sQ*uUE2)<4C0z8b znqi+L#J~2QV{5z|$q}pZy%|z5IL50)?zyJQ3UwCb<9|IRfN$*qoYSdv(H^+{lqsuZ6_uAJA>t-MC)o7p6E+%IH=GU-Al!XHWi7LB$Gd@pu5lferP=5Yl`UMLF{ zv>*|n{2~zoItqtGqu{(y`2Qiu&Yolx7KuUmByVSY^|)Z~U$211AuyIy3>w5^K?}$u z0eXea-ZBydtW|mR;sppJ=%Gv?A|e9G<{l9+=zONi+NH_u29Rj=f+#GM!2~=+kt`+` y?#h7Nzgi<5hqg`s+4kK-A%DH9>M-8C8o^en=kNNOSkww3fUDy!2dUlRxW56(Ti12~ literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/go-now.png b/share/pnp/media/images/go-now.png new file mode 100644 index 0000000000000000000000000000000000000000..91c21df1c8dfa2cc320d99348596e254d2589852 GIT binary patch literal 1660 zcma)+dpOg39LHCQQX(C4$w@i7aJK!n*~Um`$7EY(HcQJmve{U&$!&z{=t0V*MB`)? z%|x{ja>?pxsV9o3j?2*^xh2uaC5NNVZ`5*-{g$w7{_|qT)E1mb3S|5g?G#bSosdS{+6_5CMU#h}Oiig!aUzn$74i zd=Qu|7b9gZUjl(>`H={C2Jvx1J2hA;vUohvsgC6h*VCwAWk1_!C9%tIm3DJbtxy zmh5XYFlXpDiF-M$swygO>&Vs>EBkl%C{~umA9wO^$``-`JSC}yI9zo3gta|s5ra&{K9wkrqG`qUmG5*o^ zZh#ImYHrt6bf)j$esh1{LVdSfvy8T=~z>^MAbbz_q>r&)rz zRq~eFlSQ^pq1xn>HV4Yw=PP^#FKoP5y?)YHwa}ucKX=1H4{qMn-5=reSZmTRF4^Z; zz%_N&8D6_cIe-4+xk8lpon9&9&=1%t(Y=pDh@am1sjA!2cJbtH=JTDKNv9v{T8SLC zc%3(C9!&0;F~3(OT4nNHb-P$5D;WIVDygqr>boN?p4hh0`q86smlZBT=5(emfGp!! z65FL8Q1l%evnp7*xwMVn6;cvv3krNcShUVboVO)M>#ZyyjCgEFs$kjH7d@!_jj(lA ztT4YE_nwL^?X~N(dKlizT zYtaido-vbELmJsVV?<6$mQ`nDRJYE%?DJ4&XY4F*QaLf7@t_K`dpUK7qyR0~uxO_H zjgE)Kdb+Hr&G7nNTRJTsohlxcC1cj6Q7S7b^NHe&ob!1dh)_0r^p-X~y1(e9+RdLu zRY+=kIX)vkyaeUR6iE!~7}SQ6mew$qiA=3gIFnCZKXSG&-=dZ}o9f!Qp6VPtOb?*H zn>s+VS=VQ?y7f~&h1>J7ZkIm;TXD;C6VdfRgWBBGw66Cxa%a$GHORN5%v>F_RJ=&Hy>wb~@!9mf z4{Pc>lp|-1onWx%g^c!m4RfSD7s?t7vScB1cEe{-1!`?Ac6}Cj*JY$!QqQ< z@uRsMVQ8pO5CId02f+_7Nh09vSZG8590dd5mcnq$|3kRDdAh@qFa(^H>BRZwamn7l zx&WY{2nPlNz@d>iJ9{XA0lToxr)Dn*m})$F33-vCfN(BEBoe{+f{+MKKp0nJ?cxU~ zGf=c)NfZ^%;XS_#UePR$}e#wi@G z=&zAFlbeS?X#0{~ov5Vt1SRc6V7O8HM0fn%&fNa~yc|~x`?_?ba|4OJ;P9eMkm)iJ73pHl5+NLsqsR?~#+~y@wBevJk5#M26ApfR6ok zM`y6(TAyQVWK^z;$%ptyTJek|G#ZnQR6PuuI^+2GTuqGHe6%rfyk|W+~wAN$A?#f7yvAubNy3c~7%ern01_i);-szUdvjca!V93okJg)gn3Jmn~8%Ye|7L zztxvAXYD5y7DPNgFz^v|4=RpS)F#v~%dZH?-Y7GhDBg19Pg2=st)PLa>HRuBB}ek4 z1Lld&uO(Cin){HYjgP(G(&xzJ+hp1k-_Z8c>~|^t$mA!Zizzn4mL1$eflX%p!5}MJ zKO*L-mRc%*n<7?l<|Ya}HeN_z3H8Op=r)2$3a8$=ezYTB?&EJ^$f>_XJ4rdLFD46G z#yv2TZ2zc!90d7cvN0KDZ(derX08)|4l*0*oJ=sz3VTLs07tx&HXXT{SHf2ra$Urq z?+S(GUIQUg?=D5Qo!CTuqO^<2R1W#Yhi-_yg_n&+=td5{ub;L@I7|mOt$B&uluh4O z=+j8K+)X>$#nwKba&^_23-R(Rx3a3NT9e&b5sw#c8{B4U&@`G7DeLcfcy5Wmr8=479fHkYwd9&DAaK9%!ubRHPjUF@S?`LO>u$0B|?} zx0Q;sC4vwUZwr9%08G^rW_$-UO5!{P12_->ApioY5S|Fx5OLpt%p%Xr{{f=e2bp1U z-vGD+jtUZpc#w#*p6`%jAS1v)xWS7*k9EEQ=|TR*Ku3v9T-87-Mn07&cR841KtkP An*aa+ literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/graph.png b/share/pnp/media/images/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..d009c191661a0e6a00a055408389147635eb0f1f GIT binary patch literal 18017 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/home.png b/share/pnp/media/images/home.png new file mode 100755 index 0000000000000000000000000000000000000000..0a5f1fc79baee65306084f2b5a2983793dadd1c0 GIT binary patch literal 6263 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 Z5_#`hPk@N+l0(Y`9v>>;mSSbF1^{|46zKo} literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/loader.gif b/share/pnp/media/images/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..8186b0c050b2f21f5fc1214b3e6c860f251004ce GIT binary patch literal 432 zcmZ?wbhEHb)Mnsj_{hLuZsYL(|Nj}Y<^V~>|J;7AA;Hd$0j@@R2F#2M3=E3@WSvSg zb4nD-GfOfQ+&$eCeDljPQx)7(6N?l~^bCLsM12!eQWcUa6&$k?D}3@3Q}iM|oD6yK(JH6~0Z3sUlMO5ua-NPWfGaG)pHb==gfwJFl+{>Rqvu3O@J!8=0e(L3?nLra)tix)e1JtWCrtD&u zuG{!)XR6N%llks)fm$W%N7t?V&9~8P_SU)me>XjznBpA!_L;U<*$G!+fjtRI=LAH5 NF^MoRScAe13;=`*poRbd literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/notify.gif b/share/pnp/media/images/notify.gif new file mode 100644 index 0000000000000000000000000000000000000000..17f0b0b3fb22a1064f46dec5b3f3055f98256310 GIT binary patch literal 947 zcmZ?wbhEHb6k!ly_|5n!+-g=hG%zp=i?eO$c#w3g zhecXRqVi%xBO_Npn~3G4C7#SI985EAZc=Mv)KBJOnZVF+c9w#3>_!MHj z6rMXQ_L{Eedf`e6<4oSgS+)UJ4_svmm(06!%T&jyJMgp?!-4{az;$u+?Np?uD;?aB P@K(xXb$EgU1A{dHajYH3 literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/pages.png b/share/pnp/media/images/pages.png new file mode 100644 index 0000000000000000000000000000000000000000..3761e4731613434a5b358d0820f38458e268c482 GIT binary patch literal 7175 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 JPDHLkV1l;o%wzxn literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/pdf.png b/share/pnp/media/images/pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..560840b37230b2b740e81d406057d4544791eb63 GIT binary patch literal 5949 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/pnp.png b/share/pnp/media/images/pnp.png new file mode 100644 index 0000000000000000000000000000000000000000..711deaaf9feb588860b97b71bccb26e6cff6ae22 GIT binary patch literal 272 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 V26g*zkW2so002ovPDHLkV1h(DsfYjo literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/stats.png b/share/pnp/media/images/stats.png new file mode 100644 index 0000000000000000000000000000000000000000..cf4f5ef936dac33aea3faf3f035ffca9c5cbe00a GIT binary patch literal 6736 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 O^RlzEE!f#u7_0%>?--l_ literal 0 HcmV?d00001 diff --git a/share/pnp/media/images/view-calendar.png b/share/pnp/media/images/view-calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..18c78c7411ce085aaa4b7f6b8938695d6ef6f46c GIT binary patch literal 1293 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 literal 0 HcmV?d00001 diff --git a/share/pnp/media/js/jquery-ui-timepicker-addon.js b/share/pnp/media/js/jquery-ui-timepicker-addon.js new file mode 100644 index 0000000..ca506d5 --- /dev/null +++ b/share/pnp/media/js/jquery-ui-timepicker-addon.js @@ -0,0 +1,1276 @@ +/* +* jQuery timepicker addon +* By: Trent Richardson [http://trentrichardson.com] +* Version 0.9.7 +* Last Modified: 10/02/2011 +* +* Copyright 2011 Trent Richardson +* Dual licensed under the MIT and GPL licenses. +* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt +* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt +* +* HERES THE CSS: +* .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } +* .ui-timepicker-div dl { text-align: left; } +* .ui-timepicker-div dl dt { height: 25px; } +* .ui-timepicker-div dl dd { margin: -25px 10px 10px 65px; } +* .ui-timepicker-div td { font-size: 90%; } +* .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; } +*/ + +(function($) { + +$.extend($.ui, { timepicker: { version: "0.9.7" } }); + +/* Time picker manager. + Use the singleton instance of this class, $.timepicker, to interact with the time picker. + Settings for (groups of) time pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Timepicker() { + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + currentText: 'Now', + closeText: 'Done', + ampm: false, + amNames: ['AM', 'A'], + pmNames: ['PM', 'P'], + timeFormat: 'hh:mm tt', + timeSuffix: '', + timeOnlyTitle: 'Choose Time', + timeText: 'Time', + hourText: 'Hour', + minuteText: 'Minute', + secondText: 'Second', + millisecText: 'Millisecond', + timezoneText: 'Time Zone' + }; + this._defaults = { // Global defaults for all the datetime picker instances + showButtonPanel: true, + timeOnly: false, + showHour: true, + showMinute: true, + showSecond: false, + showMillisec: false, + showTimezone: false, + showTime: true, + stepHour: 0.05, + stepMinute: 0.05, + stepSecond: 0.05, + stepMillisec: 0.5, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: '+0000', + hourMin: 0, + minuteMin: 0, + secondMin: 0, + millisecMin: 0, + hourMax: 23, + minuteMax: 59, + secondMax: 59, + millisecMax: 999, + minDateTime: null, + maxDateTime: null, + onSelect: null, + hourGrid: 0, + minuteGrid: 0, + secondGrid: 0, + millisecGrid: 0, + alwaysSetTime: true, + separator: ' ', + altFieldTimeOnly: true, + showTimepicker: true, + timezoneIso8609: false, + timezoneList: null + }; + $.extend(this._defaults, this.regional['']); +} + +$.extend(Timepicker.prototype, { + $input: null, + $altInput: null, + $timeObj: null, + inst: null, + hour_slider: null, + minute_slider: null, + second_slider: null, + millisec_slider: null, + timezone_select: null, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: '+0000', + hourMinOriginal: null, + minuteMinOriginal: null, + secondMinOriginal: null, + millisecMinOriginal: null, + hourMaxOriginal: null, + minuteMaxOriginal: null, + secondMaxOriginal: null, + millisecMaxOriginal: null, + ampm: '', + formattedDate: '', + formattedTime: '', + formattedDateTime: '', + timezoneList: null, + + /* Override the default settings for all instances of the time picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + //######################################################################## + // Create a new Timepicker instance + //######################################################################## + _newInst: function($input, o) { + var tp_inst = new Timepicker(), + inlineSettings = {}; + + for (var attrName in this._defaults) { + var attrValue = $input.attr('time:' + attrName); + if (attrValue) { + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, { + beforeShow: function(input, dp_inst) { + if ($.isFunction(o.beforeShow)) + o.beforeShow(input, dp_inst, tp_inst); + }, + onChangeMonthYear: function(year, month, dp_inst) { + // Update the time as well : this prevents the time from disappearing from the $input field. + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onChangeMonthYear)) + o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); + }, + onClose: function(dateText, dp_inst) { + if (tp_inst.timeDefined === true && $input.val() != '') + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onClose)) + o.onClose.call($input[0], dateText, dp_inst, tp_inst); + }, + timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); + }); + tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) { return val.toUpperCase() }); + tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) { return val.toUpperCase() }); + + if (tp_inst._defaults.timezoneList === null) { + var timezoneList = []; + for (var i = -11; i <= 12; i++) + timezoneList.push((i >= 0 ? '+' : '-') + ('0' + Math.abs(i).toString()).slice(-2) + '00'); + if (tp_inst._defaults.timezoneIso8609) + timezoneList = $.map(timezoneList, function(val) { + return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3)); + }); + tp_inst._defaults.timezoneList = timezoneList; + } + + tp_inst.hour = tp_inst._defaults.hour; + tp_inst.minute = tp_inst._defaults.minute; + tp_inst.second = tp_inst._defaults.second; + tp_inst.millisec = tp_inst._defaults.millisec; + tp_inst.ampm = ''; + tp_inst.$input = $input; + + if (o.altField) + tp_inst.$altInput = $(o.altField) + .css({ cursor: 'pointer' }) + .focus(function(){ $input.trigger("focus"); }); + + if(tp_inst._defaults.minDate==0 || tp_inst._defaults.minDateTime==0) + { + tp_inst._defaults.minDate=new Date(); + } + if(tp_inst._defaults.maxDate==0 || tp_inst._defaults.maxDateTime==0) + { + tp_inst._defaults.maxDate=new Date(); + } + + // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. + if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) + tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); + if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) + tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); + if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) + tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); + if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) + tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); + return tp_inst; + }, + + //######################################################################## + // add our sliders to the calendar + //######################################################################## + _addTimePicker: function(dp_inst) { + var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? + this.$input.val() + ' ' + this.$altInput.val() : + this.$input.val(); + + this.timeDefined = this._parseTime(currDT); + this._limitMinMaxDateTime(dp_inst, false); + this._injectTimePicker(); + }, + + //######################################################################## + // parse the time string from input value or _setTime + //######################################################################## + _parseTime: function(timeString, withDate) { + var regstr = this._defaults.timeFormat.toString() + .replace(/h{1,2}/ig, '(\\d?\\d)') + .replace(/m{1,2}/ig, '(\\d?\\d)') + .replace(/s{1,2}/ig, '(\\d?\\d)') + .replace(/l{1}/ig, '(\\d?\\d?\\d)') + .replace(/t{1,2}/ig, this._getPatternAmpm()) + .replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?') + .replace(/\s/g, '\\s?') + this._defaults.timeSuffix + '$', + order = this._getFormatPositions(), + ampm = '', + treg; + + if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]); + + if (withDate || !this._defaults.timeOnly) { + // the time should come after x number of characters and a space. + // x = at least the length of text specified by the date format + var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); + // escape special regex characters in the seperator + var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); + regstr = '.{' + dp_dateFormat.length + ',}' + this._defaults.separator.replace(specials, "\\$&") + regstr; + } + + treg = timeString.match(new RegExp(regstr, 'i')); + + if (treg) { + if (order.t !== -1) { + if (treg[order.t] === undefined || treg[order.t].length === 0) { + ampm = ''; + this.ampm = ''; + } else { + ampm = $.inArray(treg[order.t].toUpperCase(), this.amNames) !== -1 ? 'AM' : 'PM'; + this.ampm = this._defaults[ampm == 'AM' ? 'amNames' : 'pmNames'][0]; + } + } + + if (order.h !== -1) { + if (ampm == 'AM' && treg[order.h] == '12') + this.hour = 0; // 12am = 0 hour + else if (ampm == 'PM' && treg[order.h] != '12') + this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12 + else this.hour = Number(treg[order.h]); + } + + if (order.m !== -1) this.minute = Number(treg[order.m]); + if (order.s !== -1) this.second = Number(treg[order.s]); + if (order.l !== -1) this.millisec = Number(treg[order.l]); + if (order.z !== -1 && treg[order.z] !== undefined) { + var tz = treg[order.z].toUpperCase(); + switch (tz.length) { + case 1: // Z + tz = this._defaults.timezoneIso8609 ? 'Z' : '+0000'; + break; + case 5: // +hhmm + if (this._defaults.timezoneIso8609) + tz = tz.substring(1) == '0000' + ? 'Z' + : tz.substring(0, 3) + ':' + tz.substring(3); + break; + case 6: // +hh:mm + if (!this._defaults.timezoneIso8609) + tz = tz == 'Z' || tz.substring(1) == '00:00' + ? '+0000' + : tz.replace(/:/, ''); + else if (tz.substring(1) == '00:00') + tz = 'Z'; + break; + } + this.timezone = tz; + } + + return true; + + } + return false; + }, + + //######################################################################## + // pattern for standard and localized AM/PM markers + //######################################################################## + _getPatternAmpm: function() { + var markers = []; + o = this._defaults; + if (o.amNames) + $.merge(markers, o.amNames); + if (o.pmNames) + $.merge(markers, o.pmNames); + markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&') }); + return '(' + markers.join('|') + ')?'; + }, + + //######################################################################## + // figure out position of time elements.. cause js cant do named captures + //######################################################################## + _getFormatPositions: function() { + var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g), + orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 }; + + if (finds) + for (var i = 0; i < finds.length; i++) + if (orders[finds[i].toString().charAt(0)] == -1) + orders[finds[i].toString().charAt(0)] = i + 1; + + return orders; + }, + + //######################################################################## + // generate and inject html for timepicker into ui datepicker + //######################################################################## + _injectTimePicker: function() { + var $dp = this.inst.dpDiv, + o = this._defaults, + tp_inst = this, + // Added by Peter Medeiros: + // - Figure out what the hour/minute/second max should be based on the step values. + // - Example: if stepMinute is 15, then minMax is 45. + hourMax = (o.hourMax - ((o.hourMax - o.hourMin) % o.stepHour)).toFixed(0), + minMax = (o.minuteMax - ((o.minuteMax - o.minuteMin) % o.stepMinute)).toFixed(0), + secMax = (o.secondMax - ((o.secondMax - o.secondMin) % o.stepSecond)).toFixed(0), + millisecMax = (o.millisecMax - ((o.millisecMax - o.millisecMin) % o.stepMillisec)).toFixed(0), + dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, ''); + + // Prevent displaying twice + //if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) { + if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) { + var noDisplay = ' style="display:none;"', + html = '

    ' + + '
    ' + o.timeText + '
    ' + + '
    ' + + '
    ' + o.hourText + '
    ', + hourGridSize = 0, + minuteGridSize = 0, + secondGridSize = 0, + millisecGridSize = 0, + size; + + // Hours + if (o.showHour && o.hourGrid > 0) { + html += '
    ' + + '
    ' + + '
    '; + + for (var h = o.hourMin; h <= hourMax; h += parseInt(o.hourGrid,10)) { + hourGridSize++; + var tmph = (o.ampm && h > 12) ? h-12 : h; + if (tmph < 10) tmph = '0' + tmph; + if (o.ampm) { + if (h == 0) tmph = 12 +'a'; + else if (h < 12) tmph += 'a'; + else tmph += 'p'; + } + html += ''; + } + + html += '
    ' + tmph + '
    ' + + '
    '; + } else html += '
    '; + + html += '
    ' + o.minuteText + '
    '; + + // Minutes + if (o.showMinute && o.minuteGrid > 0) { + html += '
    ' + + '
    ' + + '
    '; + + for (var m = o.minuteMin; m <= minMax; m += parseInt(o.minuteGrid,10)) { + minuteGridSize++; + html += ''; + } + + html += '
    ' + ((m < 10) ? '0' : '') + m + '
    ' + + '
    '; + } else html += '
    '; + + // Seconds + html += '
    ' + o.secondText + '
    '; + + if (o.showSecond && o.secondGrid > 0) { + html += '
    ' + + '
    ' + + '
    '; + + for (var s = o.secondMin; s <= secMax; s += parseInt(o.secondGrid,10)) { + secondGridSize++; + html += ''; + } + + html += '
    ' + ((s < 10) ? '0' : '') + s + '
    ' + + '
    '; + } else html += '
    '; + + // Milliseconds + html += '
    ' + o.millisecText + '
    '; + + if (o.showMillisec && o.millisecGrid > 0) { + html += '
    ' + + '
    ' + + '
    '; + + for (var l = o.millisecMin; l <= millisecMax; l += parseInt(o.millisecGrid,10)) { + millisecGridSize++; + html += ''; + } + + html += '
    ' + ((l < 10) ? '0' : '') + s + '
    ' + + '
    '; + } else html += '
    '; + + // Timezone + html += '
    ' + o.timezoneText + '
    '; + html += '
    '; + + html += '
    '; + $tp = $(html); + + // if we only want time picker... + if (o.timeOnly === true) { + $tp.prepend( + '
    ' + + '
    ' + o.timeOnlyTitle + '
    ' + + '
    '); + $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide(); + } + + this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({ + orientation: "horizontal", + value: this.hour, + min: o.hourMin, + max: hourMax, + step: o.stepHour, + slide: function(event, ui) { + tp_inst.hour_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + // Updated by Peter Medeiros: + // - Pass in Event and UI instance into slide function + this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({ + orientation: "horizontal", + value: this.minute, + min: o.minuteMin, + max: minMax, + step: o.stepMinute, + slide: function(event, ui) { + // update the global minute slider instance value with the current slider value + tp_inst.minute_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({ + orientation: "horizontal", + value: this.second, + min: o.secondMin, + max: secMax, + step: o.stepSecond, + slide: function(event, ui) { + tp_inst.second_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + this.millisec_slider = $tp.find('#ui_tpicker_millisec_'+ dp_id).slider({ + orientation: "horizontal", + value: this.millisec, + min: o.millisecMin, + max: millisecMax, + step: o.stepMillisec, + slide: function(event, ui) { + tp_inst.millisec_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + this.timezone_select = $tp.find('#ui_tpicker_timezone_'+ dp_id).append('').find("select"); + $.fn.append.apply(this.timezone_select, + $.map(o.timezoneList, function(val, idx) { + return $("
    '); + (opts.closePosition == 'bottom') ? $closeLink.appendTo($cluetipInner) : (opts.closePosition == 'title') ? $closeLink.prependTo($cluetipTitle) : $closeLink.prependTo($cluetipInner); + $closeLink.bind('click.cluetip', function() { + cluetipClose(); + return false; + }); + if (opts.mouseOutClose) { + if ($.fn.hoverIntent && opts.hoverIntent) { + $cluetip.hoverIntent({ + over: doNothing, + timeout: opts.hoverIntent.timeout, + out: function() { $closeLink.trigger('click.cluetip'); } + }); + } else { + $cluetip.hover(doNothing, + function() {$closeLink.trigger('click.cluetip'); }); + } + } else { + $cluetip.unbind('mouseout'); + } + } +// now that content is loaded, finish the positioning + var direction = ''; + $cluetipOuter.css({zIndex: $this.data('thisInfo').zIndex, overflow: defHeight == 'auto' ? 'visible' : 'auto', height: defHeight}); + tipHeight = defHeight == 'auto' ? Math.max($cluetip.outerHeight(),$cluetip.height()) : parseInt(defHeight,10); + tipY = posY; + baseline = sTop + wHeight; + if (opts.positionBy == 'fixed') { + tipY = posY - opts.dropShadowSteps + tOffset; + } else if ( (posX < mouseX && Math.max(posX, 0) + tipWidth > mouseX) || opts.positionBy == 'bottomTop') { + if (posY + tipHeight + tOffset > baseline && mouseY - sTop > tipHeight + tOffset) { + tipY = mouseY - tipHeight - tOffset; + direction = 'top'; + } else { + tipY = mouseY + tOffset; + direction = 'bottom'; + } + } else if ( posY + tipHeight + tOffset > baseline ) { + tipY = (tipHeight >= wHeight) ? sTop : baseline - tipHeight - tOffset; + } else if ($this.css('display') == 'block' || link.tagName.toLowerCase() == 'area' || opts.positionBy == "mouse") { + tipY = bpY - tOffset; + } else { + tipY = posY - opts.dropShadowSteps; + } + if (direction == '') { + posX < linkLeft ? direction = 'left' : direction = 'right'; + } + $cluetip.css({top: tipY + 'px'}).removeClass().addClass('clue-' + direction + '-' + ctClass).addClass(' cluetip-' + ctClass); + if (opts.arrows) { // set up arrow positioning to align with element + var bgY = (posY - tipY - opts.dropShadowSteps); + $cluetipArrows.css({top: (/(left|right)/.test(direction) && posX >=0 && bgY > 0) ? bgY + 'px' : /(left|right)/.test(direction) ? 0 : ''}).show(); + } else { + $cluetipArrows.hide(); + } + +// (first hide, then) ***SHOW THE CLUETIP*** + $dropShadow.hide(); + $cluetip.hide()[opts.fx.open](opts.fx.open != 'show' && opts.fx.openSpeed); + if (opts.dropShadow) { $dropShadow.css({height: tipHeight, width: tipInnerWidth, zIndex: $this.data('thisInfo').zIndex-1}).show(); } + if ($.fn.bgiframe) { $cluetip.bgiframe(); } + // delayed close (not fully tested) + if (opts.delayedClose > 0) { + closeOnDelay = setTimeout(cluetipClose, opts.delayedClose); + } + // trigger the optional onShow function + opts.onShow.call(link, $cluetip, $cluetipInner); + }; + +/*************************************** + =INACTIVATION +-------------------------------------- */ + var inactivate = function(event) { + isActive = false; + $cluetipWait.hide(); + if (!opts.sticky || (/click|toggle/).test(opts.activation) ) { + cluetipClose(); + clearTimeout(closeOnDelay); + }; + if (opts.hoverClass) { + $this.removeClass(opts.hoverClass); + } + }; +// close cluetip and reset some things + var cluetipClose = function() { + $cluetipOuter + .parent().hide().removeClass(); + opts.onHide.call(link, $cluetip, $cluetipInner); + $this.removeClass('cluetip-clicked'); + if (tipTitle) { + $this.attr(opts.titleAttribute, tipTitle); + } + $this.css('cursor',''); + if (opts.arrows) $cluetipArrows.css({top: ''}); + }; + + $(document).bind('hideCluetip', function(e) { + cluetipClose(); + }); +/*************************************** + =BIND EVENTS +-------------------------------------- */ + // activate by click + if ( (/click|toggle/).test(opts.activation) ) { + $this.bind('click.cluetip', function(event) { + if ($cluetip.is(':hidden') || !$this.is('.cluetip-clicked')) { + activate(event); + $('.cluetip-clicked').removeClass('cluetip-clicked'); + $this.addClass('cluetip-clicked'); + } else { + inactivate(event); + } + this.blur(); + return false; + }); + // activate by focus; inactivate by blur + } else if (opts.activation == 'focus') { + $this.bind('focus.cluetip', function(event) { + activate(event); + }); + $this.bind('blur.cluetip', function(event) { + inactivate(event); + }); + // activate by hover + // clicking is returned false if cluetip url is same as href url + } else { + $this.bind('click.cluetip', function() { + if ($this.attr('href') && $this.attr('href') == tipAttribute && !opts.clickThrough) { + return false; + } + }); + //set up mouse tracking + var mouseTracks = function(evt) { + if (opts.tracking == true) { + var trackX = posX - evt.pageX; + var trackY = tipY ? tipY - evt.pageY : posY - evt.pageY; + $this.bind('mousemove.cluetip', function(evt) { + $cluetip.css({left: evt.pageX + trackX, top: evt.pageY + trackY }); + }); + } + }; + if ($.fn.hoverIntent && opts.hoverIntent) { + $this.hoverIntent({ + sensitivity: opts.hoverIntent.sensitivity, + interval: opts.hoverIntent.interval, + over: function(event) { + activate(event); + mouseTracks(event); + }, + timeout: opts.hoverIntent.timeout, + out: function(event) {inactivate(event); $this.unbind('mousemove.cluetip');} + }); + } else { + $this.bind('mouseenter.cluetip', function(event) { + activate(event); + mouseTracks(event); + }) + .bind('mouseleave.cluetip', function(event) { + inactivate(event); + $this.unbind('mousemove.cluetip'); + }); + } + // remove default title tooltip on hover + $this.bind('mouseenter.cluetip', function(event) { + $this.attr('title',''); + }) + .bind('mouseleave.cluetip', function(event) { + $this.attr('title', $this.data('thisInfo').title); + }); + + } + }); + }; + +/* + * options for clueTip + * + * each one can be explicitly overridden by changing its value. + * for example: $.fn.cluetip.defaults.width = 200; + * would change the default width for all clueTips to 200. + * + * each one can also be overridden by passing an options map to the cluetip method. + * for example: $('a.example').cluetip({width: 200}); + * would change the default width to 200 for clueTips invoked by a link with class of "example" + * + */ + + $.fn.cluetip.defaults = { // set up default options + width: 275, // The width of the clueTip + height: 'auto', // The height of the clueTip + cluezIndex: 97, // Sets the z-index style property of the clueTip + positionBy: 'auto', // Sets the type of positioning: 'auto', 'mouse','bottomTop', 'fixed' + topOffset: 15, // Number of px to offset clueTip from top of invoking element + leftOffset: 15, // Number of px to offset clueTip from left of invoking element + local: false, // Whether to use content from the same page for the clueTip's body + localPrefix: null, // string to be prepended to the tip attribute if local is true + hideLocal: true, // If local option is set to true, this determines whether local content + // to be shown in clueTip should be hidden at its original location + attribute: 'rel', // the attribute to be used for fetching the clueTip's body content + titleAttribute: 'title', // the attribute to be used for fetching the clueTip's title + splitTitle: '', // A character used to split the title attribute into the clueTip title and divs + // within the clueTip body. more info below [6] + escapeTitle: false, // whether to html escape the title attribute + showTitle: true, // show title bar of the clueTip, even if title attribute not set + cluetipClass: 'default',// class added to outermost clueTip div in the form of 'cluetip-' + clueTipClass. + hoverClass: '', // class applied to the invoking element onmouseover and removed onmouseout + waitImage: true, // whether to show a "loading" img, which is set in jquery.cluetip.css + cursor: 'help', + arrows: false, // if true, displays arrow on appropriate side of clueTip + dropShadow: true, // set to false if you don't want the drop-shadow effect on the clueTip + dropShadowSteps: 6, // adjusts the size of the drop shadow + sticky: false, // keep visible until manually closed + mouseOutClose: false, // close when clueTip is moused out + activation: 'hover', // set to 'click' to force user to click to show clueTip + // set to 'focus' to show on focus of a form element and hide on blur + clickThrough: false, // if true, and activation is not 'click', then clicking on link will take user to the link's href, + // even if href and tipAttribute are equal + tracking: false, // if true, clueTip will track mouse movement (experimental) + delayedClose: 0, // close clueTip on a timed delay (experimental) + closePosition: 'top', // location of close text for sticky cluetips; can be 'top' or 'bottom' or 'title' + closeText: 'Close', // text (or HTML) to to be clicked to close sticky clueTips + truncate: 0, // number of characters to truncate clueTip's contents. if 0, no truncation occurs + + // effect and speed for opening clueTips + fx: { + open: 'show', // can be 'show' or 'slideDown' or 'fadeIn' + openSpeed: '' + }, + + // settings for when hoverIntent plugin is used + hoverIntent: { + sensitivity: 3, + interval: 50, + timeout: 0 + }, + + // short-circuit function to run just before clueTip is shown. + onActivate: function(e) {return true;}, + + // function to run just after clueTip is shown. + onShow: function(ct, ci){}, + // function to run just after clueTip is hidden. + onHide: function(ct, ci){}, + // whether to cache results of ajax request to avoid unnecessary hits to server + ajaxCache: true, + + // process data retrieved via xhr before it's displayed + ajaxProcess: function(data) { + data = data.replace(/<(script|style|title)[^<]+<\/(script|style|title)>/gm, '').replace(/<(link|meta)[^>]+>/g,''); + return data; + }, + + // can pass in standard $.ajax() parameters. Callback functions, such as beforeSend, + // will be queued first within the default callbacks. + // The only exception is error, which overrides the default + ajaxSettings: { + // error: function(ct, ci) { /* override default error callback */ } + // beforeSend: function(ct, ci) { /* called first within default beforeSend callback } + dataType: 'html' + }, + debug: false + }; + + +/* + * Global defaults for clueTips. Apply to all calls to the clueTip plugin. + * + * @example $.cluetip.setup({ + * insertionType: 'prependTo', + * insertionElement: '#container' + * }); + * + * @property + * @name $.cluetip.setup + * @type Map + * @cat Plugins/tooltip + * @option String insertionType: Default is 'appendTo'. Determines the method to be used for inserting the clueTip into the DOM. Permitted values are 'appendTo', 'prependTo', 'insertBefore', and 'insertAfter' + * @option String insertionElement: Default is 'body'. Determines which element in the DOM the plugin will reference when inserting the clueTip. + * + */ + + var insertionType = 'appendTo', insertionElement = 'body'; + + $.cluetip.setup = function(options) { + if (options && options.insertionType && (options.insertionType).match(/appendTo|prependTo|insertBefore|insertAfter/)) { + insertionType = options.insertionType; + } + if (options && options.insertionElement) { + insertionElement = options.insertionElement; + } + }; + +})(jQuery); diff --git a/share/pnp/media/js/jquery.imgareaselect.Debian.txt b/share/pnp/media/js/jquery.imgareaselect.Debian.txt new file mode 100644 index 0000000..5ecf191 --- /dev/null +++ b/share/pnp/media/js/jquery.imgareaselect.Debian.txt @@ -0,0 +1,14 @@ +/* + * imgAreaSelect jQuery plugin + * version 0.9.10 + * + * Copyright (c) 2008-2013 Michal Wojciechowski (odyniec.net) + * + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://odyniec.net/projects/imgareaselect/ + * + * Added to the DFSG tarball by + * Markus Frosch + */ diff --git a/share/pnp/media/js/jquery.imgareaselect.js b/share/pnp/media/js/jquery.imgareaselect.js new file mode 100644 index 0000000..7e1b790 --- /dev/null +++ b/share/pnp/media/js/jquery.imgareaselect.js @@ -0,0 +1,730 @@ +/* + * imgAreaSelect jQuery plugin + * version 0.9.10 + * + * Copyright (c) 2008-2013 Michal Wojciechowski (odyniec.net) + * + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://odyniec.net/projects/imgareaselect/ + * + */ + +(function($) { + +var abs = Math.abs, + max = Math.max, + min = Math.min, + round = Math.round; + +function div() { + return $('
    '); +} + +$.imgAreaSelect = function (img, options) { + var + + $img = $(img), + + imgLoaded, + + $box = div(), + $area = div(), + $border = div().add(div()).add(div()).add(div()), + $outer = div().add(div()).add(div()).add(div()), + $handles = $([]), + + $areaOpera, + + left, top, + + imgOfs = { left: 0, top: 0 }, + + imgWidth, imgHeight, + + $parent, + + parOfs = { left: 0, top: 0 }, + + zIndex = 0, + + position = 'absolute', + + startX, startY, + + scaleX, scaleY, + + resize, + + minWidth, minHeight, maxWidth, maxHeight, + + aspectRatio, + + shown, + + x1, y1, x2, y2, + + selection = { x1: 0, y1: 0, x2: 0, y2: 0, width: 0, height: 0 }, + + docElem = document.documentElement, + + ua = navigator.userAgent, + + $p, d, i, o, w, h, adjusted; + + function viewX(x) { + return x + imgOfs.left - parOfs.left; + } + + function viewY(y) { + return y + imgOfs.top - parOfs.top; + } + + function selX(x) { + return x - imgOfs.left + parOfs.left; + } + + function selY(y) { + return y - imgOfs.top + parOfs.top; + } + + function evX(event) { + return event.pageX - parOfs.left; + } + + function evY(event) { + return event.pageY - parOfs.top; + } + + function getSelection(noScale) { + var sx = noScale || scaleX, sy = noScale || scaleY; + + return { x1: round(selection.x1 * sx), + y1: round(selection.y1 * sy), + x2: round(selection.x2 * sx), + y2: round(selection.y2 * sy), + width: round(selection.x2 * sx) - round(selection.x1 * sx), + height: round(selection.y2 * sy) - round(selection.y1 * sy) }; + } + + function setSelection(x1, y1, x2, y2, noScale) { + var sx = noScale || scaleX, sy = noScale || scaleY; + + selection = { + x1: round(x1 / sx || 0), + y1: round(y1 / sy || 0), + x2: round(x2 / sx || 0), + y2: round(y2 / sy || 0) + }; + + selection.width = selection.x2 - selection.x1; + selection.height = selection.y2 - selection.y1; + } + + function adjust() { + if (!imgLoaded || !$img.width()) + return; + + imgOfs = { left: round($img.offset().left), top: round($img.offset().top) }; + + imgWidth = $img.innerWidth(); + imgHeight = $img.innerHeight(); + + imgOfs.top += ($img.outerHeight() - imgHeight) >> 1; + imgOfs.left += ($img.outerWidth() - imgWidth) >> 1; + + minWidth = round(options.minWidth / scaleX) || 0; + minHeight = round(options.minHeight / scaleY) || 0; + maxWidth = round(min(options.maxWidth / scaleX || 1<<24, imgWidth)); + maxHeight = round(min(options.maxHeight / scaleY || 1<<24, imgHeight)); + + if ($().jquery == '1.3.2' && position == 'fixed' && + !docElem['getBoundingClientRect']) + { + imgOfs.top += max(document.body.scrollTop, docElem.scrollTop); + imgOfs.left += max(document.body.scrollLeft, docElem.scrollLeft); + } + + parOfs = /absolute|relative/.test($parent.css('position')) ? + { left: round($parent.offset().left) - $parent.scrollLeft(), + top: round($parent.offset().top) - $parent.scrollTop() } : + position == 'fixed' ? + { left: $(document).scrollLeft(), top: $(document).scrollTop() } : + { left: 0, top: 0 }; + + left = viewX(0); + top = viewY(0); + + if (selection.x2 > imgWidth || selection.y2 > imgHeight) + doResize(); + } + + function update(resetKeyPress) { + if (!shown) return; + + $box.css({ left: viewX(selection.x1), top: viewY(selection.y1) }) + .add($area).width(w = selection.width).height(h = selection.height); + + $area.add($border).add($handles).css({ left: 0, top: 0 }); + + $border + .width(max(w - $border.outerWidth() + $border.innerWidth(), 0)) + .height(max(h - $border.outerHeight() + $border.innerHeight(), 0)); + + $($outer[0]).css({ left: left, top: top, + width: selection.x1, height: imgHeight }); + $($outer[1]).css({ left: left + selection.x1, top: top, + width: w, height: selection.y1 }); + $($outer[2]).css({ left: left + selection.x2, top: top, + width: imgWidth - selection.x2, height: imgHeight }); + $($outer[3]).css({ left: left + selection.x1, top: top + selection.y2, + width: w, height: imgHeight - selection.y2 }); + + w -= $handles.outerWidth(); + h -= $handles.outerHeight(); + + switch ($handles.length) { + case 8: + $($handles[4]).css({ left: w >> 1 }); + $($handles[5]).css({ left: w, top: h >> 1 }); + $($handles[6]).css({ left: w >> 1, top: h }); + $($handles[7]).css({ top: h >> 1 }); + case 4: + $handles.slice(1,3).css({ left: w }); + $handles.slice(2,4).css({ top: h }); + } + + if (resetKeyPress !== false) { + if ($.imgAreaSelect.onKeyPress != docKeyPress) + $(document).unbind($.imgAreaSelect.keyPress, + $.imgAreaSelect.onKeyPress); + + if (options.keys) + $(document)[$.imgAreaSelect.keyPress]( + $.imgAreaSelect.onKeyPress = docKeyPress); + } + + if (msie && $border.outerWidth() - $border.innerWidth() == 2) { + $border.css('margin', 0); + setTimeout(function () { $border.css('margin', 'auto'); }, 0); + } + } + + function doUpdate(resetKeyPress) { + adjust(); + update(resetKeyPress); + x1 = viewX(selection.x1); y1 = viewY(selection.y1); + x2 = viewX(selection.x2); y2 = viewY(selection.y2); + } + + function hide($elem, fn) { + options.fadeSpeed ? $elem.fadeOut(options.fadeSpeed, fn) : $elem.hide(); + + } + + function areaMouseMove(event) { + var x = selX(evX(event)) - selection.x1, + y = selY(evY(event)) - selection.y1; + + if (!adjusted) { + adjust(); + adjusted = true; + + $box.one('mouseout', function () { adjusted = false; }); + } + + resize = ''; + + if (options.resizable) { + if (y <= options.resizeMargin) + resize = 'n'; + else if (y >= selection.height - options.resizeMargin) + resize = 's'; + if (x <= options.resizeMargin) + resize += 'w'; + else if (x >= selection.width - options.resizeMargin) + resize += 'e'; + } + + $box.css('cursor', resize ? resize + '-resize' : + options.movable ? 'move' : ''); + if ($areaOpera) + $areaOpera.toggle(); + } + + function docMouseUp(event) { + $('body').css('cursor', ''); + if (options.autoHide || selection.width * selection.height == 0) + hide($box.add($outer), function () { $(this).hide(); }); + + $(document).unbind('mousemove', selectingMouseMove); + $box.mousemove(areaMouseMove); + + options.onSelectEnd(img, getSelection()); + } + + function areaMouseDown(event) { + if (event.which != 1) return false; + + adjust(); + + if (resize) { + $('body').css('cursor', resize + '-resize'); + + x1 = viewX(selection[/w/.test(resize) ? 'x2' : 'x1']); + y1 = viewY(selection[/n/.test(resize) ? 'y2' : 'y1']); + + $(document).mousemove(selectingMouseMove) + .one('mouseup', docMouseUp); + $box.unbind('mousemove', areaMouseMove); + } + else if (options.movable) { + startX = left + selection.x1 - evX(event); + startY = top + selection.y1 - evY(event); + + $box.unbind('mousemove', areaMouseMove); + + $(document).mousemove(movingMouseMove) + .one('mouseup', function () { + options.onSelectEnd(img, getSelection()); + + $(document).unbind('mousemove', movingMouseMove); + $box.mousemove(areaMouseMove); + }); + } + else + $img.mousedown(event); + + return false; + } + + function fixAspectRatio(xFirst) { + if (aspectRatio) + if (xFirst) { + x2 = max(left, min(left + imgWidth, + x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1))); + + y2 = round(max(top, min(top + imgHeight, + y1 + abs(x2 - x1) / aspectRatio * (y2 > y1 || -1)))); + x2 = round(x2); + } + else { + y2 = max(top, min(top + imgHeight, + y1 + abs(x2 - x1) / aspectRatio * (y2 > y1 || -1))); + x2 = round(max(left, min(left + imgWidth, + x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1)))); + y2 = round(y2); + } + } + + function doResize() { + x1 = min(x1, left + imgWidth); + y1 = min(y1, top + imgHeight); + + if (abs(x2 - x1) < minWidth) { + x2 = x1 - minWidth * (x2 < x1 || -1); + + if (x2 < left) + x1 = left + minWidth; + else if (x2 > left + imgWidth) + x1 = left + imgWidth - minWidth; + } + + if (abs(y2 - y1) < minHeight) { + y2 = y1 - minHeight * (y2 < y1 || -1); + + if (y2 < top) + y1 = top + minHeight; + else if (y2 > top + imgHeight) + y1 = top + imgHeight - minHeight; + } + + x2 = max(left, min(x2, left + imgWidth)); + y2 = max(top, min(y2, top + imgHeight)); + + fixAspectRatio(abs(x2 - x1) < abs(y2 - y1) * aspectRatio); + + if (abs(x2 - x1) > maxWidth) { + x2 = x1 - maxWidth * (x2 < x1 || -1); + fixAspectRatio(); + } + + if (abs(y2 - y1) > maxHeight) { + y2 = y1 - maxHeight * (y2 < y1 || -1); + fixAspectRatio(true); + } + + selection = { x1: selX(min(x1, x2)), x2: selX(max(x1, x2)), + y1: selY(min(y1, y2)), y2: selY(max(y1, y2)), + width: abs(x2 - x1), height: abs(y2 - y1) }; + + update(); + + options.onSelectChange(img, getSelection()); + } + + function selectingMouseMove(event) { + x2 = /w|e|^$/.test(resize) || aspectRatio ? evX(event) : viewX(selection.x2); + y2 = /n|s|^$/.test(resize) || aspectRatio ? evY(event) : viewY(selection.y2); + + doResize(); + + return false; + + } + + function doMove(newX1, newY1) { + x2 = (x1 = newX1) + selection.width; + y2 = (y1 = newY1) + selection.height; + + $.extend(selection, { x1: selX(x1), y1: selY(y1), x2: selX(x2), + y2: selY(y2) }); + + update(); + + options.onSelectChange(img, getSelection()); + } + + function movingMouseMove(event) { + x1 = max(left, min(startX + evX(event), left + imgWidth - selection.width)); + y1 = max(top, min(startY + evY(event), top + imgHeight - selection.height)); + + doMove(x1, y1); + + event.preventDefault(); + + return false; + } + + function startSelection() { + $(document).unbind('mousemove', startSelection); + adjust(); + + x2 = x1; + y2 = y1; + + doResize(); + + resize = ''; + + if (!$outer.is(':visible')) + $box.add($outer).hide().fadeIn(options.fadeSpeed||0); + + shown = true; + + $(document).unbind('mouseup', cancelSelection) + .mousemove(selectingMouseMove).one('mouseup', docMouseUp); + $box.unbind('mousemove', areaMouseMove); + + options.onSelectStart(img, getSelection()); + } + + function cancelSelection() { + $(document).unbind('mousemove', startSelection) + .unbind('mouseup', cancelSelection); + hide($box.add($outer)); + + setSelection(selX(x1), selY(y1), selX(x1), selY(y1)); + + if (!(this instanceof $.imgAreaSelect)) { + options.onSelectChange(img, getSelection()); + options.onSelectEnd(img, getSelection()); + } + } + + function imgMouseDown(event) { + if (event.which != 1 || $outer.is(':animated')) return false; + + adjust(); + startX = x1 = evX(event); + startY = y1 = evY(event); + + $(document).mousemove(startSelection).mouseup(cancelSelection); + + return false; + } + + function windowResize() { + doUpdate(false); + } + + function imgLoad() { + imgLoaded = true; + + setOptions(options = $.extend({ + classPrefix: 'imgareaselect', + movable: true, + parent: 'body', + resizable: true, + resizeMargin: 10, + onInit: function () {}, + onSelectStart: function () {}, + onSelectChange: function () {}, + onSelectEnd: function () {} + }, options)); + + $box.add($outer).css({ visibility: '' }); + + if (options.show) { + shown = true; + adjust(); + update(); + $box.add($outer).hide().fadeIn(options.fadeSpeed||0); + } + + setTimeout(function () { options.onInit(img, getSelection()); }, 0); + } + + var docKeyPress = function(event) { + var k = options.keys, d, t, key = event.keyCode; + + d = !isNaN(k.alt) && (event.altKey || event.originalEvent.altKey) ? k.alt : + !isNaN(k.ctrl) && event.ctrlKey ? k.ctrl : + !isNaN(k.shift) && event.shiftKey ? k.shift : + !isNaN(k.arrows) ? k.arrows : 10; + + if (k.arrows == 'resize' || (k.shift == 'resize' && event.shiftKey) || + (k.ctrl == 'resize' && event.ctrlKey) || + (k.alt == 'resize' && (event.altKey || event.originalEvent.altKey))) + { + switch (key) { + case 37: + d = -d; + case 39: + t = max(x1, x2); + x1 = min(x1, x2); + x2 = max(t + d, x1); + fixAspectRatio(); + break; + case 38: + d = -d; + case 40: + t = max(y1, y2); + y1 = min(y1, y2); + y2 = max(t + d, y1); + fixAspectRatio(true); + break; + default: + return; + } + + doResize(); + } + else { + x1 = min(x1, x2); + y1 = min(y1, y2); + + switch (key) { + case 37: + doMove(max(x1 - d, left), y1); + break; + case 38: + doMove(x1, max(y1 - d, top)); + break; + case 39: + doMove(x1 + min(d, imgWidth - selX(x2)), y1); + break; + case 40: + doMove(x1, y1 + min(d, imgHeight - selY(y2))); + break; + default: + return; + } + } + + return false; + }; + + function styleOptions($elem, props) { + for (var option in props) + if (options[option] !== undefined) + $elem.css(props[option], options[option]); + } + + function setOptions(newOptions) { + if (newOptions.parent) + ($parent = $(newOptions.parent)).append($box.add($outer)); + + $.extend(options, newOptions); + + adjust(); + + if (newOptions.handles != null) { + $handles.remove(); + $handles = $([]); + + i = newOptions.handles ? newOptions.handles == 'corners' ? 4 : 8 : 0; + + while (i--) + $handles = $handles.add(div()); + + $handles.addClass(options.classPrefix + '-handle').css({ + position: 'absolute', + fontSize: 0, + zIndex: zIndex + 1 || 1 + }); + + if (!parseInt($handles.css('width')) >= 0) + $handles.width(5).height(5); + + if (o = options.borderWidth) + $handles.css({ borderWidth: o, borderStyle: 'solid' }); + + styleOptions($handles, { borderColor1: 'border-color', + borderColor2: 'background-color', + borderOpacity: 'opacity' }); + } + + scaleX = options.imageWidth / imgWidth || 1; + scaleY = options.imageHeight / imgHeight || 1; + + if (newOptions.x1 != null) { + setSelection(newOptions.x1, newOptions.y1, newOptions.x2, + newOptions.y2); + newOptions.show = !newOptions.hide; + } + + if (newOptions.keys) + options.keys = $.extend({ shift: 1, ctrl: 'resize' }, + newOptions.keys); + + $outer.addClass(options.classPrefix + '-outer'); + $area.addClass(options.classPrefix + '-selection'); + for (i = 0; i++ < 4;) + $($border[i-1]).addClass(options.classPrefix + '-border' + i); + + styleOptions($area, { selectionColor: 'background-color', + selectionOpacity: 'opacity' }); + styleOptions($border, { borderOpacity: 'opacity', + borderWidth: 'border-width' }); + styleOptions($outer, { outerColor: 'background-color', + outerOpacity: 'opacity' }); + if (o = options.borderColor1) + $($border[0]).css({ borderStyle: 'solid', borderColor: o }); + if (o = options.borderColor2) + $($border[1]).css({ borderStyle: 'dashed', borderColor: o }); + + $box.append($area.add($border).add($areaOpera)).append($handles); + + if (msie) { + if (o = ($outer.css('filter')||'').match(/opacity=(\d+)/)) + $outer.css('opacity', o[1]/100); + if (o = ($border.css('filter')||'').match(/opacity=(\d+)/)) + $border.css('opacity', o[1]/100); + } + + if (newOptions.hide) + hide($box.add($outer)); + else if (newOptions.show && imgLoaded) { + shown = true; + $box.add($outer).fadeIn(options.fadeSpeed||0); + doUpdate(); + } + + aspectRatio = (d = (options.aspectRatio || '').split(/:/))[0] / d[1]; + + $img.add($outer).unbind('mousedown', imgMouseDown); + + if (options.disable || options.enable === false) { + $box.unbind('mousemove', areaMouseMove).unbind('mousedown', areaMouseDown); + $(window).unbind('resize', windowResize); + } + else { + if (options.enable || options.disable === false) { + if (options.resizable || options.movable) + $box.mousemove(areaMouseMove).mousedown(areaMouseDown); + + $(window).resize(windowResize); + } + + if (!options.persistent) + $img.add($outer).mousedown(imgMouseDown); + } + + options.enable = options.disable = undefined; + } + + this.remove = function () { + setOptions({ disable: true }); + $box.add($outer).remove(); + }; + + this.getOptions = function () { return options; }; + + this.setOptions = setOptions; + + this.getSelection = getSelection; + + this.setSelection = setSelection; + + this.cancelSelection = cancelSelection; + + this.update = doUpdate; + + var msie = (/msie ([\w.]+)/i.exec(ua)||[])[1], + opera = /opera/i.test(ua), + safari = /webkit/i.test(ua) && !/chrome/i.test(ua); + + $p = $img; + + while ($p.length) { + zIndex = max(zIndex, + !isNaN($p.css('z-index')) ? $p.css('z-index') : zIndex); + if ($p.css('position') == 'fixed') + position = 'fixed'; + + $p = $p.parent(':not(body)'); + } + + zIndex = options.zIndex || zIndex; + + if (msie) + $img.attr('unselectable', 'on'); + + $.imgAreaSelect.keyPress = msie || safari ? 'keydown' : 'keypress'; + + if (opera) + + $areaOpera = div().css({ width: '100%', height: '100%', + position: 'absolute', zIndex: zIndex + 2 || 2 }); + + $box.add($outer).css({ visibility: 'hidden', position: position, + overflow: 'hidden', zIndex: zIndex || '0' }); + $box.css({ zIndex: zIndex + 2 || 2 }); + $area.add($border).css({ position: 'absolute', fontSize: 0 }); + + img.complete || img.readyState == 'complete' || !$img.is('img') ? + imgLoad() : $img.one('load', imgLoad); + + if (!imgLoaded && msie && msie >= 7) + img.src = img.src; +}; + +$.fn.imgAreaSelect = function (options) { + options = options || {}; + + this.each(function () { + if ($(this).data('imgAreaSelect')) { + if (options.remove) { + $(this).data('imgAreaSelect').remove(); + $(this).removeData('imgAreaSelect'); + } + else + $(this).data('imgAreaSelect').setOptions(options); + } + else if (!options.remove) { + if (options.enable === undefined && options.disable === undefined) + options.enable = true; + + $(this).data('imgAreaSelect', new $.imgAreaSelect(this, options)); + } + }); + + if (options.instance) + return $(this).data('imgAreaSelect'); + + return this; +}; + +})(jQuery); diff --git a/share/pnp/templates.dist/check-host-alive.php b/share/pnp/templates.dist/check-host-alive.php new file mode 120000 index 0000000..cdbf865 --- /dev/null +++ b/share/pnp/templates.dist/check-host-alive.php @@ -0,0 +1 @@ +check_ping.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_apachestatus.php b/share/pnp/templates.dist/check_apachestatus.php new file mode 100644 index 0000000..2bfb57d --- /dev/null +++ b/share/pnp/templates.dist/check_apachestatus.php @@ -0,0 +1,117 @@ + +# pnp version >= 0.6.5 +# +# +# from apache's scoreboard.h +# #define SERVER_DEAD 0 +# #define SERVER_STARTING 1 /* Server Starting up */ +# #define SERVER_READY 2 /* Waiting for connection (or accept() lock) */ +# #define SERVER_BUSY_READ 3 /* Reading a client request */ +# #define SERVER_BUSY_WRITE 4 /* Processing a client request */ +# #define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */ +# #define SERVER_BUSY_LOG 6 /* Logging the request */ +# #define SERVER_BUSY_DNS 7 /* Looking up a hostname */ +# #define SERVER_CLOSING 8 /* Closing the connection */ +# #define SERVER_GRACEFUL 9 /* server is gracefully finishing request */ +# #define SERVER_IDLE_KILL 10 /* Server is cleaning up idle children. */ +# #define SERVER_NUM_STATUS 11 /* number of status settings */ + +# perfdata example: +# Performance Data: 'Waiting for Connection'=90 'Starting Up'=0 'Reading Request'=10 'Sending Reply'=196 'Keepalive (read)'=360 'DNS Lookup'=0 'Closing Connection'=77 'Logging'=0 'Gracefully finishing'=0 'Idle cleanup'=0 'Open slot'=547 'Requests/sec'=119.0 'kB per sec'=8294.4KB 'kB per Request'=69.9KB +# + + +# first graph - workers that do smth, not just idling.. +$ds_name[1]="Working slots"; +$opt[1] = " --vertical-label \"Workers\" --title \"Apache Workers: working on $hostname / $servicedesc\" "; +$opt[1] .= " --slope-mode "; +$def[1] = rrd::def("var2",$RRDFILE[2],$DS[2],"AVERAGE"); #starting +$def[1] .= rrd::cdef("negstarting","var2,-1,*"); #starting +$def[1] .= rrd::def("var3",$RRDFILE[3],$DS[3],"AVERAGE"); #reading +$def[1] .= rrd::cdef("negreading","var3,-1,*"); #reading +$def[1] .= rrd::def("var4",$RRDFILE[4],$DS[4],"AVERAGE"); #reply +$def[1] .= rrd::def("var6",$RRDFILE[6],$DS[6],"AVERAGE"); #DNS LOOKUP +$def[1] .= rrd::cdef("negdns","var6,-1,*"); #DNS LOOKUP +$def[1] .= rrd::def("var7",$RRDFILE[7],$DS[7],"AVERAGE"); #closing +$def[1] .= rrd::cdef("negclosing","var7,-1,*"); #closing +$def[1] .= rrd::def("var8",$RRDFILE[8],$DS[8],"AVERAGE"); #logging +$def[1] .= rrd::cdef("neglogging","var8,-1,*"); #logging +$def[1] .= rrd::area("negclosing","#b7ff9e","closing",true ); #closing +$def[1] .= rrd::line1("negclosing","#2eae00"); +$def[1] .= rrd::gprint("var7",array("LAST","MAX","AVERAGE"),"%7.0lf") ; +$def[1] .= rrd::area("negstarting","#993300","starting"); #startung +$def[1] .= rrd::gprint("var2",array("LAST","MAX","AVERAGE"),"%7.0lf"); +$def[1] .= rrd::area("negreading","#001919","reading",true); #reading +$def[1] .= rrd::gprint("var3",array("LAST","MAX","AVERAGE"),"%7.0lf") ; +$def[1] .= rrd::area("negdns","#009900","DNS lookup",true); #dns lookup +$def[1] .= rrd::gprint("var6",array("LAST","MAX","AVERAGE"),"%7.0lf") ; +$def[1] .= rrd::area("neglogging","#ff0000","logging",true); #logging +$def[1] .= rrd::gprint("var8",array("LAST","MAX","AVERAGE"),"%7.0lf") ; +$def[1] .= rrd::area("var4","#6fb7ff","replying"); #replying +$def[1] .= rrd::line1("var4","#0019ff",FALSE,FALSE); +$def[1] .= rrd::gprint("var4",array("LAST","MAX","AVERAGE"),"%7.0lf") ; + + +# second graph - idling workers +#some idle actions like graceful shutdown, open slots & such +$ds_name[2]="Idling slots"; +$opt[2] = " --vertical-label \"Workers\" --title \"Apache Workers: idling on $hostname / $servicedesc\" "; +$opt[2] .= " --slope-mode "; +$def[2] = rrd::def("var2",$RRDFILE[5],$DS[5],"AVERAGE"); #keepalive (read) +$def[2] .= rrd::def("var3",$RRDFILE[1],$DS[1],"AVERAGE"); #waiting +$def[2] .= rrd::def("var4",$RRDFILE[10],$DS[10],"AVERAGE"); #idle cleanup +$def[2] .= rrd::def("var5",$RRDFILE[9],$DS[9],"AVERAGE"); #gracefully finishing +$def[2] .= rrd::area("var3","#ffe4c4","waiting for conn"); +$def[2] .= rrd::line1("var3","#eb891d"); +$def[2] .= rrd::gprint("var3",array("LAST","MAX","AVERAGE"),"%7.0lf") ;#TODO - add border lines like for finishing +$def[2] .= rrd::area("var2","#503020","keepalive",true); #TODO - add border lines like for finishing +$def[2] .= rrd::gprint("var2",array("LAST","MAX","AVERAGE"),"%7.0lf") ; +$def[2] .= rrd::area("var4","#66cdaa","idle cleanup",true); +$def[2] .= rrd::gprint("var4",array("LAST","MAX","AVERAGE"),"%7.0lf") ; +$def[2] .= rrd::area("var5","#6fb7ff","gracefully finishing",true); +$def[2] .= rrd::cdef("grline","var2,var3,var4,var5,+,+,+"); #line shouldn't be stacked over +$def[2] .= rrd::line1("grline","#0019ff",FALSE,FALSE); +$def[2] .= rrd::gprint("var5",array("LAST","MAX","AVERAGE"),"%7.0lf") ; + +#third graph - open slots count +$ds_name[3]="Open slots"; +$opt[3] = " --vertical-label \"Workers\" --title \"Apache open slots on $hostname / $servicedesc\" "; +$opt[3] .= " --slope-mode "; +$def[3] = rrd::def("var1",$RRDFILE[11],$DS[11],"AVERAGE"); +$def[3] .= rrd::area("var1","#e0e0e0","open slots" ); +$def[3] .= rrd::line1("var1","#858585"); +$def[3] .= rrd::gprint("var1",array("LAST","MAX","AVERAGE"),"%7.0lf") ; + + +#fourth graph - server's traffic total and per request +$ds_name[4]="Apache Traffic"; +$opt[4] = " --vertical-label \"Traffic\" -b 1024 --title \"Apache Traffic for $hostname / $servicedesc\" "; +$opt[4] .= " --slope-mode "; +$def[4] = rrd::def("var1",$RRDFILE[13],$DS[13],"AVERAGE"); +$def[4] .= rrd::cdef("trbytes","var1,1024,*"); +$def[4] .= rrd::def("var2",$RRDFILE[14],$DS[14],"AVERAGE"); +$def[4] .= rrd::cdef("negperreq","var2,-1,*"); +$def[4] .= "VDEF:totalbytes=trbytes,TOTAL "; +$def[4] .= rrd::area("trbytes","#b0c0fb","throughput"); +$def[4] .= rrd::line1("trbytes","#3c63ff"); +$def[4] .= rrd::gprint("trbytes",array("LAST","MAX","AVERAGE"),"%7.2lf %sB/sec") ; +$def[4] .= rrd::line2("negperreq","#00ff00","kB/request"); +$def[4] .= rrd::gprint("var2",array("LAST","MAX","AVERAGE"),"%7.2lf %s$UNIT[14]") ; +$def[4] .= "GPRINT:totalbytes:\"%3.0lf %sB total\\n\" "; + +#fifth graph - requests per sec ( rate is calculated by apache, time smoothed, very averaged, shouldn't be believed) +$ds_name[5]="Apache requests"; +$opt[5] = " --vertical-label \"Request/sec\" --title \"Apache request/sec for $hostname / $servicedesc\" "; +$opt[5] .= " --slope-mode "; +$def[5] = rrd::def("var1",$RRDFILE[12],$DS[12],"AVERAGE"); +$def[5] .= rrd::area("var1","#b7ff9e","Requests / sec"); +$def[5] .= rrd::line1("var1","#2eae00"); +$def[5] .= rrd::gprint("var1",array("LAST","MAX","AVERAGE"),"%7.2lf %s") ; + +?> diff --git a/share/pnp/templates.dist/check_apachestatus_auto.php b/share/pnp/templates.dist/check_apachestatus_auto.php new file mode 100644 index 0000000..d9a4c2f --- /dev/null +++ b/share/pnp/templates.dist/check_apachestatus_auto.php @@ -0,0 +1,101 @@ +DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::area ("var".$KEY, $color ,rrd::cut($VAL['NAME'],12), 'STACK' ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.0lf"); + } +} +$regex = '/Busy/'; +$color = '#ff0000'; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::area ("var".$KEY, $color, rrd::cut($VAL['NAME'],12), 'STACK' ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.0lf"); + } +} +# +# Slots +# +$i++; +$def[$i] = ""; +$opt[$i] = " --title 'Slots'"; +$ds_name[$i] = "Slots"; +$regex = '/^Slots$/'; +$color = '#ff0000'; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::area ("var".$KEY, $color,rrd::cut($VAL['NAME'],12) ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.0lf"); + } +} +$regex = '/^OpenSlots$/'; +$color = '#00ff00'; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::area ("var".$KEY, $color,rrd::cut($VAL['NAME'],12) ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.0lf"); + } +} +# +# Requests per Second +# +$i++; +$def[$i] = ""; +$opt[$i] = " --title Requests/s"; +$ds_name[$i] = "Requests/s"; +$regex = '/ReqPerSec/'; +$color = '#000000'; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::line1 ("var".$KEY, $color, rrd::cut($VAL['NAME'],16), 'STACK' ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.1lf/s"); + } +} +# +# Bytes per Second +# +$i++; +$def[$i] = ""; +$opt[$i] = " --title 'Bytes per Second'"; +$ds_name[$i] = "Bytes/s"; +$regex='/BytesPerSec/'; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::line1 ("var".$KEY, rrd::color($KEY),rrd::cut($VAL['NAME'],16), 'STACK' ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.1lf %sb/s"); + } +} +# +# Stats +# +$i++; +$def[$i] = ""; +$opt[$i] = " --title 'Worker States'"; +$ds_name[$i] = "Worker States"; +$regex='/Starting|DNS|Reading|Sending|Keepalive|Closing|Logging|Finishing/'; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match($regex, $VAL['NAME'])) { + $def[$i] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$i] .= rrd::line1 ("var".$KEY, rrd::color($KEY),rrd::cut($VAL['NAME'],16), 'STACK' ); + $def[$i] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%6.0lf".$VAL['UNIT']); + } +} +?> diff --git a/share/pnp/templates.dist/check_dell_bladechassis.php b/share/pnp/templates.dist/check_dell_bladechassis.php new file mode 100644 index 0000000..42028f6 --- /dev/null +++ b/share/pnp/templates.dist/check_dell_bladechassis.php @@ -0,0 +1,140 @@ + diff --git a/share/pnp/templates.dist/check_disk.php b/share/pnp/templates.dist/check_disk.php new file mode 100644 index 0000000..e7c26ce --- /dev/null +++ b/share/pnp/templates.dist/check_disk.php @@ -0,0 +1,64 @@ +DS as $KEY=>$VAL) { +# set initial values + $fmt = '%7.3lf'; + $pct = ''; + $upper = ""; + $maximum = ""; + $divis = 1; + $return = '\n'; + $unit = "B"; + $label = $unit; + if ($VAL['UNIT'] != "") { + $unit = $VAL['UNIT']; + $label = $unit; + if ($VAL['UNIT'] == "%%") { + $label = '%'; + $fmt = '%5.1lf'; + $pct = '%'; + } + } + if ($VAL['MAX'] != "") { + # adjust value and unit, details in .../helpers/pnp.php + $max = pnp::adjust_unit( $VAL['MAX'].$unit,1024,$fmt ); + $upper = "-u $max[1] "; + $maximum = "of $max[1] $max[2]$pct used"; + $label = $max[2]; + $divis = $max[3]; + $return = ''; + } + $ds_name[$KEY] = str_replace("_","/",$VAL['NAME']); + # set graph labels + $opt[$KEY] = "--vertical-label $label -l 0 $upper --title \"Filesystem $ds_name[$KEY]\" "; + # Graph Definitions + $def[$KEY] = rrd::def( "var1", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE" ); + # "normalize" graph values + $def[$KEY] .= rrd::cdef( "v_n","var1,$divis,/"); + $def[$KEY] .= rrd::area( "v_n", "#c6c6c6", $ds_name[$KEY] ); + $def[$KEY] .= rrd::line1( "v_n", "#003300" ); + # show values in legend + $def[$KEY] .= rrd::gprint( "v_n", "LAST", "$fmt $label$pct $maximum "); + $def[$KEY] .= rrd::gprint( "v_n", "AVERAGE", "$fmt $label$pct avg used $return"); + # create max line and legend + if ($VAL['MAX'] != "") { + $def[$KEY] .= rrd::gprint( "v_n", "MAX", "$fmt $label$pct max used \\n" ); + $def[$KEY] .= rrd::hrule( $max[1], "#003300", "Size of FS $max[0] \\n"); + } + # create warning line and legend + if ($VAL['WARN'] != "") { + $warn = pnp::adjust_unit( $VAL['WARN'].$unit,1024,$fmt ); + $def[$KEY] .= rrd::hrule( $warn[1], "#ffff00", "Warning on $warn[0] \\n" ); + } + # create critical line and legend + if ($VAL['CRIT'] != "") { + $crit = pnp::adjust_unit( $VAL['CRIT'].$unit,1024,$fmt ); + $def[$KEY] .= rrd::hrule( $crit[1], "#ff0000", "Critical on $crit[0]\\n" ); + } +} +?> diff --git a/share/pnp/templates.dist/check_dns.php b/share/pnp/templates.dist/check_dns.php new file mode 100644 index 0000000..b8ab048 --- /dev/null +++ b/share/pnp/templates.dist/check_dns.php @@ -0,0 +1,24 @@ + diff --git a/share/pnp/templates.dist/check_esx3.php b/share/pnp/templates.dist/check_esx3.php new file mode 100644 index 0000000..4154e4c --- /dev/null +++ b/share/pnp/templates.dist/check_esx3.php @@ -0,0 +1,105 @@ + +Contributor(s): Joerg Linge + +For direct contact with any of the op5 developers send a mail to dev@op5.com +Discussions are directed to the mailing list op5-users@op5.com, +see http://lists.op5.com/mailman/listinfo/op5-users + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Requires: + pnp4nagios 0.4.14+ + enable_recursive_template_search enabled in configfile + check_esx3.pl from http://git.op5.org/git/?p=nagios/op5plugins.git;a=summary +*/ + +$color_list = array( + 1 => "#ff77ee", // Purple + 2 => "#fed409", // Yellow + 3 => "#007dd0", // Blue + 4 => "#ee0a04", // Red + 5 => "#56a901", // Green + 6 => "#ff6600", // Orange + 7 => "#a4a4a4", // Grey + 8 => "#336633" // darker green + ); + +$opt[1] = ''; +$def[1] = ''; +$filled = 0; +$base = "1024"; +$cdef = ""; +$vlabel = ""; + +// Specific settings based on first DataSource, if we want to customize it. +switch ($NAME[1]) { + case "cpu_usage": + $vlabel = "Percent"; + $opt[1] .= "--lower-limit=0 --upper-limit=105 "; + break; + case "mem_usage": + $vlabel = "Percent"; + $opt[1] .= "--lower-limit=0 --upper-limit=105 "; + break; + case "net_receive": + $vlabel = "Kb/sec"; + break; + case "cpu_usagemhz": + $vlabel = "CPU Usage"; + $filled = 1; + break; + default: + break; +} + +$opt[1] .= " --imgformat=PNG --title=\" $hostname / $servicedesc\" --base=$base --vertical-label=\"$vlabel\" --slope-mode "; +$opt[1] .= "--watermark=\"http://www.op5.com template: $TEMPLATE[1]\" "; +$opt[1] .= "--units-exponent=0 "; + +for ($i = 1; $i <= count($DS); $i++) { + $def[1] .= "DEF:ds$i=$RRDFILE[$i]:$DS[$i]:AVERAGE " ; + $def[1] .= "CDEF:var$i=ds$i "; + + if (isset($color)) { + $color_list = $color; + } + + /* If we have few datasources we fill the area below with a semitransparent version of basecolor + This makes the graph look more "modern" */ + if ($filled || count($DS) <= 3) { + $def[1] .= "AREA:var$i". $color_list[$i] . "32 "; + } + $def[1] .= "LINE1:var$i" . $color_list[$i] . "FF:\"$NAME[$i]\t\" "; + $def[1] .= "GPRINT:var$i:LAST:\"Cur\\:%8.2lf $UNIT[$i]\" "; + $def[1] .= "GPRINT:var$i:AVERAGE:\"Avg\\:%8.2lf $UNIT[$i]\" "; + $def[1] .= "GPRINT:var$i:MAX:\"Max\\:%8.2lf $UNIT[$i]\\n\" "; +} + +for ($i = 1; $i <= count($DS); $i++) { + if ($UNIT[$i] == "%%") { + $UNIT[$i] = "%"; + } + + if (isset($WARN[$i]) && $WARN[$i] != "") { + $def[1] .= "HRULE:$WARN[$i]#FFFF00:\"Warning ($NAME[$i])\: " . $WARN[$i] . " " . $UNIT[$i] . " \\n\" " ; + } + + if (isset($CRIT[$i]) && $CRIT[$i] != "") { + $def[1] .= "HRULE:$CRIT[$i]#FF0000:\"Critical ($NAME[$i])\: " . $CRIT[$i] . " " . $UNIT[$i] . " \\n\" " ; + } +} +?> diff --git a/share/pnp/templates.dist/check_fping.php b/share/pnp/templates.dist/check_fping.php new file mode 100644 index 0000000..ae61063 --- /dev/null +++ b/share/pnp/templates.dist/check_fping.php @@ -0,0 +1,65 @@ + + diff --git a/share/pnp/templates.dist/check_gearman.php b/share/pnp/templates.dist/check_gearman.php new file mode 100644 index 0000000..3c84349 --- /dev/null +++ b/share/pnp/templates.dist/check_gearman.php @@ -0,0 +1,36 @@ +DS as $KEY=>$VAL) { + if(preg_match('/(.*)_([^_].*)$/',$VAL['LABEL'],$matches)){ + $queue = $matches[1]; + $state = $matches[2]; + if($state == "waiting"){ + $i++; + $opt[$i]=''; + $def[$i]=''; + } + $opt[$i] = "-l0 --title \"Gearman Queue '$queue'\" "; + # + $ds_name[$i] = "$queue"; + $def[$i] .= rrd::def("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[$i] .= rrd::line1("var$KEY", $color[$state], rrd::cut($state,16)); + $def[$i] .= rrd::gprint("var$KEY", array('LAST', 'MAX', 'AVERAGE'), "%6.2lf".$VAL['UNIT']) ; + }else{ + $i++; + $opt[$i] = "-l0 --title \"Gearman Statistics\" "; + # + $ds_name[$i] = $VAL['NAME']; + $def[$i] = rrd::def("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[$i] .= rrd::line1("var$KEY", '#00C600', rrd::cut($VAL['NAME'],16)); + $def[$i] .= rrd::gprint("var$KEY", array('LAST', 'MAX', 'AVERAGE'), "%6.2lf") ; + } +} diff --git a/share/pnp/templates.dist/check_hp_bladechassis.php b/share/pnp/templates.dist/check_hp_bladechassis.php new file mode 100644 index 0000000..d338bbb --- /dev/null +++ b/share/pnp/templates.dist/check_hp_bladechassis.php @@ -0,0 +1,42 @@ + diff --git a/share/pnp/templates.dist/check_hpasm.php b/share/pnp/templates.dist/check_hpasm.php new file mode 100644 index 0000000..763f22a --- /dev/null +++ b/share/pnp/templates.dist/check_hpasm.php @@ -0,0 +1,42 @@ + $VAL){ + if(preg_match('/^fan_/',$NAME[$KEY])){ + $ds_name[1] = "Fan Speed"; + $opt[1] = "-X0 --slope-mode -u $max_rpm --vertical-label \"RPMs\" --title \"HPASM Fan Speed\" "; + if(!isset($def[1])){ + $def[1] = ""; + } + $def[1] .= "DEF:ovar$KEY=$RRDFILE[$KEY]:$DS[$KEY]:AVERAGE " ; + $def[1] .= "CDEF:var$KEY=ovar$KEY,100,/,$max_rpm,* " ; + $def[1] .= "LINE:var$KEY#".$colors[$col_f].":\"$NAME[$KEY]\" " ; + $def[1] .= "GPRINT:var$KEY:LAST:\"%6.0lf RPM LAST \" "; + $def[1] .= "GPRINT:var$KEY:MAX:\"%6.0lf RPM MAX \" "; + $def[1] .= "GPRINT:var$KEY:AVERAGE:\"%6.2lf RPM AVERAGE \\n\" "; + $col_f++; + } + + if(preg_match('/^temp_/',$NAME[$KEY])){ + $ds_name[2] = "Temperature"; + $opt[2] = "--slope-mode --vertical-label \"Grad Celsius\" --title \"HPASM Temperature\" "; + if(!isset($def[2])){ + $def[2] = ""; + } + $def[2] .= "DEF:var$KEY=$RRDFILE[$KEY]:$DS[$KEY]:AVERAGE " ; + $def[2] .= "LINE:var$KEY#".$colors[$col_t].":\"$NAME[$KEY]\\t\" " ; + $def[2] .= "GPRINT:var$KEY:LAST:\"%6.0lf $UNIT[$KEY] LAST \" "; + $def[2] .= "GPRINT:var$KEY:MAX:\"%6.0lf $UNIT[$KEY] MAX \" "; + $def[2] .= "GPRINT:var$KEY:AVERAGE:\"%6.2lf $UNIT[$KEY] AVERAGE \\n\" "; + $col_t++; + } +} +?> diff --git a/share/pnp/templates.dist/check_http.php b/share/pnp/templates.dist/check_http.php new file mode 100644 index 0000000..d24d367 --- /dev/null +++ b/share/pnp/templates.dist/check_http.php @@ -0,0 +1,42 @@ + diff --git a/share/pnp/templates.dist/check_icmp.php b/share/pnp/templates.dist/check_icmp.php new file mode 120000 index 0000000..cdbf865 --- /dev/null +++ b/share/pnp/templates.dist/check_icmp.php @@ -0,0 +1 @@ +check_ping.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_iftraffic_counter.php b/share/pnp/templates.dist/check_iftraffic_counter.php new file mode 100644 index 0000000..400b11a --- /dev/null +++ b/share/pnp/templates.dist/check_iftraffic_counter.php @@ -0,0 +1,17 @@ + diff --git a/share/pnp/templates.dist/check_iftraffic_pct.php b/share/pnp/templates.dist/check_iftraffic_pct.php new file mode 100644 index 0000000..746355a --- /dev/null +++ b/share/pnp/templates.dist/check_iftraffic_pct.php @@ -0,0 +1,18 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_connector_errors.php b/share/pnp/templates.dist/check_jmx4perl_connector_errors.php new file mode 100644 index 0000000..8c2f108 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_connector_errors.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_connector_nr_requests.php b/share/pnp/templates.dist/check_jmx4perl_connector_nr_requests.php new file mode 100644 index 0000000..71ca663 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_connector_nr_requests.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_connector_proc_time.php b/share/pnp/templates.dist/check_jmx4perl_connector_proc_time.php new file mode 100644 index 0000000..0da72d3 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_connector_proc_time.php @@ -0,0 +1,16 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_connector_received.php b/share/pnp/templates.dist/check_jmx4perl_connector_received.php new file mode 100644 index 0000000..1c3779b --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_connector_received.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_connector_sent.php b/share/pnp/templates.dist/check_jmx4perl_connector_sent.php new file mode 100644 index 0000000..59ff535 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_connector_sent.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_connector_threads.php b/share/pnp/templates.dist/check_jmx4perl_connector_threads.php new file mode 100644 index 0000000..0b3cdfb --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_connector_threads.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_memory_gc_count.php b/share/pnp/templates.dist/check_jmx4perl_memory_gc_count.php new file mode 100644 index 0000000..e35a321 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_memory_gc_count.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_memory_gc_time.php b/share/pnp/templates.dist/check_jmx4perl_memory_gc_time.php new file mode 100644 index 0000000..779e0c9 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_memory_gc_time.php @@ -0,0 +1,16 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_memory_heap.php b/share/pnp/templates.dist/check_jmx4perl_memory_heap.php new file mode 100644 index 0000000..3ce8506 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_memory_heap.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_thread_count.php b/share/pnp/templates.dist/check_jmx4perl_thread_count.php new file mode 100644 index 0000000..928bfd4 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_thread_count.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_jmx4perl_thread_increase.php b/share/pnp/templates.dist/check_jmx4perl_thread_increase.php new file mode 100644 index 0000000..73745b0 --- /dev/null +++ b/share/pnp/templates.dist/check_jmx4perl_thread_increase.php @@ -0,0 +1,21 @@ + diff --git a/share/pnp/templates.dist/check_load.php b/share/pnp/templates.dist/check_load.php new file mode 100644 index 0000000..c3b46af --- /dev/null +++ b/share/pnp/templates.dist/check_load.php @@ -0,0 +1,26 @@ + diff --git a/share/pnp/templates.dist/check_local_disk.php b/share/pnp/templates.dist/check_local_disk.php new file mode 120000 index 0000000..3167fdb --- /dev/null +++ b/share/pnp/templates.dist/check_local_disk.php @@ -0,0 +1 @@ +check_disk.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_local_load.php b/share/pnp/templates.dist/check_local_load.php new file mode 120000 index 0000000..18c488e --- /dev/null +++ b/share/pnp/templates.dist/check_local_load.php @@ -0,0 +1 @@ +check_load.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_messpc_temp.php b/share/pnp/templates.dist/check_messpc_temp.php new file mode 100644 index 0000000..96d517f --- /dev/null +++ b/share/pnp/templates.dist/check_messpc_temp.php @@ -0,0 +1,23 @@ + +# +if ($WARN[1] == "") { + $WARN[1] = 0; +} +if ($CRIT[1] == "") { + $CRIT[1] = 0; +} + +$opt[1] = "--vertical-label \"Temperature\" --title \"Temperature for $hostname / $servicedesc\" "; + +$def[1] = "DEF:var1=$RRDFILE[1]:$DS[1]:AVERAGE "; +$def[1] .= "AREA:var1#00FF00:\"Temperature \" "; +$def[1] .= "LINE1:var1#000000:\"\" "; +$def[1] .= "GPRINT:var1:LAST:\"%3.4lg %s$UNIT[1] LAST \" "; +$def[1] .= "GPRINT:var1:MAX:\"%3.4lg %s$UNIT[1] MAX \" "; +$def[1] .= "GPRINT:var1:AVERAGE:\"%3.4lg %s$UNIT[1] AVERAGE \\n\" "; +$def[1] .= "HRULE:$WARN[1]#FFFF00:\"Warning on $WARN[1]C\" "; +$def[1] .= "HRULE:$CRIT[1]#FF0000:\"Critical on $CRIT[1]C\" "; +?> diff --git a/share/pnp/templates.dist/check_mssql_health.php b/share/pnp/templates.dist/check_mssql_health.php new file mode 100644 index 0000000..1ffd2a3 --- /dev/null +++ b/share/pnp/templates.dist/check_mssql_health.php @@ -0,0 +1,364 @@ +DS as $KEY=>$VAL) { + $warning = ($VAL['WARN'] != "") ? $VAL['WARN'] : ""; + $warnmin = ($VAL['WARN_MIN'] != "") ? $VAL['WARN_MIN'] : ""; + $warnmax = ($VAL['WARN_MAX'] != "") ? $VAL['WARN_MAX'] : ""; + $critical = ($VAL['CRIT'] != "") ? $VAL['CRIT'] : ""; + $critmin = ($VAL['CRIT_MIN'] != "") ? $VAL['CRIT_MIN'] : ""; + $critmax = ($VAL['CRIT_MAX'] != "") ? $VAL['CRIT_MAX'] : ""; + $minimum = ($VAL['MIN'] != "") ? $VAL['MIN'] : ""; + $maximum = ($VAL['MAX'] != "") ? $VAL['MAX'] : ""; + + if(preg_match('/^connection_time$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Time to connect"; + $opt[$defcnt] = "--vertical-label \"Seconds\" --title \"Time to establish a connection to $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("connectiontime",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::area("connectiontime","#111111"); + $def[$defcnt] .= rrd::gprint("connectiontime",array("LAST", "MAX", "AVERAGE"),"%3.2lf Seconds") ; + $defcnt++; + } + if(preg_match('/^cpu_busy$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "CPU Busy Time"; + $opt[$defcnt] = "--vertical-label \"%\" --title \"CPU busy time on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("cpubusy",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::cdef("ag","cpubusy,".$VAL['WARN'].",LE,cpubusy,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,cpubusy,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","cpubusy,".$VAL['CRIT'].",LE,cpubusy,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,cpubusy,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","cpubusy,100,LE,cpubusy,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,cpubusy,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green"); + $def[$defcnt] .= rrd::area("ay","#$yellow"); + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("cpubusy","#111111"); + $def[$defcnt] .= rrd::gprint("cpubusy","LAST","CPU is busy for %3.2lf percent of the time\\n"); + $defcnt++; + } + if(preg_match('/^io_busy$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "IO Busy Time"; + $opt[$defcnt] = "--vertical-label \"%\" --title \"IO busy time on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("iobusy",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::cdef("ag","iobusy,".$VAL['WARN'].",LE,iobusy,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,iobusy,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","iobusy,".$VAL['CRIT'].",LE,iobusy,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,iobusy,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","iobusy,100,LE,iobusy,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,iobusy,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green"); + $def[$defcnt] .= rrd::area("ay","#$yellow"); + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("iobusy","#111111"); + $def[$defcnt] .= rrd::gprint("iobusy","LAST","IO is busy for %3.2lf percent of the time\\n"); + $defcnt++; + } + if(preg_match('/^full_scans_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Full Table Scans / Sec"; + $opt[$defcnt] = "--vertical-label \"scans / sec\" --title \"Full table scans / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("fullscans",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","fullscans,".$VAL['WARN'].",LE,fullscans,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,fullscans,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","fullscans,".$VAL['CRIT'].",LE,fullscans,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,fullscans,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","fullscans,INF,LE,fullscans,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,fullscans,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green"); + $def[$defcnt] .= rrd::area("ay","#$yellow"); + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("fullscans","#000000", "Full table sacns"); + $def[$defcnt] .= rrd::gprint("fullscans",array("MAX", "AVERAGE", "LAST"),"%3.2lf"); + $defcnt++; + } + if(preg_match('/^connected_users$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Connected Users"; + $opt[$defcnt] = "--vertical-label \"Users\" --title \"Users connected to $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("users",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","users,".$VAL['WARN'].",LE,users,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,users,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","users,".$VAL['CRIT'].",LE,users,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,users,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","users,INF,LE,users,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,users,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("users","#000000","connected users"); + $def[$defcnt] .= rrd::gprint("users",array("LAST","MAX","AVERAGE"),"%.0lf"); + $defcnt++; + } + + if(preg_match('/^(.*)_transactions_per_sec/', $VAL['NAME'], $match)) { + $dsname = $match[1]; + if(empty($opt[1])){ + $opt[1] = "--vertical-label \"Transactions/s\" -l0 --title \"Database transactions / sec\" "; + } + if(empty($def[1])){ + $def[1] = ""; + } + $ds_name[1] = "Transactions Per Seconds "; + $def[1] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[1] .= rrd::line1 ("var".$KEY, rrd::color($KEY), rrd::cut($dsname, 12) ) ; + $def[1] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%3.6lf %S" ); + + } + + if(preg_match('/^latch_waits_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Latch Waits / Sec"; + $opt[$defcnt] = "--vertical-label \"waits / sec\" --title \"Latch waits / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("waits",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","waits,".$VAL['WARN'].",LE,waits,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,waits,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","waits,".$VAL['CRIT'].",LE,waits,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,waits,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","waits,INF,LE,waits,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,waits,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green"); + $def[$defcnt] .= rrd::area("ay","#$yellow"); + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("waits","#000000", "waits/s"); + $def[$defcnt] .= rrd::gprint("waits",array("MAX","AVERAGE","LAST"),"%3.2lf"); + $defcnt++; + } + if(preg_match('/^latch_avg_wait_time$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Latch Wait Time"; + $opt[$defcnt] = "--vertical-label \"msec\" --title \"Latch avg wait time on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("waittime",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","waittime,".$VAL['WARN'].",LE,waittime,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,waittime,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","waittime,".$VAL['CRIT'].",LE,waittime,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,waittime,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","waittime,INF,LE,waittime,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,waittime,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("waittime","#000000"); + $def[$defcnt] .= rrd::gprint("waittime",array("MAX", "AVERAGE", "LAST"),"%3.2lf"); + $defcnt++; + } + if(preg_match('/^sql_initcompilations_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Initial Compilations"; + $opt[$defcnt] = "--vertical-label \"initcomps/s\" --title \"Initial compilations / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("comps",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","comps,".$VAL['WARN'].",LE,comps,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,comps,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","comps,".$VAL['CRIT'].",LE,comps,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,comps,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","comps,INF,LE,comps,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,comps,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("comps","#000000","Compilations"); + $def[$defcnt] .= rrd::gprint("comps",array("MAX", "AVERAGE", "LAST"),"%3.2lf/s"); + $defcnt++; + } + if(preg_match('/^sql_recompilations_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Re-Compilations"; + $opt[$defcnt] = "--vertical-label \"re-comps/s\" --title \"Re-Compilations / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("comps",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","comps,".$VAL['WARN'].",LE,comps,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,comps,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","comps,".$VAL['CRIT'].",LE,comps,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,comps,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","comps,INF,LE,comps,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,comps,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green"); + $def[$defcnt] .= rrd::area("ay","#$yellow"); + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("comps","#000000","Re-Compilations"); + $def[$defcnt] .= rrd::gprint("comps",array("MAX", "AVERAGE", "LAST"),"%3.2lf/s"); + $defcnt++; + } + if(preg_match('/^batch_requests_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Batch Requests"; + $opt[$defcnt] = "--vertical-label \"batchreqs/s\" --title \"Batch requests / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("breqs",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","breqs,".$VAL['WARN'].",LE,breqs,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,breqs,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","breqs,".$VAL['CRIT'].",LE,breqs,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,breqs,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","breqs,INF,LE,breqs,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,breqs,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("breqs","#000000","Batch Requests"); + $def[$defcnt] .= rrd::gprint("breqs",array("LAST","AVERAGE","MAX"),"%3.2lf"); + $defcnt++; + } + if(preg_match('/^checkpoint_pages_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Checkpoint Pages"; + $opt[$defcnt] = "--vertical-label \"pages/s\" --title \"Flushed pages / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("pages",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","pages,".$VAL['WARN'].",LE,pages,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,pages,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","pages,".$VAL['CRIT'].",LE,pages,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,pages,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","pages,INF,LE,pages,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,pages,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("pages","#000000", "pages flushed"); + $def[$defcnt] .= rrd::gprint("pages",array("LAST","AVERAGE","MAX"),"%3.2lf"); + $defcnt++; + } + if(preg_match('/^free_list_stalls_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Free List Stalls"; + $opt[$defcnt] = "--vertical-label \"stalls/s\" --title \"Free list stalls / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("stalls",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","stalls,".$VAL['WARN'].",LE,stalls,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,stalls,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","stalls,".$VAL['CRIT'].",LE,stalls,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,stalls,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","stalls,INF,LE,stalls,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,stalls,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green"); + $def[$defcnt] .= rrd::area("ay","#$yellow"); + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("stalls","#000000", "free list stalls"); + $def[$defcnt] .= rrd::gprint("stalls",array("LAST", "AVERAGE","MAX"),"%3.2lf"); + $defcnt++; + } + if(preg_match('/^lazy_writes_per_sec$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Lazy Writes"; + $opt[$defcnt] = "--vertical-label \"lazyw/s\" --title \"Lazy writes / sec on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("lazyw",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::cdef("ag","lazyw,".$VAL['WARN'].",LE,lazyw,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,lazyw,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","lazyw,".$VAL['CRIT'].",LE,lazyw,".$VAL['WARN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,lazyw,0,IF"); + $def[$defcnt] .= rrd::cdef("ar","lazyw,INF,LE,lazyw,".$VAL['CRIT'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,lazyw,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red"); + $def[$defcnt] .= rrd::line1("lazyw","#000000"); + $def[$defcnt] .= rrd::gprint("lazyw",array("LAST", "AVERAGE","MAX"),"%3.4lf"); + $defcnt++; + } + if(preg_match('/^page_life_expectancy$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Page Life Expectancy"; + $opt[$defcnt] = "--vertical-label \"s\" --title \"Page life expectancy on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("lifeexp",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::cdef("ar","lifeexp,".$VAL['CRIT_MIN'].",LE,lifeexp,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,lifeexp,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","lifeexp,".$VAL['WARN_MIN'].",LE,lifeexp,".$VAL['CRIT_MIN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,lifeexp,0,IF"); + $def[$defcnt] .= rrd::cdef("ag","lifeexp,INF,LE,lifeexp,".$VAL['WARN_MIN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,lifeexp,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("lifeexp","#000000","Page Live"); + $def[$defcnt] .= rrd::gprint("lifeexp",array("LAST", "AVERAGE", "MIN"),"%3.2lf") ; + $defcnt++; + } + if(preg_match('/^total_server_memory$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Total Server memory"; + $opt[$defcnt] = "--vertical-label \"Bytes\" --title \"Total sql server memory on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("mem",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST"); + $def[$defcnt] .= rrd::area("mem","#c3c3c3", "Memory"); + $def[$defcnt] .= rrd::line1("mem","#111111"); + $def[$defcnt] .= rrd::gprint("mem",array("MAX","AVERAGE", "LAST"),"%.1lf %SB") ; + $defcnt++; + } + if(preg_match('/^buffer_cache_hit_ratio$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Buffer Cache Hit Ratio"; + $opt[$defcnt] = "--vertical-label \"%\" --title \"Buffer cache hit ratio on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("bufcahitrat",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::cdef("ar","bufcahitrat,".$VAL['CRIT_MIN'].",LE,bufcahitrat,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,bufcahitrat,0,IF"); + $def[$defcnt] .= rrd::cdef("ay","bufcahitrat,".$VAL['WARN_MIN'].",LE,bufcahitrat,".$VAL['CRIT_MIN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,bufcahitrat,0,IF"); + $def[$defcnt] .= rrd::cdef("ag","bufcahitrat,100,LE,bufcahitrat,".$VAL['WARN_MIN'].",GT,INF,UNKN,IF,UNKN,IF,ISINF,bufcahitrat,0,IF"); + $def[$defcnt] .= rrd::area("ag","#$green") ; + $def[$defcnt] .= rrd::area("ay","#$yellow") ; + $def[$defcnt] .= rrd::area("ar","#$red") ; + $def[$defcnt] .= rrd::line1("bufcahitrat","#000000:"); + $def[$defcnt] .= rrd::gprint("bufcahitrat","LAST","Hit ratio is %3.2lf percent\\n") ; + $defcnt++; + } + + if(preg_match('/^(.*)_lock_timeouts_per_sec/', $VAL['NAME'], $match)) { + $dsname = $match[1]; + if(empty($opt[1])){ + $opt[1] = "--vertical-label \"Lock timeouts/s\" -l0 --title \"Locks timeouts / sec\" "; + } + if(empty($def[1])){ + $def[1] = ""; + } + $ds_name[1] = "Lock Timeouts Per Second "; + $def[1] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[1] .= rrd::line1 ("var".$KEY, rrd::color($KEY), rrd::cut($dsname, 12) ) ; + $def[1] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%3.6lf" ); + + } + + if(preg_match('/^(.*)_lock_waits_per_sec/', $VAL['NAME'], $match)) { + $dsname = $match[1]; + if(!defined($opt[1])){ + $opt[1] = "--vertical-label \"Lockwaity/s\" -l0 --title \"Lockwaits / sec\" "; + } + if(empty($def[1])){ + $def[1] = ""; + } + $ds_name[1] = "Lockwaits / sec "; + $def[1] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[1] .= rrd::line1 ("var".$KEY, rrd::color($KEY), rrd::cut($dsname, 12) ) ; + $def[1] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%3.6lf" ); + + } + + if(preg_match('/^(.*)_deadlocks_per_sec/', $VAL['NAME'], $match)) { + $dsname = $match[1]; + if(!defined($opt[1])){ + $opt[1] = "--vertical-label \"Deadlocks/s\" -l0 --title \"Deadlocks / sec\" "; + } + if(empty($def[1])){ + $def[1] = ""; + } + $ds_name[1] = "Deadlocks / sec "; + $def[1] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[1] .= rrd::line1 ("var".$KEY, rrd::color($KEY), rrd::cut($dsname, 12) ) ; + $def[1] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%3.6lf" ); + } + + if(preg_match('/^db_(.*)_free_pct/', $VAL['NAME'], $match)) { + $dsname = $match[1]; + if(!defined($opt[1])){ + $opt[1] = "--vertical-label \"%\" -l0 --title \"DB Freespace %\" "; + } + if(empty($def[1])){ + $def[1] = ""; + } + $ds_name[1] = "DB Freespace %"; + $def[1] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[1] .= rrd::line1 ("var".$KEY, rrd::color($KEY), rrd::cut($dsname, 12) ) ; + $def[1] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%3.2lf%%" ); + } + if(preg_match('/^db_(.*)_free$/', $VAL['NAME'], $match)) { + $dsname = $match[1]; + if(empty($opt[2])){ + $opt[2] = "--vertical-label \"MB\" --title \"DB Freespace MB\" "; + } + if(empty($def[2])){ + $def[2] = ""; + } + $ds_name[2] = "DB Freespace MB"; + $def[2] .= rrd::def ("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + $def[2] .= rrd::line1 ("var".$KEY, rrd::color($KEY), rrd::cut($dsname, 12) ) ; + $def[2] .= rrd::gprint ("var".$KEY, array("LAST","MAX","AVERAGE"), "%3.2lf %SM" ); + } + + if(preg_match('/^select$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Output from sql-query for $servicedesc"; + $opt[$defcnt] = "--vertical-label \"Counts\" --title \"Output from sql-query for $servicedesc on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("var".$KEY,$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::area("var".$KEY,"#111111"); + $def[$defcnt] .= rrd::gprint("var".$KEY,array("LAST", "MAX", "AVERAGE"),"%3.2lf Counts") ; + $defcnt++; + } + + if(preg_match('/^(.*)bck_age$/', $VAL['NAME'])) { + $ds_name[$defcnt] = "Last DB Backup"; + $opt[$defcnt] = "--vertical-label \"Hours\" --title \"Last DB Backup\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= rrd::def("var".$KEY,$VAL['RRDFILE'],$VAL['DS'],"AVERAGE:reduce=LAST") ; + $def[$defcnt] .= rrd::area("var".$KEY,"#111111"); + $def[$defcnt] .= rrd::gprint("var".$KEY,array("LAST", "MAX", "AVERAGE"),"%3.2lf Counts") ; + $defcnt++; + } + +} +?> + diff --git a/share/pnp/templates.dist/check_multi.php b/share/pnp/templates.dist/check_multi.php new file mode 100644 index 0000000..ba6bcd1 --- /dev/null +++ b/share/pnp/templates.dist/check_multi.php @@ -0,0 +1,23 @@ + diff --git a/share/pnp/templates.dist/check_multi_nagiostats.php b/share/pnp/templates.dist/check_multi_nagiostats.php new file mode 100644 index 0000000..64eac64 --- /dev/null +++ b/share/pnp/templates.dist/check_multi_nagiostats.php @@ -0,0 +1,104 @@ + diff --git a/share/pnp/templates.dist/check_mysql_health.php b/share/pnp/templates.dist/check_mysql_health.php new file mode 100644 index 0000000..2a8f433 --- /dev/null +++ b/share/pnp/templates.dist/check_mysql_health.php @@ -0,0 +1,400 @@ +60s) on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:longrun=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:longrun#111111 "; + $def[$defcnt] .= "VDEF:vlongrun=longrun,LAST " ; + $def[$defcnt] .= "GPRINT:vlongrun:\"%.0lf long running processes \" " ; + $defcnt++; + } + if(preg_match('/^keycache_hitrate_now$/', $NAME[$i])) { + $ds_name[$defcnt] = "MyISAM key cache hitrate"; + $opt[$defcnt] = "--vertical-label \"Percent\" --title \"MyISAM key cache hitrate on $hostname\" --upper-limit 100 --lower-limit 0 "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^keycache_hitrate$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitrate=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "CDEF:ar=hitrate,$CRIT_MIN[$ii],LE,hitrate,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ay=hitrate,$WARN_MIN[$ii],LE,hitrate,$CRIT_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ag=hitrate,100,LE,hitrate,$WARN_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "AREA:ag#$green: " ; + $def[$defcnt] .= "AREA:ay#$yellow: " ; + $def[$defcnt] .= "AREA:ar#$red: " ; + $def[$defcnt] .= "LINE1.5:hitrate#111111:\" \" "; + $def[$defcnt] .= "VDEF:vhitrate=hitrate,LAST " ; + $def[$defcnt] .= "GPRINT:vhitrate:\"Hitratio (since epoch) is %3.2lf percent \\n\" "; + } + if(preg_match('/^keycache_hitrate_now$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitratenow=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "LINE1.5:hitratenow#$now:\" \" "; + $def[$defcnt] .= "VDEF:vhitratenow=hitratenow,LAST " ; + $def[$defcnt] .= "GPRINT:vhitratenow:\"Hitratio (current) is %3.2lf percent \\n\" "; + } + } + $defcnt++; + } + if(preg_match('/^qcache_hitrate_now$/', $NAME[$i])) { + $ds_name[$defcnt] = "Query cache hitrate"; + $opt[$defcnt] = "--vertical-label \"Percent\" --title \"Query cache hitrate on $hostname\" --upper-limit 100 --lower-limit 0 "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^qcache_hitrate$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitrate=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "CDEF:ar=hitrate,$CRIT_MIN[$ii],LE,hitrate,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ay=hitrate,$WARN_MIN[$ii],LE,hitrate,$CRIT_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ag=hitrate,100,LE,hitrate,$WARN_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "AREA:ag#$green: " ; + $def[$defcnt] .= "AREA:ay#$yellow: " ; + $def[$defcnt] .= "AREA:ar#$red: " ; + $def[$defcnt] .= "LINE1.5:hitrate#111111:\" \" "; + $def[$defcnt] .= "VDEF:vhitrate=hitrate,LAST " ; + $def[$defcnt] .= "GPRINT:vhitrate:\"Hitratio (since epoch) is %3.2lf percent \\n\" "; + } + if(preg_match('/^qcache_hitrate_now$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitratenow=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "LINE1.5:hitratenow#$now:\" \" "; + $def[$defcnt] .= "VDEF:vhitratenow=hitratenow,LAST " ; + $def[$defcnt] .= "GPRINT:vhitratenow:\"Hitratio (current) is %3.2lf percent \\n\" "; + } + } + $defcnt++; + $ds_name[$defcnt] = "Selects per second"; + $opt[$defcnt] = "--vertical-label \"Selects / sec\" --title \"Selects per second on $hostname\" "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^selects_per_sec$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:sps=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:sps#$now:\" \" "; + $def[$defcnt] .= "VDEF:vsps=sps,LAST " ; + $def[$defcnt] .= "GPRINT:vsps:\"%3.2lf Selects per second \\n\" "; + } + } + $defcnt++; + } + if(preg_match('/^qcache_lowmem_prunes_rate$/', $NAME[$i])) { + $ds_name[$defcnt] = "Query cache low memory prunes"; + $opt[$defcnt] = "--vertical-label \"Prunes / sec\" --title \"Query cache low mem prunes on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:prunes=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:prunes#111111 "; + $def[$defcnt] .= "VDEF:vprunes=prunes,LAST " ; + $def[$defcnt] .= "GPRINT:vprunes:\"Rate is %3.2lf Prunes / Second \" " ; + $defcnt++; + } + if(preg_match('/^slow_queries_rate$/', $NAME[$i])) { + $ds_name[$defcnt] = "Slow query rate"; + $opt[$defcnt] = "--vertical-label \"Slow queries / sec\" --title \"Slow queries on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:prunes=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:prunes#111111 "; + $def[$defcnt] .= "VDEF:vprunes=prunes,LAST " ; + $def[$defcnt] .= "GPRINT:vprunes:\"%3.2lf Slow queries / Second \" " ; + $defcnt++; + } + if(preg_match('/^tablelock_contention_now$/', $NAME[$i])) { + $ds_name[$defcnt] = "Table lock contention"; + # set upper limit to 10, because 3 means an already dead database + $opt[$defcnt] = "--vertical-label \"Percent\" --title \"Table lock contention on $hostname\" --upper-limit 10 --lower-limit 0 "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^tablelock_contention$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:tbllckcont=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "CDEF:ag=tbllckcont,$WARN[$ii],LE,tbllckcont,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,tbllckcont,0,IF "; + $def[$defcnt] .= "CDEF:ay=tbllckcont,$CRIT[$ii],LE,tbllckcont,$WARN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,tbllckcont,0,IF "; + $def[$defcnt] .= "CDEF:ar=tbllckcont,100,LE,tbllckcont,$CRIT[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,tbllckcont,0,IF "; + $def[$defcnt] .= "AREA:ag#$green: " ; + $def[$defcnt] .= "AREA:ay#$yellow: " ; + $def[$defcnt] .= "AREA:ar#$red: " ; + $def[$defcnt] .= "LINE:tbllckcont#111111:\" \" "; + $def[$defcnt] .= "VDEF:vtbllckcont=tbllckcont,LAST " ; + $def[$defcnt] .= "GPRINT:vtbllckcont:\"Lock contention (since epoch) is %3.2lf%%\\n\" " ; + } + if(preg_match('/^tablelock_contention_now$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:tbllckcontnow=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "LINE1.5:tbllckcontnow#$now:\" \" "; + $def[$defcnt] .= "VDEF:vtbllckcontnow=tbllckcontnow,LAST " ; + $def[$defcnt] .= "GPRINT:vtbllckcontnow:\"Lock contention (current) is %3.2lf%%\" "; + } + } + $defcnt++; + } + if(preg_match('/^tablecache_fillrate$/', $NAME[$i])) { + $ds_name[$defcnt] = "Table cache hitrate"; + $opt[$defcnt] = "--vertical-label \"Percent\" --title \"Table cache hitrate on $hostname\" --upper-limit 100 --lower-limit 0 "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^tablecache_hitrate$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitrate=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "CDEF:ar=hitrate,$CRIT_MIN[$ii],LE,hitrate,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ay=hitrate,$WARN_MIN[$ii],LE,hitrate,$CRIT_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ag=hitrate,100,LE,hitrate,$WARN_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "AREA:ag#$green: " ; + $def[$defcnt] .= "AREA:ay#$yellow: " ; + $def[$defcnt] .= "AREA:ar#$red: " ; + $def[$defcnt] .= "LINE:hitrate#111111:\" \" "; + $def[$defcnt] .= "VDEF:vhitrate=hitrate,LAST " ; + $def[$defcnt] .= "GPRINT:vhitrate:\"Hitratio is %3.2lf percent \\n\" "; + } + if(preg_match('/^tablecache_fillrate$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitratenow=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "LINE1.5:hitratenow#$now:\" \" "; + $def[$defcnt] .= "VDEF:vhitratenow=hitratenow,LAST " ; + $def[$defcnt] .= "GPRINT:vhitratenow:\"%3.2lf%% of the cache is filled \\n\" "; + } + } + $defcnt++; + } + if(preg_match('/^pct_tmp_table_on_disk_now$/', $NAME[$i])) { + $ds_name[$defcnt] = "Temporary tables created on disk "; + $opt[$defcnt] = "--vertical-label \"Percent\" --title \"Temporary tables created on disk on $hostname\" --upper-limit 10 --lower-limit 0 "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^pct_tmp_table_on_disk$/', $NAME[$ii])) { + + $def[$defcnt] .= "DEF:tmptbldsk=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "CDEF:ag=tmptbldsk,$WARN[$ii],LE,tmptbldsk,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,tmptbldsk,0,IF "; + $def[$defcnt] .= "CDEF:ay=tmptbldsk,$CRIT[$ii],LE,tmptbldsk,$WARN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,tmptbldsk,0,IF "; + $def[$defcnt] .= "CDEF:ar=tmptbldsk,100,LE,tmptbldsk,$CRIT[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,tmptbldsk,0,IF "; + $def[$defcnt] .= "AREA:ag#$green: " ; + $def[$defcnt] .= "AREA:ay#$yellow: " ; + $def[$defcnt] .= "AREA:ar#$red: " ; + $def[$defcnt] .= "LINE:tmptbldsk#111111:\" \" "; + $def[$defcnt] .= "VDEF:vtmptbldsk=tmptbldsk,LAST " ; + $def[$defcnt] .= "GPRINT:vtmptbldsk:\"%3.2lf percent of temp tables were created on disk (since epoch)\\n\" " ; + } + if(preg_match('/^pct_tmp_table_on_disk_now$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:tmptbldsknow=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "LINE1.5:tmptbldsknow#$now:\" \" "; + $def[$defcnt] .= "VDEF:vtmptbldsknow=tmptbldsknow,LAST " ; + $def[$defcnt] .= "GPRINT:vtmptbldsknow:\"%3.2lf percent of temp tables were created on disk (recently)\\n\" " ; + } + } + $defcnt++; + } + if(preg_match('/^thread_cache_hitrate_now$/', $NAME[$i])) { + $ds_name[$defcnt] = "Thread cache hitrate"; + $opt[$defcnt] = "--vertical-label \"Percent\" --title \"Thread cache hitrate on $hostname\" --upper-limit 100 --lower-limit 0 "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^thread_cache_hitrate$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitrate=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "CDEF:ar=hitrate,$CRIT_MIN[$ii],LE,hitrate,0,GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ay=hitrate,$WARN_MIN[$ii],LE,hitrate,$CRIT_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "CDEF:ag=hitrate,100,LE,hitrate,$WARN_MIN[$ii],GT,INF,UNKN,IF,UNKN,IF,ISINF,hitrate,0,IF "; + $def[$defcnt] .= "AREA:ag#$green: " ; + $def[$defcnt] .= "AREA:ay#$yellow: " ; + $def[$defcnt] .= "AREA:ar#$red: " ; + $def[$defcnt] .= "LINE:hitrate#111111:\" \" "; + $def[$defcnt] .= "VDEF:vhitrate=hitrate,LAST " ; + $def[$defcnt] .= "GPRINT:vhitrate:\"Hitratio (since epoch) is %3.2lf percent \\n\" "; + } + if(preg_match('/^thread_cache_hitrate_now$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:hitratenow=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "LINE1.5:hitratenow#$now:\" \" "; + $def[$defcnt] .= "VDEF:vhitratenow=hitratenow,LAST " ; + $def[$defcnt] .= "GPRINT:vhitratenow:\"Hitratio (current) is %3.2lf percent \\n\" "; + } + } + $defcnt++; + $ds_name[$defcnt] = "Connects per second"; + $opt[$defcnt] = "--vertical-label \"Conects / sec\" --title \"Connects per second on $hostname\" "; + $def[$defcnt] = ""; + foreach ($DS as $ii) { + if(preg_match('/^connections_per_sec$/', $NAME[$ii])) { + $def[$defcnt] .= "DEF:sps=$RRDFILE[$ii]:$DS[$ii]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:sps#$now:\" \" "; + $def[$defcnt] .= "VDEF:vsps=sps,LAST " ; + $def[$defcnt] .= "GPRINT:vsps:\"%3.2lf Connects per second \\n\" "; + } + } + $defcnt++; + } + if(preg_match('/^threads_connected$/', $NAME[$i])) { + $ds_name[$defcnt] = "Connection threads"; + $opt[$defcnt] = "--vertical-label \"Threads\" --title \"Connection threads on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:threads=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:threads#111111 "; + $def[$defcnt] .= "VDEF:vthreads=threads,LAST " ; + $def[$defcnt] .= "GPRINT:vthreads:\"%.0lf Connection threads \" " ; + $defcnt++; + } + if(preg_match('/^threads_running$/', $NAME[$i])) { + $ds_name[$defcnt] = "Running threads"; + $opt[$defcnt] = "--vertical-label \"Threads\" --title \"Running threads on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:threads=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:threads#111111 "; + $def[$defcnt] .= "VDEF:vthreads=threads,LAST " ; + $def[$defcnt] .= "GPRINT:vthreads:\"%.0lf Running threads \" " ; + $defcnt++; + } + if(preg_match('/^threads_cached$/', $NAME[$i])) { + $ds_name[$defcnt] = "Cached threads"; + $opt[$defcnt] = "--vertical-label \"Threads\" --title \"Cached threads on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:threads=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:threads#111111 "; + $def[$defcnt] .= "VDEF:vthreads=threads,LAST " ; + $def[$defcnt] .= "GPRINT:vthreads:\"%.0lf Cached threads \" " ; + $defcnt++; + } + if(preg_match('/^pct_open_files$/', $NAME[$i])) { + $ds_name[$defcnt] = "PCT Open Files"; + $opt[$defcnt] = "--vertical-label \"OpenFiles\" --title \"PCT Open Files $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:threads=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:threads#111111 "; + $def[$defcnt] .= "VDEF:vthreads=threads,LAST " ; + $def[$defcnt] .= "GPRINT:vthreads:\"%.0lf Open Files \" " ; + $defcnt++; + } + if(preg_match('/^threads_created_per_sec$/', $NAME[$i])) { + $ds_name[$defcnt] = "Created thread per second"; + $opt[$defcnt] = "--vertical-label \"Created threads / sec\" --title \"Created threads per second on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:sps=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:sps#$now:\" \" "; + $def[$defcnt] .= "VDEF:vsps=sps,LAST " ; + $def[$defcnt] .= "GPRINT:vsps:\"%3.2lf Created threads per second \\n\" "; + } + if(preg_match('/^connects_aborted_per_sec$/', $NAME[$i])) { + $ds_name[$defcnt] = "Aborted Connects per second"; + $opt[$defcnt] = "--vertical-label \"Aborted connects / sec\" --title \"Aborted Connects per second on $hostname\" "; + $def[$defcnt] = ""; + $def[$defcnt] .= "DEF:sps=$RRDFILE[$i]:$DS[$i]:AVERAGE:reduce=LAST " ; + $def[$defcnt] .= "AREA:sps#$now:\" \" "; + $def[$defcnt] .= "VDEF:vsps=sps,LAST " ; + $def[$defcnt] .= "GPRINT:vsps:\"%3.2lf Aborted Connects per second \\n\" "; + } +} +?> + diff --git a/share/pnp/templates.dist/check_nt_cpu.php b/share/pnp/templates.dist/check_nt_cpu.php new file mode 100644 index 0000000..8a226ce --- /dev/null +++ b/share/pnp/templates.dist/check_nt_cpu.php @@ -0,0 +1,24 @@ + diff --git a/share/pnp/templates.dist/check_nt_disk.php b/share/pnp/templates.dist/check_nt_disk.php new file mode 100644 index 0000000..34df9ce --- /dev/null +++ b/share/pnp/templates.dist/check_nt_disk.php @@ -0,0 +1,24 @@ + diff --git a/share/pnp/templates.dist/check_nt_mem.php b/share/pnp/templates.dist/check_nt_mem.php new file mode 100644 index 0000000..0eb2dd7 --- /dev/null +++ b/share/pnp/templates.dist/check_nt_mem.php @@ -0,0 +1,20 @@ + diff --git a/share/pnp/templates.dist/check_ntp_time.php b/share/pnp/templates.dist/check_ntp_time.php new file mode 100644 index 0000000..a4df209 --- /dev/null +++ b/share/pnp/templates.dist/check_ntp_time.php @@ -0,0 +1,25 @@ + diff --git a/share/pnp/templates.dist/check_nwstat_CONNS.php b/share/pnp/templates.dist/check_nwstat_CONNS.php new file mode 100644 index 0000000..d6087f2 --- /dev/null +++ b/share/pnp/templates.dist/check_nwstat_CONNS.php @@ -0,0 +1,34 @@ + diff --git a/share/pnp/templates.dist/check_nwstat_LOAD.php b/share/pnp/templates.dist/check_nwstat_LOAD.php new file mode 100644 index 0000000..2bb0231 --- /dev/null +++ b/share/pnp/templates.dist/check_nwstat_LOAD.php @@ -0,0 +1,34 @@ + diff --git a/share/pnp/templates.dist/check_nwstat_LOAD1.php b/share/pnp/templates.dist/check_nwstat_LOAD1.php new file mode 120000 index 0000000..c328a6d --- /dev/null +++ b/share/pnp/templates.dist/check_nwstat_LOAD1.php @@ -0,0 +1 @@ +check_nwstat_LOAD.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_nwstat_LOAD15.php b/share/pnp/templates.dist/check_nwstat_LOAD15.php new file mode 120000 index 0000000..c328a6d --- /dev/null +++ b/share/pnp/templates.dist/check_nwstat_LOAD15.php @@ -0,0 +1 @@ +check_nwstat_LOAD.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_nwstat_LOAD5.php b/share/pnp/templates.dist/check_nwstat_LOAD5.php new file mode 120000 index 0000000..c328a6d --- /dev/null +++ b/share/pnp/templates.dist/check_nwstat_LOAD5.php @@ -0,0 +1 @@ +check_nwstat_LOAD.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_nwstat_ofiles.php b/share/pnp/templates.dist/check_nwstat_ofiles.php new file mode 100644 index 0000000..67a0d99 --- /dev/null +++ b/share/pnp/templates.dist/check_nwstat_ofiles.php @@ -0,0 +1,34 @@ + diff --git a/share/pnp/templates.dist/check_openmanage.php b/share/pnp/templates.dist/check_openmanage.php new file mode 100644 index 0000000..6ceefb9 --- /dev/null +++ b/share/pnp/templates.dist/check_openmanage.php @@ -0,0 +1,545 @@ +. + +# Array with different colors +$colors = array("0022ff", "22ff22", "ff0000", "00aaaa", "ff00ff", + "ffa500", "cc0000", "0000cc", "0080C0", "8080C0", + "FF0080", "800080", "688e23", "408080", "808000", + "000000", "00FF00", "0080FF", "FF8000", "800000", + "FB31FB"); + +# Counters +$f = 0; # fan probe counter +$t = 0; # temp probe counter +$a = 0; # amp probe counter +$v = 0; # volt probe counter +$e = 0; # enclosure counter + +# Flags +$visited_amp = 0; + +# IDs +$id_temp1 = 1; +$id_temp2 = 2; +$id_watt = 3; +$id_amp = 4; +$id_volt = 5; +$id_fan = 6; +$id_enc = 7; + +# Enclosure id +$enclosure_id = ''; + +# Default title +$def_title = 'Dell OpenManage'; + +# Temperature unit +if (!defined('tempunit_defined')) { + define('tempunit_defined', 1); + + function tempunit($arg) + { + $unit = 'unknown'; + $vlabel = 'unknown'; + + switch ($arg) { + default: + $vlabel = "Celsius"; + $unit = "°C"; + break; + case "F": + $vlabel = "Fahrenheit"; + $unit = "°F"; + break; + case "K": + $vlabel = "Kelvin"; + $unit = "K"; + break; + case "R": + $vlabel = "Rankine"; + $unit = "°R"; + break; + } + return array($unit, $vlabel); + } +} + + +# Determine if we're running in legacy mode +$legacy = "no"; +foreach ($this->DS as $KEY=>$VAL) { + if (preg_match('/^(pwr_mon_|fan_|temp_|enclosure_|p\d+|f\d+|t\d+|e.+?t\d+)/', $VAL['LABEL'])) { + $legacy = "yes"; + break; + } +} + +#------------------------------------------------------ +# MAIN LOOP +#------------------------------------------------------ +if ($legacy == "yes") { # --legacy-- + + $count = 0; # general counter + $PWRcolor = "66FF00"; + + # Flags + $visited_fan = 0; + $visited_temp = 0; + $visited_pwr = 0; + + # Loop through the performance data + foreach ($this->DS as $KEY=>$VAL) { + + # AMPERAGE PROBE + if(preg_match('/^pwr_mon_/', $VAL['NAME']) || preg_match('/^p\d+[aw]$/', $VAL['NAME'])) { + + # Watt + if (preg_match('/system/', $VAL['NAME']) || preg_match('/^p\d+w$/', $VAL['NAME'])) { + + # Long label + $VAL['NAME'] = preg_replace('/^pwr_mon_\d+_/', '', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/_/', ' ', $VAL['NAME']); + + # Short label + $VAL['NAME'] = preg_replace('/^p(\d+)w$/', 'Power Probe $1', $VAL['NAME']); + + ++$count; + $ds_name[$count] = "Power Consumption"; + $vlabel = "Watt"; + + $title = $ds_name[$count]; + + $opt[$count] = "--slope-mode --vertical-label \"$vlabel\" --title \"$def_title: $title\" "; + + if(isset($def[$count])){ + $def[$count] .= rrd::def("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + } + else { + $def[$count] = rrd::def("var".$KEY, $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + } + $def[$count] .= rrd::area("var$KEY", "#".$PWRcolor, $VAL['NAME']); + $def[$count] .= rrd::line1("var$KEY","#000000"); + $def[$count] .= rrd::gprint("var$KEY",array("LAST", "MAX", "AVERAGE"), "%6.0lf W"); + } + # Ampere + elseif (preg_match('/current/', $VAL['NAME']) || preg_match('/^p\d+a$/', $VAL['NAME'])) { + + # Long label + $VAL['NAME'] = preg_replace('/^pwr_mon_\d+_/', '', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/_/', ' ', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/ current \d+$/', '', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/ps/', 'PowerSupply', $VAL['NAME']); + + # Short label + $VAL['NAME'] = preg_replace('/^p(\d+)a$/', 'Amperage Probe $1', $VAL['NAME']); + + if ($visited_pwr == 0) { + ++$count; + $visited_pwr = 1; + } + $ds_name[$count] = "Amperage Probes"; + $vlabel = "Ampere"; + + $title = $ds_name[$count]; + + $opt[$count] = "-X0 --lower-limit 0 --slope-mode --vertical-label \"$vlabel\" --title \"$def_title: $title\" "; + if(isset($def[$count])){ + $def[$count] .= rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + else { + $def[$count] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + $def[$count] .= rrd::line1("var$KEY", "#".$colors[$a], $VAL['NAME']) ; + $def[$count] .= rrd::area("var$KEY","#".$colors[$a++]."20") ; + $def[$count] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%4.2lf A") ; + } + } + + # FANS (RPMs) + if(preg_match('/^fan_/', $VAL['NAME']) || preg_match('/^f\d+$/', $VAL['NAME'])){ + if ($visited_fan == 0) { + ++$count; + $visited_fan = 1; + } + + # Long label + $VAL['NAME'] = preg_replace('/^fan_\d+_/', '', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/_rpm$/', '', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/_/', ' ', $VAL['NAME']); + + # Short label + $VAL['NAME'] = preg_replace('/^f(\d+)$/', 'Fan Probe $1', $VAL['NAME']); + + $ds_name[$count] = "Fan Speed"; + + $opt[$count] = "-X0 --slope-mode --vertical-label \"RPMs\" --title \"$def_title: Fan Speeds\" "; + if(isset($def[$count])){ + $def[$count] .= rrd::def("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + } + else { + $def[$count] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE"); + } + $def[$count] .= rrd::line1("var$KEY", "#".$colors[$f++],$VAL['NAME']); + $def[$count] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%6.0lf RPM"); + } + + # TEMPERATURES (Celsius) + if(preg_match('/^temp_/', $VAL['NAME']) || preg_match('/^t\d+$/', $VAL['NAME'])){ + if ($visited_temp == 0) { + ++$count; + $visited_temp = 1; + } + + # Long label + $VAL['NAME'] = preg_replace('/^temp_\d+_/', '', $VAL['NAME']); + $VAL['NAME'] = preg_replace('/_/', ' ', $VAL['NAME']); + + # Short label + $VAL['NAME'] = preg_replace('/^t(\d+)$/', 'Temperature Probe $1', $VAL['NAME']); + + $ds_name[$count] = "Chassis Temperatures"; + + $warnThresh = "INF"; + $critThresh = "INF"; + + if ($VAL['WARN'] != "") { + $warnThresh = $VAL['WARN']; + } + if ($VAL['CRIT'] != "") { + $critThresh = $VAL['CRIT']; + } + + $opt[$count] = "--slope-mode --vertical-label \"Celsius\" --title \"$def_title: Chassis Temperatures\" "; + if(isset($def[$count])){ + $def[$count] .= rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + else { + $def[$count] = rrd::def("var$KEY", $VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + $def[$count] .= rrd::line1("var$KEY", "#".$colors[$t++], $VAL['NAME']); + $def[$count] .= rrd::gprint("var$KEY",array("LAST", "MAX", "AVERAGE"),"%6.0lf C"); + } + + # ENCLOSURE TEMPERATURES (Celsius) + if(preg_match('/^enclosure_(?P.+?)_temp_\d+$/', $VAL['NAME'], $matches) + || preg_match('/^e(?P.+?)t\d+$/', $VAL['NAME'], $matches)) { + $this_id = $matches['id']; + + if ($enclosure_id != $this_id) { + $e = 0; + ++$count; + $enclosure_id = $this_id; + } + + # Long label + $VAL['NAME'] = preg_replace('/^enclosure_.+?_temp_(\d+)$/', 'Probe $1', $VAL['NAME']); + + # Short label + $VAL['NAME'] = preg_replace('/^e.+?t(\d+)$/', 'Probe $1', $VAL['NAME']); + + $ds_name[$count] = "Enclosure $enclosure_id Temperatures"; + + $warnThresh = "INF"; + $critThresh = "INF"; + + if ($VAL['WARN'] != "") { + $warnThresh = $VAL['WARN']; + } + if ($VAL['CRIT'] != "") { + $critThresh = $VAL['CRIT']; + } + + $opt[$count] = "--slope-mode --vertical-label \"Celsius\" --title \"$def_title: Enclosure $enclosure_id Temperatures\" "; + + if(isset($def[$count])){ + $def[$count] .= rrd::def("var$KEY", $VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + else { + $def[$count] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + $def[$count] .= rrd::line1("var$KEY","#".$colors[$e++],$VAL['NAME']) ; + $def[$count] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%6.0lf C"); + } + } +} +else { # --new-- + + # Loop through the performance data + foreach ($this->DS as $KEY=>$VAL) { + + $label = $VAL['LABEL']; + + # TEMPERATURES (AMBIENT) + if (preg_match('/^T/', $label) && preg_match('/Ambient/', $label)) { + + # Temperature unit and vertical label + list ($unit, $vlabel) = tempunit($VAL['UNIT']); + + # Long label + $label = preg_replace('/^T(\d+)_(.+)/', '$2', $label); + $label = preg_replace('/_/', ' ', $label); + + # Short label + $label = preg_replace('/^T(\d+)$/', 'Probe $1', $label); + + $ds_name[$id_temp1] = "Temperatures"; + + $opt[$id_temp1] = "--slope-mode --vertical-label \"$vlabel\" --title \"$def_title: Ambient Temperature\" "; + if(isset($def[$id_temp1])){ + $def[$id_temp1] .= rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + else { + $def[$id_temp1] = rrd::def("var$KEY", $VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + + # fancy graphing + $def[$id_temp1] .= rrd::gradient("var$KEY","#114480", "#1144dc", $label, 10, "50%"); + $def[$id_temp1] .= rrd::gprint("var$KEY",array("LAST", "MAX", "AVERAGE"),"%5.1lf $unit"); + + # insert extra vertical space if we have thresholds + if ($VAL['WARN'] != "" || $VAL['CRIT'] != "") { + $def[$id_temp1] .= "COMMENT:\\s "; + } + + # warning threshold + if ($VAL['WARN'] != "") { + $warnThresh = $VAL['WARN']; + $def[$id_temp1] .= rrd::cdef("warn$KEY", "var$KEY,$warnThresh,GT,var$KEY,UNKN,IF"); + $def[$id_temp1] .= rrd::gradient("warn$KEY","#c4c400", "#ffff00","Above Upper Warning Threshold\: $warnThresh $unit\\l", 10, "50%"); + } + + # critical threshold + if ($VAL['CRIT'] != "") { + $critThresh = $VAL['CRIT']; + $def[$id_temp1] .= rrd::cdef("crit$KEY", "var$KEY,$critThresh,GT,var$KEY,UNKN,IF"); + $def[$id_temp1] .= rrd::gradient("crit$KEY","#800000", "#dc0000","Above Upper Critical Threshold\: $critThresh $unit\\l", 10, "50%"); + } + } + + # TEMPERATURES + if (preg_match('/^T/', $label) && !preg_match('/Ambient/', $label)) { + + # Temperature unit and vertical label + list ($unit, $vlabel) = tempunit($VAL['UNIT']); + + # Long label + $label = preg_replace('/^T(\d+)_(.+)/', '$2', $label); + $label = preg_replace('/_/', ' ', $label); + + # Short label + $label = preg_replace('/^T(\d+)$/', 'Probe $1', $label); + + $ds_name[$id_temp2] = "Temperatures"; + + $opt[$id_temp2] = "--slope-mode --vertical-label \"$vlabel\" --title \"$def_title: Chassis Temperatures\" "; + if (isset($def[$id_temp2])) { + $def[$id_temp2] .= rrd::def("var$KEY", $VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + else { + $def[$id_temp2] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + $def[$id_temp2] .= rrd::line1("var$KEY", "#".$colors[$t++], rrd::cut($label,20) ); + $def[$id_temp2] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"), "%4.1lf $unit"); + } + + # WATTAGE PROBE + if (preg_match('/^W/', $label)) { + + # Long label + $label = preg_replace('/^W(\d+)_(.+)/', '$2', $label); + $label = preg_replace('/_/', ' ', $label); + + # Short label + $label = preg_replace('/^W(\d+)$/', 'Probe $1', $label); + + $ds_name[$id_watt] = "Power Consumption"; + $vlabel = "Watt"; + + $title = $ds_name[$id_watt]; + + $opt[$id_watt] = "--slope-mode --vertical-label \"$vlabel\" --title \"$def_title: $title\" "; + + if(isset($def[$id_watt])){ + $def[$id_watt] .= rrd::def("var$KEY",$VAL['RRDFILE'], $VAL['DS'], "AVERAGE") ; + } + else { + $def[$id_watt] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE") ; + } + + # calculate kWh and BTU + $def[$id_watt] .= "VDEF:tot$KEY=var$KEY,TOTAL "; + # rrd:vdef is broken in pnp4nagios 0.6.13 # $def[$id_watt] .= rrd::vdef("tot$KEY","var$KEY,TOTAL"); + $def[$id_watt] .= rrd::cdef("kwh$KEY","var$KEY,POP,tot$KEY,1000,/,60,/,60,/"); + $def[$id_watt] .= rrd::cdef("btu$KEY","kwh$KEY,3412.3,*"); + + # fancy graphing + $def[$id_watt] .= rrd::gradient("var$KEY","#800000","#dc0000","$label", 10, "50%"); + + # print avg, max and min + $def[$id_watt] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%6.0lf W"); + + # print kWh and BTU for time period + $def[$id_watt] .= rrd::comment("\\s"); + $def[$id_watt] .= rrd::comment(" Total power used in time period\:"); + $def[$id_watt] .= rrd::gprint("kwh$KEY","AVERAGE","%10.2lf kWh\l"); + $def[$id_watt] .= rrd::comment(" "); + $def[$id_watt] .= rrd::gprint("btu$KEY","AVERAGE","%10.2lf BTU\l"); + } + + # AMPERAGE PROBE + if (preg_match('/^A/', $label)) { + + $first = 0; + if ($visited_amp == 0) { + $first = 1; + $visited_amp = 1; + } + + # Long label + $label = preg_replace('/^A(\d+)_(.+)/', '$2', $label); + $label = preg_replace('/_/', ' ', $label); + + # Short label + $label = preg_replace('/^A(\d+)$/', 'Probe $1', $label); + + $ds_name[$id_amp] = "Amperage Probes"; + $vlabel = "Ampere"; + + $title = $ds_name[$id_amp]; + + $opt[$id_amp] = "-X0 --lower-limit 0 --slope-mode --vertical-label \"$vlabel\" --title \"$def_title: $title\" "; + if(isset($def[$id_amp])){ + $def[$id_amp] .= rrd::def("var$KEY",$VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + } + else { + $def[$id_amp] = rrd::def("var$KEY",$VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + } + + $space = strlen($label) < 16 ? str_repeat(' ', 16 - strlen($label)) : ' '; + + $def[$id_amp] .= rrd::cdef("tier$KEY", "var$KEY,10,/"); + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."b7::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."bf::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."c7::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."cf::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."d7::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."df::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."e7::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."ef::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."f7::STACK "; + $def[$id_amp] .= "AREA:tier$KEY#".$colors[$a]."ff:\"$label$space\":STACK "; + $a++; + + if ($first) { + $def[$id_amp] .= rrd::cdef("sum$KEY", "var$KEY,0,+"); + } + else { + $def[$id_amp] .= rrd::cdef("sum$KEY", "sum".($KEY-1).",var$KEY,+"); + } + $def[$id_amp] .= rrd::line1("sum$KEY", "#555555"); + $def[$id_amp] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%6.1lf A last") ; + } + + # VOLTAGE PROBE + if (preg_match('/^V/', $label)) { + + # Long label + $label = preg_replace('/^V(\d+)_(.+)/', '$2', $label); + $label = preg_replace('/_/', ' ', $label); + + # Short label + $label = preg_replace('/^V(\d+)$/', 'Probe $1', $label); + + $ds_name[$id_volt] = "Voltage Probes"; + $vlabel = "Volts"; + + $title = $ds_name[$id_volt]; + + $opt[$id_volt] = "--slope-mode --vertical-label \"$vlabel\" --title \"$def_title: $title\" "; + if(isset($def[$id_volt])){ + $def[$id_volt] .= rrd::def("var$KEY", $VAL['RRDFILE'], $VAL['DS'],"AVERAGE"); + } + else { + $def[$id_volt] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'],"AVERAGE"); + } + $def[$id_volt] .= rrd::line1("var$KEY", "#".$colors[$v++], rrd::cut($label,18) ) ; + $def[$id_volt] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%8.2lf A"); + } + + # FANS (RPMs) + if (preg_match('/^F/', $label)) { + + # Long label + $label = preg_replace('/^F(\d+)_(.+)/', '$2', $label); + $label = preg_replace('/_/', ' ', $label); + + # Short label + $label = preg_replace('/^F(\d+)$/', 'Probe $1', $label); + + $ds_name[$id_fan] = "Fan Probes"; + + $opt[$id_fan] = "-X0 --slope-mode --vertical-label \"RPMs\" --title \"$def_title: Fan Speeds\" "; + if(isset($def[$id_fan])){ + $def[$id_fan] .= rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'], "AVERAGE") ; + } + else { + $def[$id_fan] = rrd::def("var$KEY",$VAL['RRDFILE'],$VAL['DS'], "AVERAGE") ; + } + $def[$id_fan] .= rrd::line1("var$KEY", "#".$colors[$f++], rrd::cut($label,18) ) ; + $def[$id_fan] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"), "%6.0lf RPM"); + } + + # ENCLOSURE TEMPERATURES (Celsius) + if (preg_match('/^E(?P.+?)_t(emp_)?(?P\d+)/', $label, $matches)) { + + $this_id = $matches['encl']; + $probe_index = $matches['probe']; + + if ($enclosure_id != $this_id) { + $e = 0; + $id_enc++; + $enclosure_id = $this_id; + } + + # Label + $label = "Probe $probe_index"; + + $ds_name[$id_enc] = "Enclosure $enclosure_id Temperatures"; + + $opt[$id_enc] = "--slope-mode --vertical-label \"Celsius\" --title \"$def_title: Enclosure $enclosure_id Temperatures\" "; + + if(isset($def[$id_enc])){ + $def[$id_enc] .= rrd::def("var$KEY", $VAL['RRDFILE'],$VAL['DS'], "AVERAGE") ; + } + else { + $def[$id_enc] = rrd::def("var$KEY", $VAL['RRDFILE'],$VAL['DS'], "AVERAGE") ; + } + $def[$id_enc] .= rrd::line1("var$KEY", "#".$colors[$e++], rrd::cut($label, 14) ); + $def[$id_enc] .= rrd::gprint("var$KEY", array("LAST", "MAX", "AVERAGE"),"%6.1lf C"); + } + } +} + +?> diff --git a/share/pnp/templates.dist/check_oracle_connection-time.php b/share/pnp/templates.dist/check_oracle_connection-time.php new file mode 100644 index 0000000..a96a383 --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_connection-time.php @@ -0,0 +1,15 @@ + diff --git a/share/pnp/templates.dist/check_oracle_health.php b/share/pnp/templates.dist/check_oracle_health.php new file mode 100644 index 0000000..fd09e98 --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_health.php @@ -0,0 +1,34 @@ + diff --git a/share/pnp/templates.dist/check_oracle_health_connection-time.php b/share/pnp/templates.dist/check_oracle_health_connection-time.php new file mode 100644 index 0000000..b1438d2 --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_health_connection-time.php @@ -0,0 +1,15 @@ + diff --git a/share/pnp/templates.dist/check_oracle_health_pga-in-memory-sort-ratio.php b/share/pnp/templates.dist/check_oracle_health_pga-in-memory-sort-ratio.php new file mode 100644 index 0000000..a664949 --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_health_pga-in-memory-sort-ratio.php @@ -0,0 +1,15 @@ + diff --git a/share/pnp/templates.dist/check_oracle_health_redo-io-traffic.php b/share/pnp/templates.dist/check_oracle_health_redo-io-traffic.php new file mode 100644 index 0000000..7d2fd53 --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_health_redo-io-traffic.php @@ -0,0 +1,15 @@ + diff --git a/share/pnp/templates.dist/check_oracle_health_switch-interval.php b/share/pnp/templates.dist/check_oracle_health_switch-interval.php new file mode 100644 index 0000000..c0e6a56 --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_health_switch-interval.php @@ -0,0 +1,15 @@ + diff --git a/share/pnp/templates.dist/check_oracle_health_tablespace-usage.php b/share/pnp/templates.dist/check_oracle_health_tablespace-usage.php new file mode 100644 index 0000000..acefe8f --- /dev/null +++ b/share/pnp/templates.dist/check_oracle_health_tablespace-usage.php @@ -0,0 +1,33 @@ + diff --git a/share/pnp/templates.dist/check_ping.php b/share/pnp/templates.dist/check_ping.php new file mode 100644 index 0000000..09c8458 --- /dev/null +++ b/share/pnp/templates.dist/check_ping.php @@ -0,0 +1,44 @@ + diff --git a/share/pnp/templates.dist/check_ping_tick.php b/share/pnp/templates.dist/check_ping_tick.php new file mode 100644 index 0000000..865479f --- /dev/null +++ b/share/pnp/templates.dist/check_ping_tick.php @@ -0,0 +1,47 @@ + diff --git a/share/pnp/templates.dist/check_pnp_rrds.php b/share/pnp/templates.dist/check_pnp_rrds.php new file mode 100644 index 0000000..4ccc6ca --- /dev/null +++ b/share/pnp/templates.dist/check_pnp_rrds.php @@ -0,0 +1,27 @@ + diff --git a/share/pnp/templates.dist/check_smtp.php b/share/pnp/templates.dist/check_smtp.php new file mode 120000 index 0000000..5093505 --- /dev/null +++ b/share/pnp/templates.dist/check_smtp.php @@ -0,0 +1 @@ +response.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_snmp_int-bits.php b/share/pnp/templates.dist/check_snmp_int-bits.php new file mode 100644 index 0000000..325e9b8 --- /dev/null +++ b/share/pnp/templates.dist/check_snmp_int-bits.php @@ -0,0 +1,24 @@ +MACRO['TIMET'] != ""){ + $def[1] .= "VRULE:".$this->MACRO['TIMET']."#000000:\"Last Service Check \\n\" "; +} +?> diff --git a/share/pnp/templates.dist/check_snmp_int.php b/share/pnp/templates.dist/check_snmp_int.php new file mode 100644 index 0000000..59c9b6f --- /dev/null +++ b/share/pnp/templates.dist/check_snmp_int.php @@ -0,0 +1,20 @@ +MACRO['TIMET'] != ""){ + $def[1] .= "VRULE:".$this->MACRO['TIMET']."#000000:\"Last Service Check \\n\" "; +} +?> diff --git a/share/pnp/templates.dist/check_swap.php b/share/pnp/templates.dist/check_swap.php new file mode 100644 index 0000000..2ab5e38 --- /dev/null +++ b/share/pnp/templates.dist/check_swap.php @@ -0,0 +1,26 @@ + diff --git a/share/pnp/templates.dist/check_tcp.php b/share/pnp/templates.dist/check_tcp.php new file mode 120000 index 0000000..5093505 --- /dev/null +++ b/share/pnp/templates.dist/check_tcp.php @@ -0,0 +1 @@ +response.php \ No newline at end of file diff --git a/share/pnp/templates.dist/check_users.php b/share/pnp/templates.dist/check_users.php new file mode 100644 index 0000000..9fe878d --- /dev/null +++ b/share/pnp/templates.dist/check_users.php @@ -0,0 +1,24 @@ + diff --git a/share/pnp/templates.dist/default.php b/share/pnp/templates.dist/default.php new file mode 100644 index 0000000..6fdf38c --- /dev/null +++ b/share/pnp/templates.dist/default.php @@ -0,0 +1,92 @@ +DS as $KEY=>$VAL) { + + $maximum = ""; + $minimum = ""; + $critical = ""; + $crit_min = ""; + $crit_max = ""; + $warning = ""; + $warn_max = ""; + $warn_min = ""; + $vlabel = " "; + $lower = ""; + $upper = ""; + + if ($VAL['WARN'] != "" && is_numeric($VAL['WARN']) ){ + $warning = $VAL['WARN']; + } + if ($VAL['WARN_MAX'] != "" && is_numeric($VAL['WARN_MAX']) ) { + $warn_max = $VAL['WARN_MAX']; + } + if ( $VAL['WARN_MIN'] != "" && is_numeric($VAL['WARN_MIN']) ) { + $warn_min = $VAL['WARN_MIN']; + } + if ( $VAL['CRIT'] != "" && is_numeric($VAL['CRIT']) ) { + $critical = $VAL['CRIT']; + } + if ( $VAL['CRIT_MAX'] != "" && is_numeric($VAL['CRIT_MAX']) ) { + $crit_max = $VAL['CRIT_MAX']; + } + if ( $VAL['CRIT_MIN'] != "" && is_numeric($VAL['CRIT_MIN']) ) { + $crit_min = $VAL['CRIT_MIN']; + } + if ( $VAL['MIN'] != "" && is_numeric($VAL['MIN']) ) { + $lower = " --lower=" . $VAL['MIN']; + $minimum = $VAL['MIN']; + } + if ( $VAL['MAX'] != "" && is_numeric($VAL['MAX']) ) { + $maximum = $VAL['MAX']; + } + if ($VAL['UNIT'] == "%%") { + $vlabel = "%"; + $upper = " --upper=101 "; + $lower = " --lower=0 "; + } + else { + $vlabel = $VAL['UNIT']; + } + + $opt[$KEY] = '--vertical-label "' . $vlabel . '" --title "' . $this->MACRO['DISP_HOSTNAME'] . ' / ' . $this->MACRO['DISP_SERVICEDESC'] . '"' . $upper . $lower; + $ds_name[$KEY] = $VAL['LABEL']; + $def[$KEY] = rrd::def ("var1", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[$KEY] .= rrd::gradient("var1", "3152A5", "BDC6DE", rrd::cut($VAL['NAME'],16), 20); + $def[$KEY] .= rrd::line1 ("var1", $_LINE ); + $def[$KEY] .= rrd::gprint ("var1", array("LAST","MAX","AVERAGE"), "%3.4lf %S".$VAL['UNIT']); + if ($warning != "") { + $def[$KEY] .= rrd::hrule($warning, $_WARNRULE, "Warning $warning \\n"); + } + if ($warn_min != "") { + $def[$KEY] .= rrd::hrule($warn_min, $_WARNRULE, "Warning (min) $warn_min \\n"); + } + if ($warn_max != "") { + $def[$KEY] .= rrd::hrule($warn_max, $_WARNRULE, "Warning (max) $warn_max \\n"); + } + if ($critical != "") { + $def[$KEY] .= rrd::hrule($critical, $_CRITRULE, "Critical $critical \\n"); + } + if ($crit_min != "") { + $def[$KEY] .= rrd::hrule($crit_min, $_CRITRULE, "Critical (min) $crit_min \\n"); + } + if ($crit_max != "") { + $def[$KEY] .= rrd::hrule($crit_max, $_CRITRULE, "Critical (max) $crit_max \\n"); + } + $def[$KEY] .= rrd::comment("Default Template\\r"); + $def[$KEY] .= rrd::comment("Command " . $VAL['TEMPLATE'] . "\\r"); +} +?> diff --git a/share/pnp/templates.dist/integer.php b/share/pnp/templates.dist/integer.php new file mode 100644 index 0000000..f4b73de --- /dev/null +++ b/share/pnp/templates.dist/integer.php @@ -0,0 +1,26 @@ + $VAL ){ + $opt[1] .= "--alt-y-grid -l 0 --vertical-label \"$LABEL[$KEY]\" --title \"$LABEL[$KEY]\" "; + $def[1] .= "DEF:var_float$KEY=$RRDFILE[$KEY]:$DS[$KEY]:MAX " ; + $def[1] .= "CDEF:var$KEY=var_float$KEY,FLOOR " ; + $def[1] .= "LINE1:var$KEY$colors[$KEY]:\"$LABEL[$KEY]\" " ; + + if ($WARN[$KEY] != "") { + $def[1] .= "HRULE:$WARN[$KEY]#FFFF00 "; + } + if ($CRIT[$KEY] != "") { + $def[1] .= "HRULE:$CRIT[$KEY]#FF0000 "; + } + + $def[1] .= "GPRINT:var$KEY:LAST:\"%.0lf $UNIT[$KEY] LAST \" "; + $def[1] .= "GPRINT:var$KEY:MAX:\"%.0lf $UNIT[$KEY] MAX \" "; + $def[1] .= "GPRINT:var$KEY:AVERAGE:\"%.0lf $UNIT[$KEY] AVERAGE \\n\" "; +} +?> diff --git a/share/pnp/templates.dist/nagiostats.php b/share/pnp/templates.dist/nagiostats.php new file mode 100644 index 0000000..3a3f64d --- /dev/null +++ b/share/pnp/templates.dist/nagiostats.php @@ -0,0 +1,62 @@ +DS as $KEY=>$VAL) { + if(preg_match('/(.*)LAT$/', $VAL['NAME'], $matches)){ + $i++; + $label = ucfirst(strtolower($matches[1])); + $def[0] .= rrd::def ("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[0] .= rrd::cdef ("var_sec$KEY", "var$KEY,1000,/"); + $def[0] .= rrd::line1 ("var_sec$KEY", rrd::color($i), rrd::cut($label,10) ); + $def[0] .= rrd::gprint ("var_sec$KEY", array("LAST","MAX","AVERAGE"), "%8.2lf"); + } +} +$opt[1] = '--title "Service Stats"'; +$ds_name[1] = "Service Stats"; +$def[1] = ""; +$i = 0; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match('/^NUMSVC(.*)$/', $VAL['NAME'], $matches)){ + $i++; + $label = ucfirst(strtolower($matches[1])); + $def[1] .= rrd::def ("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[1] .= rrd::line1 ("var$KEY", rrd::color($i), rrd::cut($label,10) ); + $def[1] .= rrd::gprint ("var$KEY", array("LAST","MAX","AVERAGE"), "%8.2lf"); + } +} +$opt[2] = '--title "Host Stats"'; +$ds_name[2] = "Host Stats"; +$def[2] = ""; +$i = 0; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match('/^NUMHST(.*)$/', $VAL['NAME'], $matches)){ + $i++; + $label = ucfirst(strtolower($matches[1])); + $def[2] .= rrd::def ("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[2] .= rrd::line1 ("var$KEY", rrd::color($i), rrd::cut($label,10) ); + $def[2] .= rrd::gprint ("var$KEY", array("LAST","MAX","AVERAGE"), "%8.2lf"); + } +} +$opt[3] = '--title "Check Execution Time"'; +$ds_name[3] = "Execution Time"; +$def[3] = ""; +$i = 0; +foreach ($this->DS as $KEY=>$VAL) { + if(preg_match('/(.*)EXT$/', $VAL['NAME'], $matches)){ + $i++; + $label = ucfirst(strtolower($matches[1])); + $def[3] .= rrd::def ("var$KEY", $VAL['RRDFILE'], $VAL['DS'], "AVERAGE"); + $def[3] .= rrd::cdef ("var_sec$KEY", "var$KEY,1000,/"); + $def[3] .= rrd::line1 ("var_sec$KEY", rrd::color($i), rrd::cut($label,10) ); + $def[3] .= rrd::gprint ("var_sec$KEY", array("LAST","MAX","AVERAGE"), "%8.2lf"); + } +} +?> diff --git a/share/pnp/templates.dist/pnp-runtime.php b/share/pnp/templates.dist/pnp-runtime.php new file mode 100644 index 0000000..21c4ae3 --- /dev/null +++ b/share/pnp/templates.dist/pnp-runtime.php @@ -0,0 +1,42 @@ +STRUCT['TIMERANGE']['end']; +$ds_name[1] = "Runtime"; +$def[1] = rrd::def("var1", $RRDFILE[1], $DS[1], "AVERAGE") ; +$def[1] .= rrd::cdef("t_var1","var1,14400,TREND"); +if ($WARN[1] != "") { + $def[1] .= rrd::hrule($WARN[1], "#FFFF00"); +} +if ($CRIT[1] != "") { + $def[1] .= rrd::hrule($CRIT[1], "#FF0000"); +} +$def[1] .= rrd::gradient("var1", "ffffff", "#33cccc", rrd::cut("Runtime",10)); +$def[1] .= rrd::line1("var1","#339999"); +$def[1] .= rrd::gprint("var1", array('LAST', 'MAX', 'AVERAGE'), "%6.2lf$UNIT[1]") ; +$def[1] .= rrd::line1("t_var1", "#ff9999", rrd::cut("4h trend",10)); +$def[1] .= rrd::gprint("t_var1", array('LAST', 'MAX', 'AVERAGE'), "%6.2lf$UNIT[1]") ; + +# +# Lines processed and RRD errors +# +$opt[2] = "--vertical-label \"Counter\" --title \"Number of updates\" "; +# +# +# +$ds_name[2] = "Errors and updates"; +$def[2] = ''; +for($i=2; $i <= sizeof($DS); $i++) { +$def[2] .= rrd::def("var$i", $RRDFILE[$i], $DS[$i] , "AVERAGE") ; +$def[2] .= rrd::line1("var$i", rrd::color($i), rrd::cut(ucfirst($LABEL[$i]),12) ); +$def[2] .= rrd::gprint("var$i", array('LAST', 'MAX', 'AVERAGE'), "%4.0lf$UNIT[$i]"); +} +?> diff --git a/share/pnp/templates.dist/response.php b/share/pnp/templates.dist/response.php new file mode 100644 index 0000000..af9dd99 --- /dev/null +++ b/share/pnp/templates.dist/response.php @@ -0,0 +1,15 @@ + diff --git a/share/pnp/templates.special/README b/share/pnp/templates.special/README new file mode 100644 index 0000000..e74365a --- /dev/null +++ b/share/pnp/templates.special/README @@ -0,0 +1 @@ +Place your special Templates here! diff --git a/share/pnp/templates.special/advanced_loop.php-sample b/share/pnp/templates.special/advanced_loop.php-sample new file mode 100644 index 0000000..a64fb22 --- /dev/null +++ b/share/pnp/templates.special/advanced_loop.php-sample @@ -0,0 +1,34 @@ +MACRO['TITLE'] = "Interface Traffic for ETH0"; +$this->MACRO['COMMENT'] = "Inbound Traffc for all Cloud Nodes"; +# +# Get a List of Services by regex +# Option 1 = 'Host Regex' +# Option 2 = 'Service Regex' +# +$services = $this->tplGetServices("node","eth0"); +# +# The Datasource Name for Graph 0 +$ds_name[0] = "RTA Times"; +$opt[0] = "--title \"Stacked RTA Times\""; +$def[0] = ""; +# +# Iterate through the list of hosts + +foreach($services as $key=>$val){ + # + # get the data for a given Host/Service + $a = $this->tplGetData($val['host'],$val['service']); + # + # Throw an exception to debug the content of $a + # Just to get Infos about the Array Structure + # + #throw new Kohana_exception(print_r($a,TRUE)); + $def[0] .= rrd::def("a$key" ,$a['DS'][0]['RRDFILE'], $a['DS'][0]['DS'], "AVERAGE"); + $def[0] .= rrd::area("a$key", rrd::color($key), $a['MACRO']['HOSTNAME'], "STACK"); + $def[0] .= rrd::gprint("a$key", array("MIN", "MAX", "LAST"), "%.2lf%s"); +} +?> diff --git a/share/pnp/templates.special/loop.php-sample b/share/pnp/templates.special/loop.php-sample new file mode 100644 index 0000000..103ba1c --- /dev/null +++ b/share/pnp/templates.special/loop.php-sample @@ -0,0 +1,28 @@ +MACRO['TITLE'] = "The Title"; +$this->MACRO['COMMENT'] = "A Comment"; +# +# Define the Service we want to graph +$service = '_HOST_'; +# +# Define a List of Host +$hosts = array('localhost','node1','node2'); +# +# The Datasource Name for Graph 1 ( index 0 ) +$ds_name[0] = "RTA Times"; +$opt[0] = "--title \"Stacked RTA Times\""; +$def[0] = ""; +# +# Iterate through the list of hosts +foreach($hosts as $key=>$host){ + # + # get the data for a given Host/Service + $a = $this->tplGetData($host,$service); + $def[0] .= rrd::def("a$key" ,$a['DS'][0]['RRDFILE'], $a['DS'][0]['DS'], "AVERAGE"); + $def[0] .= rrd::area("a$key", rrd::color($key), $a['MACRO']['HOSTNAME'], "STACK"); + $def[0] .= rrd::gprint("a$key", array("MIN", "MAX", "LAST"), "%.2lf%s"); +} +?> diff --git a/share/pnp/templates.special/static.php-sample b/share/pnp/templates.special/static.php-sample new file mode 100644 index 0000000..30aac5e --- /dev/null +++ b/share/pnp/templates.special/static.php-sample @@ -0,0 +1,19 @@ +MACRO['TITLE'] = "All Ping Times for Cluster Nodes"; +$this->MACRO['COMMENT'] = "This is a comment"; + +# +# The Name of this Datasource (ds) +$ds_name[0] = "RTA Times"; + +$opt[0] = "--title \"Graph Title\" "; +$def[0] = "DEF:var1=/usr/local/pnp4nagios/var/perfdata/node1/_HOST_.rrd:1:AVERAGE "; +$def[0] .= "DEF:var2=/usr/local/pnp4nagios/var/perfdata/node2/_HOST_.rrd:1:AVERAGE "; +$def[0] .= "LINE1:var1".rrd::color(1).":\"Localhost \\n\" "; +$def[0] .= "LINE1:var2".rrd::color(2).":\"Node1 \\n\" "; +?> diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..b4323b4 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,137 @@ +############################ +# Makefile for PNP +# +# Last Modified: 11-17-2008 +############################ + + +# Source code directories +SRC_INCLUDE=../include + +CC=@CC@ +CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE + +# Compiler flags for use with Valgrind +#CFLAGS=-O0 -g -DHAVE_CONFIG_H -DNSCORE + +# Compiler flags for optimization (overrides default) +#CFLAGS=-O3 -Wall -fno-strict-aliasing -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -DHAVE_CONFIG_H -DNSCORE + +# Compiler flags for optimization (complements default) +#CFLAGS_WARN=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs +#CFLAGS_DEBUG=-ggdb3 -g3 +#CFLAGS_GPROF=-pg +#CFLAGS+=$(CFLAGS_WARN) $(CFLAGS_DEBUG) $(CFLAGS_GPROF) + +LDFLAGS=@LDFLAGS@ +LIBS=@LIBS@ + +MOD_LDFLAGS=@MOD_LDFLAGS@ +MOD_CFLAGS=@MOD_CFLAGS@ + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +LOGDIR=@localstatedir@ +CFGDIR=@sysconfdir@ +BINDIR=@bindir@ +LIBEXECDIR=@libexecdir@ +LIBDIR=@libdir@ +CGIDIR=@sbindir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +STRIP=@STRIP@ +DATAROOTDIR=@datarootdir@ +PERFDATA_DIR=@PERFDATA_DIR@ +PERFDATA_SPOOL_DIR=@PERFDATA_SPOOL_DIR@ + +MATHLIBS=-lm + +CP=@CP@ + +OBJS=pnpsender.o npcd.o config.o + +NPCDOBJS=utils.o config.o logging.o +NPCDHEAD=$(SRC_INCLUDE)/pnp.h $(SRC_INCLUDE)/config.h + +OBJDEPS= + +all: npcd npcdmod.o + +# Required Objects + +logging: logging.c $(NPCDHEAD) + $(CC) $(CFLAGS) -o $@ logging.c + +config: config.c $(NPCDHEAD) + $(CC) $(CFLAGS) -o $@ config.c + +utils: utils.c $(NPCDHEAD) + $(CC) $(CFLAGS) -o $@ utils.c + +############################### +# +# PNPSENDER +# +############################### + +pnpsender: pnpsender.c + $(CC) $(CFLAGS) -o $@ pnpsender.c + +############################### +# +# NPCD +# +############################### +npcd: npcd.c $(NPCDOBJS) $(NPCDHEAD) + $(CC) $(CFLAGS) -o $@ npcd.c $(NPCDOBJS) -lpthread + +############################### +# +# NPCDMOD +# +############################### +npcdmod.o: npcdmod.c + $(CC) $(MOD_CFLAGS) $(CFLAGS) -o npcdmod.o npcdmod.c $(MOD_LDFLAGS) $(LDFLAGS) $(LIBS) -fPIC + +############################### +# +# Cleanups +# +############################### + +clean: + -rm -f pnpsender *.o + -rm -f npcd *.o + -rm -f *~ *.*~ + +distclean: clean + -rm -f Makefile + +devclean: distclean + + +############################### +# +# Install +# +################################ + +install: + $(MAKE) install-basic + $(MAKE) strip-post-install + +install-unstripped: + $(MAKE) install-basic + +install-basic: + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR) + $(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(PERFDATA_DIR) + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(PERFDATA_SPOOL_DIR) + $(INSTALL) -m 754 $(INSTALL_OPTS) @npcd_name@ $(DESTDIR)$(BINDIR) + $(INSTALL) -m 754 $(INSTALL_OPTS) npcdmod.o $(DESTDIR)$(LIBDIR) + +strip-post-install: + $(STRIP) $(DESTDIR)$(BINDIR)/@npcd_name@ + $(STRIP) $(DESTDIR)$(LIBDIR)/npcdmod.o diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..08183a8 --- /dev/null +++ b/src/config.c @@ -0,0 +1,584 @@ +// Copyright (C) 2007-2009 Hendrik Baecker +// Inspired by Ethan Galstad +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "../include/config.h" +#include "../include/pnp.h" + +#include + +extern void pnp_strip(char *); + +extern char *macro_x[CONFIG_OPT_COUNT]; +extern char *log_file, *log_type; +extern char *command, *command_args, *user, *group, *directory, *pidfile; +extern int daemon_mode; +extern int sighup_detected; +extern int use_syslog; +extern int loglevel; +extern int max_logfile_size; +extern int max_threads; +extern int use_load_threshold; +extern int sleeptime; +extern int identmyself; +extern double load_threshold; + +void process_configfile(char *config_file) { + FILE *fh_config_file = NULL; + char current_config_line[MAX_BUFFER_SIZE]; + char error_msg[MAX_BUFFER_SIZE]; + char variable[MAX_VARIABLE_LENGTH]; + char value[MAX_VALUE_LENGTH]; + // char *input = NULL; + char *temp; + extern int loglevel; + + int error = FALSE; + // int warning = FALSE; + int line_number = 0; + + fh_config_file = fopen(config_file, (const char*) "r"); + + /* check if we can not open that file */ + if (fh_config_file == NULL) { + snprintf(error_msg, MAX_BUFFER_SIZE, + "ERROR - Could not open config file - %s", strerror(errno)); + error = TRUE; + } + + /* ok - parsing the config file line by line */ + else { + while (feof(fh_config_file) == 0) { + line_number++; + temp = fgets(current_config_line, 1024, fh_config_file); + temp = NULL; + if (current_config_line == NULL) { + printf("Error reading config\n"); + exit(1); + } + + if (current_config_line[0] == '#' || current_config_line[0] == '\n') + continue; + + pnp_strip(current_config_line); + + temp = strtok(current_config_line, "="); + pnp_strip(temp); + + /* if there is no variable name, return error */ + if (temp == NULL) { + strcpy(error_msg, "No variable found - exiting"); + error = TRUE; + break; + } + + /* else the variable is good */ + strncpy(variable, temp, sizeof(variable)); + variable[sizeof(variable) - 1] = '\x0'; + + /* get the value */ + temp = strtok(NULL, "\n"); + pnp_strip(temp); + /* if no value exists, return error */ + if (temp == NULL) { + strcpy(error_msg, "NULL value"); + error = TRUE; + break; + } + + /* else the value is good */ + strncpy(value, temp, sizeof(value)); + value[sizeof(value) - 1] = '\x0'; + pnp_strip(value); + + /* process the variable/value */ + + /* log_file directive */ + if (!strcmp(variable, "log_file")) { + if (strlen(value) > MAX_FILENAME_LENGTH - 1) { + strcpy(error_msg, "Log file is too long"); + error = TRUE; + break; + } + + if (log_file != NULL) + free(log_file); + + log_file = (char *) strdup(value); + pnp_strip(log_file); + + /* save the macro */ + if (macro_x[CONFIG_OPT_LOGFILE] != NULL) + free(macro_x[CONFIG_OPT_LOGFILE]); + + macro_x[CONFIG_OPT_LOGFILE] = (char *) strdup(log_file); + + if (macro_x[CONFIG_OPT_LOGFILE] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro logfile"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_LOGFILE]); + } + + /* log_file_size directive */ + else if (!strcmp(variable, "max_logfile_size")) { + if (strlen(value) == 1) { + if (isdigit((int)value[strlen(value)-1]) == FALSE) { + strcpy(error_msg, "log_file_size should be an integer"); + error = TRUE; + break; + } + } + + /* save the macro */ + if (macro_x[CONFIG_OPT_LOGFILESIZE] != NULL) + free(macro_x[CONFIG_OPT_LOGFILESIZE]); + + macro_x[CONFIG_OPT_LOGFILESIZE] = (char *) strdup(value); + max_logfile_size = atoi(value); + if (macro_x[CONFIG_OPT_LOGFILESIZE] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro logfilesize"); + error = TRUE; + break; + } + + pnp_strip(macro_x[CONFIG_OPT_LOGFILESIZE]); + } + + /* log_level directive */ + else if (!strcmp(variable, "log_level")) { + if (strlen(value) == 1) { + if (isdigit((int)value[strlen(value)-1]) == FALSE) { + strcpy(error_msg, "log_level should be an integer"); + error = TRUE; + break; + } + } + + /* save the macro */ + if (macro_x[CONFIG_OPT_LOGLEVEL] != NULL) + free(macro_x[CONFIG_OPT_LOGLEVEL]); + + macro_x[CONFIG_OPT_LOGLEVEL] = (char *) strdup(value); + loglevel = atoi(value); + if (macro_x[CONFIG_OPT_LOGLEVEL] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro loglevel"); + error = TRUE; + break; + } + + pnp_strip(macro_x[CONFIG_OPT_LOGLEVEL]); + } + + /* log_type directive */ + else if (!strcmp(variable, "log_type")) { + + if (log_type != NULL) + free(log_type); + + log_type = (char *) strdup(value); + pnp_strip(log_type); + + /* save the macro */ + if (macro_x[CONFIG_OPT_LOGTYPE] != NULL) + free(macro_x[CONFIG_OPT_LOGTYPE]); + + macro_x[CONFIG_OPT_LOGTYPE] = (char *) strdup(log_type); + + if (macro_x[CONFIG_OPT_LOGTYPE] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro log_type"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_LOGTYPE]); + + if (strcmp(macro_x[CONFIG_OPT_LOGTYPE], "syslog") == 0) + use_syslog = TRUE; + else if (strcmp(macro_x[CONFIG_OPT_LOGTYPE], "file") == 0) + use_syslog = FALSE; + else { + strcpy(error_msg, + "Please define \"syslog\" or \"file\" as log_type!"); + error = TRUE; + break; + } + } + + else if (!strcmp(variable, "perfdata_spool_dir")) { + if (strlen(value) > MAX_FILENAME_LENGTH - 1) { + strcpy(error_msg, "Perfdata Spool Path is too long"); + error = TRUE; + break; + } + + /* save the macro */ + if (macro_x[CONFIG_OPT_SCANDIR] != NULL) + free(macro_x[CONFIG_OPT_SCANDIR]); + + macro_x[CONFIG_OPT_SCANDIR] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_SCANDIR] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro Scandir"); + error = TRUE; + break; + } + + pnp_strip(macro_x[CONFIG_OPT_LOGFILE]); + } + + else if (!strcmp(variable, "perfdata_file")) + ; + + else if (!strcmp(variable, "perfdata_spool_filename")) + ; + + else if (!strcmp(variable, "perfdata_file_processing_interval")) + ; + + else if (!strcmp(variable, "user")) { + + /* save the macro */ + if (macro_x[CONFIG_OPT_USER] != NULL) + free(macro_x[CONFIG_OPT_USER]); + + macro_x[CONFIG_OPT_USER] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_USER] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro user"); + error = TRUE; + break; + } + + pnp_strip(macro_x[CONFIG_OPT_USER]); + + } + + else if (!strcmp(variable, "group")) { + + /* save the macro */ + if (macro_x[CONFIG_OPT_GROUP] != NULL) + free(macro_x[CONFIG_OPT_GROUP]); + + macro_x[CONFIG_OPT_GROUP] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_GROUP] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro group"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_GROUP]); + } + + else if (!strcmp(variable, "perfdata_file_run_cmd")) { + + /* save the macro */ + if (macro_x[CONFIG_OPT_RUNCMD] != NULL) + free(macro_x[CONFIG_OPT_RUNCMD]); + + macro_x[CONFIG_OPT_RUNCMD] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_RUNCMD] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro runcmd"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_RUNCMD]); + } + + else if (!strcmp(variable, "perfdata_file_run_cmd_args")) { + + /* save the macro */ + if (macro_x[CONFIG_OPT_RUNCMD_ARG] != NULL) + free(macro_x[CONFIG_OPT_RUNCMD_ARG]); + + macro_x[CONFIG_OPT_RUNCMD_ARG] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_RUNCMD_ARG] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro runcmd_arg"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_RUNCMD_ARG]); + } + + else if (!strcmp(variable, "npcd_max_threads")) { + + if (strlen(value) == 1) { + if (isdigit((int)value[strlen(value)-1]) == FALSE) { + strcpy(error_msg, + "npcd_max_threads should be an integer"); + error = TRUE; + break; + } + } + /* save the macro */ + if (macro_x[CONFIG_OPT_MAXTHREADS] != NULL) + free(macro_x[CONFIG_OPT_MAXTHREADS]); + + macro_x[CONFIG_OPT_MAXTHREADS] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_MAXTHREADS] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro MAXTHREADS"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_MAXTHREADS]); + } + + else if (!strcmp(variable, "use_load_threshold")) { + strcpy(error_msg, + "The option 'use_load_threshold' is obsolete."); + printf( + "An Warning occured while reading your config on line %d. Message was: \"%s\"\n", + line_number, error_msg); + } else if (!strcmp(variable, "load_threshold")) { + + /* save the macro */ + if (macro_x[CONFIG_OPT_LOAD] != NULL) + free(macro_x[CONFIG_OPT_LOAD]); + + macro_x[CONFIG_OPT_LOAD] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_LOAD] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro LOAD"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_LOAD]); + } + + else if (!strcmp(variable, "pid_file")) { + FILE *fppid; + /* save the macro */ + if (macro_x[CONFIG_OPT_PIDFILE] != NULL) + free(macro_x[CONFIG_OPT_PIDFILE]); + + macro_x[CONFIG_OPT_PIDFILE] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_PIDFILE] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro PIDFILE"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_PIDFILE]); + + if (daemon_mode == TRUE && sighup_detected == FALSE) { + fppid = fopen(macro_x[CONFIG_OPT_PIDFILE], "w"); + if (fppid == NULL) { + snprintf(error_msg, sizeof(error_msg), + "Could not open pidfile '%s': %s", + macro_x[CONFIG_OPT_PIDFILE], strerror(errno)); + error = TRUE; + } else { + fclose(fppid); + } + } + } + + else if (!strcmp(variable, "sleep_time")) { + + if (strlen(value) == 1) { + if (isdigit((int)value[strlen(value)-1]) == FALSE) { + strcpy(error_msg, "sleep_time should be an integer"); + error = TRUE; + break; + } + } + + /* save the macro */ + if (macro_x[CONFIG_OPT_SLEEPTIME] != NULL) + free(macro_x[CONFIG_OPT_SLEEPTIME]); + + macro_x[CONFIG_OPT_SLEEPTIME] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_MAXTHREADS] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro SLEEPTIME"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_SLEEPTIME]); + } + + else if (!strcmp(variable, "identify_npcd")) { + + if (strlen(value) == 1) { + if (isdigit((int)value[strlen(value)-1]) == FALSE) { + strcpy(error_msg, "identify_npcd should be an integer"); + error = TRUE; + break; + } + } + /* save the macro */ + if (macro_x[CONFIG_OPT_IDENTMYSELF] != NULL) + free(macro_x[CONFIG_OPT_IDENTMYSELF]); + + macro_x[CONFIG_OPT_IDENTMYSELF] = (char *) strdup(value); + + if (macro_x[CONFIG_OPT_IDENTMYSELF] == NULL) { + strcpy(error_msg, + "Could not allocate memory for macro IDENTMYSELF"); + error = TRUE; + break; + } + pnp_strip(macro_x[CONFIG_OPT_IDENTMYSELF]); + } + + else { + strcpy(error_msg, + "There is a config directive that I don't know"); + error = TRUE; + break; + } + } + } + + if (fh_config_file != NULL) + fclose(fh_config_file); + + if (error) { + printf( + "An Error occured while reading your config on line %d\nMessage was: \"%s\"\n", + line_number, error_msg); + exit(EXIT_FAILURE); + } +} + +/************************************ + * + * check if we have all we need + * + * **********************************/ +int check_needed_config_options() { + /* Needed config options are: + * logtype + * if syslog: ignore logfile + * if file: logfile is needed + * command + * if command args: command is needed + */ + char error_msg[MAX_BUFFER_SIZE]; + int error = FALSE; + int warning = FALSE; + + if (macro_x[CONFIG_OPT_LOGTYPE] == NULL) { + strcpy(error_msg, "You have to define a logtype."); + error = TRUE; + } else if ((strcmp(macro_x[CONFIG_OPT_LOGTYPE], "file") == 0) + && (macro_x[CONFIG_OPT_LOGFILE] == NULL)) { + strcpy(error_msg, + "You have to define a logfile if you wish to use a file for logging."); + error = TRUE; + } else if (macro_x[CONFIG_OPT_RUNCMD_ARG] != NULL + && macro_x[CONFIG_OPT_RUNCMD] == NULL) { + strcpy(error_msg, "There should no argument to no command."); + error = TRUE; + } else if (macro_x[CONFIG_OPT_RUNCMD] == NULL) { + strcpy(error_msg, + "There is nothing I can do - please give me a 'perfdata_file_run_cmd'."); + error = TRUE; + } else if (macro_x[CONFIG_OPT_SCANDIR] == NULL) { + strcpy(error_msg, + "You should define a performance data spool directory."); + warning = TRUE; + } + if (error) { + printf("ERROR - %s\n", error_msg); + return ERROR; + } else if (warning) { + printf("WARNING - %s\n", error_msg); + return OK; + } else + return OK; +} + +/* Prepare config file variables to program vars */ +int prepare_vars() { + if (macro_x[CONFIG_OPT_MAXTHREADS] != NULL) { + max_threads = atoi(macro_x[CONFIG_OPT_MAXTHREADS]); + } else + max_threads = 5; + + if (macro_x[CONFIG_OPT_LOAD] != NULL) { + load_threshold = strtod(macro_x[CONFIG_OPT_LOAD], NULL); + if (load_threshold != 0.0) + use_load_threshold = TRUE; + } else { + load_threshold = 0.0; + use_load_threshold = FALSE; + } + + if (macro_x[CONFIG_OPT_RUNCMD] != NULL) { + command = macro_x[CONFIG_OPT_RUNCMD]; + } + + if (macro_x[CONFIG_OPT_RUNCMD_ARG] != NULL) { + command_args = macro_x[CONFIG_OPT_RUNCMD_ARG]; + } + + if (macro_x[CONFIG_OPT_USER] != NULL) { + user = macro_x[CONFIG_OPT_USER]; + } else + user = "nagios"; + + if (macro_x[CONFIG_OPT_GROUP] != NULL) { + group = macro_x[CONFIG_OPT_GROUP]; + } else + group = "nagios"; + + if (macro_x[CONFIG_OPT_SCANDIR] != NULL) { + directory = macro_x[CONFIG_OPT_SCANDIR]; + } else { + directory = "/usr/local/nagios/var/spool/perfdata/"; + printf( + "WARNING - Adapting a hardcoded default perfdata spooldir - '%s'\n", + directory); + } + + if (macro_x[CONFIG_OPT_PIDFILE] != NULL) { + pidfile = macro_x[CONFIG_OPT_PIDFILE]; + } else + pidfile = "/var/run/npcd.pid"; + + if (macro_x[CONFIG_OPT_LOGLEVEL] != NULL) { + loglevel = atoi(macro_x[CONFIG_OPT_LOGLEVEL]); + } else + loglevel = 0; + + if (macro_x[CONFIG_OPT_SLEEPTIME] != NULL) { + sleeptime = atoi(macro_x[CONFIG_OPT_SLEEPTIME]); + } else + sleeptime = 15; + + if (macro_x[CONFIG_OPT_IDENTMYSELF] != NULL) { + identmyself = atoi(macro_x[CONFIG_OPT_IDENTMYSELF]); + } else + identmyself = TRUE; + + return OK; +} diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 0000000..45b2cc7 --- /dev/null +++ b/src/logging.c @@ -0,0 +1,93 @@ +// Copyright (C) 2007-2009 Hendrik Baecker +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include +#include +#include "../include/config.h" +#include "../include/pnp.h" + +int write_log(char *); + +extern char* log_file; +extern int use_syslog; +extern int loglevel; +extern int max_logfile_size; + +int do_log(char *message) { + if (use_syslog) { + syslog(LOG_NOTICE, "%s", message); + return OK; + } else if (use_syslog == FALSE) { + if (write_log(message)==0) + return OK; + else + return ERROR; + } + return OK; +} + +int write_log(char *message) { + int fd; + long filelen; + struct timeval tv; + char temp_buffer[2048]; + + time_t curtime; + + gettimeofday(&tv, NULL); + curtime = tv.tv_sec; + + strftime(temp_buffer, sizeof(temp_buffer) - 1, "[%m-%d-%Y %T] NPCD: ", + localtime(&curtime)); + strcat(temp_buffer, message); + + /* open / create logfile */ + if ((fd = open(log_file, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR + | S_IRGRP | S_IROTH)) == -1) { + printf("Cannot open log file %s\n", log_file); + return 0; + } + /* write log message */ + if (write(fd, temp_buffer, strlen(temp_buffer)) != strlen(temp_buffer)) { + perror("NPCD: Error writing to log file"); + close(fd); + return 0; + } + + /* rotate logfile if size > max_logfile_size */ + if ((filelen = lseek(fd, 0L, SEEK_END)) > max_logfile_size) { + /* LOG(0, "Begin Logrotation!\n"); */ + char buffer[PATH_MAX]; + close(fd); + + /* delete .old log file */ + strncpy(buffer, log_file, sizeof(buffer) - 1); + strncat(buffer, ".old", sizeof(buffer) - 1); + unlink(buffer); + + /* rename log_file to log_file.old */ + if (rename(log_file, buffer) != 0) { + snprintf(buffer, sizeof(buffer) - 1, "Error rename() logfile - %s", + strerror(errno)); + LOG(0, buffer); + //perror("Error renaming logfile\n"); + return 0; + } + LOG(0, "Logfile rotated!\n"); + } else { + close(fd); + } + return filelen; +} diff --git a/src/module/modpnpsender.c b/src/module/modpnpsender.c new file mode 100644 index 0000000..350404a --- /dev/null +++ b/src/module/modpnpsender.c @@ -0,0 +1,297 @@ +/***************************************************************************** + * + * modpnpsender.c - NEB Module for sending PNP performance data + * + * Copyright (c) 2007-2009 Hendrik Baecker (http://www.process-zero.de) + * + * Last Modified: $LastChangedDate: 2009-01-07 19:53:58 +0100 (Wed, 07 Jan 2009) $ + * by: $Author: hendrikb $ + * + * + * Description: + * + * Will follow soon.... + * + * + * Instructions: + * + * Compile with the following command: + * + * gcc -shared -o modpnpsender.o modpnpsender.c + * + *****************************************************************************/ + +/* include (minimum required) event broker header files */ +#include "../include/nebmodules.h" +#include "../include/nebcallbacks.h" + +/* include other event broker header files that we need for our work */ +#include "../include/nebstructs.h" +#include "../include/broker.h" + +/* include some Nagios stuff as well */ +#include "../include/config.h" +#include "../include/common.h" +#include "../include/nagios.h" + +#include +#include +#include +#include + +#define OPEN 1 +#define CLOSE 0 + +#define BUFFER 1024 + +/* specify event broker API version (required) */ +NEB_API_VERSION(CURRENT_NEB_API_VERSION); + +#define DEFAULT_SERVERPORT 5661 + +void *modpnpsender_module_handle=NULL; + +int modpnpsender_handle_data(int,void *); +int send_data(nebstruct_service_check_data *); +int open_sock(); + +char *serverip="127.0.0.1"; +char *port, *saveptr1; +int serverport=DEFAULT_SERVERPORT; +int socket_status=CLOSE; + +/* this function gets called when the module is loaded by the event broker */ +int nebmodule_init(int flags, char *args, nebmodule *handle){ + char temp_buffer[1024]; + time_t current_time; + unsigned long interval; + + /* save our handle */ + modpnpsender_module_handle=handle; + + /* log module info to the Nagios log file */ + write_to_all_logs("modpnpsender: Copyright (c)2007 Hendrik Baecker (andurin@process-zero.de)",NSLOG_INFO_MESSAGE); + + /* log a message to the Nagios log file */ + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: PNPSender module starting the engines!\n"); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + + if(args == NULL) { + write_to_all_logs("modpnpsender: WARNING assuming '127.0.0.1' as destination IP Address)",NSLOG_INFO_MESSAGE); + } + else { + if((serverip = strtok_r(args, " ", &saveptr1))!=NULL){ + serverip = serverip; + } + + if((port = strtok_r(NULL, " ", &saveptr1))!=NULL){ + serverport=atoi(port); + } + } + + + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Arguments are %s - %d",serverip,serverport); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + + + /* register to be notified of certain events... */ + neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA,modpnpsender_module_handle,0,modpnpsender_handle_data); + + return 0; + } + + +/* this function gets called when the module is unloaded by the event broker */ +int nebmodule_deinit(int flags, int reason){ + char temp_buffer[1024]; + + /* deregister for all events we previously registered for... */ + neb_deregister_callback(NEBCALLBACK_SERVICE_CHECK_DATA,modpnpsender_handle_data); + + /* log a message to the Nagios log file */ + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Exiting - Thanks for for the flight!\n"); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + + return 0; + } + + +/* handle data from Nagios daemon */ +int modpnpsender_handle_data(int event_type, void *data){ + nebstruct_service_check_data *scdata=NULL; + char temp_buffer[1024]; + + /* what type of event/data do we have? */ + switch(event_type){ + + case NEBCALLBACK_SERVICE_CHECK_DATA: + + /* a service check event occurs */ + if((scdata=(nebstruct_service_check_data *)data)!=NULL){ + + if (scdata->type==NEBTYPE_SERVICECHECK_INITIATE) { + + /* Check if this service check has performance data */ + + if (scdata->perf_data != NULL) { + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Processing PNP for %s / %s with perfdata %s",scdata->host_name,scdata->service_description,scdata->perf_data); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + if(send_data(scdata)!=0) { + write_to_all_logs("modpnpsender: An error occured while sending data!",NSLOG_INFO_MESSAGE); + } + else { + write_to_all_logs("modpnpsender: Message sent - finish for now.",NSLOG_INFO_MESSAGE); + return 0; + } + } + } + } + break; + + + default: + break; + } + + return 0; + } + +/********************************************* + * + * Sending Data + * + * *******************************************/ + +int send_data(nebstruct_service_check_data *data){ + char temp_buffer[1024]; + char *message; + int socket; + int message_length = 1024; + char cmd[1024]; + time_t t; + + if (socket_status == CLOSE) { + socket = open_sock(); + if (socket == -1) { + write_to_all_logs("modpnpsender: Arg! Socket is -1",NSLOG_INFO_MESSAGE); + return (-1); + } + } + + if (!(message = (char *) malloc(message_length))) { + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: cannot allocate memory for message. Aborting...\n"); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + return (-1); + } + + bzero((void *)message, message_length); + + strcat(message,"\n"); + strcat(message,"\nserviceperfdata\n"); + + strcat(message,""); + strcat(message,data->host_name); + strcat(message,"\n"); + + strcat(message,""); + strcat(message,data->service_description); + strcat(message,"\n"); + + strcat(message,""); + strcat(message,data->perf_data); + strcat(message,"\n"); + + strcat(message,""); + if (data->command_name != NULL) { + strcat(message,data->command_name); + } + strcat(message,"\n"); + + strcat(message,""); + if (data->command_args != NULL) strcat(message,data->command_args); + strcat(message,"\n"); + + strcat(message,""); + if (data->command_line != NULL) strcat(message,data->command_line); + strcat(message,"\n"); + + strcat(message,""); + if (data->output != NULL) strcat(message,data->output); + strcat(message,"\n"); + + + time(&t); + snprintf(temp_buffer, sizeof(temp_buffer)-1,"%ld",t); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + + strcat(message,""); + strcat(message, temp_buffer); + strcat(message,"\n"); + bzero((void *)temp_buffer,sizeof(temp_buffer)-1); + + strcat(message,"\n"); + + if(send(socket, message, strlen(message), 0) == -1) { + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: error while sending message to server. - %s\n",strerror(errno)); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + } + + close (socket); + socket_status = CLOSE; + + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Sending perfdata for %s / %s with perfdata %s",data->host_name,data->service_description,data->perf_data); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + + return 0; +} + +int open_sock(){ + int tosocket; /* the socket descriptor*/ + char temp_buffer[BUFFER]; + + /* description of struct sockaddr_in is mentioned in netinet/in.h */ + struct sockaddr_in toaddr; /* store address of server here */ + + /* create tcp socket */ + tosocket = socket(PF_INET,SOCK_STREAM,0); + if(tosocket == -1){ + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Unable to create socket. Aborting...\n"); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + return(-1); + } + /* else { + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Socket is OK....\n"); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + } */ + + /* define server address */ + toaddr.sin_family = PF_INET; + toaddr.sin_addr.s_addr = inet_addr(serverip); + toaddr.sin_port = htons(serverport); + + /* connect to server */ + if(connect(tosocket, (struct sockaddr *)&toaddr, sizeof(toaddr)) == -1){ + + snprintf(temp_buffer,sizeof(temp_buffer)-1,"modpnpsender: Unable to connect to server '%s' on port %d. Aborting...\n", serverip, serverport); + temp_buffer[sizeof(temp_buffer)-1]='\x0'; + write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE); + // write_to_all_logs("modpnpsender: Connect failed... closing the socket...",NSLOG_INFO_MESSAGE); + close (tosocket); + // write_to_all_logs("modpnpsender: Socket closed...",NSLOG_INFO_MESSAGE); + return(-1); + } + else { + socket_status=OPEN; + return tosocket; + } + return (-1); +} diff --git a/src/npcd.c b/src/npcd.c new file mode 100644 index 0000000..15412f2 --- /dev/null +++ b/src/npcd.c @@ -0,0 +1,572 @@ +/* Copyright (C) 2007-2009 Hendrik Baecker +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation; +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../include/config.h" +#include "../include/pnp.h" + +typedef void (*sighandler_t)(int); + +void *processfile(void *); +static void *exit_handler_mem(void *); +extern int process_arguments(int, char **); +extern void process_configfile(char *); +extern void check_sig(int); +extern int prepare_vars(void); +extern int drop_privileges(char *, char *); +extern sighandler_t handle_signal(int, sighandler_t); +extern int is_file(const struct dirent *d); +extern int check_needed_config_options(); + +double getload(int); + +static int thread_counter = 0; +int max_threads = 5; +int daemon_mode = FALSE; +int use_syslog = TRUE; +int loglevel = 0; +int max_logfile_size = 10485760; /* default 10Mbyte */ +int use_load_threshold = FALSE; +int we_should_stop = FALSE; +int sleeptime = 15; +int identmyself = TRUE; +double load_threshold = 10.0; + +extern int sighup_detected; + +char *command, *command_args, *user, *group, *pidfile; +char *macro_x[CONFIG_OPT_COUNT]; +char *log_file, *log_type; +char *config_file = NULL; + +const char *directory = NULL; +const char progname[5] = "npcd"; + +static void start_daemon(const char *log_name, int facility) { + int i; + pid_t pid; + + /* Kill parent after for to get a waise */ + if ((pid = fork()) != 0) + exit(EXIT_SUCCESS); + + /* Get this waise to sessionleader */ + if (setsid() < 0) { + printf("%s could not get sessionleader\n", log_name); + exit(EXIT_FAILURE); + } + + /* Ignore SIGHUP */ + handle_signal(SIGHUP, SIG_IGN); + + /* terminate child */ + if ((pid = fork()) != 0) + exit(EXIT_SUCCESS); + + /* for core dump handling and better unmounting behavior */ + /* Its return should not be ignored. + * npcd.c:79: warning: ignoring return value of ‘chdir’ */ + if (chdir("/") != 0) + exit(EXIT_FAILURE); + + /* change umask to defined value - be independet from parent umask */ + umask(002); + + /* close all possible file handles */ + for (i = sysconf(_SC_OPEN_MAX); i > 0; i--) + close(i); + + /* to hear the daemon you are calling... use syslog */ + if (use_syslog == TRUE && log_name != NULL) + openlog(log_name, LOG_PID | LOG_CONS | LOG_NDELAY, facility); + + /* close existing stdin, stdout, stderr */ + close(0); + close(1); + close(2); + + /* re-open stdin, stdout, stderr with known values */ + open("/dev/null",O_RDONLY); + open("/dev/null",O_WRONLY); + open("/dev/null",O_WRONLY); + +} + +int main(int argc, char **argv) { + + int i = 0; + int filecounter = 0, pthread_ret = 0; + double load; + char buffer[MAX_LOGMESSAGE_SIZE]; + + FILE *fppid = NULL; + + struct dirent **namelist; + + load = 0.0; + + if (process_arguments(argc, argv) == EXIT_FAILURE) + exit(EXIT_FAILURE); + + process_configfile(config_file); + + if (loglevel == -1) { + printf("DEBUG: Config File = %s\n", config_file); + printf("CONFIG_OPT_LOGTYPE = %s\n", macro_x[CONFIG_OPT_LOGTYPE]); + printf("CONFIG_OPT_LOGFILE = %s\n", macro_x[CONFIG_OPT_LOGFILE]); + printf("CONFIG_OPT_LOGFILESIZE = %s\n", macro_x[CONFIG_OPT_LOGFILESIZE]); + printf("CONFIG_OPT_LOGLEVEL = %s\n", macro_x[CONFIG_OPT_LOGLEVEL]); + printf("CONFIG_OPT_SCANDIR = %s\n", macro_x[CONFIG_OPT_SCANDIR]); + printf("CONFIG_OPT_RUNCMD = %s\n", macro_x[CONFIG_OPT_RUNCMD]); + printf("CONFIG_OPT_RUNCMD_ARG = %s\n", macro_x[CONFIG_OPT_RUNCMD_ARG]); + printf("CONFIG_OPT_MAXTHREADS = %s\n", macro_x[CONFIG_OPT_MAXTHREADS]); + printf("CONFIG_OPT_LOAD = %s\n", macro_x[CONFIG_OPT_LOAD]); + printf("CONFIG_OPT_USER = %s\n", macro_x[CONFIG_OPT_USER]); + printf("CONFIG_OPT_GROUP = %s\n", macro_x[CONFIG_OPT_GROUP]); + printf("CONFIG_OPT_PIDFILE = %s\n", macro_x[CONFIG_OPT_PIDFILE]); + printf("CONFIG_OPT_SLEEPTIME = %s\n", macro_x[CONFIG_OPT_SLEEPTIME]); + printf("CONFIG_OPT_IDENTMYSELF = %s\n", macro_x[CONFIG_OPT_IDENTMYSELF]); + printf("---------------------------\n"); + if (check_needed_config_options() != 0) { + printf("There is an Error! Exiting...\n"); + exit(EXIT_FAILURE); + } + } + + if (prepare_vars() != 0) + exit(EXIT_FAILURE); + if (loglevel == -1) + printf("DEBUG: load_threshold is %s - ('%f')\n", + use_load_threshold ? "enabled" : "disabled", load_threshold); + + pthread_t th[max_threads]; + for (i=0;i load_threshold)) { + + snprintf(buffer, sizeof(buffer) - 1, + "WARN: MAX load reached: load %f/%f at i=%d", load, + load_threshold, i); + LOG(0, buffer); + + if (i > 0) + i--; + sleep(sleeptime); + continue; + } +#endif + + snprintf(buffer, sizeof(buffer) - 1, + "ThreadCounter %d/%d File is %s\n", thread_counter, + max_threads, namelist[i]->d_name); + LOG(2, buffer); + + struct stat attribute; + + if (stat(namelist[i]->d_name, &attribute) == -1) { + LOG(0, "Error while getting file status"); + break; + } + + if (strstr((namelist[i]->d_name), "-PID-") != NULL) { + snprintf( + buffer, + sizeof(buffer) - 1, + "File '%s' is an already in process PNP file. Leaving it untouched.\n", + namelist[i]->d_name); + + LOG(1, buffer); + continue; + } + + if (S_ISREG(attribute.st_mode)) { + snprintf(buffer, sizeof(buffer) - 1, "Regular File: %s\n", + namelist[i]->d_name); + LOG(2, buffer); + + /* only start new threads if the max_thread config option is not reached */ + if (thread_counter < max_threads && we_should_stop == FALSE) { + + if ((pthread_ret = pthread_create(&th[thread_counter], + NULL, processfile, namelist[i]->d_name)) != 0) { + snprintf(buffer, sizeof(buffer) - 1, + "Could not create thread... exiting with error '%s'\n", strerror(errno)); + LOG(0, buffer); + exit(EXIT_FAILURE); + } + + snprintf(buffer, sizeof(buffer) - 1, + "A thread was started on thread_counter = %d\n", + thread_counter); + LOG(2, buffer); + + thread_counter++; + + } + + else if (we_should_stop == TRUE) + break; + + else { + + snprintf( + buffer, + sizeof(buffer) - 1, + "WARN: MAX Thread reached: %s comes later with ThreadCounter: %d\n", + namelist[i]->d_name, thread_counter); + LOG(2, buffer); + + i--; + + for (thread_counter = thread_counter; thread_counter > 0; thread_counter--) { + snprintf(buffer, sizeof(buffer) - 1, + "DEBUG: Will wait for th['%d']\n", + thread_counter - 1); + LOG(2, buffer); + pthread_join(th[thread_counter - 1], NULL); + } + } + } + } + + if (thread_counter > 0) { + /* Wait for open threads before working on the next run */ + snprintf(buffer, sizeof(buffer) - 1, + "Have to wait: Filecounter = %d - thread_counter = %d\n", + filecounter - 2, thread_counter); + LOG(2, buffer); + + for (thread_counter = thread_counter; thread_counter > 0; thread_counter--) + pthread_join(th[thread_counter - 1], NULL); + } + + if (we_should_stop == TRUE) + break; + + for (i = 0, namelist; i < filecounter; i++) { + free(namelist[i]); + } + + free(namelist); + + snprintf(buffer, sizeof(buffer) - 1, + "No more files to process... waiting for %d seconds\n", + sleeptime); + LOG(1, buffer); + + sleep(sleeptime); + + } + + snprintf(buffer, sizeof(buffer) - 1, "Daemon ended. PID was '%d'\n", + getpid()); + LOG(0, buffer); + + if (use_syslog) + closelog(); + return EXIT_SUCCESS; +} + +/* ************************************************************** + * + * Function to parse and check the commandline arguments + * + * *************************************************************/ + +int process_arguments(int argc, char **argv) { + int c; + int error = FALSE; + int display_license = FALSE; + int display_help = FALSE; + +#ifdef HAVE_GETOPT_H + int option_index = 0; + static struct option long_options[] = { { "help", no_argument, 0, 'h' }, { + "version", no_argument, 0, 'V' }, + { "license", no_argument, 0, 'V' }, + { "daemon", no_argument, 0, 'd' }, { "config", required_argument, + 0, 'f' }, { 0, 0, 0, 0 } }; +#endif + + /* make sure we have the correct number of command line arguments */ + if (argc < 2) + error = TRUE; + + while (1) { + +#ifdef HAVE_GETOPT_H + c = getopt_long(argc, argv, "+hVdf:", long_options, &option_index); +#else + c = getopt(argc, argv, "+hVdf:"); +#endif + + if (c == -1 || c == EOF) + break; + + switch (c) { + + case '?': /* usage */ + case 'h': + display_help = TRUE; + break; + + case 'V': /* version */ + printf("%s %s - $Revision: 637 $\n\n", progname, PACKAGE_VERSION); + display_license = TRUE; + break; + + case 'd': /* run in daemon mode */ + daemon_mode = TRUE; + break; + + case 'f': /* config file */ + if (optarg != NULL) + config_file = optarg; + break; + + default: + break; + } + + } + + if (display_license == TRUE) { + + printf( + "This program is free software; you can redistribute it and/or modify\n"); + printf( + "it under the terms of the GNU General Public License version 2 as\n"); + printf("published by the Free Software Foundation.\n\n"); + printf( + "This program is distributed in the hope that it will be useful,\n"); + printf( + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf( + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU General Public License for more details.\n\n"); + printf( + "You should have received a copy of the GNU General Public License\n"); + printf("along with this program; if not, write to the Free Software\n"); + printf( + "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n\n"); + + exit(EXIT_SUCCESS); + } + + /* if there are no command line options (or if we encountered an error), print usage */ + if (error == TRUE || display_help == TRUE) { + printf("\nUsage: %s -f [-d] \n", argv[0]); + printf("\n"); + printf("Options:\n"); + printf("\n"); + printf(" -d | --daemon \n"); + printf("\t\tRun as daemon in background\n"); + printf("\n"); + printf(" -f | --config \n"); + printf("\t\tPath to config file\n"); + printf("\n"); + printf( + "Visit the Website at http://sourceforge.net/projects/pnp4nagios/ for bug fixes, \n"); + printf("new releases, online documentation, FAQs, Mailinglists.\n"); + printf("\n"); + + exit(EXIT_FAILURE); + } + return EXIT_SUCCESS; +} + +/******************************************************************** + * * + * processfile - this is the function for each thread * + * * + ********************************************************************/ + +void * processfile(void *filename) { + + char *file = (char *) filename; + char command_line[MAX_COMMANDLINE_LENGTH]; + char buffer[MAX_LOGMESSAGE_SIZE]; + int result; + FILE *proc; + + /* npcd.c:493: warning: ‘result’ may be used uninitialized in this function */ + result = 0; + + snprintf(command_line, sizeof(command_line), "%s %s %s %s/%s", command, + identmyself ? "-n" : "\b", command_args, directory, file); + + pthread_cleanup_push((void *) &exit_handler_mem, file); + + snprintf(buffer, sizeof(buffer) - 1, + "Processing file %s with ID %ld - going to exec %s\n", file, + pthread_self(), command_line); + LOG(2, buffer); + + snprintf(buffer, sizeof(buffer) - 1, "Processing file '%s'\n", file); + LOG(1, buffer); + + if ((proc = popen(command_line, "r")) != NULL) + result = pclose(proc); + + result >>= 8; + + if (result != 0) { + snprintf(buffer, sizeof(buffer) - 1, + "ERROR: Executed command exits with return code '%d'\n", + result); + LOG(0, buffer); + + snprintf(buffer, sizeof(buffer) - 1, + "ERROR: Command line was '%s'\n", command_line); + LOG(0, buffer); + + we_should_stop = FALSE; + } + + if (loglevel == -1) + sleep(2); + + pthread_cleanup_pop(1); + pthread_exit((void *) pthread_self()); +} + +/* ****************************************************************** + * * + * processfile - this is the function for each thread * + * * + * ******************************************************************/ + +static void *exit_handler_mem(void * arg) { + // syslog( LOG_NOTICE, "Will now clean up thread %ld\n",pthread_self()); + //if (thread_counter > 0) + //thread_counter--; + return 0; +} + +#ifdef HAVE_GETLOADAVG +double getload(int which_sample) { + + double loadavg[3]; + char buffer[MAX_LOGMESSAGE_SIZE]; + + if (which_sample == 1) { + which_sample = 0; + } else if (which_sample == 5) { + which_sample = 1; + } else if (which_sample == 15) { + which_sample = 2; + } else { + snprintf(buffer, sizeof(buffer) - 1, + "Invalid load sample %d - allowed is 1,5,15\n", which_sample); + LOG(0, buffer); + + return -1; + } + getloadavg(loadavg, 3); + return loadavg[which_sample]; +} +#endif diff --git a/src/npcdmod.c b/src/npcdmod.c new file mode 100644 index 0000000..cfd2565 --- /dev/null +++ b/src/npcdmod.c @@ -0,0 +1,598 @@ +/***************************************************************************** + * + * NPCDMOD.C + * + * Copyright (c) 2008-2010 Hendrik Baecker (http://www.pnp4nagios.org) + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Last Modified: 07-30-2010 + * + *****************************************************************************/ + +/* include (minimum required) event broker header files */ +#include "../include/nebmodules.h" +#include "../include/nebcallbacks.h" + +/* include other event broker header files that we need for our work */ +#include "../include/nebstructs.h" +#include "../include/broker.h" + +/* include some Nagios stuff as well */ +#include "../include/config.h" +#include "../include/common.h" +#include "../include/nagios.h" + +/* include some pnp stuff */ +#include "../include/pnp.h" +#include "../include/npcdmod.h" + +/* specify event broker API version (required) */ +NEB_API_VERSION(CURRENT_NEB_API_VERSION); + +extern int process_performance_data; + +FILE *fp = NULL; + +void *npcdmod_module_handle = NULL; +char *perfdata_file = "/usr/local/nagios/var/perfdata"; +char *perfdata_spool_filename = "perfdata"; +char *spool_dir = NULL; +char *perfdata_file_processing_interval = "15"; + +void npcdmod_file_roller(); +int npcdmod_handle_data(int, void *); + +int npcdmod_process_config_var(char *arg); +int npcdmod_process_module_args(char *args); + +/* this function gets called when the module is loaded by the event broker */ +int nebmodule_init(int flags, char *args, nebmodule *handle) { + char temp_buffer[1024]; + time_t current_time; + //unsigned long interval; + + /* save our handle */ + npcdmod_module_handle = handle; + + /* set some info - this is completely optional, as Nagios doesn't do anything with this data */ + neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_TITLE, "npcdmod"); + neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_AUTHOR, "Hendrik Baecker"); + neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_TITLE, "Copyright (c) 2008-2009 Hendrik Baecker"); + neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_VERSION, "0.0.2"); + neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_LICENSE, "GPL v2"); + neb_set_module_info(npcdmod_module_handle, NEBMODULE_MODINFO_DESC, "A simple performance data extractor."); + + /* log module info to the Nagios log file */ + write_to_all_logs("npcdmod: Copyright (c) 2008-2009 Hendrik Baecker (andurin@process-zero.de) - http://www.pnp4nagios.org", NSLOG_INFO_MESSAGE); + + if (process_performance_data == FALSE) { + write_to_all_logs("npcdmod: I can not work with disabled performance data in nagios.cfg.", NSLOG_INFO_MESSAGE); + write_to_all_logs("npcdmod: Please enable it with 'process_performance_data=1' in nagios.cfg", NSLOG_INFO_MESSAGE); + return -1; + } + + /* process arguments */ + if (npcdmod_process_module_args(args) == ERROR) { + write_to_all_logs("npcdmod: An error occurred while attempting to process module arguments.", NSLOG_INFO_MESSAGE); + return -1; + } + + /* de-initialize if there is no perfdata file nor spool dir */ + if (spool_dir == NULL || perfdata_file == NULL) { + write_to_all_logs("npcdmod: An error occurred process your config file. Check your perfdata_file or perfdata_spool_dir.", NSLOG_INFO_MESSAGE); + return -1; + } + + /* Log some health data */ + snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: spool_dir = '%s'.", spool_dir); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + + snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: perfdata file '%s'.", perfdata_file); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + + /* open perfdata_file to write perfdata in it */ + if ((fp = fopen(perfdata_file, "a")) == NULL) { + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: Could not open file. %s", strerror(errno)); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + return -1; + } + + /* log a message to the Nagios log file that we're ready */ + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: Ready to run to have some fun!\n"); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + + /* register for a 15 seconds file move event */ + time(¤t_time); + //interval = 15; + schedule_new_event(EVENT_USER_FUNCTION,TRUE, current_time + atoi(perfdata_file_processing_interval), TRUE, + atoi(perfdata_file_processing_interval), NULL, TRUE, (void *) npcdmod_file_roller, "", 0); + + /* register to be notified of certain events... */ + neb_register_callback(NEBCALLBACK_HOST_CHECK_DATA, npcdmod_module_handle, + 0, npcdmod_handle_data); + neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA, + npcdmod_module_handle, 0, npcdmod_handle_data); + return 0; +} + +/* this function gets called when the module is unloaded by the event broker */ +int nebmodule_deinit(int flags, int reason) { + char temp_buffer[1024]; + + /* deregister for all events we previously registered for... */ + neb_deregister_callback(NEBCALLBACK_HOST_CHECK_DATA,npcdmod_handle_data); + neb_deregister_callback(NEBCALLBACK_SERVICE_CHECK_DATA,npcdmod_handle_data); + + /* log a message to the Nagios log file */ + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: If you don't like me, I will go out! Bye.\n"); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + + return 0; +} + +/* gets called every X seconds by an event in the scheduling queue */ +void npcdmod_file_roller() { + char temp_buffer[1024]; + char spool_file[1024]; + int result = 0; + time_t current_time; + + time(¤t_time); + + sprintf(spool_file, "%s/%s.%d", spool_dir, perfdata_spool_filename, (int)current_time); + spool_file[sizeof(spool_file) - 1] = '\x0'; + + /* close actual file */ + fclose(fp); + + /* move the original file */ + result = my_rename(perfdata_file, spool_file); + + /* open a new file */ + if ((fp = fopen(perfdata_file, "a")) == NULL) { + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: Could not reopen file. %s", strerror(errno)); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + } + + return; +} + +/* handle data from Nagios daemon */ +int npcdmod_handle_data(int event_type, void *data) { + nebstruct_host_check_data *hostchkdata = NULL; + nebstruct_service_check_data *srvchkdata = NULL; + + host *host=NULL; + service *service=NULL; + + char temp_buffer[1024]; + char perfdatafile_template[PERFDATA_BUFFER]; + int written; + + + /* what type of event/data do we have? */ + switch (event_type) { + + case NEBCALLBACK_HOST_CHECK_DATA: + /* an aggregated status data dump just started or ended... */ + if ((hostchkdata = (nebstruct_host_check_data *) data)) { + + host = find_host(hostchkdata->host_name); + + if(host->process_performance_data == 0) { + break; + } + + /* Do some Debuglog */ + /* + snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: DEBUG >>> %s\n", + host->host_check_command); + + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + */ + + if (hostchkdata->type == NEBTYPE_HOSTCHECK_PROCESSED + && hostchkdata->perf_data != NULL) { + written = snprintf(perfdatafile_template, PERFDATA_BUFFER, + "DATATYPE::HOSTPERFDATA\t" + "TIMET::%d\t" + "HOSTNAME::%s\t" + "HOSTPERFDATA::%s\t" + "HOSTCHECKCOMMAND::%s!%s\t" + "HOSTSTATE::%d\t" + "HOSTSTATETYPE::%d\n", (int)hostchkdata->timestamp.tv_sec, + hostchkdata->host_name, hostchkdata->perf_data, + hostchkdata->command_name, hostchkdata->command_args, + hostchkdata->state, hostchkdata->state_type); + + if (written >= PERFDATA_BUFFER) { + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: Buffer size of %d in npcdmod.h is too small, ignoring data for %s\n", PERFDATA_BUFFER, hostchkdata->host_name); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + } else { + fputs(perfdatafile_template, fp); + } + } + } + break; + + case NEBCALLBACK_SERVICE_CHECK_DATA: + /* an aggregated status data dump just started or ended... */ + if ((srvchkdata = (nebstruct_service_check_data *) data)) { + + if (srvchkdata->type == NEBTYPE_SERVICECHECK_PROCESSED + && srvchkdata->perf_data != NULL) { + + /* find the nagios service object for this service */ + service = find_service(srvchkdata->host_name, srvchkdata->service_description); + + if(service->process_performance_data == 0) { + break; + } + + /* Do some Debuglog */ + /* + snprintf(temp_buffer, sizeof(temp_buffer) - 1, "npcdmod: DEBUG >>> %s\n", + service->service_check_command); + + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + */ + + written = snprintf(perfdatafile_template, PERFDATA_BUFFER, + "DATATYPE::SERVICEPERFDATA\t" + "TIMET::%d\t" + "HOSTNAME::%s\t" + "SERVICEDESC::%s\t" + "SERVICEPERFDATA::%s\t" + "SERVICECHECKCOMMAND::%s\t" + "SERVICESTATE::%d\t" + "SERVICESTATETYPE::%d\n", (int)srvchkdata->timestamp.tv_sec, + srvchkdata->host_name, srvchkdata->service_description, + srvchkdata->perf_data, service->service_check_command, + srvchkdata->state, srvchkdata->state_type); + + if (written >= PERFDATA_BUFFER) { + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: Buffer size of %d in npcdmod.h is too small, ignoring data for %s / %s\n", PERFDATA_BUFFER, srvchkdata->host_name, srvchkdata->service_description); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + } else { + fputs(perfdatafile_template, fp); + } + } + } + break; + + default: + break; + } + + + return 0; +} + +/****************************************************************************/ +/* CONFIG FUNCTIONS */ +/****************************************************************************/ + +/* process arguments that were passed to the module at startup */ +int npcdmod_process_module_args(char *args) { + char *ptr = NULL; + char **arglist = NULL; + char **newarglist = NULL; + int argcount = 0; + int memblocks = 64; + int arg = 0; + + if (args == NULL) + return OK; + + /* get all the var/val argument pairs */ + + /* allocate some memory */ + if ((arglist = (char **) malloc(memblocks * sizeof(char **))) == NULL) + return ERROR; + + /* process all args */ + ptr = strtok(args, ","); + while (ptr) { + + /* save the argument */ + arglist[argcount++] = strdup(ptr); + + /* allocate more memory if needed */ + if (!(argcount % memblocks)) { + if ((newarglist = (char **) realloc(arglist, (argcount + memblocks) + * sizeof(char **))) == NULL) { + for (arg = 0; arg < argcount; arg++) + free(arglist[argcount]); + free(arglist); + return ERROR; + } else + arglist = newarglist; + } + + ptr = strtok(NULL, ","); + } + + /* terminate the arg list */ + arglist[argcount] = '\x0'; + + /* process each argument */ + for (arg = 0; arg < argcount; arg++) { + if (npcdmod_process_config_var(arglist[arg]) == ERROR) { + for (arg = 0; arg < argcount; arg++) + free(arglist[arg]); + free(arglist); + return ERROR; + } + } + + /* free allocated memory */ + for (arg = 0; arg < argcount; arg++) + free(arglist[arg]); + free(arglist); + + return OK; +} + +/* process all config vars in a file */ +int npcdmod_process_config_file(char *filename) { + pnp_mmapfile *thefile = NULL; + char *buf = NULL; + char temp_buffer[1024]; + int result = OK; + + /* open the file */ + if ((thefile = pnp_mmap_fopen(filename)) == NULL) { + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod ERROR: failed to open %s\n", filename); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + return ERROR; + + } else { + snprintf(temp_buffer, sizeof(temp_buffer) - 1, + "npcdmod: %s initialized\n", filename); + temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; + write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE); + } + + /* process each line of the file */ + while ((buf = pnp_mmap_fgets(thefile))) { + + /* skip comments */ + if (buf[0] == '#') { + free(buf); + continue; + } + + /* skip blank lines */ + if (!strcmp(buf, "")) { + free(buf); + continue; + } + + /* skip new lines */ + if (!strcmp(buf, "\n")) { + free(buf); + continue; + } + /* process the variable */ + result = npcdmod_process_config_var(buf); + + /* free memory */ + free(buf); + + if (result != OK) + break; + } + + /* close the file */ + pnp_mmap_fclose(thefile); + + return result; +} + +/* process a single module config variable */ +int npcdmod_process_config_var(char *arg) { + char *var = NULL; + char *val = NULL; + + /* split var/val */ + var = strtok(arg, "="); + val = strtok(NULL, "\n"); + + /* skip incomplete var/val pairs */ + if (var == NULL || val == NULL) + return OK; + + /* strip var/val */ + strip(var); + strip(val); + + /* process the variable... */ + if (!strcmp(var, "config_file")) + npcdmod_process_config_file(val); + + else if (!strcmp(var, "perfdata_spool_dir")) + spool_dir = strdup(val); + + else if (!strcmp(var, "perfdata_file")) + perfdata_file = strdup(val); + + else if (!strcmp(var, "perfdata_spool_filename")) + perfdata_spool_filename = strdup(val); + + else if (!strcmp(var, "perfdata_file_processing_interval")) + perfdata_file_processing_interval = strdup(val); + + else if (!strcmp(var, "user")) + ; + else if (!strcmp(var, "group")) + ; + else if (!strcmp(var, "log_type")) + ; + else if (!strcmp(var, "log_file")) + ; + else if (!strcmp(var, "max_logfile_size")) + ; + else if (!strcmp(var, "log_level")) + ; + else if (!strcmp(var, "perfdata_file_run_cmd")) + ; + else if (!strcmp(var, "perfdata_file_run_cmd_args")) + ; + else if (!strcmp(var, "identify_npcd")) + ; + else if (!strcmp(var, "npcd_max_threads")) + ; + else if (!strcmp(var, "sleep_time")) + ; + else if (!strcmp(var, "load_threshold")) + ; + else if (!strcmp(var, "pid_file")) + ; + else + return ERROR; + + return OK; +} + +/**************************************************************/ +/****** MMAP()'ED FILE FUNCTIONS ******************************/ +/**************************************************************/ + +/* open a file read-only via mmap() */ +pnp_mmapfile *pnp_mmap_fopen(char *filename) { + pnp_mmapfile *new_mmapfile; + int fd; + void *mmap_buf; + struct stat statbuf; + int mode = O_RDONLY; + + /* allocate memory */ + if ((new_mmapfile = (pnp_mmapfile *) malloc(sizeof(pnp_mmapfile))) == NULL) + return NULL; + + /* open the file */ + if ((fd = open(filename, mode)) == -1) { + free(new_mmapfile); + return NULL; + } + + /* get file info */ + if ((fstat(fd, &statbuf)) == -1) { + close(fd); + free(new_mmapfile); + return NULL; + } + + /* mmap() the file */ + if ((mmap_buf = (void *) mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, + fd, 0)) == MAP_FAILED) { + close(fd); + free(new_mmapfile); + return NULL; + } + + /* populate struct info for later use */ + /*new_mmapfile->path=strdup(filename);*/ + new_mmapfile->path = NULL; + new_mmapfile->fd = fd; + new_mmapfile->file_size = (unsigned long) (statbuf.st_size); + new_mmapfile->current_position = 0L; + new_mmapfile->current_line = 0L; + new_mmapfile->mmap_buf = mmap_buf; + + return new_mmapfile; +} + +/* close a file originally opened via mmap() */ +int pnp_mmap_fclose(pnp_mmapfile *temp_mmapfile) { + + if (temp_mmapfile == NULL) + return ERROR; + + /* un-mmap() the file */ + munmap(temp_mmapfile->mmap_buf, temp_mmapfile->file_size); + + /* close the file */ + close(temp_mmapfile->fd); + + /* free memory */ + if (temp_mmapfile->path != NULL) + free(temp_mmapfile->path); + free(temp_mmapfile); + + return OK; +} + +/* gets one line of input from an mmap()'ed file */ +char *pnp_mmap_fgets(pnp_mmapfile *temp_mmapfile) { + char *buf = NULL; + unsigned long x = 0L; + int len = 0; + + if (temp_mmapfile == NULL) + return NULL; + + /* we've reached the end of the file */ + if (temp_mmapfile->current_position >= temp_mmapfile->file_size) + return NULL; + + /* find the end of the string (or buffer) */ + for (x = temp_mmapfile->current_position; x < temp_mmapfile->file_size; x++) { + if (*((char *) (temp_mmapfile->mmap_buf) + x) == '\n') { + x++; + break; + } + } + + /* calculate length of line we just read */ + len = (int) (x - temp_mmapfile->current_position); + + /* allocate memory for the new line */ + if ((buf = (char *) malloc(len + 1)) == NULL) { + write_to_all_logs("could not allocate a new buf", NSLOG_INFO_MESSAGE); + return NULL; + } + + /* copy string to newly allocated memory and terminate the string */ + memcpy(buf, ((char *) (temp_mmapfile->mmap_buf) + + temp_mmapfile->current_position), len); + buf[len] = '\x0'; + + /* update the current position */ + temp_mmapfile->current_position = x; + + /* increment the current line */ + temp_mmapfile->current_line++; + + return buf; +} + diff --git a/src/pnpsender.c b/src/pnpsender.c new file mode 100644 index 0000000..ece4b32 --- /dev/null +++ b/src/pnpsender.c @@ -0,0 +1,384 @@ +// Copyright (C) 2006-2009 Hendrik Baecker +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "../include/config.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_GETOPT_H +#include +#endif + +#include +#include +#include +#include + +#define BUFFER_SIZE 255 +#define DEFAULT_SERVERPORT 5661 /* Ein Port der auch von 'gewhnlichen' Benutzern verwendet werden darf */ +#define MSG_SIZE 8192 /* Die maximale Anzahl an Zeichen, die 'msg' enhalten darf */ + +#define OPEN 1 +#define CLOSE 0 + +#define TRUE 1 +#define FALSE 0 + +#define OK 0 +#define ERROR -1 + +struct Nagios_Env { + char varname[128]; + char varvalue[128]; + struct Nagios_Env *next; +}; + +/* function prototypes */ +void print_list(int, struct Nagios_Env *); +int parse_env(char *, struct Nagios_Env **); +int process_env(char *[]); +int open_sock(); +int process_arguments(int, char **); + +void timeout_sighandler(int); + +/* variable declaration*/ +pid_t fork(void); +int socket_status = CLOSE; +int serverport = DEFAULT_SERVERPORT; +int timeout = 10; /* Default time out to 10 seconds */ +char *serverip, *datatype; +char msg[MSG_SIZE]; /* Buffer for sending the message to remote server */ + +int main(int argc, char *argv[], char *envp[]) { + + if (process_arguments(argc, argv) == ERROR) + exit(ERROR); + + pid_t pid; + int error_code = 0; + switch (pid = fork()) { + case -1: + /* Here pid is -1, the fork failed */ + /* Some possible reasons are that you're */ + /* out of process slots or virtual memory */ + perror("The fork failed!"); + error_code = -1; + break; + + case 0: + /* pid of zero is the child */ + signal(SIGALRM, timeout_sighandler); + alarm(timeout); + process_env(envp); + _exit(0); + + default: + /* pid greater than zero is parent getting the child's pid */ + //printf("Child's pid is %d\n",pid); + error_code = 0; + } + exit(error_code); +} + +void timeout_sighandler(int sig) { + + /* force the child process to exit... */ + fprintf(stderr, "Caught SIGALRM - timeout\n"); + _exit(-1); +} + +/*************************************************** + * processing command line arguments + * + * Gets number of args and pointer reference to argv + ***************************************************/ +int process_arguments(int argc, char **argv) { + int c; + int error = FALSE; + int test_mode = FALSE; + int display_license = FALSE; + int display_help = FALSE; + +#ifdef HAVE_GETOPT_H + int option_index=0; + static struct option long_options[]= { + { "help",no_argument,0,'h'}, + { "version",no_argument,0,'V'}, + { "license",no_argument,0,'V'}, + { "test",no_argument,0,'t'}, + { "host",required_argument,0,'H'}, + { "port",required_argument,0,'p'}, + { "datatype",required_argument,0,'d'}, + { "timeout",required_argument,0,'t'}, + { 0,0,0,0} + }; +#endif + + /* make sure we have the correct number of command line arguments */ + if (argc < 2) + error = TRUE; + + while (1) { + +#ifdef HAVE_GETOPT_H + c=getopt_long(argc,argv,"+hH:p:d:Vt:",long_options,&option_index); +#else + c = getopt(argc, argv, "+hH:p:d:Vt:"); +#endif + + if (c == -1 || c == EOF) + break; + + switch (c) { + + case '?': /* usage */ + case 'h': + display_help = TRUE; + break; + + case 'V': /* version */ + display_license = TRUE; + break; + + case 'H': /* host ip */ + // ToDo: Check if it there + if (optarg != NULL) { + serverip = optarg; + } else + error = TRUE; + break; + + case 'p': /* port to use */ + // ToDo: Check for port + if (optarg != NULL) + serverport = atoi(optarg); + break; + + case 'd': /* datatype like hostperfdata, serviceperfdata and so on */ + if (optarg != NULL) + datatype = optarg; + else + error = TRUE; + break; + + case 't': /* timeout */ + if (optarg != NULL) + timeout = atoi(optarg); + else + error = TRUE; + break; + + default: + break; + } + + } + + /* it makes no sense to do anything without a target host*/ + if (serverip == NULL) + error = TRUE; + + if (display_license == TRUE) { + + printf( + "This program is free software; you can redistribute it and/or modify\n"); + printf( + "it under the terms of the GNU General Public License version 2 as\n"); + printf("published by the Free Software Foundation.\n\n"); + printf( + "This program is distributed in the hope that it will be useful,\n"); + printf( + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf( + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU General Public License for more details.\n\n"); + printf( + "You should have received a copy of the GNU General Public License\n"); + printf("along with this program; if not, write to the Free Software\n"); + printf( + "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n\n"); + + exit(OK); + } + + /* if there are no command line options (or if we encountered an error), print usage */ + if (error == TRUE || display_help == TRUE) { + printf( + "Usage: %s -H [-p ] -d -t \n", + argv[0]); + printf("\n"); + printf("Options:\n"); + printf("\n"); + printf(" -H | --host Host IP Address to send data to.\n"); + printf("\n"); + printf( + " -p | --port Host Port to send data to. (Default: tcp/1500)\n"); + printf("\n"); + printf( + " -t | --timeout Timeout value to kill process (Default: 10 seconds)\n"); + printf("\n"); + printf(" -d | --datatype Free string what this Data stands for\n"); + printf( + " like \"serviceperfdata\", \"hostperfdata\", \"eventhandler\"\n"); + printf("\n\n"); + printf( + "Visit the PNP website at http://www.pnp4nagios.org/pnp/ for bug fixes, new\n"); + printf( + "releases, online documentation, FAQs, information on subscribing to\n"); + printf("the mailing lists.\n"); + printf("\n"); + + exit(ERROR); + } + return OK; +} + +int process_env(char *envp[]) { + int count = 0; + int socket; + struct Nagios_Env *base = NULL; + struct Nagios_Env *ptr = NULL; + while (1) { + if (socket_status == CLOSE) { + socket = open_sock(serverip); + } + if (envp[count] == NULL) { + break; + } + parse_env(envp[count], &base); + count++; + } + print_list(socket, base); + return (0); +} + +void print_list(int socket, struct Nagios_Env *base) { + struct Nagios_Env *ptr = NULL; + char *message, dtype[BUFFER_SIZE]; + int message_length = sizeof(struct Nagios_Env) - sizeof(ptr->next); + ptr = base; + strcat(dtype, + "\n"); + strcat(dtype, "\n"); + strcat(dtype, " "); + strcat(dtype, datatype); + strcat(dtype, "\n"); + if (send(socket, dtype, strlen(dtype), 0) == -1) { + fprintf(stderr, "error while sending request to server\n"); + } + bzero((void *) dtype, BUFFER_SIZE); + + while (ptr != NULL) { + if (!(message = (char *) malloc(sizeof(struct Nagios_Env)))) { + fprintf(stderr, "Cannot allocate memory for this message\n"); + exit(ERROR); + } + strncat(message, " <", message_length); + strncat(message, ptr->varname, message_length); + strncat(message, ">", message_length); + strncat(message, ptr->varvalue, message_length); + strncat(message, "varname, message_length); + strncat(message, ">\n", message_length); + message[message_length] = '\0'; + if (send(socket, message, strlen(message), 0) == -1) { + fprintf(stderr, "error while sending request to server\n"); + } + ptr = ptr->next; + } + strcat(dtype, "\n"); + if (send(socket, dtype, strlen(dtype), 0) == -1) { + fprintf(stderr, "error while sending request to server\n"); + } +} + +int parse_env(char *curr, struct Nagios_Env **base) { + char tmpbuf[BUFFER_SIZE]; + char *var1; + char *var2; + struct Nagios_Env *ptr = NULL; + ptr = *base; + + strncpy(tmpbuf, curr, BUFFER_SIZE); + var1 = strtok(tmpbuf, "="); + var2 = strtok(NULL, ""); + if (strncmp(var1, (char *) "NAGIOS_", 7) == 0) { + if (var2 != NULL) { + if (ptr == NULL) { + /* create first list element */ + ptr = (struct Nagios_Env *) malloc(sizeof(struct Nagios_Env)); + if (ptr == NULL) + return ERROR; + *base = ptr; + } else { + /* create a new list element */ + /* first look for the end of list */ + while (ptr->next != NULL) + ptr = ptr->next; + + /* neues Listenelement erzeugen */ + ptr->next = (struct Nagios_Env *) malloc( + sizeof(struct Nagios_Env)); + if (ptr->next == NULL) + return ERROR; + ptr = ptr->next; + } + + // Building dynamic list + strcpy(ptr->varname, var1); + strcpy(ptr->varvalue, var2); + ptr->next = NULL; + } + } + bzero((void *) tmpbuf, BUFFER_SIZE); + return (0); +} + +int open_sock() { + int tosocket; /* the socket descriptor*/ + + /* description of struct sockaddr_in is mentioned in netinet/in.h */ + struct sockaddr_in toaddr; /* store address of server here */ + + /* create tcp socket */ + tosocket = socket(PF_INET, SOCK_STREAM, 0); + if (tosocket == -1) { + fprintf(stderr, "cannot open socket\n"); + exit(1); + } + + /* define server address */ + toaddr.sin_family = PF_INET; + toaddr.sin_addr.s_addr = inet_addr(serverip); + toaddr.sin_port = htons(serverport); + + /* connect to server */ + if (connect(tosocket, (struct sockaddr *) &toaddr, sizeof(toaddr)) == -1) { + fprintf(stderr, + "Unable to connect to server '%s' on port %d. Exiting...\n", + serverip, serverport); + close(tosocket); + exit(1); + } else { + socket_status = OPEN; + return tosocket; + } + return -1; +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..991d3bd --- /dev/null +++ b/src/utils.c @@ -0,0 +1,228 @@ +// Copyright (C) 2006-2009 Hendrik Baecker +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#include "../include/config.h" +#include "../include/pnp.h" + +extern int prepare_vars(); + +extern int thread_counter; +extern int max_threads; +extern int daemon_mode; +extern int loglevel; +extern int use_syslog; +int sighup_detected = FALSE; + +extern char** command; +extern char *command_args; +extern char *user; +extern char *group; +extern char *directory; +extern char *macro_x; +extern char *config_file; +extern char buffer[MAX_LOGMESSAGE_SIZE]; + +extern void process_configfile(char *); +extern int check_needed_config_options(void); + +typedef void (*sighandler_t)(int); + +// This function has special copyright!!! +/* Copyright (c) 1999-2006 Ethan Galstad (nagios@nagios.org) */ +/* strip newline, carriage return, and tab characters from beginning and end of a string */ +void pnp_strip(char *buffer) { + register int x; + register int y; + register int z; + + if (buffer == NULL || buffer[0] == '\x0') + return; + + /* strip end of string */ + y = (int) strlen(buffer); + for (x = y - 1; x >= 0; x--) { + if (buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r' + || buffer[x] == '\t' || buffer[x] == 13) + buffer[x] = '\x0'; + else + break; + } + + /* strip beginning of string (by shifting) */ + y = (int) strlen(buffer); + for (x = 0; x < y; x++) { + if (buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r' + || buffer[x] == '\t' || buffer[x] == 13) + continue; + else + break; + } + if (x > 0) { + for (z = x; z < y; z++) + buffer[z - x] = buffer[z]; + buffer[y - x] = '\x0'; + } + + return; +} + +/******************************************************************/ +/*********************** SECURITY FUNCTIONS ***********************/ +/******************************************************************/ +/* drops privileges */ +int drop_privileges(char *user, char *group) { + uid_t uid = -1; + gid_t gid = -1; + struct group *grp = NULL; + struct passwd *pw = NULL; + int result = OK; + + /* only drop privileges if we're running as root, so we don't interfere with being debugged while running as some random user */ + if (getuid() != 0) + return OK; + + /* set effective group ID */ + if (group != NULL) { + + /* see if this is a group name */ + if (strspn(group, "0123456789") < strlen(group)) { + grp = (struct group *) getgrnam(group); + if (grp != NULL) { + gid = (gid_t) (grp->gr_gid); + } else { + printf("Warning: Could not get group entry for '%s'\n", group); + } + } + + /* else we were passed the GID */ + else + gid = (gid_t) atoi(group); + + /* set effective group ID if other than current EGID */ + if (gid != getegid()) { + + if (setgid(gid) == -1) { + printf("Warning: Could not set effective GID=%d\n", (int) gid); + result = ERROR; + } + } + } + + /* set effective user ID */ + if (user != NULL) { + + /* see if this is a user name */ + if (strspn(user, "0123456789") < strlen(user)) { + pw = (struct passwd *) getpwnam(user); + if (pw != NULL) + uid = (uid_t) (pw->pw_uid); + else { + printf("Warning: Could not get passwd entry for '%s'\n", user); + } + } + + /* else we were passed the UID */ + else + uid = (uid_t) atoi(user); + +#ifdef HAVE_INITGROUPS + + if(uid!=geteuid()) { + + /* initialize supplementary groups */ + if(initgroups(user,gid)==-1) { + if(errno==EPERM) { + printf("Warning: Unable to change supplementary groups using initgroups() -- I hope you know what you're doing\n"); + } + else { + printf("Warning: Possibly root user failed dropping privileges with initgroups()\n"); + return ERROR; + } + } + } +#endif + if (setuid(uid) == -1) { + printf("Warning: Could not set effective UID=%d\n", (int) uid); + result = ERROR; + } + } + return result; +} + +/******************* + * + * Signal functions + * + *******************/ + +sighandler_t handle_signal(int sig_nr, sighandler_t signalhandler) { + struct sigaction new_sig, old_sig; + + new_sig.sa_handler = signalhandler; + sigemptyset(&new_sig.sa_mask); + new_sig.sa_flags = SA_RESTART; + if (sigaction(sig_nr, &new_sig, &old_sig) < 0) + return SIG_ERR; + return old_sig.sa_handler; +} + +void check_sig(int signr) { + char buffer[MAX_LOGMESSAGE_SIZE]; + + switch (signr) { + case SIGINT: + LOG(0, "Caught SIGINT - Good bye\n"); + exit(EXIT_SUCCESS); + break; + + case SIGTERM: + LOG(0, "Caught Termination Signal - Astalavista... baby\n"); + exit(EXIT_SUCCESS); + break; + + case SIGHUP: + LOG(0, "Caught SIGHUP - reloading configuration\n"); + sighup_detected = TRUE; + + process_configfile(config_file); + if (check_needed_config_options() != 0) { + LOG(0, "There is an error in the config! Exiting...\n"); + exit(EXIT_FAILURE); + } + prepare_vars(); + LOG(0, "Configuration reload succesfull.\n"); + + break; + + default: + snprintf(buffer, sizeof(buffer - 1), + "Caught the Signal '%d' but don't care about this.\n", signr); + LOG(2, buffer); + break; + } +} + +/* This won't compile on Solaris and HP UX */ + +#ifdef HAVE_STRUCT_DIRENT_D_TYPE +int is_file(const struct dirent *d) { + if (d->d_type == DT_REG) + return 1; + + //free(d); + return 0; +} +#endif + diff --git a/subst.in b/subst.in new file mode 100755 index 0000000..9e8685b --- /dev/null +++ b/subst.in @@ -0,0 +1,142 @@ +#!@PERL@ -w + +my ${prefix}="@prefix@"; + +my ${exec_prefix}="@exec_prefix@"; + +my ${datarootdir}="@datarootdir@"; + +my ${datadir}="@datadir@"; + +my $PERL="@PERL@"; +my $PERL_LIB_PATH="@PERL_LIB_PATH@"; +if( $PERL_LIB_PATH ne "no" ){ + $PERL_LIB_PATH_CODE = "use lib '".$PERL_LIB_PATH."';"; +}else{ + $PERL_LIB_PATH = ""; + $PERL_LIB_PATH_CODE = ""; +} +my $SHELL="@SHELL@"; +my $STRIP="@STRIP@"; +my $INSTALL="@INSTALL@"; +if($INSTALL =~ /^\.\//){ + $INSTALL =~ s/^\.\//\.\.\//; +} +my $INSTALL_OPTS="@INSTALL_OPTS@"; +my $DEBUG="@DEBUG@"; +my $PERFDATA_DIR="@PERFDATA_DIR@"; +my $PERFDATA_LOG="@PERFDATA_LOG@"; +my $PERFDATA_SPOOL_DIR="@PERFDATA_SPOOL_DIR@"; +my $RRDTOOL="@RRDTOOL@"; +my $RRDS="@RRDS@"; +my $XML_STRUCTURE_VERSION="@XML_STRUCTURE_VERSION@"; +my $PKG_REL_DATE="@PKG_REL_DATE@"; +my $PKG_VERSION="@PKG_VERSION@"; +my $PKG_NAME="@PKG_NAME@"; +my $BASE_URL="@BASE_URL@"; +my $HTTPD_CONF="@HTTPD_CONF@"; +my $init_dir="@init_dir@"; +my $npcd_name="@npcd_name@"; +my $pp_pl_name="@pp_pl_name@"; +my $nagios_user="@nagios_user@"; +my $nagios_grp="@nagios_grp@"; +my $libexecdir="@libexecdir@"; # put all --with-vars before directories +my $localstatedir="@localstatedir@"; +my $KOHANA="@KOHANA@"; +my $KOHANA_SYSTEM="@KOHANA_SYSTEM@"; +my $libdir="@libdir@"; +my $sysconfdir="@sysconfdir@"; +my $host_os="@host_os@"; +my $ac_configure_args="@ac_configure_args@"; + +my $sbindir="@sbindir@"; +my $bindir="@bindir@"; +my $srcdir="@srcdir@"; + +my $CC="@CC@"; +my $CFLAGS="@CFLAGS@"; +my $DEFS="@DEFS@"; +my $LDFLAGS="@LDFLAGS@"; +my $LIBS="@LIBS@"; +my $MOD_CFLAGS="@MOD_CFLAGS@"; +my $MOD_LDFLAGS="@MOD_LDFLAGS@"; + +my $CP="@CP@"; + + +while ($f = shift @ARGV) { + + if (-x "/bin/mktemp") { + $TEMP = `/bin/mktemp $f.$$.XXXXXX`; + die 'Cannot make temporary file $TEMP' if($?); + chomp $TEMP; + } else { + $XXXXXX = rand; + $TEMP = "$f.$$.$XXXXXX"; + } + + open(IN,"<$f.in"); + open(OUT,">$TEMP") || die 'Cannot make temporary file $TEMP'; + + while () { + s|\@PERL\@|$PERL|g; + s|\@PERL_LIB_PATH\@|$PERL_LIB_PATH|g; + s|\@PERL_LIB_PATH_CODE\@|$PERL_LIB_PATH_CODE|g; + s|\@SHELL\@|$SHELL|g; + s|\@STRIP\@|$STRIP|g; + s|\@INSTALL\@|$INSTALL|g; + s|\@INSTALL_OPTS\@|$INSTALL_OPTS|g; + s|\@DEBUG\@|$DEBUG|g; + s|\@PERFDATA_DIR\@|$PERFDATA_DIR|g; + s|\@PERFDATA_LOG\@|$PERFDATA_LOG|g; + s|\@PERFDATA_SPOOL_DIR\@|$PERFDATA_SPOOL_DIR|g; + s|\@RRDTOOL\@|$RRDTOOL|g; + s|\@RRDS\@|$RRDS|g; + s|\@XML_STRUCTURE_VERSION\@|$XML_STRUCTURE_VERSION|g; + s|\@PKG_REL_DATE\@|$PKG_REL_DATE|g; + s|\@PKG_VERSION\@|$PKG_VERSION|g; + s|\@PKG_NAME\@|$PKG_NAME|g; + s|\@BASE_URL\@|$BASE_URL|g; + s|\@HTTPD_CONF\@|$HTTPD_CONF|g; + s|\@npcd_name\@|$npcd_name|g; + s|\@pp_pl_name\@|$pp_pl_name|g; + s|\@nagios_user\@|$nagios_user|g; + s|\@nagios_grp\@|$nagios_grp|g; + s|\@libexecdir\@|$libexecdir|g; # put all --with-vars before directories + s|\@localstatedir\@|$localstatedir|g; + s|\@KOHANA\@|$KOHANA|g; + s|\@KOHANA_SYSTEM\@|$KOHANA_SYSTEM|g; + s|\@libdir\@|$libdir|g; + s|\@init_dir\@|$init_dir|g; + s|\@sysconfdir\@|$sysconfdir|g; + s|\@datarootdir\@|$datarootdir|g; + s|\@datadir\@|$datadir|g; + s|\@sbindir\@|$sbindir|g; + s|\@bindir\@|$bindir|g; + s|\@srcdir\@|$srcdir|g; + s|\@CC\@|$CC|g; + s|\@CFLAGS\@|$CFLAGS|g; + s|\@DEFS\@|$DEFS|g; + s|\@LDFLAGS\@|$LDFLAGS|g; + s|\@MOD_LDFLAGS\@|$MOD_LDFLAGS|g; + s|\@MOD_CFLAGS\@|$MOD_CFLAGS|g; + s|\@LIBS\@|$LIBS|g; + s|\@CP\@|$CP|g; + s|\@prefix\@|$prefix|g; + s|\@host_os\@|$host_os|g; + s|\@ac_configure_args\@|$ac_configure_args|g; + s|\$\{exec_prefix\}|$exec_prefix|g; # must be next to last + s|\$\{prefix\}|$prefix|g; # must be last + print OUT $_; + } + + close IN; + close OUT; + + if ((! -e $f) || (`diff $f $TEMP`)) { + `mv $TEMP $f`; + } else { + unlink $TEMP; + } + +} diff --git a/summary.in b/summary.in new file mode 100644 index 0000000..43b4242 --- /dev/null +++ b/summary.in @@ -0,0 +1,86 @@ +#@PERL@ -w +@PERL_LIB_PATH_CODE@ + +my %conf = ( + VERSION => "@PKG_VERSION@", + USE_RRDs => "@RRDS@", + DEBUG_LEVEL => "@DEBUG@", + PERL_LIB_PATH => "@PERL_LIB_PATH@" +); + +if ( $conf{USE_RRDs} == 1 ) { + unless ( eval "use RRDs;1" ) { + $conf{USE_RRDs} = 0; + } +} + +if($conf{USE_RRDs} == 1){ + $rrds_version = $RRDs::VERSION; +} + +my $RRD_BINARY = "@RRDTOOL@"; +@T = `$RRD_BINARY`; +@v = split(/ /,$T[0]); +$rrdtool_version = $v[1]; +$rrdtool_message = ""; +if($rrdtool_version == ""){ + $rrdtool_message = "WARNING: \"$RRD_BINARY\" does not look like rrdtool"; +}else{ + $rrdtool_message = "$RRD_BINARY Version $rrdtool_version"; +} + +printf ("\n\n"); +printf ("*** Configuration summary for %s-%s %s ***","@PKG_NAME@","@PKG_VERSION@","@PKG_REL_DATE@"); +printf ("\n\n"); +printf (" General Options:\n"); +printf (" ------------------------- -------------------\n"); +printf (" Nagios user/group: %s %s\n","@nagios_user@","@nagios_grp@"); +printf (" Install directory: %s\n","@prefix@"); +printf (" HTML Dir: %s\n","@datarootdir@"); +printf (" Config Dir: %s\n","@sysconfdir@"); +printf (" Location of rrdtool binary: %s\n",$rrdtool_message); +printf (" RRDs Perl Modules: %s\n","*** NOT FOUND ***") if($conf{USE_RRDs} == 0); +printf (" RRDs Perl Modules: %s (Version %s)\n","FOUND", $rrds_version) if($conf{USE_RRDs} == 1); +printf (" RRDs Perl search path: %s\n","@PERL_LIB_PATH@") if($conf{PERL_LIB_PATH} ne ""); +printf (" RRD Files stored in: %s\n","@PERFDATA_DIR@"); +printf (" process_perfdata.pl Logfile: %s\n","@PERFDATA_LOG@"); +printf (" Perfdata files (NPCD) stored in: %s\n","@PERFDATA_SPOOL_DIR@"); +printf ("\n"); +printf (" Web Interface Options:\n"); +printf (" ------------------------- -------------------\n"); +printf (" HTML URL: %s\n","http://localhost@BASE_URL@"); +printf (" Apache Config File: %s\n","@HTTPD_CONF@/@PKG_NAME@.conf"); +if( $#ARGV == -1){ +printf ("\n\n"); +printf (" Review the options above for accuracy. If they look okay,\n"); +printf (" type 'make all' to compile.\n"); +} +if($conf{USE_RRDs} == 0){ + print "\n\n"; + print " WARNING: The RRDs Perl Modules are not found on your system\n"; + print " Using RRDs will speedup things in larger installations.\n"; +} + +if($ENV{DESTDIR}){ + print "\n\n"; + print " WARNING: \$DESTDIR is set to $ENV{DESTDIR} \n"; +} + +if($conf{DEBUG_LEVEL} != 0){ + printf ("\n\n"); + printf (" Found PERL at: %s\n","@PERL@"); + printf (" Found SHELL at: %s\n","@SHELL@"); + printf (" Debug Level: %s\n","@DEBUG@"); + printf (" Libexecdir: %s\n","@libexecdir@"); + printf (" localstatedir: %s\n","@localstatedir@"); + printf (" libdir: %s\n","@libdir@"); + printf (" sysconfdir: %s\n","@sysconfdir@"); + printf (" datarootdir: %s\n","@datarootdir@"); + printf (" sbindir: %s\n","@sbindir@"); + printf (" bindir: %s\n","@bindir@"); + printf (" System: %s\n","@host_os@"); +} + +print "\n\n"; + +exit 0;