¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

Re: Help with parsing


bfschroe
 

Thanks guys. I think I understand. I do need to keep the connection
open while receiving the data since there are a few required
responses to feed the data stream (handshakes, hellos, validate
sender, etc then tell the sender ready for the message and
acknowledge message receipt and close connection).

There is a delimiter (CRLF.CRLF) so I will try to gather the string
data once I get to the meat of the message after the initial
handshaking.

Here (below) is what I have now (not that I expect anyone to go
through this).
I already have a semaphore to tell me when we switch from handshaking
to actual message data so I guess I just need to add the gather and
then parse after breaking the connection.

Thanks
Bruce



Change Mail_Rx$
{
integer pos,first, last, found,startpos, endpos, cols, n,newstart,
subflag, boundend;
string temp$[1000];
String starttag$[10], endtag$[5],result$[60], boundary$[100];
integer end, start;


if (Message_Mode=0)//Only check during Header Changes to 1 after DATA
header
{
//Incoming Message
pos=find ("HELO",Mail_Rx$,1);
if (pos > 0 ) {
Mail_Tx$="250 Hello\n";
clearbuffer (Mail_Rx$);

}
//End Incoming

//Handhshake
pos=find ("EHLO",Mail_Rx$,1);
if (pos > 0)
{Mail_Tx$="250 EHLO\n";
clearbuffer (Mail_Rx$);}

//End Handshake

//Parse "TO"

pos=find ("RCPT TO:",mail_Rx$); if (pos > 0 )
{
first= find ("RCPT TO:<",mail_Rx$);
last= find ("@",mail_Rx$,first);
localto$= MID(mail_Rx$,(first+9),(last-first-9));
IF (localTo$="DISPLAY" || localTo$="CONSOLE" ||
localTo$= "LOGIC" || localTo$="display" || localTo$="console" ||
localTo$= "logic") Mail_Tx$="250 RCPT OK&#92;n";
else {
Mail_Tx$="550 Invalid User &#92;n";
fail=1;}
clearbuffer (Mail_Rx$);
}
//End "TO"

//Parse From and Validate User

pos=find ("MAIL FROM:",Mail_Rx$,1);
if (pos > 0)
{
first= find ("MAIL FROM:<",Mail_Rx$,pos);
last= find (">",Mail_Rx$,first);
localFrom$= MID(Mail_Rx$,(first+10),(last-first-11));
newlocalfrom$="";
Mail_Tx$="250 From Received. Validation Pending.&#92;n";
clearbuffer (Mail_Rx$);
}

//"DATA" preceeds message. Respond to begin transmission of
subject/message
pos=find ("DATA",Mail_Rx$,1);
if (pos > 0 )
{Message_Mode=1;
clearbuffer (Mail_Rx$);
Mail_Tx$="354 &#92;n";
}
//End Data



}

//end if for Header Section

If (Message_Mode=1)//after DATA header received
{
//Update From.
pos=find ("From: ",Mail_Rx$,1);
endpos= find ("&#92;x0D&#92;x0A",Mail_Rx$,pos);
if ((pos > 0) && (endpos >pos) && (Message_Mode=1) &&
(newlocalfrom$=""))
{ newlocalfrom$=mid (mail_rx$,pos+6, endpos-pos-6);
first= find ("<",newlocalfrom$,1);
last= find (">",newlocalfrom$,1);
if ((first>0)&&(last>first))newlocalFrom$= MID(newlocalfrom$,
(first+1),(last-first-1));
localFrom$=newlocalfrom$;


//Validate User

found=0;
n=0;
Do
{n=n+1;
IF (valid_sender$[n]=localfrom$)found=1;
}
until (valid_sender$[n]="" || n > getnumarraycols(valid_sender$)
||found=1);

If (found=0)

{ Mail_Tx$="550 Unauthorized Sender <"+localfrom$+"> &#92;n 221 BYE &#92;n";
fail=1;
clearbuffer (Mail_Rx$);}






}
//End From

//Get Date/Time
StartTag$ = "Date: " ;
Start = FIND(StartTag$,Mail_Rx$,1);
EndTag$ = "&#92;x0D" ;
End = FIND(EndTag$,Mail_Rx$,Start);
IF ((Start > 0) && (End > Start))
{
Result$ = MID(Mail_Rx$,(Start+6),(end-start-6));
localdate$= Result$; }
//Date is from the mail server. May not be desired time zone
//end date




//Substitue From with the Reply-to for reply
pos=find ("Reply-To: ",Mail_Rx$,1);
endpos= find ("&#92;x0D&#92;x0A",Mail_Rx$,pos);
if ((pos > 0) && (endpos >pos) && (Message_Mode=1))
{ localfrom$=mid (mail_rx$,pos+10, endpos-pos-10);
first= find ("<",localfrom$,1);
last= find (">",localfrom$,1);
if ((first>0)&&(last>first))localFrom$= MID(localfrom$,(first+1),
(last-first-1));

//End Reply to
}


//Parse Subject
StartTag$ = "Subject: " ;
Start = FIND(StartTag$,Mail_Rx$,1);
EndTag$ = "&#92;x0D&#92;x0A" ;
End = FIND(EndTag$,Mail_Rx$,Start);
IF ((Start > 0) && (End > Start) )
{
Result$ = MID(Mail_Rx$,(Start+9),(end-start-9));
localsubject$= Result$;
print("%s", localsubject$);
}
//end subject


//Get message. Message is between 2 CRLF and a CRLF.CRLF
newstart= find ("Content-Type: text/plain",Mail_Rx$);
start= max (newstart, 1);
boundary$="&#92;x0D&#92;x0A&#92;x0D&#92;x0A";
startpos=find("&#92;x0D&#92;x0A&#92;x0D&#92;x0A",Mail_Rx$,start);
endpos=find("&#92;x0D&#92;x0A&#92;x2E&#92;x0D&#92;x0A",Mail_Rx$,start);
end=find(boundary$,Mail_Rx$,startpos+1);
if (end>0) endpos=end;

If ((startpos>0) && (endpos>startpos)&&localmessage$="")
{
subflag=len (boundary$);
localmessage$=mid(Mail_Rx$,startpos+subflag,endpos-startpos-
subflag);
pos=find ("=0A", localMessage$);
if (pos>0) localmessage$= mid (localmessage$,1,pos-1);
if ((find ("&#92;x0D&#92;x0A",localMessage$,1)<=0) && ((localto$="console")||
(localto$="logic"))) localmessage$=localmessage$+"&#92;x0D&#92;x0A";//CRLF to
message

if ((fail=0))
{
Mail_Tx$="250 Message Received&#92;n";
To$=localto$;
From$=localfrom$;
//subject$=localsubject$;
subject$=localsubject$;
message$=localmessage$;
Date$=localdate$;
pulse (pulsetime,Message_Complete);
clearbuffer (Mail_Rx$);
}
}

//end get message

}//end Mode=1 section




}

--- In Crestron@..., "Chip Moody" <cfm@...> wrote:


Disclaimer - this is an example for when you don't have a
convenient
delimiter to use in a GATHER statement. :) Did I mention it's
been a
while since I've played with SMTP?

- Chip


--- In Crestron@..., "Chip Moody" <cfm@> wrote:


As long as your buffer is large enough to hold an entire
response
from the server, you shouldn't have issues.

Rather than doing change events on string/buffer inputs, I've
taken
recently to starting the parsing routine after the server has
disconnected, with the mindset that there's no discernible
difference
in time between when data is flowing in from the server vs. when
the
server is DONE sending data and disconnects. (I believe I did
this
with the Yahoo Answers/Yahoo News modules if you wanted something
to
pick apart)

I haven't screwed with SMTP in a long time, so I don't remember
if
you need to maintain the connection after you get data from the
server
or not. If that's the case, are you looking in the buffer on each
change event for something that indicates all the data has come
in?
I.E., don't parse the buffer EVERY time the change triggers - only
parse when the change triggers AND you can confirm that
everything you
want is in there. Also make sure that you're using some kind of
flag/semaphore on the change event that prevents it from
triggering
your test/parse code when it may already be running...

CHANGE rx$
{
IF (not_parsing)
{
not_parsing = OFF;
//
// check your buffer contents here
//
not_parsing = ON;
}
}

Obviously you want to clear the buffer and set not_parsing to
ON at
some point BEFORE you expect data to be coming in.

- Chip


--- In Crestron@..., "bfschroe" <schroeder@> wrote:

I am having some inconsistent trouble parsing a long
serial "string".

Basically this is the SMTP parser I have been working on. It
seems to
work mostly but every so often it misses something--e.g.
doesn't find
the subject in the message.

I am running the TCP client feed from Simpl to a Change
statement in
S+. The Rx$ connects to a buffer type variable in S+ and then I
do
some basic parsing on that string.

Is it possible that the buffer is changing faster than the
parser can
find the data? If so, what is the method to prevent this? Do I
need to
create a local static copy of the text to parse so it isn't
changing
between the program lines that "find" the text and extract it?
Any
links to a parsing module that can handle a large string (?2000
character serial)

thanks

Bruce

Join [email protected] to automatically receive all group messages.