1 /*
2 *
3 * php_rrdtool.c
4 *
5 * PHP interface to RRD Tool. (for php4/zend)
6 *
7 *
8 * Joe Miller, <joeym@ibizcorp.com>, <joeym@inficad.com>
9 * iBIZ Technology Corp, SkyLynx / Inficad Communications
10 * 2/12/2000 & 7/18/2000
11 *
12 * Jeffrey Wheat <jeff@cetlink.net> - 10/01/2002
13 * - Fixed to build with php-4.2.3
14 *
15 * See README, INSTALL, and USAGE files for more details.
16 *
17 * $Id$
18 *
19 */
21 /* PHP Includes */
22 #include "php.h"
23 #include "php_logos.h"
24 #include "ext/standard/info.h"
25 #include "SAPI.h"
27 /* rrdtool includes */
28 #include "php_rrdtool.h"
29 #include "rrdtool_logo.h"
30 #include <rrd.h>
32 #ifdef HAVE_CONFIG_H
33 #include "php_config.h"
34 #endif
36 #if HAVE_RRDTOOL
38 /* If you declare any globals in php_rrdtool.h uncomment this:
39 ZEND_DECLARE_MODULE_GLOBALS(rrdtool)
40 */
42 function_entry rrdtool_functions[] = {
43 PHP_FE(rrd_graph, NULL)
44 PHP_FE(rrd_fetch, NULL)
45 PHP_FE(rrd_error, NULL)
46 PHP_FE(rrd_clear_error, NULL)
47 PHP_FE(rrd_update, NULL)
48 PHP_FE(rrd_last, NULL)
49 PHP_FE(rrd_create, NULL)
50 PHP_FE(rrdtool_info, NULL)
51 PHP_FE(rrdtool_logo_guid, NULL)
52 {NULL, NULL, NULL}
53 };
55 zend_module_entry rrdtool_module_entry = {
56 #if ZEND_EXTENSION_API_NO >= 220050617
57 STANDARD_MODULE_HEADER_EX, NULL,
58 NULL, /* dependencies */
59 #else
60 STANDARD_MODULE_HEADER,
61 #endif
62 "rrdtool", /* name */
63 rrdtool_functions, /* functions */
64 PHP_MINIT(rrdtool), /* module_startup_func */
65 PHP_MSHUTDOWN(rrdtool), /* module_shutdown_func */
66 NULL, /* request_startup_func */
67 NULL, /* request_shutdown_func */
68 PHP_MINFO(rrdtool), /* info_func */
69 NO_VERSION_YET,
70 STANDARD_MODULE_PROPERTIES
71 };
73 #ifdef COMPILE_DL_RRDTOOL
74 ZEND_GET_MODULE(rrdtool)
75 #endif
77 #ifdef COMPILE_DL_RRDTOOL
78 #define PHP_RRD_VERSION_STRING "1.2.x extension"
79 #else
80 #define PHP_RRD_VERSION_STRING "1.2.x bundled"
81 #endif
83 /* {{{ PHP_MINIT_FUNCTION */
84 PHP_MINIT_FUNCTION(rrdtool)
85 {
86 php_register_info_logo(RRDTOOL_LOGO_GUID , "image/gif", rrdtool_logo , sizeof(rrdtool_logo));
88 return SUCCESS;
89 }
90 /* }}} */
92 /* {{{ PHP_MSHUTDOWN_FUNCTION */
93 PHP_MSHUTDOWN_FUNCTION(rrdtool)
94 {
95 php_unregister_info_logo(RRDTOOL_LOGO_GUID);
97 return SUCCESS;
98 }
99 /* }}} */
101 /* {{{ PHP_MINFO_FUNCTION */
102 PHP_MINFO_FUNCTION(rrdtool)
103 {
104 php_info_print_box_start(1);
105 PUTS("<a href=\"http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/\" target=\"rrdtool\"><img border=\"0\" src=\"");
106 if (SG(request_info).request_uri) {
107 PUTS(SG(request_info).request_uri);
108 }
109 PUTS("?="RRDTOOL_LOGO_GUID"\" alt=\"ClamAV logo\" /></a>\n");
110 php_printf("<h1 class=\"p\">rrdtool Version %s</h1>\n", PHP_RRD_VERSION_STRING);
111 php_info_print_box_end();
112 php_info_print_table_start();
113 php_info_print_table_row(2, "rrdtool support", "enabled");
114 php_info_print_table_end();
115 }
116 /* }}} */
118 /* {{{ proto mixed rrd_graph(string file, array args_arr, int argc)
119 Creates a graph based on options passed via an array */
120 PHP_FUNCTION(rrd_graph)
121 {
122 pval *file, *args, *p_argc;
123 pval *entry;
124 zval *p_calcpr;
125 HashTable *args_arr;
126 int i, xsize, ysize, argc;
127 double ymin, ymax;
128 char **argv, **calcpr;
131 if ( rrd_test_error() )
132 rrd_clear_error();
134 if ( (ZEND_NUM_ARGS() >= 3 && ZEND_NUM_ARGS() <= 6) &&
135 zend_get_parameters(ht, 3, &file, &args, &p_argc) == SUCCESS)
136 {
137 if ( args->type != IS_ARRAY )
138 {
139 php_error(E_WARNING, "2nd Variable passed to rrd_graph is not an array!\n");
140 RETURN_FALSE;
141 }
143 convert_to_long(p_argc);
144 convert_to_string(file);
146 convert_to_array(args);
147 args_arr = args->value.ht;
149 argc = p_argc->value.lval + 3;
150 argv = (char **) emalloc(argc * sizeof(char *));
152 argv[0] = "dummy";
153 argv[1] = estrdup("graph");
154 argv[2] = estrdup(file->value.str.val);
156 for (i = 3; i < argc; i++)
157 {
158 pval **dataptr;
160 if ( zend_hash_get_current_data(args_arr, (void *) &dataptr) == FAILURE )
161 continue;
163 entry = *dataptr;
165 if ( entry->type != IS_STRING )
166 convert_to_string(entry);
168 argv[i] = estrdup(entry->value.str.val);
170 if ( i < argc )
171 zend_hash_move_forward(args_arr);
172 }
174 optind = 0; opterr = 0;
175 if ( rrd_graph(argc-1, &argv[1], &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) != -1 )
176 {
177 array_init(return_value);
178 add_assoc_long(return_value, "xsize", xsize);
179 add_assoc_long(return_value, "ysize", ysize);
180 add_assoc_double(return_value, "ymin", ymin);
181 add_assoc_double(return_value, "ymax", ymax);
183 MAKE_STD_ZVAL(p_calcpr);
184 array_init(p_calcpr);
186 if (calcpr)
187 {
188 for (i = 0; calcpr[i]; i++)
189 {
190 add_next_index_string(p_calcpr, calcpr[i], 1);
191 free(calcpr[i]);
192 }
193 free(calcpr);
194 }
195 zend_hash_update(return_value->value.ht, "calcpr", sizeof("calcpr"),
196 (void *)&p_calcpr, sizeof(zval *), NULL);
197 }
198 else
199 {
200 RETVAL_FALSE;
201 }
202 for (i = 1; i < argc; i++)
203 efree(argv[i]);
205 efree(argv);
206 }
207 else
208 {
209 WRONG_PARAM_COUNT;
210 }
211 return;
212 }
213 /* }}} */
215 /* {{{ proto mixed rrd_fetch(string file, array args_arr, int p_argc)
216 Fetch info from an RRD file */
217 PHP_FUNCTION(rrd_fetch)
218 {
219 pval *file, *args, *p_argc;
220 pval *entry;
221 pval *p_start, *p_end, *p_step, *p_ds_cnt;
222 HashTable *args_arr;
223 zval *p_ds_namv, *p_data;
224 int i, j, argc;
225 time_t start, end;
226 unsigned long step, ds_cnt;
227 char **argv, **ds_namv;
228 rrd_value_t *data, *datap;
230 if ( rrd_test_error() )
231 rrd_clear_error();
233 if ( ZEND_NUM_ARGS() == 3 &&
234 zend_get_parameters(ht, 3, &file, &args, &p_argc) == SUCCESS)
235 {
236 if ( args->type != IS_ARRAY )
237 {
238 php_error(E_WARNING, "2nd Variable passed to rrd_fetch is not an array!\n");
239 RETURN_FALSE;
240 }
242 convert_to_long(p_argc);
243 convert_to_string(file);
245 convert_to_array(args);
246 args_arr = args->value.ht;
248 argc = p_argc->value.lval + 3;
249 argv = (char **) emalloc(argc * sizeof(char *));
251 argv[0] = "dummy";
252 argv[1] = estrdup("fetch");
253 argv[2] = estrdup(file->value.str.val);
255 for (i = 3; i < argc; i++)
256 {
257 pval **dataptr;
259 if ( zend_hash_get_current_data(args_arr, (void *) &dataptr) == FAILURE )
260 continue;
262 entry = *dataptr;
264 if ( entry->type != IS_STRING )
265 convert_to_string(entry);
267 argv[i] = estrdup(entry->value.str.val);
269 if ( i < argc )
270 zend_hash_move_forward(args_arr);
271 }
273 optind = 0; opterr = 0;
275 if ( rrd_fetch(argc-1, &argv[1], &start,&end,&step,&ds_cnt,&ds_namv,&data) != -1 )
276 {
277 array_init(return_value);
278 add_assoc_long(return_value, "start", start);
279 add_assoc_long(return_value, "end", end);
280 add_assoc_long(return_value, "step", step);
281 add_assoc_long(return_value, "ds_cnt", ds_cnt);
283 MAKE_STD_ZVAL(p_ds_namv);
284 MAKE_STD_ZVAL(p_data);
285 array_init(p_ds_namv);
286 array_init(p_data);
288 if (ds_namv)
289 {
290 for (i = 0; i < ds_cnt; i++)
291 {
292 add_next_index_string(p_ds_namv, ds_namv[i], 1);
293 free(ds_namv[i]);
294 }
295 free(ds_namv);
296 }
298 if (data)
299 {
300 datap = data;
302 for (i = start; i <= end; i += step)
303 for (j = 0; j < ds_cnt; j++)
304 add_next_index_double(p_data, *(datap++));
306 free(data);
307 }
309 zend_hash_update(return_value->value.ht, "ds_namv", sizeof("ds_namv"),
310 (void *)&p_ds_namv, sizeof(zval *), NULL);
311 zend_hash_update(return_value->value.ht, "data", sizeof("data"),
312 (void *)&p_data, sizeof(zval *), NULL);
313 }
314 else
315 {
316 RETVAL_FALSE;
317 }
318 for (i = 1; i < argc; i++)
319 efree(argv[i]);
321 efree(argv);
322 }
323 else
324 {
325 WRONG_PARAM_COUNT;
326 }
327 return;
328 }
329 /* }}} */
331 /* {{{ proto string rrd_error(void)
332 Get the error message set by the last rrd tool function call */
333 PHP_FUNCTION(rrd_error)
334 {
335 char *msg;
337 if ( rrd_test_error() )
338 {
339 msg = rrd_get_error();
341 RETVAL_STRING(msg, 1);
342 rrd_clear_error();
343 }
344 else
345 return;
346 }
347 /* }}} */
349 /* {{{ proto void rrd_clear_error(void)
350 Clear the error set by the last rrd tool function call */
351 PHP_FUNCTION(rrd_clear_error)
352 {
353 if ( rrd_test_error() )
354 rrd_clear_error();
356 return;
357 }
358 /* }}} */
360 /* {{{ proto int rrd_update(string file, string opt)
361 Update an RRD file with values specified */
362 PHP_FUNCTION(rrd_update)
363 {
364 pval *file, *opt;
365 char **argv;
367 if ( rrd_test_error() )
368 rrd_clear_error();
370 if ( ZEND_NUM_ARGS() == 2 &&
371 zend_get_parameters(ht, 2, &file, &opt) == SUCCESS )
372 {
373 convert_to_string(file);
374 convert_to_string(opt);
376 argv = (char **) emalloc(4 * sizeof(char *));
378 argv[0] = "dummy";
379 argv[1] = estrdup("update");
380 argv[2] = estrdup(file->value.str.val);
381 argv[3] = estrdup(opt->value.str.val);
383 optind = 0; opterr = 0;
384 if ( rrd_update(3, &argv[1]) != -1 )
385 {
386 RETVAL_TRUE;
387 }
388 else
389 {
390 RETVAL_FALSE;
391 }
392 efree(argv[1]); efree(argv[2]); efree(argv[3]);
393 efree(argv);
394 }
395 else
396 {
397 WRONG_PARAM_COUNT;
398 }
399 return;
400 }
401 /* }}} */
403 /* {{{ proto int rrd_last(string file)
404 Gets last update time of an RRD file */
405 PHP_FUNCTION(rrd_last)
406 {
407 pval *file;
408 unsigned long retval;
410 char **argv = (char **) emalloc(3 * sizeof(char *));
412 if ( rrd_test_error() )
413 rrd_clear_error();
415 if (zend_get_parameters(ht, 1, &file) == SUCCESS)
416 {
417 convert_to_string(file);
419 argv[0] = "dummy";
420 argv[1] = estrdup("last");
421 argv[2] = estrdup(file->value.str.val);
423 optind = 0; opterr = 0;
424 retval = rrd_last(2, &argv[1]);
426 efree(argv[1]); efree(argv[2]);
427 efree(argv);
428 RETVAL_LONG(retval);
429 }
430 else
431 {
432 WRONG_PARAM_COUNT;
433 }
434 return;
435 }
436 /* }}} */
438 /* {{{ proto int rrd_create(string file, array args_arr, int argc)
439 Create an RRD file with the options passed (passed via array) */
440 PHP_FUNCTION(rrd_create)
441 {
442 pval *file, *args, *p_argc;
443 pval *entry;
444 char **argv;
445 HashTable *args_arr;
446 int argc, i;
448 if ( rrd_test_error() )
449 rrd_clear_error();
451 if ( ZEND_NUM_ARGS() == 3 &&
452 getParameters(ht, 3, &file, &args, &p_argc) == SUCCESS )
453 {
454 if ( args->type != IS_ARRAY )
455 {
456 php_error(E_WARNING, "2nd Variable passed to rrd_create is not an array!\n");
457 RETURN_FALSE;
458 }
460 convert_to_long(p_argc);
461 convert_to_string(file);
463 convert_to_array(args);
464 args_arr = args->value.ht;
465 zend_hash_internal_pointer_reset(args_arr);
467 argc = p_argc->value.lval + 3;
468 argv = (char **) emalloc(argc * sizeof(char *));
470 argv[0] = "dummy";
471 argv[1] = estrdup("create");
472 argv[2] = estrdup(file->value.str.val);
474 for (i = 3; i < argc; i++)
475 {
476 pval **dataptr;
478 if ( zend_hash_get_current_data(args_arr, (void *) &dataptr) == FAILURE )
479 continue;
481 entry = *dataptr;
483 if ( entry->type != IS_STRING )
484 convert_to_string(entry);
486 argv[i] = estrdup(entry->value.str.val);
488 if ( i < argc )
489 zend_hash_move_forward(args_arr);
490 }
492 optind = 0; opterr = 0;
494 if ( rrd_create(argc-1, &argv[1]) != -1 )
495 {
496 RETVAL_TRUE;
497 }
498 else
499 {
500 RETVAL_FALSE;
501 }
502 for (i = 1; i < argc; i++)
503 efree(argv[i]);
505 efree(argv);
506 }
507 else
508 {
509 WRONG_PARAM_COUNT;
510 }
511 return;
512 }
513 /* }}} */
515 PHP_FUNCTION(rrdtool_info)
516 {
518 if (ZEND_NUM_ARGS()!=0) {
519 ZEND_WRONG_PARAM_COUNT();
520 RETURN_FALSE;
521 }
523 PUTS("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n");
524 PUTS("<html>");
525 PUTS("<head>\n");
526 PUTS("<style type=\"text/css\"><!--");
527 PUTS("body {background-color: #ffffff; color: #000000;}");
528 PUTS("body, td, th, h1, h2 {font-family: sans-serif;}");
529 PUTS("pre {margin: 0px; font-family: monospace;}");
530 PUTS("a:link {color: #000099; text-decoration: none; background-color: #ffffff;}");
531 PUTS("a:hover {text-decoration: underline;}");
532 PUTS("table {border-collapse: collapse;}");
533 PUTS(".center {text-align: center;}");
534 PUTS(".center table { margin-left: auto; margin-right: auto; text-align: left;}");
535 PUTS(".center th { text-align: center !important; }");
536 PUTS("td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}");
537 PUTS("h1 {font-size: 150%;}");
538 PUTS("h2 {font-size: 125%;}");
539 PUTS(".p {text-align: left;}");
540 PUTS(".e {background-color: #ccccff; font-weight: bold; color: #000000;}");
541 PUTS(".h {background-color: #9999cc; font-weight: bold; color: #000000;}");
542 PUTS(".v {background-color: #cccccc; color: #000000;}");
543 PUTS("i {color: #666666; background-color: #cccccc;}");
544 PUTS("img {float: right; border: 0px;}");
545 PUTS("hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}");
546 PUTS("//--></style>");
547 PUTS("<title>rrdtool_info()</title>");
548 PUTS("</head>\n");
549 PUTS("<body><div class=\"center\">\n");
551 php_info_print_box_start(1);
552 PUTS("<a href=\"http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/\" target=\"rrdtool\"><img border=\"0\" src=\"");
553 if (SG(request_info).request_uri) {
554 PUTS(SG(request_info).request_uri);
555 }
556 PUTS("?="RRDTOOL_LOGO_GUID"\" alt=\"ClamAV logo\" /></a>\n");
557 php_printf("<h1 class=\"p\">rrdtool Version %s</h1>\n", PHP_RRD_VERSION_STRING);
558 php_info_print_box_end();
559 php_info_print_table_start();
560 php_info_print_table_row(2, "System", PHP_UNAME );
561 php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__ );
562 php_info_print_table_row(2, "rrdtool Support","Enabled");
563 php_info_print_table_end();
565 PUTS("<h2>RRDTOOL Copyright</h2>\n");
566 php_info_print_box_start(0);
567 PUTS("COPYRIGHT STATEMENT FOLLOWS THIS LINE</p>\n<blockquote>\n");
568 PUTS("<p>Portions copyright 2005 by Dale Walsh (buildsmart@daleenterprise.com).</p>\n");
569 PUTS("<p>Portions relating to rrdtool 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Tobias Oetiker.</p>\n");
570 php_info_print_box_end();
571 PUTS("<h2>RRDTOOL License</h2>\n");
572 php_info_print_box_start(0);
573 PUTS("<p><b>Permission has been granted to copy, distribute and modify rrd in any context without fee, including a commercial application, provided that this notice is present in user-accessible supporting documentation. </b></p>");
574 PUTS("<p>This does not affect your ownership of the derived work itself, and the intent is to assure proper credit for the authors of rrdtool, not to interfere with your productive use of rrdtool. If you have questions, ask. \"Derived works\" ");
575 PUTS("includes all programs that utilize the library. Credit must be given in user-accessible documentation.</p>\n");
576 PUTS("<p><b>This software is provided \"AS IS.\"</b> The copyright holders disclaim all warranties, either express or implied, including but not limited to implied warranties of merchantability and fitness for a particular purpose, ");
577 PUTS("with respect to this code and accompanying documentation.</p>\n");
578 php_info_print_box_end();
579 PUTS("<h2>Special Thanks</h2>\n");
580 php_info_print_box_start(0);
581 PUTS("<p>Perl by Larry Wall");
582 PUTS("<p>gd library by Thomas Boutell");
583 PUTS("<p>gifcode from David Koblas");
584 PUTS("<p>libpng by Glenn Randers-Pehrson / Andreas Eric Dilger / Guy Eric Schalnat");
585 PUTS("<p>cgilib by Martin Schulze");
586 PUTS("<p>zlib by Jean-loup Gailly and Mark Adler");
587 PUTS("<p>Portions relating to php4 and php5 bindings, Dale Walsh (buildsmart@daleenterprise.com)");
588 php_info_print_box_end();
590 PUTS("</div></body></html>");
591 }
592 /* }}} */
594 PHP_FUNCTION(rrdtool_logo_guid)
595 {
596 if (ZEND_NUM_ARGS() != 0) {
597 WRONG_PARAM_COUNT;
598 }
600 RETURN_STRINGL(RRDTOOL_LOGO_GUID, sizeof(RRDTOOL_LOGO_GUID)-1, 1);
601 }
602 /* }}} */
604 #endif /* HAVE_RRDTOOL */
606 /*
607 * Local variables:
608 * tab-width: 4
609 * c-basic-offset: 4
610 * End:
611 * vim600: noet sw=4 ts=4 fdm=marker
612 * vim<600: noet sw=4 ts=4
613 */