aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/str_util.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-30 15:57:58 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-30 15:57:58 +0100
commit800399108d67878a6d52db6c3cb28d15e01ccc2a (patch)
tree0b6d3ba9ee9e291f0ef8477aac96c18d7267aaa2 /src/libutil/str_util.c
parent3f3ff6c3150ea10058fb804275111f0d4f051bf1 (diff)
downloadrspamd-800399108d67878a6d52db6c3cb28d15e01ccc2a.tar.gz
rspamd-800399108d67878a6d52db6c3cb28d15e01ccc2a.zip
Add routine to find end of headers position in mime messages.
Diffstat (limited to 'src/libutil/str_util.c')
-rw-r--r--src/libutil/str_util.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/libutil/str_util.c b/src/libutil/str_util.c
index 00f689bff..6465208f9 100644
--- a/src/libutil/str_util.c
+++ b/src/libutil/str_util.c
@@ -1069,3 +1069,111 @@ rspamd_substring_search (const gchar *in, gsize inlen,
return -1;
}
+
+goffset
+rspamd_string_find_eoh (GString *input)
+{
+ const gchar *p, *c = NULL, *end;
+ enum {
+ skip_char = 0,
+ got_cr,
+ got_lf,
+ got_linebreak,
+ got_linebreak_cr,
+ got_linebreak_lf
+ } state = skip_char;
+
+ g_assert (input != NULL);
+
+ p = input->str;
+ end = p + input->len;
+
+ while (p < end) {
+ switch (state) {
+ case skip_char:
+ if (*p == '\r') {
+ p++;
+ state = got_cr;
+ }
+ else if (*p == '\n') {
+ p++;
+ state = got_lf;
+ }
+ else {
+ p++;
+ }
+ break;
+
+ case got_cr:
+ if (*p == '\r') {
+ /*
+ * Double \r\r, so need to check the current char
+ * if it is '\n', then we have \r\r\n sequence, that is NOT
+ * double end of line
+ */
+ if (p < end && p[1] == '\n') {
+ p++;
+ state = got_lf;
+ }
+ else {
+ /* We have \r\r[^\n] */
+ return p - input->str;
+ }
+ }
+ else if (*p == '\n') {
+ p++;
+ state = got_lf;
+ }
+ else {
+ p++;
+ state = skip_char;
+ }
+ break;
+ case got_lf:
+ if (*p == '\n') {
+ /* We have \n\n, which is obviously end of headers */
+ return p - input->str;
+ }
+ else if (*p == '\r') {
+ state = got_linebreak;
+ }
+ else {
+ p++;
+ state = skip_char;
+ }
+ break;
+ case got_linebreak:
+ if (*p == '\r') {
+ c = p;
+ p++;
+ state = got_linebreak_cr;
+ }
+ else if (*p == '\n') {
+ c = p;
+ p++;
+ state = got_linebreak_lf;
+ }
+ else {
+ p++;
+ state = skip_char;
+ }
+ break;
+ case got_linebreak_cr:
+ if (*p == '\r') {
+ /* Got double \r\r after \n, so does not treat it as EOH */
+ state = got_linebreak_cr;
+ p++;
+ }
+ else if (*p == '\n') {
+ state = got_linebreak_lf;
+ p++;
+ }
+ break;
+ case got_linebreak_lf:
+ g_assert (c != NULL);
+ return c - input->str;
+ }
+ }
+
+ return -1;
+}