dad436720e3830610e185bbd7c2860ea47dc307d
[collection4.git] / src / action_list_graphs.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5
6 #include "action_list_graphs.h"
7 #include "common.h"
8 #include "graph.h"
9 #include "graph_ident.h"
10 #include "graph_list.h"
11 #include "utils_cgi.h"
12
13 #include <fcgiapp.h>
14 #include <fcgi_stdio.h>
15
16 #define RESULT_LIMIT 50
17
18 struct callback_data_s
19 {
20   graph_config_t *cfg;
21   int limit;
22   _Bool first;
23 };
24 typedef struct callback_data_s callback_data_t;
25
26 static int json_begin_graph (graph_config_t *cfg) /* {{{ */
27 {
28   char desc[1024];
29
30   if (cfg == NULL)
31     return (EINVAL);
32
33   graph_get_title (cfg, desc, sizeof (desc));
34
35   printf ("{\"title\":\"%s\",\"instances\":[", desc);
36
37   return (0);
38 } /* }}} int json_begin_graph */
39
40 static int json_end_graph (void) /* {{{ */
41 {
42   printf ("]}");
43
44   return (0);
45 } /* }}} int json_end_graph */
46
47 static int json_print_instance (graph_config_t *cfg, /* {{{ */
48     graph_instance_t *inst)
49 {
50   char params[1024];
51   char desc[1024];
52
53   if ((cfg == NULL) || (inst == NULL))
54     return (EINVAL);
55
56   memset (desc, 0, sizeof (desc));
57   inst_describe (cfg, inst, desc, sizeof (desc));
58
59   memset (params, 0, sizeof (params));
60   inst_get_params (cfg, inst, params, sizeof (params));
61
62   printf ("{\"description\":\"%s\",\"params\":\"%s\"}",
63       desc, params);
64
65   return (0);
66 } /* }}} int json_print_instance */
67
68 static int print_graph_inst_json (graph_config_t *cfg, /* {{{ */
69     graph_instance_t *inst,
70     void *user_data)
71 {
72   callback_data_t *data = user_data;
73
74   if (data->cfg != cfg)
75   {
76     if (!data->first)
77     {
78       json_end_graph ();
79       printf (",\n");
80     }
81     json_begin_graph (cfg);
82
83     data->cfg = cfg;
84     data->first = 0;
85   }
86   else /* if (not first instance) */
87   {
88     printf (",\n");
89   }
90
91   json_print_instance (cfg, inst);
92
93   if (data->limit > 0)
94     data->limit--;
95
96   if (data->limit == 0)
97     return (1);
98
99   return (0);
100 } /* }}} int print_graph_inst_json */
101
102 static int list_graphs_json (const char *term) /* {{{ */
103 {
104   callback_data_t data;
105
106   time_t now;
107   char time_buffer[128];
108   int status;
109
110   printf ("Content-Type: application/json\n");
111
112   now = time (NULL);
113   status = time_to_rfc1123 (now + 300, time_buffer, sizeof (time_buffer));
114   if (status == 0)
115     printf ("Expires: %s\n"
116         "Cache-Control: public\n",
117         time_buffer);
118   printf ("\n");
119
120   data.cfg = NULL;
121   data.limit = RESULT_LIMIT;
122   data.first = 1;
123
124   printf ("[\n");
125   if (term == NULL)
126     gl_instance_get_all (print_graph_inst_json, /* user_data = */ &data);
127   else
128     gl_search (term, print_graph_inst_json, /* user_data = */ &data);
129
130   if (!data.first)
131     json_end_graph ();
132
133   printf ("\n]");
134
135   return (0);
136 } /* }}} int list_graphs_json */
137
138 static int print_graph_inst_html (graph_config_t *cfg, /* {{{ */
139     graph_instance_t *inst,
140     void *user_data)
141 {
142   callback_data_t *data = user_data;
143   char params[1024];
144   char desc[1024];
145
146   if (data->cfg != cfg)
147   {
148     if (data->cfg != NULL)
149       printf ("  </ul></li>\n");
150
151     memset (desc, 0, sizeof (desc));
152     graph_get_title (cfg, desc, sizeof (desc));
153     html_escape_buffer (desc, sizeof (desc));
154
155     printf ("  <li class=\"graph\">%s\n"
156         "  <ul class=\"instance_list\">\n", desc);
157
158     data->cfg = cfg;
159   }
160
161   memset (params, 0, sizeof (params));
162   inst_get_params (cfg, inst, params, sizeof (params));
163   html_escape_buffer (params, sizeof (params));
164
165   memset (desc, 0, sizeof (desc));
166   inst_describe (cfg, inst, desc, sizeof (desc));
167   html_escape_buffer (desc, sizeof (desc));
168
169   printf ("    <li class=\"instance\"><a href=\"%s?action=graph;%s\">%s</a></li>\n",
170       script_name (), params, desc);
171
172   if (data->limit > 0)
173     data->limit--;
174
175   /* Abort scan if limit is reached. */
176   if (data->limit == 0)
177     return (1);
178
179   return (0);
180 } /* }}} int print_graph_inst_html */
181
182 struct page_data_s
183 {
184   const char *search_term;
185 };
186 typedef struct page_data_s page_data_t;
187
188 static int print_search_box (void *user_data) /* {{{ */
189 {
190   page_data_t *data = user_data;
191   char *term_html;
192
193   if (data == NULL)
194   {
195     fprintf (stderr, "print_search_box: data == NULL\n");
196     return (EINVAL);
197   }
198
199   term_html = html_escape (data->search_term);
200
201   printf ("<form action=\"%s\" method=\"get\">\n"
202       "  <input type=\"hidden\" name=\"action\" value=\"list_graphs\" />\n"
203       "  <input type=\"text\" name=\"search\" value=\"%s\" id=\"search-input\" />\n"
204       "  <input type=\"submit\" name=\"button\" value=\"Search\" />\n"
205       "</form>\n",
206       script_name (),
207       (term_html != NULL) ? term_html : "");
208
209   free (term_html);
210
211   return (0);
212 } /* }}} int print_search_box */
213
214 static int print_search_result (void *user_data) /* {{{ */
215 {
216   page_data_t *pg_data = user_data;
217   callback_data_t cb_data = { NULL, /* limit = */ RESULT_LIMIT, /* first = */ 1 };
218
219   printf ("    <ul id=\"search-output\" class=\"graph_list\">\n");
220   if (pg_data->search_term == NULL)
221     gl_instance_get_all (print_graph_inst_html, /* user_data = */ &cb_data);
222   else
223   {
224     char *term_lc = strtolower_copy (pg_data->search_term);
225     gl_search (term_lc, print_graph_inst_html, /* user_data = */ &cb_data);
226     free (term_lc);
227   }
228
229   if (cb_data.cfg != NULL)
230     printf ("      </ul></li>\n");
231
232   printf ("    </ul>\n");
233
234   return (0);
235 } /* }}} int print_search_result */
236
237 struct print_host_list_data_s
238 {
239   str_array_t *array;
240   char *last_host;
241 };
242 typedef struct print_host_list_data_s print_host_list_data_t;
243
244 static int print_host_list_callback (graph_config_t *cfg, /* {{{ */
245     graph_instance_t *inst, void *user_data)
246 {
247   print_host_list_data_t *data = user_data;
248   graph_ident_t *ident;
249   const char *host;
250
251   /* make compiler happy */
252   cfg = NULL;
253
254   ident = inst_get_selector (inst);
255   if (ident == NULL)
256     return (-1);
257
258   host = ident_get_host (ident);
259   if (host == NULL)
260   {
261     ident_destroy (ident);
262     return (-1);
263   }
264
265   if (IS_ALL (host))
266     return (0);
267
268   if ((data->last_host != NULL)
269       && (strcmp (data->last_host, host) == 0))
270   {
271     ident_destroy (ident);
272     return (0);
273   }
274
275   free (data->last_host);
276   data->last_host = strdup (host);
277
278   array_append (data->array, host);
279
280   ident_destroy (ident);
281   return (0);
282 } /* }}} int print_host_list_callback */
283
284 static int print_host_list (__attribute__((unused)) void *user_data) /* {{{ */
285 {
286   print_host_list_data_t data;
287   int hosts_argc;
288   char **hosts_argv;
289   int i;
290
291   data.array = array_create ();
292   data.last_host = NULL;
293
294   gl_instance_get_all (print_host_list_callback, &data);
295
296   free (data.last_host);
297   data.last_host = NULL;
298
299   array_sort (data.array);
300
301   hosts_argc = array_argc (data.array);
302   hosts_argv = array_argv (data.array);
303
304   if (hosts_argc < 1)
305   {
306     array_destroy (data.array);
307     return (0);
308   }
309
310   printf ("<ul id=\"host-list\">\n");
311   for (i = 0; i < hosts_argc; i++)
312   {
313     char *host = hosts_argv[i];
314     char *host_html;
315
316     if ((data.last_host != NULL) && (strcmp (data.last_host, host) == 0))
317       continue;
318     data.last_host = host;
319
320     host_html = html_escape (host);
321
322     printf ("  <li><a href=\"%s?action=list_graphs&search=%s\">%s</a></li>\n",
323         script_name (), host_html, host_html);
324
325     free (host_html);
326   }
327   printf ("</ul>\n");
328
329   array_destroy (data.array);
330
331   return (0);
332 } /* }}} int print_host_list */
333
334 static int list_graphs_html (const char *term) /* {{{ */
335 {
336   page_data_t pg_data;
337   page_callbacks_t pg_callbacks = PAGE_CALLBACKS_INIT;
338   char title[512];
339
340   if (term != NULL)
341     snprintf (title, sizeof (title), "c4: Graphs matching \"%s\"", term);
342   else
343     strncpy (title, "c4: List of all graphs", sizeof (title));
344   title[sizeof (title) - 1] = 0;
345
346   memset (&pg_data, 0, sizeof (pg_data));
347   pg_data.search_term = term;
348
349   pg_callbacks.top_right = print_search_box;
350   pg_callbacks.middle_left = print_host_list;
351   pg_callbacks.middle_center = print_search_result;
352
353   html_print_page (title, &pg_callbacks, &pg_data);
354
355   return (0);
356 } /* }}} int list_graphs_html */
357
358 int action_list_graphs (void) /* {{{ */
359 {
360   const char *format;
361   char *search;
362   int status;
363
364   gl_update ();
365
366   search = strtolower_copy (param ("search"));
367
368   format = param ("format");
369   if (format == NULL)
370     format = "html";
371
372   if (strcmp ("json", format) == 0)
373     status = list_graphs_json (search);
374   else
375     status = list_graphs_html (search);
376
377   free (search);
378
379   return (status);
380 } /* }}} int action_list_graphs */
381
382 /* vim: set sw=2 sts=2 et fdm=marker : */