backup
[platform/upstream/libsolv.git] / tools / repo_updateinfoxml.c
1
2 /*
3  * Copyright (c) 2007, Novell Inc.
4  *
5  * This program is licensed under the BSD license, read LICENSE.BSD
6  * for further information
7  */
8
9 #include <sys/types.h>
10 #include <limits.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <expat.h>
16
17 #include "pool.h"
18 #include "repo.h"
19 #include "repo_patchxml.h"
20 #include "repo_rpmmd.h"
21
22 //#define TESTMM
23
24 /*
25 <updates>
26   <update from="rel-eng@fedoraproject.org" status="stable" type="security" version="1.4">
27     <id>FEDORA-2007-4594</id>
28     <title>imlib-1.9.15-6.fc8</title>
29     <release>Fedora 8</release>
30     <issued date="2007-12-28 16:42:30"/>
31     <references>
32       <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=426091" id="426091" title="CVE-2007-3568 imlib: infinite loop DoS using crafted BMP image" type="bugzilla"/>
33     </references>
34     <description>This update includes a fix for a denial-of-service issue (CVE-2007-3568) whereby an attacker who could get an imlib-using user to view a  specially-crafted BMP image could cause the user's CPU to go into an infinite loop.</description>
35     <pkglist>
36       <collection short="F8">
37         <name>Fedora 8</name>
38         <package arch="ppc64" name="imlib-debuginfo" release="6.fc8" src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm" version="1.9.15">
39           <filename>imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm</filename>
40         </package>
41 */
42
43 enum state {
44   STATE_START,
45   STATE_UPDATES,
46   STATE_UPDATE,
47   STATE_ID,
48   STATE_TITLE,
49   STATE_RELEASE,
50   STATE_ISSUED,
51   STATE_REFERENCES,
52   STATE_REFERENCE,
53   STATE_DESCRIPTION,
54   STATE_PKGLIST,
55   STATE_COLLECTION,
56   STATE_NAME,
57   STATE_PACKAGE,
58   STATE_FILENAME,
59   NUMSTATES
60 };
61
62 struct stateswitch {
63   enum state from;
64   char *ename;
65   enum state to;
66   int docontent;
67 };
68
69 static struct stateswitch stateswitches[] = {
70   { STATE_START,       "updates",         STATE_UPDATES, 0 },
71   { STATE_START,       "update",          STATE_UPDATE, 0 },
72   { STATE_UPDATES,     "update",          STATE_UPDATE, 0},
73   { STATE_UPDATE,      "id",              STATE_ID, 1},
74   { STATE_UPDATE,      "title",           STATE_TITLE, 1},
75   { STATE_UPDATE,      "release",         STATE_RELEASE, 1},
76   { STATE_UPDATE,      "issued",          STATE_ISSUED, 1},
77   { STATE_UPDATE,      "references",      STATE_REFERENCES, 0},
78   { STATE_UPDATE,      "description",     STATE_DESCRIPTION, 0},
79   { STATE_REFERENCES,  "reference",       STATE_REFERENCE, 0},
80   { STATE_UPDATE,      "pkglist",         STATE_PKGLIST, 0},
81   { STATE_PKGLIST,     "collection",      STATE_COLLECTION, 0},
82   { STATE_COLLECTION,  "name",            STATE_NAME, 1},
83   { STATE_COLLECTION,  "package",         STATE_PACKAGE, 0},
84   { STATE_COLLECTION,  "filename",        STATE_FILENAME, 1},
85   { NUMSTATES}
86 };
87
88 struct parsedata {
89   int depth;
90   enum state state;
91   int statedepth;
92   char *content;
93   int lcontent;
94   int acontent;
95   int docontent;
96   Pool *pool;
97   Repo *repo;
98   Repodata *data;
99   unsigned int datanum;
100   Solvable *solvable;
101   char *kind;
102   unsigned int timestamp;
103   
104   struct stateswitch *swtab[NUMSTATES];
105   enum state sbtab[NUMSTATES];
106   char *tempstr;
107   int ltemp;
108   int atemp;
109 };
110
111 /*
112  * find attribute
113  */
114
115 /*
116 static const char *
117 find_attr(const char *txt, const char **atts)
118 {
119   for (; *atts; atts += 2)
120     {
121       if (!strcmp(*atts, txt))
122         return atts[1];
123     }
124   return 0;
125 }
126 */
127
128 static void XMLCALL
129 startElement(void *userData, const char *name, const char **atts)
130 {
131   struct parsedata *pd = userData;
132   /*Pool *pool = pd->pool;*/
133   /*Solvable *s = pd->solvable;*/
134   struct stateswitch *sw;
135   /*const char *str; */
136
137   if (pd->depth != pd->statedepth)
138     {
139       pd->depth++;
140       return;
141     }
142
143   pd->depth++;
144   for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)  /* find name in statetable */
145     if (!strcmp(sw->ename, name))
146       break;
147   
148   if (sw->from != pd->state)
149     {
150 #if 0
151       fprintf(stderr, "into unknown: %s\n", name);
152 #endif
153       return;
154     }
155   pd->state = sw->to;
156   pd->docontent = sw->docontent;
157   pd->statedepth = pd->depth;
158   pd->lcontent = 0;
159   *pd->content = 0;
160
161   switch(pd->state)
162     {
163      default:
164       break;
165     }
166 }
167
168 static void XMLCALL
169 endElement(void *userData, const char *name)
170 {
171   struct parsedata *pd = userData;
172   Pool *pool = pd->pool;
173   Solvable *s = pd->solvable;
174
175   if (pd->depth != pd->statedepth)
176     {
177       pd->depth--;
178       // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
179       return;
180     }
181
182   pd->depth--;
183   pd->statedepth--;
184   switch (pd->state)
185     {
186         case STATE_ID:
187             s->name = str2id(pool, pd->content, 1);
188             break;
189         case STATE_TITLE:
190             repodata_set_str(pd->data, pd->datanum, SOLVABLE_SUMMARY, pd->content);
191             break;
192         case STATE_RELEASE:
193         case STATE_ISSUED:
194             s->name = str2id(pool, pd->content, 1);
195         case STATE_REFERENCE:
196         case STATE_DESCRIPTION:
197             repodata_set_str(pd->data, pd->datanum, SOLVABLE_DESCRIPTION, pd->content);
198             break;
199         case STATE_NAME:
200       
201
202         default:
203             break;
204     }
205
206
207
208 }
209
210 static void XMLCALL
211 characterData(void *userData, const XML_Char *s, int len)
212 {
213   struct parsedata *pd = userData;
214   int l;
215   char *c;
216
217   if (!pd->docontent)
218     return;
219   l = pd->lcontent + len + 1;
220   if (l > pd->acontent)
221     {
222       pd->content = realloc(pd->content, l + 256);
223       pd->acontent = l + 256;
224     }
225   c = pd->content + pd->lcontent;
226   pd->lcontent += len;
227   while (len-- > 0)
228     *c++ = *s++;
229   *c = 0;
230 }
231
232
233 #define BUFF_SIZE 8192
234
235 void
236 repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags)
237 {
238   Pool *pool = repo->pool;
239   struct parsedata pd;
240   char buf[BUFF_SIZE];
241   int i, l;
242   struct stateswitch *sw;
243
244   memset(&pd, 0, sizeof(pd));
245   for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
246     {
247       if (!pd.swtab[sw->from])
248         pd.swtab[sw->from] = sw;
249       pd.sbtab[sw->to] = sw->from;
250     }
251   pd.pool = pool;
252   pd.repo = repo;
253   pd.data = repo_add_repodata(pd.repo, 0);
254
255   pd.content = malloc(256);
256   pd.acontent = 256;
257   pd.lcontent = 0;
258   pd.tempstr = malloc(256);
259   pd.atemp = 256;
260   pd.ltemp = 0;
261   XML_Parser parser = XML_ParserCreate(NULL);
262   XML_SetUserData(parser, &pd);
263   XML_SetElementHandler(parser, startElement, endElement);
264   XML_SetCharacterDataHandler(parser, characterData);
265   for (;;)
266     {
267       l = fread(buf, 1, sizeof(buf), fp);
268       if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
269         {
270           fprintf(stderr, "repo_updateinfoxml: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
271           exit(1);
272         }
273       if (l == 0)
274         break;
275     }
276   XML_ParserFree(parser);
277
278   if (pd.data)
279     repodata_internalize(pd.data);
280
281   free(pd.content);
282 }