summaryrefslogtreecommitdiff
path: root/src/feature/control/control_fmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/control/control_fmt.c')
-rw-r--r--src/feature/control/control_fmt.c95
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;
+}