src/utils_cgi.[ch]: Move "html_print_search_box" to here.
[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_result (void *user_data) /* {{{ */
189 {
190   page_data_t *pg_data = user_data;
191   callback_data_t cb_data = { NULL, /* limit = */ RESULT_LIMIT, /* first = */ 1 };
192
193   printf ("    <ul id=\"search-output\" class=\"graph_list\">\n");
194   if (pg_data->search_term == NULL)
195     gl_instance_get_all (print_graph_inst_html, /* user_data = */ &cb_data);
196   else
197   {
198     char *term_lc = strtolower_copy (pg_data->search_term);
199     gl_search (term_lc, print_graph_inst_html, /* user_data = */ &cb_data);
200     free (term_lc);
201   }
202
203   if (cb_data.cfg != NULL)
204     printf ("      </ul></li>\n");
205
206   printf ("    </ul>\n");
207
208   return (0);
209 } /* }}} int print_search_result */
210
211 struct print_host_list_data_s
212 {
213   str_array_t *array;
214   char *last_host;
215 };
216 typedef struct print_host_list_data_s print_host_list_data_t;
217
218 static int print_host_list_callback (graph_config_t *cfg, /* {{{ */
219     graph_instance_t *inst, void *user_data)
220 {
221   print_host_list_data_t *data = user_data;
222   graph_ident_t *ident;
223   const char *host;
224
225   /* make compiler happy */
226   cfg = NULL;
227
228   ident = inst_get_selector (inst);
229   if (ident == NULL)
230     return (-1);
231
232   host = ident_get_host (ident);
233   if (host == NULL)
234   {
235     ident_destroy (ident);
236     return (-1);
237   }
238
239   if (IS_ALL (host))
240     return (0);
241
242   if ((data->last_host != NULL)
243       && (strcmp (data->last_host, host) == 0))
244   {
245     ident_destroy (ident);
246     return (0);
247   }
248
249   free (data->last_host);
250   data->last_host = strdup (host);
251
252   array_append (data->array, host);
253
254   ident_destroy (ident);
255   return (0);
256 } /* }}} int print_host_list_callback */
257
258 static int print_host_list (__attribute__((unused)) void *user_data) /* {{{ */
259 {
260   print_host_list_data_t data;
261   int hosts_argc;
262   char **hosts_argv;
263   int i;
264
265   data.array = array_create ();
266   data.last_host = NULL;
267
268   gl_instance_get_all (print_host_list_callback, &data);
269
270   free (data.last_host);
271   data.last_host = NULL;
272
273   array_sort (data.array);
274
275   hosts_argc = array_argc (data.array);
276   hosts_argv = array_argv (data.array);
277
278   if (hosts_argc < 1)
279   {
280     array_destroy (data.array);
281     return (0);
282   }
283
284   printf ("<ul id=\"host-list\">\n");
285   for (i = 0; i < hosts_argc; i++)
286   {
287     char *host = hosts_argv[i];
288     char *host_html;
289
290     if ((data.last_host != NULL) && (strcmp (data.last_host, host) == 0))
291       continue;
292     data.last_host = host;
293
294     host_html = html_escape (host);
295
296     printf ("  <li><a href=\"%s?action=list_graphs&search=%s\">%s</a></li>\n",
297         script_name (), host_html, host_html);
298
299     free (host_html);
300   }
301   printf ("</ul>\n");
302
303   array_destroy (data.array);
304
305   return (0);
306 } /* }}} int print_host_list */
307
308 static int list_graphs_html (const char *term) /* {{{ */
309 {
310   page_data_t pg_data;
311   page_callbacks_t pg_callbacks = PAGE_CALLBACKS_INIT;
312   char title[512];
313
314   if (term != NULL)
315     snprintf (title, sizeof (title), "c4: Graphs matching \"%s\"", term);
316   else
317     strncpy (title, "c4: List of all graphs", sizeof (title));
318   title[sizeof (title) - 1] = 0;
319
320   memset (&pg_data, 0, sizeof (pg_data));
321   pg_data.search_term = term;
322
323   pg_callbacks.top_right = html_print_search_box;
324   pg_callbacks.middle_left = print_host_list;
325   pg_callbacks.middle_center = print_search_result;
326
327   html_print_page (title, &pg_callbacks, &pg_data);
328
329   return (0);
330 } /* }}} int list_graphs_html */
331
332 int action_list_graphs (void) /* {{{ */
333 {
334   const char *format;
335   char *search;
336   int status;
337
338   gl_update ();
339
340   search = strtolower_copy (param ("search"));
341
342   format = param ("format");
343   if (format == NULL)
344     format = "html";
345
346   if (strcmp ("json", format) == 0)
347     status = list_graphs_json (search);
348   else
349     status = list_graphs_html (search);
350
351   free (search);
352
353   return (status);
354 } /* }}} int action_list_graphs */
355
356 /* vim: set sw=2 sts=2 et fdm=marker : */