Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Worksheet;
   4  
   5  use PhpOffice\PhpSpreadsheet\Shared\PasswordHasher;
   6  
   7  class Protection
   8  {
   9      const ALGORITHM_MD2 = 'MD2';
  10      const ALGORITHM_MD4 = 'MD4';
  11      const ALGORITHM_MD5 = 'MD5';
  12      const ALGORITHM_SHA_1 = 'SHA-1';
  13      const ALGORITHM_SHA_256 = 'SHA-256';
  14      const ALGORITHM_SHA_384 = 'SHA-384';
  15      const ALGORITHM_SHA_512 = 'SHA-512';
  16      const ALGORITHM_RIPEMD_128 = 'RIPEMD-128';
  17      const ALGORITHM_RIPEMD_160 = 'RIPEMD-160';
  18      const ALGORITHM_WHIRLPOOL = 'WHIRLPOOL';
  19  
  20      /**
  21       * Sheet.
  22       *
  23       * @var bool
  24       */
  25      private $sheet = false;
  26  
  27      /**
  28       * Objects.
  29       *
  30       * @var bool
  31       */
  32      private $objects = false;
  33  
  34      /**
  35       * Scenarios.
  36       *
  37       * @var bool
  38       */
  39      private $scenarios = false;
  40  
  41      /**
  42       * Format cells.
  43       *
  44       * @var bool
  45       */
  46      private $formatCells = false;
  47  
  48      /**
  49       * Format columns.
  50       *
  51       * @var bool
  52       */
  53      private $formatColumns = false;
  54  
  55      /**
  56       * Format rows.
  57       *
  58       * @var bool
  59       */
  60      private $formatRows = false;
  61  
  62      /**
  63       * Insert columns.
  64       *
  65       * @var bool
  66       */
  67      private $insertColumns = false;
  68  
  69      /**
  70       * Insert rows.
  71       *
  72       * @var bool
  73       */
  74      private $insertRows = false;
  75  
  76      /**
  77       * Insert hyperlinks.
  78       *
  79       * @var bool
  80       */
  81      private $insertHyperlinks = false;
  82  
  83      /**
  84       * Delete columns.
  85       *
  86       * @var bool
  87       */
  88      private $deleteColumns = false;
  89  
  90      /**
  91       * Delete rows.
  92       *
  93       * @var bool
  94       */
  95      private $deleteRows = false;
  96  
  97      /**
  98       * Select locked cells.
  99       *
 100       * @var bool
 101       */
 102      private $selectLockedCells = false;
 103  
 104      /**
 105       * Sort.
 106       *
 107       * @var bool
 108       */
 109      private $sort = false;
 110  
 111      /**
 112       * AutoFilter.
 113       *
 114       * @var bool
 115       */
 116      private $autoFilter = false;
 117  
 118      /**
 119       * Pivot tables.
 120       *
 121       * @var bool
 122       */
 123      private $pivotTables = false;
 124  
 125      /**
 126       * Select unlocked cells.
 127       *
 128       * @var bool
 129       */
 130      private $selectUnlockedCells = false;
 131  
 132      /**
 133       * Hashed password.
 134       *
 135       * @var string
 136       */
 137      private $password = '';
 138  
 139      /**
 140       * Algorithm name.
 141       *
 142       * @var string
 143       */
 144      private $algorithm = '';
 145  
 146      /**
 147       * Salt value.
 148       *
 149       * @var string
 150       */
 151      private $salt = '';
 152  
 153      /**
 154       * Spin count.
 155       *
 156       * @var int
 157       */
 158      private $spinCount = 10000;
 159  
 160      /**
 161       * Create a new Protection.
 162       */
 163      public function __construct()
 164      {
 165      }
 166  
 167      /**
 168       * Is some sort of protection enabled?
 169       *
 170       * @return bool
 171       */
 172      public function isProtectionEnabled()
 173      {
 174          return $this->sheet ||
 175              $this->objects ||
 176              $this->scenarios ||
 177              $this->formatCells ||
 178              $this->formatColumns ||
 179              $this->formatRows ||
 180              $this->insertColumns ||
 181              $this->insertRows ||
 182              $this->insertHyperlinks ||
 183              $this->deleteColumns ||
 184              $this->deleteRows ||
 185              $this->selectLockedCells ||
 186              $this->sort ||
 187              $this->autoFilter ||
 188              $this->pivotTables ||
 189              $this->selectUnlockedCells;
 190      }
 191  
 192      /**
 193       * Get Sheet.
 194       *
 195       * @return bool
 196       */
 197      public function getSheet()
 198      {
 199          return $this->sheet;
 200      }
 201  
 202      /**
 203       * Set Sheet.
 204       *
 205       * @param bool $pValue
 206       *
 207       * @return $this
 208       */
 209      public function setSheet($pValue)
 210      {
 211          $this->sheet = $pValue;
 212  
 213          return $this;
 214      }
 215  
 216      /**
 217       * Get Objects.
 218       *
 219       * @return bool
 220       */
 221      public function getObjects()
 222      {
 223          return $this->objects;
 224      }
 225  
 226      /**
 227       * Set Objects.
 228       *
 229       * @param bool $pValue
 230       *
 231       * @return $this
 232       */
 233      public function setObjects($pValue)
 234      {
 235          $this->objects = $pValue;
 236  
 237          return $this;
 238      }
 239  
 240      /**
 241       * Get Scenarios.
 242       *
 243       * @return bool
 244       */
 245      public function getScenarios()
 246      {
 247          return $this->scenarios;
 248      }
 249  
 250      /**
 251       * Set Scenarios.
 252       *
 253       * @param bool $pValue
 254       *
 255       * @return $this
 256       */
 257      public function setScenarios($pValue)
 258      {
 259          $this->scenarios = $pValue;
 260  
 261          return $this;
 262      }
 263  
 264      /**
 265       * Get FormatCells.
 266       *
 267       * @return bool
 268       */
 269      public function getFormatCells()
 270      {
 271          return $this->formatCells;
 272      }
 273  
 274      /**
 275       * Set FormatCells.
 276       *
 277       * @param bool $pValue
 278       *
 279       * @return $this
 280       */
 281      public function setFormatCells($pValue)
 282      {
 283          $this->formatCells = $pValue;
 284  
 285          return $this;
 286      }
 287  
 288      /**
 289       * Get FormatColumns.
 290       *
 291       * @return bool
 292       */
 293      public function getFormatColumns()
 294      {
 295          return $this->formatColumns;
 296      }
 297  
 298      /**
 299       * Set FormatColumns.
 300       *
 301       * @param bool $pValue
 302       *
 303       * @return $this
 304       */
 305      public function setFormatColumns($pValue)
 306      {
 307          $this->formatColumns = $pValue;
 308  
 309          return $this;
 310      }
 311  
 312      /**
 313       * Get FormatRows.
 314       *
 315       * @return bool
 316       */
 317      public function getFormatRows()
 318      {
 319          return $this->formatRows;
 320      }
 321  
 322      /**
 323       * Set FormatRows.
 324       *
 325       * @param bool $pValue
 326       *
 327       * @return $this
 328       */
 329      public function setFormatRows($pValue)
 330      {
 331          $this->formatRows = $pValue;
 332  
 333          return $this;
 334      }
 335  
 336      /**
 337       * Get InsertColumns.
 338       *
 339       * @return bool
 340       */
 341      public function getInsertColumns()
 342      {
 343          return $this->insertColumns;
 344      }
 345  
 346      /**
 347       * Set InsertColumns.
 348       *
 349       * @param bool $pValue
 350       *
 351       * @return $this
 352       */
 353      public function setInsertColumns($pValue)
 354      {
 355          $this->insertColumns = $pValue;
 356  
 357          return $this;
 358      }
 359  
 360      /**
 361       * Get InsertRows.
 362       *
 363       * @return bool
 364       */
 365      public function getInsertRows()
 366      {
 367          return $this->insertRows;
 368      }
 369  
 370      /**
 371       * Set InsertRows.
 372       *
 373       * @param bool $pValue
 374       *
 375       * @return $this
 376       */
 377      public function setInsertRows($pValue)
 378      {
 379          $this->insertRows = $pValue;
 380  
 381          return $this;
 382      }
 383  
 384      /**
 385       * Get InsertHyperlinks.
 386       *
 387       * @return bool
 388       */
 389      public function getInsertHyperlinks()
 390      {
 391          return $this->insertHyperlinks;
 392      }
 393  
 394      /**
 395       * Set InsertHyperlinks.
 396       *
 397       * @param bool $pValue
 398       *
 399       * @return $this
 400       */
 401      public function setInsertHyperlinks($pValue)
 402      {
 403          $this->insertHyperlinks = $pValue;
 404  
 405          return $this;
 406      }
 407  
 408      /**
 409       * Get DeleteColumns.
 410       *
 411       * @return bool
 412       */
 413      public function getDeleteColumns()
 414      {
 415          return $this->deleteColumns;
 416      }
 417  
 418      /**
 419       * Set DeleteColumns.
 420       *
 421       * @param bool $pValue
 422       *
 423       * @return $this
 424       */
 425      public function setDeleteColumns($pValue)
 426      {
 427          $this->deleteColumns = $pValue;
 428  
 429          return $this;
 430      }
 431  
 432      /**
 433       * Get DeleteRows.
 434       *
 435       * @return bool
 436       */
 437      public function getDeleteRows()
 438      {
 439          return $this->deleteRows;
 440      }
 441  
 442      /**
 443       * Set DeleteRows.
 444       *
 445       * @param bool $pValue
 446       *
 447       * @return $this
 448       */
 449      public function setDeleteRows($pValue)
 450      {
 451          $this->deleteRows = $pValue;
 452  
 453          return $this;
 454      }
 455  
 456      /**
 457       * Get SelectLockedCells.
 458       *
 459       * @return bool
 460       */
 461      public function getSelectLockedCells()
 462      {
 463          return $this->selectLockedCells;
 464      }
 465  
 466      /**
 467       * Set SelectLockedCells.
 468       *
 469       * @param bool $pValue
 470       *
 471       * @return $this
 472       */
 473      public function setSelectLockedCells($pValue)
 474      {
 475          $this->selectLockedCells = $pValue;
 476  
 477          return $this;
 478      }
 479  
 480      /**
 481       * Get Sort.
 482       *
 483       * @return bool
 484       */
 485      public function getSort()
 486      {
 487          return $this->sort;
 488      }
 489  
 490      /**
 491       * Set Sort.
 492       *
 493       * @param bool $pValue
 494       *
 495       * @return $this
 496       */
 497      public function setSort($pValue)
 498      {
 499          $this->sort = $pValue;
 500  
 501          return $this;
 502      }
 503  
 504      /**
 505       * Get AutoFilter.
 506       *
 507       * @return bool
 508       */
 509      public function getAutoFilter()
 510      {
 511          return $this->autoFilter;
 512      }
 513  
 514      /**
 515       * Set AutoFilter.
 516       *
 517       * @param bool $pValue
 518       *
 519       * @return $this
 520       */
 521      public function setAutoFilter($pValue)
 522      {
 523          $this->autoFilter = $pValue;
 524  
 525          return $this;
 526      }
 527  
 528      /**
 529       * Get PivotTables.
 530       *
 531       * @return bool
 532       */
 533      public function getPivotTables()
 534      {
 535          return $this->pivotTables;
 536      }
 537  
 538      /**
 539       * Set PivotTables.
 540       *
 541       * @param bool $pValue
 542       *
 543       * @return $this
 544       */
 545      public function setPivotTables($pValue)
 546      {
 547          $this->pivotTables = $pValue;
 548  
 549          return $this;
 550      }
 551  
 552      /**
 553       * Get SelectUnlockedCells.
 554       *
 555       * @return bool
 556       */
 557      public function getSelectUnlockedCells()
 558      {
 559          return $this->selectUnlockedCells;
 560      }
 561  
 562      /**
 563       * Set SelectUnlockedCells.
 564       *
 565       * @param bool $pValue
 566       *
 567       * @return $this
 568       */
 569      public function setSelectUnlockedCells($pValue)
 570      {
 571          $this->selectUnlockedCells = $pValue;
 572  
 573          return $this;
 574      }
 575  
 576      /**
 577       * Get hashed password.
 578       *
 579       * @return string
 580       */
 581      public function getPassword()
 582      {
 583          return $this->password;
 584      }
 585  
 586      /**
 587       * Set Password.
 588       *
 589       * @param string $pValue
 590       * @param bool $pAlreadyHashed If the password has already been hashed, set this to true
 591       *
 592       * @return $this
 593       */
 594      public function setPassword($pValue, $pAlreadyHashed = false)
 595      {
 596          if (!$pAlreadyHashed) {
 597              $salt = $this->generateSalt();
 598              $this->setSalt($salt);
 599              $pValue = PasswordHasher::hashPassword($pValue, $this->getAlgorithm(), $this->getSalt(), $this->getSpinCount());
 600          }
 601  
 602          $this->password = $pValue;
 603  
 604          return $this;
 605      }
 606  
 607      /**
 608       * Create a pseudorandom string.
 609       */
 610      private function generateSalt(): string
 611      {
 612          return base64_encode(random_bytes(16));
 613      }
 614  
 615      /**
 616       * Get algorithm name.
 617       */
 618      public function getAlgorithm(): string
 619      {
 620          return $this->algorithm;
 621      }
 622  
 623      /**
 624       * Set algorithm name.
 625       */
 626      public function setAlgorithm(string $algorithm): void
 627      {
 628          $this->algorithm = $algorithm;
 629      }
 630  
 631      /**
 632       * Get salt value.
 633       */
 634      public function getSalt(): string
 635      {
 636          return $this->salt;
 637      }
 638  
 639      /**
 640       * Set salt value.
 641       */
 642      public function setSalt(string $salt): void
 643      {
 644          $this->salt = $salt;
 645      }
 646  
 647      /**
 648       * Get spin count.
 649       */
 650      public function getSpinCount(): int
 651      {
 652          return $this->spinCount;
 653      }
 654  
 655      /**
 656       * Set spin count.
 657       */
 658      public function setSpinCount(int $spinCount): void
 659      {
 660          $this->spinCount = $spinCount;
 661      }
 662  
 663      /**
 664       * Verify that the given non-hashed password can "unlock" the protection.
 665       */
 666      public function verify(string $password): bool
 667      {
 668          if (!$this->isProtectionEnabled()) {
 669              return true;
 670          }
 671  
 672          $hash = PasswordHasher::hashPassword($password, $this->getAlgorithm(), $this->getSalt(), $this->getSpinCount());
 673  
 674          return $this->getPassword() === $hash;
 675      }
 676  
 677      /**
 678       * Implement PHP __clone to create a deep clone, not just a shallow copy.
 679       */
 680      public function __clone()
 681      {
 682          $vars = get_object_vars($this);
 683          foreach ($vars as $key => $value) {
 684              if (is_object($value)) {
 685                  $this->$key = clone $value;
 686              } else {
 687                  $this->$key = $value;
 688              }
 689          }
 690      }
 691  }