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 ResObject::constPtr &obj )
00166 {
00167 stringstream out;
00168
00169
00170 detail::ResImplTraits<ResObject::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00171 out << translatedTextToXML(pipp->summary(), "summary");
00172 out << translatedTextToXML(pipp->description(), "description");
00173
00174 out << translatedTextToXML(pipp->insnotify(), "install-notify");
00175 out << translatedTextToXML(pipp->delnotify(), "delete-notify");
00176
00177 out << translatedTextToXML(pipp->licenseToConfirm(), "license-to-confirm");
00178 out << " <vendor>" << xml_escape(obj->vendor()) << "</vendor>" << std::endl;
00179 out << " <size>" << obj->size() << "</size>" << std::endl;
00180 out << " <archive-size>" << obj->archivesize() << "</archive-size>" << std::endl;
00181 out << " <install-only>" << ( obj->installOnly() ? "true" : "false" ) << "</install-only>" << std::endl;
00182 out << " <build-time>" << obj->buildtime().asSeconds() << "</build-time>" << std::endl;
00183
00184 out << " <install-time>" << Date::now() << "</install-time>" << std::endl;
00185
00186 return out.str();
00187 }
00188
00189 template<>
00190 std::string toXML( const Package::constPtr &obj )
00191 {
00192 stringstream out;
00193 out << "<package>" << std::endl;
00194
00195 out << toXML(static_cast<Resolvable::constPtr>(obj));
00196 out << toXML(static_cast<ResObject::constPtr>(obj));
00197
00198
00199
00200 out << "</package>" << std::endl;
00201 return out.str();
00202 }
00203
00204 template<>
00205 std::string toXML( const Script::constPtr &obj )
00206 {
00207 stringstream out;
00208 out << "<script>" << std::endl;
00209
00210 out << toXML(static_cast<Resolvable::constPtr>(obj));
00211 out << toXML(static_cast<ResObject::constPtr>(obj));
00212 out << " <do>" << std::endl;
00213 out << " <![CDATA[" << std::endl;
00214
00215
00216 ifstream infile;
00217 infile.open(obj->do_script().asString().c_str());
00218 while (infile.good())
00219 {
00220 char c = (char)infile.get();
00221 if (! infile.eof())
00222 out << c;
00223 }
00224 infile.close();
00225
00226 out << " ]]>" << std::endl;
00227 out << " </do>" << std::endl;
00228
00229 if ( obj->undo_available() )
00230 {
00231 out << " <undo>" << std::endl;
00232 out << " <![CDATA[" << std::endl;
00233
00234
00235 infile.open(obj->undo_script().asString().c_str());
00236 while (infile.good())
00237 {
00238 char c = (char)infile.get();
00239 if (! infile.eof())
00240 out << c;
00241 }
00242 infile.close();
00243
00244 out << " ]]>" << std::endl;
00245 out << " </undo>" << std::endl;
00246
00247 }
00248 out << "</script>" << std::endl;
00249 return out.str();
00250 }
00251
00252 template<>
00253 std::string toXML( const Message::constPtr &obj )
00254 {
00255 stringstream out;
00256 out << "<message>" << std::endl;
00257
00258 out << toXML(static_cast<Resolvable::constPtr>(obj));
00259 out << toXML(static_cast<ResObject::constPtr>(obj));
00260 out << " <text>" << xml_escape(obj->text().text()) << "</text>" << std::endl;
00261 out << "</message>" << std::endl;
00262 return out.str();
00263 }
00264
00265 template<>
00266 std::string toXML( const Language::constPtr &obj )
00267 {
00268 stringstream out;
00269 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00270 out << "<language xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00271 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00272 out << toXML(static_cast<ResObject::constPtr>(obj));
00273 out << "</language>" << std::endl;
00274 return out.str();
00275 }
00276
00277
00278 template<>
00279 std::string toXML( const Selection::constPtr &obj )
00280 {
00281 stringstream out;
00282 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00283 out << "<pattern xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00284
00285 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00286 out << toXML(static_cast<ResObject::constPtr>(obj));
00287
00288
00289 out << " <uservisible>" << (obj->visible() ? "true" : "false" ) << "</uservisible>" << std::endl;
00290 out << " <category>" << xml_escape(obj->category()) << "</category>" << std::endl;
00291 out << " <icon></icon>" << std::endl;
00292 out << "</pattern>" << std::endl;
00293 return out.str();
00294 }
00295
00296 template<>
00297 std::string toXML( const Atom::constPtr &obj )
00298 {
00299 stringstream out;
00300 out << "<atom>" << std::endl;
00301 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00302 out << toXML(static_cast<ResObject::constPtr>(obj));
00303 out << "</atom>" << std::endl;
00304 return out.str();
00305 }
00306
00307 template<>
00308 std::string toXML( const Pattern::constPtr &obj )
00309 {
00310 stringstream out;
00311 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00312 out << "<pattern xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00313
00314 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00315 out << toXML(static_cast<ResObject::constPtr>(obj));
00316
00317 out << " <default>" << (obj->isDefault() ? "true" : "false" ) << "</default>" << std::endl;
00318 out << " <uservisible>" << (obj->userVisible() ? "true" : "false" ) << "</uservisible>" << std::endl;
00319 out << " <category>" << xml_escape(obj->category()) << "</category>" << std::endl;
00320 out << " <icon>" << xml_escape(obj->icon().asString()) << "</icon>" << std::endl;
00321 out << " <script>" << xml_escape(obj->script().asString()) << "</script>" << std::endl;
00322 out << "</pattern>" << std::endl;
00323 return out.str();
00324 }
00325
00326 template<>
00327 std::string toXML( const Product::constPtr &obj )
00328 {
00329 stringstream out;
00330 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00331 out << "<product xmlns=\"http://www.novell.com/metadata/zypp/xml-store\" type=\"" << xml_escape(obj->category()) << "\">" << std::endl;
00332 out << toXML(static_cast<Resolvable::constPtr>(obj)) << std::endl;
00333 #warning "FIXME description and displayname of products"
00334
00335 out << toXML(static_cast<ResObject::constPtr>(obj));
00336
00337
00338 detail::ResImplTraits<Product::Impl>::constPtr pipp( detail::ImplConnect::resimpl( obj ) );
00339 out << translatedTextToXML(pipp->shortName(), "shortname");
00340
00341 out << " <source>" << xml_escape(obj->source().alias()) << "</source>" << std::endl;
00342 out << " <release-notes-url>" << xml_escape(obj->releaseNotesUrl().asString()) << "</release-notes-url>" << std::endl;
00343 out << " <update-urls>" << std::endl;
00344 std::list<Url> updateUrls = obj->updateUrls();
00345 for ( std::list<Url>::const_iterator it = updateUrls.begin(); it != updateUrls.end(); ++it)
00346 {
00347 out << " <update-url>" << xml_escape(it->asString()) << "</update-url>" << std::endl;
00348 }
00349 out << " </update-urls>" << std::endl;
00350 out << " <product-flags>" << std::endl;
00351 std::list<std::string> flags = obj->flags();
00352 for ( std::list<std::string>::const_iterator it = flags.begin(); it != flags.end(); ++it)
00353 {
00354 out << " <product-flag>" << xml_escape(*it) << "</product-flag>" << std::endl;
00355 }
00356 out << " </product-flags>" << std::endl;
00357
00358 out << "</product>" << std::endl;
00359
00360 return out.str();
00361 }
00362
00363
00364 std::string castedToXML( const Resolvable::constPtr &resolvable )
00365 {
00366 stringstream out;
00367 if ( isKind<Package>(resolvable) )
00368 out << toXML(asKind<const Package>(resolvable)) << std::endl;
00369 if ( isKind<Patch>(resolvable) )
00370 out << toXML(asKind<const Patch>(resolvable)) << std::endl;
00371 if ( isKind<Message>(resolvable) )
00372 out << toXML(asKind<const Message>(resolvable)) << std::endl;
00373 if ( isKind<Script>(resolvable) )
00374 out << toXML(asKind<const Script>(resolvable)) << std::endl;
00375 if ( isKind<Atom>(resolvable) )
00376 out << toXML(asKind<const Atom>(resolvable)) << std::endl;
00377 if ( isKind<Product>(resolvable) )
00378 out << toXML(asKind<const Product>(resolvable)) << std::endl;
00379 if ( isKind<Pattern>(resolvable) )
00380 out << toXML(asKind<const Pattern>(resolvable)) << std::endl;
00381 if ( isKind<Selection>(resolvable) )
00382 out << toXML(asKind<const Selection>(resolvable)) << std::endl;
00383 if ( isKind<Language>(resolvable) )
00384 out << toXML(asKind<const Language>(resolvable)) << std::endl;
00385 return out.str();
00386 }
00387
00388 std::string resolvableTypeToString( const Resolvable::constPtr &resolvable, bool plural )
00389 {
00390 return resolvableKindToString(resolvable->kind(), plural);
00391 }
00392
00393 std::string resolvableKindToString( const Resolvable::Kind &kind, bool plural)
00394 {
00395 std::string k = kind.asString();
00396 if (k.substr(k.size() - 2, 2) == "ch")
00397 return k + (plural?"es":"");
00398 else
00399 return k + (plural?"s":"");
00400 }
00401
00402 template<>
00403 std::string toXML( const Patch::constPtr &obj )
00404 {
00405 stringstream out;
00406 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00407 out << "<patch xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00408
00409
00410 out << toXML(static_cast<Resolvable::constPtr>(obj));
00411 out << toXML(static_cast<ResObject::constPtr>(obj));
00412
00413 out << "<id>" << xml_escape(obj->id()) << "</id>" << std::endl;
00414 out << "<timestamp>" << obj->timestamp().asSeconds() << "</timestamp>" << std::endl;
00415
00416 out << "<category>" << obj->category() << "</category>" << std::endl;
00417 out << "<affects-package-manager>" << ( obj->affects_pkg_manager() ? "true" : "false" ) << "</affects-package-manager>" << std::endl;
00418 out << "<reboot-needed>" << ( obj->reboot_needed() ? "true" : "false" ) << "</reboot-needed>" << std::endl;
00419 out << "<interactive>" << ( obj->interactive() ? "true" : "false" ) << "</interactive>" << std::endl;
00420
00421 Patch::AtomList at = obj->atoms();
00422 out << " <atoms>" << std::endl;
00423 for (Patch::AtomList::iterator it = at.begin(); it != at.end(); it++)
00424 {
00425 Resolvable::Ptr one_atom = *it;
00426 out << castedToXML(one_atom) << std::endl;
00427 }
00428 out << " </atoms>" << std::endl;
00429 out << "</patch>" << std::endl;
00430 return out.str();
00431 }
00432
00433 template<>
00434 std::string toXML( const PersistentStorage::SourceData &obj )
00435 {
00436 stringstream out;
00437 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
00438 out << "<source xmlns=\"http://www.novell.com/metadata/zypp/xml-store\">" << std::endl;
00439 out << " <enabled>" << (obj.enabled ? "true" : "false" ) << "</enabled>" << std::endl;
00440 out << " <auto-refresh>" << ( obj.autorefresh ? "true" : "false" ) << "</auto-refresh>" << std::endl;
00441 out << " <product-dir>" << obj.product_dir << "</product-dir>" << std::endl;
00442 out << " <cache-dir>" << obj.cache_dir << "</cache-dir>" << std::endl;
00443 out << " <type>" << xml_escape(obj.type) << "</type>" << std::endl;
00444 out << " <url>" << xml_escape(obj.url.asCompleteString()) << "</url>" << std::endl;
00445 out << " <alias>" << xml_escape(obj.alias) << "</alias>" << std::endl;
00446 out << "</source>" << std::endl;
00447 return out.str();
00448 }
00449
00451 }
00454 }