cmake/Source/CPack/WiX/cmWIXSourceWriter.cxx

217 lines
5.2 KiB
C++
Raw Normal View History

2013-03-16 19:13:01 +02:00
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2012 Kitware, Inc.
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "cmWIXSourceWriter.h"
#include <CPack/cmCPackGenerator.h>
#include <windows.h>
cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
2016-07-09 11:21:54 +02:00
std::string const& filename,
bool isIncludeFile)
: Logger(logger)
, File(filename.c_str())
, State(DEFAULT)
, SourceFilename(filename)
2013-03-16 19:13:01 +02:00
{
WriteXMLDeclaration();
2016-07-09 11:21:54 +02:00
if (isIncludeFile) {
2013-03-16 19:13:01 +02:00
BeginElement("Include");
2016-07-09 11:21:54 +02:00
} else {
2013-03-16 19:13:01 +02:00
BeginElement("Wix");
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi");
}
cmWIXSourceWriter::~cmWIXSourceWriter()
{
2016-07-09 11:21:54 +02:00
if (Elements.size() > 1) {
cmCPackLogger(cmCPackLog::LOG_ERROR, Elements.size() - 1
<< " WiX elements were still open when closing '"
<< SourceFilename << "'" << std::endl);
2014-08-03 19:52:23 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2014-08-03 19:52:23 +02:00
EndElement(Elements.back());
2013-03-16 19:13:01 +02:00
}
2015-04-27 22:25:09 +02:00
void cmWIXSourceWriter::BeginElement(std::string const& name)
2013-03-16 19:13:01 +02:00
{
2016-07-09 11:21:54 +02:00
if (State == BEGIN) {
2014-08-03 19:52:23 +02:00
File << ">";
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
2014-08-03 19:52:23 +02:00
File << "\n";
Indent(Elements.size());
File << "<" << name;
2013-03-16 19:13:01 +02:00
2014-08-03 19:52:23 +02:00
Elements.push_back(name);
State = BEGIN;
2013-03-16 19:13:01 +02:00
}
2014-08-03 19:52:23 +02:00
void cmWIXSourceWriter::EndElement(std::string const& name)
2013-03-16 19:13:01 +02:00
{
2016-07-09 11:21:54 +02:00
if (Elements.empty()) {
2014-08-03 19:52:23 +02:00
cmCPackLogger(cmCPackLog::LOG_ERROR,
2016-07-09 11:21:54 +02:00
"can not end WiX element with no open elements in '"
<< SourceFilename << "'" << std::endl);
2014-08-03 19:52:23 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2014-08-03 19:52:23 +02:00
2016-07-09 11:21:54 +02:00
if (Elements.back() != name) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "WiX element <"
<< Elements.back() << "> can not be closed by </" << name
<< "> in '" << SourceFilename << "'" << std::endl);
2013-03-16 19:13:01 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
2016-07-09 11:21:54 +02:00
if (State == DEFAULT) {
2014-08-03 19:52:23 +02:00
File << "\n";
2016-07-09 11:21:54 +02:00
Indent(Elements.size() - 1);
2014-08-03 19:52:23 +02:00
File << "</" << Elements.back() << ">";
2016-07-09 11:21:54 +02:00
} else {
2014-08-03 19:52:23 +02:00
File << "/>";
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
2014-08-03 19:52:23 +02:00
Elements.pop_back();
State = DEFAULT;
2013-03-16 19:13:01 +02:00
}
2016-03-13 13:35:51 +01:00
void cmWIXSourceWriter::AddTextNode(std::string const& text)
{
2016-07-09 11:21:54 +02:00
if (State == BEGIN) {
2016-03-13 13:35:51 +01:00
File << ">";
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
2016-07-09 11:21:54 +02:00
if (Elements.empty()) {
2016-03-13 13:35:51 +01:00
cmCPackLogger(cmCPackLog::LOG_ERROR,
2016-07-09 11:21:54 +02:00
"can not add text without open WiX element in '"
<< SourceFilename << "'" << std::endl);
2016-03-13 13:35:51 +01:00
return;
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
File << this->EscapeAttributeValue(text);
State = DEFAULT;
}
2016-07-09 11:21:54 +02:00
void cmWIXSourceWriter::AddProcessingInstruction(std::string const& target,
std::string const& content)
2013-03-16 19:13:01 +02:00
{
2016-07-09 11:21:54 +02:00
if (State == BEGIN) {
2014-08-03 19:52:23 +02:00
File << ">";
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
2014-08-03 19:52:23 +02:00
File << "\n";
Indent(Elements.size());
File << "<?" << target << " " << content << "?>";
2013-03-16 19:13:01 +02:00
2014-08-03 19:52:23 +02:00
State = DEFAULT;
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
void cmWIXSourceWriter::AddAttribute(std::string const& key,
std::string const& value)
2013-03-16 19:13:01 +02:00
{
2015-08-17 11:37:30 +02:00
std::string utf8 = CMakeEncodingToUtf8(value);
2013-03-16 19:13:01 +02:00
2014-08-03 19:52:23 +02:00
File << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"';
}
2016-07-09 11:21:54 +02:00
void cmWIXSourceWriter::AddAttributeUnlessEmpty(std::string const& key,
std::string const& value)
2014-08-03 19:52:23 +02:00
{
2016-07-09 11:21:54 +02:00
if (!value.empty()) {
2014-08-03 19:52:23 +02:00
AddAttribute(key, value);
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
}
2015-08-17 11:37:30 +02:00
std::string cmWIXSourceWriter::CMakeEncodingToUtf8(std::string const& value)
2013-03-16 19:13:01 +02:00
{
2015-08-17 11:37:30 +02:00
#ifdef CMAKE_ENCODING_UTF8
return value;
#else
2016-07-09 11:21:54 +02:00
if (value.empty()) {
2013-03-16 19:13:01 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
int characterCount = MultiByteToWideChar(
CP_ACP, 0, value.c_str(), static_cast<int>(value.size()), 0, 0);
2016-07-09 11:21:54 +02:00
if (characterCount == 0) {
2013-03-16 19:13:01 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
std::vector<wchar_t> utf16(characterCount);
2016-07-09 11:21:54 +02:00
MultiByteToWideChar(CP_ACP, 0, value.c_str(), static_cast<int>(value.size()),
&utf16[0], static_cast<int>(utf16.size()));
2013-03-16 19:13:01 +02:00
int utf8ByteCount = WideCharToMultiByte(
CP_UTF8, 0, &utf16[0], static_cast<int>(utf16.size()), 0, 0, 0, 0);
2016-07-09 11:21:54 +02:00
if (utf8ByteCount == 0) {
2013-03-16 19:13:01 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
std::vector<char> utf8(utf8ByteCount);
WideCharToMultiByte(CP_UTF8, 0, &utf16[0], static_cast<int>(utf16.size()),
2016-07-09 11:21:54 +02:00
&utf8[0], static_cast<int>(utf8.size()), 0, 0);
2013-03-16 19:13:01 +02:00
return std::string(&utf8[0], utf8.size());
2015-08-17 11:37:30 +02:00
#endif
2013-03-16 19:13:01 +02:00
}
void cmWIXSourceWriter::WriteXMLDeclaration()
{
2014-08-03 19:52:23 +02:00
File << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
2013-03-16 19:13:01 +02:00
}
void cmWIXSourceWriter::Indent(size_t count)
{
2016-07-09 11:21:54 +02:00
for (size_t i = 0; i < count; ++i) {
2014-08-03 19:52:23 +02:00
File << " ";
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
std::string cmWIXSourceWriter::EscapeAttributeValue(std::string const& value)
2013-03-16 19:13:01 +02:00
{
std::string result;
result.reserve(value.size());
char c = 0;
2016-07-09 11:21:54 +02:00
for (size_t i = 0; i < value.size(); ++i) {
2013-03-16 19:13:01 +02:00
c = value[i];
2016-07-09 11:21:54 +02:00
switch (c) {
case '<':
result += "&lt;";
break;
case '>':
result += "&gt;";
break;
case '&':
result += "&amp;";
break;
case '"':
result += "&quot;";
break;
default:
result += c;
break;
}
}
2013-03-16 19:13:01 +02:00
return result;
}