diff options
author | Edward Thomson <ethomson@microsoft.com> | 2015-09-23 16:30:48 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@github.com> | 2016-05-26 13:01:06 -0500 |
commit | d3d95d5ae2c0c06724d040713a04202073114041 (patch) | |
tree | 230acabe28ae3b49cc291d1ae90de5ce658bbced /src/buffer.c | |
parent | 72806f4cca7602460d19fbee8be98449304e92a2 (diff) | |
download | libgit2-d3d95d5ae2c0c06724d040713a04202073114041.tar.gz |
git_buf_quote: quote ugly characters
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/buffer.c b/src/buffer.c index c2a54a5bd..31341c4b5 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -858,6 +858,72 @@ int git_buf_splice( return 0; } +/* Quote per http://marc.info/?l=git&m=112927316408690&w=2 */ +int git_buf_quote(git_buf *buf) +{ + const char whitespace[] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' }; + git_buf quoted = GIT_BUF_INIT; + size_t i = 0; + bool quote = false; + int error = 0; + + /* walk to the first char that needs quoting */ + if (buf->size && buf->ptr[0] == '!') + quote = true; + + for (i = 0; !quote && i < buf->size; i++) { + if (buf->ptr[i] == '"' || buf->ptr[i] == '\\' || + buf->ptr[i] < ' ' || buf->ptr[i] > '~') { + quote = true; + break; + } + } + + if (!quote) + goto done; + + git_buf_putc("ed, '"'); + git_buf_put("ed, buf->ptr, i); + + for (; i < buf->size; i++) { + /* whitespace - use the map above, which is ordered by ascii value */ + if (buf->ptr[i] >= '\a' && buf->ptr[i] <= '\r') { + git_buf_putc("ed, '\\'); + git_buf_putc("ed, whitespace[buf->ptr[i] - '\a']); + } + + /* double quote and backslash must be escaped */ + else if (buf->ptr[i] == '"' || buf->ptr[i] == '\\') { + git_buf_putc("ed, '\\'); + git_buf_putc("ed, buf->ptr[i]); + } + + /* escape anything unprintable as octal */ + else if (buf->ptr[i] != ' ' && + (buf->ptr[i] < '!' || buf->ptr[i] > '~')) { + git_buf_printf("ed, "\\%03o", buf->ptr[i]); + } + + /* yay, printable! */ + else { + git_buf_putc("ed, buf->ptr[i]); + } + } + + git_buf_putc("ed, '"'); + + if (git_buf_oom("ed)) { + error = -1; + goto done; + } + + git_buf_swap("ed, buf); + +done: + git_buf_free("ed); + return error; +} + /* Unquote per http://marc.info/?l=git&m=112927316408690&w=2 */ int git_buf_unquote(git_buf *buf) { |