TempFile::~TempFile() { if (handle == nullptr) return;
if (!closed) {
oslFileError e = osl_closeFile(handle); if (e != osl_File_E_None) {
SAL_WARN("configmgr", "osl_closeFile failed with " << +e);
}
}
osl::FileBase::RC e = osl::File::remove(url); if (e != osl::FileBase::E_None) {
SAL_WARN( "configmgr", "osl::File::remove(" << url << ") failed with " << +e);
}
}
void writeModifications(
Components & components, TempFile &handle,
std::u16string_view parentPathRepresentation,
rtl::Reference< Node > const & parent, OUString const & nodeName,
rtl::Reference< Node > const & node,
Modifications::Node const & modifications)
{ // It is never necessary to write oor:finalized or oor:mandatory attributes, // as they cannot be set via the UNO API. if (modifications.children.empty()) {
assert(parent.is()); // components themselves have no parent but must have children
handle.writeString("<item oor:path=\"");
writeAttributeValue(handle, parentPathRepresentation);
handle.writeString("\">"); if (node.is()) {
writeNode(components, handle, parent, nodeName, node);
} else { switch (parent->kind()) { case Node::KIND_LOCALIZED_PROPERTY:
handle.writeString("<value"); if (!nodeName.isEmpty()) {
handle.writeString(" xml:lang=\"");
writeAttributeValue(handle, nodeName);
handle.writeString("\"");
}
handle.writeString(" oor:op=\"remove\"/>"); break; case Node::KIND_GROUP:
assert( static_cast< GroupNode * >(parent.get())->isExtensible());
handle.writeString("<prop oor:name=\"");
writeAttributeValue(handle, nodeName);
handle.writeString("\" oor:op=\"remove\"/>"); break; case Node::KIND_SET:
handle.writeString("<node oor:name=\"");
writeAttributeValue(handle, nodeName);
handle.writeString("\" oor:op=\"remove\"/>"); break; default:
assert(false); // this cannot happen break;
}
}
handle.writeString("</item>\n");
} else {
assert(node.is());
OUString pathRep(
OUString::Concat(parentPathRepresentation) + "/" +
Data::createSegment(node->getTemplateName(), nodeName));
// copy configmgr::Modifications::Node's to a sortable list. Use pointers // to just reference the data instead of copying it
std::vector< const ModNodePairEntry* > ModNodePairEntryVector;
ModNodePairEntryVector.reserve(modifications.children.size());
for (constauto& rCand : modifications.children)
{
ModNodePairEntryVector.push_back(&rCand);
}
// sort the list
std::sort(ModNodePairEntryVector.begin(), ModNodePairEntryVector.end(), PairEntrySorter());
// now use the list to write entries in sorted order // instead of random as from the unordered map for (constauto & i : ModNodePairEntryVector)
{
writeModifications(
components, handle, pathRep, node, i->first,
node->getMember(i->first), i->second);
}
}
}
void writeValueContent(TempFile &handle, std::u16string_view value) {
std::size_t i = 0;
std::size_t j = i; for (; j != value.size(); ++j) {
char16_t c = value[j]; if ((c < 0x0020 && c != 0x0009 && c != 0x000A && c != 0x000D) ||
c == 0xFFFE || c == 0xFFFF)
{
handle.writeString(convertToUtf8(value.substr(i, j - i)));
handle.writeString("<unicode oor:scalar=\"");
handle.writeString(OString::number(c));
handle.writeString("\"/>");
i = j + 1;
} elseif (c == '\x0D') {
handle.writeString(convertToUtf8(value.substr(i, j - i)));
handle.writeString("
");
i = j + 1;
} elseif (c == '&') {
handle.writeString(convertToUtf8(value.substr(i, j - i)));
handle.writeString("&");
i = j + 1;
} elseif (c == '<') {
handle.writeString(convertToUtf8(value.substr(i, j - i)));
handle.writeString("<");
i = j + 1;
} elseif (c == '>') { // "MUST, for compatibility, be escaped [...] when it appears in the // string ']]>'":
handle.writeString(convertToUtf8(value.substr(i, j - i)));
handle.writeString(">");
i = j + 1;
}
}
handle.writeString(convertToUtf8(value.substr(i, j - i)));
}
void writeModFile(
Components & components, OUString const & url, Data const & data)
{
sal_Int32 i = url.lastIndexOf('/');
assert(i != -1);
OUString dir(url.copy(0, i)); switch (osl::Directory::createPath(dir)) { case osl::FileBase::E_None: case osl::FileBase::E_EXIST: break; case osl::FileBase::E_ACCES:
SAL_INFO( "configmgr",
("cannot create registrymodifications.xcu path (E_ACCES); changes" " will be lost")); return; default: throw css::uno::RuntimeException( "cannot create directory " + dir);
}
TempFile tmp; switch (osl::FileBase::createTempFile(&dir, &tmp.handle, &tmp.url)) { case osl::FileBase::E_None: break; case osl::FileBase::E_ACCES:
SAL_INFO( "configmgr",
("cannot create temp registrymodifications.xcu (E_ACCES); changes" " will be lost")); return; default: throw css::uno::RuntimeException( "cannot create temporary file in " + dir);
}
tmp.writeString( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items" " xmlns:oor=\"http://openoffice.org/2001/registry\"" " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"); //TODO: Do not write back information about those removed items that did not // come from the .xcs/.xcu files, anyway (but had been added dynamically // instead):
{
osl::MutexGuard g(components.getLock());
// For profilesafemode it is necessary to detect changes in the // registrymodifications file, this is done based on file size in bytes and crc32. // Unfortunately this write is based on writing unordered map entries, which creates // valid and semantically equal XML-Files, bubt with different crc32 checksums. For // the future usage it will be preferable to have easily comparable config files // which is guaranteed by writing the entries in sorted order. Indeed with this change // (and in the recursive writeModifications call) the same config files get written
// copy configmgr::Modifications::Node's to a sortable list. Use pointers // to just reference the data instead of copying it
std::vector< const ModNodePairEntry* > ModNodePairEntryVector;
ModNodePairEntryVector.reserve(data.modifications.getRoot().children.size());
for (constauto& rCand : data.modifications.getRoot().children)
{
ModNodePairEntryVector.push_back(&rCand);
}
// sort the list
std::sort(ModNodePairEntryVector.begin(), ModNodePairEntryVector.end(), PairEntrySorter());
// now use the list to write entries in sorted order // instead of random as from the unordered map for (constauto& j : ModNodePairEntryVector)
{
writeModifications(
components, tmp, u"", rtl::Reference< Node >(), j->first,
data.getComponents().findNode(Data::NO_LAYER, j->first),
j->second);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.