Major redesign. All input is handled through XML. Raw input data is first
[gnucomo.git] / src / gcm_input / message_filter.cpp
1
2 /**************************************************************************
3 **  (c) Copyright 2003, Andromeda Technology & Automation
4 ** This is free software; you can redistribute it and/or modify it under the
5 ** terms of the GNU General Public License, see the file COPYING.
6 ***************************************************************************
7 ** MODULE INFORMATION *
8 ***********************
9 **      FILE NAME      : message_filter.cpp
10 **      SYSTEM NAME    : 
11 **      VERSION NUMBER : $Revision: 1.1 $
12 **
13 **  DESCRIPTION      :  
14 **
15 **  EXPORTED OBJECTS : 
16 **  LOCAL    OBJECTS : 
17 **  MODULES  USED    :
18 ***************************************************************************
19 **  ADMINISTRATIVE INFORMATION *
20 ********************************
21 **      ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
22 **      CREATION DATE   : Nov 26, 2003
23 **      LAST UPDATE     : Nov 26, 2003
24 **      MODIFICATIONS   : 
25 **************************************************************************/
26
27 /*****************************
28    $Log: message_filter.cpp,v $
29    Revision 1.1  2003-12-04 10:38:09  arjen
30    Major redesign. All input is handled through XML. Raw input data is first
31    transformed into an XML document for further processing.
32    A collection of polymorphic classes handle the transformation of various
33    input formats into XML.
34    Classifying input data is done with a finite improbability calculation.
35
36 *****************************/
37
38 /* static const char *RCSID = "$Id: message_filter.cpp,v 1.1 2003-12-04 10:38:09 arjen Exp $"; */
39
40 #include "message_filter.h"
41
42 extern std::ostream *Log;
43
44 /*=========================================================================
45 **  NAME           : constructXML
46 **  SYNOPSIS       : int constructXML(message_buffer &in, std::strstream &xml)
47 **  PARAMETERS     : 
48 **  RETURN VALUE   : 
49 **
50 **  DESCRIPTION    : Copy the input stream into the internal XML buffer
51 **                   The input is already in XML format, so no real transformation
52 **                   is needed.
53 **
54 **  VARS USED      :
55 **  VARS CHANGED   :
56 **  FUNCTIONS USED :
57 **  SEE ALSO       :
58 **  LAST MODIFIED  : Nov 26, 2003
59 **=========================================================================
60 */
61
62 void message_filter::construct_XML(message_buffer &in, std::strstream &xml)
63 {
64    String line;
65
66    while (in >> line)
67    {
68       xml << line << "\n";
69    }
70 }
71
72 static const String mail_date_re("[[:alpha:]]{3}, [ 123]?[0-9] [[:alpha:]]{3} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} [+-][0-9]{4}");
73 static const String unix_date_re("[[:alpha:]]{3} [[:alpha:]]{3} [ 123][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4}");
74 static const regex re_uxmail_from("^From [^ \t]+[ ]+" + unix_date_re);
75 static const regex re_mail_From("^From:[[:blank:]]+");
76 static const regex re_mail_Date("^Date:[[:blank:]]+" + mail_date_re);
77 static const regex re_mail_MsId("^Message-Id:[[:blank:]]+");
78 static const regex re_email_address("[[:alnum:]_.-]+@[[:alnum:]_.-]+");
79 static const regex re_email_user("[[:alnum:]_.-]+@");
80
81 /*=========================================================================
82 **  NAME           : scan_email_header
83 **  SYNOPSIS       : void scan_email_header(message_buffer &in)
84 **  PARAMETERS     : 
85 **  RETURN VALUE   : 
86 **
87 **  DESCRIPTION    : 
88 **
89 **  VARS USED      :
90 **  VARS CHANGED   :
91 **  FUNCTIONS USED :
92 **  SEE ALSO       :
93 **  LAST MODIFIED  : Nov 26, 2003
94 **=========================================================================
95 */
96
97 void message_filter::scan_email_header(message_buffer &in)
98 {
99    String line;
100
101    /*  First, check if the message has a mail header. */
102
103    if (in >> line && line == re_uxmail_from)
104    {
105       String    from_address;
106
107       /*  Scan ahead for the hostname and date of arrival.  */
108
109       while (in >> line && line != "")
110       {
111
112          if (line == re_mail_From)
113          {
114             from_address = line(re_email_address);
115             from_address(re_email_user) = "";            //  Remove the user part;
116             if (from_address != "" && ~hn < ~from_address)
117             {
118                *Log << "Detected hostname " << from_address << "\n";
119                hn = from_address;
120             }
121          }
122          if (line == re_mail_MsId)
123          {
124             from_address = line(re_email_address);
125             from_address(re_email_user) = "";            //  Remove the user part;
126             if (from_address != "" && ~hn < ~from_address)
127             {
128                *Log << "Detected hostname " << from_address << "\n";
129                hn = from_address;
130             }
131          }
132          if (line == re_mail_Date)
133          {
134             ts = UTC(line(regex(mail_date_re)));
135          }
136       }
137    }
138    else
139    {
140       //  Push the first line back, we need to read it again.
141       --in;
142
143    }
144
145 }
146
147 /*=========================================================================
148 **  NAME           : construct_header
149 **  SYNOPSIS       : void construct_header(std::strstream &xml)
150 **  PARAMETERS     : 
151 **  RETURN VALUE   : 
152 **
153 **  DESCRIPTION    : Create the header for a Gnucomo XML document.
154 **
155 **  VARS USED      :
156 **  VARS CHANGED   :
157 **  FUNCTIONS USED :
158 **  SEE ALSO       :
159 **  LAST MODIFIED  : Nov 26, 2003
160 **=========================================================================
161 */
162
163 void message_filter::construct_header(std::strstream &xml)
164 {
165    //xml << "<?xml version='1.0' encoding='utf-8'?>\n";
166    xml << "<?xml version='1.0' encoding='ISO-8859-1'?>\n";
167    xml << "<gcmt:message xmlns:gcmt='http://gnucomo.org/transport/'>\n";
168    xml << "  <gcmt:header>\n";
169    xml << "    <gcmt:messagetype>" << mt << "</gcmt:messagetype>\n";
170    xml << "    <gcmt:hostname>" << hn << "</gcmt:hostname>\n";
171    xml << "    <gcmt:service>" << srv << "</gcmt:service>\n";
172    xml << "    <gcmt:time>" << ts << "</gcmt:time>\n";
173    xml << "  </gcmt:header>\n";
174 }