diff options
author | Ashod Nakashian <ashodnakashian@yahoo.com> | 2017-11-02 21:20:50 -0400 |
---|---|---|
committer | Ashod Nakashian <ashnakash@gmail.com> | 2017-11-06 06:12:21 +0100 |
commit | e6b200524bd5f614ab5ece88e8187466e7c40096 (patch) | |
tree | c90e7c8d45f353a43465aa8c43e9881d4d55d53f /sw | |
parent | ffa46ebe6d83c5e812753c41857f31c059f33986 (diff) |
TSCP: Store paragraph signature RDF in the paragraph
Change-Id: Ic44e3238bd1c35445bc23d0cc1de07aa2bf4512c
Reviewed-on: https://gerrit.libreoffice.org/44243
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/core/edit/edfcol.cxx | 177 | ||||
-rw-r--r-- | sw/source/core/edit/edws.cxx | 5 |
2 files changed, 127 insertions, 55 deletions
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 2b32ccfb9f0d..2486c3fb769e 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -95,9 +95,12 @@ namespace { static const OUString MetaFilename("tscp/bails.rdf"); static const OUString MetaNS("urn:bails"); -static const OUString ParagraphSignatureRDFName = "urn:bails:loext:paragraph:signature"; -static const OUString ParagraphSignatureDateRDFName = "urn:bails:loext:paragraph:signature:date"; -static const OUString ParagraphSignatureUsageRDFName = "urn:bails:loext:paragraph:signature:usage"; +static const OUString ParagraphSignatureRDFNamespace = "urn:bails:loext:paragraph:signature:"; +static const OUString ParagraphSignatureIdRDFName = "urn:bails:loext:paragraph:signature:id"; +static const OUString ParagraphSignatureDigestRDFName = ":digest"; +static const OUString ParagraphSignatureDateRDFName = ":date"; +static const OUString ParagraphSignatureUsageRDFName = ":usage"; +static const OUString ParagraphSignatureLastIdRDFName = "urn:bails:loext:paragraph:signature:lastid"; static const OUString ParagraphClassificationNameRDFName = "urn:bails:loext:paragraph:classification:name"; static const OUString ParagraphClassificationValueRDFName = "urn:bails:loext:paragraph:classification:value"; static const OUString MetadataFieldServiceName = "com.sun.star.text.textfield.MetadataField"; @@ -275,29 +278,68 @@ std::pair<OUString, OUString> lcl_getFieldRDF(const uno::Reference<frame::XModel bool lcl_IsParagraphSignatureField(const uno::Reference<frame::XModel>& xModel, const uno::Reference<css::text::XTextField>& xField) { - return lcl_getFieldRDF(xModel, xField, ParagraphSignatureRDFName).first == ParagraphSignatureRDFName; + return (lcl_getFieldRDF(xModel, xField, ParagraphSignatureIdRDFName).first == ParagraphSignatureIdRDFName); +} + +struct SignatureDescr +{ + OUString msSignature; + OUString msUsage; + OUString msDate; + OUString msId; + + bool isValid() const { return !msSignature.isEmpty(); } +}; + +SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextContent>& xParagraph, + const OUString& sFieldId) +{ + SignatureDescr aDescr; + aDescr.msId = sFieldId; + + const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY); + const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xParaSubject); + const auto itSig = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureDigestRDFName); + aDescr.msSignature = (itSig != aStatements.end() ? itSig->second : OUString()); + + const auto itDate = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureDateRDFName); + aDescr.msDate = (itDate != aStatements.end() ? itDate->second : OUString()); + + const auto itUsage = aStatements.find(ParagraphSignatureRDFNamespace + sFieldId + ParagraphSignatureUsageRDFName); + aDescr.msUsage = (itUsage != aStatements.end() ? itUsage->second : OUString()); + + return aDescr; +} + +SignatureDescr lcl_getSignatureDescr(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextContent>& xParagraph, + const uno::Reference<css::text::XTextField>& xField) +{ + const css::uno::Reference<css::rdf::XResource> xFieldSubject(xField, uno::UNO_QUERY); + std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xFieldSubject); + const auto itId = aStatements.find(ParagraphSignatureIdRDFName); + return (itId != aStatements.end() ? lcl_getSignatureDescr(xModel, xParagraph, itId->second) : SignatureDescr()); } /// Validate and return validation result and signature field display text. std::pair<bool, OUString> lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextContent>& xParagraph, const uno::Reference<css::text::XTextField>& xField, const OString& utf8Text) { OUString msg = SwResId(STR_INVALID_SIGNATURE); bool valid = false; - const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY); - std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject); - - const auto it = aStatements.find(ParagraphSignatureRDFName); - if (it != aStatements.end()) + const SignatureDescr aDescr = lcl_getSignatureDescr(xModel, xParagraph, xField); + if (aDescr.isValid()) { const sal_Char* pData = utf8Text.getStr(); const std::vector<unsigned char> data(pData, pData + utf8Text.getLength()); OString encSignature; - if (it->second.convertToString(&encSignature, RTL_TEXTENCODING_UTF8, 0)) + if (aDescr.msSignature.convertToString(&encSignature, RTL_TEXTENCODING_UTF8, 0)) { const std::vector<unsigned char> sig(svl::crypto::DecodeHexString(encSignature)); SignatureInformation aInfo(0); @@ -305,13 +347,8 @@ lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel, valid = valid && aInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; msg = SwResId(STR_SIGNED_BY) + ": " + aInfo.ouSubject + ", "; - - const auto itDate = aStatements.find(ParagraphSignatureDateRDFName); - msg += (itDate != aStatements.end() ? itDate->second : OUString()); - - const auto itUsage = aStatements.find(ParagraphSignatureUsageRDFName); - msg += (itUsage != aStatements.end() ? (" (" + itUsage->second + "): ") : OUString(": ")); - + msg += aDescr.msDate; + msg += (!aDescr.msUsage.isEmpty() ? (" (" + aDescr.msUsage + "): ") : OUString(": ")); msg += (valid ? SwResId(STR_VALID) : SwResId(STR_INVALID)); } } @@ -319,9 +356,20 @@ lcl_MakeParagraphSignatureFieldText(const uno::Reference<frame::XModel>& xModel, return std::make_pair(valid, msg); } +/// Generate the next valid ID for the a new signature on this paragraph. +OUString lcl_getNextSignatureId(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<text::XTextContent>& xParagraph) +{ + const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY); + std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xParaSubject); + const auto it = aStatements.find(ParagraphSignatureLastIdRDFName); + return OUString::number(it != aStatements.end() ? it->second.toInt32() + 1 : 1); +} + + /// Creates and inserts Paragraph Signature Metadata field and creates the RDF entry uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Reference<frame::XModel>& xModel, - const uno::Reference<text::XTextContent>& xParent, + const uno::Reference<text::XTextContent>& xParagraph, const OUString& signature, const OUString& usage) { @@ -329,16 +377,15 @@ uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Referen auto xField = uno::Reference<text::XTextField>(xMultiServiceFactory->createInstance(MetadataFieldServiceName), uno::UNO_QUERY); // Add the signature at the end. - xField->attach(xParent->getAnchor()->getEnd()); + xField->attach(xParagraph->getAnchor()->getEnd()); + + const OUString sId = lcl_getNextSignatureId(xModel, xParagraph); const css::uno::Reference<css::rdf::XResource> xSubject(xField, uno::UNO_QUERY); - SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xSubject, ParagraphSignatureRDFName, signature); - SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xSubject, ParagraphSignatureUsageRDFName, usage); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xSubject, ParagraphSignatureIdRDFName, sId); - // First convert the UTC UNIX timestamp to a tools::DateTime. + // First convert the UTC UNIX timestamp to a tools::DateTime then to local time. DateTime aDateTime = DateTime::CreateFromUnixTime(time(nullptr)); - - // Then convert to a local UNO DateTime. aDateTime.ConvertToLocalTime(); OUStringBuffer rBuffer; rBuffer.append((sal_Int32)aDateTime.GetYear()); @@ -351,7 +398,12 @@ uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Referen rBuffer.append('0'); rBuffer.append((sal_Int32)aDateTime.GetDay()); - SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xSubject, ParagraphSignatureDateRDFName, rBuffer.makeStringAndClear()); + // 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); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureLastIdRDFName, sId); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureRDFNamespace + sId + ParagraphSignatureDigestRDFName, signature); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureRDFNamespace + sId + ParagraphSignatureUsageRDFName, usage); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xParaSubject, ParagraphSignatureRDFNamespace + sId + ParagraphSignatureDateRDFName, rBuffer.makeStringAndClear()); return xField; } @@ -359,6 +411,7 @@ uno::Reference<text::XTextField> lcl_InsertParagraphSignature(const uno::Referen /// Updates the signature field text if changed and returns true only iff updated. bool lcl_UpdateParagraphSignatureField(SwDoc* pDoc, const uno::Reference<frame::XModel>& xModel, + const uno::Reference<css::text::XTextContent>& xParagraph, const uno::Reference<css::text::XTextField>& xField, const OString& utf8Text) { @@ -369,7 +422,7 @@ bool lcl_UpdateParagraphSignatureField(SwDoc* pDoc, pDoc->GetIDocumentUndoRedo().DoUndo(isUndoEnabled); }); - const std::pair<bool, OUString> res = lcl_MakeParagraphSignatureFieldText(xModel, xField, utf8Text); + const std::pair<bool, OUString> res = lcl_MakeParagraphSignatureFieldText(xModel, xParagraph, xField, utf8Text); uno::Reference<css::text::XTextRange> xText(xField, uno::UNO_QUERY); const OUString curText = xText->getString(); if (curText != res.second) @@ -463,13 +516,15 @@ bool lcl_UpdateParagraphClassificationField(SwDoc* pDoc, }); uno::Reference<text::XTextField> xField = lcl_InsertParagraphClassification(xModel, xTextNode); + css::uno::Reference<css::rdf::XResource> xFieldSubject(xField, uno::UNO_QUERY); SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xFieldSubject, sKey, sValue); - css::uno::Reference<css::rdf::XResource> xNodeSubject(xTextNode, uno::UNO_QUERY); - SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xNodeSubject, sKey, sValue); SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xFieldSubject, ParagraphClassificationNameRDFName, sKey); SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xFieldSubject, ParagraphClassificationValueRDFName, sValue); + css::uno::Reference<css::rdf::XResource> xNodeSubject(xTextNode, uno::UNO_QUERY); + SwRDFHelper::addStatement(xModel, MetaNS, MetaFilename, xNodeSubject, sKey, sValue); + uno::Reference<css::text::XTextRange> xText(xField, uno::UNO_QUERY); const OUString curDisplayText = xText->getString(); if (curDisplayText != sDisplayText) @@ -488,6 +543,20 @@ void lcl_ValidateParagraphSignatures(SwDoc* pDoc, const uno::Reference<text::XTe return; uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + + // Check if the paragraph is signed. + try + { + const css::uno::Reference<css::rdf::XResource> xParaSubject(xParagraph, uno::UNO_QUERY); + const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xParaSubject); + if (aStatements.find(ParagraphSignatureLastIdRDFName) == aStatements.end()) + return; + } + catch (const ::css::uno::Exception&) + { + return; + } + uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraph, uno::UNO_QUERY); if (!xTextPortionEnumerationAccess.is()) return; @@ -522,9 +591,9 @@ void lcl_ValidateParagraphSignatures(SwDoc* pDoc, const uno::Reference<text::XTe if (updateDontRemove) { - lcl_UpdateParagraphSignatureField(pDoc, xModel, xField, utf8Text); + lcl_UpdateParagraphSignatureField(pDoc, xModel, xParagraph, xField, utf8Text); } - else if (!lcl_MakeParagraphSignatureFieldText(xModel, xField, utf8Text).first) + else if (!lcl_MakeParagraphSignatureFieldText(xModel, xParagraph, xField, utf8Text).first) { pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::PARA_SIGN_ADD, nullptr); SwUndoParagraphSigning* pUndo = new SwUndoParagraphSigning(pDoc, xField, xParagraph, false); @@ -1112,23 +1181,11 @@ void SwEditShell::ApplyParagraphClassification(std::vector<svx::ClassificationRe } } -std::vector<svx::ClassificationResult> SwEditShell::CollectParagraphClassification() +std::vector<svx::ClassificationResult> lcl_CollectParagraphClassification(const uno::Reference<frame::XModel>& xModel, const uno::Reference<text::XTextContent>& xParagraph) { std::vector<svx::ClassificationResult> aResult; - SwDocShell* pDocShell = GetDoc()->GetDocShell(); - if (!pDocShell) - return aResult; - - SwTextNode* pNode = GetCursor()->Start()->nNode.GetNode().GetTextNode(); - if (pNode == nullptr) - return aResult; - - uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); - uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); - uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY); - - uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraph, uno::UNO_QUERY); if (!xTextPortionEnumerationAccess.is()) return aResult; @@ -1178,6 +1235,23 @@ std::vector<svx::ClassificationResult> SwEditShell::CollectParagraphClassificati return aResult; } +std::vector<svx::ClassificationResult> SwEditShell::CollectParagraphClassification() +{ + std::vector<svx::ClassificationResult> aResult; + + SwDocShell* pDocShell = GetDoc()->GetDocShell(); + if (!pDocShell) + return aResult; + + SwTextNode* pNode = GetCursor()->Start()->nNode.GetNode().GetTextNode(); + if (pNode == nullptr) + return aResult; + + uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); + uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); + return lcl_CollectParagraphClassification(xModel, xParent); +} + sal_Int16 lcl_GetAngle(const drawing::HomogenMatrix3& rMatrix) { basegfx::B2DHomMatrix aTransformation; @@ -1494,8 +1568,9 @@ SwUndoParagraphSigning::SwUndoParagraphSigning(SwDoc* pDoc, // Save the metadata and field content to undo/redo. uno::Reference<frame::XModel> xModel = m_pDoc->GetDocShell()->GetBaseModel(); const css::uno::Reference<css::rdf::XResource> xSubject(m_xField, uno::UNO_QUERY); + std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject); - const auto it = aStatements.find(ParagraphSignatureRDFName); + const auto it = aStatements.find(ParagraphSignatureIdRDFName); if (it != aStatements.end()) m_signature = it->second; @@ -1579,8 +1654,8 @@ void SwEditShell::SignParagraph() return; // 1. Get the text (without fields). - const uno::Reference<text::XTextContent> xParent = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); - const OString utf8Text = lcl_getParagraphBodyText(xParent); + const uno::Reference<text::XTextContent> xParagraph = SwXParagraph::CreateXParagraph(*pNode->GetDoc(), pNode); + const OString utf8Text = lcl_getParagraphBodyText(xParagraph); if (utf8Text.isEmpty()) return; @@ -1624,11 +1699,11 @@ void SwEditShell::SignParagraph() GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::PARA_SIGN_ADD, nullptr); const uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel(); - uno::Reference<css::text::XTextField> xField = lcl_InsertParagraphSignature(xModel, xParent, signature, aUsage); + uno::Reference<css::text::XTextField> xField = lcl_InsertParagraphSignature(xModel, xParagraph, signature, aUsage); - lcl_UpdateParagraphSignatureField(GetDoc(), xModel, xField, utf8Text); + lcl_UpdateParagraphSignatureField(GetDoc(), xModel, xParagraph, xField, utf8Text); - SwUndoParagraphSigning* pUndo = new SwUndoParagraphSigning(GetDoc(), xField, xParent, true); + SwUndoParagraphSigning* pUndo = new SwUndoParagraphSigning(GetDoc(), xField, xParagraph, true); GetDoc()->GetIDocumentUndoRedo().AppendUndo(pUndo); GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::PARA_SIGN_ADD, nullptr); @@ -1698,7 +1773,7 @@ uno::Reference<text::XTextField> lcl_GetParagraphMetadataFieldAtIndex(const SwDo const css::uno::Reference<css::rdf::XResource> xSubject(pMeta->MakeUnoObject(), uno::UNO_QUERY); uno::Reference<frame::XModel> xModel = pDocSh->GetBaseModel(); const std::map<OUString, OUString> aStatements = SwRDFHelper::getStatements(xModel, MetaNS, xSubject); - if (aStatements.find(ParagraphSignatureRDFName) != aStatements.end() || + if (aStatements.find(ParagraphSignatureIdRDFName) != aStatements.end() || aStatements.find(ParagraphClassificationNameRDFName) != aStatements.end()) { xTextField = uno::Reference<text::XTextField>(xSubject, uno::UNO_QUERY); diff --git a/sw/source/core/edit/edws.cxx b/sw/source/core/edit/edws.cxx index 01dc694ab450..73f8c6aba112 100644 --- a/sw/source/core/edit/edws.cxx +++ b/sw/source/core/edit/edws.cxx @@ -53,10 +53,7 @@ SwEditShell::SwEditShell( SwDoc& rDoc, vcl::Window *pWindow, const SwViewOption // Update the paragraph signatures. // Since this ctor is called only on creating/loading the doc, we validate once only. - //FIXME: This is taking too long for the scheduler's taste. - // Need to do a quick check to see if a paragraph is signed or not, - // but for that need paragraph RDF, which is in a later patch. - // ValidateAllParagraphSignatures(true); + ValidateAllParagraphSignatures(true); } SwEditShell::~SwEditShell() // USED |