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_lastupdate, NULL)
50 PHP_FE(rrd_create, NULL)
51 PHP_FE(rrdtool_info, NULL)
52 PHP_FE(rrdtool_logo_guid, NULL)
53 {NULL, NULL, NULL}
54 };
56 zend_module_entry rrdtool_module_entry = {
57 #if ZEND_EXTENSION_API_NO >= 220050617
58 STANDARD_MODULE_HEADER_EX, NULL,
59 NULL, /* dependencies */
60 #else
61 STANDARD_MODULE_HEADER,
62 #endif
63 "rrdtool", /* name */
64 rrdtool_functions, /* functions */
65 PHP_MINIT(rrdtool), /* module_startup_func */
66 PHP_MSHUTDOWN(rrdtool), /* module_shutdown_func */
67 NULL, /* request_startup_func */
68 NULL, /* request_shutdown_func */
69 PHP_MINFO(rrdtool), /* info_func */
70 NO_VERSION_YET,
71 STANDARD_MODULE_PROPERTIES
72 };
74 #ifdef COMPILE_DL_RRDTOOL
75 ZEND_GET_MODULE(rrdtool)
76 #endif
78 #ifdef COMPILE_DL_RRDTOOL
79 #define PHP_RRD_VERSION_STRING "1.2.x extension"
80 #else
81 #define PHP_RRD_VERSION_STRING "1.2.x bundled"
82 #endif
84 /* {{{ PHP_MINIT_FUNCTION */
85 PHP_MINIT_FUNCTION(rrdtool)
86 {
87 php_register_info_logo(RRDTOOL_LOGO_GUID , "image/gif", rrdtool_logo , sizeof(rrdtool_logo));
89 return SUCCESS;
90 }
91 /* }}} */
93 /* {{{ PHP_MSHUTDOWN_FUNCTION */
94 PHP_MSHUTDOWN_FUNCTION(rrdtool)
95 {
96 php_unregister_info_logo(RRDTOOL_LOGO_GUID);
98 return SUCCESS;
99 }
100 /* }}} */
102 /* {{{ PHP_MINFO_FUNCTION */
103 PHP_MINFO_FUNCTION(rrdtool)
104 {
105 php_info_print_box_start(1);
106 PUTS("<a href=\"http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/\" target=\"rrdtool\"><img border=\"0\" src=\"");
107 if (SG(request_info).request_uri) {
108 PUTS(SG(request_info).request_uri);
109 }
110 PUTS("?="RRDTOOL_LOGO_GUID"\" alt=\"ClamAV logo\" /></a>\n");
111 php_printf("<h1 class=\"p\">rrdtool Version %s</h1>\n", PHP_RRD_VERSION_STRING);
112 php_info_print_box_end();
113 php_info_print_table_start();
114 php_info_print_table_row(2, "rrdtool support", "enabled");
115 php_info_print_table_end();
116 }
117 /* }}} */
119 /* {{{ proto mixed rrd_graph(string file, array args_arr, int argc)
120 Creates a graph based on options passed via an array */
121 PHP_FUNCTION(rrd_graph)
122 {
123 pval *file, *args, *p_argc;
124 pval *entry;
125 zval *p_calcpr;
126 HashTable *args_arr;
127 int i, xsize, ysize, argc;
128 double ymin, ymax;
129 char **argv, **calcpr;
132 if ( rrd_test_error() )
133 rrd_clear_error();
135 if ( (ZEND_NUM_ARGS() >= 3 && ZEND_NUM_ARGS() <= 6) &&
136 zend_get_parameters(ht, 3, &file, &args, &p_argc) == SUCCESS)
137 {
138 if ( args->type != IS_ARRAY )
139 {
140 php_error(E_WARNING, "2nd Variable passed to rrd_graph is not an array!\n");
141 RETURN_FALSE;
142 }
144 convert_to_long(p_argc);
145 convert_to_string(file);
147 convert_to_array(args);
148 args_arr = args->value.ht;
150 argc = p_argc->value.lval + 3;
151 argv = (char **) emalloc(argc * sizeof(char *));
153 argv[0] = "dummy";
154 argv[1] = estrdup("graph");
155 argv[2] = estrdup(file->value.str.val);
157 for (i = 3; i < argc; i++)
158 {
159 pval **dataptr;
161 if ( zend_hash_get_current_data(args_arr, (void *) &dataptr) == FAILURE )
162 continue;
164 entry = *dataptr;
166 if ( entry->type != IS_STRING )
167 convert_to_string(entry);
169 argv[i] = estrdup(entry->value.str.val);
171 if ( i < argc )
172 zend_hash_move_forward(args_arr);
173 }
175 optind = 0; opterr = 0;
176 if ( rrd_graph(argc-1, &argv[1], &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) != -1 )
177 {
178 array_init(return_value);
179 add_assoc_long(return_value, "xsize", xsize);
180 add_assoc_long(return_value, "ysize", ysize);
181 add_assoc_double(return_value, "ymin", ymin);
182 add_assoc_double(return_value, "ymax", ymax);
184 MAKE_STD_ZVAL(p_calcpr);
185 array_init(p_calcpr);
187 if (calcpr)
188 {
189 for (i = 0; calcpr[i]; i++)
190 {
191 add_next_index_string(p_calcpr, calcpr[i], 1);
192 free(calcpr[i]);
193 }
194 free(calcpr);
195 }
196 zend_hash_update(return_value->value.ht, "calcpr", sizeof("calcpr"),
197 (void *)&p_calcpr, sizeof(zval *), NULL);
198 }
199 else
200 {
201 RETVAL_FALSE;
202 }
203 for (i = 1; i < argc; i++)
204 efree(argv[i]);
206 efree(argv);
207 }
208 else
209 {
210 WRONG_PARAM_COUNT;
211 }
212 return;
213 }
214 /* }}} */
216 /* {{{ proto mixed rrd_fetch(string file, array args_arr, int p_argc)
217 Fetch info from an RRD file */
218 PHP_FUNCTION(rrd_fetch)
219 {
220 pval *file, *args, *p_argc;
221 pval *entry;
222 pval *p_start, *p_end, *p_step, *p_ds_cnt;
223 HashTable *args_arr;
224 zval *p_ds_namv, *p_data;
225 int i, j, argc;
226 time_t start, end;
227 unsigned long step, ds_cnt;
228 char **argv, **ds_namv;
229 rrd_value_t *data, *datap;
231 if ( rrd_test_error() )
232 rrd_clear_error();
234 if ( ZEND_NUM_ARGS() == 3 &&
235 zend_get_parameters(ht, 3, &file, &args, &p_argc) == SUCCESS)
236 {
237 if ( args->type != IS_ARRAY )
238 {
239 php_error(E_WARNING, "2nd Variable passed to rrd_fetch is not an array!\n");
240 RETURN_FALSE;
241 }
243 convert_to_long(p_argc);
244 convert_to_string(file);
246 convert_to_array(args);
247 args_arr = args->value.ht;
249 argc = p_argc->value.lval + 3;
250 argv = (char **) emalloc(argc * sizeof(char *));
252 argv[0] = "dummy";
253 argv[1] = estrdup("fetch");
254 argv[2] = estrdup(file->value.str.val);
256 for (i = 3; i < argc; i++)
257 {
258 pval **dataptr;
260 if ( zend_hash_get_current_data(args_arr, (void *) &dataptr) == FAILURE )
261 continue;
263 entry = *dataptr;
265 if ( entry->type != IS_STRING )
266 convert_to_string(entry);
268 argv[i] = estrdup(entry->value.str.val);
270 if ( i < argc )
271 zend_hash_move_forward(args_arr);
272 }
274 optind = 0; opterr = 0;
276 if ( rrd_fetch(argc-1, &argv[1], &start,&end,&step,&ds_cnt,&ds_namv,&data) != -1 )
277 {
278 array_init(return_value);
279 add_assoc_long(return_value, "start", start);
280 add_assoc_long(return_value, "end", end);
281 add_assoc_long(return_value, "step", step);
282 add_assoc_long(return_value, "ds_cnt", ds_cnt);
284 MAKE_STD_ZVAL(p_ds_namv);
285 MAKE_STD_ZVAL(p_data);
286 array_init(p_ds_namv);
287 array_init(p_data);
289 if (ds_namv)
290 {
291 for (i = 0; i < ds_cnt; i++)
292 {
293 add_next_index_string(p_ds_namv, ds_namv[i], 1);
294 free(ds_namv[i]);
295 }
296 free(ds_namv);
297 }
299 if (data)
300 {
301 datap = data;
303 for (i = start + step; i <= end; i += step)
304 for (j = 0; j < ds_cnt; j++)
305 add_next_index_double(p_data, *(datap++));
307 free(data);
308 }
310 zend_hash_update(return_value->value.ht, "ds_namv", sizeof("ds_namv"),
311 (void *)&p_ds_namv, sizeof(zval *), NULL);
312 zend_hash_update(return_value->value.ht, "data", sizeof("data"),
313 (void *)&p_data, sizeof(zval *), NULL);
314 }
315 else
316 {
317 RETVAL_FALSE;
318 }
319 for (i = 1; i < argc; i++)
320 efree(argv[i]);
322 efree(argv);
323 }
324 else
325 {
326 WRONG_PARAM_COUNT;
327 }
328 return;
329 }
330 /* }}} */
332 /* {{{ proto string rrd_error(void)
333 Get the error message set by the last rrd tool function call */
334 PHP_FUNCTION(rrd_error)
335 {
336 char *msg;
338 if ( rrd_test_error() )
339 {
340 msg = rrd_get_error();
342 RETVAL_STRING(msg, 1);
343 rrd_clear_error();
344 }
345 else
346 return;
347 }
348 /* }}} */
350 /* {{{ proto void rrd_clear_error(void)
351 Clear the error set by the last rrd tool function call */
352 PHP_FUNCTION(rrd_clear_error)
353 {
354 if ( rrd_test_error() )
355 rrd_clear_error();
357 return;
358 }
359 /* }}} */
361 /* {{{ proto int rrd_update(string file, string opt)
362 Update an RRD file with values specified */
363 PHP_FUNCTION(rrd_update)
364 {
365 pval *file, *opt;
366 char **argv;
368 if ( rrd_test_error() )
369 rrd_clear_error();
371 if ( ZEND_NUM_ARGS() == 2 &&
372 zend_get_parameters(ht, 2, &file, &opt) == SUCCESS )
373 {
374 convert_to_string(file);
375 convert_to_string(opt);
377 argv = (char **) emalloc(4 * sizeof(char *));
379 argv[0] = "dummy";
380 argv[1] = estrdup("update");
381 argv[2] = estrdup(file->value.str.val);
382 argv[3] = estrdup(opt->value.str.val);
384 optind = 0; opterr = 0;
385 if ( rrd_update(3, &argv[1]) != -1 )
386 {
387 RETVAL_TRUE;
388 }
389 else
390 {
391 RETVAL_FALSE;
392 }
393 efree(argv[1]); efree(argv[2]); efree(argv[3]);
394 efree(argv);
395 }
396 else
397 {
398 WRONG_PARAM_COUNT;
399 }
400 return;
401 }
402 /* }}} */
404 /* {{{ proto int rrd_last(string file)
405 Gets last update time of an RRD file */
406 PHP_FUNCTION(rrd_last)
407 {
408 pval *file;
409 unsigned long retval;
411 char **argv = (char **) emalloc(3 * sizeof(char *));
413 if ( rrd_test_error() )
414 rrd_clear_error();
416 if (zend_get_parameters(ht, 1, &file) == SUCCESS)
417 {
418 convert_to_string(file);
420 argv[0] = "dummy";
421 argv[1] = estrdup("last");
422 argv[2] = estrdup(file->value.str.val);
424 optind = 0; opterr = 0;
425 retval = rrd_last(2, &argv[1]);
427 efree(argv[1]); efree(argv[2]);
428 efree(argv);
429 RETVAL_LONG(retval);
430 }
431 else
432 {
433 WRONG_PARAM_COUNT;
434 }
435 return;
436 }
437 /* }}} */
439 /* {{{ proto int rrd_lastupdate(string file)
440 Gets last update time and data of an RRD file */
441 PHP_FUNCTION(rrd_lastupdate)
442 {
443 pval *file;
444 zval *p_ds_namv,*p_last_ds;
445 time_t last_update;
446 char **ds_namv;
447 char **last_ds;
448 int argc;
449 unsigned long ds_cnt, i;
450 char **argv = (char **) emalloc(3 * sizeof(char *));
452 //char **argv = (char **) emalloc(3 * sizeof(char *));
454 if ( rrd_test_error() )
455 rrd_clear_error();
457 if (zend_get_parameters(ht, 1, &file) == SUCCESS)
458 {
459 convert_to_string(file);
461 argv[0] = "dummy";
462 argv[1] = estrdup("last");
463 argv[2] = estrdup(file->value.str.val);
466 if ( rrd_lastupdate(2, &argv[1],&last_update,&ds_cnt, &ds_namv, &last_ds) !=-1 ) {
467 array_init(return_value);
468 add_assoc_long(return_value, "time", last_update);
470 MAKE_STD_ZVAL(p_ds_namv);
471 MAKE_STD_ZVAL(p_last_ds);
472 array_init(p_ds_namv);
473 array_init(p_last_ds);
475 if (ds_namv) {
476 for (i = 0; i < ds_cnt; i++)
477 {
478 add_next_index_string(p_ds_namv, ds_namv[i], 1);
479 free(ds_namv[i]);
480 }
481 free(ds_namv);
482 }
484 if (last_ds) {
485 for (i = 0; i < ds_cnt; i++)
486 {
487 add_next_index_string(p_last_ds, last_ds[i], 1);
488 free(last_ds[i]);
489 }
490 free(last_ds);
492 }
493 zend_hash_update(return_value->value.ht, "ds_name", sizeof("ds_namv"),
494 (void *)&p_ds_namv, sizeof(zval *), NULL);
495 zend_hash_update(return_value->value.ht, "last_ds", sizeof("last_ds"),
496 (void *)&p_last_ds, sizeof(zval *), NULL);
498 }
499 efree(argv);
501 // RETVAL_LONG(retval);
502 }
503 else
504 {
505 WRONG_PARAM_COUNT;
506 }
507 return;
508 }
510 /* }}} */
512 /* {{{ proto int rrd_create(string file, array args_arr, int argc)
513 Create an RRD file with the options passed (passed via array) */
514 PHP_FUNCTION(rrd_create)
515 {
516 pval *file, *args, *p_argc;
517 pval *entry;
518 char **argv;
519 HashTable *args_arr;
520 int argc, i;
522 if ( rrd_test_error() )
523 rrd_clear_error();
525 if ( ZEND_NUM_ARGS() == 3 &&
526 getParameters(ht, 3, &file, &args, &p_argc) == SUCCESS )
527 {
528 if ( args->type != IS_ARRAY )
529 {
530 php_error(E_WARNING, "2nd Variable passed to rrd_create is not an array!\n");
531 RETURN_FALSE;
532 }
534 convert_to_long(p_argc);
535 convert_to_string(file);
537 convert_to_array(args);
538 args_arr = args->value.ht;
539 zend_hash_internal_pointer_reset(args_arr);
541 argc = p_argc->value.lval + 3;
542 argv = (char **) emalloc(argc * sizeof(char *));
544 argv[0] = "dummy";
545 argv[1] = estrdup("create");
546 argv[2] = estrdup(file->value.str.val);
548 for (i = 3; i < argc; i++)
549 {
550 pval **dataptr;
552 if ( zend_hash_get_current_data(args_arr, (void *) &dataptr) == FAILURE )
553 continue;
555 entry = *dataptr;
557 if ( entry->type != IS_STRING )
558 convert_to_string(entry);
560 argv[i] = estrdup(entry->value.str.val);
562 if ( i < argc )
563 zend_hash_move_forward(args_arr);
564 }
566 optind = 0; opterr = 0;
568 if ( rrd_create(argc-1, &argv[1]) != -1 )
569 {
570 RETVAL_TRUE;
571 }
572 else
573 {
574 RETVAL_FALSE;
575 }
576 for (i = 1; i < argc; i++)
577 efree(argv[i]);
579 efree(argv);
580 }
581 else
582 {
583 WRONG_PARAM_COUNT;
584 }
585 return;
586 }
587 /* }}} */
589 PHP_FUNCTION(rrdtool_info)
590 {
592 if (ZEND_NUM_ARGS()!=0) {
593 ZEND_WRONG_PARAM_COUNT();
594 RETURN_FALSE;
595 }
597 PUTS("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n");
598 PUTS("<html>");
599 PUTS("<head>\n");
600 PUTS("<style type=\"text/css\"><!--");
601 PUTS("body {background-color: #ffffff; color: #000000;}");
602 PUTS("body, td, th, h1, h2 {font-family: sans-serif;}");
603 PUTS("pre {margin: 0px; font-family: monospace;}");
604 PUTS("a:link {color: #000099; text-decoration: none; background-color: #ffffff;}");
605 PUTS("a:hover {text-decoration: underline;}");
606 PUTS("table {border-collapse: collapse;}");
607 PUTS(".center {text-align: center;}");
608 PUTS(".center table { margin-left: auto; margin-right: auto; text-align: left;}");
609 PUTS(".center th { text-align: center !important; }");
610 PUTS("td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}");
611 PUTS("h1 {font-size: 150%;}");
612 PUTS("h2 {font-size: 125%;}");
613 PUTS(".p {text-align: left;}");
614 PUTS(".e {background-color: #ccccff; font-weight: bold; color: #000000;}");
615 PUTS(".h {background-color: #9999cc; font-weight: bold; color: #000000;}");
616 PUTS(".v {background-color: #cccccc; color: #000000;}");
617 PUTS("i {color: #666666; background-color: #cccccc;}");
618 PUTS("img {float: right; border: 0px;}");
619 PUTS("hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}");
620 PUTS("//--></style>");
621 PUTS("<title>rrdtool_info()</title>");
622 PUTS("</head>\n");
623 PUTS("<body><div class=\"center\">\n");
625 php_info_print_box_start(1);
626 PUTS("<a href=\"http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/\" target=\"rrdtool\"><img border=\"0\" src=\"");
627 if (SG(request_info).request_uri) {
628 PUTS(SG(request_info).request_uri);
629 }
630 PUTS("?="RRDTOOL_LOGO_GUID"\" alt=\"ClamAV logo\" /></a>\n");
631 php_printf("<h1 class=\"p\">rrdtool Version %s</h1>\n", PHP_RRD_VERSION_STRING);
632 php_info_print_box_end();
633 php_info_print_table_start();
634 php_info_print_table_row(2, "System", PHP_UNAME );
635 php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__ );
636 php_info_print_table_row(2, "rrdtool Support","Enabled");
637 php_info_print_table_end();
639 PUTS("<h2>RRDTOOL Copyright</h2>\n");
640 php_info_print_box_start(0);
641 PUTS("COPYRIGHT STATEMENT FOLLOWS THIS LINE</p>\n<blockquote>\n");
642 PUTS("<p>Portions copyright 2005 by Dale Walsh (buildsmart@daleenterprise.com).</p>\n");
643 PUTS("<p>Portions relating to rrdtool 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Tobias Oetiker.</p>\n");
644 php_info_print_box_end();
645 PUTS("<h2>RRDTOOL License</h2>\n");
646 php_info_print_box_start(0);
647 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>");
648 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\" ");
649 PUTS("includes all programs that utilize the library. Credit must be given in user-accessible documentation.</p>\n");
650 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, ");
651 PUTS("with respect to this code and accompanying documentation.</p>\n");
652 php_info_print_box_end();
653 PUTS("<h2>Special Thanks</h2>\n");
654 php_info_print_box_start(0);
655 PUTS("<p>Perl by Larry Wall");
656 PUTS("<p>gd library by Thomas Boutell");
657 PUTS("<p>gifcode from David Koblas");
658 PUTS("<p>libpng by Glenn Randers-Pehrson / Andreas Eric Dilger / Guy Eric Schalnat");
659 PUTS("<p>cgilib by Martin Schulze");
660 PUTS("<p>zlib by Jean-loup Gailly and Mark Adler");
661 PUTS("<p>Portions relating to php4 and php5 bindings, Dale Walsh (buildsmart@daleenterprise.com)");
662 php_info_print_box_end();
664 PUTS("</div></body></html>");
665 }
666 /* }}} */
668 PHP_FUNCTION(rrdtool_logo_guid)
669 {
670 if (ZEND_NUM_ARGS() != 0) {
671 WRONG_PARAM_COUNT;
672 }
674 RETURN_STRINGL(RRDTOOL_LOGO_GUID, sizeof(RRDTOOL_LOGO_GUID)-1, 1);
675 }
676 /* }}} */
678 #endif /* HAVE_RRDTOOL */
680 /*
681 * Local variables:
682 * tab-width: 4
683 * c-basic-offset: 4
684 * End:
685 * vim600: noet sw=4 ts=4 fdm=marker
686 * vim<600: noet sw=4 ts=4
687 */