1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sfx2/classificationhelper.hxx>
16 #include <com/sun/star/beans/XPropertyContainer.hpp>
17 #include <com/sun/star/beans/Property.hpp>
18 #include <com/sun/star/beans/XPropertySet.hpp>
19 #include <com/sun/star/document/XDocumentProperties.hpp>
20 #include <com/sun/star/xml/sax/Parser.hpp>
21 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
22 #include <com/sun/star/xml/sax/SAXParseException.hpp>
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
25 #include <sal/log.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <sfx2/infobar.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <unotools/pathoptions.hxx>
30 #include <unotools/ucbstreamhelper.hxx>
31 #include <unotools/streamwrap.hxx>
32 #include <cppuhelper/implbase.hxx>
33 #include <sfx2/strings.hrc>
34 #include <sfx2/sfxresid.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include <tools/datetime.hxx>
37 #include <tools/diagnose_ex.h>
38 #include <unotools/datetime.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/settings.hxx>
41 #include <vcl/weld.hxx>
42 #include <svl/fstathelper.hxx>
44 #include <officecfg/Office/Common.hxx>
46 using namespace com::sun::star
;
51 const OUString
& PROP_BACNAME()
53 static const OUString
sProp("BusinessAuthorizationCategory:Name");
57 const OUString
& PROP_STARTVALIDITY()
59 static const OUString
sProp("Authorization:StartValidity");
63 const OUString
& PROP_NONE()
65 static const OUString
sProp("None");
69 const OUString
& PROP_IMPACTSCALE()
71 static const OUString
sProp("Impact:Scale");
75 const OUString
& PROP_IMPACTLEVEL()
77 static const OUString
sProp("Impact:Level:Confidentiality");
81 const OUString
& PROP_PREFIX_EXPORTCONTROL()
83 static const OUString
sProp("urn:bails:ExportControl:");
87 const OUString
& PROP_PREFIX_NATIONALSECURITY()
89 static const OUString
sProp("urn:bails:NationalSecurity:");
93 /// Represents one category of a classification policy.
94 class SfxClassificationCategory
97 /// PROP_BACNAME() is stored separately for easier lookup.
99 OUString m_aAbbreviatedName
; //< An abbreviation to display instead of m_aName.
100 OUString m_aIdentifier
; //< The Identifier of this entry.
101 size_t m_nConfidentiality
; //< 0 is the lowest (least-sensitive).
102 std::map
<OUString
, OUString
> m_aLabels
;
105 /// Parses a policy XML conforming to the TSCP BAF schema.
106 class SfxClassificationParser
: public cppu::WeakImplHelper
<xml::sax::XDocumentHandler
>
109 std::vector
<SfxClassificationCategory
> m_aCategories
;
110 std::vector
<OUString
> m_aMarkings
;
111 std::vector
<OUString
> m_aIPParts
;
112 std::vector
<OUString
> m_aIPPartNumbers
;
114 OUString m_aPolicyAuthorityName
;
115 bool m_bInPolicyAuthorityName
= false;
116 OUString m_aPolicyName
;
117 bool m_bInPolicyName
= false;
118 OUString m_aProgramID
;
119 bool m_bInProgramID
= false;
121 bool m_bInScale
= false;
122 OUString m_aConfidentalityValue
;
123 bool m_bInConfidentalityValue
= false;
124 OUString m_aIdentifier
;
125 bool m_bInIdentifier
= false;
127 bool m_bInValue
= false;
129 /// Pointer to a value in m_aCategories, the currently parsed category.
130 SfxClassificationCategory
* m_pCategory
= nullptr;
132 SfxClassificationParser();
134 void SAL_CALL
startDocument() override
;
136 void SAL_CALL
endDocument() override
;
138 void SAL_CALL
startElement(const OUString
& rName
, const uno::Reference
<xml::sax::XAttributeList
>& xAttribs
) override
;
140 void SAL_CALL
endElement(const OUString
& rName
) override
;
142 void SAL_CALL
characters(const OUString
& rChars
) override
;
144 void SAL_CALL
ignorableWhitespace(const OUString
& rWhitespaces
) override
;
146 void SAL_CALL
processingInstruction(const OUString
& rTarget
, const OUString
& rData
) override
;
148 void SAL_CALL
setDocumentLocator(const uno::Reference
<xml::sax::XLocator
>& xLocator
) override
;
151 SfxClassificationParser::SfxClassificationParser() = default;
153 void SAL_CALL
SfxClassificationParser::startDocument()
157 void SAL_CALL
SfxClassificationParser::endDocument()
161 void SAL_CALL
SfxClassificationParser::startElement(const OUString
& rName
, const uno::Reference
<xml::sax::XAttributeList
>& xAttribs
)
163 if (rName
== "baf:PolicyAuthorityName")
165 m_aPolicyAuthorityName
.clear();
166 m_bInPolicyAuthorityName
= true;
168 else if (rName
== "baf:PolicyName")
170 m_aPolicyName
.clear();
171 m_bInPolicyName
= true;
173 else if (rName
== "baf:ProgramID")
175 m_aProgramID
.clear();
176 m_bInProgramID
= true;
178 else if (rName
== "baf:BusinessAuthorizationCategory")
180 const OUString aName
= xAttribs
->getValueByName("Name");
181 if (!m_pCategory
&& !aName
.isEmpty())
183 OUString aIdentifier
= xAttribs
->getValueByName("Identifier");
185 // Create a new category and initialize it with the data that's true for all categories.
186 m_aCategories
.emplace_back(SfxClassificationCategory());
187 SfxClassificationCategory
& rCategory
= m_aCategories
.back();
189 rCategory
.m_aName
= aName
;
190 // Set the abbreviated name, if any, otherwise fallback on the full name.
191 const OUString aAbbreviatedName
= xAttribs
->getValueByName("loextAbbreviatedName");
192 rCategory
.m_aAbbreviatedName
= !aAbbreviatedName
.isEmpty() ? aAbbreviatedName
: aName
;
193 rCategory
.m_aIdentifier
= aIdentifier
;
195 rCategory
.m_aLabels
["PolicyAuthority:Name"] = m_aPolicyAuthorityName
;
196 rCategory
.m_aLabels
["Policy:Name"] = m_aPolicyName
;
197 rCategory
.m_aLabels
["BusinessAuthorization:Identifier"] = m_aProgramID
;
198 rCategory
.m_aLabels
["BusinessAuthorizationCategory:Identifier"] = aIdentifier
;
200 // Also initialize defaults.
201 rCategory
.m_aLabels
["PolicyAuthority:Identifier"] = PROP_NONE();
202 rCategory
.m_aLabels
["PolicyAuthority:Country"] = PROP_NONE();
203 rCategory
.m_aLabels
["Policy:Identifier"] = PROP_NONE();
204 rCategory
.m_aLabels
["BusinessAuthorization:Name"] = PROP_NONE();
205 rCategory
.m_aLabels
["BusinessAuthorization:Locator"] = PROP_NONE();
206 rCategory
.m_aLabels
["BusinessAuthorizationCategory:Identifier:OID"] = PROP_NONE();
207 rCategory
.m_aLabels
["BusinessAuthorizationCategory:Locator"] = PROP_NONE();
208 rCategory
.m_aLabels
["BusinessAuthorization:Locator"] = PROP_NONE();
209 rCategory
.m_aLabels
["MarkingPrecedence"] = PROP_NONE();
210 rCategory
.m_aLabels
["Marking:general-summary"].clear();
211 rCategory
.m_aLabels
["Marking:general-warning-statement"].clear();
212 rCategory
.m_aLabels
["Marking:general-warning-statement:ext:2"].clear();
213 rCategory
.m_aLabels
["Marking:general-warning-statement:ext:3"].clear();
214 rCategory
.m_aLabels
["Marking:general-warning-statement:ext:4"].clear();
215 rCategory
.m_aLabels
["Marking:general-distribution-statement"].clear();
216 rCategory
.m_aLabels
["Marking:general-distribution-statement:ext:2"].clear();
217 rCategory
.m_aLabels
["Marking:general-distribution-statement:ext:3"].clear();
218 rCategory
.m_aLabels
["Marking:general-distribution-statement:ext:4"].clear();
219 rCategory
.m_aLabels
[SfxClassificationHelper::PROP_DOCHEADER()].clear();
220 rCategory
.m_aLabels
[SfxClassificationHelper::PROP_DOCFOOTER()].clear();
221 rCategory
.m_aLabels
[SfxClassificationHelper::PROP_DOCWATERMARK()].clear();
222 rCategory
.m_aLabels
["Marking:email-first-line-of-text"].clear();
223 rCategory
.m_aLabels
["Marking:email-last-line-of-text"].clear();
224 rCategory
.m_aLabels
["Marking:email-subject-prefix"].clear();
225 rCategory
.m_aLabels
["Marking:email-subject-suffix"].clear();
226 rCategory
.m_aLabels
[PROP_STARTVALIDITY()] = PROP_NONE();
227 rCategory
.m_aLabels
["Authorization:StopValidity"] = PROP_NONE();
228 m_pCategory
= &rCategory
;
231 else if (rName
== "loext:Marking")
233 OUString aName
= xAttribs
->getValueByName("Name");
234 m_aMarkings
.push_back(aName
);
236 else if (rName
== "loext:IntellectualPropertyPart")
238 OUString aName
= xAttribs
->getValueByName("Name");
239 m_aIPParts
.push_back(aName
);
241 else if (rName
== "loext:IntellectualPropertyPartNumber")
243 OUString aName
= xAttribs
->getValueByName("Name");
244 m_aIPPartNumbers
.push_back(aName
);
246 else if (rName
== "baf:Scale")
251 else if (rName
== "baf:ConfidentalityValue")
253 m_aConfidentalityValue
.clear();
254 m_bInConfidentalityValue
= true;
256 else if (rName
== "baf:Identifier")
258 m_aIdentifier
.clear();
259 m_bInIdentifier
= true;
261 else if (rName
== "baf:Value")
268 void SAL_CALL
SfxClassificationParser::endElement(const OUString
& rName
)
270 if (rName
== "baf:PolicyAuthorityName")
271 m_bInPolicyAuthorityName
= false;
272 else if (rName
== "baf:PolicyName")
273 m_bInPolicyName
= false;
274 else if (rName
== "baf:ProgramID")
275 m_bInProgramID
= false;
276 else if (rName
== "baf:BusinessAuthorizationCategory")
277 m_pCategory
= nullptr;
278 else if (rName
== "baf:Scale")
282 m_pCategory
->m_aLabels
[PROP_IMPACTSCALE()] = m_aScale
;
284 else if (rName
== "baf:ConfidentalityValue")
286 m_bInConfidentalityValue
= false;
289 std::map
<OUString
, OUString
>& rLabels
= m_pCategory
->m_aLabels
;
290 rLabels
[PROP_IMPACTLEVEL()] = m_aConfidentalityValue
;
291 m_pCategory
->m_nConfidentiality
= m_aConfidentalityValue
.toInt32(); // 0-based class sensitivity; 0 is lowest.
292 // Set the two other type of levels as well, if they're not set
293 // yet: they're optional in BAF, but not in BAILS.
294 rLabels
.try_emplace("Impact:Level:Integrity", m_aConfidentalityValue
);
295 rLabels
.try_emplace("Impact:Level:Availability", m_aConfidentalityValue
);
298 else if (rName
== "baf:Identifier")
299 m_bInIdentifier
= false;
300 else if (rName
== "baf:Value")
304 if (m_aIdentifier
== "Document: Header")
305 m_pCategory
->m_aLabels
[SfxClassificationHelper::PROP_DOCHEADER()] = m_aValue
;
306 else if (m_aIdentifier
== "Document: Footer")
307 m_pCategory
->m_aLabels
[SfxClassificationHelper::PROP_DOCFOOTER()] = m_aValue
;
308 else if (m_aIdentifier
== "Document: Watermark")
309 m_pCategory
->m_aLabels
[SfxClassificationHelper::PROP_DOCWATERMARK()] = m_aValue
;
314 void SAL_CALL
SfxClassificationParser::characters(const OUString
& rChars
)
316 if (m_bInPolicyAuthorityName
)
317 m_aPolicyAuthorityName
+= rChars
;
318 else if (m_bInPolicyName
)
319 m_aPolicyName
+= rChars
;
320 else if (m_bInProgramID
)
321 m_aProgramID
+= rChars
;
324 else if (m_bInConfidentalityValue
)
325 m_aConfidentalityValue
+= rChars
;
326 else if (m_bInIdentifier
)
327 m_aIdentifier
+= rChars
;
332 void SAL_CALL
SfxClassificationParser::ignorableWhitespace(const OUString
& /*rWhitespace*/)
336 void SAL_CALL
SfxClassificationParser::processingInstruction(const OUString
& /*rTarget*/, const OUString
& /*rData*/)
340 void SAL_CALL
SfxClassificationParser::setDocumentLocator(const uno::Reference
<xml::sax::XLocator
>& /*xLocator*/)
344 } // anonymous namespace
346 /// Implementation details of SfxClassificationHelper.
347 class SfxClassificationHelper::Impl
350 /// Selected categories, one category for each policy type.
351 std::map
<SfxClassificationPolicyType
, SfxClassificationCategory
> m_aCategory
;
352 /// Possible categories of a policy to choose from.
353 std::vector
<SfxClassificationCategory
> m_aCategories
;
354 std::vector
<OUString
> m_aMarkings
;
355 std::vector
<OUString
> m_aIPParts
;
356 std::vector
<OUString
> m_aIPPartNumbers
;
358 uno::Reference
<document::XDocumentProperties
> m_xDocumentProperties
;
360 bool m_bUseLocalized
;
362 explicit Impl(uno::Reference
<document::XDocumentProperties
> xDocumentProperties
, bool bUseLocalized
);
364 /// Synchronize m_aLabels back to the document properties.
365 void pushToDocumentProperties();
366 /// Set the classification start date to the system time.
367 void setStartValidity(SfxClassificationPolicyType eType
);
370 SfxClassificationHelper::Impl::Impl(uno::Reference
<document::XDocumentProperties
> xDocumentProperties
, bool bUseLocalized
)
371 : m_xDocumentProperties(std::move(xDocumentProperties
))
372 , m_bUseLocalized(bUseLocalized
)
377 void SfxClassificationHelper::Impl::parsePolicy()
379 uno::Reference
<uno::XComponentContext
> xComponentContext
= comphelper::getProcessComponentContext();
380 SvtPathOptions aOptions
;
381 OUString aPath
= aOptions
.GetClassificationPath();
383 // See if there is a localized variant next to the configured XML.
384 OUString
aExtension(".xml");
385 if (aPath
.endsWith(aExtension
) && m_bUseLocalized
)
387 OUString aBase
= aPath
.copy(0, aPath
.getLength() - aExtension
.getLength());
388 const LanguageTag
& rLanguageTag
= Application::GetSettings().GetLanguageTag();
389 // Expected format is "<original path>_xx-XX.xml".
390 OUString aLocalized
= aBase
+ "_" + rLanguageTag
.getBcp47() + aExtension
;
391 if (FStatHelper::IsDocument(aLocalized
))
395 std::unique_ptr
<SvStream
> pStream
= utl::UcbStreamHelper::CreateStream(aPath
, StreamMode::READ
);
396 uno::Reference
<io::XInputStream
> xInputStream(new utl::OStreamWrapper(std::move(pStream
)));
397 xml::sax::InputSource aParserInput
;
398 aParserInput
.aInputStream
= xInputStream
;
400 uno::Reference
<xml::sax::XParser
> xParser
= xml::sax::Parser::create(xComponentContext
);
401 rtl::Reference
<SfxClassificationParser
> xClassificationParser(new SfxClassificationParser());
402 uno::Reference
<xml::sax::XDocumentHandler
> xHandler(xClassificationParser
.get());
403 xParser
->setDocumentHandler(xHandler
);
406 xParser
->parseStream(aParserInput
);
408 catch (const xml::sax::SAXParseException
&)
410 TOOLS_WARN_EXCEPTION("sfx.view", "parsePolicy() failed");
412 m_aCategories
= xClassificationParser
->m_aCategories
;
413 m_aMarkings
= xClassificationParser
->m_aMarkings
;
414 m_aIPParts
= xClassificationParser
->m_aIPParts
;
415 m_aIPPartNumbers
= xClassificationParser
->m_aIPPartNumbers
;
418 static bool lcl_containsProperty(const uno::Sequence
<beans::Property
>& rProperties
, const OUString
& rName
)
420 return std::any_of(rProperties
.begin(), rProperties
.end(), [&](const beans::Property
& rProperty
)
422 return rProperty
.Name
== rName
;
426 void SfxClassificationHelper::Impl::setStartValidity(SfxClassificationPolicyType eType
)
428 auto itCategory
= m_aCategory
.find(eType
);
429 if (itCategory
== m_aCategory
.end())
432 SfxClassificationCategory
& rCategory
= itCategory
->second
;
433 auto it
= rCategory
.m_aLabels
.find(policyTypeToString(eType
) + PROP_STARTVALIDITY());
434 if (it
!= rCategory
.m_aLabels
.end())
436 if (it
->second
== PROP_NONE())
438 // The policy left the start date unchanged, replace it with the system time.
439 util::DateTime aDateTime
= DateTime(DateTime::SYSTEM
).GetUNODateTime();
440 it
->second
= utl::toISO8601(aDateTime
);
445 void SfxClassificationHelper::Impl::pushToDocumentProperties()
447 uno::Reference
<beans::XPropertyContainer
> xPropertyContainer
= m_xDocumentProperties
->getUserDefinedProperties();
448 uno::Reference
<beans::XPropertySet
> xPropertySet(xPropertyContainer
, uno::UNO_QUERY
);
449 uno::Sequence
<beans::Property
> aProperties
= xPropertySet
->getPropertySetInfo()->getProperties();
450 for (auto& rPair
: m_aCategory
)
452 SfxClassificationPolicyType eType
= rPair
.first
;
453 SfxClassificationCategory
& rCategory
= rPair
.second
;
454 std::map
<OUString
, OUString
> aLabels
= rCategory
.m_aLabels
;
455 aLabels
[policyTypeToString(eType
) + PROP_BACNAME()] = rCategory
.m_aName
;
456 for (const auto& rLabel
: aLabels
)
460 if (lcl_containsProperty(aProperties
, rLabel
.first
))
461 xPropertySet
->setPropertyValue(rLabel
.first
, uno::makeAny(rLabel
.second
));
463 xPropertyContainer
->addProperty(rLabel
.first
, beans::PropertyAttribute::REMOVABLE
, uno::makeAny(rLabel
.second
));
465 catch (const uno::Exception
&)
467 TOOLS_WARN_EXCEPTION("sfx.view", "pushDocumentProperties() failed for property " << rLabel
.first
);
473 bool SfxClassificationHelper::IsClassified(const uno::Reference
<document::XDocumentProperties
>& xDocumentProperties
)
475 uno::Reference
<beans::XPropertyContainer
> xPropertyContainer
= xDocumentProperties
->getUserDefinedProperties();
476 if (!xPropertyContainer
.is())
479 uno::Reference
<beans::XPropertySet
> xPropertySet(xPropertyContainer
, uno::UNO_QUERY
);
480 const uno::Sequence
<beans::Property
> aProperties
= xPropertySet
->getPropertySetInfo()->getProperties();
481 for (const beans::Property
& rProperty
: aProperties
)
483 if (rProperty
.Name
.startsWith("urn:bails:"))
490 SfxClassificationCheckPasteResult
SfxClassificationHelper::CheckPaste(const uno::Reference
<document::XDocumentProperties
>& xSource
,
491 const uno::Reference
<document::XDocumentProperties
>& xDestination
)
493 if (!SfxClassificationHelper::IsClassified(xSource
))
494 // No classification on the source side. Return early, regardless the
495 // state of the destination side.
496 return SfxClassificationCheckPasteResult::None
;
498 if (!SfxClassificationHelper::IsClassified(xDestination
))
500 // Paste from a classified document to a non-classified one -> deny.
501 return SfxClassificationCheckPasteResult::TargetDocNotClassified
;
504 // Remaining case: paste between two classified documents.
505 SfxClassificationHelper
aSource(xSource
);
506 SfxClassificationHelper
aDestination(xDestination
);
507 if (aSource
.GetImpactScale() != aDestination
.GetImpactScale())
508 // It's possible to compare them if they have the same scale.
509 return SfxClassificationCheckPasteResult::None
;
511 if (aSource
.GetImpactLevel() > aDestination
.GetImpactLevel())
512 // Paste from a doc that has higher classification -> deny.
513 return SfxClassificationCheckPasteResult::DocClassificationTooLow
;
515 return SfxClassificationCheckPasteResult::None
;
518 bool SfxClassificationHelper::ShowPasteInfo(SfxClassificationCheckPasteResult eResult
)
522 case SfxClassificationCheckPasteResult::None
:
527 case SfxClassificationCheckPasteResult::TargetDocNotClassified
:
529 if (!Application::IsHeadlessModeEnabled())
531 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
532 VclMessageType::Info
, VclButtonsType::Ok
,
533 SfxResId(STR_TARGET_DOC_NOT_CLASSIFIED
)));
539 case SfxClassificationCheckPasteResult::DocClassificationTooLow
:
541 if (!Application::IsHeadlessModeEnabled())
543 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
544 VclMessageType::Info
, VclButtonsType::Ok
,
545 SfxResId(STR_DOC_CLASSIFICATION_TOO_LOW
)));
556 SfxClassificationHelper::SfxClassificationHelper(const uno::Reference
<document::XDocumentProperties
>& xDocumentProperties
, bool bUseLocalizedPolicy
)
557 : m_pImpl(std::make_unique
<Impl
>(xDocumentProperties
, bUseLocalizedPolicy
))
559 if (!xDocumentProperties
.is())
562 uno::Reference
<beans::XPropertyContainer
> xPropertyContainer
= xDocumentProperties
->getUserDefinedProperties();
563 if (!xPropertyContainer
.is())
566 uno::Reference
<beans::XPropertySet
> xPropertySet(xPropertyContainer
, uno::UNO_QUERY
);
567 const uno::Sequence
<beans::Property
> aProperties
= xPropertySet
->getPropertySetInfo()->getProperties();
568 for (const beans::Property
& rProperty
: aProperties
)
570 if (!rProperty
.Name
.startsWith("urn:bails:"))
573 uno::Any aAny
= xPropertySet
->getPropertyValue(rProperty
.Name
);
577 SfxClassificationPolicyType eType
= stringToPolicyType(rProperty
.Name
);
578 OUString aPrefix
= policyTypeToString(eType
);
579 if (!rProperty
.Name
.startsWith(aPrefix
))
580 // It's a prefix we did not recognize, ignore.
583 //TODO: Support abbreviated names(?)
584 if (rProperty
.Name
== (aPrefix
+ PROP_BACNAME()))
585 m_pImpl
->m_aCategory
[eType
].m_aName
= aValue
;
587 m_pImpl
->m_aCategory
[eType
].m_aLabels
[rProperty
.Name
] = aValue
;
592 SfxClassificationHelper::~SfxClassificationHelper() = default;
594 std::vector
<OUString
> const & SfxClassificationHelper::GetMarkings() const
596 return m_pImpl
->m_aMarkings
;
599 std::vector
<OUString
> const & SfxClassificationHelper::GetIntellectualPropertyParts() const
601 return m_pImpl
->m_aIPParts
;
604 std::vector
<OUString
> const & SfxClassificationHelper::GetIntellectualPropertyPartNumbers() const
606 return m_pImpl
->m_aIPPartNumbers
;
609 const OUString
& SfxClassificationHelper::GetBACName(SfxClassificationPolicyType eType
) const
611 return m_pImpl
->m_aCategory
[eType
].m_aName
;
614 const OUString
& SfxClassificationHelper::GetAbbreviatedBACName(const OUString
& sFullName
)
616 for (const auto& category
: m_pImpl
->m_aCategories
)
618 if (category
.m_aName
== sFullName
)
619 return category
.m_aAbbreviatedName
;
625 OUString
SfxClassificationHelper::GetBACNameForIdentifier(const OUString
& sIdentifier
)
627 if (sIdentifier
.isEmpty())
630 for (const auto& category
: m_pImpl
->m_aCategories
)
632 if (category
.m_aIdentifier
== sIdentifier
)
633 return category
.m_aName
;
639 OUString
SfxClassificationHelper::GetHigherClass(const OUString
& first
, const OUString
& second
)
641 size_t nFirstConfidentiality
= 0;
642 size_t nSecondConfidentiality
= 0;
643 for (const auto& category
: m_pImpl
->m_aCategories
)
645 if (category
.m_aName
== first
)
646 nFirstConfidentiality
= category
.m_nConfidentiality
;
647 if (category
.m_aName
== second
)
648 nSecondConfidentiality
= category
.m_nConfidentiality
;
651 return nFirstConfidentiality
>= nSecondConfidentiality
? first
: second
;
654 bool SfxClassificationHelper::HasImpactLevel()
656 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
657 if (itCategory
== m_pImpl
->m_aCategory
.end())
660 SfxClassificationCategory
& rCategory
= itCategory
->second
;
661 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTSCALE());
662 if (it
== rCategory
.m_aLabels
.end())
665 it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTLEVEL());
666 return it
!= rCategory
.m_aLabels
.end();
669 bool SfxClassificationHelper::HasDocumentHeader()
671 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
672 if (itCategory
== m_pImpl
->m_aCategory
.end())
675 SfxClassificationCategory
& rCategory
= itCategory
->second
;
676 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_DOCHEADER());
677 return it
!= rCategory
.m_aLabels
.end() && !it
->second
.isEmpty();
680 bool SfxClassificationHelper::HasDocumentFooter()
682 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
683 if (itCategory
== m_pImpl
->m_aCategory
.end())
686 SfxClassificationCategory
& rCategory
= itCategory
->second
;
687 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_DOCFOOTER());
688 return it
!= rCategory
.m_aLabels
.end() && !it
->second
.isEmpty();
691 InfobarType
SfxClassificationHelper::GetImpactLevelType()
695 aRet
= InfobarType::WARNING
;
697 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
698 if (itCategory
== m_pImpl
->m_aCategory
.end())
701 SfxClassificationCategory
& rCategory
= itCategory
->second
;
702 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTSCALE());
703 OUString aScale
= it
->second
;
704 if (it
== rCategory
.m_aLabels
.end())
707 it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTLEVEL());
708 OUString aLevel
= it
->second
;
709 if (it
== rCategory
.m_aLabels
.end())
712 // The spec defines two valid scale values: FIPS-199 and UK-Cabinet.
713 if (aScale
== "UK-Cabinet")
716 aRet
= InfobarType::SUCCESS
;
717 else if (aLevel
== "1")
718 aRet
= InfobarType::WARNING
;
719 else if (aLevel
== "2")
720 aRet
= InfobarType::WARNING
;
721 else if (aLevel
== "3")
722 aRet
= InfobarType::DANGER
;
724 else if (aScale
== "FIPS-199")
727 aRet
= InfobarType::SUCCESS
;
728 else if (aLevel
== "Moderate")
729 aRet
= InfobarType::WARNING
;
730 else if (aLevel
== "High")
731 aRet
= InfobarType::DANGER
;
736 sal_Int32
SfxClassificationHelper::GetImpactLevel()
740 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
741 if (itCategory
== m_pImpl
->m_aCategory
.end())
744 SfxClassificationCategory
& rCategory
= itCategory
->second
;
745 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTSCALE());
746 if (it
== rCategory
.m_aLabels
.end())
748 OUString aScale
= it
->second
;
750 it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTLEVEL());
751 if (it
== rCategory
.m_aLabels
.end())
753 OUString aLevel
= it
->second
;
755 if (aScale
== "UK-Cabinet")
757 sal_Int32 nValue
= aLevel
.toInt32();
758 if (nValue
< 0 || nValue
> 3)
762 else if (aScale
== "FIPS-199")
764 static std::map
<OUString
, sal_Int32
> const aValues
770 auto itValues
= aValues
.find(aLevel
);
771 if (itValues
== aValues
.end())
773 nRet
= itValues
->second
;
779 OUString
SfxClassificationHelper::GetImpactScale()
781 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
782 if (itCategory
== m_pImpl
->m_aCategory
.end())
785 SfxClassificationCategory
& rCategory
= itCategory
->second
;
786 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_IMPACTSCALE());
787 if (it
!= rCategory
.m_aLabels
.end())
793 OUString
SfxClassificationHelper::GetDocumentWatermark()
795 auto itCategory
= m_pImpl
->m_aCategory
.find(SfxClassificationPolicyType::IntellectualProperty
);
796 if (itCategory
== m_pImpl
->m_aCategory
.end())
799 SfxClassificationCategory
& rCategory
= itCategory
->second
;
800 auto it
= rCategory
.m_aLabels
.find(PROP_PREFIX_INTELLECTUALPROPERTY() + PROP_DOCWATERMARK());
801 if (it
!= rCategory
.m_aLabels
.end())
807 std::vector
<OUString
> SfxClassificationHelper::GetBACNames()
809 if (m_pImpl
->m_aCategories
.empty())
810 m_pImpl
->parsePolicy();
812 std::vector
<OUString
> aRet
;
813 std::transform(m_pImpl
->m_aCategories
.begin(), m_pImpl
->m_aCategories
.end(), std::back_inserter(aRet
), [](const SfxClassificationCategory
& rCategory
)
815 return rCategory
.m_aName
;
820 std::vector
<OUString
> SfxClassificationHelper::GetBACIdentifiers()
822 if (m_pImpl
->m_aCategories
.empty())
823 m_pImpl
->parsePolicy();
825 std::vector
<OUString
> aRet
;
826 std::transform(m_pImpl
->m_aCategories
.begin(), m_pImpl
->m_aCategories
.end(), std::back_inserter(aRet
), [](const SfxClassificationCategory
& rCategory
)
828 return rCategory
.m_aIdentifier
;
833 std::vector
<OUString
> SfxClassificationHelper::GetAbbreviatedBACNames()
835 if (m_pImpl
->m_aCategories
.empty())
836 m_pImpl
->parsePolicy();
838 std::vector
<OUString
> aRet
;
839 std::transform(m_pImpl
->m_aCategories
.begin(), m_pImpl
->m_aCategories
.end(), std::back_inserter(aRet
), [](const SfxClassificationCategory
& rCategory
)
841 return rCategory
.m_aAbbreviatedName
;
846 void SfxClassificationHelper::SetBACName(const OUString
& rName
, SfxClassificationPolicyType eType
)
848 if (m_pImpl
->m_aCategories
.empty())
849 m_pImpl
->parsePolicy();
851 auto it
= std::find_if(m_pImpl
->m_aCategories
.begin(), m_pImpl
->m_aCategories
.end(), [&](const SfxClassificationCategory
& rCategory
)
853 return rCategory
.m_aName
== rName
;
855 if (it
== m_pImpl
->m_aCategories
.end())
857 SAL_WARN("sfx.view", "'" << rName
<< "' is not a recognized category name");
861 m_pImpl
->m_aCategory
[eType
].m_aName
= it
->m_aName
;
862 m_pImpl
->m_aCategory
[eType
].m_aAbbreviatedName
= it
->m_aAbbreviatedName
;
863 m_pImpl
->m_aCategory
[eType
].m_nConfidentiality
= it
->m_nConfidentiality
;
864 m_pImpl
->m_aCategory
[eType
].m_aLabels
.clear();
865 const OUString
& rPrefix
= policyTypeToString(eType
);
866 for (const auto& rLabel
: it
->m_aLabels
)
867 m_pImpl
->m_aCategory
[eType
].m_aLabels
[rPrefix
+ rLabel
.first
] = rLabel
.second
;
869 m_pImpl
->setStartValidity(eType
);
870 m_pImpl
->pushToDocumentProperties();
871 SfxViewFrame
* pViewFrame
= SfxViewFrame::Current();
875 UpdateInfobar(*pViewFrame
);
878 void SfxClassificationHelper::UpdateInfobar(SfxViewFrame
& rViewFrame
)
880 OUString aBACName
= GetBACName(SfxClassificationPolicyType::IntellectualProperty
);
881 bool bImpactLevel
= HasImpactLevel();
882 if (!aBACName
.isEmpty() && bImpactLevel
)
884 OUString aMessage
= SfxResId(STR_CLASSIFIED_DOCUMENT
);
885 aMessage
= aMessage
.replaceFirst("%1", aBACName
);
887 rViewFrame
.RemoveInfoBar("classification");
888 rViewFrame
.AppendInfoBar("classification", "", aMessage
, GetImpactLevelType());
892 SfxClassificationPolicyType
SfxClassificationHelper::stringToPolicyType(const OUString
& rType
)
894 if (rType
.startsWith(PROP_PREFIX_EXPORTCONTROL()))
895 return SfxClassificationPolicyType::ExportControl
;
896 else if (rType
.startsWith(PROP_PREFIX_NATIONALSECURITY()))
897 return SfxClassificationPolicyType::NationalSecurity
;
899 return SfxClassificationPolicyType::IntellectualProperty
;
902 const OUString
& SfxClassificationHelper::policyTypeToString(SfxClassificationPolicyType eType
)
906 case SfxClassificationPolicyType::ExportControl
:
907 return PROP_PREFIX_EXPORTCONTROL();
909 case SfxClassificationPolicyType::NationalSecurity
:
910 return PROP_PREFIX_NATIONALSECURITY();
912 case SfxClassificationPolicyType::IntellectualProperty
:
916 return PROP_PREFIX_INTELLECTUALPROPERTY();
919 const OUString
& SfxClassificationHelper::PROP_DOCHEADER()
921 static const OUString
sProp("Marking:document-header");
925 const OUString
& SfxClassificationHelper::PROP_DOCFOOTER()
927 static const OUString
sProp("Marking:document-footer");
931 const OUString
& SfxClassificationHelper::PROP_DOCWATERMARK()
933 static const OUString
sProp("Marking:document-watermark");
937 const OUString
& SfxClassificationHelper::PROP_PREFIX_INTELLECTUALPROPERTY()
939 static const OUString
sProp("urn:bails:IntellectualProperty:");
943 SfxClassificationPolicyType
SfxClassificationHelper::getPolicyType()
945 sal_Int32 nPolicyTypeNumber
= officecfg::Office::Common::Classification::Policy::get();
946 auto eType
= static_cast<SfxClassificationPolicyType
>(nPolicyTypeNumber
);
956 OUString
getProperty(uno::Reference
<beans::XPropertyContainer
> const& rxPropertyContainer
,
957 OUString
const& rName
)
961 uno::Reference
<beans::XPropertySet
> xPropertySet(rxPropertyContainer
, uno::UNO_QUERY
);
962 return xPropertySet
->getPropertyValue(rName
).get
<OUString
>();
964 catch (const css::uno::Exception
&)
971 } // end anonymous namespace
973 sfx::ClassificationCreationOrigin
getCreationOriginProperty(uno::Reference
<beans::XPropertyContainer
> const & rxPropertyContainer
,
974 sfx::ClassificationKeyCreator
const & rKeyCreator
)
976 OUString sValue
= getProperty(rxPropertyContainer
, rKeyCreator
.makeCreationOriginKey());
977 if (sValue
.isEmpty())
978 return sfx::ClassificationCreationOrigin::NONE
;
980 return (sValue
== "BAF_POLICY")
981 ? sfx::ClassificationCreationOrigin::BAF_POLICY
982 : sfx::ClassificationCreationOrigin::MANUAL
;
987 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */