Bugfix: Segmentation fault when reading an rpm package list
[gnucomo.git] / src / gcm_input / rpm_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      : rpm_filter.cpp
10 **      SYSTEM NAME    : 
11 **      VERSION NUMBER : $Revision: 1.2 $
12 **
13 **  DESCRIPTION      :  Transform a list of packages into a Gnucomo XML document
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 27, 2003
23 **      LAST UPDATE     : Nov 12, 2007
24 **      MODIFICATIONS   : 
25 **************************************************************************/
26
27 /*****************************
28    $Log: rpm_filter.cpp,v $
29    Revision 1.2  2007-11-14 16:19:25  arjen
30    Bugfix: Segmentation fault when reading an rpm package list
31    with empty lines.
32
33    Revision 1.1  2003/12/04 10:38:09  arjen
34    Major redesign. All input is handled through XML. Raw input data is first
35    transformed into an XML document for further processing.
36    A collection of polymorphic classes handle the transformation of various
37    input formats into XML.
38    Classifying input data is done with a finite improbability calculation.
39
40 *****************************/
41
42 /* static const char *RCSID = "$Id: rpm_filter.cpp,v 1.2 2007-11-14 16:19:25 arjen Exp $"; */
43
44 #include <ctype.h>
45
46 #include "rpm_filter.h"
47
48 /*=========================================================================
49 **  NAME           : constructXML
50 **  SYNOPSIS       : int constructXML(message_buffer &in, strstream &xml)
51 **  PARAMETERS     : 
52 **  RETURN VALUE   : Create an XML document from a list of RPMs
53 **
54 **  DESCRIPTION    : 
55 **                   Scan a list of packages and versions from "rpm -a".
56 **                   A similar listing can be created on IRIX 6.5 by using the
57 **                   command "showprods -3 -n|awk '{printf "%s-%s\n",$2,$3}'|grep -v '^[-=]' \
58 **                             |grep -v Version-Description".
59 **                 
60 **                   We have to separate the package name and the version.
61 **                   The separation is marked by a '-', followed by a digit.
62 **                   However, there may be other sequences of '-'digit in the package name,
63 **                   do we have to scan ahead until there is at most one such sequence
64 **                   left in the version string. The '-'digit seqeunce inside the
65 **                   version usually separates the version and the release number.
66 **
67 **  VARS USED      :
68 **  VARS CHANGED   :
69 **  FUNCTIONS USED :
70 **  SEE ALSO       :
71 **  LAST MODIFIED  : Nov 12, 2007
72 **=========================================================================
73 */
74
75 static const regex re_rpm("[[:alnum:]+-]+-[0-9][[:alnum:].-]");
76
77 void rpm_filter::construct_XML(message_buffer &in, std::strstream &xml)
78 {
79    String line;
80
81    scan_email_header(in);
82    construct_header(xml);
83
84    xml << "  <gcmt:data>\n";
85    xml << "    <gcmt:parameters class='package'>\n";
86
87    while (in >> line)
88    { 
89       int  version_start, next_version_start;
90       int  i;
91
92       if (line == re_rpm)
93       {
94          //   Separate the package name from the version number
95  
96          i = line.index('-');
97
98          version_start = i;
99          next_version_start = i;
100
101          while (i < ~line - 1)
102          {
103             while (i < ~line - 1 && !(line[i] == '-' && isdigit(line[i + 1])))
104             {
105                i++;
106             }
107             if (i < ~line - 1)
108             {
109                version_start = next_version_start;
110                next_version_start = i;
111             }
112             i++;
113          }
114       
115          if (!isdigit(line[version_start + 1]))
116          {
117             version_start = next_version_start;
118          }
119          String package(line(0,version_start));
120          String version(line(version_start + 1, ~line));
121
122          //   Create the XML element.
123
124          xml << "    <gcmt:parameter name='" << package << "'>\n";
125          xml << "      <gcmt:property name='version'>" << version << "</gcmt:property>\n";
126          xml << "    </gcmt:parameter>\n";
127       }
128    }
129    xml << "    </gcmt:parameters>\n";
130    xml << "  </gcmt:data>\n";
131    xml << "</gcmt:message>\n";
132 }
133
134 bool rpm_cooker::check_pattern(String logline)
135 {
136    return logline == re_rpm;
137 }
138
139 bool rpm_cooker::cook_this(String logline, UTC arrival)
140 {
141    return true;
142 }