13 #include <fcgi_stdio.h>
20 typedef struct parameter_s parameter_t;
24 parameter_t *parameters;
25 size_t parameters_num;
28 static param_list_t *pl_global = NULL;
30 static char *uri_unescape_copy (char *dest, const char *src, size_t n) /* {{{ */
35 if ((dest == NULL) || (src == NULL) || (n < 1))
52 else if ((src_ptr[0] == '%')
53 && isxdigit ((int) src_ptr[1]) && isxdigit ((int) src_ptr[2]))
59 tmpstr[0] = src_ptr[1];
60 tmpstr[1] = src_ptr[2];
65 value = strtol (tmpstr, &endptr, /* base = */ 16);
66 if ((endptr == tmpstr) || (errno != 0))
72 *dest_ptr = (char) value;
85 } /* while (*src_ptr != 0) */
87 assert (*dest_ptr == 0);
89 } /* }}} char *uri_unescape */
91 static char *uri_unescape (const char *string) /* {{{ */
98 uri_unescape_copy (buffer, string, sizeof (buffer));
100 return (strdup (buffer));
101 } /* }}} char *uri_unescape */
103 static int param_parse_keyval (param_list_t *pl, char *keyval) /* {{{ */
111 value_raw = strchr (key_raw, '=');
112 if (value_raw == NULL)
117 key = uri_unescape (key_raw);
121 value = uri_unescape (value_raw);
128 param_set (pl, key, value);
134 } /* }}} int param_parse_keyval */
136 static int parse_query_string (param_list_t *pl, /* {{{ */
142 if ((pl == NULL) || (query_string == NULL))
145 dummy = query_string;
146 while ((keyval = strtok (dummy, ";&")) != NULL)
149 param_parse_keyval (pl, keyval);
153 } /* }}} int parse_query_string */
155 int param_init (void) /* {{{ */
157 if (pl_global != NULL)
160 pl_global = param_create (/* query string = */ NULL);
161 if (pl_global == NULL)
165 } /* }}} int param_init */
167 void param_finish (void) /* {{{ */
169 param_destroy (pl_global);
171 } /* }}} void param_finish */
173 const char *param (const char *key) /* {{{ */
177 return (param_get (pl_global, key));
178 } /* }}} const char *param */
180 param_list_t *param_create (const char *query_string) /* {{{ */
185 if (query_string == NULL)
186 query_string = getenv ("QUERY_STRING");
188 if (query_string == NULL)
191 tmp = strdup (query_string);
195 pl = malloc (sizeof (*pl));
201 memset (pl, 0, sizeof (*pl));
203 parse_query_string (pl, tmp);
207 } /* }}} param_list_t *param_create */
209 param_list_t *param_clone (__attribute__((unused)) param_list_t *pl) /* {{{ */
211 /* FIXME: To be implemented. */
214 } /* }}} param_list_t *param_clone */
216 void param_destroy (param_list_t *pl) /* {{{ */
223 for (i = 0; i < pl->parameters_num; i++)
225 free (pl->parameters[i].key);
226 free (pl->parameters[i].value);
228 free (pl->parameters);
230 } /* }}} void param_destroy */
232 const char *param_get (param_list_t *pl, const char *name) /* {{{ */
236 if ((pl == NULL) || (name == NULL))
239 for (i = 0; i < pl->parameters_num; i++)
241 if ((name == NULL) && (pl->parameters[i].key == NULL))
242 return (pl->parameters[i].value);
243 else if ((name != NULL) && (pl->parameters[i].key != NULL)
244 && (strcmp (name, pl->parameters[i].key) == 0))
245 return (pl->parameters[i].value);
249 } /* }}} char *param_get */
251 static int param_add (param_list_t *pl, /* {{{ */
252 const char *key, const char *value)
256 tmp = realloc (pl->parameters,
257 sizeof (*pl->parameters) * (pl->parameters_num + 1));
260 pl->parameters = tmp;
261 tmp = pl->parameters + pl->parameters_num;
263 memset (tmp, 0, sizeof (*tmp));
264 tmp->key = strdup (key);
265 if (tmp->key == NULL)
268 tmp->value = strdup (value);
269 if (tmp->value == NULL)
275 pl->parameters_num++;
278 } /* }}} int param_add */
280 static int param_delete (param_list_t *pl, /* {{{ */
285 if ((pl == NULL) || (name == NULL))
288 for (i = 0; i < pl->parameters_num; i++)
289 if (strcasecmp (pl->parameters[i].key, name) == 0)
292 if (i >= pl->parameters_num)
295 if (i < (pl->parameters_num - 1))
299 p = pl->parameters[i];
300 pl->parameters[i] = pl->parameters[pl->parameters_num - 1];
301 pl->parameters[pl->parameters_num - 1] = p;
304 pl->parameters_num--;
305 free (pl->parameters[pl->parameters_num].key);
306 free (pl->parameters[pl->parameters_num].value);
309 } /* }}} int param_delete */
311 int param_set (param_list_t *pl, const char *name, /* {{{ */
318 if ((pl == NULL) || (name == NULL))
322 return (param_delete (pl, name));
325 for (i = 0; i < pl->parameters_num; i++)
327 if (strcasecmp (pl->parameters[i].key, name) == 0)
329 p = pl->parameters + i;
335 return (param_add (pl, name, value));
337 value_copy = strdup (value);
338 if (value_copy == NULL)
342 p->value = value_copy;
345 } /* }}} int param_set */
347 char *param_as_string (param_list_t *pl) /* {{{ */
358 for (i = 0; i < pl->parameters_num; i++)
360 uri_escape_copy (key, pl->parameters[i].key, sizeof (key));
361 uri_escape_copy (value, pl->parameters[i].value, sizeof (value));
364 strlcat (buffer, ";", sizeof (buffer));
365 strlcat (buffer, key, sizeof (buffer));
366 strlcat (buffer, "=", sizeof (buffer));
367 strlcat (buffer, value, sizeof (buffer));
370 return (strdup (buffer));
371 } /* }}} char *param_as_string */
373 int param_print_hidden (param_list_t *pl) /* {{{ */
382 for (i = 0; i < pl->parameters_num; i++)
384 html_escape_copy (key, pl->parameters[i].key, sizeof (key));
385 html_escape_copy (value, pl->parameters[i].value, sizeof (value));
387 printf (" <input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
392 } /* }}} int param_print_hidden */
394 char *uri_escape_copy (char *dest, const char *src, size_t n) /* {{{ */
408 else if ((((unsigned char) src[in]) < 32)
413 || (((unsigned char) src[in]) >= 128))
420 snprintf (esc, sizeof (esc), "%%%02x", (unsigned int) src[in]);
422 dest[out+1] = esc[1];
423 dest[out+2] = esc[2];
437 } /* }}} char *uri_escape_copy */
439 char *uri_escape (const char *string) /* {{{ */
446 uri_escape_copy (buffer, string, sizeof (buffer));
448 return (strdup (buffer));
449 } /* }}} char *uri_escape */
451 const char *script_name (void) /* {{{ */
455 ret = getenv ("SCRIPT_NAME");
457 ret = "collection4.fcgi";
460 } /* }}} char *script_name */
462 int time_to_rfc1123 (time_t t, char *buffer, size_t buffer_size) /* {{{ */
467 /* RFC 1123 *requires* the time to be GMT and the "GMT" timezone string.
468 * Apache will ignore the timezone if "localtime_r" and "%z" is used,
469 * resulting in weird behavior. */
470 if (gmtime_r (&t, &tm_tmp) == NULL)
473 status = strftime (buffer, buffer_size, "%a, %d %b %Y %T GMT", &tm_tmp);
478 } /* }}} int time_to_rfc1123 */
480 #define COPY_ENTITY(e) do { \
481 size_t len = strlen (e); \
482 if (dest_size < (len + 1)) \
484 strcpy (dest_ptr, (e)); \
489 char *html_escape_copy (char *dest, const char *src, size_t n) /* {{{ */
498 for (pos = 0; src[pos] != 0; pos++)
501 COPY_ENTITY (""");
502 else if (src[pos] == '<')
503 COPY_ENTITY ("<");
504 else if (src[pos] == '>')
505 COPY_ENTITY (">");
506 else if (src[pos] == '&')
507 COPY_ENTITY ("&");
510 *dest_ptr = src[pos];
521 } /* }}} char *html_escape_copy */
525 char *html_escape_buffer (char *buffer, size_t buffer_size) /* {{{ */
527 char tmp[buffer_size];
529 html_escape_copy (tmp, buffer, sizeof (tmp));
530 memcpy (buffer, tmp, buffer_size);
533 } /* }}} char *html_escape_buffer */
535 char *html_escape (const char *string) /* {{{ */
542 html_escape_copy (buffer, string, sizeof (buffer));
544 return (strdup (buffer));
545 } /* }}} char *html_escape */
547 int html_print_page (const char *title, /* {{{ */
548 const page_callbacks_t *cb, void *user_data)
552 printf ("Content-Type: text/html\n\n");
555 title = "c4: collection4 graph interface";
557 title_html = html_escape (title);
561 " <title>%s</title>\n"
562 " <link rel=\"stylesheet\" type=\"text/css\" href=\"../share/style.css\" />\n"
563 " <script type=\"text/javascript\" src=\"../share/jquery-1.4.2.min.js\">\n"
565 " <script type=\"text/javascript\" src=\"../share/collection.js\">\n"
571 " <table id=\"layout-table\">\n"
572 " <tr id=\"layout-top\">\n"
573 " <td id=\"layout-top-left\">");
574 if (cb->top_left != NULL)
575 (*cb->top_left) (user_data);
577 html_print_logo (NULL);
579 " <td id=\"layout-top-center\">");
580 if (cb->top_center != NULL)
581 (*cb->top_center) (user_data);
583 printf ("<h1>%s</h1>", title_html);
585 " <td id=\"layout-top-right\">");
586 if (cb->top_right != NULL)
587 (*cb->top_right) (user_data);
590 " <tr id=\"layout-middle\">\n"
591 " <td id=\"layout-middle-left\">");
592 if (cb->middle_left != NULL)
593 (*cb->middle_left) (user_data);
595 " <td id=\"layout-middle-center\">");
596 if (cb->middle_center != NULL)
597 (*cb->middle_center) (user_data);
599 " <td id=\"layout-middle-right\">");
600 if (cb->middle_right != NULL)
601 (*cb->middle_right) (user_data);
604 " <tr id=\"layout-bottom\">\n"
605 " <td id=\"layout-bottom-left\">");
606 if (cb->bottom_left != NULL)
607 (*cb->bottom_left) (user_data);
609 " <td id=\"layout-bottom-center\">");
610 if (cb->bottom_center != NULL)
611 (*cb->bottom_center) (user_data);
613 " <td id=\"layout-bottom-right\">");
614 if (cb->bottom_right != NULL)
615 (*cb->bottom_right) (user_data);
624 } /* }}} int html_print_page */
626 int html_print_logo (__attribute__((unused)) void *user_data) /* {{{ */
628 printf ("<a href=\"%s?action=list_graphs\" id=\"logo-canvas\">\n"
629 " <h1>c<sup>4</sup></h1>\n"
630 " <div id=\"logo-subscript\">collection 4</div>\n"
634 } /* }}} int html_print_search_box */
636 int html_print_search_box (__attribute__((unused)) void *user_data) /* {{{ */
640 term_html = html_escape (param ("q"));
642 printf ("<form action=\"%s\" method=\"get\" id=\"search-form\">\n"
643 " <input type=\"hidden\" name=\"action\" value=\"list_graphs\" />\n"
644 " <input type=\"text\" name=\"q\" value=\"%s\" id=\"search-input\" />\n"
645 " <input type=\"submit\" name=\"button\" value=\"Search\" />\n"
648 (term_html != NULL) ? term_html : "");
653 } /* }}} int html_print_search_box */
655 /* vim: set sw=2 sts=2 et fdm=marker : */