"list graphs" action: Support searching for exact host, plugin and type names.
[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 graph_index;
22   int graph_limit;
23   _Bool graph_more;
24   int inst_index;
25   int inst_limit;
26   _Bool inst_more;
27 };
28 typedef struct callback_data_s callback_data_t;
29
30 static int print_graph_inst_html (graph_config_t *cfg, /* {{{ */
31     graph_instance_t *inst,
32     void *user_data)
33 {
34   callback_data_t *data = user_data;
35   char params[1024];
36   char desc[1024];
37
38   if (data->cfg != cfg)
39   {
40     data->graph_index++;
41     if (data->graph_index >= data->graph_limit)
42     {
43       data->graph_more = 1;
44       return (1);
45     }
46
47     if (data->cfg != NULL)
48       printf ("  </ul></li>\n");
49
50     memset (desc, 0, sizeof (desc));
51     graph_get_title (cfg, desc, sizeof (desc));
52     html_escape_buffer (desc, sizeof (desc));
53
54     printf ("  <li class=\"graph\">%s\n"
55         "  <ul class=\"instance_list\">\n", desc);
56
57     data->cfg = cfg;
58     data->inst_index = -1;
59     data->inst_more = 0;
60   }
61
62   data->inst_index++;
63   if (data->inst_index >= data->inst_limit)
64   {
65     if (!data->inst_more)
66     {
67       printf ("    <li class=\"instance more\">More ...</li>\n");
68       data->inst_more = 1;
69     }
70     return (0);
71   }
72
73   memset (params, 0, sizeof (params));
74   inst_get_params (cfg, inst, params, sizeof (params));
75   html_escape_buffer (params, sizeof (params));
76
77   memset (desc, 0, sizeof (desc));
78   inst_describe (cfg, inst, desc, sizeof (desc));
79   html_escape_buffer (desc, sizeof (desc));
80
81   printf ("    <li class=\"instance\"><a href=\"%s?action=show_graph;%s\">%s</a></li>\n",
82       script_name (), params, desc);
83
84   return (0);
85 } /* }}} int print_graph_inst_html */
86
87 struct page_data_s
88 {
89   const char *search_term;
90 };
91 typedef struct page_data_s page_data_t;
92
93 static int print_search_result (void *user_data) /* {{{ */
94 {
95   page_data_t *pg_data = user_data;
96   callback_data_t cb_data = { /* cfg = */ NULL,
97     /* graph_index = */ -1, /* graph_limit = */ 20, /* graph_more = */ 0,
98     /* inst_index = */  -1, /* inst_limit = */   5, /* inst more = */  0 };
99
100   if (pg_data->search_term != NULL)
101   {
102     char *search_term_html = html_escape (pg_data->search_term);
103     printf ("    <h2>Search results for &quot;%s&quot;</h2>\n",
104         search_term_html);
105     free (search_term_html);
106   }
107
108   printf ("    <ul id=\"search-output\" class=\"graph_list\">\n");
109   if (pg_data->search_term == NULL)
110     gl_instance_get_all (print_graph_inst_html, /* user_data = */ &cb_data);
111   else
112   {
113     char *term_lc = strtolower_copy (pg_data->search_term);
114
115     if (strncmp ("host:", term_lc, strlen ("host:")) == 0)
116       gl_search_field (GIF_HOST, term_lc + strlen ("host:"),
117           print_graph_inst_html, /* user_data = */ &cb_data);
118     else if (strncmp ("plugin:", term_lc, strlen ("plugin:")) == 0)
119       gl_search_field (GIF_PLUGIN, term_lc + strlen ("plugin:"),
120           print_graph_inst_html, /* user_data = */ &cb_data);
121     else if (strncmp ("type:", term_lc, strlen ("type:")) == 0)
122       gl_search_field (GIF_TYPE, term_lc + strlen ("type:"),
123           print_graph_inst_html, /* user_data = */ &cb_data);
124     else
125       gl_search (term_lc,
126           print_graph_inst_html, /* user_data = */ &cb_data);
127
128     free (term_lc);
129   }
130
131   if (cb_data.cfg != NULL)
132     printf ("      </ul></li>\n");
133
134   if (cb_data.graph_more)
135   {
136     printf ("    <li class=\"graph more\">More ...</li>\n");
137   }
138
139   printf ("    </ul>\n");
140
141   return (0);
142 } /* }}} int print_search_result */
143
144 struct print_host_list_data_s
145 {
146   str_array_t *array;
147   char *last_host;
148 };
149 typedef struct print_host_list_data_s print_host_list_data_t;
150
151 static int print_host_list_callback (graph_config_t *cfg, /* {{{ */
152     graph_instance_t *inst, void *user_data)
153 {
154   print_host_list_data_t *data = user_data;
155   graph_ident_t *ident;
156   const char *host;
157
158   /* make compiler happy */
159   cfg = NULL;
160
161   ident = inst_get_selector (inst);
162   if (ident == NULL)
163     return (-1);
164
165   host = ident_get_host (ident);
166   if (host == NULL)
167   {
168     ident_destroy (ident);
169     return (-1);
170   }
171
172   if (IS_ALL (host))
173     return (0);
174
175   if ((data->last_host != NULL)
176       && (strcmp (data->last_host, host) == 0))
177   {
178     ident_destroy (ident);
179     return (0);
180   }
181
182   free (data->last_host);
183   data->last_host = strdup (host);
184
185   array_append (data->array, host);
186
187   ident_destroy (ident);
188   return (0);
189 } /* }}} int print_host_list_callback */
190
191 static int print_host_list (__attribute__((unused)) void *user_data) /* {{{ */
192 {
193   print_host_list_data_t data;
194   int hosts_argc;
195   char **hosts_argv;
196   int i;
197
198   data.array = array_create ();
199   data.last_host = NULL;
200
201   gl_instance_get_all (print_host_list_callback, &data);
202
203   free (data.last_host);
204   data.last_host = NULL;
205
206   array_sort (data.array);
207
208   hosts_argc = array_argc (data.array);
209   hosts_argv = array_argv (data.array);
210
211   if (hosts_argc < 1)
212   {
213     array_destroy (data.array);
214     return (0);
215   }
216
217   printf ("<div><h3>List of hosts</h3>\n"
218       "<ul id=\"host-list\">\n");
219   for (i = 0; i < hosts_argc; i++)
220   {
221     char *host = hosts_argv[i];
222     char *host_html;
223
224     if ((data.last_host != NULL) && (strcmp (data.last_host, host) == 0))
225       continue;
226     data.last_host = host;
227
228     host_html = html_escape (host);
229
230     printf ("  <li><a href=\"%s?action=list_graphs&q=%s\">%s</a></li>\n",
231         script_name (), host_html, host_html);
232
233     free (host_html);
234   }
235   printf ("</ul></div>\n");
236
237   array_destroy (data.array);
238
239   return (0);
240 } /* }}} int print_host_list */
241
242 static int list_graphs_html (const char *term) /* {{{ */
243 {
244   page_data_t pg_data;
245   page_callbacks_t pg_callbacks = PAGE_CALLBACKS_INIT;
246   char title[512];
247
248   if (term != NULL)
249     snprintf (title, sizeof (title), "c4: Graphs matching \"%s\"", term);
250   else
251     strncpy (title, "c4: List of all graphs", sizeof (title));
252   title[sizeof (title) - 1] = 0;
253
254   memset (&pg_data, 0, sizeof (pg_data));
255   pg_data.search_term = term;
256
257   pg_callbacks.top_right = html_print_search_box;
258   pg_callbacks.middle_left = print_host_list;
259   pg_callbacks.middle_center = print_search_result;
260
261   html_print_page (title, &pg_callbacks, &pg_data);
262
263   return (0);
264 } /* }}} int list_graphs_html */
265
266 int action_list_graphs (void) /* {{{ */
267 {
268   char *search;
269   int status;
270
271   gl_update ();
272
273   search = strtolower_copy (param ("q"));
274   status = list_graphs_html (search);
275   free (search);
276
277   return (status);
278 } /* }}} int action_list_graphs */
279
280 /* vim: set sw=2 sts=2 et fdm=marker : */