1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
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"
13 #include <fcgiapp.h>
14 #include <fcgi_stdio.h>
16 #define RESULT_LIMIT 50
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;
26 static int json_begin_graph (graph_config_t *cfg) /* {{{ */
27 {
28 char desc[1024];
30 if (cfg == NULL)
31 return (EINVAL);
33 graph_get_title (cfg, desc, sizeof (desc));
35 printf ("{\"title\":\"%s\",\"instances\":[", desc);
37 return (0);
38 } /* }}} int json_begin_graph */
40 static int json_end_graph (void) /* {{{ */
41 {
42 printf ("]}");
44 return (0);
45 } /* }}} int json_end_graph */
47 static int json_print_instance (graph_config_t *cfg, /* {{{ */
48 graph_instance_t *inst)
49 {
50 char params[1024];
51 char desc[1024];
53 if ((cfg == NULL) || (inst == NULL))
54 return (EINVAL);
56 memset (desc, 0, sizeof (desc));
57 inst_describe (cfg, inst, desc, sizeof (desc));
59 memset (params, 0, sizeof (params));
60 inst_get_params (cfg, inst, params, sizeof (params));
62 printf ("{\"description\":\"%s\",\"params\":\"%s\"}",
63 desc, params);
65 return (0);
66 } /* }}} int json_print_instance */
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;
74 if (data->cfg != cfg)
75 {
76 if (!data->first)
77 {
78 json_end_graph ();
79 printf (",\n");
80 }
81 json_begin_graph (cfg);
83 data->cfg = cfg;
84 data->first = 0;
85 }
86 else /* if (not first instance) */
87 {
88 printf (",\n");
89 }
91 json_print_instance (cfg, inst);
93 if (data->limit > 0)
94 data->limit--;
96 if (data->limit == 0)
97 return (1);
99 return (0);
100 } /* }}} int print_graph_inst_json */
102 static int list_graphs_json (const char *term) /* {{{ */
103 {
104 callback_data_t data;
106 time_t now;
107 char time_buffer[128];
108 int status;
110 printf ("Content-Type: application/json\n");
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");
120 data.cfg = NULL;
121 data.limit = RESULT_LIMIT;
122 data.first = 1;
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);
130 if (!data.first)
131 json_end_graph ();
133 printf ("\n]");
135 return (0);
136 } /* }}} int list_graphs_json */
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];
146 if (data->cfg != cfg)
147 {
148 if (data->cfg != NULL)
149 printf (" </ul></li>\n");
151 memset (desc, 0, sizeof (desc));
152 graph_get_title (cfg, desc, sizeof (desc));
153 html_escape_buffer (desc, sizeof (desc));
155 printf (" <li class=\"graph\">%s\n"
156 " <ul class=\"instance_list\">\n", desc);
158 data->cfg = cfg;
159 }
161 memset (params, 0, sizeof (params));
162 inst_get_params (cfg, inst, params, sizeof (params));
163 html_escape_buffer (params, sizeof (params));
165 memset (desc, 0, sizeof (desc));
166 inst_describe (cfg, inst, desc, sizeof (desc));
167 html_escape_buffer (desc, sizeof (desc));
169 printf (" <li class=\"instance\"><a href=\"%s?action=graph;%s\">%s</a></li>\n",
170 script_name (), params, desc);
172 if (data->limit > 0)
173 data->limit--;
175 /* Abort scan if limit is reached. */
176 if (data->limit == 0)
177 return (1);
179 return (0);
180 } /* }}} int print_graph_inst_html */
182 struct page_data_s
183 {
184 const char *search_term;
185 };
186 typedef struct page_data_s page_data_t;
188 static int print_search_box (void *user_data) /* {{{ */
189 {
190 page_data_t *data = user_data;
191 char *term_html;
193 if (data == NULL)
194 {
195 fprintf (stderr, "print_search_box: data == NULL\n");
196 return (EINVAL);
197 }
199 term_html = html_escape (data->search_term);
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 : "");
209 free (term_html);
211 return (0);
212 } /* }}} int print_search_box */
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 };
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 }
229 if (cb_data.cfg != NULL)
230 printf (" </ul></li>\n");
232 printf (" </ul>\n");
234 return (0);
235 } /* }}} int print_search_result */
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;
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;
251 /* make compiler happy */
252 cfg = NULL;
254 ident = inst_get_selector (inst);
255 if (ident == NULL)
256 return (-1);
258 host = ident_get_host (ident);
259 if (host == NULL)
260 {
261 ident_destroy (ident);
262 return (-1);
263 }
265 if (IS_ALL (host))
266 return (0);
268 if ((data->last_host != NULL)
269 && (strcmp (data->last_host, host) == 0))
270 {
271 ident_destroy (ident);
272 return (0);
273 }
275 free (data->last_host);
276 data->last_host = strdup (host);
278 array_append (data->array, host);
280 ident_destroy (ident);
281 return (0);
282 } /* }}} int print_host_list_callback */
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;
291 data.array = array_create ();
292 data.last_host = NULL;
294 gl_instance_get_all (print_host_list_callback, &data);
296 free (data.last_host);
297 data.last_host = NULL;
299 array_sort (data.array);
301 hosts_argc = array_argc (data.array);
302 hosts_argv = array_argv (data.array);
304 if (hosts_argc < 1)
305 {
306 array_destroy (data.array);
307 return (0);
308 }
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;
316 if ((data.last_host != NULL) && (strcmp (data.last_host, host) == 0))
317 continue;
318 data.last_host = host;
320 host_html = html_escape (host);
322 printf (" <li><a href=\"%s?action=list_graphs&search=%s\">%s</a></li>\n",
323 script_name (), host_html, host_html);
325 free (host_html);
326 }
327 printf ("</ul>\n");
329 array_destroy (data.array);
331 return (0);
332 } /* }}} int print_host_list */
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];
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;
346 memset (&pg_data, 0, sizeof (pg_data));
347 pg_data.search_term = term;
349 pg_callbacks.top_right = print_search_box;
350 pg_callbacks.middle_left = print_host_list;
351 pg_callbacks.middle_center = print_search_result;
353 html_print_page (title, &pg_callbacks, &pg_data);
355 return (0);
356 } /* }}} int list_graphs_html */
358 int action_list_graphs (void) /* {{{ */
359 {
360 const char *format;
361 char *search;
362 int status;
364 gl_update ();
366 search = strtolower_copy (param ("search"));
368 format = param ("format");
369 if (format == NULL)
370 format = "html";
372 if (strcmp ("json", format) == 0)
373 status = list_graphs_json (search);
374 else
375 status = list_graphs_html (search);
377 free (search);
379 return (status);
380 } /* }}} int action_list_graphs */
382 /* vim: set sw=2 sts=2 et fdm=marker : */