1 <?php
2 /*
3 This code is part of GOsa (https://gosa.gonicus.de)
4 Copyright (C) 2006 Gina Haeussge <osd@foosel.net>
5 Copyright (C) 2006 Bernd Zeimetz <bernd@zeimetz.de>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
22 /*! \brief netatalk plugin
23 \author Gina Haeussge <osd@foosel.net>
24 \author Bernd Zeimetz <bernd@zeimetz.de>
25 \version 0.1
26 \date 21.3.2006
28 This class provides the functionality to read and write all attributes
29 relevant for netatalk from/to the LDAP. It does syntax checking
30 and displays the formulars required.
31 */
33 class netatalk extends plugin {
35 /* Definitions */
36 var $plHeadline = "Netatalk";
37 var $plDescription = "Manage Netatalk account";
39 var $view_logged = FALSE;
41 /* Plugin specific values */
42 var $apple_user_homepath_raw = "";
43 var $apple_user_homeurl_raw = "";
44 var $apple_user_homeurl_xml = "";
45 var $apple_user_homeurl = "";
46 var $apple_user_homeDirectory = "";
47 var $apple_user_share = "";
48 var $shares = array();
49 var $shares_settings = array();
50 var $selectedshare = "";
51 var $mountDirectory = "/Network/Servers";
53 /* Attributes to save to LDAP */
54 var $attributes = array ("apple_user_homeurl", "apple_user_homeDirectory");
55 var $CopyPasteVars= array("apple_user_homeurl", "apple_user_homeDirectory",
56 "apple_user_share","shares_settings","apple_user_homepath_raw",
57 "apple_user_homeurl_raw","apple_user_homeurl_xml","apple_user_homeurl",
58 "selectedshare","mountDirectory");
60 /* Attributes to use in smarty template */
61 var $smarty_attributes = array ("apple_user_homepath_raw", "shares", "selectedshare");
63 /* Attributes to save from $_POST */
64 var $post_attributes = array ("netatalkShare" => "apple_user_share",
65 "netatalkUserHomepath" => "apple_user_homepath_raw");
67 /* Objectclasses */
68 var $objectclasses = array ("apple-user");
69 var $uid ="";
71 /* The constructor just saves a copy of the config. You may add what ever you need. */
72 function netatalk(&$config, $dn = NULL)
73 {
75 /* Include config object */
76 $this->config = $config;
77 plugin::plugin($config, $dn);
79 /* set user id */
80 if(isset($this->attrs['uid'])){
81 $this->uid = $this->attrs['uid'][0];
82 }
84 /* Netatalk attribute include '-' and we can't handle thos attribute names.
85 Copy all thos attribute into a useable name.
86 */
87 foreach($this->attributes as $val) {
88 $name = str_replace('_', '-', $val);
89 if (isset($this->attrs[$name][0])) {
90 $this->$val = $this->attrs[$name][0];
91 }
92 }
94 /* Extract homepath value
95 */
96 if (strlen($this->apple_user_homeDirectory) >0) {
97 $this->apple_user_homepath_raw =
98 substr($this->apple_user_homeDirectory, strrpos($this->apple_user_homeDirectory, '/') + 1 );
99 }
101 /* get share list an set default values */
102 $this->get_netatalk_shares();
103 $this->apple_user_share = $this->selectedshare;
105 if(!$this->is_account){
106 $this->apple_user_share = key($this->shares);
107 }
109 /* Save initial account state */
110 $this->initially_was_account = $this->is_account;
111 }
115 /* Get netatalk shares */
116 function get_netatalk_shares()
117 {
118 /* Get netatalk shares */
119 $this->shares = array();
120 $ldap = $this->config->get_ldap_link();
121 $ldap->cd($this->config->current['BASE']);
122 $ldap->search ("(&(objectClass=mount)(|(mountType=url)(mountType=nfs))(cn=*))");
124 while ($attrs = $ldap->fetch()){
125 $tmp = explode(":", $attrs["cn"][0]);
126 $host = trim($tmp[0]);
127 $dir = trim($tmp[1]);
128 $mountType = trim($attrs["mountType"][0]);
129 if ($mountType == "url") {
130 $mountTypeReal = "netatalk";
131 } else {
132 $mountTypeReal = $mountType;
133 }
134 $share = $attrs["cn"][0]. " (" . $mountTypeReal . ")";
135 $this->shares[$share] = $share;
136 $this->shares_settings[$share]["mountType"]=$mountType;
137 $this->shares_settings[$share]["dir"]=$dir;
138 $this->shares_settings[$share]["host"]=$host;
140 $oldShare=substr($this->apple_user_homeDirectory, 0, strrpos($this->apple_user_homeDirectory, '/'));
141 $newShare=($this->mountDirectory . "/". $host . $dir );
142 if (strcmp($oldShare, $newShare)==0) {
143 $this->selectedshare = $share;
144 }
145 }
146 asort($this->shares);
147 }
150 /* Execute the plugin, produce the output. */
151 function execute()
152 {
153 plugin :: execute();
155 /* Log view */
156 if($this->is_account && !$this->view_logged){
157 $this->view_logged = TRUE;
158 new log("view","users/".get_class($this),$this->dn);
159 }
161 /* Use the smarty templating engine here... */
162 $smarty = get_smarty();
163 $display = "";
165 /* Do we need to flip is_account state? */
166 if (isset ($_POST['modify_state'])) {
167 $this->is_account = !$this->is_account;
168 }
170 /* Do we represent a valid account? */
171 if (!$this->is_account && $this->parent === NULL) {
172 $display = "<img alt=\"\"src=\"images/small-error.png\" align=\"middle\"> <b>".
173 msgPool::noValidExtension(_("Netatalk"))."</b>";
174 $display .= back_to_main();
175 return ($display);
176 }
178 /* Show tab dialog headers */
179 if ($this->parent !== NULL) {
180 if ($this->is_account) {
181 $display = $this->show_disable_header(msgPool::removeFeaturesButton(_("Netatalk")),
182 msgPool::featuresEnabled(_("Netatalk")));
183 } else {
184 $errmsg="";
185 $obj = $this->parent->by_object['posixAccount'];
186 if (!($obj->is_account) ) {
187 $display = $this->show_enable_header(msgPool::addFeaturesButton(_("Netatalk")),
188 msgPool::featuresDisabled(_("Netatalk"), _("POSIX")), TRUE);
189 } elseif (count($this->shares)== 0) {
190 $display = $this->show_enable_header(msgPool::addFeaturesButton(_("Netatalk")),
191 msgPool::featuresDisabled(_("Netatalk"), _("Netatalk or NFS share")), TRUE);
192 } else {
193 $display = $this->show_enable_header(msgPool::addFeaturesButton(_("Netatalk")),
194 msgPool::featuresDisabled(_("Netatalk")));
195 }
196 return ($display);
197 }
198 }
200 /* Assign attributes
201 */
202 foreach ($this->smarty_attributes as $val) {
203 $smarty->assign("$val", set_post($this-> $val));
204 }
206 /* Assign ACLs
207 */
208 $tmp = $this->plInfo();
209 foreach($tmp['plProvidedAcls'] as $name => $desc){
210 $smarty->assign($name."ACL",$this->getacl($name));
211 }
213 /* Let smarty fetch and process the page. */
214 $display .= ($smarty->fetch(get_template_path('netatalk.tpl', TRUE, dirname(__FILE__))));
215 return ($display);
216 }
219 /* Check if we have correct data */
220 function check()
221 {
222 $message = array ();
223 if (strlen($this->apple_user_share) == 0) {
224 $message[] = msgPool::required(_("Share"));
225 }
226 return ($message);
227 }
230 /* Save to LDAP */
231 function save()
232 {
234 /* remove a / at the end of the homepath, we neither need it there nor
235 * do we want to check for it later.
236 */
237 if(substr($this->apple_user_homepath_raw, -1, 1) === '/') {
238 $this->apple_user_homepath_raw=substr($this->apple_user_homepath_raw, 0, -1);
239 }
241 $mountType=$this->shares_settings[$this->apple_user_share]["mountType"];
242 $dir=$this->shares_settings[$this->apple_user_share]["dir"];
243 $host=$this->shares_settings[$this->apple_user_share]["host"];
245 /* Convert raw data to wished format */
246 if ($this->is_account) {
247 if($mountType=="url") {
248 $this->apple_user_homeurl_xml = '<home_dir><url>afp://'.$host.$dir . '</url><path>'.
249 $this->apple_user_homepath_raw.'</path></home_dir>';
250 $this->apple_user_homeurl = $this->apple_user_homeurl_xml;
251 } else {
252 $this->apple_user_homeurl = "";
253 }
254 $this->apple_user_homeDirectory = $this->mountDirectory . '/' . $host .
255 $dir . '/' . $this->apple_user_homepath_raw;
256 } else {
257 $this->apple_user_homeurl = "";
258 $this->apple_user_homeDirectory = "";
259 }
261 $ldap = $this->config->get_ldap_link();
262 plugin :: save();
264 /* Transform variable names from '_' to '-'.
265 */
266 foreach ($this->attributes as $val) {
267 unset($this->attrs[$val]);
268 $name = str_replace('_', '-', $val);
269 if ($this->$val != "") {
270 $this->attrs[$name] = $this->$val;
271 } else {
272 $this->attrs[$name] = array();
273 }
274 }
276 /* Write back to ldap */
277 $ldap->cd($this->dn);
278 $this->cleanup();
279 $ldap->modify($this->attrs);
281 if($this->initially_was_account){
282 new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
283 }else{
284 new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
285 }
287 if (!$ldap->success()){
288 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
289 }
291 /* Optionally execute a command after we're done */
292 if ($this->initially_was_account == $this->is_account) {
293 if ($this->is_modified) {
294 $this->handle_post_events("modify",array("uid" => $this->uid));
295 }
296 } else {
297 $this->handle_post_events("add",array("uid" => $this->uid));
298 }
299 }
302 /* Use Save_object for every Post handling
303 */
304 function save_object()
305 {
306 if (isset ($_POST['netatalkTab'])) {
307 /* Save ldap attributes */
308 plugin :: save_object();
310 foreach($this->post_attributes as $acl => $val) {
311 if(!preg_match("/w/",$this->getacl($acl))) continue;
312 if (isset ($_POST[$val])) {
313 $this->$val = get_post($val);
314 } else {
315 $this->$val = "";
316 }
317 }
318 $this->apple_user_homeurl_raw = 'afp://' . $this->apple_user_share;
319 }
320 }
323 function remove_from_parent()
324 {
326 /* Cancel if there's nothing to do here */
327 if (!$this->initially_was_account) {
328 return;
329 }
331 /* include global link_info */
332 $ldap = $this->config->get_ldap_link();
334 /* Remove and write to LDAP */
335 plugin :: remove_from_parent();
336 $this->cleanup();
338 /* Attribute name conversion "_" to "-" */
339 foreach($this->attributes as $val){
340 unset($this->attrs[$val]);
341 $name = preg_replace("/_/","-",$val);
342 $this->attrs[$name] = array();
343 }
345 @ DEBUG(DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__, $this->attributes, "Save");
346 $ldap->cd($this->dn);
348 $ldap->modify($this->attrs);
350 new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
352 if (!$ldap->success()){
353 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
354 }
356 /* remove the entry from LDAP */
357 unset ($this->attrs['uid']);
359 /* Optionally execute a command after we're done */
360 $this->handle_post_events('remove', array("uid" => $this->uid));
361 }
364 /* Return plugin informations for acl handling*/
365 static function plInfo()
366 {
367 return (array(
368 "plDescription" => _("Netatalk"),
369 "plSelfModify" => TRUE,
370 "plDepends" => array("user"),
371 "plPriority" => 6,
372 "plSection" => array("personal" => _("My account")),
373 "plCategory" => array("users"),
374 "plOptions" => array(),
375 "plRequirements"=> array(
376 'ldapSchema' => array('apple-user' => ''),
377 'onFailureDisablePlugin' => array(get_class())),
378 "plProvidedAcls" => array(
379 "netatalkUserHomepath" => _("User home path"),
380 "netatalkShare" => _("Share"))
381 ));
382 }
384 function adapt_from_template($dn, $skip= array())
385 {
386 /* As the 'apple-user-homeDirectory' LDAP attribute is stored as
387 * 'apple_user_homeDirectory' internally by GOsa (to avoid problem with
388 * dashes as variable names), we need to add the dashed version to
389 * $this->attributes so that the adapt_from_template function in the plugin
390 * class will find the dashed LDAP attribute and substitute possibly
391 * placeholders like %uid. We remove the dashed version of
392 * 'apple_user_homeDirectory' from the attributes again afterwards. */
393 array_push($this->attributes, "apple-user-homeDirectory");
394 plugin::adapt_from_template($dn, $skip);
395 array_pop($this->attributes);
397 /* Loop through the available shares and find out which is the share from
398 * 'apple-user-homeDirectory'. Remove its host and directory (as well as
399 * the default 'mountDirectory' prefix) to get 'apple_user_homepath_raw'
400 * and store that share as 'selectedshare' so that it gets displayed by
401 * default in the netatalk tab. */
402 foreach($this->shares as $share) {
403 $apple_user_homepath = $this->mountDirectory."/".
404 $this->shares_settings[$share]["host"].
405 $this->shares_settings[$share]["dir"]."/";
406 if (preg_match("#$apple_user_homepath#", $this->{'apple-user-homeDirectory'})) {
407 $this->apple_user_homepath_raw = preg_replace("#$apple_user_homepath#", "", $this->{'apple-user-homeDirectory'});
408 $this->selectedshare = $share;
409 }
410 }
411 }
412 }
414 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
415 ?>