; rss.vnm ; test parsing an RSS feed with Protocol analyser ; ; Illustates fetching a simple http URL and use of the ; protocol analyser V2. ; Needs June 2007 or later version of Venom. ; site-specific definitions. You WILL have to change these! DEFINE my_ip "172.16.1.150" DEFINE my_nameserver "172.16.1.146" DEFINE my_gateway "172.16.1.199" TO init MAKE eth Protocol("eth", 1, $d) eth.Address('i') := my_ip eth.Address('n') := my_nameserver eth.Address('d') := my_gateway MAKE tcp Protocol("tcp") MAKE pa ProtAnalyser(tcp, 0) MAKE s String(100) END TO main ; note how the URL "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml" ; is broken down. ; HTTP uses port 80, which we use when opening the connection. ; "newsrss.bbc.co.uk" is is the hostname, which we use when opening the connection and ; again in a "host:" header after sending the GET request ; "/rss/newsonline_uk_edition/front_page/rss.xml" is the path we specify in the GET request ; IF tcp.Open("newsrss.bbc.co.uk", 80) [ PRINT "http connection opened",CR PRINT TO tcp, "GET /rss/newsonline_uk_edition/front_page/rss.xml HTTP/1.1",CR, "host: newsrss.bbc.co.uk",CR, CR PRINT "=headers=",CR WHILE tcp.Get(s) > 0 ; read headers until we get an empty line = end of headers PRINT s, CR PRINT "==",CR pa.Reset ; every title we want to display is a element inside an <item> element ; there are a couple of <title> elements at the beginning of the file that do not apply WHILE pa.Find("<item>", 0) [ IF pa.Find("<title>", 0) [ pa.Get(s, "<") convert_entity(s) PRINT "Title: ", s, CR ] ] tcp.Close tcp.Reset ] ELSE PRINT "tcp open failed, status ", tcp.Status:1, CR tcp.Reset END ; table for converting certain HTML codes back into characters */ ; the first entry in each pair is a string preceded by '&' and ; followed by ';' in the XML/HTML ; e.g. "&" represents '&' Array entities("", 8) "amp" "&" "apos" "'" "pound" "£" "quot", "\"" END ; convert XML/HTML character entity codes in a string TO convert_entity(s) AUTODESTRUCT LOCAL s1 := NEW String(100) ; holder for converted string LOCAL pa1 := NEW ProtAnalyser(s, 1) LOCAL c LOCAL n s.Reset s1.Empty WHILE s.Queue [ c := pa1.Get IF c = '&' [ ; this uses protanalyser "array of names" feature n := pa1.Get(entities, ";") IF n <> -1 PRINT TO s1, entities.(n + 1) ] ELSE s1.Put(c) ] s.Empty s.Put(s1) ; copy converted string back to original END