diff options
Diffstat (limited to 'test/mailbox1.rl')
-rw-r--r-- | test/mailbox1.rl | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/test/mailbox1.rl b/test/mailbox1.rl new file mode 100644 index 0000000..89e8775 --- /dev/null +++ b/test/mailbox1.rl @@ -0,0 +1,252 @@ +/* + * @LANG: c++ + * @CFLAGS: -I../aapl + * @ALLOW_GENFLAGS: -T0 -T1 -F0 -F1 -G0 -G1 -G2 -P + */ + +/* + * Parses unix mail boxes into headers and bodies. + */ + +#include "mailbox1.h" + +%%{ + machine MBox; + + # Buffer the header names. + action bufHeadName { fsm->headName.append(fc); } + + # Buffer the header content. + action bufHeadContent { fsm->headContent.append(fc); } + + # Terminate a header. If it is an interesting header then prints it. + action finBufHeadContent { + /* Terminate the buffers. */ + fsm->headName.append(0); + fsm->headContent.append(0); + + /* Print the header. Interesting headers. */ + printf("%s:%s\n", fsm->headName.data, fsm->headContent.data); + + /* Clear for the next time we use them. */ + fsm->headName.empty(); + fsm->headContent.empty(); + } + + action msgstart{ + printf("NEW MESSAGE\n"); + } + + # Prints a blank line after the end of the headers of each message. + action blankLine { + printf("\n"); + } + + # Helpers we will use in matching the date section of the from line. + day = /[A-Z][a-z][a-z]/; + month = /[A-Z][a-z][a-z]/; + year = /[0-9][0-9][0-9][0-9]/; + time = /[0-9][0-9]:[0-9][0-9]/ . ( /:[0-9][0-9]/ | '' ); + letterZone = /[A-Z][A-Z][A-Z]/; + numZone = /[+\-][0-9][0-9][0-9][0-9]/; + zone = letterZone | numZone; + dayNum = /[0-9 ][0-9]/; + + # These are the different formats of the date minus an obscure + # type that has a funny string 'remote from xxx' on the end. Taken + # from c-client in the imap-2000 distribution. + date = day . ' ' . month . ' ' . dayNum . ' ' . time . ' ' . + ( year | year . ' ' . zone | zone . ' ' . year ); + + # Note the priority assignment on the end of the from line. While we + # matching the body of a message we may enter into this machine. We will + # not leave the body of the previous message until this entire from line is + # matched. + fromLine = 'From ' . /[^\n]/* . ' ' . date . '\n' @(new_msg,1) @msgstart; + + # The types of characters that can be used as a header name. + hchar = print - [ :]; + + header = + # The name of the header. + hchar+ $bufHeadName . ':' + # The content of the header. Look out for continuations. + . ( (extend - '\n') $bufHeadContent | '\n'. [ \t] @bufHeadContent )* + # Buffer must end with a newline that does not continue. + . '\n' %finBufHeadContent; + + messageLine = ( extend - '\n' )* . '\n' @(new_msg, 0); + + # When we get to the last newline we are still matching messageLine + # so on the last newline it will think we are still in the message. + # We need this because we can't assume that every newline means + # the end of the current message, whereas at the same time we requre + # that there be a newline before the fromLine of the next message. + message = ( fromLine . header* . '\n' @blankLine . messageLine* . '\n' ); + + # Its important that the priority in the fromLine gets bumped up + # so that we are able to move to new messages. Otherwise we + # will always stay in the message body of the first message. + main := message*; +}%% + +%% write data; + +void MBox::init( ) +{ + MBox *fsm = this; + %% write init; +} + +void MBox::execute( char *data, int len ) +{ + MBox *fsm = this; + char *p = data; + char *pe = data + len; + %%{ + access fsm->; + write exec; + }%% +} + +int MBox::finish( ) +{ + if ( cs == MBox_error ) + return -1; + if ( cs >= MBox_first_final ) + return 1; + return 0; +} + +MBox mbox; + +void test( char *buf ) +{ + int len = strlen( buf ); + mbox.init(); + mbox.execute( buf, len ); + if ( mbox.finish() > 0 ) + printf("ACCEPT\n"); + else + printf("FAIL\n"); +} + + +int main() +{ + test( + "From email address goes here Wed Nov 28 13:30:05 2001 -0500\n" + "Header1: this is the header contents\n" + " there is more on the second line\n" + " and more on the third line.\n" + "Header2: slkdj\n" + "\n" + "This is the message data\n" + "\n" + "From email Wed Nov 28 13:30:05 2001 -0500\n" + "Header: \n" + "\n" + "mail message\n" + "\n" + ); + + test( + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "\n" + "There are no headers. \n" + "\n" + "From email Wed Nov 28 13:30:05 EST 2000\n" + "\n" + "There are no headers.\n" + "\n" + ); + + test( + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "Header:alsdj\n" + "\n" + "Header:\n" + "salkfj\n" + "\n" + "There are no headers. \n" + "\n" + ); + + test( + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "Header:alsdj\n" + "\n" + "Header:\n" + "salkfj\n" + "\n" + "There are no headers. \n" + "\n" + ">From user@host.dom Wed Nov 28 13:30:05 2001\n" + "\n" + ); + + test( + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "Header:alsdj\n" + "\n" + "Header:\n" + "salkfj\n" + "\n" + "There are no headers. \n" + "\n" + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "\n" + ); + + test( + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "Header:alsdj\n" + "\n" + "Header:\n" + "salkfj\n" + "\n" + "There are no headers. \n" + "\n" + "From user@host.dom Wed Nov 28 13:30:05 2001\n" + "\n" + "\n" + ); + + return 0; +} + +#ifdef _____OUTPUT_____ +NEW MESSAGE +Header1: this is the header contents there is more on the second line and more on the third line. +Header2: slkdj + +NEW MESSAGE +Header: + +ACCEPT +NEW MESSAGE + +NEW MESSAGE + +ACCEPT +NEW MESSAGE +Header:alsdj + +ACCEPT +NEW MESSAGE +Header:alsdj + +ACCEPT +NEW MESSAGE +Header:alsdj + +NEW MESSAGE + +FAIL +NEW MESSAGE +Header:alsdj + +NEW MESSAGE + +ACCEPT +#endif |