diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2018-11-28 02:12:41 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2018-11-28 02:12:41 -0500 |
commit | 77c01f981725512653c01cde5ca74c11633dfec4 (patch) | |
tree | ba511202897b50f59e4ad81fd1df2cee73d35210 | |
parent | 608026e5aaed1b1c510814d3020aa8241d78f905 (diff) | |
download | lighttpd-git-77c01f981725512653c01cde5ca74c11633dfec4.tar.gz |
[core] buffer_append_path_len()
concatenate paths, placing single '/' between strings
reverts broken commit:b9402283
(thx avij)
-rw-r--r-- | src/buffer.c | 15 | ||||
-rw-r--r-- | src/buffer.h | 1 | ||||
-rw-r--r-- | src/chunk.c | 3 | ||||
-rw-r--r-- | src/mod_dirlisting.c | 6 | ||||
-rw-r--r-- | src/mod_userdir.c | 12 | ||||
-rw-r--r-- | src/mod_webdav.c | 42 | ||||
-rw-r--r-- | src/response.c | 6 | ||||
-rw-r--r-- | src/t/test_buffer.c | 34 |
8 files changed, 73 insertions, 46 deletions
diff --git a/src/buffer.c b/src/buffer.c index 77d76a8e..f958e17f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -198,6 +198,21 @@ void buffer_append_string_len(buffer *b, const char *s, size_t s_len) { b->used += s_len; } +void buffer_append_path_len(buffer *b, const char *a, size_t alen) { + size_t blen = buffer_string_length(b); + int aslash = (alen && a[0] == '/'); + buffer_string_prepare_append(b, alen+2); /*(+ '/' and + '\0' if 0 == blen)*/ + if (blen && b->ptr[blen-1] == '/') { + if (aslash) --b->used; + } + else { + if (!b->used) ++b->used; + if (!aslash) b->ptr[++b->used - 2] = '/'; + } + memcpy(b->ptr+b->used-1, a, alen); + b->ptr[(b->used += alen)-1] = '\0'; +} + void buffer_append_uint_hex_lc(buffer *b, uintmax_t value) { char *buf; unsigned int shift = 0; diff --git a/src/buffer.h b/src/buffer.h index 733cb43a..df461e1a 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -170,6 +170,7 @@ static inline int light_isalnum(int c) { static inline size_t buffer_string_length(const buffer *b); /* buffer string length without terminating 0 */ static inline size_t buffer_string_space(const buffer *b); /* maximum length of string that can be stored without reallocating */ static inline void buffer_append_slash(buffer *b); /* append '/' no non-empty strings not ending in '/' */ +void buffer_append_path_len(buffer *b, const char *a, size_t alen); /* join strings with '/', if '/' not present */ #define BUFFER_APPEND_STRING_CONST(x, y) \ buffer_append_string_len(x, y, sizeof(y) - 1) diff --git a/src/chunk.c b/src/chunk.c index 4489a854..8f32d643 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -509,8 +509,7 @@ static chunk *chunkqueue_get_append_tempfile(server *srv, chunkqueue *cq) { data_string *ds = (data_string *)cq->tempdirs->data[cq->tempdir_idx]; buffer_copy_buffer(template, ds->value); - buffer_append_slash(template); - buffer_append_string_len(template, CONST_STR_LEN("lighttpd-upload-XXXXXX")); + buffer_append_path_len(template, CONST_STR_LEN("lighttpd-upload-XXXXXX")); #ifdef __COVERITY__ /* POSIX-2008 requires mkstemp create file with 0600 perms */ diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c index 5c492a95..2f746740 100644 --- a/src/mod_dirlisting.c +++ b/src/mod_dirlisting.c @@ -807,8 +807,7 @@ static void http_list_directory_header(server *srv, connection *con, plugin_data buffer *hb = p->conf.show_header; if (hb->ptr[0] != '/') { buffer_copy_buffer(p->tmp_buf, con->physical.path); - buffer_append_slash(p->tmp_buf); - buffer_append_string_buffer(p->tmp_buf, p->conf.show_header); + buffer_append_path_len(p->tmp_buf, CONST_BUF_LEN(p->conf.show_header)); hb = p->tmp_buf; } @@ -858,8 +857,7 @@ static void http_list_directory_footer(server *srv, connection *con, plugin_data buffer *rb = p->conf.show_readme; if (rb->ptr[0] != '/') { buffer_copy_buffer(p->tmp_buf, con->physical.path); - buffer_append_slash(p->tmp_buf); - buffer_append_string_buffer(p->tmp_buf, p->conf.show_readme); + buffer_append_path_len(p->tmp_buf, CONST_BUF_LEN(p->conf.show_readme)); rb = p->tmp_buf; } diff --git a/src/mod_userdir.c b/src/mod_userdir.c index cf99cc03..6389d9fa 100644 --- a/src/mod_userdir.c +++ b/src/mod_userdir.c @@ -262,6 +262,7 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { } /* we build the physical path */ + buffer_clear(p->temp_path); if (buffer_string_is_empty(p->conf.basepath)) { #ifdef HAVE_PWD_H @@ -287,16 +288,13 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { } buffer_copy_buffer(p->temp_path, p->conf.basepath); - buffer_append_slash(p->temp_path); if (p->conf.letterhomes) { if (p->username->ptr[0] == '.') return HANDLER_GO_ON; - buffer_append_string_len(p->temp_path, p->username->ptr, 1); - buffer_append_slash(p->temp_path); + buffer_append_path_len(p->temp_path, p->username->ptr, 1); } - buffer_append_string_buffer(p->temp_path, p->username); + buffer_append_path_len(p->temp_path, CONST_BUF_LEN(p->username)); } - buffer_append_slash(p->temp_path); - buffer_append_string_buffer(p->temp_path, p->conf.path); + buffer_append_path_len(p->temp_path, CONST_BUF_LEN(p->conf.path)); if (buffer_string_is_empty(p->conf.basepath)) { struct stat st; @@ -330,8 +328,6 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { } buffer_copy_buffer(con->physical.path, p->temp_path); - buffer_clear(p->temp_path); - return HANDLER_GO_ON; } diff --git a/src/mod_webdav.c b/src/mod_webdav.c index 1fde022e..8087779c 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -590,6 +590,7 @@ static int webdav_delete_dir(server *srv, connection *con, handler_ctx *hctx, ph while(NULL != (de = readdir(dir))) { struct stat st; + size_t nlen; if ((de->d_name[0] == '.' && de->d_name[1] == '\0') || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { @@ -597,13 +598,12 @@ static int webdav_delete_dir(server *srv, connection *con, handler_ctx *hctx, ph /* ignore the parent dir */ } + nlen = strlen(de->d_name); buffer_copy_buffer(d.path, dst->path); - buffer_append_slash(d.path); - buffer_append_string(d.path, de->d_name); + buffer_append_path_len(d.path, de->d_name, nlen); buffer_copy_buffer(d.rel_path, dst->rel_path); - buffer_append_slash(d.rel_path); - buffer_append_string(d.rel_path, de->d_name); + buffer_append_path_len(d.rel_path, de->d_name, nlen); /* stat and unlink afterwards */ if (-1 == stat(d.path->ptr, &st)) { @@ -770,27 +770,25 @@ static int webdav_copy_dir(server *srv, connection *con, handler_ctx *hctx, phys while (NULL != (de = readdir(srcdir))) { struct stat st; + size_t nlen; if ((de->d_name[0] == '.' && de->d_name[1] == '\0') || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { continue; } + nlen = strlen(de->d_name); buffer_copy_buffer(s.path, src->path); - buffer_append_slash(s.path); - buffer_append_string(s.path, de->d_name); + buffer_append_path_len(s.path, de->d_name, nlen); buffer_copy_buffer(d.path, dst->path); - buffer_append_slash(d.path); - buffer_append_string(d.path, de->d_name); + buffer_append_path_len(d.path, de->d_name, nlen); buffer_copy_buffer(s.rel_path, src->rel_path); - buffer_append_slash(s.rel_path); - buffer_append_string(s.rel_path, de->d_name); + buffer_append_path_len(s.rel_path, de->d_name, nlen); buffer_copy_buffer(d.rel_path, dst->rel_path); - buffer_append_slash(d.rel_path); - buffer_append_string(d.rel_path, de->d_name); + buffer_append_path_len(d.rel_path, de->d_name, nlen); if (-1 == stat(s.path->ptr, &st)) { /* why ? */ @@ -1500,19 +1498,18 @@ static handler_t mod_webdav_propfind(server *srv, connection *con, plugin_data * d.rel_path = buffer_init(); while(NULL != (de = readdir(dir))) { + size_t nlen; if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))) { continue; /* ignore the parent and target dir */ } + nlen = strlen(de->d_name); buffer_copy_buffer(d.path, dst->path); - buffer_append_slash(d.path); + buffer_append_path_len(d.path, de->d_name, nlen); buffer_copy_buffer(d.rel_path, dst->rel_path); - buffer_append_slash(d.rel_path); - - buffer_append_string(d.path, de->d_name); - buffer_append_string(d.rel_path, de->d_name); + buffer_append_path_len(d.rel_path, de->d_name, nlen); buffer_clear(prop_200); buffer_clear(prop_404); @@ -2064,16 +2061,7 @@ static handler_t mod_webdav_copymove(server *srv, connection *con, plugin_data * buffer_copy_buffer(p->physical.path, p->physical.doc_root); buffer_append_slash(p->physical.path); buffer_copy_buffer(p->physical.basedir, p->physical.path); - - /* don't add a second / */ - if (p->physical.rel_path->ptr[0] == '/') { - #ifdef __COVERITY__ - if (buffer_string_length(p->physical.rel_path) < 1) return HANDLER_ERROR; - #endif - buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, buffer_string_length(p->physical.rel_path) - 1); - } else { - buffer_append_string_buffer(p->physical.path, p->physical.rel_path); - } + buffer_append_path_len(p->physical.path, CONST_BUF_LEN(p->physical.rel_path)); } } diff --git a/src/response.c b/src/response.c index 7df36691..f6d910dd 100644 --- a/src/response.c +++ b/src/response.c @@ -615,11 +615,7 @@ handler_t http_response_prepare(server *srv, connection *con) { buffer_copy_buffer(con->physical.basedir, con->physical.doc_root); buffer_copy_buffer(con->physical.path, con->physical.doc_root); - if (buffer_string_is_empty(con->physical.rel_path) - || con->physical.rel_path->ptr[0] != '/') { - buffer_append_slash(con->physical.path); - } - buffer_append_string_buffer(con->physical.path, con->physical.rel_path); + buffer_append_path_len(con->physical.path, CONST_BUF_LEN(con->physical.rel_path)); if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root"); diff --git a/src/t/test_buffer.c b/src/t/test_buffer.c index 3e6eb4df..1dae0b41 100644 --- a/src/t/test_buffer.c +++ b/src/t/test_buffer.c @@ -114,10 +114,44 @@ static void test_buffer_string_space(void) { buffer_free(b); } +static void test_buffer_append_path_len(void) { + buffer *b = buffer_init(); + + buffer_append_path_len(b, CONST_STR_LEN("a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("/a"))); + buffer_clear(b); + buffer_append_path_len(b, CONST_STR_LEN("a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("/a"))); + buffer_clear(b); + buffer_append_path_len(b, CONST_STR_LEN("/a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("/a"))); + buffer_copy_string_len(b, CONST_STR_LEN("/")); + buffer_append_path_len(b, CONST_STR_LEN("a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("/a"))); + buffer_copy_string_len(b, CONST_STR_LEN("/")); + buffer_append_path_len(b, CONST_STR_LEN("/a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("/a"))); + buffer_copy_string_len(b, CONST_STR_LEN("a")); + buffer_append_path_len(b, CONST_STR_LEN("a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("a/a"))); + buffer_copy_string_len(b, CONST_STR_LEN("a/")); + buffer_append_path_len(b, CONST_STR_LEN("a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("a/a"))); + buffer_copy_string_len(b, CONST_STR_LEN("a/")); + buffer_append_path_len(b, CONST_STR_LEN("/a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("a/a"))); + buffer_copy_string_len(b, CONST_STR_LEN("/a/")); + buffer_append_path_len(b, CONST_STR_LEN("/a")); + assert(buffer_is_equal_string(b, CONST_STR_LEN("/a/a"))); + + buffer_free(b); +} + int main() { test_buffer_path_simplify(); test_buffer_to_lower_upper(); test_buffer_string_space(); + test_buffer_append_path_len(); return 0; } |