httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From soc-r...@apache.org
Subject svn commit: r279518 - in /httpd/mod_smtpd/trunk: smtp_core.c smtp_filters.c smtp_filters.h smtp_protocol.c smtp_util.c
Date Thu, 08 Sep 2005 05:26:41 GMT
Author: soc-rian
Date: Wed Sep  7 22:26:37 2005
New Revision: 279518

URL: http://svn.apache.org/viewcvs?rev=279518&view=rev
Log:
moved data command termination to a filter

Modified:
    httpd/mod_smtpd/trunk/smtp_core.c
    httpd/mod_smtpd/trunk/smtp_filters.c
    httpd/mod_smtpd/trunk/smtp_filters.h
    httpd/mod_smtpd/trunk/smtp_protocol.c
    httpd/mod_smtpd/trunk/smtp_util.c

Modified: httpd/mod_smtpd/trunk/smtp_core.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/smtp_core.c?rev=279518&r1=279517&r2=279518&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/smtp_core.c (original)
+++ httpd/mod_smtpd/trunk/smtp_core.c Wed Sep  7 22:26:37 2005
@@ -38,6 +38,7 @@
 #include "smtp_filters.h"
 
 module AP_MODULE_DECLARE_DATA smtpd_module;
+ap_filter_rec_t *smtpd_data_input_filter_handle;
 
 static apr_hash_t *smtpd_handlers;
 
@@ -281,14 +282,14 @@
 };
 
 /* registers httpd hooks */
-static void register_hooks (apr_pool_t *p)
+static void register_hooks(apr_pool_t *p)
 {
-    /* register connection processor  */
+    /* register connection processor */
     ap_hook_process_connection(process_smtp_connection, NULL, NULL,
                                APR_HOOK_MIDDLE);
 
-    smtpd_smtp_input_filter_handle =
-        ap_register_input_filter("SMTP_IN", smtpd_smtp_filter,
+    smtpd_data_input_filter_handle =
+        ap_register_input_filter("SMTP_IN", smtpd_data_filter,
                                  NULL, AP_FTYPE_PROTOCOL);
     
     smtpd_handlers = apr_hash_make(p);

Modified: httpd/mod_smtpd/trunk/smtp_filters.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/smtp_filters.c?rev=279518&r1=279517&r2=279518&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/smtp_filters.c (original)
+++ httpd/mod_smtpd/trunk/smtp_filters.c Wed Sep  7 22:26:37 2005
@@ -17,31 +17,92 @@
 #include "util_filter.h"
 #include "apr_buckets.h"
 
-ap_filter_rec_t *smtpd_smtp_input_filter_handle;
+#include "mod_smtpd.h"
+#include "smtp_filters.h"
 
-apr_status_t smtpd_smtp_filter(ap_filter_t *f, apr_bucket_brigade *b,
+#define SMTPD_ASCII_DOT 0x2E
+apr_status_t smtpd_data_filter(ap_filter_t *f, apr_bucket_brigade *b,
                                ap_input_mode_t mode, apr_read_type_e block,
                                apr_off_t readbytes)
 {
-    apr_bucket_brigade *old_bb = f->ctx;
+    static int saw_eos = 0;
 
-    /* if our input brigade is empty, just go on */
-    if (APR_BRIGADE_EMPTY(old_bb))
-        return ap_get_brigade(f->next, b, mode, block, readbytes);
+    /* if we already got a dot, don't read more data
+       just fill the brigade with an eos bucket and return
+    */
     
-    if (mode == AP_MODE_GETLINE) {
-        apr_off_t bb_len;
-        apr_brigade_split_line(b, old_bb, block, 1000);
-        /* if we have one last empty bucket
-           our brigade is empty */
-        apr_brigade_length(old_bb, 1, &bb_len);
-        if (!bb_len)
-            apr_brigade_cleanup(old_bb);
+    if (saw_eos) {
+        /* then insert a EOS bucket at the head of the brigade */
+        apr_bucket *ne = apr_bucket_eos_create(f->c->bucket_alloc);
+        APR_BRIGADE_INSERT_HEAD(b, ne);
+        return APR_SUCCESS;
     }
-    /* XXX: since we are only using AP_MODE_GETLINE in mod_smtpd
-       the other read types are ignored, but this can be robustified */
-    else {
-        APR_BRIGADE_CONCAT(b, old_bb);
+
+    if (mode == AP_MODE_GETLINE) {
+        apr_bucket *e;
+        char stack_buf[3];
+        apr_status_t rc;
+        apr_size_t bytes_handled = 0;
+        int breakpoint;
+        char ending_sequence[3] = {SMTPD_ASCII_DOT, APR_ASCII_CR, APR_ASCII_LF};
+
+        rc = ap_get_brigade(f->next, b, mode, block, readbytes);
+        if (rc != APR_SUCCESS)
+            return rc;
+        
+        /* only get the first 3 bytes of the brigade */
+        for (e = APR_BRIGADE_FIRST(b);
+             e != APR_BRIGADE_SENTINEL(b);
+             e = APR_BUCKET_NEXT(e)) {
+            const char *str;
+            apr_size_t len;
+
+            rc = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
+            if (rc != APR_SUCCESS)
+                return rc;
+
+            breakpoint = 3 - bytes_handled;
+            memcpy(stack_buf + bytes_handled, str, breakpoint < len ?
+                   breakpoint : len);
+        
+            bytes_handled += len;
+
+            /* if the first three bytes are ".\r\n"
+               delete that stuff, and put an EOS bucket there instead
+            */
+            if ((bytes_handled >= 3)  &&
+                (!strncmp(stack_buf, ending_sequence, 3))) {
+                apr_bucket *ne;
+
+                apr_bucket_split(e, breakpoint);
+                e = APR_BUCKET_NEXT(e);
+            
+                /* delete the buckets that entail ".\r\n" */
+                while (!APR_BRIGADE_EMPTY(b)) {
+                    ne = APR_BRIGADE_FIRST(b);
+
+                    if (ne == e)
+                        break;
+                
+                    apr_bucket_delete(ne);
+                }
+
+                /* then insert a EOS bucket at the head of the brigade */
+                ne = apr_bucket_eos_create(f->c->bucket_alloc);
+                APR_BRIGADE_INSERT_HEAD(b, ne);
+                saw_eos = 1;
+                break;
+            }
+        }
+
+    } else if (mode == AP_MODE_READBYTES) {
+        /* XXX: need to check for single "./r/n" here too!!
+           maybe. might not have to since SMTP is line oriented
+        */
+        return ap_get_brigade(f->next, b, mode, block, readbytes);
+    } else {
+        return ap_get_brigade(f->next, b, mode, block, readbytes);
     }
+    
     return APR_SUCCESS;
 }

Modified: httpd/mod_smtpd/trunk/smtp_filters.h
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/smtp_filters.h?rev=279518&r1=279517&r2=279518&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/smtp_filters.h (original)
+++ httpd/mod_smtpd/trunk/smtp_filters.h Wed Sep  7 22:26:37 2005
@@ -21,8 +21,7 @@
 extern "C" {
 #endif
 
-extern ap_filter_rec_t *smtpd_smtp_input_filter_handle;
-apr_status_t smtpd_smtp_filter(ap_filter_t *f, apr_bucket_brigade *b,
+apr_status_t smtpd_data_filter(ap_filter_t *f, apr_bucket_brigade *b,
                                ap_input_mode_t mode, apr_read_type_e block,
                                apr_off_t readbytes);
 

Modified: httpd/mod_smtpd/trunk/smtp_protocol.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/smtp_protocol.c?rev=279518&r1=279517&r2=279518&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/smtp_protocol.c (original)
+++ httpd/mod_smtpd/trunk/smtp_protocol.c Wed Sep  7 22:26:37 2005
@@ -38,6 +38,7 @@
 #include "smtp_filters.h"
 
 extern module AP_MODULE_DECLARE_DATA smtpd_module;
+extern ap_filter_rec_t *smtpd_data_input_filter_handle;
 
 inline static int smtpd_handle_unrecognized_command(smtpd_conn_rec *scr,
                                                     smtpd_return_data *in_data,
@@ -133,7 +134,7 @@
         else {
             smtpd_respond_oneline(scr, 521, "Command Denied");
         }
-    return 521;
+        return 521;
     case SMTPD_DONE:
         return 1;
     case SMTPD_DONE_DISCONNECT:
@@ -531,7 +532,6 @@
     char our_buffer[BUFFER_STR_LEN];
     apr_file_t *tfp;
     apr_size_t len, total_data = 0;
-    apreq_parser_t *rfc822_parser;
     apr_bucket_brigade *bb;
 
     switch(smtpd_run_data(scr, in_data)) {
@@ -578,12 +578,12 @@
     default:
         break;
     }
-    
+
     if (str->trans_state != SMTPD_STATE_GOT_RCPT) {
         smtpd_respond_oneline(scr, 503, "Error: need RCPT command");
         return 503;
     }
-
+    
     tempfile = apr_pstrdup(str->p, "/tmp/tmp.XXXXXX");
     rv = apr_file_mktemp(&tfp, tempfile,
                          APR_CREATE | APR_WRITE | APR_READ |
@@ -597,8 +597,11 @@
 
     smtpd_respond_oneline(scr, 354, "End data with <CR><LF>.<CR><LF>");
 
-    bb = apr_brigade_create(str->p, scr->c->bucket_alloc);
-    
+    /* add filter that translates ".\r\n" into EOS */
+    smtpd_add_input_filter_handle(smtpd_data_input_filter_handle, NULL, scr);
+
+    /* going to make header parsing a filter */
+#if 0
     /* get a line after the data command */
     smtpd_getline(scr, our_buffer, BUFFER_STR_LEN - 3, &len,
                   SMTPD_READ_COMMAND);
@@ -617,7 +620,9 @@
 
     /* if the first line is a header, then parse the rest as header */
     if (is_rfc822_header(our_buffer)) {
-        rfc822_parser = apreq_parser_make(str->p, scr->c->bucket_alloc,
+        apreq_parser_t *rfc822_parser;
+        rfc822_parser = apreq_parser_make(str->p,
+                                          scr->c->bucket_alloc,
                                           "text/rfc822", apreq_parse_headers,
                                           1000, NULL, NULL, NULL);
         do {
@@ -627,25 +632,23 @@
             rv = apreq_parser_run(rfc822_parser, str->headers, bb);
         } while (rv == APR_INCOMPLETE);
     }
-   
-    /* add filter that returns data just read */
-    smtpd_add_input_filter_handle(smtpd_smtp_input_filter_handle, bb, scr);
 
+#endif
     /* by convention this is where most filters
        should be inserted, but no action can be taken here
        right in the middle of the data command
        it is called even when there are no headers.
     */
     smtpd_run_headers_parsed(scr, in_data);
-
-    /* just wait until we get the line with a dot. */
-    /* or until we can't read anymore. */
-    /* or until we have too much data */
+   
+    /* wait until there is no more data
+       or until we have too much data */
     while (((rv = smtpd_getline(scr, our_buffer, BUFFER_STR_LEN, &len,
-                                SMTPD_READ_DATA))
-            == APR_SUCCESS) &&
-           (strcmp(our_buffer, ".")) &&
+                                SMTPD_READ_DATA)) == APR_SUCCESS) &&
            (total_data < pConfig->max_data)) {
+        if (len == 0)
+            break;
+
         /* character data read plus newline */
         total_data += len + 1;
         apr_file_write(tfp, our_buffer, &len);
@@ -665,7 +668,7 @@
     case SMTPD_DENY:
         retval = 552;
         if (in_data->msgs) {
-        smtpd_respond_multiline(scr, 552, in_data->msgs);
+            smtpd_respond_multiline(scr, 552, in_data->msgs);
         }
         else {
             smtpd_respond_oneline(scr, 552, "Message denied");

Modified: httpd/mod_smtpd/trunk/smtp_util.c
URL: http://svn.apache.org/viewcvs/httpd/mod_smtpd/trunk/smtp_util.c?rev=279518&r1=279517&r2=279518&view=diff
==============================================================================
--- httpd/mod_smtpd/trunk/smtp_util.c (original)
+++ httpd/mod_smtpd/trunk/smtp_util.c Wed Sep  7 22:26:37 2005
@@ -54,11 +54,13 @@
     const char *str;
     char *pos, *last_char = data;
     apr_size_t len, bytes_handled = 0;
+    int saw_eos = 0;
     ap_filter_t *input_filters = read_type == SMTPD_READ_DATA ?
       scr->transaction->input_filters :
       scr->c->input_filters;
 
-    while (1) {
+    while (!saw_eos) {
+        apr_brigade_cleanup(scr->bb_in);
         rc = ap_get_brigade(input_filters, scr->bb_in, AP_MODE_GETLINE,
                             APR_BLOCK_READ, 0);
         if (rc != APR_SUCCESS)
@@ -66,7 +68,13 @@
         
         while(!APR_BRIGADE_EMPTY(scr->bb_in)) {
             e = APR_BRIGADE_FIRST(scr->bb_in);
-            
+
+            /* If we see an EOS, don't bother doing anything more. */
+            if (APR_BUCKET_IS_EOS(e)) {
+                saw_eos = 1;
+                break;
+            }
+
             rc = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
             if (rc != APR_SUCCESS)
                 return rc;      



Mime
View raw message