Code

free step_list on error. fix for #317
[rrdtool-all.git] / contrib / php4 / rrdtool.c
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));
88         
89         return SUCCESS;
90 }
91 /* }}} */
93 /* {{{ PHP_MSHUTDOWN_FUNCTION */
94 PHP_MSHUTDOWN_FUNCTION(rrdtool)
95 {
96         php_unregister_info_logo(RRDTOOL_LOGO_GUID);
97         
98         return SUCCESS;
99 }
100 /* }}} */
102 /* {{{ PHP_MINFO_FUNCTION */
103 PHP_MINFO_FUNCTION(rrdtool)
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();
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)
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;
130     
132         if ( rrd_test_error() )
133                 rrd_clear_error();
134     
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                 }
143         
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 *));
152  
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                 }
174    
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);
186     
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;
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)
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;
230     
231         if ( rrd_test_error() )
232                 rrd_clear_error();
233     
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                 }
242         
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 *));
251  
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                 }
273   
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);
288    
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;
302  
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++));
306  
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;
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)
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;
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)
354         if ( rrd_test_error() )
355                 rrd_clear_error();
357         return;
359 /* }}} */
361 /* {{{ proto int rrd_update(string file, string opt) 
362         Update an RRD file with values specified */
363 PHP_FUNCTION(rrd_update)
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;
402 /* }}} */
404 /* {{{ proto int rrd_last(string file)
405         Gets last update time of an RRD file */
406 PHP_FUNCTION(rrd_last)
408         pval *file;
409         unsigned long retval;
411         char **argv = (char **) emalloc(3 * sizeof(char *));
412     
413         if ( rrd_test_error() )
414                 rrd_clear_error();
415     
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;
437 /* }}} */
439 /* {{{ proto int rrd_lastupdate(string file)
440         Gets last update time and data of an RRD file */
441 PHP_FUNCTION(rrd_lastupdate)
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);
465                 
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);
469                         
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;
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)
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);
536                 
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                 }
565   
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;
587 /* }}} */
589 PHP_FUNCTION(rrdtool_info)
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>");
666 /* }}} */
668 PHP_FUNCTION(rrdtool_logo_guid)
670         if (ZEND_NUM_ARGS() != 0) {
671                 WRONG_PARAM_COUNT;
672         }
674         RETURN_STRINGL(RRDTOOL_LOGO_GUID, sizeof(RRDTOOL_LOGO_GUID)-1, 1);
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  */