[PATCH 1 of 7] Mail: add IMAP ID command support

Filipe da Silva fdasilvayy at gmail.com
Tue Jan 14 11:54:18 UTC 2014


# HG changeset patch
# User Filipe da Silva <fdasilvayy at gmail.com>
# Date 1389700210 -3600
#      Tue Jan 14 12:50:10 2014 +0100
# Node ID 0ff28c3c519125db11ae3c56fbf34a7a5975a452
# Parent  d049b0ea00a388c142627f10a0ee01c5b1bedc43
Mail: add IMAP ID command support.
add parsing of IMAP ID command and his parameter list, see RFC2971

diff -r d049b0ea00a3 -r 0ff28c3c5191 src/mail/ngx_mail.h
--- a/src/mail/ngx_mail.h	Fri Jan 10 16:12:40 2014 +0100
+++ b/src/mail/ngx_mail.h	Tue Jan 14 12:50:10 2014 +0100
@@ -215,6 +215,7 @@
     unsigned                quoted:1;
     unsigned                backslash:1;
     unsigned                no_sync_literal:1;
+    unsigned                params_list:1;
     unsigned                starttls:1;
     unsigned                esmtp:1;
     unsigned                auth_method:3;
@@ -233,6 +234,7 @@
     ngx_str_t               smtp_helo;
     ngx_str_t               smtp_from;
     ngx_str_t               smtp_to;
+    ngx_str_t               imap_client_id;
 
     ngx_str_t               cmd;
 
@@ -284,6 +286,7 @@
 
 #define NGX_IMAP_AUTHENTICATE  7
 
+#define NGX_IMAP_ID            8
 
 #define NGX_SMTP_HELO          1
 #define NGX_SMTP_EHLO          2
diff -r d049b0ea00a3 -r 0ff28c3c5191 src/mail/ngx_mail_imap_handler.c
--- a/src/mail/ngx_mail_imap_handler.c	Fri Jan 10 16:12:40 2014 +0100
+++ b/src/mail/ngx_mail_imap_handler.c	Tue Jan 14 12:50:10 2014 +0100
@@ -16,6 +16,8 @@
     ngx_connection_t *c);
 static ngx_int_t ngx_mail_imap_authenticate(ngx_mail_session_t *s,
     ngx_connection_t *c);
+static ngx_int_t ngx_mail_imap_id(ngx_mail_session_t *s,
+    ngx_connection_t *c);
 static ngx_int_t ngx_mail_imap_capability(ngx_mail_session_t *s,
     ngx_connection_t *c);
 static ngx_int_t ngx_mail_imap_starttls(ngx_mail_session_t *s,
@@ -32,6 +34,9 @@
 static u_char  imap_bye[] = "* BYE" CRLF;
 static u_char  imap_invalid_command[] = "BAD invalid command" CRLF;
 
+static ngx_str_t  ngx_mail_imap_client_id_nil = ngx_string("ID NIL");
+static ngx_str_t  ngx_mail_imap_server_id_nil = ngx_string("* ID NIL" CRLF);
+
 
 void
 ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
@@ -179,6 +184,10 @@
                 tag = (rc != NGX_OK);
                 break;
 
+            case NGX_IMAP_ID:
+                rc = ngx_mail_imap_id(s, c);
+                break;
+
             case NGX_IMAP_CAPABILITY:
                 rc = ngx_mail_imap_capability(s, c);
                 break;
@@ -292,6 +301,60 @@
     ngx_mail_send(c->write);
 }
 
+static ngx_int_t
+ngx_mail_imap_id(ngx_mail_session_t *s, ngx_connection_t *c)
+{
+    ngx_str_t   *arg;
+    size_t       size, i;
+    u_char      *p, *data;
+
+    arg = s->args.elts;
+    if (s->args.nelts < 1 || arg[0].len == 0) {
+        return NGX_MAIL_PARSE_INVALID_COMMAND;
+    }
+
+    // Client sends ID NIL or ID ( ... )
+    if (s->args.nelts == 1) {
+
+        if (ngx_strncasecmp(arg[0].data, (u_char *) "NIL", 3) != 0)
+            return NGX_MAIL_PARSE_INVALID_COMMAND;
+
+        s->imap_client_id = ngx_mail_imap_client_id_nil;
+
+    } else {
+        size = sizeof("ID (") - 1;
+        for (i = 0; i < s->args.nelts; i++) {
+            size += 1 + arg[i].len + 2; // 1 space plus 2 quotes
+        }
+
+        data = ngx_pnalloc(c->pool, size);
+        if (data == NULL) {
+            return NGX_ERROR;
+        }
+
+        p = ngx_cpymem(data, "ID (", sizeof("ID (") - 1);
+        for (i = 0; i < s->args.nelts; i++) {
+            *p++ = '"';
+            p = ngx_cpymem(p, arg[i].data, arg[i].len);
+            *p++ = '"';
+            *p++ = ' ';
+        }
+        *--p = ')'; // replace last space
+
+        s->imap_client_id.len = size;
+        s->imap_client_id.data = data;
+    }
+
+    ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
+                   "imap client ID:\"%V%V\"",
+                    &s->tag, &s->imap_client_id);
+
+    // Prepare server response to ID command
+    s->text = ngx_mail_imap_server_id_nil;
+
+    return NGX_OK;
+}
+
 
 static ngx_int_t
 ngx_mail_imap_login(ngx_mail_session_t *s, ngx_connection_t *c)
diff -r d049b0ea00a3 -r 0ff28c3c5191 src/mail/ngx_mail_parse.c
--- a/src/mail/ngx_mail_parse.c	Fri Jan 10 16:12:40 2014 +0100
+++ b/src/mail/ngx_mail_parse.c	Tue Jan 14 12:50:10 2014 +0100
@@ -279,6 +279,16 @@
                 c = s->cmd_start;
 
                 switch (p - c) {
+                case 2:
+                    if ((c[0] == 'I' || c[0] == 'i')
+                        && (c[1] == 'D'|| c[1] == 'd'))
+                    {
+                        s->command = NGX_IMAP_ID;
+
+                    } else {
+                        goto invalid;
+                    }
+                    break;
 
                 case 4:
                     if ((c[0] == 'N' || c[0] == 'n')
@@ -409,14 +419,31 @@
             case ' ':
                 break;
             case CR:
+                if (s->params_list == 1)
+                    goto invalid;
                 state = sw_almost_done;
                 s->arg_end = p;
                 break;
             case LF:
+                if (s->params_list == 1)
+                    goto invalid;
                 s->arg_end = p;
                 goto done;
+            case '(':   // params list begin
+                if (!s->params_list && s->args.nelts == 0) {
+                    s->params_list = 1;
+                    break;
+                }
+                goto invalid;
+            case ')':   // params list closing
+                if (s->params_list == 1 && s->args.nelts > 0) {
+                    s->params_list = 0;
+                    state = sw_spaces_before_argument;
+                    break;
+                }
+                goto invalid;
             case '"':
-                if (s->args.nelts <= 2) {
+                if (s->args.nelts <= 2 || s->params_list) {
                     s->quoted = 1;
                     s->arg_start = p + 1;
                     state = sw_argument;
@@ -430,7 +457,7 @@
                 }
                 goto invalid;
             default:
-                if (s->args.nelts <= 2) {
+                if (s->args.nelts <= 2 && !s->params_list) {
                     s->arg_start = p;
                     state = sw_argument;
                     break;
@@ -602,6 +629,7 @@
         s->quoted = 0;
         s->no_sync_literal = 0;
         s->literal_len = 0;
+        s->params_list = 0;
     }
 
     s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument;
@@ -614,6 +642,7 @@
     s->quoted = 0;
     s->no_sync_literal = 0;
     s->literal_len = 0;
+    s->params_list = 0;
 
     return NGX_MAIL_PARSE_INVALID_COMMAND;
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 000-ImapID_CommandSupport.diff
Type: text/x-patch
Size: 6682 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20140114/05be87e2/attachment-0001.bin>


More information about the nginx-devel mailing list