class_SnapshotHandler.inc 11.5 KB
Newer Older
1
2
3
4
<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
  Copyright (C) 2003-2010  Cajus Pollmeier
5
  Copyright (C) 2011-2015  FusionDirectory
6
7
8
9
10
11
12
13
14
15
16
17
18

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
19
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20
21
*/

22
23
24
/*
 * \file class_SnapshotHandler
 * Source code for class SnapshotHandler
25
 */
26
27
28

/*!
 * \brief This class contains all the function needed to handle
Benoit Mortier's avatar
Benoit Mortier committed
29
30
 * the snapshot functionality
 */
31
32
class SnapshotHandler {
  var $config;
33
  var $snapshotBases  = array();
34

35
36
37
  /*!
   * \brief Create handler
   *
38
   * \param config $config
39
   */
40
  function __construct(&$config)
41
  {
42
    $this->config = $config;
43
44
45
46
47
48
49
50
51

    /* Prepare base */
    $this->snapshotRDN = $this->config->get_cfg_value("snapshotBase");
    $ldap = $this->config->get_ldap_link();
    $ldap->cd($this->config->current['BASE']);
    $ldap->create_missing_trees($this->snapshotRDN);
    if (!$ldap->success()) {
      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->snapshotRDN, "", get_class()), LDAP_ERROR);
    }
52
53
  }

54
55
56
57
  /*!
   * \brief Check if the snapshot is enable
   *
   * \return boolean TRUE if is enable, return FALSE otherwise
58
   */
59
60
  function enabled()
  {
61
    return $this->config->snapshotEnabled();
62
  }
63

64
65
66
67
  /*!
   * \brief Set a new snapshot bases
   *
   * \param array $bases
68
   */
69
70
  function setSnapshotBases($bases)
  {
71
    $this->snapshotBases = $bases;
72
73
  }

74
75
76
77
  /*!
   * \brief Get the current snapshot bases
   *
   * \return array $bases
78
   */
79
80
81
82
83
  function getSnapshotBases()
  {
    return $this->snapshotBases;
  }

84
85
86
87
88
  /* \brief Get the snapshot dn of an object dn
   */
  protected function snapshot_dn($dn)
  {
    return preg_replace("/".preg_quote($this->config->current['BASE'], '/')."$/", "", $dn)
89
            .$this->snapshotRDN;
90
91
  }

92
93
94
95
96
  /*!
   * \brief Get the deleted snapshots
   *
   * \param string $objectBase
   *
97
   * \param boolean $raw FALSE
98
   */
99
  function getDeletedSnapshots($objectBase, $raw = FALSE)
100
  {
101
102
    if (!$this->enabled()) {
      return array();
103
104
    }

105
    $ldap = $this->config->get_ldap_link();
106
107

    // Initialize base
108
    $base = $this->snapshot_dn($objectBase);
109
110

    /* Fetch all objects and check if they do not exist anymore */
111
    $objects = array();
112
113
    $ldap->cd($base);
    $ldap->ls("(objectClass=gosaSnapshotObject)", $base,
114
                      array("gosaSnapshotTimestamp", "gosaSnapshotDN", "description"));
115
    while ($entry = $ldap->fetch()) {
116
117
118
119
      $chk = str_replace($base, "", $entry['dn']);
      if (preg_match("/,ou=/", $chk)) {
        continue;
      }
120

121
      if (!isset($entry['description'][0])) {
122
123
124
125
126
127
        $entry['description'][0]  = "";
      }
      $objects[] = $entry;
    }

    /* Check if entry still exists */
128
    foreach ($objects as $key => $entry) {
129
      $ldap->cat($entry['gosaSnapshotDN'][0]);
130
      if ($ldap->count()) {
131
132
133
134
135
        unset($objects[$key]);
      }
    }

    /* Format result as requested */
136
137
138
    if ($raw) {
      return $objects;
    } else {
139
      $tmp = array();
140
      foreach ($objects as $key => $entry) {
141
142
143
        $tmp[base64_encode($entry['dn'])] = $entry['description'][0];
      }
    }
144
    return $tmp;
145
146
  }

147
148
149
150
  /*!
   * \brief Check if the DN has snapshots
   *
   * \return the numbers of snapshots
151
   */
152
153
154
155
156
  function hasSnapshots($dn)
  {
    return (count($this->getSnapshots($dn)) > 0);
  }

157
158
159
160
161
  /*!
   * \brief Get snapshots
   *
   * \param string $dn The DN
   *
162
   * \param string $raw FALSE
163
   */
164
  function getSnapshots($dn, $raw = FALSE)
165
  {
166
167
    if (!$this->enabled()) {
      return array();
168
169
    }

170
    $ldap = $this->config->get_ldap_link();
171

172
    $objectBase = preg_replace("/^[^,]*./", "", $dn);
173
174

    // Initialize base
175
    $base = $this->snapshot_dn($objectBase);
176
177

    /* Fetch all objects with  gosaSnapshotDN=$dn */
178
179
    $ldap->cd($base);
    $ldap->ls("(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN=".$dn."))", $base,
180
        array("gosaSnapshotTimestamp","gosaSnapshotDN","description"));
181
182

    /* Put results into a list and add description if missing */
183
    $objects = array();
184
    while ($entry = $ldap->fetch()) {
185
      if (!isset($entry['description'][0])) {
186
187
188
189
190
191
        $entry['description'][0]  = "";
      }
      $objects[] = $entry;
    }

    /* Return the raw array, or format the result */
192
193
194
    if ($raw) {
      return $objects;
    } else {
195
      $tmp = array();
196
      foreach ($objects as $entry) {
197
198
199
        $tmp[base64_encode($entry['dn'])] = $entry['description'][0];
      }
    }
200
    return $tmp;
201
202
203
  }


204
205
206
207
208
209
210
  /*!
   * \brief Create a snapshot of the current object
   *
   * \param string $dn The DN
   *
   * \param array $description Snapshot description
   */
Côme Bernigaud's avatar
Côme Bernigaud committed
211
  function create_snapshot($dn, $description = array())
212
  {
213
    if (!$this->enabled()) {
214
      @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot are disabled but tried to create snapshot');
215
216
217
      return;
    }

218
219
220
221
222
223
    if (is_array($dn)) {
      $dns  = $dn;
      $dn   = $dns[0];
    } else {
      $dns = array($dn);
    }
224

225
    $ldap = $this->config->get_ldap_link();
226
227

    /* check if the dn exists */
228
    if (!$ldap->dn_exists($dn)) {
229
230
231
      @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Tried to snapshot non-existing dn');
      return;
    }
232

233
234
    /* Extract seconds & mysecs, they are used as entry index */
    list($usec, $sec) = explode(" ", microtime());
Côme Bernigaud's avatar
Côme Bernigaud committed
235

236
237
238
239
240
241
242
243
244
245
246
    /* Collect some infos */
    $base_of_object = preg_replace ('/^[^,]+,/i', '', $dn);
    $new_base       = $this->snapshot_dn($base_of_object);
    /* Create object */
    $data = '';
    foreach ($dns as $tmp_dn) {
      $data .= $ldap->generateLdif(LDAP::fix($tmp_dn), '(!(objectClass=gosaDepartment))', 'sub');
      if (!$ldap->success()) {
        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $tmp_dn, "", get_class()), LDAP_ERROR);
      }
    }
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    $newName  = str_replace(".", "", $sec."-".$usec);
    $target   = array();

    $target['objectClass']            = array("top", "gosaSnapshotObject");
    $target['gosaSnapshotData']       = gzcompress($data, 6);
    $target['gosaSnapshotDN']         = $dn;
    $target['description']            = $description;
    $target['gosaSnapshotTimestamp']  = $newName;

    /* Insert the new snapshot
       But we have to check first, if the given gosaSnapshotTimestamp
       is already used, in this case we should increment this value till there is
       an unused value. */
    $new_dn = "gosaSnapshotTimestamp=".$newName.",".$new_base;
    $ldap->cat($new_dn);
    while ($ldap->count()) {
264
      $ldap->cat($new_dn);
265
266
267
268
269
270
271
272
273
274
      $newName = str_replace(".", "", $sec."-".(++$usec));
      $new_dn                           = "gosaSnapshotTimestamp=".$newName.",".$new_base;
      $target['gosaSnapshotTimestamp']  = $newName;
    }
    /* Inset this new snapshot */
    $ldap->cd($this->snapshotRDN);
    $ldap->create_missing_trees($this->snapshotRDN);
    $ldap->create_missing_trees($new_base);
    $ldap->cd($new_dn);
    $ldap->add($target);
275

276
277
    if (!$ldap->success()) {
      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $new_base, "", get_class()), LDAP_ERROR);
278
279
280
    }
  }

281
282
283
284
  /*!
   * \brief Remove a snapshot
   *
   * \param string $dn The DN
285
   */
286
287
288
289
  function remove_snapshot($dn)
  {
    $ldap = $this->config->get_ldap_link();
    $ldap->cd($this->config->current['BASE']);
290
    $ldap->rmdir_recursive($dn);
291
    if (!$ldap->success()) {
292
      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn), LDAP_ERROR);
293
294
    }
  }
295

296
297
  /*!
   * \brief Get the available snapshots
298
   *
299
   * \return available snapshots for the given base
300
   */
301
  function Available_SnapsShots($dn, $raw = FALSE)
302
  {
303
304
305
    if (!$this->enabled()) {
      return array();
    }
306

307
    $ldap = $this->config->get_ldap_link();
308
309
310

    /* Prepare bases and some other infos */
    $base_of_object = preg_replace ('/^[^,]+,/i', '', $dn);
311
    $new_base       = $this->snapshot_dn($base_of_object);
312
313
314
    $tmp            = array();

    /* Fetch all objects with  gosaSnapshotDN=$dn */
315
316
    $ldap->cd($new_base);
    $ldap->ls("(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN=".$dn."))", $new_base,
317
        array("gosaSnapshotTimestamp","gosaSnapshotDN","description"));
318
319

    /* Put results into a list and add description if missing */
320
    while ($entry = $ldap->fetch()) {
321
      if (!isset($entry['description'][0])) {
322
323
324
325
326
327
        $entry['description'][0]  = "";
      }
      $tmp[] = $entry;
    }

    /* Return the raw array, or format the result */
328
329
330
    if ($raw) {
      return $tmp;
    } else {
331
      $tmp2 = array();
332
      foreach ($tmp as $entry) {
333
334
335
        $tmp2[base64_encode($entry['dn'])] = $entry['description'][0];
      }
    }
336
    return $tmp2;
337
  }
338
339
340
341
342
343

  /*!
   * \brief Get all deleted snapshots
   *
   * \param string $base_of_object
   *
344
   * \param boolean $raw FALSE
345
   */
346
  function getAllDeletedSnapshots($base_of_object, $raw = FALSE)
347
  {
348
349
    if (!$this->enabled()) {
      return array();
350
351
    }

352
    $ldap = $this->config->get_ldap_link();
353

354
    /* Prepare bases */
355
356
357
    $new_base       = $this->snapshot_dn($base_of_object);
    /* Fetch all objects and check if they do not exist anymore */
    $tmp  = array();
358
    $ldap->cd($new_base);
359
    $ldap->ls("(objectClass=gosaSnapshotObject)", $new_base, array("gosaSnapshotTimestamp","gosaSnapshotDN","description"));
360
    while ($entry = $ldap->fetch()) {
361

362
363
364
365
      $chk = str_replace($new_base, "", $entry['dn']);
      if (preg_match("/,ou=/", $chk)) {
        continue;
      }
366

367
      if (!isset($entry['description'][0])) {
368
369
370
371
372
373
        $entry['description'][0]  = "";
      }
      $tmp[] = $entry;
    }

    /* Check if entry still exists */
374
    foreach ($tmp as $key => $entry) {
375
      $ldap->cat($entry['gosaSnapshotDN'][0]);
376
      if ($ldap->count()) {
377
378
379
380
381
        unset($tmp[$key]);
      }
    }

    /* Format result as requested */
382
383
384
    if ($raw) {
      return $tmp;
    } else {
385
      $tmp2 = array();
386
      foreach ($tmp as $key => $entry) {
387
388
389
        $tmp2[base64_encode($entry['dn'])] = $entry['description'][0];
      }
    }
390
    return $tmp2;
391
392
393
  }


394
395
396
397
398
  /*!
   * \brief Restore selected snapshot
   *
   * \param string $dn The DN
   */
399
400
  function restore_snapshot($dn)
  {
401
    if (!$this->enabled()) {
402
      @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot are disabled but tried to restore snapshot');
403
      return array();
404
405
    }

406
    $ldap = $this->config->get_ldap_link();
407

408
    /* Get the snapshot */
409
410
    $ldap->cat($dn);
    $ldap->fetch();
411
412

    /* Prepare import string */
413
    $data = gzuncompress($ldap->get_attribute($dn, 'gosaSnapshotData'));
414
415
416
    if ($data === FALSE) {
      msg_dialog::display(_('Error'), _('There was a problem uncompressing snapshot data'), ERROR_DIALOG);
    }
417
418

    /* Import the given data */
419
420
    try {
      $ldap->import_complete_ldif($data, FALSE, FALSE);
421
422
423
      if (!$ldap->success()) {
        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, "", get_class()), LDAP_ERROR);
      }
424
    } catch (Exception $e) {
425
426
      msg_dialog::display(_('LDAP error'), $e->getMessage(), ERROR_DIALOG);
    }
427
428
429
  }
}
?>