Commit 8070a357fb6e1dc60a65a2281c932f71bbbd65d6

Edward Thomson 2018-03-03T18:47:35

Introduce `git_buf_decode_percent` Introduce a function to take a percent-encoded string (URI encoded, described by RFC 1738) and decode it into a `git_buf`.

diff --git a/src/buffer.c b/src/buffer.c
index 6dfcbfb..8a58d1a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -212,7 +212,7 @@ int git_buf_put(git_buf *buf, const char *data, size_t len)
 		size_t new_size;
 
 		assert(data);
-		
+
 		GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, len);
 		GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
 		ENSURE_SIZE(buf, new_size);
@@ -455,6 +455,36 @@ on_error:
 	return -1;
 }
 
+#define HEX_DECODE(c) ((c | 32) % 39 - 9)
+
+int git_buf_decode_percent(
+	git_buf *buf,
+	const char *str,
+	size_t str_len)
+{
+	size_t str_pos, new_size;
+
+	GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, str_len);
+	GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
+	ENSURE_SIZE(buf, new_size);
+
+	for (str_pos = 0; str_pos < str_len; buf->size++, str_pos++) {
+		if (str[str_pos] == '%' &&
+			str_len > str_pos + 2 &&
+			isxdigit(str[str_pos + 1]) &&
+			isxdigit(str[str_pos + 2])) {
+			buf->ptr[buf->size] = (HEX_DECODE(str[str_pos + 1]) << 4) +
+				HEX_DECODE(str[str_pos + 2]);
+			str_pos += 2;
+		} else {
+			buf->ptr[buf->size] = str[str_pos];
+		}
+	}
+
+	buf->ptr[buf->size] = '\0';
+	return 0;
+}
+
 int git_buf_vprintf(git_buf *buf, const char *format, va_list ap)
 {
 	size_t expected_size, new_size;
diff --git a/src/buffer.h b/src/buffer.h
index b0aece4..cc77fc0 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -190,6 +190,9 @@ int git_buf_encode_base85(git_buf *buf, const char *data, size_t len);
 /* Decode the given "base85" and write the result to the buffer */
 int git_buf_decode_base85(git_buf *buf, const char *base64, size_t len, size_t output_len);
 
+/* Decode the given percent-encoded string and write the result to the buffer */
+int git_buf_decode_percent(git_buf *buf, const char *str, size_t len);
+
 /*
  * Insert, remove or replace a portion of the buffer.
  *