/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/// Find all page styles which are currently used in the document.
std::vector<ProgName> lcl_getUsedPageStyles(SwViewShell const * pShell)
{
std::vector<ProgName> aReturn;
/// Search for a field named rFieldName of type rServiceName in xText and return it.
uno::Reference<text::XTextField> lcl_findField(const uno::Reference<text::XText>& xText, const OUString& rServiceName, std::u16string_view rFieldName)
{
uno::Reference<text::XTextField> xField;
uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xText, uno::UNO_QUERY);
uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration(); while (xParagraphs->hasMoreElements())
{
uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraphs->nextElement(), uno::UNO_QUERY);
uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration(); while (xTextPortions->hasMoreElements())
{
uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
OUString aTextPortionType;
xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType; if (aTextPortionType != UNO_NAME_TEXT_FIELD) continue;
uno::Reference<lang::XServiceInfo> xTextField;
xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xTextField; if (!xTextField->supportsService(rServiceName)) continue;
/// Search for a field named rFieldName of type rServiceName in xText and return true iff found. bool lcl_hasField(const uno::Reference<text::XText>& xText, const OUString& rServiceName, std::u16string_view rFieldName)
{ return lcl_findField(xText, rServiceName, rFieldName).is();
}
/// Search for a frame with WATERMARK_NAME in name of type rServiceName in xText. Returns found name in rShapeName.
uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XText>& xText, const OUString& rServiceName, OUString& rShapeName, bool& bSuccess)
{
bSuccess = false;
uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xText, uno::UNO_QUERY);
uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration(); while (xParagraphs->hasMoreElements())
{
uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraphs->nextElement(), uno::UNO_QUERY); if (!xTextPortionEnumerationAccess.is()) continue;
bSuccess = true;
uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration(); while (xTextPortions->hasMoreElements())
{
uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
OUString aTextPortionType;
xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType; if (aTextPortionType != "Frame") continue;
uno::Reference<container::XContentEnumerationAccess> xContentEnumerationAccess(xTextPortion, uno::UNO_QUERY); if (!xContentEnumerationAccess.is()) continue;
uno::Reference<container::XEnumeration> xEnumeration = xContentEnumerationAccess->createContentEnumeration(u"com.sun.star.text.TextContent"_ustr); if (!xEnumeration->hasMoreElements()) continue;
uno::Reference<lang::XServiceInfo> xWatermark(xEnumeration->nextElement(), uno::UNO_QUERY); if (!xWatermark->supportsService(rServiceName)) continue;
/// Extract the text of the paragraph without any of the fields. /// TODO: Consider moving to SwTextNode, or extend ModelToViewHelper.
OString lcl_getParagraphBodyText(const uno::Reference<text::XTextContent>& xText)
{
OUStringBuffer strBuf;
uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xText, uno::UNO_QUERY); if (!xTextPortionEnumerationAccess.is()) return OString();
/// Returns true iff the field in question is paragraph signature. /// Note: must have associated RDF, since signatures are otherwise just metadata fields. bool lcl_IsParagraphSignatureField(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextField>& xField)
{ return (lcl_getRDF(xModel, xField, ParagraphSignatureIdRDFName).first == ParagraphSignatureIdRDFName);
}
/// Validate and create the signature field display text from the fields.
std::pair<bool, OUString> lcl_MakeParagraphSignatureFieldText(const SignatureDescr& aDescr, const OString& utf8Text)
{
OUString msg = SwResId(STR_INVALID_SIGNATURE); bool valid = false;
/// Validate and return validation result and signature field display text.
std::pair<bool, OUString>
lcl_MakeParagraphSignatureFieldText(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<css::text::XTextContent>& xParagraph, const uno::Reference<css::text::XTextField>& xField, const OString& utf8Text)
{ const SignatureDescr aDescr = lcl_getSignatureDescr(xModel, xParagraph, xField); return lcl_MakeParagraphSignatureFieldText(aDescr, utf8Text);
}
/// Generate the next valid ID for the new signature on this paragraph.
OUString lcl_getNextSignatureId(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParagraph)
{ const OUString sFieldId = lcl_getRDF(xModel, xParagraph, ParagraphSignatureLastIdRDFName).second; return OUString::number(!sFieldId.isEmpty() ? sFieldId.toInt32() + 1 : 1);
}
/// Creates and inserts Paragraph Signature Metadata field and creates the RDF entry
uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const rtl::Reference<SwXTextDocument>& xModel, const uno::Reference<text::XTextContent>& xParagraph, const OUString& signature, const OUString& usage)
{ auto xField = uno::Reference<text::XTextField>(xModel->createInstance(MetadataFieldServiceName), uno::UNO_QUERY);
// Add the signature at the end.
xField->attach(xParagraph->getAnchor()->getEnd());
// First convert the UTC UNIX timestamp to a tools::DateTime then to local time.
DateTime aDateTime = DateTime::CreateFromUnixTime(time(nullptr));
aDateTime.ConvertToLocalTime();
OUStringBuffer rBuffer;
rBuffer.append(static_cast<sal_Int32>(aDateTime.GetYear()));
rBuffer.append('-'); if (aDateTime.GetMonth() < 10)
rBuffer.append('0');
rBuffer.append(static_cast<sal_Int32>(aDateTime.GetMonth()));
rBuffer.append('-'); if (aDateTime.GetDay() < 10)
rBuffer.append('0');
rBuffer.append(static_cast<sal_Int32>(aDateTime.GetDay()));
// Now set the RDF on the paragraph, since that's what is preserved in .doc(x). const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY); const OUString prefix = ParagraphSignatureRDFNamespace + sId;
SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureLastIdRDFName, sId);
SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, prefix + ParagraphSignatureDigestRDFName, signature);
SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, prefix + ParagraphSignatureUsageRDFName, usage);
SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, prefix + ParagraphSignatureDateRDFName, rBuffer.makeStringAndClear());
return xField;
}
/// Updates the signature field text if changed and returns true only iff updated. bool lcl_DoUpdateParagraphSignatureField(SwDoc& rDoc, const uno::Reference<css::text::XTextField>& xField, const OUString& sDisplayText)
{ // Disable undo to avoid introducing noise when we edit the metadata field. constbool isUndoEnabled = rDoc.GetIDocumentUndoRedo().DoesUndo();
rDoc.GetIDocumentUndoRedo().DoUndo(false);
comphelper::ScopeGuard const g([&rDoc, isUndoEnabled]() {
rDoc.GetIDocumentUndoRedo().DoUndo(isUndoEnabled);
});
// Enumerate text portions to find metadata fields. This is expensive, best to enumerate fields only.
rtl::Reference<SwXTextPortionEnumeration> xTextPortions = xParagraph->createTextFieldsEnumeration(); while (xTextPortions->hasMoreElements())
{
uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
OUString aTextPortionType;
xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType; if (aTextPortionType != UNO_NAME_TEXT_FIELD) continue;
uno::Reference<lang::XServiceInfo> xServiceInfo;
xTextPortion->getPropertyValue(UNO_NAME_TEXT_FIELD) >>= xServiceInfo; if (!xServiceInfo->supportsService(MetadataFieldServiceName)) continue;
// Apply properties from the BA policy for (svx::ClassificationResult const & rResult : rResults)
{ if (rResult.meType == svx::ClassificationType::CATEGORY)
{
aHelper.SetBACName(rResult.msName, SfxClassificationHelper::getPolicyType());
}
}
// Insert full text as document property
svx::classification::insertFullTextualRepresentationAsDocumentProperty(xPropertyContainer, aCreator, rResults);
for (const ProgName& rPageStyleName : aUsedPageStyles)
{
uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName.toString()), uno::UNO_QUERY);
case svx::ClassificationType::PARAGRAPH:
{
nParagraph++;
if (nParagraph != 0) // only jump to next paragraph, if we aren't at the first paragraph
{
xHeaderParagraphCursor->gotoNextParagraph(false);
xFooterParagraphCursor->gotoNextParagraph(false);
}
for (const OUString& rPageStyleName : aStyles)
{
uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
if (bHeaderIsNeeded || bWatermarkIsNeeded || bHadWatermark)
{ // If the header is off, turn it on. bool bHeaderIsOn = false;
xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; if (!bHeaderIsOn)
xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::Any(true));
// If the header already contains a document header field, no need to do anything.
uno::Reference<text::XText> xHeaderText;
xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
if (bHeaderIsNeeded)
{ if (!lcl_hasField(xHeaderText, DocInfoServiceName, Concat2View(SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCHEADER())))
{ // Append a field to the end of the header text.
uno::Reference<beans::XPropertySet> xField(xModel->createInstance(DocInfoServiceName), uno::UNO_QUERY);
xField->setPropertyValue(UNO_NAME_NAME, uno::Any(SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCHEADER()));
uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, /*bAbsorb=*/false);
}
}
if (bFooterIsNeeded)
{ // If the footer is off, turn it on. bool bFooterIsOn = false;
xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn; if (!bFooterIsOn)
xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::Any(true));
// If the footer already contains a document header field, no need to do anything.
uno::Reference<text::XText> xFooterText;
xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText; static OUString sFooter = SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY() + SfxClassificationHelper::PROP_DOCFOOTER(); if (!lcl_hasField(xFooterText, DocInfoServiceName, sFooter))
{ // Append a field to the end of the footer text.
uno::Reference<beans::XPropertySet> xField(xModel->createInstance(DocInfoServiceName), uno::UNO_QUERY);
xField->setPropertyValue(UNO_NAME_NAME, uno::Any(sFooter));
uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false);
}
}
}
}
// We pass xParent and xNodeSubject even though they point to the same thing because the UNO_QUERY is // on a performance-sensitive path. staticvoid lcl_ApplyParagraphClassification(SwDoc* pDoc, const rtl::Reference<SwXTextDocument>& xModel, const rtl::Reference<SwXParagraph>& xParent, const css::uno::Reference<css::rdf::XResource>& xNodeSubject,
std::vector<svx::ClassificationResult> aResults)
{ if (!xNodeSubject.is()) return;
// Remove all paragraph classification fields. for (;;)
{
uno::Reference<text::XTextField> xTextField = lcl_FindParagraphClassificationField(xModel, xParent); if (!xTextField.is()) break;
lcl_RemoveParagraphMetadataField(xTextField);
}
if (aResults.empty()) return;
// Since we always insert at the start of the paragraph, // need to insert in reverse order.
std::reverse(aResults.begin(), aResults.end()); // Ignore "PARAGRAPH" types
std::erase_if(aResults,
[](const svx::ClassificationResult& rResult)-> bool
{ return rResult.meType == svx::ClassificationType::PARAGRAPH; });
// Correct the order
std::reverse(aFieldNames.begin(), aFieldNames.end());
OUStringBuffer sFieldNames; bool first = true; for (const OUString& rFieldName : aFieldNames)
{ if (!first)
sFieldNames.append("/");
sFieldNames.append(rFieldName);
first = false;
}
SwTextNode* pNode = GetCursor()->Start()->GetNode().GetTextNode(); if (pNode == nullptr) return;
// Prevent recursive validation since this is triggered on node updates, which we do below. constbool bOldValidationFlag = SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([this, bOldValidationFlag]() {
SetParagraphSignatureValidation(bOldValidationFlag);
});
if (xWatermark.is())
{
SfxWatermarkItem aItem;
uno::Reference<text::XTextRange> xTextRange(xWatermark, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xPropertySet(xWatermark, uno::UNO_QUERY);
Color nColor;
sal_Int16 nTransparency;
OUString aFont;
drawing::HomogenMatrix3 aMatrix;
aItem.SetText(xTextRange->getString());
if (xPropertySet->getPropertyValue(UNO_NAME_CHAR_FONT_NAME) >>= aFont)
aItem.SetFont(aFont); if (xPropertySet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= nColor)
aItem.SetColor(nColor); if (xPropertySet->getPropertyValue(u"Transformation"_ustr) >>= aMatrix)
aItem.SetAngle(lcl_GetAngle(aMatrix)); if (xPropertySet->getPropertyValue(UNO_NAME_FILL_TRANSPARENCE) >>= nTransparency)
aItem.SetTransparency(nTransparency);
// If the header already contains a watermark, see if it its text is up to date.
uno::Reference<text::XTextRange> xTextRange(xWatermark, uno::UNO_QUERY); if (xTextRange->getString() != rWatermark.GetText()
|| aFont != rWatermark.GetFont()
|| nColor != rWatermark.GetColor()
|| nAngle != rWatermark.GetAngle()
|| nTransparency != rWatermark.GetTransparency()
|| bDeleteWatermark)
{ // No: delete it and we'll insert a replacement.
uno::Reference<lang::XComponent> xComponent(xWatermark, uno::UNO_QUERY);
xComponent->dispose();
xWatermark.clear();
}
}
if (!bSuccess || xWatermark.is() || bDeleteWatermark) return;
// The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering.
uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY);
xLockable->addActionLock();
xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::Any(static_cast<sal_Int32>(nColor)));
xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::Any(drawing::FillStyle_SOLID));
xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::Any(nTransparency));
xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::Any(drawing::LineStyle_NONE));
xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::Any(false));
xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::Any(false));
xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::Any(false));
xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::Any(nHeight));
xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::Any(nWidth));
xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::Any(text::WrapTextMode_THROUGH));
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::Any(text::RelOrientation::PAGE_PRINT_AREA));
xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::Any(text::RelOrientation::PAGE_PRINT_AREA));
xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::Any(sFont));
xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME_ASIAN, uno::Any(sFont));
xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME_COMPLEX, uno::Any(sFont));
xPropertySet->setPropertyValue(UNO_NAME_CHAR_HEIGHT, uno::Any(WATERMARK_AUTO_SIZE));
xPropertySet->setPropertyValue(u"Transformation"_ustr, uno::Any(aMatrix));
auto aGeomPropSeq = xPropertySet->getPropertyValue(u"CustomShapeGeometry"_ustr).get< uno::Sequence<beans::PropertyValue> >(); auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq);
uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
{
{"TextPath", uno::Any(true)},
})); auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue)
{ return rValue.Name == "TextPath";
}); if (it == aGeomPropVec.end())
aGeomPropVec.push_back(comphelper::makePropertyValue(u"TextPath"_ustr, aPropertyValues)); else
it->Value <<= aPropertyValues;
xPropertySet->setPropertyValue(u"CustomShapeGeometry"_ustr, uno::Any(comphelper::containerToSequence(aGeomPropVec)));
// tdf#108494, tdf#109313 the header height was switched to height of a watermark // and shape was moved to the lower part of a page, force position update
xPropertySet->getPropertyValue(u"Transformation"_ustr) >>= aMatrix;
xPropertySet->setPropertyValue(u"Transformation"_ustr, uno::Any(aMatrix));
for (const OUString& rPageStyleName : aStyles)
{
uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
// If the header is off, turn it on. bool bHeaderIsOn = false;
xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn; if (!bHeaderIsOn)
{ if (bNoWatermark) continue; // the style doesn't have any watermark - no need to do anything
// If the header already contains a document header field, no need to do anything.
uno::Reference<text::XText> xHeaderText;
uno::Reference<text::XText> xHeaderTextFirst;
uno::Reference<text::XText> xHeaderTextLeft;
uno::Reference<text::XText> xHeaderTextRight;
// tdf#108494 the header height was switched to height of a watermark // and shape was moved to the lower part of a page
xPageStyle->setPropertyValue(UNO_NAME_HEADER_HEIGHT, uno::Any(sal_Int32(11)));
xPageStyle->setPropertyValue(UNO_NAME_HEADER_HEIGHT, uno::Any(nOldValue));
xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_DYNAMIC_HEIGHT, uno::Any(bDynamicHeight));
}
}
SwUndoParagraphSigning::SwUndoParagraphSigning(SwDoc& rDoc,
uno::Reference<text::XTextField> xField,
uno::Reference<text::XTextContent> xParent, constbool bRemove)
: SwUndo(SwUndoId::PARA_SIGN_ADD, rDoc),
m_rDoc(rDoc),
m_xField(std::move(xField)),
m_xParent(std::move(xParent)),
m_bRemove(bRemove)
{ // Save the metadata and field content to undo/redo. if (SwDocShell* pShell = m_rDoc.GetDocShell())
{
rtl::Reference<SwXTextDocument> xModel = pShell->GetBaseModel(); const std::map<OUString, OUString> aStatements = lcl_getRDFStatements(xModel, m_xField); constauto it = aStatements.find(ParagraphSignatureIdRDFName); if (it != aStatements.end())
m_signature = it->second;
void SwUndoParagraphSigning::Insert()
{ // Disable undo to avoid introducing noise when we edit the metadata field. constbool isUndoEnabled = m_rDoc.GetIDocumentUndoRedo().DoesUndo();
m_rDoc.GetIDocumentUndoRedo().DoUndo(false);
// Prevent validation since this will trigger a premature validation // upon inserting, but before setting the metadata.
SwEditShell* pEditSh = m_rDoc.GetEditShell(); constbool bOldValidationFlag = pEditSh && pEditSh->SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([&] () { if (pEditSh)
pEditSh->SetParagraphSignatureValidation(bOldValidationFlag);
m_rDoc.GetIDocumentUndoRedo().DoUndo(isUndoEnabled);
});
// Table text signing is not supported. if (pNode->FindTableNode() != nullptr) return;
// 1. Get the text (without fields). const rtl::Reference<SwXParagraph> xParagraph = SwXParagraph::CreateXParagraph(pNode->GetDoc(), pNode, nullptr); const OString utf8Text = lcl_getParagraphBodyText(xParagraph); if (utf8Text.isEmpty()) return;
// 2. Get certificate.
uno::Reference<security::XDocumentDigitalSignatures> xSigner( // here none of the version-dependent methods are called
security::DocumentDigitalSignatures::createDefault(
comphelper::getProcessComponentContext()));
uno::Sequence<css::beans::PropertyValue> aProperties;
uno::Reference<security::XCertificate> xCertificate = xSigner->chooseCertificateWithProps(aProperties); if (!xCertificate.is()) return;
// 3. Sign it.
svl::crypto::SigningContext aSigningContext;
aSigningContext.m_xCertificate = std::move(xCertificate);
svl::crypto::Signing signing(aSigningContext);
signing.AddDataRange(utf8Text.getStr(), utf8Text.getLength());
OStringBuffer sigBuf; if (!signing.Sign(sigBuf)) return;
auto it = std::find_if(aProperties.begin(), aProperties.end(), [](const beans::PropertyValue& rValue)
{ return rValue.Name == "Usage";
});
OUString aUsage; if (it != aProperties.end())
it->Value >>= aUsage;
// 4. Add metadata // Prevent validation since this will trigger a premature validation // upon inserting, but before setting the metadata. constbool bOldValidationFlag = SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([this, bOldValidationFlag] () {
SetParagraphSignatureValidation(bOldValidationFlag);
});
// Table text signing is not supported. if (pNode->FindTableNode() != nullptr) return;
// Prevent recursive validation since this is triggered on node updates, which we do below. constbool bOldValidationFlag = SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([this, bOldValidationFlag] () {
SetParagraphSignatureValidation(bOldValidationFlag);
});
SwDocShell* pDocShell = GetDoc()->GetDocShell(); if (!pDocShell) return;
// Prevent recursive validation since this is triggered on node updates, which we do below. constbool bOldValidationFlag = SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([this, bOldValidationFlag] () {
SetParagraphSignatureValidation(bOldValidationFlag);
});
// Prevent recursive validation since this is triggered on node updates, which we do below. constbool bOldValidationFlag = SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([this, bOldValidationFlag] () {
SetParagraphSignatureValidation(bOldValidationFlag);
});
std::vector<svx::ClassificationResult> aResults; if (!sFieldNames.isEmpty())
{ // Order the fields
sal_Int32 nIndex = 0; do
{ const OUString sCurFieldName = sFieldNames.getToken(0, '/', nIndex); if (sCurFieldName.isEmpty()) break;
OUString sName;
OUString sValue;
it = aParagraphStatements.find(sCurFieldName); if (it != aParagraphStatements.end())
{
sName = it->first;
sValue = it->second;
}
bool SwEditShell::RemoveParagraphMetadataFieldAtCursor()
{ if (GetCursor() && GetCursor()->Start())
{
SwTextNode* pNode = GetCursor()->Start()->GetNode().GetTextNode();
sal_uLong index = GetCursor()->Start()->GetContentIndex();
uno::Reference<text::XTextField> xField = lcl_GetParagraphMetadataFieldAtIndex(GetDoc()->GetDocShell(), pNode, index); if (!xField.is())
{ // Try moving the cursor to see if we're _facing_ a metafield or not, // as opposed to being within one.
index--; // Backspace moves left
void SwEditShell::ClassifyDocPerHighestParagraphClass()
{
SwDocShell* pDocShell = GetDoc()->GetDocShell(); if (!pDocShell) return;
// Bail out as early as possible if we don't have paragraph classification. if (!SwRDFHelper::hasMetadataGraph(pDocShell->GetBaseModel(), MetaNS)) return;
// Prevent paragraph signature validation since the below changes (f.e. watermarking) are benign. constbool bOldValidationFlag = SetParagraphSignatureValidation(false);
comphelper::ScopeGuard const g([this, bOldValidationFlag]() {
SetParagraphSignatureValidation(bOldValidationFlag);
});
// Check the origin, if "manual" (created via advanced classification dialog), // then we just need to set the category name. if (sfx::getCreationOriginProperty(xPropertyContainer, aKeyCreator) == sfx::ClassificationCreationOrigin::MANUAL)
{
aHelper.SetBACName(sHighestClass, eHighestClassType);
ApplyAdvancedClassification(CollectAdvancedClassification());
} else
{
SetClassification(sHighestClass, eHighestClassType);
}
}
// Change the paragraph style to pLocal and remove all direct paragraph formatting.
GetDoc()->SetTextFormatColl(rPaM, pLocal, true, bResetListAttrs, !!(nMode & SetAttrMode::REMOVE_ALL_ATTR), GetLayout());
// If there are hints on the nodes which cover the whole node, then remove those, too.
SwPaM aPaM(*rPaM.Start(), *rPaM.End()); if (SwTextNode* pEndTextNode = aPaM.End()->GetNode().GetTextNode())
{
aPaM.Start()->SetContent(0);
aPaM.End()->SetContent(pEndTextNode->GetText().getLength());
}
GetDoc()->RstTextAttrs(aPaM, /*bInclRefToxMark=*/false, /*bExactRange=*/true, GetLayout());
// add redline tracking the previous paragraph style if ( GetDoc()->getIDocumentRedlineAccess().IsRedlineOn() && // multi-paragraph ParagraphFormat redline ranges // haven't supported by AppendRedline(), yet // TODO handle multi-paragraph selections, too, // e.g. by breaking them to single paragraphs
aPaM.Start()->GetNode() == aPaM.End()->GetNode() )
{
SwRangeRedline * pRedline = new SwRangeRedline( RedlineType::ParagraphFormat, aPaM ); autoconst result(GetDoc()->getIDocumentRedlineAccess().AppendRedline( pRedline, true)); // store original paragraph style to reject formatting change if ( IDocumentRedlineAccess::AppendResult::IGNORED != result &&
( nPoolId == RES_POOLCOLL_STANDARD || !sParaStyleName.isEmpty() ) )
{
std::unique_ptr<SwRedlineExtraData_FormatColl> xExtra;
xExtra.reset(new SwRedlineExtraData_FormatColl(std::move(sParaStyleName), nPoolId, nullptr));
pRedline->SetExtraData( xExtra.get() );
}
}
}
void SwEditShell::FillByEx(SwTextFormatColl* pColl)
{
SwPaM * pCursor = GetCursor();
SwContentNode * pCnt = pCursor->GetPointContentNode(); if (pCnt->IsTextNode()) // uhm... what nonsense would happen if not?
{ // only need properties-node because BREAK/PAGEDESC filtered anyway!
pCnt = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
} const SfxItemSet* pSet = pCnt->GetpSwAttrSet(); if( !pSet ) return;
// JP 05.10.98: Special treatment if one of the attributes Break/PageDesc/NumRule(auto) is // in the ItemSet. Otherwise there will be too much or wrong processing (NumRules!) // Bug 57568
// Do NOT copy AutoNumRules into the template const SwNumRuleItem* pItem; const SwNumRule* pRule = nullptr; if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false)
|| SfxItemState::SET == pSet->GetItemState(RES_PAGEDESC, false)
|| ((pItem = pSet->GetItemIfSet(RES_PARATR_NUMRULE, false))
&& nullptr != (pRule = GetDoc()->FindNumRulePtr(pItem->GetValue()))
&& pRule->IsAutoRule()))
{
SfxItemSet aSet( *pSet );
aSet.ClearItem( RES_BREAK );
aSet.ClearItem( RES_PAGEDESC );
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.