diff options
Diffstat (limited to 'src/feature/control/control_fmt.c')
-rw-r--r-- | src/feature/control/control_fmt.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/feature/control/control_fmt.c b/src/feature/control/control_fmt.c index c87a224ac5..290ea61450 100644 --- a/src/feature/control/control_fmt.c +++ b/src/feature/control/control_fmt.c @@ -297,3 +297,98 @@ read_escaped_data(const char *data, size_t len, char **out) *outp = '\0'; return outp - *out; } + +/** Send a "DONE" message down the control connection <b>conn</b>. */ +void +send_control_done(control_connection_t *conn) +{ + connection_write_str_to_buf("250 OK\r\n", conn); +} + +/** If the first <b>in_len_max</b> characters in <b>start</b> contain a + * double-quoted string with escaped characters, return the length of that + * string (as encoded, including quotes). Otherwise return -1. */ +static inline int +get_escaped_string_length(const char *start, size_t in_len_max, + int *chars_out) +{ + const char *cp, *end; + int chars = 0; + + if (*start != '\"') + return -1; + + cp = start+1; + end = start+in_len_max; + + /* Calculate length. */ + while (1) { + if (cp >= end) { + return -1; /* Too long. */ + } else if (*cp == '\\') { + if (++cp == end) + return -1; /* Can't escape EOS. */ + ++cp; + ++chars; + } else if (*cp == '\"') { + break; + } else { + ++cp; + ++chars; + } + } + if (chars_out) + *chars_out = chars; + return (int)(cp - start+1); +} + +/** As decode_escaped_string, but does not decode the string: copies the + * entire thing, including quotation marks. */ +const char * +extract_escaped_string(const char *start, size_t in_len_max, + char **out, size_t *out_len) +{ + int length = get_escaped_string_length(start, in_len_max, NULL); + if (length<0) + return NULL; + *out_len = length; + *out = tor_strndup(start, *out_len); + return start+length; +} + +/** Given a pointer to a string starting at <b>start</b> containing + * <b>in_len_max</b> characters, decode a string beginning with one double + * quote, containing any number of non-quote characters or characters escaped + * with a backslash, and ending with a final double quote. Place the resulting + * string (unquoted, unescaped) into a newly allocated string in *<b>out</b>; + * store its length in <b>out_len</b>. On success, return a pointer to the + * character immediately following the escaped string. On failure, return + * NULL. */ +const char * +decode_escaped_string(const char *start, size_t in_len_max, + char **out, size_t *out_len) +{ + const char *cp, *end; + char *outp; + int len, n_chars = 0; + + len = get_escaped_string_length(start, in_len_max, &n_chars); + if (len<0) + return NULL; + + end = start+len-1; /* Index of last quote. */ + tor_assert(*end == '\"'); + outp = *out = tor_malloc(len+1); + *out_len = n_chars; + + cp = start+1; + while (cp < end) { + if (*cp == '\\') + ++cp; + *outp++ = *cp++; + } + *outp = '\0'; + tor_assert((outp - *out) == (int)*out_len); + + return end+1; +} |