CPack/DragNDrop: Fix handling of certain license file content (#15899)

There were issues in the special-character-escaping and line-wrapping
code which caused DragNDrop packaging to fail mysteriously at a later
step with parsing errors in the `sla.r` file generated by the following
code.
This commit is contained in:
Andrey Mishchenko 2016-01-02 16:11:00 -05:00 committed by Brad King
parent 5112da5c2f
commit bbb3c4ffc1
2 changed files with 77 additions and 25 deletions

View File

@ -693,27 +693,49 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
ofs << std::dec << std::nouppercase << std::setfill(' '); ofs << std::dec << std::nouppercase << std::setfill(' ');
} }
bool have_write_license_error = false;
std::string error;
if(oldStyle) if(oldStyle)
{ {
WriteLicense(ofs, 0, "", cpack_license_file); if(!this->WriteLicense(ofs, 0, "", cpack_license_file, &error))
{
have_write_license_error = true;
}
} }
else else
{ {
for(size_t i = 0; i < languages.size(); ++i) for(size_t i = 0; i < languages.size() && !have_write_license_error; ++i)
{ {
if(singleLicense) if(singleLicense)
{ {
WriteLicense(ofs, i + 5000, languages[i], cpack_license_file); if(!this->WriteLicense(ofs, i + 5000, languages[i],
cpack_license_file, &error))
{
have_write_license_error = true;
}
} }
else else
{ {
WriteLicense(ofs, i + 5000, languages[i]); if(!this->WriteLicense(ofs, i + 5000, languages[i], "", &error))
{
have_write_license_error = true;
}
} }
} }
} }
ofs.Close(); ofs.Close();
if(have_write_license_error)
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error writing license file to SLA." << std::endl
<< error
<< std::endl);
return 0;
}
// convert to UDCO // convert to UDCO
std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
temp_udco += "/temp-udco.dmg"; temp_udco += "/temp-udco.dmg";
@ -724,7 +746,6 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
udco_image_command << " -format UDCO"; udco_image_command << " -format UDCO";
udco_image_command << " -ov -o \"" << temp_udco << "\""; udco_image_command << " -ov -o \"" << temp_udco << "\"";
std::string error;
if(!this->RunCommand(udco_image_command, &error)) if(!this->RunCommand(udco_image_command, &error))
{ {
cmCPackLogger(cmCPackLog::LOG_ERROR, cmCPackLogger(cmCPackLog::LOG_ERROR,
@ -855,9 +876,10 @@ cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
return GetComponentPackageFileName(package_file_name, componentName, false); return GetComponentPackageFileName(package_file_name, componentName, false);
} }
void bool
cmCPackDragNDropGenerator::WriteLicense(cmGeneratedFileStream& outputStream, cmCPackDragNDropGenerator::WriteLicense(cmGeneratedFileStream& outputStream,
int licenseNumber, std::string licenseLanguage, std::string licenseFile) int licenseNumber, std::string licenseLanguage, std::string licenseFile,
std::string *error)
{ {
if(!licenseFile.empty() && !singleLicense) if(!licenseFile.empty() && !singleLicense)
{ {
@ -881,9 +903,12 @@ cmCPackDragNDropGenerator::WriteLicense(cmGeneratedFileStream& outputStream,
std::getline(license_ifs, line); std::getline(license_ifs, line);
if(!line.empty()) if(!line.empty())
{ {
EscapeQuotes(line); EscapeQuotesAndBackslashes(line);
std::vector<std::string> lines; std::vector<std::string> lines;
BreakLongLine(line, lines); if(!this->BreakLongLine(line, lines, error))
{
return false;
}
for(size_t i = 0; i < lines.size(); ++i) for(size_t i = 0; i < lines.size(); ++i)
{ {
outputStream << " \"" << lines[i] << "\"\n"; outputStream << " \"" << lines[i] << "\"\n";
@ -920,9 +945,12 @@ cmCPackDragNDropGenerator::WriteLicense(cmGeneratedFileStream& outputStream,
std::getline(menu_ifs, line); std::getline(menu_ifs, line);
if(!line.empty()) if(!line.empty())
{ {
EscapeQuotes(line); EscapeQuotesAndBackslashes(line);
std::vector<std::string> lines; std::vector<std::string> lines;
BreakLongLine(line, lines); if(!this->BreakLongLine(line, lines, error))
{
return false;
}
for(size_t i = 0; i < lines.size(); ++i) for(size_t i = 0; i < lines.size(); ++i)
{ {
std::string comma; std::string comma;
@ -949,31 +977,53 @@ cmCPackDragNDropGenerator::WriteLicense(cmGeneratedFileStream& outputStream,
outputStream << "};\n"; outputStream << "};\n";
outputStream << "\n"; outputStream << "\n";
} }
return true;
} }
void bool
cmCPackDragNDropGenerator::BreakLongLine(const std::string& line, cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
std::vector<std::string>& lines) std::vector<std::string>& lines, std::string *error)
{ {
const size_t max_line_length = 512; const size_t max_line_length = 512;
for(size_t i = 0; i < line.size(); i += max_line_length) for(size_t i = 0; i < line.size(); i += max_line_length)
{ {
int line_length = max_line_length; size_t line_length = max_line_length;
if(i + max_line_length > line.size()) if(i + line_length > line.size())
{ {
line_length = line.size() - i; line_length = line.size() - i;
} }
else while(line_length > 0 && line[i + line_length - 1] != ' ')
{
line_length = line_length - 1;
}
if(line_length == 0)
{
*error = "Please make sure there are no words "
"(or character sequences not broken up by spaces or newlines) "
"in your license file which are more than 512 characters long.";
return false;
}
lines.push_back(line.substr(i, line_length)); lines.push_back(line.substr(i, line_length));
} }
return true;
} }
void void
cmCPackDragNDropGenerator::EscapeQuotes(std::string& line) cmCPackDragNDropGenerator::EscapeQuotesAndBackslashes(std::string& line)
{ {
std::string::size_type pos = line.find('\"'); std::string::size_type backslash_pos = line.find('\\');
while(pos != std::string::npos) while(backslash_pos != std::string::npos)
{ {
line.replace(pos, 1, "\\\""); line.replace(backslash_pos, 1, "\\\\");
pos = line.find('\"', pos + 2); backslash_pos = line.find('\\', backslash_pos + 2);
}
std::string::size_type quote_pos = line.find('\"');
while(quote_pos != std::string::npos)
{
line.replace(quote_pos, 1, "\\\"");
quote_pos = line.find('\"', quote_pos + 2);
} }
} }

View File

@ -50,11 +50,13 @@ private:
std::string slaDirectory; std::string slaDirectory;
bool singleLicense; bool singleLicense;
void WriteLicense(cmGeneratedFileStream& outputStream, int licenseNumber, bool WriteLicense(cmGeneratedFileStream& outputStream, int licenseNumber,
std::string licenseLanguage, std::string licenseFile = ""); std::string licenseLanguage, std::string licenseFile,
void BreakLongLine(const std::string& line, std::string *error);
std::vector<std::string>& lines); bool BreakLongLine(const std::string& line,
void EscapeQuotes(std::string& line); std::vector<std::string>& lines,
std::string *error);
void EscapeQuotesAndBackslashes(std::string& line);
}; };
#endif #endif