You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Expiration.php 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Morris Jobke <hey@morrisjobke.de>
  7. * @author Roeland Jago Douma <roeland@famdouma.nl>
  8. * @author Victor Dubiniuk <dubiniuk@owncloud.com>
  9. *
  10. * @license AGPL-3.0
  11. *
  12. * This code is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License, version 3,
  14. * as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU Affero General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Affero General Public License, version 3,
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>
  23. *
  24. */
  25. namespace OCA\Files_Versions;
  26. use OCP\AppFramework\Utility\ITimeFactory;
  27. use OCP\IConfig;
  28. class Expiration {
  29. // how long do we keep files a version if no other value is defined in the config file (unit: days)
  30. public const NO_OBLIGATION = -1;
  31. /** @var ITimeFactory */
  32. private $timeFactory;
  33. /** @var string */
  34. private $retentionObligation;
  35. /** @var int */
  36. private $minAge;
  37. /** @var int */
  38. private $maxAge;
  39. /** @var bool */
  40. private $canPurgeToSaveSpace;
  41. public function __construct(IConfig $config,ITimeFactory $timeFactory) {
  42. $this->timeFactory = $timeFactory;
  43. $this->retentionObligation = $config->getSystemValue('versions_retention_obligation', 'auto');
  44. if ($this->retentionObligation !== 'disabled') {
  45. $this->parseRetentionObligation();
  46. }
  47. }
  48. /**
  49. * Is versions expiration enabled
  50. * @return bool
  51. */
  52. public function isEnabled() {
  53. return $this->retentionObligation !== 'disabled';
  54. }
  55. /**
  56. * Is default expiration active
  57. */
  58. public function shouldAutoExpire() {
  59. return $this->minAge === self::NO_OBLIGATION
  60. || $this->maxAge === self::NO_OBLIGATION;
  61. }
  62. /**
  63. * Check if given timestamp in expiration range
  64. * @param int $timestamp
  65. * @param bool $quotaExceeded
  66. * @return bool
  67. */
  68. public function isExpired($timestamp, $quotaExceeded = false) {
  69. // No expiration if disabled
  70. if (!$this->isEnabled()) {
  71. return false;
  72. }
  73. // Purge to save space (if allowed)
  74. if ($quotaExceeded && $this->canPurgeToSaveSpace) {
  75. return true;
  76. }
  77. $time = $this->timeFactory->getTime();
  78. // Never expire dates in future e.g. misconfiguration or negative time
  79. // adjustment
  80. if ($time < $timestamp) {
  81. return false;
  82. }
  83. // Purge as too old
  84. if ($this->maxAge !== self::NO_OBLIGATION) {
  85. $maxTimestamp = $time - ($this->maxAge * 86400);
  86. $isOlderThanMax = $timestamp < $maxTimestamp;
  87. } else {
  88. $isOlderThanMax = false;
  89. }
  90. if ($this->minAge !== self::NO_OBLIGATION) {
  91. // older than Min obligation and we are running out of quota?
  92. $minTimestamp = $time - ($this->minAge * 86400);
  93. $isMinReached = ($timestamp < $minTimestamp) && $quotaExceeded;
  94. } else {
  95. $isMinReached = false;
  96. }
  97. return $isOlderThanMax || $isMinReached;
  98. }
  99. /**
  100. * Get maximal retention obligation as a timestamp
  101. * @return int
  102. */
  103. public function getMaxAgeAsTimestamp() {
  104. $maxAge = false;
  105. if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
  106. $time = $this->timeFactory->getTime();
  107. $maxAge = $time - ($this->maxAge * 86400);
  108. }
  109. return $maxAge;
  110. }
  111. /**
  112. * Read versions_retention_obligation, validate it
  113. * and set private members accordingly
  114. */
  115. private function parseRetentionObligation() {
  116. $splitValues = explode(',', $this->retentionObligation);
  117. if (!isset($splitValues[0])) {
  118. $minValue = 'auto';
  119. } else {
  120. $minValue = trim($splitValues[0]);
  121. }
  122. if (!isset($splitValues[1])) {
  123. $maxValue = 'auto';
  124. } else {
  125. $maxValue = trim($splitValues[1]);
  126. }
  127. $isValid = true;
  128. // Validate
  129. if (!ctype_digit($minValue) && $minValue !== 'auto') {
  130. $isValid = false;
  131. \OC::$server->getLogger()->warning(
  132. $minValue . ' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
  133. ['app' => 'files_versions']
  134. );
  135. }
  136. if (!ctype_digit($maxValue) && $maxValue !== 'auto') {
  137. $isValid = false;
  138. \OC::$server->getLogger()->warning(
  139. $maxValue . ' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
  140. ['app' => 'files_versions']
  141. );
  142. }
  143. if (!$isValid) {
  144. $minValue = 'auto';
  145. $maxValue = 'auto';
  146. }
  147. if ($minValue === 'auto' && $maxValue === 'auto') {
  148. // Default: Delete anytime if space needed
  149. $this->minAge = self::NO_OBLIGATION;
  150. $this->maxAge = self::NO_OBLIGATION;
  151. $this->canPurgeToSaveSpace = true;
  152. } elseif ($minValue !== 'auto' && $maxValue === 'auto') {
  153. // Keep for X days but delete anytime if space needed
  154. $this->minAge = (int)$minValue;
  155. $this->maxAge = self::NO_OBLIGATION;
  156. $this->canPurgeToSaveSpace = true;
  157. } elseif ($minValue === 'auto' && $maxValue !== 'auto') {
  158. // Delete anytime if space needed, Delete all older than max automatically
  159. $this->minAge = self::NO_OBLIGATION;
  160. $this->maxAge = (int)$maxValue;
  161. $this->canPurgeToSaveSpace = true;
  162. } elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
  163. // Delete all older than max OR older than min if space needed
  164. // Max < Min as per https://github.com/owncloud/core/issues/16301
  165. if ($maxValue < $minValue) {
  166. $maxValue = $minValue;
  167. }
  168. $this->minAge = (int)$minValue;
  169. $this->maxAge = (int)$maxValue;
  170. $this->canPurgeToSaveSpace = false;
  171. }
  172. }
  173. }