diff --git a/include/lighttpd/encoding.h b/include/lighttpd/encoding.h index 48705f3..3ab8864 100644 --- a/include/lighttpd/encoding.h +++ b/include/lighttpd/encoding.h @@ -13,6 +13,7 @@ typedef enum { /* encodes special characters in a string and returns the new string */ +GString *string_encode_append(const gchar *str, GString *dest, encoding_t encoding); GString *string_encode(const gchar *str, GString *dest, encoding_t encoding); #endif \ No newline at end of file diff --git a/src/encoding.c b/src/encoding.c index beeafe1..de7e01d 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -38,14 +38,14 @@ static const gchar encode_map_html[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 70 - 70 DEL */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ }; /* relative URI, everything except: ! ( ) * - . / 0-9 A-Z _ a-z */ @@ -71,7 +71,7 @@ static const gchar encode_map_uri[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ }; -GString *string_encode(const gchar *str, GString *dest, encoding_t encoding) { +GString *string_encode_append(const gchar *str, GString *dest, encoding_t encoding) { GString *result; guchar *c; guchar *pos = NULL; @@ -105,15 +105,18 @@ GString *string_encode(const gchar *str, GString *dest, encoding_t encoding) { } if (dest) { + gsize oldlen = dest->len; result = dest; g_string_set_size(result, dest->len + new_len); + pos = (guchar*) result->str + oldlen; } else { result = g_string_sized_new(new_len); + pos = (guchar*) result->str; } switch (encoding) { case ENCODING_HTML: - for (c = (guchar*)str, pos = (guchar*)(result->str+dest->len); *c != '\0'; c++) { + for (c = (guchar*)str; *c != '\0'; c++) { if (map[*c]) { /* char needs to be encoded */ /* &#xHH */ @@ -130,7 +133,7 @@ GString *string_encode(const gchar *str, GString *dest, encoding_t encoding) { } break; case ENCODING_HEX: - for (c = (guchar*)str, pos = (guchar*)(result->str+dest->len); *c != '\0'; c++) { + for (c = (guchar*)str; *c != '\0'; c++) { if (map[*c]) { /* char needs to be encoded */ *pos++ = hex_chars[((*c) >> 4) & 0x0F]; @@ -142,7 +145,7 @@ GString *string_encode(const gchar *str, GString *dest, encoding_t encoding) { } break; case ENCODING_URI: - for (c = (guchar*)str, pos = (guchar*)(result->str+dest->len); *c != '\0'; c++) { + for (c = (guchar*)str; *c != '\0'; c++) { if (map[*c]) { /* char needs to be encoded */ *pos++ = '%'; @@ -159,4 +162,9 @@ GString *string_encode(const gchar *str, GString *dest, encoding_t encoding) { *pos = '\0'; return result; -} \ No newline at end of file +} + +GString *string_encode(const gchar *str, GString *dest, encoding_t encoding) { + if (dest) g_string_truncate(dest, 0); + return string_encode_append(str, dest, encoding); +} diff --git a/src/modules/mod_dirlist.c b/src/modules/mod_dirlist.c index ff39324..eb50d0f 100644 --- a/src/modules/mod_dirlist.c +++ b/src/modules/mod_dirlist.c @@ -114,6 +114,7 @@ struct dirlist_data { gboolean debug; GPtrArray *exclude_suffix; GPtrArray *exclude_prefix; + GString *content_type; }; typedef struct dirlist_data dirlist_data; @@ -254,7 +255,7 @@ static handler_t dirlist(vrequest *vr, gpointer param, gpointer *context) { if (dd->debug) VR_DEBUG(vr, "dirlist for \"%s\", %u entries", sce->data.path->str, sce->dirlist->len); - http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); + http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), GSTR_LEN(dd->content_type)); etag_set_header(vr, &sce->data.st, &cachable); if (cachable) { vr->response.http_status = 304; @@ -430,6 +431,8 @@ static void dirlist_free(server *srv, gpointer param) { g_string_free(g_ptr_array_index(data->exclude_prefix, i), TRUE); g_ptr_array_free(data->exclude_prefix, TRUE); + g_string_free(data->content_type, TRUE); + g_slice_free(dirlist_data, data); } @@ -451,6 +454,7 @@ static action* dirlist_create(server *srv, plugin* p, value *val) { data->hide_tildefiles = TRUE; data->exclude_suffix = g_ptr_array_new(); data->exclude_prefix = g_ptr_array_new(); + data->content_type = g_string_new("text/html; charset=utf-8"); if (val) { for (i = 0; i < val->data.list->len; i++) { @@ -530,6 +534,13 @@ static action* dirlist_create(server *srv, plugin* p, value *val) { return NULL; } data->debug = v->data.boolean; + } else if (g_str_equal(k->str, "content-type")) { + if (v->type != VALUE_STRING) { + ERROR(srv, "%s", "dirlist: content-type parameter must be a string"); + dirlist_free(srv, data); + return NULL; + } + g_string_assign(data->content_type, v->data.string->str); } else { ERROR(srv, "dirlist: unknown parameter \"%s\"", k->str); dirlist_free(srv, data); diff --git a/src/modules/mod_rewrite.c b/src/modules/mod_rewrite.c index b599711..e9e55a6 100644 --- a/src/modules/mod_rewrite.c +++ b/src/modules/mod_rewrite.c @@ -294,7 +294,7 @@ static gboolean rewrite_internal(vrequest *vr, GString *dest_path, GString *dest g_string_append_len(dest, CONST_STR_LEN("http")); } else { if (encoded) - string_encode(str->str, dest, ENCODING_URI); + string_encode_append(str->str, dest, ENCODING_URI); else g_string_append_len(dest, GSTR_LEN(str)); }