Browse Source

ENH: Create cmXMLSafe to help escapes in XML

This class provides easy syntax to efficiently insert blocks of data
into XML documents with proper escapes.  It replaces the old
cmCTest::MakeXMLSafe and cmSystemTools::MakeXMLSafe methods which
allocated extra memory instead of directly streaming the data.
Brad King 16 years ago
parent
commit
dc13914cd6

+ 2 - 0
Source/CMakeLists.txt

@@ -213,6 +213,8 @@ SET(SRCS
   cmVersion.h
   cmVersion.h
   cmXMLParser.cxx
   cmXMLParser.cxx
   cmXMLParser.h
   cmXMLParser.h
+  cmXMLSafe.cxx
+  cmXMLSafe.h
   cmake.cxx
   cmake.cxx
   cmake.h
   cmake.h
   cmakewizard.cxx
   cmakewizard.cxx

+ 2 - 1
Source/CPack/cmCPackGenerator.cxx

@@ -24,6 +24,7 @@
 #include "cmLocalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
 #include "cmCPackComponentGroup.h"
 #include "cmCPackComponentGroup.h"
+#include "cmXMLSafe.h"
 
 
 #include <cmsys/SystemTools.hxx>
 #include <cmsys/SystemTools.hxx>
 #include <cmsys/Glob.hxx>
 #include <cmsys/Glob.hxx>
@@ -143,7 +144,7 @@ int cmCPackGenerator::PrepareNames()
       "Read description file: " << descFileName << std::endl);
       "Read description file: " << descFileName << std::endl);
     while ( ifs && cmSystemTools::GetLineFromStream(ifs, line) )
     while ( ifs && cmSystemTools::GetLineFromStream(ifs, line) )
       {
       {
-      ostr << cmSystemTools::MakeXMLSafe(line.c_str()) << std::endl;
+      ostr << cmXMLSafe(line) << std::endl;
       }
       }
     this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
     this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
     }
     }

+ 5 - 4
Source/CTest/cmCTestBuildHandler.cxx

@@ -23,6 +23,7 @@
 #include "cmLocalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmGlobalGenerator.h"
 #include "cmGlobalGenerator.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
+#include "cmXMLSafe.h"
 
 
 //#include <cmsys/RegularExpression.hxx>
 //#include <cmsys/RegularExpression.hxx>
 #include <cmsys/Process.h>
 #include <cmsys/Process.h>
@@ -490,7 +491,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os)
     static_cast<unsigned int>(this->StartBuildTime)
     static_cast<unsigned int>(this->StartBuildTime)
      << "</StartBuildTime>\n"
      << "</StartBuildTime>\n"
      << "<BuildCommand>"
      << "<BuildCommand>"
-     << this->CTest->MakeXMLSafe(
+     << cmXMLSafe(
        this->CTest->GetCTestConfiguration("MakeCommand"))
        this->CTest->GetCTestConfiguration("MakeCommand"))
      << "</BuildCommand>" << std::endl;
      << "</BuildCommand>" << std::endl;
 }
 }
@@ -526,7 +527,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
         }
         }
       os << "\t<" << (cm->Error ? "Error" : "Warning") << ">\n"
       os << "\t<" << (cm->Error ? "Error" : "Warning") << ">\n"
          << "\t\t<BuildLogLine>" << cm->LogLine << "</BuildLogLine>\n"
          << "\t\t<BuildLogLine>" << cm->LogLine << "</BuildLogLine>\n"
-         << "\t\t<Text>" << this->CTest->MakeXMLSafe(cm->Text)
+         << "\t\t<Text>" << cmXMLSafe(cm->Text).Quotes(false)
          << "\n</Text>" << std::endl;
          << "\n</Text>" << std::endl;
       std::vector<cmCTestCompileErrorWarningRex>::iterator rit;
       std::vector<cmCTestCompileErrorWarningRex>::iterator rit;
       for ( rit = this->ErrorWarningFileLineRegex.begin();
       for ( rit = this->ErrorWarningFileLineRegex.begin();
@@ -579,9 +580,9 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
             << "</SourceLineNumber>" << std::endl;
             << "</SourceLineNumber>" << std::endl;
           }
           }
         }
         }
-      os << "\t\t<PreContext>" << this->CTest->MakeXMLSafe(cm->PreContext)
+      os << "\t\t<PreContext>" << cmXMLSafe(cm->PreContext).Quotes(false)
          << "</PreContext>\n"
          << "</PreContext>\n"
-         << "\t\t<PostContext>" << this->CTest->MakeXMLSafe(cm->PostContext);
+         << "\t\t<PostContext>" << cmXMLSafe(cm->PostContext).Quotes(false);
       // is this the last warning or error, if so notify
       // is this the last warning or error, if so notify
       if (cm->Error && !numErrorsAllowed ||
       if (cm->Error && !numErrorsAllowed ||
           !cm->Error && !numWarningsAllowed)
           !cm->Error && !numWarningsAllowed)

+ 2 - 1
Source/CTest/cmCTestConfigureHandler.cxx

@@ -20,6 +20,7 @@
 #include "cmCTest.h"
 #include "cmCTest.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
 #include "cmake.h"
 #include "cmake.h"
+#include "cmXMLSafe.h"
 #include <cmsys/Process.h>
 #include <cmsys/Process.h>
 
 
 
 
@@ -106,7 +107,7 @@ int cmCTestConfigureHandler::ProcessHandler()
       os << "<ConfigureCommand>" << cCommand.c_str() << "</ConfigureCommand>"
       os << "<ConfigureCommand>" << cCommand.c_str() << "</ConfigureCommand>"
         << std::endl;
         << std::endl;
       cmCTestLog(this->CTest, DEBUG, "End" << std::endl);
       cmCTestLog(this->CTest, DEBUG, "End" << std::endl);
-      os << "<Log>" << cmCTest::MakeXMLSafe(output) << "</Log>" << std::endl;
+      os << "<Log>" << cmXMLSafe(output) << "</Log>" << std::endl;
       std::string end_time = this->CTest->CurrentTime();
       std::string end_time = this->CTest->CurrentTime();
       os << "\t<ConfigureStatus>" << retVal << "</ConfigureStatus>\n"
       os << "\t<ConfigureStatus>" << retVal << "</ConfigureStatus>\n"
          << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"
          << "\t<EndDateTime>" << end_time << "</EndDateTime>\n"

+ 12 - 11
Source/CTest/cmCTestCoverageHandler.cxx

@@ -19,6 +19,7 @@
 #include "cmake.h"
 #include "cmake.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
+#include "cmXMLSafe.h"
 
 
 #include <cmsys/Process.h>
 #include <cmsys/Process.h>
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/RegularExpression.hxx>
@@ -470,8 +471,8 @@ int cmCTestCoverageHandler::ProcessHandler()
     const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov
     const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov
       = fileIterator->second;
       = fileIterator->second;
     covLogFile << "\t<File Name=\""
     covLogFile << "\t<File Name=\""
-      << this->CTest->MakeXMLSafe(fileName.c_str())
-      << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
+      << cmXMLSafe(fileName)
+      << "\" FullPath=\"" << cmXMLSafe(
         this->CTest->GetShortPathToFile(
         this->CTest->GetShortPathToFile(
           fileIterator->first.c_str())) << "\">" << std::endl
           fileIterator->first.c_str())) << "\">" << std::endl
       << "\t\t<Report>" << std::endl;
       << "\t\t<Report>" << std::endl;
@@ -507,7 +508,7 @@ int cmCTestCoverageHandler::ProcessHandler()
         }
         }
       covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc]
       covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc]
         << "\">"
         << "\">"
-        << this->CTest->MakeXMLSafe(line.c_str()) << "</Line>" << std::endl;
+        << cmXMLSafe(line) << "</Line>" << std::endl;
       if ( fcov[cc] == 0 )
       if ( fcov[cc] == 0 )
         {
         {
         untested ++;
         untested ++;
@@ -536,8 +537,8 @@ int cmCTestCoverageHandler::ProcessHandler()
     total_untested += untested;
     total_untested += untested;
     covLogFile << "\t\t</Report>" << std::endl
     covLogFile << "\t\t</Report>" << std::endl
       << "\t</File>" << std::endl;
       << "\t</File>" << std::endl;
-    covSumFile << "\t<File Name=\"" << this->CTest->MakeXMLSafe(fileName)
-      << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
+    covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName)
+      << "\" FullPath=\"" << cmXMLSafe(
         this->CTest->GetShortPathToFile(fullFileName.c_str()))
         this->CTest->GetShortPathToFile(fullFileName.c_str()))
       << "\" Covered=\"" << (tested > 0 ? "true":"false") << "\">\n"
       << "\" Covered=\"" << (tested > 0 ? "true":"false") << "\">\n"
       << "\t\t<LOCTested>" << tested << "</LOCTested>\n"
       << "\t\t<LOCTested>" << tested << "</LOCTested>\n"
@@ -1329,8 +1330,8 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
                    << std::endl);
                    << std::endl);
         // start the file output
         // start the file output
         covLogFile << "\t<File Name=\""
         covLogFile << "\t<File Name=\""
-                   << this->CTest->MakeXMLSafe(i->first.c_str())
-                   << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
+                   << cmXMLSafe(i->first)
+                   << "\" FullPath=\"" << cmXMLSafe(
                      this->CTest->GetShortPathToFile(
                      this->CTest->GetShortPathToFile(
                        i->second.c_str())) << "\">" << std::endl
                        i->second.c_str())) << "\">" << std::endl
                    << "\t\t<Report>" << std::endl;
                    << "\t\t<Report>" << std::endl;
@@ -1339,7 +1340,7 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
         for(int k =0; bullseyeHelp[k] != 0; ++k)
         for(int k =0; bullseyeHelp[k] != 0; ++k)
           {
           {
           covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
           covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
-                     << this->CTest->MakeXMLSafe(bullseyeHelp[k]) 
+                     << cmXMLSafe(bullseyeHelp[k])
                      << "</Line>" << std::endl;
                      << "</Line>" << std::endl;
           line++;
           line++;
           }
           }
@@ -1355,7 +1356,7 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
     else if(valid)
     else if(valid)
       {
       {
       covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
       covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">"
-                 << this->CTest->MakeXMLSafe(lineIn.c_str()) 
+                 << cmXMLSafe(lineIn)
                  << "</Line>" << std::endl;
                  << "</Line>" << std::endl;
       line++;
       line++;
       }
       }
@@ -1561,8 +1562,8 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
       tmpLog << "percentBranch: " << percentBranch << "\n";
       tmpLog << "percentBranch: " << percentBranch << "\n";
       tmpLog << "percentCoverage: " << percent_coverage << "\n";
       tmpLog << "percentCoverage: " << percent_coverage << "\n";
       tmpLog << "coverage metric: " << cmet << "\n";
       tmpLog << "coverage metric: " << cmet << "\n";
-      covSumFile << "\t<File Name=\"" << this->CTest->MakeXMLSafe(sourceFile)
-                 << "\" FullPath=\"" << this->CTest->MakeXMLSafe(
+      covSumFile << "\t<File Name=\"" << cmXMLSafe(sourceFile)
+                 << "\" FullPath=\"" << cmXMLSafe(
                    this->CTest->GetShortPathToFile(file.c_str()))
                    this->CTest->GetShortPathToFile(file.c_str()))
                  << "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n"
                  << "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n"
                  << "\t\t<BranchesTested>"
                  << "\t\t<BranchesTested>"

+ 8 - 7
Source/CTest/cmCTestMemCheckHandler.cxx

@@ -24,6 +24,7 @@
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/Base64.h>
 #include <cmsys/Base64.h>
 #include "cmMakefile.h"
 #include "cmMakefile.h"
+#include "cmXMLSafe.h"
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <math.h>
 #include <math.h>
@@ -77,8 +78,8 @@ public:
       int i = 0;
       int i = 0;
       for(; atts[i] != 0; i+=2)
       for(; atts[i] != 0; i+=2)
         {
         {
-        ostr << "   " << this->CTest->MakeXMLSafe(atts[i]).c_str() 
-             << " - " << this->CTest->MakeXMLSafe(atts[i+1]).c_str() << "\n";
+        ostr << "   " << cmXMLSafe(atts[i])
+             << " - " << cmXMLSafe(atts[i+1]) << "\n";
         }
         }
       ostr << "\n";
       ostr << "\n";
       this->Log += ostr.str();
       this->Log += ostr.str();
@@ -313,7 +314,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
     {
     {
     cmCTestTestResult *result = &this->TestResults[cc];
     cmCTestTestResult *result = &this->TestResults[cc];
     std::string testPath = result->Path + "/" + result->Name;
     std::string testPath = result->Path + "/" + result->Name;
-    os << "\t\t<Test>" << cmCTest::MakeXMLSafe(
+    os << "\t\t<Test>" << cmXMLSafe(
       this->CTest->GetShortPathToFile(testPath.c_str()))
       this->CTest->GetShortPathToFile(testPath.c_str()))
       << "</Test>" << std::endl;
       << "</Test>" << std::endl;
     }
     }
@@ -610,7 +611,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
       results[failure] ++;
       results[failure] ++;
       defects ++;
       defects ++;
       }
       }
-    ostr << cmCTest::MakeXMLSafe(*i) << std::endl;
+    ostr << cmXMLSafe(*i) << std::endl;
     }
     }
 
 
   log = ostr.str();
   log = ostr.str();
@@ -750,7 +751,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
         defects ++;
         defects ++;
         }
         }
       totalOutputSize += lines[cc].size();
       totalOutputSize += lines[cc].size();
-      ostr << cmCTest::MakeXMLSafe(lines[cc]) << std::endl;
+      ostr << cmXMLSafe(lines[cc]) << std::endl;
       } 
       } 
     else
     else
       {
       {
@@ -767,9 +768,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
       cmCTestLog(this->CTest, DEBUG, "before xml safe "
       cmCTestLog(this->CTest, DEBUG, "before xml safe "
                  << lines[*i] << std::endl);
                  << lines[*i] << std::endl);
       cmCTestLog(this->CTest, DEBUG, "after  xml safe "
       cmCTestLog(this->CTest, DEBUG, "after  xml safe "
-                 <<  cmCTest::MakeXMLSafe(lines[*i]) << std::endl);
+                 <<  cmXMLSafe(lines[*i]) << std::endl);
 
 
-      ostr << cmCTest::MakeXMLSafe(lines[*i]) << std::endl;
+      ostr << cmXMLSafe(lines[*i]) << std::endl;
       if(!unlimitedOutput && totalOutputSize > 
       if(!unlimitedOutput && totalOutputSize > 
          static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
          static_cast<size_t>(this->CustomMaximumFailedTestOutputSize))
         {
         {

+ 12 - 11
Source/CTest/cmCTestTestHandler.cxx

@@ -28,6 +28,7 @@
 #include "cmLocalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmCommand.h"
 #include "cmCommand.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
+#include "cmXMLSafe.h"
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <math.h>
 #include <math.h>
@@ -1464,7 +1465,7 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
     {
     {
     cmCTestTestResult *result = &this->TestResults[cc];
     cmCTestTestResult *result = &this->TestResults[cc];
     std::string testPath = result->Path + "/" + result->Name;
     std::string testPath = result->Path + "/" + result->Name;
-    os << "\t\t<Test>" << cmCTest::MakeXMLSafe(
+    os << "\t\t<Test>" << cmXMLSafe(
       this->CTest->GetShortPathToFile(testPath.c_str()))
       this->CTest->GetShortPathToFile(testPath.c_str()))
       << "</Test>" << std::endl;
       << "</Test>" << std::endl;
     }
     }
@@ -1481,7 +1482,7 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
         {
         {
         os << "\t\t\t<NamedMeasurement type=\"text/string\" "
         os << "\t\t\t<NamedMeasurement type=\"text/string\" "
           "name=\"Exit Code\"><Value>"
           "name=\"Exit Code\"><Value>"
-          << cmCTest::MakeXMLSafe(this->GetTestStatus(result->Status))
+          << cmXMLSafe(this->GetTestStatus(result->Status))
           << "</Value>"
           << "</Value>"
           "</NamedMeasurement>\n"
           "</NamedMeasurement>\n"
           << "\t\t\t<NamedMeasurement type=\"text/string\" "
           << "\t\t\t<NamedMeasurement type=\"text/string\" "
@@ -1498,13 +1499,13 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
       os
       os
         << "\t\t\t<NamedMeasurement type=\"text/string\" "
         << "\t\t\t<NamedMeasurement type=\"text/string\" "
         << "name=\"Completion Status\"><Value>"
         << "name=\"Completion Status\"><Value>"
-        << cmCTest::MakeXMLSafe(result->CompletionStatus)
+        << cmXMLSafe(result->CompletionStatus)
         << "</Value></NamedMeasurement>\n";
         << "</Value></NamedMeasurement>\n";
       }
       }
     os
     os
       << "\t\t\t<NamedMeasurement type=\"text/string\" "
       << "\t\t\t<NamedMeasurement type=\"text/string\" "
       << "name=\"Command Line\"><Value>"
       << "name=\"Command Line\"><Value>"
-      << cmCTest::MakeXMLSafe(result->FullCommandLine)
+      << cmXMLSafe(result->FullCommandLine)
       << "</Value></NamedMeasurement>\n";
       << "</Value></NamedMeasurement>\n";
     std::map<cmStdString,cmStdString>::iterator measureIt;
     std::map<cmStdString,cmStdString>::iterator measureIt;
     for ( measureIt = result->Properties->Measurements.begin();
     for ( measureIt = result->Properties->Measurements.begin();
@@ -1514,13 +1515,13 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
       os
       os
         << "\t\t\t<NamedMeasurement type=\"text/string\" "
         << "\t\t\t<NamedMeasurement type=\"text/string\" "
         << "name=\"" << measureIt->first.c_str() << "\"><Value>"
         << "name=\"" << measureIt->first.c_str() << "\"><Value>"
-        << cmCTest::MakeXMLSafe(measureIt->second.c_str())
+        << cmXMLSafe(measureIt->second)
         << "</Value></NamedMeasurement>\n";
         << "</Value></NamedMeasurement>\n";
       }
       }
     os
     os
       << "\t\t\t<Measurement>\n"
       << "\t\t\t<Measurement>\n"
       << "\t\t\t\t<Value>";
       << "\t\t\t\t<Value>";
-    os << cmCTest::MakeXMLSafe(result->Output);
+    os << cmXMLSafe(result->Output);
     os
     os
       << "</Value>\n"
       << "</Value>\n"
       << "\t\t\t</Measurement>\n"
       << "\t\t\t</Measurement>\n"
@@ -1556,13 +1557,13 @@ void cmCTestTestHandler::WriteTestResultHeader(std::ostream& os,
     }
     }
   std::string testPath = result->Path + "/" + result->Name;
   std::string testPath = result->Path + "/" + result->Name;
   os << "\">\n"
   os << "\">\n"
-     << "\t\t<Name>" << cmCTest::MakeXMLSafe(result->Name) << "</Name>\n"
-     << "\t\t<Path>" << cmCTest::MakeXMLSafe(
+     << "\t\t<Name>" << cmXMLSafe(result->Name) << "</Name>\n"
+     << "\t\t<Path>" << cmXMLSafe(
        this->CTest->GetShortPathToFile(result->Path.c_str())) << "</Path>\n"
        this->CTest->GetShortPathToFile(result->Path.c_str())) << "</Path>\n"
-     << "\t\t<FullName>" << cmCTest::MakeXMLSafe(
+     << "\t\t<FullName>" << cmXMLSafe(
        this->CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
        this->CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n"
      << "\t\t<FullCommandLine>"
      << "\t\t<FullCommandLine>"
-     << cmCTest::MakeXMLSafe(result->FullCommandLine)
+     << cmXMLSafe(result->FullCommandLine)
      << "</FullCommandLine>\n";
      << "</FullCommandLine>\n";
 }
 }
 
 
@@ -1577,7 +1578,7 @@ void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os,
     for(std::vector<std::string>::const_iterator li = labels.begin();
     for(std::vector<std::string>::const_iterator li = labels.begin();
         li != labels.end(); ++li)
         li != labels.end(); ++li)
       {
       {
-      os << "\t\t\t<Label>" << cmCTest::MakeXMLSafe(*li) << "</Label>\n";
+      os << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n";
       }
       }
     os << "\t\t</Labels>\n";
     os << "\t\t</Labels>\n";
     }
     }

+ 20 - 19
Source/CTest/cmCTestUpdateHandler.cxx

@@ -25,6 +25,7 @@
 #include "cmVersion.h"
 #include "cmVersion.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
 #include "cmXMLParser.h"
 #include "cmXMLParser.h"
+#include "cmXMLSafe.h"
 
 
 //#include <cmsys/RegularExpression.hxx>
 //#include <cmsys/RegularExpression.hxx>
 #include <cmsys/Process.h>
 #include <cmsys/Process.h>
@@ -653,9 +654,9 @@ int cmCTestUpdateHandler::ProcessHandler()
     << this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
     << this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl;
   os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
   os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n"
     << "\t<StartTime>" << start_time_time << "</StartTime>\n"
     << "\t<StartTime>" << start_time_time << "</StartTime>\n"
-    << "\t<UpdateCommand>" << this->CTest->MakeXMLSafe(command)
+    << "\t<UpdateCommand>" << cmXMLSafe(command)
     << "</UpdateCommand>\n"
     << "</UpdateCommand>\n"
-    << "\t<UpdateType>" << this->CTest->MakeXMLSafe(
+    << "\t<UpdateType>" << cmXMLSafe(
       cmCTestUpdateHandlerUpdateToString(updateType))
       cmCTestUpdateHandlerUpdateToString(updateType))
     << "</UpdateType>\n";
     << "</UpdateType>\n";
 
 
@@ -1009,17 +1010,17 @@ int cmCTestUpdateHandler::ProcessHandler()
           << path.c_str() << " / " << fname.c_str() << " was updated by "
           << path.c_str() << " / " << fname.c_str() << " was updated by "
           << sauthor1.c_str() << " to revision: " << srevision1.c_str()
           << sauthor1.c_str() << " to revision: " << srevision1.c_str()
           << " from revision: " << srevision2.c_str() << std::endl);
           << " from revision: " << srevision2.c_str() << std::endl);
-        os << "\t\t<File Directory=\"" << cmCTest::MakeXMLSafe(path) << "\">"
-          << cmCTest::MakeXMLSafe(fname)
+        os << "\t\t<File Directory=\"" << cmXMLSafe(path) << "\">"
+          << cmXMLSafe(fname)
           << "</File>\n"
           << "</File>\n"
-          << "\t\t<Directory>" << cmCTest::MakeXMLSafe(path)
+          << "\t\t<Directory>" << cmXMLSafe(path)
           << "</Directory>\n"
           << "</Directory>\n"
-          << "\t\t<FullName>" << cmCTest::MakeXMLSafe(file) << "</FullName>\n"
-          << "\t\t<CheckinDate>" << cmCTest::MakeXMLSafe(sdate1)
+          << "\t\t<FullName>" << cmXMLSafe(file) << "</FullName>\n"
+          << "\t\t<CheckinDate>" << cmXMLSafe(sdate1)
           << "</CheckinDate>\n"
           << "</CheckinDate>\n"
-          << "\t\t<Author>" << cmCTest::MakeXMLSafe(sauthor1) << "</Author>\n"
-          << "\t\t<Email>" << cmCTest::MakeXMLSafe(semail1) << "</Email>\n"
-          << "\t\t<Log>" << cmCTest::MakeXMLSafe(comment1) << "</Log>\n"
+          << "\t\t<Author>" << cmXMLSafe(sauthor1) << "</Author>\n"
+          << "\t\t<Email>" << cmXMLSafe(semail1) << "</Email>\n"
+          << "\t\t<Log>" << cmXMLSafe(comment1) << "</Log>\n"
           << "\t\t<Revision>" << srevision1 << "</Revision>\n"
           << "\t\t<Revision>" << srevision1 << "</Revision>\n"
           << "\t\t<PriorRevision>" << srevision2 << "</PriorRevision>"
           << "\t\t<PriorRevision>" << srevision2 << "</PriorRevision>"
           << std::endl;
           << std::endl;
@@ -1030,26 +1031,26 @@ int cmCTestUpdateHandler::ProcessHandler()
             << "\t\t\t<Revision>" << srevision1 << "</Revision>\n"
             << "\t\t\t<Revision>" << srevision1 << "</Revision>\n"
             << "\t\t\t<PreviousRevision>" << srevision2
             << "\t\t\t<PreviousRevision>" << srevision2
             << "</PreviousRevision>\n"
             << "</PreviousRevision>\n"
-            << "\t\t\t<Author>" << cmCTest::MakeXMLSafe(sauthor1)
+            << "\t\t\t<Author>" << cmXMLSafe(sauthor1)
             << "</Author>\n"
             << "</Author>\n"
-            << "\t\t\t<Date>" << cmCTest::MakeXMLSafe(sdate1)
+            << "\t\t\t<Date>" << cmXMLSafe(sdate1)
             << "</Date>\n"
             << "</Date>\n"
-            << "\t\t\t<Comment>" << cmCTest::MakeXMLSafe(comment1)
+            << "\t\t\t<Comment>" << cmXMLSafe(comment1)
             << "</Comment>\n"
             << "</Comment>\n"
-            << "\t\t\t<Email>" << cmCTest::MakeXMLSafe(semail1)
+            << "\t\t\t<Email>" << cmXMLSafe(semail1)
             << "</Email>\n"
             << "</Email>\n"
             << "\t\t</Revisions>\n"
             << "\t\t</Revisions>\n"
             << "\t\t<Revisions>\n"
             << "\t\t<Revisions>\n"
             << "\t\t\t<Revision>" << srevision2 << "</Revision>\n"
             << "\t\t\t<Revision>" << srevision2 << "</Revision>\n"
             << "\t\t\t<PreviousRevision>" << srevision2
             << "\t\t\t<PreviousRevision>" << srevision2
             << "</PreviousRevision>\n"
             << "</PreviousRevision>\n"
-            << "\t\t\t<Author>" << cmCTest::MakeXMLSafe(sauthor2)
+            << "\t\t\t<Author>" << cmXMLSafe(sauthor2)
             << "</Author>\n"
             << "</Author>\n"
-            << "\t\t\t<Date>" << cmCTest::MakeXMLSafe(sdate2)
+            << "\t\t\t<Date>" << cmXMLSafe(sdate2)
             << "</Date>\n"
             << "</Date>\n"
-            << "\t\t\t<Comment>" << cmCTest::MakeXMLSafe(comment2)
+            << "\t\t\t<Comment>" << cmXMLSafe(comment2)
             << "</Comment>\n"
             << "</Comment>\n"
-            << "\t\t\t<Email>" << cmCTest::MakeXMLSafe(semail2)
+            << "\t\t\t<Email>" << cmXMLSafe(semail2)
             << "</Email>\n"
             << "</Email>\n"
             << "\t\t</Revisions>" << std::endl;
             << "\t\t</Revisions>" << std::endl;
           }
           }
@@ -1147,7 +1148,7 @@ int cmCTestUpdateHandler::ProcessHandler()
   if ( updateProducedError )
   if ( updateProducedError )
     {
     {
     os << "Update error: ";
     os << "Update error: ";
-    os << this->CTest->MakeXMLSafe(checkoutErrorMessages);
+    os << cmXMLSafe(checkoutErrorMessages);
     cmCTestLog(this->CTest, ERROR_MESSAGE, "   Update with command: "
     cmCTestLog(this->CTest, ERROR_MESSAGE, "   Update with command: "
       << command << " failed" << std::endl);
       << command << " failed" << std::endl);
     }
     }

+ 4 - 55
Source/cmCTest.cxx

@@ -25,6 +25,7 @@
 #include <cmsys/SystemInformation.hxx>
 #include <cmsys/SystemInformation.hxx>
 #include "cmDynamicLoader.h"
 #include "cmDynamicLoader.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
+#include "cmXMLSafe.h"
 #include "cmCTestCommand.h"
 #include "cmCTestCommand.h"
 
 
 #include "cmCTestBuildHandler.h"
 #include "cmCTestBuildHandler.h"
@@ -149,59 +150,7 @@ std::string cmCTest::CurrentTime()
     strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t);
     strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t);
     }
     }
   cmCTestLog(this, DEBUG, "   Current_Time: " << current_time << std::endl);
   cmCTestLog(this, DEBUG, "   Current_Time: " << current_time << std::endl);
-  return cmCTest::MakeXMLSafe(cmCTest::CleanString(current_time));
-}
-
-
-//----------------------------------------------------------------------
-std::string cmCTest::MakeXMLSafe(const std::string& str)
-{
-  std::vector<char> result;
-  result.reserve(500);
-  const char* pos = str.c_str();
-  for ( ;*pos; ++pos)
-    {
-    char ch = *pos;
-    if ( (ch > 126 || ch < 32) && ch != 9  &&
-      ch != 10 && ch != 13 && ch != '\r' )
-      {
-      char buffer[33];
-      sprintf(buffer, "&lt;%d&gt;", (int)ch);
-      //sprintf(buffer, "&#x%0x;", (unsigned int)ch);
-      result.insert(result.end(), buffer, buffer+strlen(buffer));
-      }
-    else
-      {
-      const char* const encodedChars[] = {
-        "&amp;",
-        "&lt;",
-        "&gt;"
-      };
-      switch ( ch )
-        {
-        case '&':
-          result.insert(result.end(), encodedChars[0], encodedChars[0]+5);
-          break;
-        case '<':
-          result.insert(result.end(), encodedChars[1], encodedChars[1]+4);
-          break;
-        case '>':
-          result.insert(result.end(), encodedChars[2], encodedChars[2]+4);
-          break;
-        case '\n':
-          result.push_back('\n');
-          break;
-        case '\r': break; // Ignore \r
-        default:
-          result.push_back(ch);
-        }
-      }
-    }
-  if ( result.size() == 0 )
-    {
-    return "";
-    }
-  return std::string(&*result.begin(), result.size());
+  return cmXMLSafe(cmCTest::CleanString(current_time)).str();
 }
 }
 
 
 //----------------------------------------------------------------------
 //----------------------------------------------------------------------
@@ -1386,7 +1335,7 @@ int cmCTest::GenerateCTestNotesOutput(std::ostream& os,
     {
     {
     cmCTestLog(this, OUTPUT, "\tAdd file: " << it->c_str() << std::endl);
     cmCTestLog(this, OUTPUT, "\tAdd file: " << it->c_str() << std::endl);
     std::string note_time = this->CurrentTime();
     std::string note_time = this->CurrentTime();
-    os << "<Note Name=\"" << this->MakeXMLSafe(it->c_str()) << "\">\n"
+    os << "<Note Name=\"" << cmXMLSafe(*it) << "\">\n"
       << "<Time>" << cmSystemTools::GetTime() << "</Time>\n"
       << "<Time>" << cmSystemTools::GetTime() << "</Time>\n"
       << "<DateTime>" << note_time << "</DateTime>\n"
       << "<DateTime>" << note_time << "</DateTime>\n"
       << "<Text>" << std::endl;
       << "<Text>" << std::endl;
@@ -1396,7 +1345,7 @@ int cmCTest::GenerateCTestNotesOutput(std::ostream& os,
       std::string line;
       std::string line;
       while ( cmSystemTools::GetLineFromStream(ifs, line) )
       while ( cmSystemTools::GetLineFromStream(ifs, line) )
         {
         {
-        os << this->MakeXMLSafe(line) << std::endl;
+        os << cmXMLSafe(line) << std::endl;
         }
         }
       ifs.close();
       ifs.close();
       }
       }

+ 0 - 3
Source/cmCTest.h

@@ -200,9 +200,6 @@ public:
                       cmGeneratedFileStream& stream,
                       cmGeneratedFileStream& stream,
                       bool compress = false);
                       bool compress = false);
 
 
-  ///! Convert string to something that is XML safe
-  static std::string MakeXMLSafe(const std::string&);
-
   ///! Should we only show what we would do?
   ///! Should we only show what we would do?
   bool GetShowOnly();
   bool GetShowOnly();
 
 

+ 0 - 50
Source/cmSystemTools.cxx

@@ -1644,56 +1644,6 @@ void cmSystemTools::EnableVSConsoleOutput()
 #endif
 #endif
 }
 }
 
 
-std::string cmSystemTools::MakeXMLSafe(const char* str)
-{
-  std::vector<char> result;
-  result.reserve(500);
-  const char* pos = str;
-  for ( ;*pos; ++pos)
-    {
-    char ch = *pos;
-    if ( (ch > 126 || ch < 32) && ch != 9  && ch != 10 && ch != 13 
-         && ch != '\r' )
-      {
-      char buffer[33];
-      sprintf(buffer, "&lt;%d&gt;", static_cast<int>(ch));
-      //sprintf(buffer, "&#x%0x;", (unsigned int)ch);
-      result.insert(result.end(), buffer, buffer+strlen(buffer));
-      }
-    else
-      {
-      const char* const encodedChars[] = {
-        "&amp;",
-        "&lt;",
-        "&gt;"
-      };
-      switch ( ch )
-        {
-        case '&':
-          result.insert(result.end(), encodedChars[0], encodedChars[0]+5);
-          break;
-        case '<':
-          result.insert(result.end(), encodedChars[1], encodedChars[1]+4);
-          break;
-        case '>':
-          result.insert(result.end(), encodedChars[2], encodedChars[2]+4);
-          break;
-        case '\n':
-          result.push_back('\n');
-          break;
-        case '\r': break; // Ignore \r
-        default:
-          result.push_back(ch);
-        }
-      }
-    }
-  if ( result.size() == 0 )
-    {
-    return "";
-    }
-  return std::string(&*result.begin(), result.size());
-}
-
 bool cmSystemTools::IsPathToFramework(const char* path)
 bool cmSystemTools::IsPathToFramework(const char* path)
 {
 {
   if(cmSystemTools::FileIsFullPath(path))
   if(cmSystemTools::FileIsFullPath(path))

+ 0 - 3
Source/cmSystemTools.h

@@ -351,9 +351,6 @@ public:
   /** Setup the environment to enable VS 8 IDE output.  */
   /** Setup the environment to enable VS 8 IDE output.  */
   static void EnableVSConsoleOutput();
   static void EnableVSConsoleOutput();
 
 
-  /** Make string XML safe */
-  static std::string MakeXMLSafe(const char* str);
-
   /** Create tar */
   /** Create tar */
   static bool ListTar(const char* outFileName,
   static bool ListTar(const char* outFileName,
                       std::vector<cmStdString>& files, 
                       std::vector<cmStdString>& files, 

+ 93 - 0
Source/cmXMLSafe.cxx

@@ -0,0 +1,93 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmXMLSafe.h"
+
+#include <cmsys/ios/iostream>
+#include <cmsys/ios/sstream>
+
+#include <string.h>
+#include <stdio.h>
+
+//----------------------------------------------------------------------------
+cmXMLSafe::cmXMLSafe(const char* s):
+  Data(s),
+  Size(static_cast<unsigned long>(strlen(s))),
+  DoQuotes(true)
+{
+}
+
+//----------------------------------------------------------------------------
+cmXMLSafe::cmXMLSafe(cmsys_stl::string const& str):
+    Data(str.c_str()),
+    Size(static_cast<unsigned long>(str.length())),
+    DoQuotes(true)
+{
+}
+
+//----------------------------------------------------------------------------
+cmXMLSafe& cmXMLSafe::Quotes(bool b)
+{
+  this->DoQuotes = b;
+  return *this;
+}
+
+//----------------------------------------------------------------------------
+cmsys_stl::string cmXMLSafe::str()
+{
+  cmsys_ios::ostringstream ss;
+  ss << *this;
+  return ss.str();
+}
+
+//----------------------------------------------------------------------------
+cmsys_ios::ostream& operator<<(cmsys_ios::ostream& os, cmXMLSafe const& self)
+{
+  char const* first = self.Data;
+  char const* last = self.Data + self.Size;
+  for(char const* ci = first; ci != last; ++ci)
+    {
+    char c = *ci;
+    switch(c)
+      {
+      case '&': os << "&amp;"; break;
+      case '<': os << "&lt;"; break;
+      case '>': os << "&gt;"; break;
+      case '"': os << (self.DoQuotes? "&quot;" : "\""); break;
+      case '\'': os << (self.DoQuotes? "&apos;" : "'"); break;
+      case '\t': os << "\t"; break;
+      case '\n': os << "\n"; break;
+      case '\r': break; // Ignore CR
+      default:
+        if(c >= 0x20 && c <= 0x7f)
+          {
+          os.put(c);
+          }
+        else
+          {
+          // TODO: More complete treatment of program output character
+          // encoding.  Instead of escaping these bytes, we should
+          // handle the current locale and its encoding.
+          unsigned char uc = static_cast<unsigned char>(c);
+          char buf[16];
+          sprintf(buf, "&#x%hx;", static_cast<unsigned short>(uc));
+          os << buf;
+          }
+        break;
+      }
+    }
+  return os;
+}

+ 49 - 0
Source/cmXMLSafe.h

@@ -0,0 +1,49 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmXMLSafe_h
+#define cmXMLSafe_h
+
+#include <cmsys/stl/string>
+#include <cmsys/ios/iosfwd>
+
+/** \class cmXMLSafe
+ * \brief Write strings to XML with proper escapes
+ */
+class cmXMLSafe
+{
+public:
+  /** Construct with the data to be written.  This assumes the data
+      will exist for the duration of this object's life.  */
+  cmXMLSafe(const char* s);
+  cmXMLSafe(cmsys_stl::string const& str);
+
+  /** Specify whether to escape quotes too.  This is needed when
+      writing the content of an attribute value.  By default quotes
+      are escaped.  */
+  cmXMLSafe& Quotes(bool b = true);
+
+  /** Get the escaped data as a string.  */
+  cmsys_stl::string str();
+private:
+  char const* Data;
+  unsigned long Size;
+  bool DoQuotes;
+  friend cmsys_ios::ostream& operator<<(cmsys_ios::ostream&,
+                                        cmXMLSafe const&);
+};
+
+#endif