Line data Source code
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 <osl/diagnose.h>
24 : #include "document.hxx"
25 :
26 : #include <vector>
27 :
28 : #define DEBUG_TAB_PROTECTION 0
29 :
30 : #define URI_SHA1 "http://www.w3.org/2000/09/xmldsig#sha1"
31 : #define URI_XLS_LEGACY "http://docs.oasis-open.org/office/ns/table/legacy-hash-excel"
32 :
33 : using namespace ::com::sun::star;
34 : using ::com::sun::star::uno::Sequence;
35 : using ::std::vector;
36 :
37 31 : bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash1, ScPasswordHash eHash2)
38 : {
39 31 : if (rDoc.IsDocProtected())
40 : {
41 0 : const ScDocProtection* p = rDoc.GetDocProtection();
42 0 : if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
43 0 : return true;
44 : }
45 :
46 31 : SCTAB nTabCount = rDoc.GetTableCount();
47 66 : for (SCTAB i = 0; i < nTabCount; ++i)
48 : {
49 35 : const ScTableProtection* p = rDoc.GetTabProtection(i);
50 35 : if (!p || !p->isProtected())
51 : // Sheet not protected. Skip it.
52 34 : continue;
53 :
54 1 : if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
55 0 : return true;
56 : }
57 :
58 31 : return false;
59 : }
60 :
61 0 : OUString ScPassHashHelper::getHashURI(ScPasswordHash eHash)
62 : {
63 0 : switch (eHash)
64 : {
65 : case PASSHASH_SHA1:
66 0 : return OUString(URI_SHA1);
67 : case PASSHASH_XL:
68 0 : return OUString(URI_XLS_LEGACY);
69 : case PASSHASH_UNSPECIFIED:
70 : default:
71 : ;
72 : }
73 0 : return OUString();
74 : }
75 :
76 0 : ScPasswordHash ScPassHashHelper::getHashTypeFromURI(const OUString& rURI)
77 : {
78 0 : if ( rURI == URI_SHA1 )
79 0 : return PASSHASH_SHA1;
80 0 : else if ( rURI == URI_XLS_LEGACY )
81 0 : return PASSHASH_XL;
82 0 : return PASSHASH_UNSPECIFIED;
83 : }
84 :
85 43 : ScPassHashProtectable::~ScPassHashProtectable()
86 : {
87 43 : }
88 :
89 43 : class ScTableProtectionImpl
90 : {
91 : public:
92 : static Sequence<sal_Int8> hashPassword(const OUString& aPassText, ScPasswordHash eHash = PASSHASH_SHA1);
93 : static Sequence<sal_Int8> hashPassword(const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash = PASSHASH_SHA1);
94 :
95 : explicit ScTableProtectionImpl(SCSIZE nOptSize);
96 : explicit ScTableProtectionImpl(const ScTableProtectionImpl& r);
97 :
98 14 : bool isProtected() const { return mbProtected;}
99 : bool isProtectedWithPass() const;
100 : void setProtected(bool bProtected);
101 :
102 1 : bool isPasswordEmpty() const { return mbEmptyPass;}
103 : bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
104 : void setPassword(const OUString& aPassText);
105 : ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(
106 : ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
107 : void setPasswordHash(
108 : const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
109 : ScPasswordHash eHash = PASSHASH_SHA1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED);
110 : bool verifyPassword(const OUString& aPassText) const;
111 :
112 : bool isOptionEnabled(SCSIZE nOptId) const;
113 : void setOption(SCSIZE nOptId, bool bEnabled);
114 :
115 : void setEnhancedProtection( const ::std::vector< ScEnhancedProtection > & rProt );
116 1 : const ::std::vector< ScEnhancedProtection > & getEnhancedProtection() const { return maEnhancedProtection;}
117 : bool updateReference( UpdateRefMode, ScDocument*, const ScRange& rWhere, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
118 : bool isBlockEditable( const ScRange& rRange ) const;
119 : bool isSelectionEditable( const ScRangeList& rRangeList ) const;
120 :
121 : private:
122 : OUString maPassText;
123 : ::com::sun::star::uno::Sequence<sal_Int8> maPassHash;
124 : ::std::vector<bool> maOptions;
125 : bool mbEmptyPass;
126 : bool mbProtected;
127 : ScPasswordHash meHash1;
128 : ScPasswordHash meHash2;
129 : ::std::vector< ScEnhancedProtection > maEnhancedProtection;
130 : };
131 :
132 0 : Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const OUString& aPassText, ScPasswordHash eHash)
133 : {
134 0 : Sequence<sal_Int8> aHash;
135 0 : switch (eHash)
136 : {
137 : case PASSHASH_XL:
138 0 : aHash = ::comphelper::DocPasswordHelper::GetXLHashAsSequence( aPassText, RTL_TEXTENCODING_UTF8 );
139 0 : break;
140 : case PASSHASH_SHA1:
141 0 : SvPasswordHelper::GetHashPassword(aHash, aPassText);
142 0 : break;
143 : default:
144 : ;
145 : }
146 0 : return aHash;
147 : }
148 :
149 0 : Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(
150 : const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash)
151 : {
152 0 : if (!rPassHash.getLength() || eHash == PASSHASH_UNSPECIFIED)
153 0 : return rPassHash;
154 :
155 : // TODO: Right now, we only support double-hash by SHA1.
156 0 : if (eHash == PASSHASH_SHA1)
157 : {
158 0 : vector<sal_Char> aChars;
159 0 : sal_Int32 n = rPassHash.getLength();
160 0 : aChars.reserve(n);
161 0 : for (sal_Int32 i = 0; i < n; ++i)
162 0 : aChars.push_back(static_cast<sal_Char>(rPassHash[i]));
163 :
164 0 : Sequence<sal_Int8> aNewHash;
165 0 : SvPasswordHelper::GetHashPassword(aNewHash, &aChars[0], aChars.size());
166 0 : return aNewHash;
167 : }
168 :
169 0 : return rPassHash;
170 : }
171 :
172 20 : ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) :
173 : maOptions(nOptSize),
174 : mbEmptyPass(true),
175 : mbProtected(false),
176 : meHash1(PASSHASH_SHA1),
177 20 : meHash2(PASSHASH_UNSPECIFIED)
178 : {
179 20 : }
180 :
181 23 : ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) :
182 : maPassText(r.maPassText),
183 : maPassHash(r.maPassHash),
184 : maOptions(r.maOptions),
185 : mbEmptyPass(r.mbEmptyPass),
186 : mbProtected(r.mbProtected),
187 : meHash1(r.meHash1),
188 : meHash2(r.meHash2),
189 23 : maEnhancedProtection(r.maEnhancedProtection)
190 : {
191 23 : }
192 :
193 0 : bool ScTableProtectionImpl::isProtectedWithPass() const
194 : {
195 0 : if (!mbProtected)
196 0 : return false;
197 :
198 0 : return !maPassText.isEmpty() || maPassHash.getLength();
199 : }
200 :
201 22 : void ScTableProtectionImpl::setProtected(bool bProtected)
202 : {
203 22 : mbProtected = bProtected;
204 : // We need to keep the old password even when the protection is off. So,
205 : // don't erase the password data here.
206 22 : }
207 :
208 1 : void ScTableProtectionImpl::setPassword(const OUString& aPassText)
209 : {
210 : // We can't hash it here because we don't know whether this document will
211 : // get saved to Excel or ODF, depending on which we will need to use a
212 : // different hashing algorithm. One alternative is to hash it using all
213 : // hash algorithms that we support, and store them all.
214 :
215 1 : maPassText = aPassText;
216 1 : mbEmptyPass = aPassText.isEmpty();
217 1 : if (mbEmptyPass)
218 : {
219 0 : maPassHash = Sequence<sal_Int8>();
220 : }
221 1 : }
222 :
223 1 : bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
224 : {
225 1 : if (mbEmptyPass)
226 1 : return true;
227 :
228 0 : if (!maPassText.isEmpty())
229 0 : return true;
230 :
231 0 : if (meHash1 == eHash)
232 : {
233 0 : if (meHash2 == PASSHASH_UNSPECIFIED)
234 : // single hash.
235 0 : return true;
236 :
237 0 : return meHash2 == eHash2;
238 : }
239 :
240 0 : return false;
241 : }
242 :
243 3 : Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(
244 : ScPasswordHash eHash, ScPasswordHash eHash2) const
245 : {
246 3 : Sequence<sal_Int8> aPassHash;
247 :
248 3 : if (mbEmptyPass)
249 : // Flaged as empty.
250 1 : return aPassHash;
251 :
252 2 : if (!maPassText.isEmpty())
253 : {
254 : // Cleartext password exists. Hash it.
255 0 : aPassHash = hashPassword(maPassText, eHash);
256 0 : if (eHash2 != PASSHASH_UNSPECIFIED)
257 : // Double-hash it.
258 0 : aPassHash = hashPassword(aPassHash, eHash2);
259 :
260 0 : return aPassHash;
261 : }
262 : else
263 : {
264 : // No clear text password. Check if we have a hash value of the right hash type.
265 2 : if (meHash1 == eHash)
266 : {
267 2 : aPassHash = maPassHash;
268 :
269 2 : if (meHash2 == eHash2)
270 : // Matching double-hash requested.
271 2 : return aPassHash;
272 0 : else if (meHash2 == PASSHASH_UNSPECIFIED)
273 : // primary hashing type match. Double hash it by the requested
274 : // double-hash type.
275 0 : return hashPassword(aPassHash, eHash2);
276 : }
277 : }
278 :
279 : // failed.
280 0 : return Sequence<sal_Int8>();
281 : }
282 :
283 4 : void ScTableProtectionImpl::setPasswordHash(
284 : const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
285 : {
286 4 : sal_Int32 nLen = aPassword.getLength();
287 4 : mbEmptyPass = nLen <= 0;
288 4 : meHash1 = eHash;
289 4 : meHash2 = eHash2;
290 4 : maPassHash = aPassword;
291 :
292 : #if DEBUG_TAB_PROTECTION
293 : for (sal_Int32 i = 0; i < nLen; ++i)
294 : printf("%2.2X ", static_cast<sal_uInt8>(aPassword[i]));
295 : printf("\n");
296 : #endif
297 4 : }
298 :
299 2 : bool ScTableProtectionImpl::verifyPassword(const OUString& aPassText) const
300 : {
301 : #if DEBUG_TAB_PROTECTION
302 : fprintf(stdout, "ScTableProtectionImpl::verifyPassword: input = '%s'\n",
303 : OUStringToOString(OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr());
304 : #endif
305 :
306 2 : if (mbEmptyPass)
307 0 : return aPassText.isEmpty();
308 :
309 2 : if (!maPassText.isEmpty())
310 : // Clear text password exists, and this one takes precedence.
311 2 : return aPassText == maPassText;
312 :
313 0 : Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash1);
314 0 : aHash = hashPassword(aHash, meHash2);
315 :
316 : #if DEBUG_TAB_PROTECTION
317 : fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = ");
318 : for (sal_Int32 i = 0; i < aHash.getLength(); ++i)
319 : printf("%2.2X ", static_cast<sal_uInt8>(aHash[i]));
320 : printf("\n");
321 : #endif
322 :
323 0 : return aHash == maPassHash;
324 : }
325 :
326 23 : bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const
327 : {
328 23 : if ( maOptions.size() <= static_cast<size_t>(nOptId) )
329 : {
330 : OSL_FAIL("ScTableProtectionImpl::isOptionEnabled: wrong size");
331 0 : return false;
332 : }
333 :
334 23 : return maOptions[nOptId];
335 : }
336 :
337 286 : void ScTableProtectionImpl::setOption(SCSIZE nOptId, bool bEnabled)
338 : {
339 286 : if ( maOptions.size() <= static_cast<size_t>(nOptId) )
340 : {
341 : OSL_FAIL("ScTableProtectionImpl::setOption: wrong size");
342 286 : return;
343 : }
344 :
345 286 : maOptions[nOptId] = bEnabled;
346 : }
347 :
348 16 : void ScTableProtectionImpl::setEnhancedProtection( const ::std::vector< ScEnhancedProtection > & rProt )
349 : {
350 16 : maEnhancedProtection = rProt;
351 16 : }
352 :
353 0 : bool ScTableProtectionImpl::updateReference( UpdateRefMode eMode, ScDocument* pDoc,
354 : const ScRange& rWhere, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
355 : {
356 0 : bool bChanged = false;
357 0 : for (::std::vector<ScEnhancedProtection>::iterator it(maEnhancedProtection.begin());
358 0 : it != maEnhancedProtection.end(); ++it)
359 : {
360 0 : if ((*it).maRangeList.Is())
361 0 : bChanged |= (*it).maRangeList->UpdateReference( eMode, pDoc, rWhere, nDx, nDy, nDz);
362 : }
363 0 : return bChanged;
364 : }
365 :
366 18 : bool ScTableProtectionImpl::isBlockEditable( const ScRange& rRange ) const
367 : {
368 : /* TODO: ask for password (and remember) if a password was set for
369 : * a matching range and no matching range without password was encountered.
370 : * Would need another return type than boolean to reflect
371 : * "password required for a specific protection". */
372 :
373 : // No protection exception or overriding permission to edit if empty.
374 18 : if (maEnhancedProtection.empty())
375 0 : return false;
376 :
377 : // No security descriptor in an enhanced protection means the ranges of
378 : // that protection are editable. If there is any security descriptor
379 : // present we assume the permission to edit is not granted. Until we
380 : // actually can evaluate the descriptors..
381 :
382 116 : for (::std::vector<ScEnhancedProtection>::const_iterator it(maEnhancedProtection.begin()),
383 18 : itEnd(maEnhancedProtection.end()); it != itEnd; ++it)
384 : {
385 84 : if (!(*it).hasSecurityDescriptor() && (*it).maRangeList.Is())
386 : {
387 48 : if ((*it).maRangeList->In( rRange))
388 : {
389 : // Range is editable if no password is assigned.
390 6 : if (!(*it).hasPassword())
391 4 : return true;
392 : }
393 : }
394 : }
395 :
396 : // For a single address, a simple check with single ranges was sufficient.
397 14 : if (rRange.aStart == rRange.aEnd)
398 8 : return false;
399 :
400 : // Test also for cases where rRange is encompassed by a union of two or
401 : // more ranges of the list. The original ranges are not necessarily joined.
402 42 : for (::std::vector<ScEnhancedProtection>::const_iterator it(maEnhancedProtection.begin()),
403 6 : itEnd(maEnhancedProtection.end()); it != itEnd; ++it)
404 : {
405 30 : if (!(*it).hasSecurityDescriptor() && (*it).maRangeList.Is())
406 : {
407 18 : ScRangeList aList( (*it).maRangeList->GetIntersectedRange( rRange));
408 18 : if (aList.size() == 1 && *aList[0] == rRange)
409 : {
410 : // Range is editable if no password is assigned.
411 0 : if (!(*it).hasPassword())
412 0 : return true;
413 18 : }
414 : }
415 : }
416 :
417 : // Ranges may even be distributed over different protection records, for
418 : // example if they are assigned different names, and can have different
419 : // passwords. Combine the ones that can be edited.
420 : /* TODO: once we handle passwords, remember a successful unlock at
421 : * ScEnhancedProtection so we can use that here. */
422 6 : ScRangeList aRangeList;
423 42 : for (::std::vector<ScEnhancedProtection>::const_iterator it(maEnhancedProtection.begin()),
424 6 : itEnd(maEnhancedProtection.end()); it != itEnd; ++it)
425 : {
426 30 : if (!(*it).hasSecurityDescriptor() && (*it).maRangeList.Is())
427 : {
428 : // Ranges are editable if no password is assigned.
429 18 : if (!(*it).hasPassword())
430 : {
431 12 : const ScRangeList& rRanges = *(*it).maRangeList;
432 12 : size_t nRanges = rRanges.size();
433 24 : for (size_t i=0; i < nRanges; ++i)
434 : {
435 12 : aRangeList.Append( *rRanges[i]);
436 : }
437 : }
438 : }
439 : }
440 12 : ScRangeList aResultList( aRangeList.GetIntersectedRange( rRange));
441 6 : if (aResultList.size() == 1 && *aResultList[0] == rRange)
442 2 : return true;
443 :
444 10 : return false;
445 : }
446 :
447 0 : bool ScTableProtectionImpl::isSelectionEditable( const ScRangeList& rRangeList ) const
448 : {
449 0 : if (rRangeList.empty())
450 0 : return false;
451 :
452 0 : for (size_t i=0, nRanges = rRangeList.size(); i < nRanges; ++i)
453 : {
454 0 : if (!isBlockEditable( *rRangeList[i]))
455 0 : return false;
456 : }
457 0 : return true;
458 : }
459 :
460 2 : ScDocProtection::ScDocProtection() :
461 2 : mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScDocProtection::NONE)))
462 : {
463 2 : }
464 :
465 5 : ScDocProtection::ScDocProtection(const ScDocProtection& r) :
466 : ScPassHashProtectable(),
467 5 : mpImpl(new ScTableProtectionImpl(*r.mpImpl))
468 : {
469 5 : }
470 :
471 13 : ScDocProtection::~ScDocProtection()
472 : {
473 13 : }
474 :
475 8 : bool ScDocProtection::isProtected() const
476 : {
477 8 : return mpImpl->isProtected();
478 : }
479 :
480 0 : bool ScDocProtection::isProtectedWithPass() const
481 : {
482 0 : return mpImpl->isProtectedWithPass();
483 : }
484 :
485 4 : void ScDocProtection::setProtected(bool bProtected)
486 : {
487 4 : mpImpl->setProtected(bProtected);
488 :
489 : // Currently Calc doesn't support document protection options. So, let's
490 : // assume that when the document is protected, its structure is protected.
491 : // We need to do this for Excel export.
492 4 : mpImpl->setOption(ScDocProtection::STRUCTURE, bProtected);
493 4 : }
494 :
495 0 : bool ScDocProtection::isPasswordEmpty() const
496 : {
497 0 : return mpImpl->isPasswordEmpty();
498 : }
499 :
500 0 : bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
501 : {
502 0 : return mpImpl->hasPasswordHash(eHash, eHash2);
503 : }
504 :
505 1 : void ScDocProtection::setPassword(const OUString& aPassText)
506 : {
507 1 : mpImpl->setPassword(aPassText);
508 1 : }
509 :
510 0 : uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
511 : {
512 0 : return mpImpl->getPasswordHash(eHash, eHash2);
513 : }
514 :
515 0 : void ScDocProtection::setPasswordHash(
516 : const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
517 : {
518 0 : mpImpl->setPasswordHash(aPassword, eHash, eHash2);
519 0 : }
520 :
521 2 : bool ScDocProtection::verifyPassword(const OUString& aPassText) const
522 : {
523 2 : return mpImpl->verifyPassword(aPassText);
524 : }
525 :
526 0 : bool ScDocProtection::isOptionEnabled(Option eOption) const
527 : {
528 0 : return mpImpl->isOptionEnabled(eOption);
529 : }
530 :
531 2 : void ScDocProtection::setOption(Option eOption, bool bEnabled)
532 : {
533 2 : mpImpl->setOption(eOption, bEnabled);
534 2 : }
535 :
536 18 : ScTableProtection::ScTableProtection() :
537 18 : mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScTableProtection::NONE)))
538 : {
539 : // Set default values for the options.
540 18 : mpImpl->setOption(SELECT_LOCKED_CELLS, true);
541 18 : mpImpl->setOption(SELECT_UNLOCKED_CELLS, true);
542 18 : }
543 :
544 18 : ScTableProtection::ScTableProtection(const ScTableProtection& r) :
545 : ScPassHashProtectable(),
546 18 : mpImpl(new ScTableProtectionImpl(*r.mpImpl))
547 : {
548 18 : }
549 :
550 68 : ScTableProtection::~ScTableProtection()
551 : {
552 68 : }
553 :
554 6 : bool ScTableProtection::isProtected() const
555 : {
556 6 : return mpImpl->isProtected();
557 : }
558 :
559 0 : bool ScTableProtection::isProtectedWithPass() const
560 : {
561 0 : return mpImpl->isProtectedWithPass();
562 : }
563 :
564 18 : void ScTableProtection::setProtected(bool bProtected)
565 : {
566 18 : mpImpl->setProtected(bProtected);
567 18 : }
568 :
569 1 : bool ScTableProtection::isPasswordEmpty() const
570 : {
571 1 : return mpImpl->isPasswordEmpty();
572 : }
573 :
574 1 : bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
575 : {
576 1 : return mpImpl->hasPasswordHash(eHash, eHash2);
577 : }
578 :
579 0 : void ScTableProtection::setPassword(const OUString& aPassText)
580 : {
581 0 : mpImpl->setPassword(aPassText);
582 0 : }
583 :
584 3 : Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
585 : {
586 3 : return mpImpl->getPasswordHash(eHash, eHash2);
587 : }
588 :
589 4 : void ScTableProtection::setPasswordHash(
590 : const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
591 : {
592 4 : mpImpl->setPasswordHash(aPassword, eHash, eHash2);
593 4 : }
594 :
595 0 : bool ScTableProtection::verifyPassword(const OUString& aPassText) const
596 : {
597 0 : return mpImpl->verifyPassword(aPassText);
598 : }
599 :
600 23 : bool ScTableProtection::isOptionEnabled(Option eOption) const
601 : {
602 23 : return mpImpl->isOptionEnabled(eOption);
603 : }
604 :
605 244 : void ScTableProtection::setOption(Option eOption, bool bEnabled)
606 : {
607 244 : mpImpl->setOption(eOption, bEnabled);
608 244 : }
609 :
610 16 : void ScTableProtection::setEnhancedProtection( const ::std::vector< ScEnhancedProtection > & rProt )
611 : {
612 16 : mpImpl->setEnhancedProtection(rProt);
613 16 : }
614 :
615 1 : const ::std::vector< ScEnhancedProtection > & ScTableProtection::getEnhancedProtection() const
616 : {
617 1 : return mpImpl->getEnhancedProtection();
618 : }
619 :
620 0 : bool ScTableProtection::updateReference( UpdateRefMode eMode, ScDocument* pDoc, const ScRange& rWhere,
621 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
622 : {
623 0 : return mpImpl->updateReference( eMode, pDoc, rWhere, nDx, nDy, nDz);
624 : }
625 :
626 18 : bool ScTableProtection::isBlockEditable( const ScRange& rRange ) const
627 : {
628 18 : return mpImpl->isBlockEditable( rRange);
629 : }
630 :
631 0 : bool ScTableProtection::isSelectionEditable( const ScRangeList& rRangeList ) const
632 : {
633 0 : return mpImpl->isSelectionEditable( rRangeList);
634 156 : }
635 :
636 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|