1 <?php
4 class mailMethod{
6 /* Allow modification of account_ids for existing mail accounts */
7 protected $modifyableMail = TRUE;
9 /* Enforces same value for 'mail' as used for 'cn' */
10 protected $mailEqualsCN = FALSE;
12 /* the attribute used to create accounts */
13 protected $uattrib = "mail"; // Naming attribute for accounts, e.g. imap.
15 /* The account prefixes, keep the '.' here! See FAQ cyrusUseSlashes */
16 protected $user_prefix = "user.";
17 protected $share_prefix = "share.";
19 /* Create accounts in cyrus style with '/' instead of '.' */
20 protected $cyrusUseSlashes= FALSE;
22 /* The atribute mapping for this class Source --> Destination */
23 protected $attributes = array();
24 protected $userObjectClasses = array();
25 protected $shareObjectClasses = array();
27 /* Enabled mail domain selection. If enabled getMailDomains must the domain parts */
28 protected $enableDomainSelection= FALSE;
29 protected $enableQuota = TRUE;
30 protected $enableSieveManager = FALSE;
31 protected $enableVacationRange = TRUE;
32 protected $enableFolderTypes = FALSE;
34 /* Default values */
35 protected $quotaValue = 0;
36 protected $quotaUsage = 0;
38 /* Method internal */
39 protected $type = "user";
40 protected $account_id = "";
41 protected $initial_account_id = "";
42 protected $connected = FALSE;
43 protected $error = "";
44 protected $parent = NULL;
45 protected $MailServer = "";
48 /*! \brief Constructs the mail class
49 @param Object Config The GOsa configuration object
50 @param Object Plugin The initator
51 @param String Open "user" or "group" account.
52 */
53 function __construct(&$config, &$parent, $type = "user")
54 {
55 $this->parent = $parent;
56 $this->config = $config;
58 /* Create a refernce to the mail selected server
59 */
60 if(isset($this->parent->gosaMailServer)){
61 $this->MailServer = &$this->parent->gosaMailServer;
62 }else{
63 trigger_error("mailMethod with invalid parent object initialized.");
64 }
66 if(!in_array($this->type,array("user","group"))){
67 trigger_error("Unknown mail class type used '".$type."'.");
68 }else{
69 $this->type = $type;
70 }
71 }
74 /*! \brief Intialize attributes and config settings.
75 */
76 protected function init()
77 {
78 /* Get config value for cyrusUseSlashes
79 */
80 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
81 $this->cyrusUseSlashes = TRUE;
82 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "cyrusUseSlashes: <b>Enabled</b>","");
83 }else{
84 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "cyrusUseSlashes: <b>Disabled</b>","");
85 }
87 /* Check if the mail account identification attribute
88 is overridden in the configuration file
89 */
90 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
91 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
92 if(in_array($new_uattrib,array("mail","uid"))){
93 $this->uattrib = $new_uattrib;
94 }else{
95 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
96 "Unsupported 'mailAttribute' in gosa configuration specified");
97 msg_dialog::display(_("Configuration error"),
98 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
99 }
100 }
101 $this->build_account_id();
102 $this->initial_account_id = $this->account_id;
103 }
106 public function fixAttributesOnLoad()
107 {
108 foreach($this->attributes as $source => $dest){
109 if(isset($this->parent->attrs[$source])){
110 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
111 }
112 if(isset($this->parent->$source)){
113 $this->parent->$dest = $this->parent->$source;
114 }
115 if(isset($this->parent->attrs[$source][0])){
116 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
117 }
118 }
119 }
122 public function mailEqualsCN()
123 {
124 return($this->mailEqualsCN);
125 }
128 public function fixAttributesOnRemove()
129 {
130 /* Remove objectClasses
131 */
132 if($this->type == "user"){
133 $this->parent->attrs['objectClass'] =
134 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
135 }else{
136 $this->parent->attrs['objectClass'] =
137 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
138 }
139 foreach($this->attributes as $source => $dest){
140 $this->attrs[$dest] = array();
141 $this->attrs[$source] = array();
142 }
143 }
145 public function fixAttributesOnStore()
146 {
147 foreach($this->attributes as $source => $dest){
148 if(isset($this->parent->attrs[$dest])){
149 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
150 }
151 if(isset($this->parent->$dest)){
152 $this->parent->$source = $this->parent->$dest;
153 }
154 }
156 if($this->type == "user"){
157 $ocs = $this->userObjectClasses;
158 }else{
159 $ocs = $this->shareObjectClasses;
160 }
161 foreach($ocs as $oc){
162 if(!in_array($oc, $this->parent->attrs['objectClass'])){
163 $this->parent->attrs['objectClass'][] = $oc;
164 }
165 }
166 }
169 /*! \brief Connect services like imap.
170 Not necessary for the base class.
171 @return Boolean True if this method is connected else false.
172 */
173 public function connect()
174 {
175 $this->reset_error();
176 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Connect method</b>: ".get_class($this),"");
177 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Current server</b>: ".$this->MailServer,"");
179 $this->connected = TRUE;
180 return(TRUE);
181 }
184 /*! \brief Returns the connection status of this method.
185 @return Boolean True if this method is connected else false.
186 */
187 public function is_connected()
188 {
189 return($this->connected);
190 }
193 /*! \brief Disconnect this method. Close services like imap connection.
194 Not necessary for the base class.
195 */
196 public function disconnect()
197 {
198 $this->reset_error();
199 if($this->is_connected()){
200 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Disconnect method</b>: ".get_class($this),"");
201 $this->connected =FALSE;
202 }
203 }
206 /*! \brief Returns true the current object represents a valid account
207 (Some methods may check imap accounts here.)
208 @return Boolean TRUE if this is a valid account else FALSE
209 */
210 public function account_exists()
211 {
212 $this->reset_error();
213 return(TRUE);
214 }
217 /*! \brief Returns the last error occurred
218 @return String The last error message.
219 */
220 public function get_error(){
221 return($this->error);
222 }
225 public function isModifyableMail()
226 {
227 return($this->modifyableMail);
228 }
231 /*! \brief Returns TRUE if the action caused an error.
232 @return Boolean TRUE on error else FALSE
233 */
234 public function is_error(){
235 return($this->error != "");
236 }
239 /*! \brief Resets the error message.
240 */
241 public function reset_error(){
242 $this->error = "";
243 }
246 public function get_account_id()
247 {
248 $this->build_account_id();
249 return($this->account_id);
250 }
252 /*! \brief Create a new account id, like 'user/name@domain.com'.
253 */
254 protected function build_account_id()
255 {
256 /* Build account identicator */
257 if($this->type == "user"){
258 $str = $this->user_prefix;
259 }else{
260 $str = $this->share_prefix;
261 }
263 /* Create account prefix and respect "cyrusUseSlashes"
264 Do not replace escaped dots for cyrusUseSlashes.
265 */
266 $uattrib = $this->uattrib;
267 if($this->cyrusUseSlashes){
268 $str = preg_replace('/([^\\\\])\./',"\\1/",$str);
269 }
270 $str = preg_replace("/\\\\([\.\/])/","\\1",$str);
271 $str = trim(strtolower($str . $this->parent->$uattrib));
273 if($this->account_id != $str){
274 $this->account_id = $str;
275 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "accountID generated: <b>".$str."</b>","");
276 }
277 }
280 /*! \brief Creates a valid folder id for a given folder name.
281 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
282 will result in "share/mailbox/test@domain.de"
283 This function is mainly used to read and write folder permissions.
284 @return String A valid folder id
285 */
286 public function create_folder_id($folder, $type = "")
287 {
289 if(!empty($folder)){
290 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
291 }
292 if(!empty($folder)){
293 $folder = "/".$folder;
294 }
296 /* Build account identicator */
297 if($type == ""){
298 $type = $this->type;
299 }
300 if($type == "user"){
301 $str = $this->user_prefix;
302 }else{
303 $str = $this->share_prefix;
304 }
306 /* Create account prefix and respect "cyrusUseSlashes"
307 Do not replace escaped dots for cyrusUseSlashes.
308 */
309 $uattrib = $this->uattrib;
310 if($this->cyrusUseSlashes){
311 $str = preg_replace('/([^\\\\])\./',"\\1/",$str);
312 }
313 $str = preg_replace("/\\\\([\.\/])/","\\1",$str);
314 $str = trim(strtolower($str . $this->parent->$uattrib));
316 if(preg_match("/\@/",$this->parent->$uattrib)){
317 list($mail,$domain) = split("\@",$this->parent->$uattrib);
318 $str = trim(strtolower($str . $mail . $folder . "@" . $domain));
319 }else{
320 $str = trim(strtolower($str . $this->parent->$uattrib));
321 }
322 return($str) ;
323 }
326 /*! \brief Returns the configured mail method for the given parent object,
327 initialized and read for use.
328 @return mailMethod The configured mailMethod.
329 */
330 public function get_method()
331 {
332 $methods = mailMethod::get_methods();
333 if ($this->config->get_cfg_value("mailmethod") != ""){
334 $method= $this->config->get_cfg_value("mailmethod");
335 $cls = get_correct_class_name("mailMethod$method");
336 if(isset($methods[$cls])){
337 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "Selected mailMethod: <b>".$cls."</b>","");
338 $tmp = new $cls($this->config,$this->parent,$this->type);
339 $tmp->init();
340 return($tmp);
341 }else{
342 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "Invalid mailMethod defined <b>".$cls.
343 "</b> falling back to <b>".get_class($this)."</b>","");
345 /* Print out configuration errors directly, we can't catch them everywhere.
346 */
347 msg_dialog::display(_("Configuration error"),
348 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
349 }
350 }
352 /* If no valued mailMethod could be detected, return the base class.
353 */
354 $this->init();
355 return($this);
356 }
359 /*! \brief Saves sieve settings
360 */
361 public function saveSieveSettings()
362 {
363 $this->reset_error();
364 return(TRUE);
365 }
368 /*! \brief Creates or Updates the mailAccount represented by this class.
369 */
370 public function updateMailbox()
371 {
372 $this->reset_error();
373 return(TRUE);
374 }
377 /*! \brief Update shared folder dependencies
378 */
379 public function updateSharedFolder()
380 {
381 $this->reset_error();
382 return(TRUE);
383 }
386 /*! \brief Removes the mailbox represented by this class,
387 and update shared folder ACLs .
388 */
389 public function deleteMailbox()
390 {
391 $this->reset_error();
393 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
394 "<b>Remove account</b> from server :".$this->MailServer);
396 return(TRUE);
398 /* No imap actions here, just updated shared folder membership
399 */
400 $ldap = $this->config->get_ldap_link();
401 $ldap->cd($this->config->current['BASE']);
402 $ldap->search("(&(objectClass=posixGroup)(objectClass=gosaMailAccount)(memberUid=".$account."))",array('dn','cn'));
403 if(class_exists("grouptabs")){
404 while($attrs = $ldap->fetch()){
405 $tmp = new grouptabs($this->config, $this->config->data['TABS']['GROUPTABS'], $attrs['dn']);
406 if(isset($tmp->by_object['mailgroup'])){
407 $tmp->by_object['mailgroup']->members= $tmp->by_object['group']->memberUid;
408 if(!$this->is_account){
409 $tmp->by_object['mailgroup']->removeUserAcl($account);
410 $tmp->by_object['mailgroup']->removeUserAcl($this->mail);
411 }
412 $tmp->by_object['mailgroup']->save();
413 }
414 }
415 }
416 return(TRUE);
417 }
420 /*! \brief Returns the used mail attribute (mail,uid)
421 @param String One out of 'mail','uid'
422 */
423 public function getUAttrib()
424 {
425 return($this->uattrib);
426 }
429 /*! \brief Returns the used mail attribute (mail,uid)
430 @param String One out of 'mail','uid'
431 */
432 public function getUAttribValue()
433 {
434 $uattrib = $this->getUAttrib();
435 return($this->parent->$uattrib);
436 }
439 /*! \brief Returns whether the quota settings are enabled or not
440 @return Boolean TRUE if enabled else FALSE
441 */
442 public function quotaEnabled()
443 {
444 return($this->enableQuota);
445 }
448 /*! \brief Returns the used quota
449 @return Integer Quota used.
450 */
451 public function getQuotaUsage()
452 {
453 return(-1);
454 }
457 /*! \brief Returns the quota restrictions.
458 @return Integer Quota restrictions.
459 */
460 public function getQuota($quotaValue)
461 {
462 return($quotaValue);
463 }
466 /*! \brief Sets the mail quota
467 */
468 public function setQuota($number)
469 {
470 if(!is_numeric($number)){
471 $number = (int) $number;
472 if(!$number){
473 $number = 0;
474 }
475 }
476 $this->quotaValue = $number;
477 return(TRUE);
478 }
481 /*! \brief Returns true whether the domain is selectable or not
482 */
483 public function domainSelectionEnabled()
484 {
485 return($this->enableDomainSelection);
486 }
489 /*! \brief Returns a list of configured mail domains
490 @return Array A list of mail domains
491 */
492 public function getMailDomains()
493 {
494 return(array("Unconfigured"));
495 }
498 /*! \brief Returns the used Spamlevels for this mailmethod
499 */
500 public function getSpamLevels()
501 {
502 $spamlevel= array();
503 for ($i= 0; $i<21; $i++){
504 $spamlevel[]= $i;
505 }
506 return($spamlevel);
507 }
510 /*! \brief Returns the list of configured mailbox folders
511 @return Array The mailbox folders.
512 */
513 public function getMailboxList()
514 {
515 return(array("INBOX"));
516 }
519 /*! \brief Returns whether the vacation range is selectable or not
520 @return Boolean TRUE, FALSE
521 */
522 public function vacationRangeEnabled()
523 {
524 return($this->enableVacationRange);
525 }
528 /*! \brief Returns true if the sieveManagement is allowed
529 @return Boolean TRUE, FALSE
530 */
531 public function allowSieveManagement()
532 {
533 return($this->enableSieveManager);
534 }
537 /*! \brief Checks dependencies to other GOsa plugins.
538 */
539 public function accountCreateable(&$reason = ""){
540 return(TRUE);
541 }
544 /*! \brief Checks whether this account is removeable or not.
545 There may be some dependencies left, eg. kolab.
546 */
547 public function accountRemoveable(&$reason = ""){
548 return(TRUE);
549 }
552 /*! \brief Returns all mail servers configured in GOsa
553 that are useable with this mailMethod.
554 @return Array All useable mail servers.
555 */
556 public function getMailServers()
557 {
558 $mailserver = array();
559 $ui = get_userinfo();
560 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
561 if( $this->MailServer == $key ||
562 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
563 $mailserver[]= $key;
564 }
565 }
566 return($mailserver);
567 }
570 /*! \brief Returns the available mailMethods
571 @return Array A list of all avaialable mailMethods_
572 */
573 static protected function get_methods()
574 {
575 global $class_mapping;
576 $available = array();
577 foreach($class_mapping as $class => $path){
578 if($class == "mailMethod") continue;
579 if(preg_match("/^mailMethod/",$class)){
580 $available[$class] = $class;
581 }
582 }
583 return($available);
584 }
587 /* \brief Some method require special folder types, "kolab" for example.
588 !! Those values are dummy values, the base class doesn't use folder types;
589 @return Array Return folder types.
590 */
591 public function getAvailableFolderTypes()
592 {
593 $ret = array();
594 $ret['CAT']['mail'] = _("Mail");
595 $ret['CAT']['peter']= _("User");
596 $ret['SUB_CAT']['mail']['a'] = "a";
597 $ret['SUB_CAT']['mail']['b'] = "b";
598 $ret['SUB_CAT']['peter']['tt'] = "tt";
599 $ret['SUB_CAT']['peter']['dd'] = "dd";
600 $ret['SUB_CAT']['peter']['did'] = "did";
601 return($ret);
602 }
605 /* \brief Returns the selected folder type.
606 !! Those values are dummy values, the base class doesn't use folder types;
607 @return Array The folde type.
608 */
609 public function getFolderType($default)
610 {
611 if($this->enableFolderTypes && $this->parent->attrs['kolabFolderType'][0]){
612 list($cat,$sub) = split("\.",$this->parent->attrs['kolabFolderType'][0]);
613 return(array("CAT" => $cat, "SUB_CAT" => $sub));
614 }else{
615 return($default);
616 }
617 }
620 /* \brief Returns the selected folder type.
621 !! Those values are dummy values, the base class doesn't use folder types;
622 @return Array The folde type.
623 */
624 public function setFolderType($type)
625 {
626 $ldap = $this->config->get_ldap_link();
627 $ldap->cd ($this->parent->dn);
628 $ldap->modify(array("kolabFolderType" => $type['CAT'].".".$type['SUB_CAT']));
629 echo "Move me to KOLAB";
630 }
633 /*! \brief Returns configured acls
634 */
635 public function getFolderACLs($folder_acls)
636 {
637 return($folder_acls);
638 }
641 /*! \brief Write ACLs back to imap or what ever
642 */
643 public function setFolderACLs($array)
644 {
645 return(TRUE);
646 }
649 /*! \brief Returns a list of all possible acls.
650 @return Array ACLs.
651 */
652 public function getAclTypes()
653 {
654 $acls["lrsw"] = _("read");
655 $acls["lrswp"] = _("post");
656 $acls["p"] = _("external post");
657 $acls["lrswip"] = _("append");
658 $acls["lrswipcd"] = _("write");
659 $acls["lrswipcda"]= _("admin");
660 $acls[" "]= _("none");
661 return($acls);
662 }
664 public function folderTypesEnabled()
665 {
666 return($this->enableFolderTypes);
667 }
669 }
672 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
673 ?>