[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH (speechd)] Various fixes for deescape_dot.
From: |
Christopher Brannon |
Subject: |
[PATCH (speechd)] Various fixes for deescape_dot. |
Date: |
Fri, 26 Feb 2010 18:28:18 -0600 |
First, this function used two different memory allocators: libc's malloc
and glib's g_malloc.
There's no way for the caller to know which allocator it was actually
using, since the decision depended on the contents of the argument string...
After this patch, deescape_dot always uses libc's malloc, since I'm
fairly certain that its return value is eventually handled by free
in all cases.
This function just needs to replace .. with . at the beginning of each
line. See the definition of the speak command in the SSIP spec. The previous
version was not quite doing that.
I also was able to remove a string duplication from the function which
calls deescape_dot, because the new implementation does not modify
its argument string.
---
src/server/parse.c | 128 ++++++++++++++++++++++-----------------------------
src/server/parse.h | 2 +-
2 files changed, 56 insertions(+), 74 deletions(-)
diff --git a/src/server/parse.c b/src/server/parse.c
index 36214ef..51fbf88 100644
--- a/src/server/parse.c
+++ b/src/server/parse.c
@@ -168,18 +168,9 @@ parse(const char *buf, const int bytes, const int fd)
new = (TSpeechDMessage*) spd_malloc(sizeof(TSpeechDMessage));
new->bytes = SpeechdSocket[fd].o_bytes;
- new->buf = (char*) spd_malloc(new->bytes + 1);
-
assert(SpeechdSocket[fd].o_buf != NULL);
- memcpy(new->buf, SpeechdSocket[fd].o_buf->str, new->bytes);
- new->buf[new->bytes] = 0;
-
-
+ new->buf = deescape_dot(SpeechdSocket[fd].o_buf->str, new->bytes);
reparted = SpeechdSocket[fd].inside_block;
-
- /* TODO: Unify this with the above copying */
- new->buf = deescape_dot(new->buf);
-
MSG(5, "New buf is now: |%s|", new->buf);
if((msg_uid = queue_message(new, fd, 1, MSGTYPE_TEXT, reparted))
== 0){
if(SPEECHD_DEBUG) FATAL("Can't queue message\n");
@@ -993,80 +984,71 @@ parse_block(const char *buf, const int bytes, const int
fd)
}
else return strdup(ERR_PARAMETER_INVALID);
}
+
+/*
+ * deescape_dot: Replace .. with . at the start of lines or at the
+ * start of the string.
+ * @orig_text: text to be unescaped.
+ * @orig_len: length of the text.
+ * Returns: a freshly allocated string, containing the unescaped data.
+ *
+ * In SSIP, the message terminator is \r\n.\r\n, just as it is in SMTP
+ * and similar protocols. Thus, period needs to be escaped when it
+ * is the only character on a line. deescape_dot reverts that
+ * transformation, after the message is received.
+ * This function deserves further examination.
+ */
-/* TODO: I have no idea how this works. It seems it doesn't
-even work. */
char*
-deescape_dot(char *otext)
+deescape_dot(const char *orig_text, size_t orig_len)
{
- char *seq;
- GString *ntext;
- char *ootext;
- char *ret = NULL;
- int len;
-
- if (otext == NULL) return NULL;
-
- MSG2(6, "escaping", "Incomming text: |%s|", otext);
-
- ootext = otext;
-
- ntext = g_string_new("");
-
- if (strlen(otext) == 2){
- if (!strcmp(otext, "..")){
- otext[1] = 0;
- g_string_free(ntext,1);
- return otext;
+ /* Constants. DOTLINE is CRLF followed by a period.
+ * DOTLINELEN is the length of DOTLINE.
+ * ESCAPED_DOTLINELEN is the length of the sequence \r\n..,
+ * which is used in the original (unescaped) text.
+ */
+ static const char *DOTLINE = "\r\n.";
+ static const size_t DOTLINELEN = 3;
+ static const size_t ESCAPED_DOTLINELEN = 4; /* \r\n.. */
+
+ char *out_text = NULL;
+ char *out_ptr;
+ const char *orig_end = orig_text + orig_len;
+
+ if (orig_text == NULL)
+ return NULL;
+
+ out_text = spd_malloc(orig_len + 1);
+ /* We may have allocated more than we need. In any case, out_text
+ * can be no longer than orig_text.
+ * Note: spd_malloc aborts the program on failure to allocate. */
+
+ out_ptr = out_text;
+ if (orig_len >= 2) {
+ /* De-escape .. at start of text. */
+ if ((orig_text[0] == '.') && (orig_text[1] == '.')) {
+ *(out_ptr++) = '.';
+ orig_text = orig_text+2;
}
}
- if (strlen(otext) >= 2){
- if ((otext[0] == '.') && (otext[1] == '.')){
- g_string_append(ntext, ".");
- otext = otext+2;
+ while (orig_text < orig_end) {
+ if ((orig_text[0] == '\r') && (orig_text[1] == '\n')
+ && (orig_text[2] == '.') && (orig_text[3] == '.')) {
+ /* We just found \r\n.., the sequence we want to unescape. */
+ memcpy(out_ptr, DOTLINE, DOTLINELEN);
+ out_ptr += DOTLINELEN;
+ orig_text += ESCAPED_DOTLINELEN;
+ } else {
+ /* Just copy the character from source to destination... */
+ *(out_ptr++) = *(orig_text++);
}
}
- MSG2(6, "escaping", "Altering text (I): |%s|", ntext->str);
-
- while ( (seq = strstr(otext, "\r\n..\r\n")) ){
- *seq = 0;
- g_string_append(ntext, otext);
- g_string_append(ntext, "\r\n.\r\n");
-
- MSG2(6, "escaping", "Altering text (II) / 1: |%s|", otext);
- otext = seq + 6;
- MSG2(6, "escaping", "Altering text (II) / 2: |%s|", otext);
- }
-
- MSG2(6, "escaping", "Altering text (II): |%s|", ntext->str);
-
- len = strlen(otext);
- if (len >= 4){
- if ((otext[len-4] == '\r') && (otext[len-3] == '\n')
- && (otext[len-2] == '.') && (otext[len-1] == '.')){
- otext[len-1] = 0;
- MSG2(6, "escaping", "Altering text (II-b) otext: |%s|", otext);
- }
- }
-
- if (otext == ootext){
- ret = otext;
- g_string_free(ntext, 1);
- }else{
- g_string_append(ntext, otext);
- spd_free(ootext);
- ret = ntext->str;
- g_string_free(ntext, 0);
- }
-
- MSG2(6, "escaping", "Altered text: |%s|", ret);
-
- return ret;
+ *out_ptr = '\0'; /* NUL-terminate. */
+ return out_text;
}
-
/* isanum() tests if the given string is a number,
* returns 1 if yes, 0 otherwise. */
int
diff --git a/src/server/parse.h b/src/server/parse.h
index 2201d03..9f930b8 100644
--- a/src/server/parse.h
+++ b/src/server/parse.h
@@ -18,7 +18,7 @@ char* parse_get(const char* buf, const int bytes, const int
fd);
char* parse_help(const char* buf, const int bytes, const int fd);
char* parse_block(const char* buf, const int bytes, const int fd);
-char* deescape_dot(char *otext);
+char* deescape_dot(const char *orig_text, size_t orig_len);
/* Function for parsing the input from clients */
char* get_param(const char *buf, const int n, const int bytes, const int
lower_case);
--
1.7.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH (speechd)] Various fixes for deescape_dot.,
Christopher Brannon <=