+/*********************************************************************
+ *
+ * Function : cgi_show_file
+ *
+ * Description : CGI function that shows the content of a
+ * configuration file.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : rsp = http_response data structure for output
+ * 3 : parameters = map of cgi parameters
+ *
+ * CGI Parameters :
+ * file : Which file to show. Only first letter is checked,
+ * valid values are:
+ * - "a"ction file
+ * - "r"egex
+ * - "t"rust
+ * Default is to show menu and other information.
+ *
+ * Returns : JB_ERR_OK on success
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+static jb_err cgi_show_file(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ unsigned i;
+ const char * filename = NULL;
+ char * file_description = NULL;
+
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ switch (*(lookup(parameters, "file")))
+ {
+ case 'a':
+ if (!get_number_param(csp, parameters, "index", &i) && i < MAX_AF_FILES && csp->actions_list[i])
+ {
+ filename = csp->actions_list[i]->filename;
+ file_description = "Actions File";
+ }
+ break;
+
+ case 'f':
+ if (!get_number_param(csp, parameters, "index", &i) && i < MAX_AF_FILES && csp->rlist[i])
+ {
+ filename = csp->rlist[i]->filename;
+ file_description = "Filter File";
+ }
+ break;
+
+#ifdef FEATURE_TRUST
+ case 't':
+ if (csp->tlist)
+ {
+ filename = csp->tlist->filename;
+ file_description = "Trust File";
+ }
+ break;
+#endif /* def FEATURE_TRUST */
+ }
+
+ if (NULL != filename)
+ {
+ struct map *exports;
+ char *s;
+ FILE * fp;
+
+ exports = default_exports(csp, "show-status");
+ if (NULL == exports)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ if ( map(exports, "file-description", 1, file_description, 1)
+ || map(exports, "filepath", 1, html_encode(filename), 0) )
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+
+ if ((fp = fopen(filename, "rb")) == NULL)
+ {
+ if (map(exports, "content", 1, "<h1>ERROR OPENING FILE!</h1>", 1))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+ }
+ else
+ {
+ /*
+ * XXX: this code is "quite similar" to the one
+ * in cgi_send_user_manual() and should be refactored.
+ * While at it, the return codes for ftell() and fseek
+ * should be verified.
+ */
+ size_t length;
+ /* Get file length */
+ fseek(fp, 0, SEEK_END);
+ length = (size_t)ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ s = (char *)zalloc(length+1);
+ if (NULL == s)
+ {
+ fclose(fp);
+ return JB_ERR_MEMORY;
+ }
+ if (!fread(s, length, 1, fp))
+ {
+ /*
+ * May happen if the file size changes between fseek() and fread().
+ * If it does, we just log it and serve what we got.
+ */
+ log_error(LOG_LEVEL_ERROR, "Couldn't completely read file %s.", filename);
+ }
+ fclose(fp);
+
+ s = html_encode_and_free_original(s);
+ if (NULL == s)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ if (map(exports, "contents", 1, s, 0))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+ }
+
+ return template_fill_for_cgi(csp, "show-status-file", exports, rsp);
+ }
+
+ /*
+ * XXX: should return JB_ERR_PARSE but CGI handlers
+ * currently aren't expected to do that.
+ */
+ return JB_ERR_OK;
+}
+
+