[Libreoffice-commits] core.git: 4 commits - include/sfx2 sc/source sd/source sfx2/source sw/inc sw/qa sw/source writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Thu Mar 10 13:33:44 UTC 2016


 include/sfx2/classificationhelper.hxx                       |   11 -
 sc/source/ui/view/formatsh.cxx                              |    2 
 sd/source/ui/view/drviews2.cxx                              |    2 
 sfx2/source/view/classificationcontroller.cxx               |    2 
 sfx2/source/view/classificationhelper.cxx                   |   40 ++--
 sfx2/source/view/viewfrm.cxx                                |    4 
 sw/inc/fmtmeta.hxx                                          |   10 +
 sw/qa/extras/rtfimport/data/classification-confidential.rtf |   11 +
 sw/qa/extras/rtfimport/data/classification-no.rtf           |    1 
 sw/qa/extras/rtfimport/data/classification-yes.rtf          |   11 +
 sw/qa/extras/rtfimport/rtfimport.cxx                        |   29 +++
 sw/qa/extras/uiwriter/uiwriter.cxx                          |   16 +
 sw/source/core/edit/edfcol.cxx                              |    2 
 sw/source/core/txtnode/fmtatr2.cxx                          |   18 ++
 sw/source/filter/ww8/rtfexport.cxx                          |    7 
 sw/source/uibase/dochdl/swdtflvr.cxx                        |    5 
 writerfilter/source/rtftok/rtfdocumentimpl.cxx              |  102 ++++++++++--
 writerfilter/source/rtftok/rtflistener.hxx                  |    3 
 18 files changed, 230 insertions(+), 46 deletions(-)

New commits:
commit b1f9369b8181b4f135bfc8a0f1fdf1be7609fd0f
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 10 11:23:51 2016 +0100

    RTF import: handle classification during copy&paste
    
    With this, it can't happen that "paste" returns an error, but "paste as
    rtf" succeeds (from a classification point of view).
    
    Change-Id: Ia6807e5a6c065557cdd735a574ea858d29a97160

diff --git a/sw/qa/extras/rtfimport/data/classification-confidential.rtf b/sw/qa/extras/rtfimport/data/classification-confidential.rtf
new file mode 100644
index 0000000..c7207f9
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/classification-confidential.rtf
@@ -0,0 +1,11 @@
+{\rtf1{\*\userprops 
+{\propname urn:bails:IntellectualProperty:Authorization:StartValidity}\proptype30{\staticval 2016-03-08T10:55:18,531376147}{\propname urn:bails:IntellectualProperty:Authorization:StopValidity}\proptype30{\staticval None}{\propname urn:bails:IntellectualPr
+operty:BusinessAuthorization:Identifier}\proptype30{\staticval urn:example:tscp:1}{\propname urn:bails:IntellectualProperty:BusinessAuthorization:Locator}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorization:Name}
+\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Identifier}\proptype30{\staticval urn:example:tscp:1:internal-only}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Identifier:OID}
+\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Locator}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Name}\proptype30{\staticval Confidential}
+{\propname urn:bails:IntellectualProperty:Impact:Level:Availability}\proptype30{\staticval 2}{\propname urn:bails:IntellectualProperty:Impact:Level:Confidentiality}\proptype30{\staticval 2}{\propname urn:bails:IntellectualProperty:Impact:Level:Integrity}
+\proptype30{\staticval 2}{\propname urn:bails:IntellectualProperty:Impact:Scale}\proptype30{\staticval UK-Cabinet}{\propname urn:bails:IntellectualProperty:Marking:document-footer}\proptype30{\staticval This content is marked Internal Only. Do not distrib
+ute it outside of the business.}{\propname urn:bails:IntellectualProperty:Marking:document-header}\proptype30{\staticval Classification: Internal Only}{\propname urn:bails:IntellectualProperty:Marking:document-watermark}\proptype30{\staticval Internal Onl
+y}{\propname urn:bails:IntellectualProperty:MarkingPrecedence}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:Policy:Identifier}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:Policy:Name}\proptype30{\staticval
+TSCP Example Policy}{\propname urn:bails:IntellectualProperty:PolicyAuthority:Country}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:PolicyAuthority:Identifier}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:Po
+licyAuthority:Name}\proptype30{\staticval TSCP Example Policy Authority}}\par classification-yes\par}
diff --git a/sw/qa/extras/rtfimport/data/classification-no.rtf b/sw/qa/extras/rtfimport/data/classification-no.rtf
new file mode 100644
index 0000000..7c773d1
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/classification-no.rtf
@@ -0,0 +1 @@
+{\rtf1 \par classification-no\par}
diff --git a/sw/qa/extras/rtfimport/data/classification-yes.rtf b/sw/qa/extras/rtfimport/data/classification-yes.rtf
new file mode 100644
index 0000000..a40c3d1
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/classification-yes.rtf
@@ -0,0 +1,11 @@
+{\rtf1{\*\userprops 
+{\propname urn:bails:IntellectualProperty:Authorization:StartValidity}\proptype30{\staticval 2016-03-08T10:55:18,531376147}{\propname urn:bails:IntellectualProperty:Authorization:StopValidity}\proptype30{\staticval None}{\propname urn:bails:IntellectualPr
+operty:BusinessAuthorization:Identifier}\proptype30{\staticval urn:example:tscp:1}{\propname urn:bails:IntellectualProperty:BusinessAuthorization:Locator}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorization:Name}
+\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Identifier}\proptype30{\staticval urn:example:tscp:1:internal-only}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Identifier:OID}
+\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Locator}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Name}\proptype30{\staticval Internal Only}
+{\propname urn:bails:IntellectualProperty:Impact:Level:Availability}\proptype30{\staticval 3}{\propname urn:bails:IntellectualProperty:Impact:Level:Confidentiality}\proptype30{\staticval 3}{\propname urn:bails:IntellectualProperty:Impact:Level:Integrity}
+\proptype30{\staticval 3}{\propname urn:bails:IntellectualProperty:Impact:Scale}\proptype30{\staticval UK-Cabinet}{\propname urn:bails:IntellectualProperty:Marking:document-footer}\proptype30{\staticval This content is marked Internal Only. Do not distrib
+ute it outside of the business.}{\propname urn:bails:IntellectualProperty:Marking:document-header}\proptype30{\staticval Classification: Internal Only}{\propname urn:bails:IntellectualProperty:Marking:document-watermark}\proptype30{\staticval Internal Onl
+y}{\propname urn:bails:IntellectualProperty:MarkingPrecedence}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:Policy:Identifier}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:Policy:Name}\proptype30{\staticval
+TSCP Example Policy}{\propname urn:bails:IntellectualProperty:PolicyAuthority:Country}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:PolicyAuthority:Identifier}\proptype30{\staticval None}{\propname urn:bails:IntellectualProperty:Po
+licyAuthority:Name}\proptype30{\staticval TSCP Example Policy Authority}}\par classification-yes\par}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index f8193cd..a8c8f79 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -2525,6 +2525,35 @@ DECLARE_RTFIMPORT_TEST(testTdf87034, "tdf87034.rtf")
     CPPUNIT_ASSERT_EQUAL(OUString("A1B3C4D"), getParagraph(1)->getString());
 }
 
+DECLARE_RTFIMPORT_TEST(testClassificatonPaste, "hello.rtf")
+{
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XTextRange> xText(xTextDocument->getText(), uno::UNO_QUERY);
+    uno::Reference<text::XTextRange> xEnd = xText->getEnd();
+
+    // Not classified source, not classified destination: OK.
+    paste("classification-no.rtf", xEnd);
+    CPPUNIT_ASSERT_EQUAL(OUString("classification-no"), getParagraph(2)->getString());
+
+    // Classified source, not classified destination: nothing should happen.
+    OUString aOld = xText->getString();
+    paste("classification-yes.rtf", xEnd);
+    CPPUNIT_ASSERT_EQUAL(aOld, xText->getString());
+}
+
+DECLARE_RTFIMPORT_TEST(testClassificatonPasteLevels, "classification-confidential.rtf")
+{
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XTextRange> xText(xTextDocument->getText(), uno::UNO_QUERY);
+    uno::Reference<text::XTextRange> xEnd = xText->getEnd();
+
+    // Classified source and classified destination, but internal only has a
+    // higher level than confidential: nothing should happen.
+    OUString aOld = xText->getString();
+    paste("classification-yes.rtf", xEnd);
+    CPPUNIT_ASSERT_EQUAL(aOld, xText->getString());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 6bea01f..1c83e66 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -22,6 +22,7 @@
 #include <unotools/streamwrap.hxx>
 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
 #include <vcl/wmf.hxx>
+#include <vcl/layout.hxx>
 #include <filter/msfilter/util.hxx>
 #include <comphelper/string.hxx>
 #include <tools/globname.hxx>
@@ -31,6 +32,9 @@
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/sequence.hxx>
 #include <sfx2/sfxbasemodel.hxx>
+#include <sfx2/classificationhelper.hxx>
+#include <sfx2/sfx.hrc>
+#include <sfx2/sfxresid.hxx>
 #include <oox/mathml/import.hxx>
 #include <ooxml/resourceids.hxx>
 #include <oox/token/namespaces.hxx>
@@ -741,6 +745,9 @@ void RTFDocumentImpl::resolve(Stream& rMapper)
     case RTFError::CHAR_OVER:
         SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: characters after last '}'");
         break;
+    case RTFError::CLASSIFICATION:
+        SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: classification prevented paste");
+        break;
     }
 }
 
@@ -5124,6 +5131,39 @@ bool lcl_containsProperty(const uno::Sequence<beans::Property>& rProperties, con
     }) != rProperties.end();
 }
 
+namespace
+{
+
+RTFError lcl_checkClassification(const uno::Reference<document::XDocumentProperties>& xSource, const uno::Reference<document::XDocumentProperties>& xDestination)
+{
+    switch (SfxClassificationHelper::CheckPaste(xSource, xDestination))
+    {
+    case SfxClassificationCheckPasteResult::None:
+    {
+        return RTFError::OK;
+    }
+    break;
+    case SfxClassificationCheckPasteResult::TargetDocNotClassified:
+    {
+        if (!Application::IsHeadlessModeEnabled())
+            ScopedVclPtrInstance<MessageDialog>::Create(nullptr, SfxResId(STR_TARGET_DOC_NOT_CLASSIFIED), VCL_MESSAGE_INFO)->Execute();
+        return RTFError::CLASSIFICATION;
+    }
+    break;
+    case SfxClassificationCheckPasteResult::DocClassificationTooLow:
+    {
+        if (!Application::IsHeadlessModeEnabled())
+            ScopedVclPtrInstance<MessageDialog>::Create(nullptr, SfxResId(STR_DOC_CLASSIFICATION_TOO_LOW), VCL_MESSAGE_INFO)->Execute();
+        return RTFError::CLASSIFICATION;
+    }
+    break;
+    }
+
+    return RTFError::OK;
+}
+
+}
+
 RTFError RTFDocumentImpl::popState()
 {
     //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before pop: m_pTokenizer->getGroup() " << m_pTokenizer->getGroup() <<
@@ -5943,6 +5983,14 @@ RTFError RTFDocumentImpl::popState()
 
         if (m_xDocumentProperties.is())
         {
+            if (!m_bIsNewDoc)
+            {
+                // Check classification.
+                RTFError nError = lcl_checkClassification(xDocumentProperties, m_xDocumentProperties);
+                if (nError != RTFError::OK)
+                    return nError;
+            }
+
             uno::Reference<beans::XPropertyContainer> xClipboardPropertyContainer = xDocumentProperties->getUserDefinedProperties();
             uno::Reference<beans::XPropertyContainer> xDocumentPropertyContainer = m_xDocumentProperties->getUserDefinedProperties();
             uno::Reference<beans::XPropertySet> xClipboardPropertySet(xClipboardPropertyContainer, uno::UNO_QUERY);
@@ -5958,7 +6006,11 @@ RTFError RTFDocumentImpl::popState()
                 try
                 {
                     if (lcl_containsProperty(aDocumentProperties, rKey))
-                        xDocumentPropertySet->setPropertyValue(rKey, aValue);
+                    {
+                        // When pasting, don't update existing properties.
+                        if (!m_bIsNewDoc)
+                            xDocumentPropertySet->setPropertyValue(rKey, aValue);
+                    }
                     else
                         xDocumentPropertyContainer->addProperty(rKey, beans::PropertyAttribute::REMOVABLE, aValue);
                 }
diff --git a/writerfilter/source/rtftok/rtflistener.hxx b/writerfilter/source/rtftok/rtflistener.hxx
index dbce218..ea3d9e2 100644
--- a/writerfilter/source/rtftok/rtflistener.hxx
+++ b/writerfilter/source/rtftok/rtflistener.hxx
@@ -30,7 +30,8 @@ enum class RTFError
     GROUP_OVER,
     UNEXPECTED_EOF,
     HEX_INVALID,
-    CHAR_OVER
+    CHAR_OVER,
+    CLASSIFICATION
 };
 
 /**
commit e75f6e549eb825c310d16d11babf0fba5ee7fd7a
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 10 08:58:00 2016 +0100

    sfx2: make SfxClassificationHelper not require a full doc shell
    
    So that input filters can build their own doc properties and can also
    use CheckPaste() without having the full original document around.
    
    Change-Id: I0b8a63702f73ce04e8728a360b56ab9d1ca67af1

diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx
index 5a58fcc..9ce8933 100644
--- a/include/sfx2/classificationhelper.hxx
+++ b/include/sfx2/classificationhelper.hxx
@@ -13,6 +13,8 @@
 #include <memory>
 #include <vector>
 
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
 #include <rtl/ustring.hxx>
 #include <sfx2/dllapi.h>
 
@@ -39,11 +41,12 @@ class SFX2_DLLPUBLIC SfxClassificationHelper
 
 public:
     /// Does the document have any BAILS properties?
-    static bool IsClassified(SfxObjectShell& rObjectShell);
-    /// Checks if pasting from rSource to rDestination would leak information.
-    static SfxClassificationCheckPasteResult CheckPaste(SfxObjectShell& rSource, SfxObjectShell& rDestination);
+    static bool IsClassified(const css::uno::Reference<css::document::XDocumentProperties>& xDocumentProperties);
+    /// Checks if pasting from xSource to xDestination would leak information.
+    static SfxClassificationCheckPasteResult CheckPaste(const css::uno::Reference<css::document::XDocumentProperties>& xSource,
+            const css::uno::Reference<css::document::XDocumentProperties>& xDestination);
 
-    SfxClassificationHelper(SfxObjectShell& rObjectShell);
+    SfxClassificationHelper(const css::uno::Reference<css::document::XDocumentProperties>& xDocumentProperties);
     ~SfxClassificationHelper();
     const OUString& GetBACName();
     /// Return all possible valid category names, based on the policy.
diff --git a/sc/source/ui/view/formatsh.cxx b/sc/source/ui/view/formatsh.cxx
index b4114b9..71434872 100644
--- a/sc/source/ui/view/formatsh.cxx
+++ b/sc/source/ui/view/formatsh.cxx
@@ -974,7 +974,7 @@ void ScFormatShell::ExecuteStyle( SfxRequest& rReq )
         if (pArgs && pArgs->GetItemState(nSlotId, false, &pItem) == SfxItemState::SET)
         {
             const OUString& rName = static_cast<const SfxStringItem*>(pItem)->GetValue();
-            SfxClassificationHelper aHelper(*pDocSh);
+            SfxClassificationHelper aHelper(pDocSh->getDocProperties());
             aHelper.SetBACName(rName);
         }
         else
diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx
index ab17cd6..e7d431c 100644
--- a/sd/source/ui/view/drviews2.cxx
+++ b/sd/source/ui/view/drviews2.cxx
@@ -1153,7 +1153,7 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq)
                 {
                     if (SfxObjectShell* pObjectShell = pViewFrame->GetObjectShell())
                     {
-                        SfxClassificationHelper aHelper(*pObjectShell);
+                        SfxClassificationHelper aHelper(pObjectShell->getDocProperties());
                         aHelper.SetBACName(rName);
                     }
                 }
diff --git a/sfx2/source/view/classificationcontroller.cxx b/sfx2/source/view/classificationcontroller.cxx
index 1dc8134..788eddf 100644
--- a/sfx2/source/view/classificationcontroller.cxx
+++ b/sfx2/source/view/classificationcontroller.cxx
@@ -164,7 +164,7 @@ void ClassificationCategoriesController::statusChanged(const frame::FeatureState
     if (!pObjectShell)
         return;
 
-    SfxClassificationHelper aHelper(*pObjectShell);
+    SfxClassificationHelper aHelper(pObjectShell->getDocProperties());
     if (m_pCategories->GetEntryCount() == 0)
     {
         std::vector<OUString> aNames = aHelper.GetBACNames();
diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx
index 6950048..2abcff8 100644
--- a/sfx2/source/view/classificationhelper.cxx
+++ b/sfx2/source/view/classificationhelper.cxx
@@ -321,18 +321,18 @@ public:
     SfxClassificationCategory m_aCategory;
     /// Possible categories of a policy to choose from.
     std::vector<SfxClassificationCategory> m_aCategories;
-    SfxObjectShell& m_rObjectShell;
+    const uno::Reference<document::XDocumentProperties>& m_xDocumentProperties;
 
-    Impl(SfxObjectShell& rObjectShell);
+    Impl(const uno::Reference<document::XDocumentProperties>& xDocumentProperties);
     void parsePolicy();
-    /// Synchronize m_aLabels back to the object shell.
-    void pushToObjectShell();
+    /// Synchronize m_aLabels back to the document properties.
+    void pushToDocumentProperties();
     /// Set the classification start date to the system time.
     void setStartValidity();
 };
 
-SfxClassificationHelper::Impl::Impl(SfxObjectShell& rObjectShell)
-    : m_rObjectShell(rObjectShell)
+SfxClassificationHelper::Impl::Impl(const uno::Reference<document::XDocumentProperties>& xDocumentProperties)
+    : m_xDocumentProperties(xDocumentProperties)
 {
 }
 
@@ -384,10 +384,9 @@ void SfxClassificationHelper::Impl::setStartValidity()
     }
 }
 
-void SfxClassificationHelper::Impl::pushToObjectShell()
+void SfxClassificationHelper::Impl::pushToDocumentProperties()
 {
-    uno::Reference<document::XDocumentProperties> xDocumentProperties = m_rObjectShell.getDocProperties();
-    uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties();
+    uno::Reference<beans::XPropertyContainer> xPropertyContainer = m_xDocumentProperties->getUserDefinedProperties();
     uno::Reference<beans::XPropertySet> xPropertySet(xPropertyContainer, uno::UNO_QUERY);
     uno::Sequence<beans::Property> aProperties = xPropertySet->getPropertySetInfo()->getProperties();
     std::map<OUString, OUString> aLabels = m_aCategory.m_aLabels;
@@ -403,14 +402,13 @@ void SfxClassificationHelper::Impl::pushToObjectShell()
         }
         catch (const uno::Exception& rException)
         {
-            SAL_WARN("sfx.view", "pushToObjectShell() failed for property " << rLabel.first << ": " << rException.Message);
+            SAL_WARN("sfx.view", "pushDocumentProperties() failed for property " << rLabel.first << ": " << rException.Message);
         }
     }
 }
 
-bool SfxClassificationHelper::IsClassified(SfxObjectShell& rObjectShell)
+bool SfxClassificationHelper::IsClassified(const uno::Reference<document::XDocumentProperties>& xDocumentProperties)
 {
-    uno::Reference<document::XDocumentProperties> xDocumentProperties = rObjectShell.getDocProperties();
     uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties();
     if (!xPropertyContainer.is())
         return false;
@@ -426,15 +424,16 @@ bool SfxClassificationHelper::IsClassified(SfxObjectShell& rObjectShell)
     return false;
 }
 
-SfxClassificationCheckPasteResult SfxClassificationHelper::CheckPaste(SfxObjectShell& rSource, SfxObjectShell& rDestination)
+SfxClassificationCheckPasteResult SfxClassificationHelper::CheckPaste(const uno::Reference<document::XDocumentProperties>& xSource,
+        const uno::Reference<document::XDocumentProperties>& xDestination)
 {
-    bool bSourceClassified = SfxClassificationHelper::IsClassified(rSource);
+    bool bSourceClassified = SfxClassificationHelper::IsClassified(xSource);
     if (!bSourceClassified)
         // No classification on the source side. Return early, regardless the
         // state of the destination side.
         return SfxClassificationCheckPasteResult::None;
 
-    bool bDestinationClassified = SfxClassificationHelper::IsClassified(rDestination);
+    bool bDestinationClassified = SfxClassificationHelper::IsClassified(xDestination);
     if (bSourceClassified && !bDestinationClassified)
     {
         // Paste from a classified document to a non-classified one -> deny.
@@ -442,8 +441,8 @@ SfxClassificationCheckPasteResult SfxClassificationHelper::CheckPaste(SfxObjectS
     }
 
     // Remaining case: paste between two classified documents.
-    SfxClassificationHelper aSource(rSource);
-    SfxClassificationHelper aDestination(rDestination);
+    SfxClassificationHelper aSource(xSource);
+    SfxClassificationHelper aDestination(xDestination);
     if (aSource.GetImpactScale() != aDestination.GetImpactScale())
         // It's possible to compare them if they have the same scale.
         return SfxClassificationCheckPasteResult::None;
@@ -455,10 +454,9 @@ SfxClassificationCheckPasteResult SfxClassificationHelper::CheckPaste(SfxObjectS
     return SfxClassificationCheckPasteResult::None;
 }
 
-SfxClassificationHelper::SfxClassificationHelper(SfxObjectShell& rObjectShell)
-    : m_pImpl(o3tl::make_unique<Impl>(rObjectShell))
+SfxClassificationHelper::SfxClassificationHelper(const uno::Reference<document::XDocumentProperties>& xDocumentProperties)
+    : m_pImpl(o3tl::make_unique<Impl>(xDocumentProperties))
 {
-    uno::Reference<document::XDocumentProperties> xDocumentProperties = rObjectShell.getDocProperties();
     uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties();
     if (!xPropertyContainer.is())
         return;
@@ -660,7 +658,7 @@ void SfxClassificationHelper::SetBACName(const OUString& rName)
     m_pImpl->m_aCategory = *it;
 
     m_pImpl->setStartValidity();
-    m_pImpl->pushToObjectShell();
+    m_pImpl->pushToDocumentProperties();
     SfxViewFrame* pViewFrame = SfxViewFrame::Current();
     if (!pViewFrame)
         return;
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index bea3126..9775ff0 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -1343,10 +1343,10 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
                     }
                 }
 
-                if (SfxClassificationHelper::IsClassified(*xObjSh.get()))
+                if (SfxClassificationHelper::IsClassified(xObjSh->getDocProperties()))
                 {
                     // Document has BAILS properties, display an infobar accordingly.
-                    SfxClassificationHelper aHelper(*xObjSh.get());
+                    SfxClassificationHelper aHelper(xObjSh->getDocProperties());
                     aHelper.UpdateInfobar(*this);
                 }
 
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 69a7827..77e8069 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -3249,6 +3249,16 @@ void SwUiWriterTest::testTdf96961()
     CPPUNIT_ASSERT(nLast > nOther);
 }
 
+namespace
+{
+
+int checkShells(SwDocShell* pSource, SwDocShell* pDestination)
+{
+    return int(SfxClassificationHelper::CheckPaste(pSource->getDocProperties(), pDestination->getDocProperties()));
+}
+
+}
+
 void SwUiWriterTest::testClassificationPaste()
 {
     SwDocShell* pSourceShell = createDoc()->GetDocShell();
@@ -3258,17 +3268,17 @@ void SwUiWriterTest::testClassificationPaste()
     SwDocShell* pDestinationShell = createDoc()->GetDocShell();
 
     // Not classified source, not classified destination.
-    CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::None), int(SfxClassificationHelper::CheckPaste(*pSourceShell, *pDestinationShell)));
+    CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::None), checkShells(pSourceShell, pDestinationShell));
 
     // Classified source, not classified destination.
     uno::Sequence<beans::PropertyValue> aInternalOnly = comphelper::InitPropertySequence({{"Name", uno::makeAny(OUString("Internal Only"))}});
     lcl_dispatchCommand(xSourceComponent, ".uno:ClassificationApply", aInternalOnly);
-    CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::TargetDocNotClassified), int(SfxClassificationHelper::CheckPaste(*pSourceShell, *pDestinationShell)));
+    CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::TargetDocNotClassified), checkShells(pSourceShell, pDestinationShell));
 
     // Classified source and classified destination -- internal only has a higher level than confidential.
     uno::Sequence<beans::PropertyValue> aConfidential = comphelper::InitPropertySequence({{"Name", uno::makeAny(OUString("Confidential"))}});
     lcl_dispatchCommand(mxComponent, ".uno:ClassificationApply", aConfidential);
-    CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::DocClassificationTooLow), int(SfxClassificationHelper::CheckPaste(*pSourceShell, *pDestinationShell)));
+    CPPUNIT_ASSERT_EQUAL(int(SfxClassificationCheckPasteResult::DocClassificationTooLow), checkShells(pSourceShell, pDestinationShell));
 
     xSourceComponent->dispose();
 }
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index c5cadf9..86b2883 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -177,7 +177,7 @@ void SwEditShell::SetClassification(const OUString& rName)
     if (!pDocShell)
         return;
 
-    SfxClassificationHelper aHelper(*pDocShell);
+    SfxClassificationHelper aHelper(pDocShell->getDocProperties());
 
     bool bHadWatermark = !aHelper.GetDocumentWatermark().isEmpty();
 
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index 0e2b838..6d47e8f 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -3226,7 +3226,7 @@ bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
     if (!pSourceShell || !pDestinationShell)
         return true;
 
-    switch (SfxClassificationHelper::CheckPaste(*pSourceShell, *pDestinationShell))
+    switch (SfxClassificationHelper::CheckPaste(pSourceShell->getDocProperties(), pDestinationShell->getDocProperties()))
     {
     case SfxClassificationCheckPasteResult::None:
     {
commit b84f5a0efa4a24a3e8074bc27fb21529b9c4d3a6
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 10 08:23:37 2016 +0100

    RTF import: set user-defined metadata only after parsing all of them
    
    This helps setting all or no metadata in case an error would happen in
    the middle of parsing metadata entries.
    
    Change-Id: I349f53148627dd07f1304ebe00f0664bd23e26ea

diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 6dd561b..6bea01f 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -8,6 +8,7 @@
  */
 
 #include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/document/DocumentProperties.hpp>
 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
 #include <com/sun/star/graphic/GraphicProvider.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
@@ -2056,6 +2057,9 @@ RTFError RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
         case RTF_USERPROPS:
             // Container of all user-defined properties.
             m_aStates.top().eDestination = Destination::USERPROPS;
+            if (m_xDocumentProperties.is())
+                // Create a custom document properties to be able to process them later all at once.
+                m_xDocumentProperties = document::DocumentProperties::create(m_xContext);
             break;
         case RTF_PROPNAME:
             m_aStates.top().eDestination = Destination::PROPNAME;
@@ -5924,20 +5928,48 @@ RTFError RTFDocumentImpl::popState()
             if (m_aStates.top().aPropType == cppu::UnoType<OUString>::get())
                 aAny = uno::makeAny(aStaticVal);
 
-            // Set it.
-            try
-            {
-                if (lcl_containsProperty(aProperties, rKey))
-                    xPropertySet->setPropertyValue(rKey, aAny);
-                else
-                    xPropertyContainer->addProperty(rKey, beans::PropertyAttribute::REMOVABLE, aAny);
-            }
-            catch (const uno::Exception& rException)
+            xPropertyContainer->addProperty(rKey, beans::PropertyAttribute::REMOVABLE, aAny);
+        }
+        break;
+    case Destination::USERPROPS:
+    {
+        // These are the imported properties.
+        uno::Reference<document::XDocumentProperties> xDocumentProperties = m_xDocumentProperties;
+
+        // These are the real document properties.
+        uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(m_xDstDoc, uno::UNO_QUERY);
+        if (xDocumentPropertiesSupplier.is())
+            m_xDocumentProperties.set(xDocumentPropertiesSupplier->getDocumentProperties(), uno::UNO_QUERY);
+
+        if (m_xDocumentProperties.is())
+        {
+            uno::Reference<beans::XPropertyContainer> xClipboardPropertyContainer = xDocumentProperties->getUserDefinedProperties();
+            uno::Reference<beans::XPropertyContainer> xDocumentPropertyContainer = m_xDocumentProperties->getUserDefinedProperties();
+            uno::Reference<beans::XPropertySet> xClipboardPropertySet(xClipboardPropertyContainer, uno::UNO_QUERY);
+            uno::Reference<beans::XPropertySet> xDocumentPropertySet(xDocumentPropertyContainer, uno::UNO_QUERY);
+            uno::Sequence<beans::Property> aClipboardProperties = xClipboardPropertySet->getPropertySetInfo()->getProperties();
+            uno::Sequence<beans::Property> aDocumentProperties = xDocumentPropertySet->getPropertySetInfo()->getProperties();
+
+            for (const beans::Property& rProperty : aClipboardProperties)
             {
-                SAL_WARN("writerfilter", "failed to set property " << rKey << ": " << rException.Message);
+                const OUString& rKey = rProperty.Name;
+                uno::Any aValue = xClipboardPropertySet->getPropertyValue(rKey);
+
+                try
+                {
+                    if (lcl_containsProperty(aDocumentProperties, rKey))
+                        xDocumentPropertySet->setPropertyValue(rKey, aValue);
+                    else
+                        xDocumentPropertyContainer->addProperty(rKey, beans::PropertyAttribute::REMOVABLE, aValue);
+                }
+                catch (const uno::Exception& rException)
+                {
+                    SAL_WARN("writerfilter", "failed to set property " << rKey << ": " << rException.Message);
+                }
             }
         }
-        break;
+    }
+    break;
     default:
         break;
     }
commit 6a114b8ffaac52322c318d2dba543a2ad52cc892
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Mar 10 08:18:41 2016 +0100

    sw: make metadata available in copy result
    
    The "copy" part of copy&paste works in sw by creating a separate SwDoc,
    then copying the selection of the original SwDoc into it, so filters can
    easily just export the whole clipboard document. A side effect of this
    is that the clipboard document has no documnent shell, that would
    contain the metadata.
    
    Add a new member to MetaFieldManager that can store metadata in the
    clipboard case, let SwTransferable::GetData() write metadata there, and
    finally adapt the RTF export to look for metadata there as well.
    
    Change-Id: Icfe32abca4290af8bf5b24a34160c43d4c87c04a

diff --git a/sw/inc/fmtmeta.hxx b/sw/inc/fmtmeta.hxx
index ab1ac82..eb276df 100644
--- a/sw/inc/fmtmeta.hxx
+++ b/sw/inc/fmtmeta.hxx
@@ -31,6 +31,9 @@
 #include <vector>
 
 namespace com { namespace sun { namespace star {
+    namespace document {
+        class XDocumentProperties;
+    }
     namespace text {
         class XTextField;
     }
@@ -190,12 +193,14 @@ public:
 };
 
     /// knows all meta-fields in the document.
-class MetaFieldManager
+class SW_DLLPUBLIC MetaFieldManager
     : private ::boost::noncopyable
 {
 private:
     typedef ::std::vector< std::weak_ptr<MetaField> > MetaFieldList_t;
     MetaFieldList_t m_MetaFields;
+    /// Document properties of a clipboard document, empty for non-clipboard documents.
+    css::uno::Reference<css::document::XDocumentProperties> m_xDocumentProperties;
 
 public:
     MetaFieldManager();
@@ -205,6 +210,9 @@ public:
                 const bool bIsFixedLanguage = false );
     /// get all meta fields
     ::std::vector< css::uno::Reference<css::text::XTextField> > getMetaFields();
+    /// Copy document properties from rSource to m_xDocumentProperties.
+    void copyDocumentProperties(const SwDoc& rSource);
+    css::uno::Reference<css::document::XDocumentProperties> getDocumentProperties();
 };
 
 } // namespace sw
diff --git a/sw/source/core/txtnode/fmtatr2.cxx b/sw/source/core/txtnode/fmtatr2.cxx
index d709111..d4a4812 100644
--- a/sw/source/core/txtnode/fmtatr2.cxx
+++ b/sw/source/core/txtnode/fmtatr2.cxx
@@ -36,6 +36,8 @@
 #include <unostyle.hxx>
 #include <unoevent.hxx>
 #include <com/sun/star/text/RubyAdjust.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
 
 #include <cmdid.h>
 #include <com/sun/star/uno/Any.h>
@@ -827,6 +829,22 @@ MetaFieldManager::getMetaFields()
     return ret;
 }
 
+void MetaFieldManager::copyDocumentProperties(const SwDoc& rSource)
+{
+    const SwDocShell* pDocShell = rSource.GetDocShell();
+    if (!pDocShell)
+        return;
+
+    uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(pDocShell->GetModel(), uno::UNO_QUERY);
+    uno::Reference<util::XCloneable> xCloneable(xDocumentPropertiesSupplier->getDocumentProperties(), uno::UNO_QUERY);
+    m_xDocumentProperties.set(xCloneable->createClone(), uno::UNO_QUERY);
+}
+
+uno::Reference<document::XDocumentProperties> MetaFieldManager::getDocumentProperties()
+{
+    return m_xDocumentProperties;
+}
+
 } // namespace sw
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index 2c3c88b..6ce1099 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -46,6 +46,7 @@
 #endif
 #include <svx/xflclit.hxx>
 #include <editeng/hyphenzoneitem.hxx>
+#include <fmtmeta.hxx>
 
 using namespace ::com::sun::star;
 
@@ -485,6 +486,12 @@ void RtfExport::WriteUserProps()
         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(), uno::UNO_QUERY);
         xDocProps.set(xDPS->getDocumentProperties());
     }
+    else
+    {
+        // Clipboard document, read metadata from the meta field manager.
+        sw::MetaFieldManager& rManager = m_pDoc->GetMetaFieldManager();
+        xDocProps.set(rManager.getDocumentProperties());
+    }
 
     if (xDocProps.is())
     {
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index 76ffde6..0e2b838 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -123,6 +123,7 @@
 #include <vcl/svapp.hxx>
 #include <swserv.hxx>
 #include <calbck.hxx>
+#include <fmtmeta.hxx>
 
 #include <vcl/GraphicNativeTransform.hxx>
 #include <vcl/GraphicNativeMetadata.hxx>
@@ -380,6 +381,8 @@ namespace
         rDest.ReplaceStyles(rSrc, false);
 
         rSrcWrtShell.Copy(&rDest);
+
+        rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
     }
 
     void lclCheckAndPerformRotation(Graphic& aGraphic)


More information about the Libreoffice-commits mailing list