-const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.73 2008/04/26 12:21:55 fabiankeil Exp $";
+const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.80 2008/05/04 16:18:32 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgisimple.c,v $
*
* Revisions :
* $Log: cgisimple.c,v $
+ * Revision 1.80 2008/05/04 16:18:32 fabiankeil
+ * Provide parse_http_url() with a third parameter to specify
+ * whether or not URLs without protocol are acceptable.
+ *
+ * Revision 1.79 2008/05/04 13:30:56 fabiankeil
+ * Streamline parse_http_url()'s prototype.
+ *
+ * Revision 1.78 2008/05/03 16:50:11 fabiankeil
+ * Leverage content_filters_enabled() in cgi_show_url_info().
+ *
+ * Revision 1.77 2008/05/02 09:47:48 fabiankeil
+ * In cgi_show_url_info, pass an initialized http structure
+ * to parse_http_url() as that will be required soonish and
+ * assert that https URLs are recognized correctly.
+ *
+ * Revision 1.76 2008/04/28 09:13:30 fabiankeil
+ * In load_file(), remember the error reason and fclose()
+ * and return later on instead of right away.
+ *
+ * Revision 1.75 2008/04/27 13:52:52 fabiankeil
+ * Move CGI file loading code into load_file() and
+ * add checks for unexpected errors.
+ *
+ * Revision 1.74 2008/04/26 15:50:56 fabiankeil
+ * Fix macro name in cgi_show_file() error path.
+ *
* Revision 1.73 2008/04/26 12:21:55 fabiankeil
* Forget about JB_ERR_PARSE. JB_ERR_CGI_PARAMS to the rescue.
*
static jb_err cgi_show_file(struct client_state *csp,
struct http_response *rsp,
const struct map *parameters);
+static jb_err load_file(const char *filename, char **buffer, size_t *length);
/*********************************************************************
*
{
const char * filename;
char *full_path;
- FILE *fp;
jb_err err = JB_ERR_OK;
size_t length;
return JB_ERR_MEMORY;
}
- /* Open user-manual file */
- if (NULL == (fp = fopen(full_path, "rb")))
+ err = load_file(full_path, &rsp->body, &rsp->content_length);
+ if (JB_ERR_OK != err)
{
- log_error(LOG_LEVEL_ERROR, "Cannot open user-manual file %s: %E", full_path);
- err = cgi_error_no_template(csp, rsp, full_path);
- free(full_path);
+ assert((JB_ERR_FILE == err) || (JB_ERR_MEMORY == err));
+ if (JB_ERR_FILE == err)
+ {
+ err = cgi_error_no_template(csp, rsp, full_path);
+ }
+ freez(full_path);
return err;
}
-
- /* Get file length */
- fseek(fp, 0, SEEK_END);
- length = (size_t)ftell(fp);
- fseek(fp, 0, SEEK_SET);
-
- /* Allocate memory and load the file directly into the body */
- rsp->body = (char *)zalloc(length+1);
- if (!rsp->body)
- {
- fclose(fp);
- free(full_path);
- return JB_ERR_MEMORY;
- }
- if (!fread(rsp->body, 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 user-manual file %s.", full_path);
- }
- fclose(fp);
- free(full_path);
-
- rsp->content_length = length;
+ freez(full_path);
/* Guess correct Content-Type based on the filename's ending */
if (filename)
url_param[0] = '\0';
}
}
- else if (url_param[0] != '\0')
+ else if (NULL == strstr(url_param, "://"))
{
- /*
- * Unknown prefix - assume http://
- */
- const size_t url_param_prefixed_size = 7 + 1 + strlen(url_param);
- char * url_param_prefixed = malloc(url_param_prefixed_size);
- if (NULL == url_param_prefixed)
+ /* No prefix - assume http:// */
+ char *url_param_prefixed = strdup("http://");
+
+ if (JB_ERR_OK != string_join(&url_param_prefixed, url_param))
{
- free(url_param);
free_map(exports);
return JB_ERR_MEMORY;
}
- strlcpy(url_param_prefixed, "http://", url_param_prefixed_size);
- strlcat(url_param_prefixed, url_param, url_param_prefixed_size);
- free(url_param);
url_param = url_param_prefixed;
}
return JB_ERR_MEMORY;
}
- err = parse_http_url(url_param, url_to_query, csp);
+ memset(url_to_query, '\0', sizeof(url_to_query));
+ err = parse_http_url(url_param, url_to_query, REQUIRE_PROTOCOL);
+ assert(url_to_query->ssl == !strncmp(url_param, "https://", 8));
free(url_param);
* If zlib support is available, if no content filters
* are enabled or if the prevent-compression action is enabled,
* suppress the "compression could prevent filtering" warning.
- *
- * XXX: Change content_filters_enabled()'s prototype so we can
- * use it here.
*/
#ifndef FEATURE_ZLIB
- if ((list_is_empty(action->multi[ACTION_MULTI_FILTER])
- && !(action->flags & ACTION_DEANIMATE))
- || (action->flags & ACTION_NO_COMPRESSION))
+ if (!content_filters_enabled(action) ||
+ (action->flags & ACTION_NO_COMPRESSION))
#endif
{
if (!err) err = map_block_killer(exports, "filters-might-be-ineffective");
{
struct map *exports;
char *s;
- FILE * fp;
+ jb_err err;
+ size_t length;
exports = default_exports(csp, "show-status");
if (NULL == exports)
return JB_ERR_MEMORY;
}
- if ((fp = fopen(filename, "rb")) == NULL)
+ err = load_file(filename, &s, &length);
+ if (JB_ERR_OK != err)
{
if (map(exports, "contents", 1, "<h1>ERROR OPENING FILE!</h1>", 1))
{
}
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_CGI_PARAMS;
}
+
+/*********************************************************************
+ *
+ * Function : load_file
+ *
+ * Description : Loads a file into a buffer.
+ *
+ * Parameters :
+ * 1 : filename = Name of the file to be loaded.
+ * 2 : buffer = Used to return the file's content.
+ * 3 : length = Used to return the size of the file.
+ *
+ * Returns : JB_ERR_OK in case of success,
+ * JB_ERR_FILE in case of ordinary file loading errors
+ * (fseek() and ftell() errors are fatal)
+ * JB_ERR_MEMORY in case of out-of-memory.
+ *
+ *********************************************************************/
+static jb_err load_file(const char *filename, char **buffer, size_t *length)
+{
+ FILE *fp;
+ int ret;
+ jb_err err = JB_ERR_OK;
+
+ fp = fopen(filename, "rb");
+ if (NULL == fp)
+ {
+ return JB_ERR_FILE;
+ }
+
+ /* Get file length */
+ if (fseek(fp, 0, SEEK_END))
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Unexpected erro while fseek()ing to the end of %s: %E",
+ filename);
+ }
+ ret = ftell(fp);
+ if (-1 == ret)
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Unexpected ftell() error while loading %s: %E",
+ filename);
+ }
+ *length = (size_t)ret;
+
+ /* Go back to the beginning. */
+ if (fseek(fp, 0, SEEK_SET))
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Unexpected error while fseek()ing to the beginning of %s: %E",
+ filename);
+ }
+
+ *buffer = (char *)zalloc(*length + 1);
+ if (NULL == *buffer)
+ {
+ err = JB_ERR_MEMORY;
+ }
+ else if (!fread(*buffer, *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);
+ err = JB_ERR_FILE;
+ }
+
+ fclose(fp);
+
+ return err;
+
+}
+
/*
Local Variables: