Edition replaced by Edition of libzypp
[platform/upstream/libzypp.git] / zypp / solver / detail / XmlParser.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* XmlParser.cc  wrapper for XML I/O
3  *
4  * Copyright (C) 2000-2002 Ximian, Inc.
5  * Copyright (C) 2005 SUSE Linux Products GmbH
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19  * 02111-1307, USA.
20  */
21
22 #include <config.h>
23 #include <ctype.h>
24 #include <assert.h>
25 #include <zypp/solver/detail/XmlParser.h>
26 #include <zypp/solver/detail/Dependency.h>
27 #include <zypp/solver/detail/OrDependency.h>
28 #include <zypp/solver/detail/PackageUpdate.h>
29 #include <zypp/solver/detail/utils.h>
30
31 #include <zypp/solver/detail/debug.h>
32 #include <zypp/ResObject.h>
33
34 /////////////////////////////////////////////////////////////////////////
35 namespace zypp 
36 { ///////////////////////////////////////////////////////////////////////
37   ///////////////////////////////////////////////////////////////////////
38   namespace solver
39   { /////////////////////////////////////////////////////////////////////
40     /////////////////////////////////////////////////////////////////////
41     namespace detail
42     { ///////////////////////////////////////////////////////////////////
43               
44       using namespace std;
45       
46       //---------------------------------------------------------------------------
47       
48       static DependencyPtr
49       parse_dep_attrs(bool *is_obsolete, const xmlChar **attrs)
50       {
51           int i;
52           bool op_present = false;
53           /* Temporary variables dependent upon the presense of an 'op' attribute */
54           const char *name = NULL;
55           int epoch = Edition::noepoch;
56           string version;
57           string release;
58           string arch = "";
59           Relation relation = Relation::Any;
60       
61           *is_obsolete = false;
62       
63           for (i = 0; attrs[i]; i++) {
64         const char *attr = (const char *)attrs[i++];
65         const char *value = (const char *)attrs[i];
66       
67         if (!strcasecmp(attr, "name"))              name = value;
68         else if (!strcasecmp(attr, "op")) {         op_present = true; relation = Relation::parse(value); }
69         else if (!strcasecmp(attr, "epoch"))        epoch = atoi (value);
70         else if (!strcasecmp(attr, "version"))      version = value;
71         else if (!strcasecmp(attr, "release"))      release = value;
72         else if (!strcasecmp(attr, "arch"))         arch = value;
73         else if (!strcasecmp (attr, "obsoletes"))   *is_obsolete = true;
74         else {
75             if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Unknown attribute: %s = %s", attr, value);
76         }
77       
78           }
79       
80           /* FIXME: should get Channel from XML */
81           /* FIXME: should get Kind from XML */
82           if ( std::strlen(arch.c_str()) > 0)
83           {
84               return new Dependency (name, relation, ResTraits<zypp::Package>::kind, new Channel(CHANNEL_TYPE_ANY), epoch, version, release, zypp::Arch(arch));
85           }
86           else
87           {
88               return new Dependency (name, relation, ResTraits<zypp::Package>::kind, new Channel(CHANNEL_TYPE_ANY), epoch, version, release, zypp::Arch_noarch);
89           }              
90       }
91       
92       
93       //---------------------------------------------------------------------------
94       // SAX callbacks
95       
96       static void
97       sax_start_document(void *ptr)
98       {
99           XmlParser *ctx = (XmlParser *)ptr;
100           if (ctx->processing()) return;
101       
102       //    if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Start document");
103       
104           ctx->setProcessing (true);
105       }
106       
107       
108       static void
109       sax_end_document(void *ptr)
110       {
111           XmlParser *ctx = (XmlParser *)ptr;
112           if (!ctx->processing()) return;
113       
114       //    if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* End document");
115       
116           ctx->setProcessing (false);
117       }
118       
119       
120       static void
121       sax_start_element(void *ptr, const xmlChar *name, const xmlChar **attrs)
122       {
123           XmlParser *ctx = (XmlParser *)ptr;
124       
125           ctx->releaseBuffer();
126       
127       #if 0
128       //    if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Start element (%s)", (const char *)name);
129       
130           if (attrs) {
131         for (int i = 0; attrs[i]; i += 2) {
132             if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "   - Attribute (%s=%s)", (const char *)attrs[i], (const char *)attrs[i+1]);
133         }
134           }
135       #endif
136           if (!strcmp((const char *)name, "channel") || !strcmp((const char *)name, "subchannel")) {
137         /* Unneeded container tags.  Ignore */
138         return;
139           }
140       
141           return ctx->startElement ((const char *)name, attrs);
142       
143       }
144       
145       
146       static void
147       sax_end_element(void *ptr, const xmlChar *name)
148       {
149           XmlParser *ctx = (XmlParser *)ptr;
150       
151       //    if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* End element (%s)", (const char *)name);
152           
153           if (!strcmp((const char *)name, "channel") || !strcmp((const char *)name, "subchannel")) {
154         /* Unneeded container tags.  Ignore */
155         name = NULL;
156           }
157       
158           return ctx->endElement ((const char *)name);
159       }
160       
161       
162       static void
163       sax_characters(void *ptr, const xmlChar *ch, int len)
164       {
165           XmlParser *ctx = (XmlParser *)ptr;
166       
167           ctx->toBuffer ((const char *)ch, len);
168           return;
169       }
170       
171       
172       static void
173       sax_warning(void *ptr, const char *msg, ...)
174       {
175           va_list args;
176           char tmp[2048];
177       
178           va_start(args, msg);
179       
180           if (vsnprintf(tmp, 2048, msg, args) >= 2048) fprintf (stderr, "vsnprintf overflow\n");
181           rc_debug (RC_DEBUG_LEVEL_WARNING, "* SAX Warning: %s", tmp);
182       
183           va_end(args);
184       }
185       
186       
187       static void
188       sax_error(void *ptr, const char *msg, ...)
189       {
190           va_list args;
191           char tmp[2048];
192       
193           va_start(args, msg);
194       
195           if (vsnprintf(tmp, 2048, msg, args) >= 2048) fprintf (stderr, "vsnprintf overflow\n");
196           rc_debug (RC_DEBUG_LEVEL_ERROR, "* SAX Error: %s", tmp);
197       
198           va_end(args);
199       }
200       
201       
202       static xmlSAXHandler sax_handler = {
203           NULL,         /* internalSubset */
204           NULL,         /* isStandalone */
205           NULL,         /* hasInternalSubset */
206           NULL,         /* hasExternalSubset */
207           NULL,         /* resolveEntity */
208           NULL,         /* getEntity */
209           NULL,         /* entityDecl */
210           NULL,         /* notationDecl */
211           NULL,         /* attributeDecl */
212           NULL,         /* elementDecl */
213           NULL,         /* unparsedEntityDecl */
214           NULL,         /* setDocumentLocator */
215           sax_start_document,   /* startDocument */
216           sax_end_document,     /* endDocument */
217           sax_start_element,    /* startElement */
218           sax_end_element,      /* endElement */
219           NULL,         /* reference */
220           sax_characters,     /* characters */
221           NULL,         /* ignorableWhitespace */
222           NULL,         /* processingInstruction */
223           NULL,         /* comment */
224           sax_warning,  /* warning */
225           sax_error,            /* error */
226           sax_error             /* fatalError */
227       };
228       
229       //---------------------------------------------------------------------------
230       
231       XmlParser::XmlParser (constChannelPtr channel)
232           : _channel (channel)
233           , _processing (false)
234           , _xml_context (NULL)
235           , _state (PARSER_TOPLEVEL)
236           , _current_package (NULL)
237           , _current_update (NULL)
238           , _toplevel_dep_list (NULL)
239           , _current_dep_list (NULL)
240           , _text_buffer (NULL)
241           , _text_buffer_size (0)
242       {
243       //    if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "* Context created (%p)", this);
244       }
245       
246       
247       XmlParser::~XmlParser()
248       {
249           releaseBuffer ();
250       }
251       
252       //---------------------------------------------------------------------------
253       
254       string
255       XmlParser::asString ( void ) const
256       {
257           return toString (*this);
258       }
259       
260       
261       string
262       XmlParser::toString ( const XmlParser & context )
263       {
264           return "<XmlParser/>";
265       }
266       
267       
268       ostream &
269       XmlParser::dumpOn( ostream & str ) const
270       {
271           str << asString();
272           return str;
273       }
274       
275       
276       ostream&
277       operator<<( ostream& os, const XmlParser& context)
278       {
279           return os << context.asString();
280       }
281       
282       //---------------------------------------------------------------------------
283       
284       void
285       XmlParser::toBuffer (const char *data, size_t size)
286       {
287           _text_buffer = (char *)realloc (_text_buffer, _text_buffer_size + size + 1);
288           strncpy (_text_buffer + _text_buffer_size, (char *)data, size);
289           _text_buffer_size += size;
290           _text_buffer[_text_buffer_size] = 0;
291       
292       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser[%p]::toBuffer(%.32s...,%ld)\n", this, data, (long)size);
293       }
294       
295       
296       void
297       XmlParser::releaseBuffer ()
298       {
299           if (_text_buffer)
300         free (_text_buffer);
301           _text_buffer = NULL;
302           _text_buffer_size = 0;
303       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser[%p]::releaseBuffer()\n", this);
304       }
305       
306       
307       void
308       XmlParser::parseChunk(const char *xmlbuf, size_t size)
309       {
310           if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::parseChunk(%.32s...,%ld)\n", xmlbuf, (long)size);
311       
312           xmlSubstituteEntitiesDefault(true);
313           
314           if (!_xml_context) {
315         _xml_context = xmlCreatePushParserCtxt(&sax_handler, this, NULL, 0, NULL);
316           }
317       
318           xmlParseChunk(_xml_context, xmlbuf, size, 0);
319       }
320       
321       
322       PackageList
323       XmlParser::done()
324       {
325       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::done()\n");
326       
327           if (_processing)
328         xmlParseChunk(_xml_context, NULL, 0, 1);
329       
330           if (_xml_context)
331         xmlFreeParserCtxt(_xml_context);
332           
333           if (_current_package) {
334         fprintf (stderr, "Incomplete package lost\n");
335           }
336       
337           if (_current_update) {
338         fprintf (stderr, "Incomplete update lost");
339           }
340       
341           return _all_packages;
342       }
343       
344       
345       //---------------------------------------------------------------------------
346       // Parser state callbacks
347       
348       void
349       XmlParser::startElement(const char *name, const xmlChar **attrs)
350       {
351       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::startElement(%s)\n", name);
352       
353           switch (_state) {
354           case PARSER_TOPLEVEL:
355         toplevelStart(name, attrs);
356         break;
357           case PARSER_PACKAGE:
358         packageStart(name, attrs);
359         break;
360           case PARSER_HISTORY:
361         historyStart(name, attrs);
362         break;
363           case PARSER_DEP:
364         dependencyStart(name, attrs);
365         break;
366           default:
367         break;
368           }
369       
370           return;
371       }
372       
373       
374       void
375       XmlParser::endElement(const char *name)
376       {
377       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::endElement(%s)\n", name);
378       
379           if (name != NULL) {                   // sax_end_element might set name to NULL
380         switch (_state) {
381             case PARSER_PACKAGE:
382                 packageEnd(name);
383                 break;
384             case PARSER_HISTORY:
385                 historyEnd(name);
386                 break;
387             case PARSER_UPDATE:
388                 updateEnd(name);
389                 break;
390             case PARSER_DEP:
391                 dependencyEnd(name);
392                 break;
393             default:
394                 break;
395         }
396           }
397       
398           releaseBuffer();
399       
400           return;
401       }
402       
403       
404       void
405       XmlParser::toplevelStart(const char * name, const xmlChar **attrs)
406       {
407       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::toplevelStart(%s)\n", name);
408       
409           if (!strcmp(name, "package")) {
410         assert(_current_package == NULL);
411       
412         _state = PARSER_PACKAGE;
413       
414         _current_package = new Package(_channel);
415         _current_requires.clear();
416         _current_provides.clear();
417         _current_conflicts.clear();
418         _current_children.clear();
419         _current_recommends.clear();
420         _current_suggests.clear();
421         _current_obsoletes.clear();
422       
423           }
424           else {
425         if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s at toplevel", (const char *)name);
426           }
427       }
428       
429       
430       void
431       XmlParser::packageStart(const char * name, const xmlChar **attrs)
432       {
433       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageStart(%s)\n", name);
434       
435           assert(_current_package != NULL);
436       
437           /* Only care about the containers here */
438           if (!strcmp((const char *)name, "history")) {
439         _state = PARSER_HISTORY;
440           }
441           else if (!strcmp (name, "deps")) {
442         /*
443          * We can get a <deps> tag surrounding the actual package
444          * dependency sections (requires, provides, conflicts, etc).
445          * In this case, we'll just ignore this tag quietly.
446          */
447           }
448           else if (!strcmp(name, "requires")) {
449         _state = PARSER_DEP;
450         _current_dep_list = _toplevel_dep_list = &_current_requires;
451           }
452           else if (!strcmp(name, "recommends")) {
453         _state = PARSER_DEP;
454         _current_dep_list = _toplevel_dep_list = &_current_recommends;
455           }
456           else if (!strcmp(name, "suggests")) {
457         _state = PARSER_DEP;
458         _current_dep_list = _toplevel_dep_list = &_current_suggests;
459           }
460           else if (!strcmp(name, "conflicts")) {
461         bool is_obsolete = false;
462         int i;
463       
464         _state = PARSER_DEP;
465       
466         for (i = 0; attrs && attrs[i] && !is_obsolete; i += 2) {
467       
468             if (!strcasecmp ((const char *)(attrs[i]), "obsoletes"))
469                 is_obsolete = true;
470         }
471       
472         if (is_obsolete)
473             _current_dep_list = _toplevel_dep_list = &_current_obsoletes;
474         else {
475             _current_dep_list = _toplevel_dep_list = &_current_conflicts;
476         }
477           }
478           else if (!strcmp(name, "obsoletes")) {
479         _state = PARSER_DEP;
480         _current_dep_list = _toplevel_dep_list = &_current_obsoletes;
481           }
482           else if (!strcmp(name, "provides")) {
483         _state = PARSER_DEP;
484         _current_dep_list = _toplevel_dep_list = &_current_provides;
485           }
486           else if (!strcmp(name, "children")) {
487         _state = PARSER_DEP;
488         _current_dep_list = _toplevel_dep_list = &_current_children;
489           } 
490           else {
491       //        if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in package start", name);
492           }
493       }
494       
495       
496       void
497       XmlParser::historyStart(const char * name, const xmlChar **attrs)
498       {
499       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::historyStart(%s)\n", name);
500       
501           assert(_current_package != NULL);
502       
503           if (!strcmp(name, "update")) {
504         assert(_current_update == NULL);
505       
506         _current_update = new PackageUpdate(_current_package->name());
507       
508         _state = PARSER_UPDATE;
509           }
510           else {
511         if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in history", name);
512           }
513       }
514       
515       
516       void
517       XmlParser::dependencyStart(const char *name, const xmlChar **attrs)
518       {
519       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::dependencyStart(%s)\n", name);
520       
521           if (!strcmp(name, "dep")) {
522         DependencyPtr dep;
523         bool is_obsolete;
524       
525         dep = parse_dep_attrs(&is_obsolete, attrs);
526       
527         if (is_obsolete)
528             _current_obsoletes.push_back (dep);
529         else {
530             _current_dep_list->push_back (dep);
531         }
532           }
533           else if (!strcmp(name, "or"))
534         _current_dep_list = new CDependencyList;
535           else {
536         if (getenv ("RC_SPEW_XML")) rc_debug (RC_DEBUG_LEVEL_ALWAYS, "! Not handling %s in dependency", name);
537           }
538       }
539       
540       
541       //---------------------------------------------------------------------------
542       
543       
544       void
545       XmlParser::packageEnd(const char *name)
546       {
547       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s)\n", name);
548       
549           assert(_current_package != NULL);
550       
551           if (!strcmp(name, "package")) {
552         PackageUpdatePtr update;
553       
554         /* If possible, grab the version info from the most recent update.
555          * Otherwise, try to find where the package provides itself and use
556          * that version info.
557          */
558         update = _current_package->getLatestUpdate();
559       
560         if (update) {
561             _current_package->setName (update->name());
562             _current_package->setKind (update->kind());
563             _current_package->setEdition (update->edition());
564             _current_package->setFileSize (update->packageSize());
565             _current_package->setInstalledSize (update->installedSize());
566         }
567         else {
568             for (CDependencyList::const_iterator iter = _current_provides.begin(); iter != _current_provides.end(); iter++) {
569                 if ((*iter)->relation().isEqual()
570                     && ((*iter)->name() == _current_package->name()))
571                 {
572                     _current_package->setKind ((*iter)->kind());
573                     _current_package->setEdition ((*iter)->edition());
574                     break;
575                 }
576             }
577         }
578
579 #if 0
580         /* Hack for the old XML */
581         if (_current_package->arch()->isUnknown()) {
582             _current_package->setArch (zypp::Arch::System);
583         }
584 #endif
585
586         
587         // check if we provide ourselfs properly
588       
589         CDependencyList::const_iterator piter;
590         for (piter = _current_provides.begin(); piter != _current_provides.end(); piter++) {
591             if ((*piter)->relation().isEqual()
592                 && ((*piter)->name() == _current_package->name()))
593             {
594                 break;
595             }
596         }
597       
598         if (piter == _current_provides.end()) {                 // no self provide found, construct one
599             constDependencyPtr selfdep = new Dependency (_current_package->name(), Relation::Equal, _current_package->kind(), _current_package->channel(), _current_package->edition());
600       //if (getenv ("RC_SPEW")) fprintf (stderr, "Adding self-provide [%s]\n", selfdep->asString().c_str());
601             _current_provides.push_front (selfdep);
602         }
603       
604         _current_package->setRequires   (_current_requires);
605         _current_package->setProvides   (_current_provides);
606         _current_package->setConflicts  (_current_conflicts);
607         _current_package->setObsoletes  (_current_obsoletes);
608         _current_package->setSuggests   (_current_suggests);
609         _current_package->setRecommends (_current_recommends);
610       
611         _all_packages.push_back (_current_package);
612         
613         if (getenv ("RC_SPEW")) fprintf (stderr, "%s\n", _current_package->asString(true).c_str());
614         if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd done: '%s'\n", _current_package->asString(true).c_str());
615       //        if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd now %ld packages\n", _all_packages.size());
616         _current_package = NULL;
617         _state = PARSER_TOPLEVEL;
618           }
619           else if (!strcmp(name, "name")) {                     _current_package->setName (strstrip (_text_buffer));
620           } else if (!strcmp(name, "pretty_name")) {            _current_package->setPrettyName (strstrip (_text_buffer));
621           } else if (!strcmp(name, "summary")) {                _current_package->setSummary (strstrip (_text_buffer));
622           } else if (!strcmp(name, "description")) {            _current_package->setDescription (strstrip (_text_buffer));
623           } else if (!strcmp(name, "section")) {                _current_package->setSection (new Section(strstrip (_text_buffer)));
624           } else if (!strcmp(name, "arch")) {                   _current_package->setArch (strstrip (_text_buffer));
625           } else if (!strcmp(name, "filesize")) {               _current_package->setFileSize (atoi(_text_buffer));
626           } else if (!strcmp(name, "installedsize")) {  _current_package->setInstalledSize (atoi(_text_buffer));
627           } else if (!strcmp(name, "install_only")) {           _current_package->setInstallOnly (true);
628           } else if (!strcmp(name, "package_set")) {            _current_package->setPackageSet (true);
629           } else {
630         if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s) unknown\n", name);
631           }
632       
633       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::packageEnd(%s) done\n", name);
634       
635           releaseBuffer();
636       }
637       
638       
639       void
640       XmlParser::historyEnd(const char *name)
641       {
642       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::historyEnd(%s)\n", name);
643           assert(_current_package != NULL);
644       
645           if (!strcmp(name, "history")) {
646         assert(_current_update == NULL);
647       
648         _state = PARSER_PACKAGE;
649           }
650       }
651       
652       
653       void
654       XmlParser::updateEnd(const char *name)
655       {
656       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::updateEnd(%s)\n", name);
657       
658           constChannelPtr channel;
659           const char *url_prefix = NULL;
660       
661           assert(_current_package != NULL);
662           assert(_current_update != NULL);
663       
664           channel = _current_package->channel();
665       
666           if (channel != NULL) {
667         url_prefix = channel->filePath ();
668           }
669       
670           if (!strcmp(name, "update")) {
671         _current_package->addUpdate(_current_update);
672       
673         _current_update = NULL;
674         _state = PARSER_HISTORY;
675       
676           } else if (!strcmp(name, "epoch")) {          _current_update->setEpoch (atoi(_text_buffer));
677           } else if (!strcmp(name, "version")) {                _current_update->setVersion (strstrip (_text_buffer));
678           } else if (!strcmp(name, "release")) {                _current_update->setRelease (strstrip (_text_buffer));
679           } else if (!strcmp(name, "arch")) {                   _current_update->setArch (strstrip (_text_buffer));
680           } else if (!strcmp(name, "filename")) {
681         strstrip (_text_buffer);
682         if (url_prefix) {
683             _current_update->setPackageUrl (maybe_merge_paths(url_prefix, _text_buffer));
684         }
685         else {
686             _current_update->setPackageUrl (_text_buffer);
687         }
688           } else if (!strcmp(name, "filesize")) {               _current_update->setPackageSize (atoi(_text_buffer));
689           } else if (!strcmp(name, "installedsize")) {  _current_update->setInstalledSize (atoi (_text_buffer));
690           } else if (!strcmp(name, "signaturename")) {
691         strstrip (_text_buffer);
692         if (url_prefix) {
693             _current_update->setSignatureUrl (maybe_merge_paths(url_prefix, _text_buffer));
694         }
695         else {
696             _current_update->setSignatureUrl (_text_buffer);
697         }
698           } else if (!strcmp(name, "signaturesize")) {  _current_update->setSignatureSize (atoi (_text_buffer));
699           } else if (!strcmp(name, "md5sum")) {         _current_update->setMd5sum (strstrip (_text_buffer));
700           } else if (!strcmp(name, "importance")) {             _current_update->setImportance (new Importance (strstrip (_text_buffer)));
701           } else if (!strcmp(name, "description")) {            _current_update->setDescription (strstrip (_text_buffer));
702           } else if (!strcmp(name, "hid")) {                    _current_update->setHid (atoi(_text_buffer));
703           } else if (!strcmp (name, "license")) {               _current_update->setLicense (strstrip (_text_buffer));
704           } else {
705         fprintf (stderr, "XmlParser::updateEnd(%s) unknown\n", name);
706           }
707       
708       //    if (_current_update != NULL && getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::updateEnd(%s) => '%s'\n", name, _current_update->asString().c_str());
709       
710           releaseBuffer();
711       
712       }
713       
714       
715       void
716       XmlParser::dependencyEnd(const char *name)
717       {
718       //    if (getenv ("RC_SPEW_XML")) fprintf (stderr, "XmlParser::dependencyEnd(%s)\n", name);
719       
720           if (!strcmp(name, "or")) {
721         OrDependencyPtr or_dep = OrDependency::fromDependencyList (*_current_dep_list);
722         DependencyPtr dep = new Dependency (or_dep);
723       
724         (*_current_dep_list).clear();
725       
726         (*_toplevel_dep_list).push_back (dep);
727         _current_dep_list = _toplevel_dep_list;
728           }
729           else if (!strcmp(name, "dep")) {
730         /* We handled everything we needed for dep in start */
731           }
732           else {
733         /* All of the dep lists (requires, provides, etc.) */
734         _toplevel_dep_list = NULL;
735         _current_dep_list = NULL;
736         _state = PARSER_PACKAGE;
737           }
738       }
739       
740       
741       
742       //===================================================================================================================
743       
744       #if 0
745       //---------------------------------------------------------------------------
746       
747       /* ------ */
748       
749       
750       static RCResItemDep *
751       rc_xml_node_to_resItem_dep_internal (const xmlNode *node)
752       {
753           gchar *name = NULL, *version = NULL, *release = NULL;
754           gboolean has_epoch = false;
755           guint32 epoch = 0;
756           RCResItemRelation relation;
757           RCResItemDep *dep;
758           
759           gchar *tmp;
760       
761           if (g_strcasecmp (node->name, "dep")) {
762         return (NULL);
763           }
764       
765           name = xml_get_prop (node, "name");
766           tmp = xml_get_prop (node, "op");
767           if (tmp) {
768         relation = rc_resItem_relation_from_string (tmp);
769         
770         has_epoch = xml_get_guint32_value (node, "epoch", &epoch);
771       
772         version = xml_get_prop (node, "version");
773         release = xml_get_prop (node, "release");
774           } else {
775         relation = RC_RELATION_ANY;
776           }
777       
778           /* FIXME: should get channel from XML */
779           dep = rc_resItem_dep_new (name, has_epoch, epoch, version, release,
780                                  relation, RC_TYPE_RESOLVABLE, RC_CHANNEL_ANY,
781                                  false, false);
782       
783           g_free (tmp);
784           g_free (name);
785           g_free (version);
786           g_free (release);
787       
788           return dep;
789       } /* rc_xml_node_to_resItem_dep_internal */
790       
791       RCResItemDep *
792       rc_xml_node_to_resItem_dep (const xmlNode *node)
793       {
794           RCResItemDep *dep = NULL;
795       
796           if (!g_strcasecmp (node->name, "dep")) {
797         dep = rc_xml_node_to_resItem_dep_internal (node);
798         return (dep);
799           } else if (!g_strcasecmp (node->name, "or")) {
800         RCResItemDepSList *or_dep_slist = NULL;
801         RCDepOr *or;
802         xmlNode *iter = node->xmlChildrenNode;
803       
804         while (iter) {
805             if (iter->type == XML_ELEMENT_NODE) {
806                 or_dep_slist = g_slist_append(
807                     or_dep_slist,
808                     rc_xml_node_to_resItem_dep_internal (iter));
809             }
810       
811             iter = iter->next;
812         }
813       
814         or = rc_dep_or_new (or_dep_slist);
815         dep = rc_dep_or_new_provide (or);
816           }
817       
818           return (dep);
819       } /* rc_xml_node_to_resItem_dep */
820       
821       /* ------ */
822       
823       /* This hack cleans 8-bit characters out of a string.  This is a very
824          problematic "solution" to the problem of non-UTF-8 package info. */
825       static gchar *
826       sanitize_string (const char *str)
827       {
828           gchar *dup = g_strdup (str);
829           gchar *c;
830       
831           return dup;
832       
833           if (dup) {
834         for (c = dup; *c; ++c) {
835             if ((guint)*c > 0x7f)
836                 *c = '_';
837         }
838           }
839       
840           return dup;
841       }
842       
843       #endif
844       ///////////////////////////////////////////////////////////////////
845     };// namespace detail
846     /////////////////////////////////////////////////////////////////////
847     /////////////////////////////////////////////////////////////////////
848   };// namespace solver
849   ///////////////////////////////////////////////////////////////////////
850   ///////////////////////////////////////////////////////////////////////
851 };// namespace zypp
852 /////////////////////////////////////////////////////////////////////////