1 <?php
4 class mailMethod{
6 /* Allow modification of account_ids for existing mail accounts */
7 protected $modifyableMail = TRUE;
9 /* Allow modification of the mail server attribute existing mail accounts */
10 protected $modifyableServer = TRUE;
12 /* Enforces same value for 'mail' as used for 'cn' */
13 protected $mailEqualsCN = FALSE;
15 /* the attribute used to create accounts */
16 protected $uattrib = "mail"; // Naming attribute for accounts, e.g. imap.
18 /* The account prefixes, keep the '.' here! See FAQ cyrusUseSlashes */
19 protected $user_prefix = "user.";
20 protected $share_prefix = "share.";
22 /* Account ID creation
24 !!Depends on the attributes 'user_prefix'/'share_prefix' and the option 'cyrusUseSlashes'
26 Examples - based on defaults :
27 %PREFIX% => "user." or "user/" (Depending on cyrusUseSlashes=FALSE/TRUE)
28 %CN% => "technik" (The groups cn)
29 %UID% => "herbert" (The users uid)
30 %MAIL% => "herbert@domain.de"(The mail address)
31 %DOMAIN% => "domain.de" (The domain part of the specified mail)
32 %MAILPART% => "herbert" (The mail address without domain)
33 %UATTRIB% => "herbert"/"herbert@domains.de"
34 (Configured in gosa.conf mailAttribute="mail"/"uid")
35 */
36 protected $user_id = "%PREFIX%%UATTRIB%";
37 protected $share_id = "%PREFIX%%UATTRIB%";
39 /* Create accounts in cyrus style with '/' instead of '.' */
40 protected $cyrusUseSlashes= FALSE;
42 /* The atribute mapping for this class Source --> Destination */
43 protected $attributes = array();
44 protected $userObjectClasses = array();
45 protected $shareObjectClasses = array();
47 /* Enabled mail domain selection. If enabled getMailDomains must the domain parts */
48 protected $enableDomainSelection= FALSE;
49 protected $enableQuota = TRUE;
50 protected $enableSieveManager = FALSE;
51 protected $enableVacationRange = TRUE;
52 protected $enableFolderTypes = FALSE;
54 /* Default values */
55 protected $quotaValue = 0;
56 protected $quotaUsage = 0;
58 /* Method internal */
59 protected $type = "user";
60 protected $account_id = "";
61 protected $initial_account_id = "";
62 protected $connected = FALSE;
63 protected $error = "";
64 protected $parent = NULL;
65 protected $MailServer = "";
67 protected $default_acls = array("__anyone__" => "p", "__member__" => "lrswp");
69 protected $acl_map = array(
70 "lrsw" => "read",
71 "lrswp" => "post",
72 "p" => "external post",
73 "lrswip" => "append",
74 "lrswipcd" => "write",
75 "lrswipcda"=> "admin",
76 " " => "none");
78 protected $acl_mapping = array();
81 /*! \brief Constructs the mail class
82 @param Object Config The GOsa configuration object
83 @param Object Plugin The initator
84 @param String Open "user" or "group" account.
85 */
86 function __construct(&$config, &$parent, $type = "user")
87 {
88 $this->parent = $parent;
89 $this->config = $config;
91 /* Create a refernce to the mail selected server
92 */
93 if(isset($this->parent->gosaMailServer)){
94 $this->MailServer = &$this->parent->gosaMailServer;
95 }else{
96 trigger_error("mailMethod with invalid parent object initialized.");
97 }
99 if(!in_array($this->type,array("user","group"))){
100 trigger_error("Unknown mail class type used '".$type."'.");
101 }else{
102 $this->type = $type;
103 }
105 }
108 /*! \brief Intialize attributes and config settings.
109 */
110 protected function init()
111 {
112 /* Get config value for cyrusUseSlashes
113 */
114 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
115 $this->cyrusUseSlashes = TRUE;
116 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Enabled</b>");
117 }else{
118 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Disabled</b>");
119 }
121 /* Check if the mail account identification attribute
122 is overridden in the configuration file
123 */
124 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
125 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
126 if(in_array($new_uattrib,array("mail","uid"))){
127 $this->uattrib = $new_uattrib;
128 }else{
129 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
130 "<b>MAIL:</b> Unsupported 'mailAttribute' in gosa configuration specified");
131 msg_dialog::display(_("Configuration error"),
132 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
133 }
134 }
136 /* Create ACL map */
137 foreach($this->acl_map as $acl => $name){
138 $this->acl_mapping[$acl] = _($name);
139 }
141 /* Check if we have an individual user/folder creation syntax
142 */
143 $tmp = $this->config->get_cfg_value("mailUserCreation");
144 if(!empty($tmp)){
145 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<i>".$tmp."</i>",
146 "<b>MAIL:</b> User creation set to");
147 $this->user_id = $tmp;
148 }
149 $tmp = $this->config->get_cfg_value("mailFolderCreation");
150 if(!empty($tmp)){
151 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<i>".$tmp."</i>",
152 "<b>MAIL:</b> Shared folder creation set to");
153 $this->share_id = $tmp;
154 }
156 $this->build_account_id();
157 $this->initial_account_id = $this->account_id;
158 }
161 public function fixAttributesOnLoad()
162 {
163 foreach($this->attributes as $source => $dest){
164 if(isset($this->parent->attrs[$source])){
165 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
166 }
167 if(isset($this->parent->$source)){
168 $this->parent->$dest = $this->parent->$source;
169 }
170 if(isset($this->parent->attrs[$source][0])){
171 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
172 }
173 }
174 }
177 public function mailEqualsCN()
178 {
179 return($this->mailEqualsCN);
180 }
183 public function fixAttributesOnRemove()
184 {
185 /* Remove objectClasses
186 */
187 if($this->type == "user"){
188 $this->parent->attrs['objectClass'] =
189 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
190 }else{
191 $this->parent->attrs['objectClass'] =
192 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
193 }
194 foreach($this->attributes as $source => $dest){
195 $this->attrs[$dest] = array();
196 $this->attrs[$source] = array();
197 }
198 }
200 public function fixAttributesOnStore()
201 {
202 foreach($this->attributes as $source => $dest){
203 if(isset($this->parent->attrs[$dest])){
204 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
205 }
206 if(isset($this->parent->$dest)){
207 $this->parent->$source = $this->parent->$dest;
208 }
209 }
211 if($this->type == "user"){
212 $ocs = $this->userObjectClasses;
213 }else{
214 $ocs = $this->shareObjectClasses;
215 }
216 foreach($ocs as $oc){
217 if(!in_array($oc, $this->parent->attrs['objectClass'])){
218 $this->parent->attrs['objectClass'][] = $oc;
219 }
220 }
221 }
224 /*! \brief Connect services like imap.
225 Not necessary for the base class.
226 @return Boolean True if this method is connected else false.
227 */
228 public function connect()
229 {
230 $this->reset_error();
231 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Connect method</b>: ".get_class($this));
232 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Current server</b>: ".$this->MailServer);
234 $this->connected = TRUE;
235 return(TRUE);
236 }
239 /*! \brief Returns the connection status of this method.
240 @return Boolean True if this method is connected else false.
241 */
242 public function is_connected()
243 {
244 return($this->connected);
245 }
248 /*! \brief Disconnect this method. Close services like imap connection.
249 Not necessary for the base class.
250 */
251 public function disconnect()
252 {
253 $this->reset_error();
254 if($this->is_connected()){
255 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Disconnect method</b>: ".get_class($this));
256 $this->connected =FALSE;
257 }
258 }
261 /*! \brief Returns true the current object represents a valid account
262 (Some methods may check imap accounts here.)
263 @return Boolean TRUE if this is a valid account else FALSE
264 */
265 public function account_exists()
266 {
267 $this->reset_error();
268 return(TRUE);
269 }
272 /*! \brief Returns the last error occurred
273 @return String The last error message.
274 */
275 public function get_error(){
276 return($this->error);
277 }
280 public function isModifyableMail()
281 {
282 return($this->modifyableMail);
283 }
286 public function isModifyableServer()
287 {
288 return($this->modifyableServer);
289 }
292 /*! \brief Returns TRUE if the action caused an error.
293 @return Boolean TRUE on error else FALSE
294 */
295 public function is_error(){
296 return($this->error != "");
297 }
300 /*! \brief Resets the error message.
301 */
302 public function reset_error(){
303 $this->error = "";
304 }
307 public function get_account_id()
308 {
309 $this->build_account_id();
310 return($this->account_id);
311 }
313 /*! \brief Create a new account id, like 'user/name@domain.com'.
314 */
315 protected function build_account_id()
316 {
317 /* Build account identicator */
318 if($this->type == "user"){
319 $prefix = $this->user_prefix;
320 $acc_string = $this->user_id;
321 }else{
322 $prefix = $this->share_prefix;
323 $acc_string = $this->share_id;
324 }
326 /* Create account prefix and respect "cyrusUseSlashes"
327 Do not replace escaped dots for cyrusUseSlashes.
328 */
329 $uattrib = $this->uattrib;
330 if($this->cyrusUseSlashes){
331 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
332 $acc_string = preg_replace('/([^\\\\])\./',"\\1/",$acc_string);
333 }
334 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
335 $acc_string = preg_replace("/\\\\([\.\/])/","\\1",$acc_string);
337 $domain = $mailpart = "";
338 $mail = $this->parent->mail;
339 if(preg_match("/\@/",$mail)){
340 list($mailpart,$domain) = split("\@",$mail);
341 }
343 /* Create account_id
344 */
345 $from = array("/%cn%/i","/%uid%/i","/%prefix%/i","/%uattrib%/i","/%domain%/i","/%mailpart%/i","/%mail%/i");
346 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
347 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
349 /* Check for not replaced pattern.
350 */
351 if(preg_match("/%/",$acc_id)){
352 $notr = preg_replace("/^[^%]*/","",$acc_id);
353 if(!empty($notr)){
354 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Warning</b>",
355 sprintf("<b>MAIL: WARNING unknown pattern in account creation string '%s' near '%s'</b>", $acc_id, $notr));
357 /* Remove incomprehensible patterns */
358 $acc_id = preg_replace("/%[^%]+%/","",$acc_id);
359 }
360 }
363 if($this->account_id != $acc_id){
364 $this->account_id = $acc_id;
365 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> AccountID generated: <b>".$acc_id."</b>");
366 }
367 }
370 /*! \brief Creates a valid folder id for a given folder name.
371 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
372 will result in "share/mailbox/test@domain.de"
373 This function is mainly used to read and write folder permissions.
374 @return String A valid folder id
375 */
376 public function create_folder_id($folder, $type = "")
377 {
379 if(!empty($folder)){
380 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
381 }
382 if(!empty($folder)){
383 $folder = "/".$folder;
384 }
386 /* Build account identicator */
387 if($this->type == "user"){
388 $prefix = $this->user_prefix;
389 $acc_string = $this->user_id;
390 }else{
391 $prefix = $this->share_prefix;
392 $acc_string = $this->share_id;
393 }
395 /* Create account prefix and respect "cyrusUseSlashes"
396 Do not replace escaped dots for cyrusUseSlashes.
397 */
398 $uattrib = $this->uattrib;
399 if($this->cyrusUseSlashes){
400 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
401 $acc_string = preg_replace('/([^\\\\])\./',"\\1/",$acc_string);
402 }
403 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
404 $acc_string = preg_replace("/\\\\([\.\/])/","\\1",$acc_string);
406 $domain = $mailpart = "";
407 $mail = $this->parent->mail;
408 if(preg_match("/\@/",$mail)){
409 list($mailpart,$domain) = split("\@",$mail);
410 }
412 /* Create account_id
413 */
414 $from = array("/%cn%/i","/%uid%/i","/%prefix%/i","/%uattrib%/i","/%domain%/i","/%mailpart%/i","/%mail%/i");
415 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
416 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
418 /* Check for not replaced pattern.
419 */
420 if(preg_match("/%/",$acc_id)){
421 $notr = preg_replace("/^[^%]*/","",$acc_id);
422 if(!empty($notr)){
423 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Warning</b>",
424 sprintf("<b>MAIL: WARNING unknown pattern in account creation string '%s' near '%s'</b>", $acc_id, $notr));
426 /* Remove incomprehensible patterns */
427 $acc_id = preg_replace("/%[^%]+%/","",$acc_id);
428 }
429 }
431 if(preg_match("/\@/",$acc_id)){
432 list($mail,$domain) = split("\@",$acc_id);
433 $str = trim($mail . $folder . "@" . $domain);
434 }else{
435 $str = trim($acc_id . $folder);
436 }
437 return($str) ;
438 }
441 /*! \brief Returns the configured mail method for the given parent object,
442 initialized and read for use.
443 @return mailMethod The configured mailMethod.
444 */
445 public function get_method()
446 {
447 $methods = mailMethod::get_methods();
448 if ($this->config->get_cfg_value("mailmethod") != ""){
449 $method= $this->config->get_cfg_value("mailmethod");
450 $cls = get_correct_class_name("mailMethod$method");
451 if(isset($methods[$cls])){
452 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> Selected mailMethod: <b>".$cls."</b>");
453 $tmp = new $cls($this->config,$this->parent,$this->type);
454 $tmp->init();
455 return($tmp);
456 }else{
457 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL: Invalid mailMethod defined: ".$cls.
458 " falling back to ".get_class($this)."</b>");
460 /* Print out configuration errors directly, we can't catch them everywhere.
461 */
462 msg_dialog::display(_("Configuration error"),
463 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
464 }
465 }
467 /* If no valued mailMethod could be detected, return the base class.
468 */
469 $this->init();
470 return($this);
471 }
474 /*! \brief Saves sieve settings
475 */
476 public function saveSieveSettings()
477 {
478 $this->reset_error();
479 return(TRUE);
480 }
483 /*! \brief Creates or Updates the mailAccount represented by this class.
484 */
485 public function updateMailbox()
486 {
487 $this->reset_error();
488 return(TRUE);
489 }
492 /*! \brief Update shared folder dependencies
493 */
494 public function updateSharedFolder()
495 {
496 $this->reset_error();
497 return(TRUE);
498 }
501 /*! \brief Removes the mailbox represented by this class,
502 and update shared folder ACLs .
503 */
504 public function deleteMailbox()
505 {
506 $this->reset_error();
508 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
509 "<b>MAIL: Remove account</b> from server :".$this->MailServer);
511 return(TRUE);
512 }
515 /*! \brief Returns the used mail attribute (mail,uid)
516 @param String One out of 'mail','uid'
517 */
518 public function getUAttrib()
519 {
520 return($this->uattrib);
521 }
524 /*! \brief Returns the used mail attribute (mail,uid)
525 @param String One out of 'mail','uid'
526 */
527 public function getUAttribValue()
528 {
529 $uattrib = $this->getUAttrib();
530 return($this->parent->$uattrib);
531 }
534 /*! \brief Returns whether the quota settings are enabled or not
535 @return Boolean TRUE if enabled else FALSE
536 */
537 public function quotaEnabled()
538 {
539 return($this->enableQuota);
540 }
543 /*! \brief Returns the used quota
544 @return Integer Quota used.
545 */
546 public function getQuotaUsage()
547 {
548 return(-1);
549 }
552 /*! \brief Returns the quota restrictions.
553 @return Integer Quota restrictions.
554 */
555 public function getQuota($quotaValue)
556 {
557 return($quotaValue);
558 }
561 /*! \brief Sets the mail quota
562 */
563 public function setQuota($number)
564 {
565 if(!is_numeric($number)){
566 $number = (int) $number;
567 if(!$number){
568 $number = 0;
569 }
570 }
571 $this->quotaValue = $number;
572 return(TRUE);
573 }
576 /*! \brief Returns true whether the domain is selectable or not
577 */
578 public function domainSelectionEnabled()
579 {
580 return($this->enableDomainSelection);
581 }
584 /*! \brief Returns a list of configured mail domains
585 @return Array A list of mail domains
586 */
587 public function getMailDomains()
588 {
589 return(array("Unconfigured"));
590 }
593 /*! \brief Returns the used Spamlevels for this mailmethod
594 */
595 public function getSpamLevels()
596 {
597 $spamlevel= array();
598 for ($i= 0; $i<21; $i++){
599 $spamlevel[]= $i;
600 }
601 return($spamlevel);
602 }
605 /*! \brief Returns the list of configured mailbox folders
606 @return Array The mailbox folders.
607 */
608 public function getMailboxList()
609 {
610 return(array("INBOX"));
611 }
614 /*! \brief Returns whether the vacation range is selectable or not
615 @return Boolean TRUE, FALSE
616 */
617 public function vacationRangeEnabled()
618 {
619 return($this->enableVacationRange);
620 }
623 /*! \brief Returns true if the sieveManagement is allowed
624 @return Boolean TRUE, FALSE
625 */
626 public function allowSieveManagement()
627 {
628 return($this->enableSieveManager);
629 }
632 /*! \brief Checks dependencies to other GOsa plugins.
633 */
634 public function accountCreateable(&$reason = ""){
635 return(TRUE);
636 }
639 /*! \brief Checks whether this account is removeable or not.
640 There may be some dependencies left, eg. kolab.
641 */
642 public function accountRemoveable(&$reason = ""){
643 return(TRUE);
644 }
647 /*! \brief Returns all mail servers configured in GOsa
648 that are useable with this mailMethod.
649 @return Array All useable mail servers.
650 */
651 public function getMailServers()
652 {
653 $mailserver = array();
654 $ui = get_userinfo();
655 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
656 if( $this->MailServer == $key ||
657 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
658 $mailserver[]= $key;
659 }
660 }
661 return($mailserver);
662 }
665 /*! \brief Returns the available mailMethods
666 @return Array A list of all avaialable mailMethods_
667 */
668 static protected function get_methods()
669 {
670 global $class_mapping;
671 $available = array();
672 foreach($class_mapping as $class => $path){
673 if($class == "mailMethod") continue;
674 if(preg_match("/^mailMethod/",$class)){
675 $available[$class] = $class;
676 }
677 }
678 return($available);
679 }
682 /* \brief Some method require special folder types, "kolab" for example.
683 !! Those values are dummy values, the base class doesn't use folder types;
684 @return Array Return folder types.
685 */
686 public function getAvailableFolderTypes()
687 {
688 $ret = array();
689 $ret['CAT'][''] = _("None");
690 $ret['SUB_CAT'][''][''] = _("None");
691 return($ret);
692 }
695 /* \brief Returns the selected folder type.
696 !! Those values are dummy values, the base class doesn't use folder types;
697 @return Array The folde type.
698 */
699 public function getFolderType($default)
700 {
701 return($default);
702 }
705 /* \brief Returns the selected folder type.
706 !! Those values are dummy values, the base class doesn't use folder types;
707 @return Array The folde type.
708 */
709 public function setFolderType($type)
710 {
711 return(TRUE) ;
712 }
715 /*! \brief Returns configured acls
716 */
717 public function getFolderACLs($folder_acls)
718 {
719 /* Merge given ACL with acl mapping
720 This ensures that no ACL will accidentally overwritten by gosa.
721 */
722 foreach($folder_acls as $user => $acl){
723 if(!isset($this->acl_mapping[$acl])){
724 $this->acl_mapping[$acl] = $acl;
725 }
726 }
728 return($folder_acls);
729 }
732 /*! \brief Write ACLs back to imap or what ever
733 */
734 public function setFolderACLs($array)
735 {
736 return(TRUE);
737 }
740 /*! \brief Returns a list of all possible acls.
741 @return Array ACLs.
742 */
743 public function getAclTypes()
744 {
745 return( $this->acl_mapping);
746 }
748 public function folderTypesEnabled()
749 {
750 return($this->enableFolderTypes);
751 }
753 public function allow_remove(&$reason)
754 {
755 return(TRUE);
756 }
759 /*! \brief Returns the configured mailMethod
760 @return String the configured mail method or ""
761 */
762 static public function get_current_method($config)
763 {
764 global $class_mapping;
765 $method= $config->get_cfg_value("mailmethod");
766 $cls = get_correct_class_name("mailMethod$method");
767 foreach($class_mapping as $class => $path){
768 if($class == $cls){
769 return($class);
770 }
771 }
772 return("");
773 }
776 static function quota_to_image($use,$quota)
777 {
778 if($use == -1){
779 return(" "._("Unknown"));
780 }elseif(empty($quota)){
781 return(" "._("Unlimited"));
782 }else{
783 $usage =round(($use/$quota) * 100);
784 return("<img src='progress.php?x=100&y=17&p=$usage'>");
785 }
786 }
789 /*! \brief Returns the default sharedFolder ACLs for this method.
790 @return Array Returns an array containg acls for __member__ and __anyone__
791 */
792 public function getDefaultACLs()
793 {
794 $tmp = $this->default_acls;
795 if(!isset($tmp['__member__'])) $tmp['__member__'] = " ";
796 if(!isset($tmp['__anyone__'])) $tmp['__anyone__'] = " ";
797 return($tmp);
798 }
799 }
802 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
803 ?>