1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <tabprotection.hxx>
21 #include <svl/PasswordHelper.hxx>
22 #include <comphelper/docpasswordhelper.hxx>
23 #include <comphelper/hash.hxx>
24 #include <comphelper/sequence.hxx>
25 #include <osl/diagnose.h>
26 #include <document.hxx>
27 
28 #include <vector>
29 
30 #define DEBUG_TAB_PROTECTION 0
31 
32 #define URI_SHA1 u"http://www.w3.org/2000/09/xmldsig#sha1"
33 #define URI_SHA256_ODF12 u"http://www.w3.org/2000/09/xmldsig#sha256"
34 #define URI_SHA256_W3C u"http://www.w3.org/2001/04/xmlenc#sha256"
35 #define URI_XLS_LEGACY u"http://docs.oasis-open.org/office/ns/table/legacy-hash-excel"
36 
37 using namespace ::com::sun::star;
38 using ::com::sun::star::uno::Sequence;
39 using ::std::vector;
40 
needsPassHashRegen(const ScDocument & rDoc,ScPasswordHash eHash1,ScPasswordHash eHash2)41 bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash1, ScPasswordHash eHash2)
42 {
43     if (rDoc.IsDocProtected())
44     {
45         const ScDocProtection* p = rDoc.GetDocProtection();
46         if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
47             return true;
48     }
49 
50     SCTAB nTabCount = rDoc.GetTableCount();
51     for (SCTAB i = 0; i < nTabCount; ++i)
52     {
53         const ScTableProtection* p = rDoc.GetTabProtection(i);
54         if (!p || !p->isProtected())
55             // Sheet not protected.  Skip it.
56             continue;
57 
58         if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
59             return true;
60     }
61 
62     return false;
63 }
64 
getHashURI(ScPasswordHash eHash)65 OUString ScPassHashHelper::getHashURI(ScPasswordHash eHash)
66 {
67     switch (eHash)
68     {
69         case PASSHASH_SHA256:
70             return URI_SHA256_ODF12;
71         case PASSHASH_SHA1:
72             return URI_SHA1;
73         case PASSHASH_XL:
74             return URI_XLS_LEGACY;
75         case PASSHASH_UNSPECIFIED:
76         default:
77             ;
78     }
79     return OUString();
80 }
81 
getHashTypeFromURI(std::u16string_view rURI)82 ScPasswordHash ScPassHashHelper::getHashTypeFromURI(std::u16string_view rURI)
83 {
84     if (rURI == URI_SHA256_ODF12 || rURI == URI_SHA256_W3C)
85         return PASSHASH_SHA256;
86     if ( rURI == URI_SHA1 )
87         return PASSHASH_SHA1;
88     else if ( rURI == URI_XLS_LEGACY )
89         return PASSHASH_XL;
90     return PASSHASH_UNSPECIFIED;
91 }
92 
verifyPassword(const OUString & aPassText) const93 bool ScOoxPasswordHash::verifyPassword( const OUString& aPassText ) const
94 {
95     if (!hasPassword())
96         return false;
97 
98     const OUString aHash( comphelper::DocPasswordHelper::GetOoxHashAsBase64(
99                 aPassText, maSaltValue, mnSpinCount, comphelper::Hash::IterCount::APPEND, maAlgorithmName));
100     if (aHash.isEmpty())
101         // unsupported algorithm
102         return false;
103 
104     return aHash == maHashValue;
105 }
106 
~ScPassHashProtectable()107 ScPassHashProtectable::~ScPassHashProtectable()
108 {
109 }
110 
111 class ScTableProtectionImpl
112 {
113 public:
114     static Sequence<sal_Int8> hashPassword(const OUString& aPassText, ScPasswordHash eHash);
115     static Sequence<sal_Int8> hashPassword(const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash);
116 
117     explicit ScTableProtectionImpl(SCSIZE nOptSize);
118     explicit ScTableProtectionImpl(const ScTableProtectionImpl& r);
119 
isProtected() const120     bool isProtected() const { return mbProtected;}
121     bool isProtectedWithPass() const;
122     void setProtected(bool bProtected);
123 
isPasswordEmpty() const124     bool isPasswordEmpty() const { return mbEmptyPass;}
125     bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const;
126     void setPassword(const OUString& aPassText);
127     css::uno::Sequence<sal_Int8> getPasswordHash(
128         ScPasswordHash eHash, ScPasswordHash eHash2) const;
129     const ScOoxPasswordHash& getPasswordHash() const;
130     void setPasswordHash(
131         const css::uno::Sequence<sal_Int8>& aPassword,
132         ScPasswordHash eHash, ScPasswordHash eHash2);
133     void setPasswordHash( const OUString& rAlgorithmName, const OUString& rHashValue,
134             const OUString& rSaltValue, sal_uInt32 nSpinCount );
135     bool verifyPassword(const OUString& aPassText) const;
136 
137     bool isOptionEnabled(SCSIZE nOptId) const;
138     void setOption(SCSIZE nOptId, bool bEnabled);
139 
140     void setEnhancedProtection( const ::std::vector< ScEnhancedProtection > & rProt );
getEnhancedProtection() const141     const ::std::vector< ScEnhancedProtection > & getEnhancedProtection() const { return maEnhancedProtection;}
142     bool updateReference( UpdateRefMode, const ScDocument&, const ScRange& rWhere, SCCOL nDx, SCROW nDy, SCTAB nDz );
143     bool isBlockEditable( const ScRange& rRange ) const;
144     bool isSelectionEditable( const ScRangeList& rRangeList ) const;
145 
146 private:
147     OUString maPassText;
148     css::uno::Sequence<sal_Int8>   maPassHash;
149     ::std::vector<bool> maOptions;
150     bool mbEmptyPass;
151     bool mbProtected;
152     ScPasswordHash meHash1;
153     ScPasswordHash meHash2;
154     ScOoxPasswordHash maPasswordHash;
155     ::std::vector< ScEnhancedProtection > maEnhancedProtection;
156 };
157 
hashPassword(const OUString & aPassText,ScPasswordHash eHash)158 Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const OUString& aPassText, ScPasswordHash eHash)
159 {
160     Sequence<sal_Int8> aHash;
161     switch (eHash)
162     {
163         case PASSHASH_XL:
164             aHash = ::comphelper::DocPasswordHelper::GetXLHashAsSequence( aPassText );
165         break;
166         case PASSHASH_SHA1:
167             SvPasswordHelper::GetHashPassword(aHash, aPassText);
168         break;
169         case PASSHASH_SHA1_UTF8:
170             SvPasswordHelper::GetHashPasswordSHA1UTF8(aHash, aPassText);
171         break;
172         case PASSHASH_SHA256:
173             SvPasswordHelper::GetHashPasswordSHA256(aHash, aPassText);
174         break;
175         default:
176             ;
177     }
178     return aHash;
179 }
180 
hashPassword(const Sequence<sal_Int8> & rPassHash,ScPasswordHash eHash)181 Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(
182     const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash)
183 {
184     if (!rPassHash.hasElements() || eHash == PASSHASH_UNSPECIFIED)
185         return rPassHash;
186 
187     // TODO: Right now, we only support double-hash by SHA1.
188     if (eHash == PASSHASH_SHA1)
189     {
190         auto aChars = comphelper::sequenceToContainer<vector<char>>(rPassHash);
191 
192         Sequence<sal_Int8> aNewHash;
193         SvPasswordHelper::GetHashPassword(aNewHash, aChars.data(), aChars.size());
194         return aNewHash;
195     }
196 
197     return rPassHash;
198 }
199 
ScTableProtectionImpl(SCSIZE nOptSize)200 ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) :
201     maOptions(nOptSize),
202     mbEmptyPass(true),
203     mbProtected(false),
204     meHash1(PASSHASH_SHA1),
205     meHash2(PASSHASH_UNSPECIFIED)
206 {
207 }
208 
ScTableProtectionImpl(const ScTableProtectionImpl & r)209 ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) :
210     maPassText(r.maPassText),
211     maPassHash(r.maPassHash),
212     maOptions(r.maOptions),
213     mbEmptyPass(r.mbEmptyPass),
214     mbProtected(r.mbProtected),
215     meHash1(r.meHash1),
216     meHash2(r.meHash2),
217     maPasswordHash(r.maPasswordHash),
218     maEnhancedProtection(r.maEnhancedProtection)
219 {
220 }
221 
isProtectedWithPass() const222 bool ScTableProtectionImpl::isProtectedWithPass() const
223 {
224     if (!mbProtected)
225         return false;
226 
227     return !maPassText.isEmpty() || maPassHash.hasElements() || maPasswordHash.hasPassword();
228 }
229 
setProtected(bool bProtected)230 void ScTableProtectionImpl::setProtected(bool bProtected)
231 {
232     mbProtected = bProtected;
233     // We need to keep the old password even when the protection is off.  So,
234     // don't erase the password data here.
235 }
236 
setPassword(const OUString & aPassText)237 void ScTableProtectionImpl::setPassword(const OUString& aPassText)
238 {
239     // We can't hash it here because we don't know whether this document will
240     // get saved to Excel or ODF, depending on which we will need to use a
241     // different hashing algorithm.  One alternative is to hash it using all
242     // hash algorithms that we support, and store them all.
243 
244     maPassText = aPassText;
245     mbEmptyPass = aPassText.isEmpty();
246     if (mbEmptyPass)
247     {
248         maPassHash = Sequence<sal_Int8>();
249     }
250     maPasswordHash.clear();
251 }
252 
hasPasswordHash(ScPasswordHash eHash,ScPasswordHash eHash2) const253 bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
254 {
255     if (mbEmptyPass)
256         return true;
257 
258     if (!maPassText.isEmpty())
259         return true;
260 
261     if (meHash1 == eHash)
262     {
263         if (meHash2 == PASSHASH_UNSPECIFIED)
264             // single hash.
265             return true;
266 
267         return meHash2 == eHash2;
268     }
269 
270     return false;
271 }
272 
getPasswordHash(ScPasswordHash eHash,ScPasswordHash eHash2) const273 Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(
274     ScPasswordHash eHash, ScPasswordHash eHash2) const
275 {
276     Sequence<sal_Int8> aPassHash;
277 
278     if (mbEmptyPass)
279         // Flagged as empty.
280         return aPassHash;
281 
282     if (!maPassText.isEmpty())
283     {
284         // Cleartext password exists.  Hash it.
285         aPassHash = hashPassword(maPassText, eHash);
286         if (eHash2 != PASSHASH_UNSPECIFIED)
287             // Double-hash it.
288             aPassHash = hashPassword(aPassHash, eHash2);
289 
290         return aPassHash;
291     }
292     else
293     {
294         // No clear text password.  Check if we have a hash value of the right hash type.
295         if (meHash1 == eHash)
296         {
297             aPassHash = maPassHash;
298 
299             if (meHash2 == eHash2)
300                 // Matching double-hash requested.
301                 return aPassHash;
302             else if (meHash2 == PASSHASH_UNSPECIFIED)
303                 // primary hashing type match.  Double hash it by the requested
304                 // double-hash type.
305                 return hashPassword(aPassHash, eHash2);
306         }
307     }
308 
309     // failed.
310     return Sequence<sal_Int8>();
311 }
312 
getPasswordHash() const313 const ScOoxPasswordHash& ScTableProtectionImpl::getPasswordHash() const
314 {
315     return maPasswordHash;
316 }
317 
setPasswordHash(const uno::Sequence<sal_Int8> & aPassword,ScPasswordHash eHash,ScPasswordHash eHash2)318 void ScTableProtectionImpl::setPasswordHash(
319     const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
320 {
321     sal_Int32 nLen = aPassword.getLength();
322     mbEmptyPass = nLen <= 0;
323     meHash1 = eHash;
324     meHash2 = eHash2;
325     maPassHash = aPassword;
326 
327 #if DEBUG_TAB_PROTECTION
328     for (sal_Int8 n : aPassword)
329         printf("%2.2X ", static_cast<sal_uInt8>(n));
330     printf("\n");
331 #endif
332 }
333 
setPasswordHash(const OUString & rAlgorithmName,const OUString & rHashValue,const OUString & rSaltValue,sal_uInt32 nSpinCount)334 void ScTableProtectionImpl::setPasswordHash( const OUString& rAlgorithmName, const OUString& rHashValue,
335         const OUString& rSaltValue, sal_uInt32 nSpinCount )
336 {
337     if (!rHashValue.isEmpty())
338     {
339         // Invalidate the other hashes.
340         setPasswordHash( uno::Sequence<sal_Int8>(), PASSHASH_UNSPECIFIED, PASSHASH_UNSPECIFIED);
341 
342         // We don't know whether this is an empty password (or would
343         // unnecessarily have to try to verify an empty password), assume it is
344         // not. A later verifyPassword() with an empty password will determine.
345         // If this was not set to false then a verifyPassword() with an empty
346         // password would unlock even if this hash here wasn't for an empty
347         // password. Ugly stuff.
348         mbEmptyPass = false;
349     }
350 
351     maPasswordHash.maAlgorithmName  = rAlgorithmName;
352     maPasswordHash.maHashValue      = rHashValue;
353     maPasswordHash.maSaltValue      = rSaltValue;
354     maPasswordHash.mnSpinCount      = nSpinCount;
355 }
356 
verifyPassword(const OUString & aPassText) const357 bool ScTableProtectionImpl::verifyPassword(const OUString& aPassText) const
358 {
359 #if DEBUG_TAB_PROTECTION
360     fprintf(stdout, "ScTableProtectionImpl::verifyPassword: input = '%s'\n",
361             OUStringToOString(aPassText, RTL_TEXTENCODING_UTF8).getStr());
362 #endif
363 
364     if (mbEmptyPass)
365         return aPassText.isEmpty();
366 
367     if (!maPassText.isEmpty())
368         // Clear text password exists, and this one takes precedence.
369         return aPassText == maPassText;
370 
371     // For PASSHASH_UNSPECIFIED also maPassHash is empty and any aPassText
372     // would yield an empty hash as well and thus compare true. Don't.
373     if (meHash1 != PASSHASH_UNSPECIFIED)
374     {
375         Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash1);
376         aHash = hashPassword(aHash, meHash2);
377 
378 #if DEBUG_TAB_PROTECTION
379         fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = ");
380         for (sal_Int32 i = 0; i < aHash.getLength(); ++i)
381             printf("%2.2X ", static_cast<sal_uInt8>(aHash[i]));
382         printf("\n");
383 #endif
384 
385         if (aHash == maPassHash)
386         {
387             return true;
388         }
389     }
390 
391     // tdf#115483 compat hack for ODF 1.2; for now UTF8-SHA1 passwords are only
392     // verified, not generated
393     if (meHash1 == PASSHASH_SHA1 && meHash2 == PASSHASH_UNSPECIFIED)
394     {
395         Sequence<sal_Int8> const aHash2 = hashPassword(aPassText, PASSHASH_SHA1_UTF8);
396         return aHash2 == maPassHash;
397     }
398 
399     // Not yet generated or tracked with meHash1 or meHash2, but can be read
400     // from OOXML.
401     return maPasswordHash.verifyPassword( aPassText);
402 }
403 
isOptionEnabled(SCSIZE nOptId) const404 bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const
405 {
406     if ( maOptions.size() <= static_cast<size_t>(nOptId) )
407     {
408         OSL_FAIL("ScTableProtectionImpl::isOptionEnabled: wrong size");
409         return false;
410     }
411 
412     return maOptions[nOptId];
413 }
414 
setOption(SCSIZE nOptId,bool bEnabled)415 void ScTableProtectionImpl::setOption(SCSIZE nOptId, bool bEnabled)
416 {
417     if ( maOptions.size() <= static_cast<size_t>(nOptId) )
418     {
419         OSL_FAIL("ScTableProtectionImpl::setOption: wrong size");
420         return;
421     }
422 
423     maOptions[nOptId] = bEnabled;
424 }
425 
setEnhancedProtection(const::std::vector<ScEnhancedProtection> & rProt)426 void ScTableProtectionImpl::setEnhancedProtection( const ::std::vector< ScEnhancedProtection > & rProt )
427 {
428     maEnhancedProtection = rProt;
429 }
430 
updateReference(UpdateRefMode eMode,const ScDocument & rDoc,const ScRange & rWhere,SCCOL nDx,SCROW nDy,SCTAB nDz)431 bool ScTableProtectionImpl::updateReference( UpdateRefMode eMode, const ScDocument& rDoc,
432         const ScRange& rWhere, SCCOL nDx, SCROW nDy, SCTAB nDz )
433 {
434     bool bChanged = false;
435     for (auto& rEnhancedProtection : maEnhancedProtection)
436     {
437         if (rEnhancedProtection.maRangeList.is())
438             bChanged |= rEnhancedProtection.maRangeList->UpdateReference( eMode, &rDoc, rWhere, nDx, nDy, nDz);
439     }
440     return bChanged;
441 }
442 
isBlockEditable(const ScRange & rRange) const443 bool ScTableProtectionImpl::isBlockEditable( const ScRange& rRange ) const
444 {
445     /* TODO: ask for password (and remember) if a password was set for
446      * a matching range and no matching range without password was encountered.
447      * Would need another return type than boolean to reflect
448      * "password required for a specific protection". */
449 
450     // No protection exception or overriding permission to edit if empty.
451     if (maEnhancedProtection.empty())
452         return false;
453 
454     // No security descriptor in an enhanced protection means the ranges of
455     // that protection are editable. If there is any security descriptor
456     // present we assume the permission to edit is not granted. Until we
457     // actually can evaluate the descriptors...
458 
459     auto lIsEditable = [rRange](const ScEnhancedProtection& rEnhancedProtection) {
460         return !rEnhancedProtection.hasSecurityDescriptor()
461             && rEnhancedProtection.maRangeList.is() && rEnhancedProtection.maRangeList->In( rRange)
462             && !rEnhancedProtection.hasPassword(); // Range is editable if no password is assigned.
463     };
464     if (std::any_of(maEnhancedProtection.begin(), maEnhancedProtection.end(), lIsEditable))
465         return true;
466 
467     // For a single address, a simple check with single ranges was sufficient.
468     if (rRange.aStart == rRange.aEnd)
469         return false;
470 
471     // Test also for cases where rRange is encompassed by a union of two or
472     // more ranges of the list. The original ranges are not necessarily joined.
473     for (const auto& rEnhancedProtection : maEnhancedProtection)
474     {
475         if (!rEnhancedProtection.hasSecurityDescriptor() && rEnhancedProtection.maRangeList.is())
476         {
477             ScRangeList aList( rEnhancedProtection.maRangeList->GetIntersectedRange( rRange));
478             if (aList.size() == 1 && aList[0] == rRange)
479             {
480                 // Range is editable if no password is assigned.
481                 if (!rEnhancedProtection.hasPassword())
482                     return true;
483             }
484         }
485     }
486 
487     // Ranges may even be distributed over different protection records, for
488     // example if they are assigned different names, and can have different
489     // passwords. Combine the ones that can be edited.
490     /* TODO: once we handle passwords, remember a successful unlock at
491      * ScEnhancedProtection so we can use that here. */
492     ScRangeList aRangeList;
493     for (const auto& rEnhancedProtection : maEnhancedProtection)
494     {
495         if (!rEnhancedProtection.hasSecurityDescriptor() && rEnhancedProtection.maRangeList.is())
496         {
497             // Ranges are editable if no password is assigned.
498             if (!rEnhancedProtection.hasPassword())
499             {
500                 const ScRangeList& rRanges = *rEnhancedProtection.maRangeList;
501                 size_t nRanges = rRanges.size();
502                 for (size_t i=0; i < nRanges; ++i)
503                 {
504                     aRangeList.push_back( rRanges[i]);
505                 }
506             }
507         }
508     }
509     ScRangeList aResultList( aRangeList.GetIntersectedRange( rRange));
510     return aResultList.size() == 1 && aResultList[0] == rRange;
511 }
512 
isSelectionEditable(const ScRangeList & rRangeList) const513 bool ScTableProtectionImpl::isSelectionEditable( const ScRangeList& rRangeList ) const
514 {
515     if (rRangeList.empty())
516         return false;
517 
518     for (size_t i=0, nRanges = rRangeList.size(); i < nRanges; ++i)
519     {
520         if (!isBlockEditable( rRangeList[i]))
521             return false;
522     }
523     return true;
524 }
525 
ScDocProtection()526 ScDocProtection::ScDocProtection() :
527     mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScDocProtection::NONE)))
528 {
529 }
530 
ScDocProtection(const ScDocProtection & r)531 ScDocProtection::ScDocProtection(const ScDocProtection& r) :
532     ScPassHashProtectable(),
533     mpImpl(new ScTableProtectionImpl(*r.mpImpl))
534 {
535 }
536 
~ScDocProtection()537 ScDocProtection::~ScDocProtection()
538 {
539 }
540 
isProtected() const541 bool ScDocProtection::isProtected() const
542 {
543     return mpImpl->isProtected();
544 }
545 
isProtectedWithPass() const546 bool ScDocProtection::isProtectedWithPass() const
547 {
548     return mpImpl->isProtectedWithPass();
549 }
550 
setProtected(bool bProtected)551 void ScDocProtection::setProtected(bool bProtected)
552 {
553     mpImpl->setProtected(bProtected);
554 
555     // Currently Calc doesn't support document protection options.  So, let's
556     // assume that when the document is protected, its structure is protected.
557     // We need to do this for Excel export.
558     mpImpl->setOption(ScDocProtection::STRUCTURE, bProtected);
559 }
560 
isPasswordEmpty() const561 bool ScDocProtection::isPasswordEmpty() const
562 {
563     return mpImpl->isPasswordEmpty();
564 }
565 
hasPasswordHash(ScPasswordHash eHash,ScPasswordHash eHash2) const566 bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
567 {
568     return mpImpl->hasPasswordHash(eHash, eHash2);
569 }
570 
setPassword(const OUString & aPassText)571 void ScDocProtection::setPassword(const OUString& aPassText)
572 {
573     mpImpl->setPassword(aPassText);
574 }
575 
getPasswordHash(ScPasswordHash eHash,ScPasswordHash eHash2) const576 uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
577 {
578     return mpImpl->getPasswordHash(eHash, eHash2);
579 }
580 
getPasswordHash() const581 const ScOoxPasswordHash& ScDocProtection::getPasswordHash() const
582 {
583     return mpImpl->getPasswordHash();
584 }
585 
setPasswordHash(const uno::Sequence<sal_Int8> & aPassword,ScPasswordHash eHash,ScPasswordHash eHash2)586 void ScDocProtection::setPasswordHash(
587     const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
588 {
589     mpImpl->setPasswordHash(aPassword, eHash, eHash2);
590 }
591 
setPasswordHash(const OUString & rAlgorithmName,const OUString & rHashValue,const OUString & rSaltValue,sal_uInt32 nSpinCount)592 void ScDocProtection::setPasswordHash( const OUString& rAlgorithmName, const OUString& rHashValue,
593         const OUString& rSaltValue, sal_uInt32 nSpinCount )
594 {
595     mpImpl->setPasswordHash( rAlgorithmName, rHashValue, rSaltValue, nSpinCount);
596 }
597 
verifyPassword(const OUString & aPassText) const598 bool ScDocProtection::verifyPassword(const OUString& aPassText) const
599 {
600     return mpImpl->verifyPassword(aPassText);
601 }
602 
isOptionEnabled(Option eOption) const603 bool ScDocProtection::isOptionEnabled(Option eOption) const
604 {
605     return mpImpl->isOptionEnabled(eOption);
606 }
607 
setOption(Option eOption,bool bEnabled)608 void ScDocProtection::setOption(Option eOption, bool bEnabled)
609 {
610     mpImpl->setOption(eOption, bEnabled);
611 }
612 
ScTableProtection()613 ScTableProtection::ScTableProtection() :
614     mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScTableProtection::NONE)))
615 {
616     // Set default values for the options.
617     mpImpl->setOption(SELECT_LOCKED_CELLS,   true);
618     mpImpl->setOption(SELECT_UNLOCKED_CELLS, true);
619 }
620 
ScTableProtection(const ScTableProtection & r)621 ScTableProtection::ScTableProtection(const ScTableProtection& r) :
622     ScPassHashProtectable(),
623     mpImpl(new ScTableProtectionImpl(*r.mpImpl))
624 {
625 }
626 
~ScTableProtection()627 ScTableProtection::~ScTableProtection()
628 {
629 }
630 
isProtected() const631 bool ScTableProtection::isProtected() const
632 {
633     return mpImpl->isProtected();
634 }
635 
isProtectedWithPass() const636 bool ScTableProtection::isProtectedWithPass() const
637 {
638     return mpImpl->isProtectedWithPass();
639 }
640 
setProtected(bool bProtected)641 void ScTableProtection::setProtected(bool bProtected)
642 {
643     mpImpl->setProtected(bProtected);
644 }
645 
isPasswordEmpty() const646 bool ScTableProtection::isPasswordEmpty() const
647 {
648     return mpImpl->isPasswordEmpty();
649 }
650 
hasPasswordHash(ScPasswordHash eHash,ScPasswordHash eHash2) const651 bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
652 {
653     return mpImpl->hasPasswordHash(eHash, eHash2);
654 }
655 
setPassword(const OUString & aPassText)656 void ScTableProtection::setPassword(const OUString& aPassText)
657 {
658     mpImpl->setPassword(aPassText);
659 }
660 
getPasswordHash(ScPasswordHash eHash,ScPasswordHash eHash2) const661 Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
662 {
663     return mpImpl->getPasswordHash(eHash, eHash2);
664 }
665 
getPasswordHash() const666 const ScOoxPasswordHash& ScTableProtection::getPasswordHash() const
667 {
668     return mpImpl->getPasswordHash();
669 }
670 
setPasswordHash(const uno::Sequence<sal_Int8> & aPassword,ScPasswordHash eHash,ScPasswordHash eHash2)671 void ScTableProtection::setPasswordHash(
672     const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
673 {
674     mpImpl->setPasswordHash(aPassword, eHash, eHash2);
675 }
676 
setPasswordHash(const OUString & rAlgorithmName,const OUString & rHashValue,const OUString & rSaltValue,sal_uInt32 nSpinCount)677 void ScTableProtection::setPasswordHash( const OUString& rAlgorithmName, const OUString& rHashValue,
678         const OUString& rSaltValue, sal_uInt32 nSpinCount )
679 {
680     mpImpl->setPasswordHash( rAlgorithmName, rHashValue, rSaltValue, nSpinCount);
681 }
682 
verifyPassword(const OUString & aPassText) const683 bool ScTableProtection::verifyPassword(const OUString& aPassText) const
684 {
685     return mpImpl->verifyPassword(aPassText);
686 }
687 
isOptionEnabled(Option eOption) const688 bool ScTableProtection::isOptionEnabled(Option eOption) const
689 {
690     return mpImpl->isOptionEnabled(eOption);
691 }
692 
setOption(Option eOption,bool bEnabled)693 void ScTableProtection::setOption(Option eOption, bool bEnabled)
694 {
695     mpImpl->setOption(eOption, bEnabled);
696 }
697 
setEnhancedProtection(const::std::vector<ScEnhancedProtection> & rProt)698 void ScTableProtection::setEnhancedProtection( const ::std::vector< ScEnhancedProtection > & rProt )
699 {
700     mpImpl->setEnhancedProtection(rProt);
701 }
702 
getEnhancedProtection() const703 const ::std::vector< ScEnhancedProtection > & ScTableProtection::getEnhancedProtection() const
704 {
705     return mpImpl->getEnhancedProtection();
706 }
707 
updateReference(UpdateRefMode eMode,const ScDocument & rDoc,const ScRange & rWhere,SCCOL nDx,SCROW nDy,SCTAB nDz)708 bool ScTableProtection::updateReference( UpdateRefMode eMode, const ScDocument& rDoc, const ScRange& rWhere,
709         SCCOL nDx, SCROW nDy, SCTAB nDz )
710 {
711     return mpImpl->updateReference( eMode, rDoc, rWhere, nDx, nDy, nDz);
712 }
713 
isBlockEditable(const ScRange & rRange) const714 bool ScTableProtection::isBlockEditable( const ScRange& rRange ) const
715 {
716     return mpImpl->isBlockEditable( rRange);
717 }
718 
isSelectionEditable(const ScRangeList & rRangeList) const719 bool ScTableProtection::isSelectionEditable( const ScRangeList& rRangeList ) const
720 {
721     return mpImpl->isSelectionEditable( rRangeList);
722 }
723 
724 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
725