commit 5b9256f5dcd32e217637938d904d582d5f81c0fd
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Tue May 3 20:01:29 2022 +0200

    add support for incomplete headers to copy_msg_convert()
    
    in the spirit of being liberal about what we accept.
    
    this completely re-structures the header processing loop, with the nice
    side effect of eliminating the gotos.
    
    REFMAIL: 87bkyzhoov....@curie.anarc.at

 src/sync_msg_cvt.c | 118 ++++++++++++++++++++++++++++++---------------
 src/tst_msg_cvt.c  |  83 +++++++++++++++++++++++++++++--
 2 files changed, 159 insertions(+), 42 deletions(-)

diff --git a/src/sync_msg_cvt.c b/src/sync_msg_cvt.c
index 472fcf6b..1e49cf7b 100644
--- a/src/sync_msg_cvt.c
+++ b/src/sync_msg_cvt.c
@@ -44,52 +44,82 @@ copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars )
        uint in_len = vars->data.len;
        uint idx = 0, sbreak = 0, ebreak = 0, break2 = UINT_MAX;
        uint lines = 0, hdr_crs = 0, bdy_crs = 0, app_cr = 0, extra = 0;
-       uint add_subj = 0;
+       uint add_subj = 0, fix_tuid = 0, fix_subj = 0, fix_hdr = 0, end_hdr = 0;
 
        if (vars->srec) {
-         nloop: ;
-               uint start = idx;
-               uint line_cr = 0;
-               char pc = 0;
-               while (idx < in_len) {
-                       char c = in_buf[idx++];
-                       if (c == '\n') {
+               for (;;) {
+                       uint start = idx;
+                       uint line_cr = 0;
+                       uint got_line = 0;
+                       char pc = 0;
+                       while (idx < in_len) {
+                               char c = in_buf[idx++];
+                               if (c == '\n') {
+                                       if (pc == '\r')
+                                               line_cr = 1;
+                                       got_line = 1;
+                                       break;
+                               }
+                               pc = c;
+                       }
+                       if (!ebreak && starts_with_upper( in_buf + start, 
(int)(in_len - start), "X-TUID: ", 8 )) {
+                               extra = (sbreak = start) - (ebreak = idx);
+                               if (!vars->minimal)
+                                       break;
+                               continue;
+                       }
+                       if (break2 == UINT_MAX && vars->minimal &&
+                           starts_with_upper( in_buf + start, (int)(in_len - 
start), "SUBJECT:", 8 )) {
+                               break2 = start + 8;
+                               if (break2 < in_len && in_buf[break2] == ' ')
+                                       break2++;
+                       }
+                       hdr_crs += line_cr;
+                       if (got_line) {
+                               lines++;
+                               if (idx - line_cr - 1 != start)
+                                       continue;
+                               // Empty line => end of headers
+                       } else {
+                               // The line is incomplete.
                                if (pc == '\r')
-                                       line_cr = 1;
-                               if (!ebreak && starts_with_upper( in_buf + 
start, (int)(in_len - start), "X-TUID: ", 8 )) {
-                                       extra = (sbreak = start) - (ebreak = 
idx);
-                                       if (!vars->minimal)
-                                               goto oke;
-                               } else {
-                                       if (break2 == UINT_MAX && vars->minimal 
&&
-                                           starts_with_upper( in_buf + start, 
(int)(in_len - start), "SUBJECT:", 8 )) {
-                                               break2 = start + 8;
-                                               if (break2 < in_len && 
in_buf[break2] == ' ')
-                                                       break2++;
-                                       }
-                                       lines++;
-                                       hdr_crs += line_cr;
+                                       idx--;  // For simplicity, move back 
before trailing CR
+                               if (idx != start) {
+                                       // The line is non-empty, so schedule 
completing it
+                                       fix_hdr = 1;
+                                       // ... and put our headers after it. 
(It would seem easier
+                                       // to prepend them, as then we could 
avoid the fixing - but
+                                       // the line might be a continuation. We 
could also prepend
+                                       // it to _all_ pre-exiting headers, but 
then we would risk
+                                       // masking an (incorrectly present) 
leading 'From ' header.)
+                                       start = idx;
                                }
-                               if (idx - line_cr - 1 == start) {
-                                       if (!ebreak)
-                                               sbreak = ebreak = start;
-                                       if (vars->minimal) {
-                                               in_len = idx;
-                                               if (break2 == UINT_MAX) {
-                                                       break2 = start;
-                                                       add_subj = 1;
-                                               }
-                                       }
-                                       goto oke;
+                               end_hdr = 1;
+                       }
+                       if (!ebreak) {
+                               sbreak = ebreak = start;
+                               fix_tuid = fix_hdr;
+                               fix_hdr = 0;
+                       }
+                       if (vars->minimal) {
+                               in_len = idx;
+                               if (break2 == UINT_MAX) {
+                                       break2 = start;
+                                       add_subj = 1;
+                                       fix_subj = fix_hdr;
+                                       fix_hdr = 0;
                                }
-                               goto nloop;
+                       } else {
+                               fix_hdr = 0;
+                               end_hdr = 0;
                        }
-                       pc = c;
+                       break;
                }
-               free( in_buf );
-               return "has incomplete header";
-         oke:
                app_cr = out_cr && (!in_cr || hdr_crs);
+               if (fix_tuid || fix_subj || fix_hdr)
+                       extra += app_cr + 1;
+               if (end_hdr)
+                       extra += app_cr + 1;
                extra += 8 + TUIDL + app_cr + 1;
        }
        if (out_cr != in_cr) {
@@ -157,6 +187,8 @@ copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars )
                }
                copy_msg_bytes( &out_buf, in_buf, &idx, sbreak, in_cr, out_cr );
 
+               if (fix_tuid)
+                       ADD_NL();
                memcpy( out_buf, "X-TUID: ", 8 );
                out_buf += 8;
                memcpy( out_buf, vars->srec->tuid, TUIDL );
@@ -170,6 +202,8 @@ copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars )
                                memcpy( out_buf, dummy_pfx, strlen(dummy_pfx) );
                                out_buf += strlen(dummy_pfx);
                        } else {
+                               if (fix_subj)
+                                       ADD_NL();
                                memcpy( out_buf, dummy_subj, strlen(dummy_subj) 
);
                                out_buf += strlen(dummy_subj);
                                ADD_NL();
@@ -178,8 +212,14 @@ copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars 
)
        }
        copy_msg_bytes( &out_buf, in_buf, &idx, in_len, in_cr, out_cr );
 
-       if (vars->minimal)
+       if (vars->minimal) {
+               if (end_hdr) {
+                       if (fix_hdr)
+                               ADD_NL();
+                       ADD_NL();
+               }
                memcpy( out_buf, dummy_msg_buf, dummy_msg_len );
+       }
 
        free( in_buf );
        return NULL;
diff --git a/src/tst_msg_cvt.c b/src/tst_msg_cvt.c
index 399c5c2b..399c5653 100644
--- a/src/tst_msg_cvt.c
+++ b/src/tst_msg_cvt.c
@@ -131,10 +131,13 @@ mintests( const char *name, const char *in, const char 
*out, int flagged )
 }
 
 #define FROM "From: de\rvil\r\n"
-#define TO "To: me\r\n"
-#define IN_TUID "X-TUID: garbage\r\n"
+#define R_TO "To: me"
+#define TO R_TO "\r\n"
+#define R_IN_TUID "X-TUID: garbage"
+#define IN_TUID R_IN_TUID "\r\n"
 #define OUT_TUID "X-TUID: " TUID "\r\n"
-#define SUBJECT "Subject: hell\r\n"
+#define R_SUBJECT "Subject: hell"
+#define SUBJECT R_SUBJECT "\r\n"
 #define PH_SUBJECT "Subject: [placeholder] hell\r\n"
 #define NO_SUBJECT "Subject: [placeholder] (No Subject)\r\n"
 #define BODY "\r\nHi,\r\n\r\n...\r\n"
@@ -177,5 +180,79 @@ main( void )
        scc out_tuid_from_subj_to[] = OUT_TUID FROM PH_SUBJECT TO PH_BODY;
        mintests( "tuid / from / subject / to", in_tuid_from_subj_to, 
out_tuid_from_subj_to, REGULAR );
 
+
+       scc in_from_to_b1[] = FROM TO;
+       fulltests( "from / to w/o end", in_from_to_b1, in_from_to_b1, AS_IS );
+       scc out_from_to_b1[] = FROM TO OUT_TUID;
+       fulltests( "from / to w/o end", in_from_to_b1, out_from_to_b1, ADD_TUID 
);
+       scc in_from_tuid_to_b1[] = FROM IN_TUID TO;
+       scc out_from_tuid_to_b1[] = FROM OUT_TUID TO;
+       fulltests( "from / tuid / to w/o end", in_from_tuid_to_b1, 
out_from_tuid_to_b1, ADD_TUID );
+       scc in_from_to_tuid_b1[] = FROM TO IN_TUID;
+       scc out_from_to_tuid_b1[] = FROM TO OUT_TUID;
+       fulltests( "from / to / tuid w/o end", in_from_to_tuid_b1, 
out_from_to_tuid_b1, ADD_TUID );
+
+       mintests( "from / to w/o end", in_from_to_b1, out_from_to_ph, REGULAR );
+       mintests( "from / tuid / to w/o end", in_from_tuid_to_b1, 
out_from_tuid_to_ph, REGULAR );
+       scc in_from_subj_to_b1[] = FROM SUBJECT TO;
+       mintests( "from / subject / to w/o end", in_from_subj_to_b1, 
out_from_subj_to, REGULAR );
+       scc in_from_subj_tuid_to_b1[] = FROM SUBJECT IN_TUID TO;
+       mintests( "from / subject / tuid / to w/o end", 
in_from_subj_tuid_to_b1, out_from_subj_tuid_to, REGULAR );
+       scc in_from_subj_to_tuid_b1[] = FROM SUBJECT TO IN_TUID;
+       scc out_from_subj_to_tuid_b1[] = FROM PH_SUBJECT TO OUT_TUID PH_BODY;
+       mintests( "from / subject / to / tuid w/o end", 
in_from_subj_to_tuid_b1, out_from_subj_to_tuid_b1, REGULAR );
+       scc in_from_tuid_subj_to_b1[] = FROM IN_TUID SUBJECT TO;
+       mintests( "from / tuid / subject / to w/o end", 
in_from_tuid_subj_to_b1, out_from_tuid_subj_to, REGULAR );
+       scc in_from_tuid_to_subj_b1[] = FROM IN_TUID TO SUBJECT;
+       scc out_from_tuid_to_subj_b1[] = FROM OUT_TUID TO PH_SUBJECT PH_BODY;
+       mintests( "from / tuid / to / subject w/o end", 
in_from_tuid_to_subj_b1, out_from_tuid_to_subj_b1, REGULAR );
+
+
+       scc in_from_to_b2[] = FROM R_TO "\r";
+       fulltests( "from / to w/o lf", in_from_to_b2, in_from_to_b2, AS_IS );
+       scc out_from_to_b2[] = FROM TO OUT_TUID "\r";
+       fulltests( "from / to w/o lf", in_from_to_b2, out_from_to_b2, ADD_TUID 
);
+       scc in_from_tuid_to_b2[] = FROM IN_TUID R_TO "\r";
+       scc out_from_tuid_to_b2[] = FROM OUT_TUID R_TO "\r";
+       fulltests( "from / tuid / to w/o lf", in_from_tuid_to_b2, 
out_from_tuid_to_b2, ADD_TUID );
+       scc in_from_to_tuid_b2[] = FROM TO R_IN_TUID "\r";
+       fulltests( "from / to / tuid w/o lf", in_from_to_tuid_b2, 
out_from_to_tuid_b1, ADD_TUID );
+
+       mintests( "from / to w/o lf", in_from_to_b2, out_from_to_ph, REGULAR );
+       mintests( "from / tuid / to w/o lf", in_from_tuid_to_b2, 
out_from_tuid_to_ph, REGULAR );
+       scc in_from_subj_to_b2[] = FROM SUBJECT R_TO "\r";
+       mintests( "from / subject / to w/o lf", in_from_subj_to_b2, 
out_from_subj_to, REGULAR );
+       scc in_from_subj_tuid_to_b2[] = FROM SUBJECT IN_TUID R_TO "\r";
+       mintests( "from / subject / tuid / to w/o lf", in_from_subj_tuid_to_b2, 
out_from_subj_tuid_to, REGULAR );
+       scc in_from_subj_to_tuid_b2[] = FROM SUBJECT TO R_IN_TUID "\r";
+       mintests( "from / subject / to / tuid w/o lf", in_from_subj_to_tuid_b2, 
out_from_subj_to_tuid_b1, REGULAR );
+       scc in_from_tuid_subj_to_b2[] = FROM IN_TUID SUBJECT R_TO "\r";
+       mintests( "from / tuid / subject / to w/o lf", in_from_tuid_subj_to_b2, 
out_from_tuid_subj_to, REGULAR );
+       scc in_from_tuid_to_subj_b2[] = FROM IN_TUID TO R_SUBJECT "\r";
+       mintests( "from / tuid / to / subject w/o lf", in_from_tuid_to_subj_b2, 
out_from_tuid_to_subj_b1, REGULAR );
+
+
+       scc in_from_to_b3[] = FROM R_TO;
+       fulltests( "from / to w/o crlf", in_from_to_b3, in_from_to_b3, AS_IS );
+       fulltests( "from / to w/o crlf", in_from_to_b3, out_from_to_b1, 
ADD_TUID );
+       scc in_from_tuid_to_b3[] = FROM IN_TUID R_TO;
+       scc out_from_tuid_to_b3[] = FROM OUT_TUID R_TO;
+       fulltests( "from / tuid / to w/o crlf", in_from_tuid_to_b3, 
out_from_tuid_to_b3, ADD_TUID );
+       scc in_from_to_tuid_b3[] = FROM TO R_IN_TUID;
+       fulltests( "from / to / tuid w/o crlf", in_from_to_tuid_b3, 
out_from_to_tuid_b1, ADD_TUID );
+
+       mintests( "from / to w/o crlf", in_from_to_b3, out_from_to_ph, REGULAR 
);
+       mintests( "from / tuid / to w/o crlf", in_from_tuid_to_b3, 
out_from_tuid_to_ph, REGULAR );
+       scc in_from_subj_to_b3[] = FROM SUBJECT R_TO;
+       mintests( "from / subject / to w/o crlf", in_from_subj_to_b3, 
out_from_subj_to, REGULAR );
+       scc in_from_subj_tuid_to_b3[] = FROM SUBJECT IN_TUID R_TO;
+       mintests( "from / subject / tuid / to w/o crlf", 
in_from_subj_tuid_to_b3, out_from_subj_tuid_to, REGULAR );
+       scc in_from_subj_to_tuid_b3[] = FROM SUBJECT TO R_IN_TUID;
+       mintests( "from / subject / to / tuid w/o crlf", 
in_from_subj_to_tuid_b3, out_from_subj_to_tuid_b1, REGULAR );
+       scc in_from_tuid_subj_to_b3[] = FROM IN_TUID SUBJECT R_TO;
+       mintests( "from / tuid / subject / to w/o crlf", 
in_from_tuid_subj_to_b3, out_from_tuid_subj_to, REGULAR );
+       scc in_from_tuid_to_subj_b3[] = FROM IN_TUID TO R_SUBJECT;
+       mintests( "from / tuid / to / subject w/o crlf", 
in_from_tuid_to_subj_b3, out_from_tuid_to_subj_b1, REGULAR );
+
        return 0;
 }


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to