00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <ctime>
00014 #include <fstream>
00015 #include <sstream>
00016 #include <streambuf>
00017
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/CapFactory.h"
00020 #include "zypp/Source.h"
00021 #include "zypp/Url.h"
00022
00023 #include "zypp/ResObject.h"
00024 #include "zypp/detail/ImplConnect.h"
00025 #include "zypp/detail/ResObjectImplIf.h"
00026 #include "zypp/detail/SelectionImplIf.h"
00027
00028 #include "serialize.h"
00029 #include "xml_escape_parser.hpp"
00030
00031 using namespace std;
00033 namespace zypp
00034 {
00035 namespace storage
00036 {
00037
00038 std::string xml_escape( const std::string &text )
00039 {
00040 iobind::parser::xml_escape_parser parser;
00041 return parser.escape(text);
00042 }
00043
00044 std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false )
00045 {
00046 std::string result;
00047 result += "<" + tag + ">";
00048
00049 if ( escape)
00050 result += xml_escape(text);
00051 else
00052 result += text;
00053
00054 result += "</" + tag + ">";
00055 return result;
00056 }
00057
00064 static std::string translatedTextToXML(const TranslatedText &text, const std::string &tagname)
00065 {
00066 std::set<Locale> locales = text.locales();
00067
00068 std::stringstream out;
00069 for ( std::set<Locale>::const_iterator it = locales.begin(); it != locales.end(); ++it)
00070 {
00071
00072 if ( *it == Locale() )
00073 out << "<" << tagname << ">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << std::endl;
00074 else
00075 out << "<" << tagname << " lang=\"" << (*it).code() << "\">" << xml_escape(text.text(*it)) << "</" << tagname << ">" << std::endl;
00076 }
00077 return out.str();
00078 }
00079
00080 template<class T>
00081 std::string toXML( const T &obj );
00082
00083 template<>
00084 std::string toXML( const Edition &edition )
00085 {
00086 stringstream out;
00087
00088 out << "<version ver=\"" << xml_escape(edition.version()) << "\" rel=\"" << xml_escape(edition.release()) << "\"/>";
00089 return out.str();
00090 }
00091
00092 template<>
00093 std::string toXML( const Arch &arch )
00094 {
00095 stringstream out;
00096 out << xml_tag_enclose(xml_escape(arch.asString()), "arch");
00097 return out.str();
00098 }
00099
00100 template<>
00101 std::string toXML( const Capability &cap )
00102 {
00103 stringstream out;
00104 CapFactory factory;
00105
00106 out << "<capability kind=\"" << cap.refers() << "\" >" << xml_escape(factory.encode(cap)) << "</capability>" << std::endl;
00107 return out.str();
00108 }
00109
00110 template<>
00111 std::string toXML( const CapSet &caps )
00112 {
00113 stringstream out;
00114 CapSet::iterator it = caps.begin();
00115 for ( ; it != caps.end(); ++it)
00116 {
00117 out << toXML((*it));
00118 }
00119 return out.str();
00120 }
00121
00122 template<>
00123 std::string toXML( const Dependencies &dep )
00124 {
00125 stringstream out;
00126 if ( dep[Dep::PROVIDES].size() > 0 )
00127 out << " " << xml_tag_enclose(toXML(dep[Dep::PROVIDES]), "provides") << std::endl;
00128 if ( dep[Dep::PREREQUIRES].size() > 0 )
00129 out << " " << xml_tag_enclose(toXML(dep[Dep::PREREQUIRES]), "prerequires") << std::endl;
00130 if ( dep[Dep::CONFLICTS].size() > 0 )
00131 out << " " << xml_tag_enclose(toXML(dep[Dep::CONFLICTS]), "conflicts") << std::endl;
00132 if ( dep[Dep::OBSOLETES].size() > 0 )
00133 out << " " << xml_tag_enclose(toXML(dep[Dep::OBSOLETES]), "obsoletes") << std::endl;
00134
00135 if ( dep[Dep::FRESHENS].size() > 0 )
00136 out << " " << xml_tag_enclose(toXML(dep[Dep::FRESHENS]), "freshens") << std::endl;
00137 if ( dep[Dep::REQUIRES].size() > 0 )
00138 out << " " << xml_tag_enclose(toXML(dep[Dep::REQUIRES]), "requires") << std::endl;
00139 if ( dep[Dep::RECOMMENDS].size() > 0 )
00140 out << " " << xml_tag_enclose(toXML(dep[Dep::RECOMMENDS]), "recommends") << std::endl;
00141 if ( dep[Dep::ENHANCES].size() > 0 )
00142 out << " " << xml_tag_enclose(toXML(dep[Dep::ENHANCES]), "enhances") << std::endl;
00143 if ( dep[Dep::SUPPLEMENTS].size() > 0 )
00144 out << " " << xml_tag_enclose(toXML(dep[Dep::SUPPLEMENTS]), "supplements") << std::endl;
00145 if ( dep[Dep::SUGGESTS].size() > 0 )
00146 out << " " << xml_tag_enclose(toXML(dep[Dep::SUGGESTS]), "suggests") << std::endl;
00147 return out.str();
00148
00149 }
00150
00151 template<>
00152 std::string toXML( const Resolvable::constPtr &obj )
00153 {
00154 stringstream out;
00155
00156 out << " <name>" << xml_escape(obj->name()) << "</name>" << std::endl;
00157
00158 out << " " << toXML(obj->edition()) << std::endl;
00159 out << " " << toXML(obj->arch()) << std::endl;
00160 out << " " << toXML(obj->deps()) << std::endl;
00161 return out.str();
00162 }
00163
00164 template<>
00165 std::string toXML( const Package::constPtr &obj )
00166 {
00167 stringstream out;
00168 out << "<package>" << std::endl;
00169
00170 toXML(static_cast<Resolvable::constPtr>(obj));
00171
00172
00173
00174 out << "</package>" << std::endl;
00175 return out.str();
00176 }
00177
00178 template<>
00179 std::string toXML( const Script::constPtr &obj )
00180 {
00181 stringstream out;
00182 out << "<script>" << std::endl;
00183
00184 out << toXML(static_cast<Resolvable::constPtr>(obj));
00185 out << " <do>" << std::endl;
00186 out << " <![CDATA[" << std::endl;
00187
00188
00189 ifstream infile;
00190 infile.open(obj->do_script().asString().c_str());
00191 while (infile.good())
00192 {
00193 char c = (char)infile.get();
00194 if (! infile.eof())
00195 out << c;
00196 }
00197 infile.close();
00198
00199 out << " ]]>" << std::endl;
00200 out << " </do>" << std::endl;
00201
00202 if ( obj->undo_available() )
00203 {
00204 out << " <undo>" << std::endl;
00205 out << " <![CDATA[" << std::endl;
00206
00207
00208 infile.open(obj->undo_script().asString().c_str());
00209 while (infile.good())
00210 {
00211 char c = (char)infile.get();
00212 if (! infile.eof())
00213 out << c;
00214 }
00215 infile.close();
00216
00217 out << " ]]>" << std::endl;
00218 out << " </undo>" << std::endl;
00219
00220 }
00221 out << "</script>" << std::endl;
00222 return out.str();
00223 }
00224
00225 template<>
00226 std::string toXML( const Message::constPtr &obj )
00227 {
00228 stringstream out;
00229 out << "<message>" << std::endl;
00230
00231 out << toXML(static_cast<Resolvable::constPtr>(obj));
00232 out << " <text>" << xml_escape(obj->text().text()) << "</text>" << std::endl;
00233 out << "</message>" << std::endl;
00234 return out.str();
00235 }
00236
00237 template<>
00238 std::string toXML( const Language::constPtr &obj )
00239 {
00240 stringstream out;
00241 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00242 out << "<language xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00243 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00244 out << "</language>" << std::endl;
00245 return out.str();
00246 }
00247
00248
00249 template<>
00250 std::string toXML( const Selection::constPtr &obj )
00251 {
00252 stringstream out;
00253 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00254 out << "<pattern xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00255
00256 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00257
00258
00259 detail::ResImplTraits<Selection::Impl>::constPtr sipp( detail::ImplConnect::resimpl( obj ) );
00260 out << translatedTextToXML(sipp->summary(), "summary");
00261 out << translatedTextToXML(sipp->description(), "description");
00262
00263 out << " <uservisible>" << (obj->visible() ? "true" : "false" ) << "</uservisible>" << std::endl;
00264 out << " <category>" << xml_escape(obj->category()) << "</category>" << std::endl;
00265 out << " <icon></icon>" << std::endl;
00266 out << "</pattern>" << std::endl;
00267 return out.str();
00268 }
00269
00270 template<>
00271 std::string toXML( const Atom::constPtr &obj )
00272 {
00273 stringstream out;
00274 out << "<atom>" << std::endl;
00275 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00276 out << "</atom>" << std::endl;
00277 return out.str();
00278 }
00279
00280 template<>
00281 std::string toXML( const Pattern::constPtr &obj )
00282 {
00283 stringstream out;
00284 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00285 out << "<pattern xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00286
00287 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00288
00289
00290 detail::ResImplTraits<Pattern::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00291 out << translatedTextToXML(pipp->summary(), "summary");
00292 out << translatedTextToXML(pipp->description(), "description");
00293
00294 out << " <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << std::endl;
00295 out << " <uservisible>" << (obj->userVisible() ? "true" : "false" ) << "</uservisible>" << std::endl;
00296 out << " <category>" << xml_escape(obj->category()) << "</category>" << std::endl;
00297 out << " <icon>" << xml_escape(obj->icon().asString()) << "</icon>" << std::endl;
00298 out << " <script>" << xml_escape(obj->script().asString()) << "</script>" << std::endl;
00299 out << "</pattern>" << std::endl;
00300 return out.str();
00301 }
00302
00303 template<>
00304 std::string toXML( const Product::constPtr &obj )
00305 {
00306 stringstream out;
00307 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00308 out << "<product xmlns=\"http://www.novell.com/metadata/zypp/xml-store\" type=\"" << xml_escape(obj->category()) << "\">" << std::endl;
00309 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00310 #warning "FIXME description and displayname of products"
00311
00312
00313 detail::ResImplTraits<Product::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00314 out << translatedTextToXML(pipp->summary(), "summary");
00315 out << translatedTextToXML(pipp->description(), "description");
00316 out << translatedTextToXML(pipp->shortName(), "shortname");
00317
00318 out << " <vendor>" << xml_escape(obj->vendor()) << "</vendor>" << std::endl;
00319 out << " <source>" << xml_escape(obj->source().alias()) << "</source>" << std::endl;
00320 out << " <release-notes-url>" << xml_escape(obj->releaseNotesUrl().asString()) << "</release-notes-url>" << std::endl;
00321 out << " <update-urls>" << std::endl;
00322 std::list<Url> updateUrls = obj->updateUrls();
00323 for ( std::list<Url>::const_iterator it = updateUrls.begin(); it != updateUrls.end(); ++it)
00324 {
00325 out << " <update-url>" << xml_escape(it->asString()) << "</update-url>" << std::endl;
00326 }
00327 out << " </update-urls>" << std::endl;
00328 out << " <product-flags>" << std::endl;
00329 std::list<std::string> flags = obj->flags();
00330 for ( std::list<std::string>::const_iterator it = flags.begin(); it != flags.end(); ++it)
00331 {
00332 out << " <product-flag>" << xml_escape(*it) << "</product-flag>" << std::endl;
00333 }
00334 out << " </product-flags>" << std::endl;
00335
00336 out << "</product>" << std::endl;
00337
00338 return out.str();
00339 }
00340
00341
00342 std::string castedToXML( const Resolvable::constPtr &resolvable )
00343 {
00344 stringstream out;
00345 if ( isKind<Package>(resolvable) )
00346 out << toXML(asKind<const Package>(resolvable)) << std::endl;
00347 if ( isKind<Patch>(resolvable) )
00348 out << toXML(asKind<const Patch>(resolvable)) << std::endl;
00349 if ( isKind<Message>(resolvable) )
00350 out << toXML(asKind<const Message>(resolvable)) << std::endl;
00351 if ( isKind<Script>(resolvable) )
00352 out << toXML(asKind<const Script>(resolvable)) << std::endl;
00353 if ( isKind<Atom>(resolvable) )
00354 out << toXML(asKind<const Atom>(resolvable)) << std::endl;
00355 if ( isKind<Product>(resolvable) )
00356 out << toXML(asKind<const Product>(resolvable)) << std::endl;
00357 if ( isKind<Pattern>(resolvable) )
00358 out << toXML(asKind<const Pattern>(resolvable)) << std::endl;
00359 if ( isKind<Selection>(resolvable) )
00360 out << toXML(asKind<const Selection>(resolvable)) << std::endl;
00361 if ( isKind<Language>(resolvable) )
00362 out << toXML(asKind<const Language>(resolvable)) << std::endl;
00363 return out.str();
00364 }
00365
00366 std::string resolvableTypeToString( const Resolvable::constPtr &resolvable, bool plural )
00367 {
00368 return resolvableKindToString(resolvable->kind(), plural);
00369 }
00370
00371 std::string resolvableKindToString( const Resolvable::Kind &kind, bool plural)
00372 {
00373 std::string k = kind.asString();
00374 if (k.substr(k.size() - 2, 2) == "ch")
00375 return k + (plural?"es":"");
00376 else
00377 return k + (plural?"s":"");
00378 }
00379
00380 template<>
00381 std::string toXML( const Patch::constPtr &obj )
00382 {
00383 stringstream out;
00384 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00385 out << "<patch xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00386
00387
00388 out << toXML(static_cast<Resolvable::constPtr>(obj));
00389
00390
00391 detail::ResImplTraits<Patch::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00392 out << translatedTextToXML(pipp->summary(), "summary");
00393 out << translatedTextToXML(pipp->description(), "description");
00394
00395 out << "<id>" << xml_escape(obj->id()) << "</id>" << std::endl;
00396 out << "<timestamp>" << obj->timestamp().asSeconds() << "</timestamp>" << std::endl;
00397
00398 out << "<category>" << obj->category() << "</category>" << std::endl;
00399 out << "<affects-package-manager>" << ( obj->affects_pkg_manager() ? "true" : "false" ) << "</affects-package-manager>" << std::endl;
00400 out << "<reboot-needed>" << ( obj->reboot_needed() ? "true" : "false" ) << "</reboot-needed>" << std::endl;
00401 out << "<interactive>" << ( obj->interactive() ? "true" : "false" ) << "</interactive>" << std::endl;
00402
00403 Patch::AtomList at = obj->atoms();
00404 out << " <atoms>" << std::endl;
00405 for (Patch::AtomList::iterator it = at.begin(); it != at.end(); it++)
00406 {
00407 Resolvable::Ptr one_atom = *it;
00408 out << castedToXML(one_atom) << std::endl;
00409 }
00410 out << " </atoms>" << std::endl;
00411 out << "</patch>" << std::endl;
00412 return out.str();
00413 }
00414
00415 template<>
00416 std::string toXML( const PersistentStorage::SourceData &obj )
00417 {
00418 stringstream out;
00419 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00420 out << "<source xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00421 out << " <enabled>" << (obj.enabled ? "true" : "false" ) << "</enabled>" << std::endl;
00422 out << " <auto-refresh>" << ( obj.autorefresh ? "true" : "false" ) << "</auto-refresh>" << std::endl;
00423 out << " <product-dir>" << obj.product_dir << "</product-dir>" << std::endl;
00424 out << " <cache-dir>" << obj.cache_dir << "</cache-dir>" << std::endl;
00425 out << " <type>" << xml_escape(obj.type) << "</type>" << std::endl;
00426 out << " <url>" << xml_escape(obj.url.asString()) << "</url>" << std::endl;
00427 out << " <alias>" << xml_escape(obj.alias) << "</alias>" << std::endl;
00428 out << "</source>" << std::endl;
00429 return out.str();
00430 }
00431
00433 }
00436 }