diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index 3d3ef31a3..19b587a5d 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -18,6 +18,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmXMLWriter.h" #include "cmake.h" #include @@ -76,14 +77,15 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) // Create the choice outline, which provides a tree-based view of // the components in their groups. std::ostringstream choiceOut; - choiceOut << "" << std::endl; + cmXMLWriter xout(choiceOut, 1); + xout.StartElement("choices-outline"); // Emit the outline for the groups std::map::iterator groupIt; for (groupIt = this->ComponentGroups.begin(); groupIt != this->ComponentGroups.end(); ++groupIt) { if (groupIt->second.ParentGroup == 0) { - CreateChoiceOutline(groupIt->second, choiceOut); + CreateChoiceOutline(groupIt->second, xout); } } @@ -92,28 +94,32 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) for (compIt = this->Components.begin(); compIt != this->Components.end(); ++compIt) { if (!compIt->second.Group) { - choiceOut << "first << "Choice\">" - << std::endl; + xout.StartElement("line"); + xout.Attribute("choice", compIt->first + "Choice"); + xout.Content(""); // Avoid self-closing tag. + xout.EndElement(); } } if (!this->PostFlightComponent.Name.empty()) { - choiceOut << "" << std::endl; + xout.StartElement("line"); + xout.Attribute("choice", PostFlightComponent.Name + "Choice"); + xout.Content(""); // Avoid self-closing tag. + xout.EndElement(); } - choiceOut << "" << std::endl; + xout.EndElement(); // choices-outline> // Create the actual choices for (groupIt = this->ComponentGroups.begin(); groupIt != this->ComponentGroups.end(); ++groupIt) { - CreateChoice(groupIt->second, choiceOut); + CreateChoice(groupIt->second, xout); } for (compIt = this->Components.begin(); compIt != this->Components.end(); ++compIt) { - CreateChoice(compIt->second, choiceOut); + CreateChoice(compIt->second, xout); } if (!this->PostFlightComponent.Name.empty()) { - CreateChoice(PostFlightComponent, choiceOut); + CreateChoice(PostFlightComponent, xout); } this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str()); @@ -124,40 +130,44 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) } void cmCPackPKGGenerator::CreateChoiceOutline( - const cmCPackComponentGroup& group, std::ostringstream& out) + const cmCPackComponentGroup& group, cmXMLWriter& xout) { - out << "" << std::endl; + xout.StartElement("line"); + xout.Attribute("choice", group.Name + "Choice"); std::vector::const_iterator groupIt; for (groupIt = group.Subgroups.begin(); groupIt != group.Subgroups.end(); ++groupIt) { - CreateChoiceOutline(**groupIt, out); + CreateChoiceOutline(**groupIt, xout); } std::vector::const_iterator compIt; for (compIt = group.Components.begin(); compIt != group.Components.end(); ++compIt) { - out << " Name << "Choice\">" - << std::endl; + xout.StartElement("line"); + xout.Attribute("choice", (*compIt)->Name + "Choice"); + xout.Content(""); // Avoid self-closing tag. + xout.EndElement(); } - out << "" << std::endl; + xout.EndElement(); } void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group, - std::ostringstream& out) + cmXMLWriter& xout) { - out << "" << std::endl; + xout.EndElement(); } void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, - std::ostringstream& out) + cmXMLWriter& xout) { std::string packageId = "com."; packageId += this->GetOption("CPACK_PACKAGE_VENDOR"); @@ -166,18 +176,16 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, packageId += '.'; packageId += component.Name; - out << " visited; - AddDependencyAttributes(component, visited, out); + AddDependencyAttributes(component, visited, selected); visited.clear(); - AddReverseDependencyAttributes(component, visited, out); - out << "\""; + AddReverseDependencyAttributes(component, visited, selected); + xout.Attribute("selected", selected.str()); } - out << ">" << std::endl; - out << " " << std::endl; - out << "" << std::endl; + xout.StartElement("pkg-ref"); + xout.Attribute("id", packageId); + xout.EndElement(); // pkg-ref + xout.EndElement(); // choice // Create a description of the package associated with this // component. @@ -219,17 +228,20 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName.c_str()); - out << "GetOption("CPACK_PACKAGE_VERSION") << "\" " - << "installKBytes=\"" << installedSize << "\" " - << ">"; + xout.StartElement("pkg-ref"); + xout.Attribute("id", packageId); + xout.Attribute("version", this->GetOption("CPACK_PACKAGE_VERSION")); + xout.Attribute("installKBytes", installedSize); + xout.Attribute("auth", "Admin"); + xout.Attribute("onConclusion", "None"); if (component.IsDownloaded) { - out << this->GetOption("CPACK_DOWNLOAD_SITE") - << this->GetPackageName(component); + xout.Content(this->GetOption("CPACK_DOWNLOAD_SITE")); + xout.Content(this->GetPackageName(component)); } else { - out << "file:./" << relativePackageLocation; + xout.Content("file:./"); + xout.Content(relativePackageLocation); } - out << "" << std::endl; + xout.EndElement(); // pkg-ref } void cmCPackPKGGenerator::AddDependencyAttributes( @@ -244,7 +256,7 @@ void cmCPackPKGGenerator::AddDependencyAttributes( std::vector::const_iterator dependIt; for (dependIt = component.Dependencies.begin(); dependIt != component.Dependencies.end(); ++dependIt) { - out << " && choices['" << (*dependIt)->Name << "Choice'].selected"; + out << " && choices['" << (*dependIt)->Name << "Choice'].selected"; AddDependencyAttributes(**dependIt, visited, out); } } @@ -266,15 +278,6 @@ void cmCPackPKGGenerator::AddReverseDependencyAttributes( } } -std::string cmCPackPKGGenerator::EscapeForXML(std::string str) -{ - cmSystemTools::ReplaceString(str, "&", "&"); - cmSystemTools::ReplaceString(str, "<", "<"); - cmSystemTools::ReplaceString(str, ">", ">"); - cmSystemTools::ReplaceString(str, "\"", """); - return str; -} - bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, const std::string& dirName) { diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h index 20ba94c7b..8d10943da 100644 --- a/Source/CPack/cmCPackPKGGenerator.h +++ b/Source/CPack/cmCPackPKGGenerator.h @@ -16,6 +16,7 @@ #include "cmCPackGenerator.h" class cmCPackComponent; +class cmXMLWriter; /** \class cmCPackPKGGenerator * \brief A generator for pkg files @@ -78,21 +79,15 @@ protected: // their components in a form that can be used by distribution // metapackages. void CreateChoiceOutline(const cmCPackComponentGroup& group, - std::ostringstream& out); + cmXMLWriter& xout); /// Create the "choice" XML element to describe a component group /// for the installer GUI. - void CreateChoice(const cmCPackComponentGroup& group, - std::ostringstream& out); + void CreateChoice(const cmCPackComponentGroup& group, cmXMLWriter& xout); /// Create the "choice" XML element to describe a component for the /// installer GUI. - void CreateChoice(const cmCPackComponent& component, - std::ostringstream& out); - - // Escape the given string to make it usable as an XML attribute - // value. - std::string EscapeForXML(std::string str); + void CreateChoice(const cmCPackComponent& component, cmXMLWriter& xout); // The PostFlight component when creating a metapackage cmCPackComponent PostFlightComponent; diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index 891d0f471..ce329ca5e 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -17,6 +17,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmXMLWriter.h" #include "cmake.h" #include @@ -523,21 +524,22 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage( std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); descriptionFile += '/' + component.Name + "-Description.plist"; cmsys::ofstream out(descriptionFile.c_str()); - out << "" << std::endl - << "" << std::endl - << "" << std::endl - << "" << std::endl - << " IFPkgDescriptionTitle" << std::endl - << " " << component.DisplayName << "" << std::endl - << " IFPkgDescriptionVersion" << std::endl - << " " << this->GetOption("CPACK_PACKAGE_VERSION") - << "" << std::endl - << " IFPkgDescriptionDescription" << std::endl - << " " + this->EscapeForXML(component.Description) - << "" << std::endl - << "" << std::endl - << "" << std::endl; + cmXMLWriter xout(out); + xout.StartDocument(); + xout.Doctype("plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"" + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\""); + xout.StartElement("plist"); + xout.Attribute("version", "1.4"); + xout.StartElement("dict"); + xout.Element("key", "IFPkgDescriptionTitle"); + xout.Element("string", component.DisplayName); + xout.Element("key", "IFPkgDescriptionVersion"); + xout.Element("string", this->GetOption("CPACK_PACKAGE_VERSION")); + xout.Element("key", "IFPkgDescriptionDescription"); + xout.Element("string", component.Description); + xout.EndElement(); // dict + xout.EndElement(); // plist + xout.EndDocument(); out.close(); // Create the Info.plist file for this component