35 protected $snapshotRDN;
36 protected $snapshotsCache;
38 static function plInfo ()
41 'plShortName' => _(
'Snapshot'),
42 'plDescription' => _(
'Snapshot handler'),
47 'restore_over' => _(
'Restore over an existing object'),
48 'restore_deleted' => _(
'Restore a deleted object'),
59 $this->
enabled = $config->snapshotEnabled();
62 $this->snapshotRDN = $config->get_cfg_value(
'snapshotBase');
63 $ldap = $config->get_ldap_link();
64 $ldap->cd($config->current[
'BASE']);
66 $ldap->create_missing_trees($this->snapshotRDN);
80 return $this->enabled;
85 protected function snapshot_dn ($dn)
88 return preg_replace(
"/".preg_quote($config->current[
'BASE'],
'/').
"$/",
"", $dn)
97 foreach ($bases as $base) {
115 $ldap = $config->get_ldap_link();
118 $base = $this->snapshot_dn($base);
122 $ldap->search(
'(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN=*))', [
'gosaSnapshotDN']);
125 $this->snapshotsCache = [];
126 while ($entry = $ldap->fetch()) {
127 $this->snapshotsCache[$entry[
'gosaSnapshotDN'][0]] = TRUE;
138 return isset($this->snapshotsCache[$dn]);
155 $ldap = $config->get_ldap_link();
157 $objectBase = preg_replace(
"/^[^,]*./",
"", $dn);
160 $base = $this->snapshot_dn($objectBase);
165 '(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN='.ldap_escape_f($dn).
'))',
166 [
'gosaSnapshotTimestamp',
'gosaSnapshotDN',
'description'],
172 while ($entry = $ldap->fetch(TRUE)) {
173 if (!isset($entry[
'description'][0])) {
174 $entry[
'description'][0] =
"";
184 foreach ($objects as $entry) {
185 $tmp[base64_encode($entry[
'dn'])] = $entry[
'description'][0];
203 function createSnapshot ($dn,
string $description,
string $objectType,
string $snapshotSource =
'FD')
207 logging::debug(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn,
'Snapshot are disabled but tried to create snapshot');
218 $ldap = $config->get_ldap_link();
221 if (!$ldap->dn_exists($dn)) {
222 logging::debug(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn,
'Tried to snapshot non-existing dn');
227 list($usec, $sec) = explode(
" ", microtime());
230 $base_of_object = preg_replace(
'/^[^,]+,/i',
'', $dn);
231 $new_base = $this->snapshot_dn($base_of_object);
234 foreach ($dns as $tmp_dn) {
236 $data .= $ldap->generateLdif($tmp_dn,
'(!(objectClass=gosaDepartment))',
'sub');
240 _(
'Failed to create snapshot: %s'),
251 $target[
'objectClass'] = [
'top',
'gosaSnapshotObject'];
252 $target[
'gosaSnapshotData'] = gzcompress($data, 6);
253 $target[
'gosaSnapshotDN'] = $dn;
254 $target[
'description'] = $description;
255 $target[
'fdSnapshotObjectType'] = $objectType;
256 $target[
'fdSnapshotDataSource'] = $snapshotSource;
257 $target[
'fdSnapshotHash'] = md5($data);
264 $target[
'gosaSnapshotTimestamp'] = str_replace(
'.',
'', $sec.
'-'.$usec);
265 $new_dn =
'gosaSnapshotTimestamp='.$target[
'gosaSnapshotTimestamp'].
','.$new_base;
268 }
while ($ldap->count());
271 $ldap->cd($this->snapshotRDN);
273 $ldap->create_missing_trees($this->snapshotRDN);
274 $ldap->create_missing_trees($new_base);
281 if (!$ldap->success()) {
285 logging::log(
'snapshot',
'create', $new_dn, array_keys($target), $ldap->get_error());
290 public function verifySnapshotRetention (
string $dn) :
void 295 if (isset($config->current[
'SNAPSHOTMINRETENTION']) && !empty($config->current[
'SNAPSHOTMINRETENTION'])) {
296 $snapMinRetention = $config->current[
'SNAPSHOTMINRETENTION'];
298 $snapMinRetention = 0;
301 if (isset($config->current[
'SNAPSHOTRETENTIONDAYS']) && !empty($config->current[
'SNAPSHOTRETENTIONDAYS'])) {
302 $snapRetentionDays = $config->current[
'SNAPSHOTRETENTIONDAYS'];
304 $snapRetentionDays = -1;
308 if ($snapRetentionDays !== -1) {
309 $todayMinusRetention = time() - ($snapRetentionDays * 24 * 60 * 60);
310 $snapDateToDelete = strtotime(date(
'Y-m-d H:i:s', $todayMinusRetention));
317 if (isset($dnSnapshotsList) && !empty($dnSnapshotsList)) {
318 foreach ($dnSnapshotsList as $snap) {
321 $snapEpoch = preg_split(
'/-/', $snap[
'gosaSnapshotTimestamp'][0]);
322 if ($snapEpoch[0] < $snapDateToDelete) {
323 $snapToDelete[] = $snap[
'dn'];
329 if (!empty($snapToDelete) && ($snapCount > $snapMinRetention)) {
330 $snapToKeep = $snapCount - $snapMinRetention;
333 for ($i = 0; $i < $snapToKeep; $i++) {
335 if (!empty($snapToDelete[$i])) {
351 $ldap = $config->get_ldap_link();
352 $ldap->cd($config->current[
'BASE']);
353 $ldap->rmdir_recursive($dn);
354 if (!$ldap->success()) {
358 logging::log(
'snapshot',
'delete', $dn, [], $ldap->get_error());
373 $ldap = $config->get_ldap_link();
376 $base_of_object = preg_replace(
'/^[^,]+,/i',
'', $dn);
377 $new_base = $this->snapshot_dn($base_of_object);
381 $ldap->cd($new_base);
383 '(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN='.ldap_escape_f($dn).
'))',
384 [
'gosaSnapshotTimestamp',
'gosaSnapshotDN',
'description',
'fdSnapshotObjectType',
'fdSnapshotHash'],
389 while ($entry = $ldap->fetch(TRUE)) {
390 if (!isset($entry[
'description'][0])) {
391 $entry[
'description'][0] =
"";
411 $ldap = $config->get_ldap_link();
414 $new_base = $this->snapshot_dn($base_of_object);
417 $ldap->cd($new_base);
419 '(objectClass=gosaSnapshotObject)',
420 [
'gosaSnapshotTimestamp',
'gosaSnapshotDN',
'description',
'fdSnapshotObjectType',
'fdSnapshotHash'],
423 while ($entry = $ldap->fetch(TRUE)) {
424 $chk = str_replace($new_base,
"", $entry[
'dn']);
425 if (preg_match(
"/,ou=/", $chk)) {
429 if (!isset($entry[
'description'][0])) {
430 $entry[
'description'][0] =
"";
436 foreach ($tmp as $key => $entry) {
437 if ($ldap->dn_exists($entry[
'gosaSnapshotDN'][0])) {
455 logging::debug(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn,
'Snapshot are disabled but tried to restore snapshot');
459 $ldap = $config->get_ldap_link();
462 $ldap->cat($dn, [
'gosaSnapshotData',
'gosaSnapshotDN'],
'(gosaSnapshotData=*)');
463 if ($attrs = $ldap->fetch()) {
465 $data = gzuncompress($attrs[
'gosaSnapshotData'][0]);
466 if ($data === FALSE) {
479 $ldap->import_complete_ldif($data, FALSE, FALSE);
480 logging::log(
'snapshot',
'restore', $dn, [], $ldap->get_error());
481 if (!$ldap->success()) {
486 return $attrs[
'gosaSnapshotDN'][0];
490 logging::log(
'snapshot',
'restore', $dn, [], $e->getMessage());
htmlescape(string $str)
Escape string for HTML output.
getAvailableSnapsShots($dn)
Get the available snapshots.
static log(string $action, string $objecttype, string $object, array $changes=[], string $result='')
logging method
Error returned by an LDAP operation called from FusionDirectory.
enabled()
Check if the snapshot is enable.
getSnapshots($dn, $raw=FALSE)
Get snapshots.
hasDeletedSnapshots($bases)
Check if there are deleted snapshots.
initSnapshotCache($base)
Cache Snapshot information for all objects in $base.
static debug(int $level, int $line, string $function, string $file, $data, string $info='')
Debug output method.
Exception class which can be thrown by LDAP class if LDIF export fails.
getAllDeletedSnapshots($base_of_object)
Get all deleted snapshots.
This class contains all the function needed to handle the snapshot functionality. ...
removeSnapshot($dn)
Remove a snapshot.
Parent class for all errors in FusionDirectory.
createSnapshot($dn, string $description, string $objectType, string $snapshotSource='FD')
Create a snapshot of the current object.
restoreSnapshot($dn)
Restore selected snapshot.
Exception class which can be thrown by LDAP if the LDIF format is broken.
__construct()
Create handler.
hasSnapshots($dn)
Check if the DN has snapshots.