Code

Backports from 2.7
[gosa.git] / gosa-core / plugins / addons / dyngroup / class_DynamicLdapGroup.inc
1 <?php
3 /*
4  * This code is part of GOsa (http://www.gosa-project.org)
5  * Copyright (C) 2003-2008 GONICUS GmbH
6  * Copyright (C) 2010 Thomas CHEMINEAU
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 /**
24  * This class will allow user to parameter dynamic group.
25  * @author Thomas Chemineau - thomas.chemineau<at>gmail.com
26  * @version 0.01
27  */
28 class DynamicLdapGroup extends plugin
29 {
31     /**
32      * The attribute that will use GOsa to store LDAP URI.
33      * @var array
34      */
35     public $attributes = array('labeledURI');
37     /**
38      * The objectClass that will use GOsa to identify a group as dynamic.
39      * @var array
40      */
41     public $objectclasses = array('labeledURIObject');
43     /**
44      * Default value for the corresponding attribute found in the $this->attributes
45      * array of this plugin.
46      * @var string
47      */
48     public $labeledURI = array();
49     public $labeledURIparsed = array();
50     public $labeledURIdefault = 'ldap:///dc=example,dc=com?memberUid?sub?(objectClass=posixGroup)';
51     
52     public $scopes = array('base','one','sub');
54     /**
55      * Store values of memberUrl.
56      * @var Array
57      */
58     private $_memberUrls = Array();
60     public $orig_dn ="";
62     /**
63      * Create this object.
64      * @param Array $config GOsa config.
65      * @param string $dn Current DN.
66      */
67     public function __construct ($config, $dn)
68     {
69         parent::__construct($config, $dn);
71         // Load labeledURI values.
72         $this->labeledURI = array();
73         if(!$this->is_account){
74             $this->labeledURI[] = str_replace('dc=example,dc=com', LDAP::fix($this->dn), $this->labeledURIdefault);
75         }elseif(isset($this->attrs['labeledURI'])){
76             for($i =0; $i < $this->attrs['labeledURI']['count']; $i++) {
77                 $this->labeledURI[] = $this->attrs['labeledURI'][$i];
78             }
79         }
81         // Parse labeledURI entries
82         $this->labeledURIparsed = array();
83         foreach($this->labeledURI as $entry){
84             list($base,$attr,$scope,$filter) = preg_split("/\?/",$entry); 
85             
86             // Ignore entries that do not have a valid scope value (one,base,sub)
87             if(!in_array_strict($scope,array('base','one','sub'))) continue;
89             // Append parsed uri
90             $scope = array_search($scope,$this->scopes);
91             $this->labeledURIparsed[] = array('base' => $base, 'attr' => $attr, 'scope' => $scope,'filter' => $filter);
92         }
93    
94         // Save dn, to be able the check for object movements - put this in plugin::move 
95         $this->orig_dn = $this->dn;
96     }
99     /*!\brief    Checks whether the given attribute is managed by this dyngroup extension or not.
100      */
101     function isAttributeDynamic($attr)
102     {
103         if($this->is_account){
104             foreach($this->labeledURIparsed as $uri){
105                 if($uri['attr'] == $attr) return(TRUE);
106             }
107         }
108         return(FALSE);
109     }
112     public function check ()
113     {
114         $messages = plugin::check();
115         
116         // At least one entry is required. 
117         if(!count($this->labeledURIparsed)){
118             $messages[] = msgPool::required(_("Labeled URI"));
119         }  
121         // Check entries
122         foreach($this->labeledURIparsed as $key => $entry){
123             $nr = $key +1;
125             // A base is required
126             if(empty($entry['base'])){
127                 $messages[] = msgPool::required(_("Base")." {$nr}");
128             }
130             // Check for invalid attributes
131             if(empty($entry['attr'])){
132                 $messages[] = msgPool::required(_("Attribute")." {$nr}");
133             }elseif(in_array_strict(strtolower($entry['attr']), array('objectclass'))){
134                 $messages[] = msgPool::reserved(_("Attribute")." {$nr}");
135             }
137             // A filter is required
138             if(empty($entry['filter'])){
139                 $messages[] = msgPool::required(_("Filter")." {$nr}");
140             }elseif(!preg_match("/^\(/", $entry['filter'])){
141                 $messages[] = msgPool::invalid(_("Filter")." {$nr}",  $entry['filter'],'', '(objectClass=gosaAccount)'." - "._("Surrounding brackets are required!"));
142             }else{
144                 // Check if filter is valid
145                 $ldap = $this->config->get_ldap_link();
146                 $ldap->cd($this->config->current['BASE']);
147                 $ldap->search($entry['filter']);
148                 if(!$ldap->success()){
149                     $messages[] = sprintf(_("The given filter '%s' for entry %s seems to be invalid!"),
150                             bold($entry['filter']), $nr);
151                 }
152             }
153         }
154  
155         return($messages);
156     }
159     /**
160      * Execute this plugin.
161      * @return string HTML to print.
162      */
163     public function execute ()
164     {
165         //
166         // Are we trying to modify state of this group ? If so,
167         // we can edit the current object.
168         //
169         if (isset($_POST['modify_state']))
170         {
171             $this->is_account = !$this->is_account;
172         }
174         //
175         // Display a message if this feature is disabled.
176         //
177         if (!$this->is_account)
178         {
179             return $this->show_disable_header(msgPool::addFeaturesButton(_("Dynamic object")), msgPool::featuresDisabled(_("Dynamic object")));
180         }
181         $display = $this->show_disable_header(msgPool::removeFeaturesButton(_("Dynamic object")), msgPool::featuresEnabled(_("Dynamic object")));
183         // Display values.
184         //
185         $smarty = get_smarty();
186         $smarty->assign('labeledURIparsed',  set_post($this->labeledURIparsed));
187         $smarty->assign('scopes', set_post($this->scopes));
188         $display .= $smarty->fetch(get_template_path('dyngroup.tpl', TRUE, dirname(__FILE__)));
189         return $display;
190     }
194     /**
195      * This plugin does nothing when this method is invoked.
196      */
197     public function remove_from_parent ()
198     {
199         parent::remove_from_parent();
200         $ldap = $this->config->get_ldap_link();
201         $ldap->cd($this->dn);
202         $ldap->modify($this->attrs);
203         if(!$ldap->success()){
204             msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
205         }
206         return;
207     }
210     /**
211      * This function is called when tab is undisplayed. For example, the current user
212      * wants to change other settings of this group, but not save it to the LDAP
213      * directory directly.
214      */
215     public function save_object ()
216     {
217         parent::save_object();
219         // Add a new labeled Uri
220         if(isset($_POST['addUri'])){
221             $this->labeledURIparsed[] = 
222                 array(
223                         'base' => 'ldap:///'.$this->dn,
224                         'attr' => 'memberUid', 
225                         'scope' => 2,
226                         'filter' => '(objectClass=posixGroup)');
227         }
229         // Remove a labeled Uri and get posts
230         foreach($this->labeledURIparsed as $key => $data){
231             foreach(array('scope','attr','filter','base') as $attr){
232                 if(isset($_POST[$attr.'_'.$key])){
233                     $this->labeledURIparsed[$key][$attr] = get_post($attr.'_'.$key);
234                 }
235             }
236         
237             // Remove labeled uri if requested
238             if(isset($_POST['delUri_'.$key])){
239                 unset($this->labeledURIparsed[$key]);
240             }
241         }
242         $this->labeledURIparsed = array_values($this->labeledURIparsed);
243     }
246     /**
247      * That will add additionnal information into the current LDAP entry.
248      * If this plugin is disable, then it will remove any data that references
249      * this plugin into the LDAP directory.
250      * @return boolean
251      */
252     public function save ()
253     {
254         // Build up labeledUri entries
255         $this->labeledURI = array();
256         foreach($this->labeledURIparsed as $entry){
257             $scope = $this->scopes[$entry['scope']];
258             $filter = $entry['filter'];
259             $this->labeledURI[] = "{$entry['base']}?{$entry['attr']}?{$scope}?{$filter}";
260         }
261         $this->labeledURI = array_unique($this->labeledURI);
263         parent::save();
264         $this->cleanup();
265         $ldap = $this->config->get_ldap_link();
266         $ldap->cd($this->dn);
267         $ldap->modify($this->attrs);
268         if(!$ldap->success()){
269             msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
270         }
271     }
274     /*! \brief      Updates labeledURI entries in ldap.
275      *              Check whether the given src_dn is part of some labeledURI entries
276      *               and then updates the entries to use the dst_dn.
277      * @param       $config     The GOsa configuration object.
278      * @param       $src_dn     The source 'dn' of the object that was moved.
279      * @param       $dst_dn     The target 'dn' of the object that was moved.
280      */
281     public static function moveDynGroup($config,$src_dn,$dst_dn)
282     {
283         // Fetch all dynamic group definitions 
284         $objs = get_list("(&(objectClass=labeledURIObject)(labeledURI=*))",array("all"),$config->current['BASE'],
285                 array("dn","labeledURI"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
286         $newAttrs = array();
287         foreach($objs as $obj){
288             $changes = false;
289             $attrs = array();
290             for($i = 0; $i < $obj['labeledURI']['count']; $i++){
291                 $c = $obj['labeledURI'][$i];
292                 $c = preg_replace('/'.preg_quote($src_dn,'/').'/',$dst_dn,$c);
293                 $attrs['labeledURI'][] = $c;
295                 // Check if something has changed
296                 if($c != $obj['labeledURI'][$i]){
297                     $changes =TRUE;
298                 }
299             }
301             // If at least one line of 'labeledURI' has changed then we have to update the whole entry.
302             if($changes)      $newAttrs[$obj['dn']] = $attrs;
303         }
304  
305         // If we've at least one entry to update then 
306         if(count($newAttrs)){
307             $ldap = $config->get_ldap_link();
308             foreach($newAttrs as $dn => $data){
309                 $ldap->cd($dn);
310                 $ldap->modify($data);
311                 if(!$ldap->success()){
312                     trigger_error(sprintf("Failed to dynamic group object for %s: %s", bold($dn), $ldap->get_error()));
313                     new log("debug",
314                             "plugin/plugin::move()",$dn,array(),
315                             " -- ERROR -- Failed to update dynamic groups (labeledURI) - ".$ldap->get_error());
316                 }else{
317                     new log("modify",
318                             "plugin/plugin::move()",$dn,array_keys($data),
319                             "Updated dynamic group entries (labeledURI)");
320                 }
321             }
322         }
323     }
326     /**
327      * Static method to set ACL for this plugin.
328      */
329     public static function plInfo()
330     {
331         return Array(
332                 "plShortName"   => _("Dynamic object"),
333                 "plDescription" => _("Dynamic object"),
334                 "plSelfModify"  => TRUE,
335                 "plDepends"     => Array(),
336                 "plPriority"    => 1,
337                 "plSection"     => Array("addon"),
338                 "plCategory"    => Array("groups", "department", "ogroups"),
339                 "plProvidedAcls" => array(
340                     'labeledURI' =>  _('Labeled URI'),
341                     )
342                 );
343     }
346 ?>