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() have to return an array
48 * with the domain parts.
49 */
50 protected $enableDomainSelection= FALSE;
51 protected $enableQuota = TRUE;
52 protected $enableSieveManager = FALSE;
53 protected $enableVacationRange = TRUE;
54 protected $enableFolderTypes = FALSE;
56 /* Default values */
57 protected $quotaValue = 0;
58 protected $quotaUsage = 0;
60 /* Method internal */
61 protected $type = "user";
62 protected $account_id = "";
63 protected $initial_account_id = "";
64 protected $connected = FALSE;
65 protected $error = "";
66 protected $parent = NULL;
67 protected $MailServer = "";
69 protected $default_acls = array("__anyone__" => "p", "__member__" => "lrswp");
71 protected $acl_map = array(
72 "lrsw" => "read",
73 "lrswp" => "post",
74 "p" => "external post",
75 "lrswip" => "append",
76 "lrswipcd" => "write",
77 "lrswipcda"=> "admin",
78 " " => "none");
80 protected $acl_mapping = array();
83 /*! \brief Constructs the mail class
84 @param Object Config The GOsa configuration object
85 @param Object Plugin The initator
86 @param String Open "user" or "group" account.
87 */
88 function __construct(&$config, &$parent, $type = "user")
89 {
90 $this->parent = $parent;
91 $this->config = $config;
93 /* Create a refernce to the mail selected server
94 */
95 if(isset($this->parent->gosaMailServer)){
96 $this->MailServer = &$this->parent->gosaMailServer;
97 }else{
98 trigger_error("mailMethod with invalid parent object initialized.");
99 }
101 if(!in_array($this->type,array("user","group"))){
102 trigger_error("Unknown mail class type used '".$type."'.");
103 }else{
104 $this->type = $type;
105 }
107 }
110 /*! \brief Intialize attributes and config settings.
111 */
112 protected function init()
113 {
114 /* Get config value for cyrusUseSlashes
115 */
116 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
117 $this->cyrusUseSlashes = TRUE;
118 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Enabled</b>");
119 }else{
120 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Disabled</b>");
121 }
123 /* Check if the mail account identification attribute
124 is overridden in the configuration file
125 */
126 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
127 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
128 if(in_array($new_uattrib,array("mail","uid"))){
129 $this->uattrib = $new_uattrib;
130 }else{
131 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
132 "<b>MAIL:</b> Unsupported 'mailAttribute' in gosa configuration specified");
133 msg_dialog::display(_("Configuration error"),
134 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
135 }
136 }
138 /* Create ACL map */
139 foreach($this->acl_map as $acl => $name){
140 $this->acl_mapping[$acl] = _($name);
141 }
143 /* Check if we have an individual user/folder creation syntax
144 */
145 $tmp = $this->config->get_cfg_value("mailUserCreation");
146 if(!empty($tmp)){
147 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<i>".$tmp."</i>",
148 "<b>MAIL:</b> User creation set to");
149 $this->user_id = $tmp;
150 }
151 $tmp = $this->config->get_cfg_value("mailFolderCreation");
152 if(!empty($tmp)){
153 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<i>".$tmp."</i>",
154 "<b>MAIL:</b> Shared folder creation set to");
155 $this->share_id = $tmp;
156 }
158 $this->build_account_id();
159 $this->initial_account_id = $this->account_id;
160 }
163 public function fixAttributesOnLoad()
164 {
165 foreach($this->attributes as $source => $dest){
166 if(isset($this->parent->attrs[$source])){
167 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
168 }
169 if(isset($this->parent->$source)){
170 $this->parent->$dest = $this->parent->$source;
171 }
172 if(isset($this->parent->attrs[$source][0])){
173 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
174 }
175 }
176 }
179 public function mailEqualsCN()
180 {
181 return($this->mailEqualsCN);
182 }
185 public function fixAttributesOnRemove()
186 {
187 /* Remove objectClasses
188 */
189 if($this->type == "user"){
190 $this->parent->attrs['objectClass'] =
191 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
192 }else{
193 $this->parent->attrs['objectClass'] =
194 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
195 }
196 foreach($this->attributes as $source => $dest){
197 $this->attrs[$dest] = array();
198 $this->attrs[$source] = array();
199 }
200 }
202 public function fixAttributesOnStore()
203 {
204 foreach($this->attributes as $source => $dest){
205 if(isset($this->parent->attrs[$dest])){
206 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
207 }
208 if(isset($this->parent->$dest)){
209 $this->parent->$source = $this->parent->$dest;
210 }
211 }
213 if($this->type == "user"){
214 $ocs = $this->userObjectClasses;
215 }else{
216 $ocs = $this->shareObjectClasses;
217 }
218 foreach($ocs as $oc){
219 if(!in_array($oc, $this->parent->attrs['objectClass'])){
220 $this->parent->attrs['objectClass'][] = $oc;
221 }
222 }
223 }
226 /*! \brief Connect services like imap.
227 Not necessary for the base class.
228 @return Boolean True if this method is connected else false.
229 */
230 public function connect()
231 {
232 $this->reset_error();
233 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Connect method</b>: ".get_class($this));
234 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Current server</b>: ".$this->MailServer);
236 $this->connected = TRUE;
237 return(TRUE);
238 }
241 /*! \brief Returns the connection status of this method.
242 @return Boolean True if this method is connected else false.
243 */
244 public function is_connected()
245 {
246 return($this->connected);
247 }
250 /*! \brief Disconnect this method. Close services like imap connection.
251 Not necessary for the base class.
252 */
253 public function disconnect()
254 {
255 $this->reset_error();
256 if($this->is_connected()){
257 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Disconnect method</b>: ".get_class($this));
258 $this->connected =FALSE;
259 }
260 }
263 /*! \brief Returns true the current object represents a valid account
264 (Some methods may check imap accounts here.)
265 @return Boolean TRUE if this is a valid account else FALSE
266 */
267 public function account_exists()
268 {
269 $this->reset_error();
270 return(TRUE);
271 }
274 /*! \brief Returns the last error occurred
275 @return String The last error message.
276 */
277 public function get_error(){
278 return($this->error);
279 }
282 public function isModifyableMail()
283 {
284 return($this->modifyableMail);
285 }
288 public function isModifyableServer()
289 {
290 return($this->modifyableServer);
291 }
294 /*! \brief Returns TRUE if the action caused an error.
295 @return Boolean TRUE on error else FALSE
296 */
297 public function is_error(){
298 return($this->error != "");
299 }
302 /*! \brief Resets the error message.
303 */
304 public function reset_error(){
305 $this->error = "";
306 }
309 public function get_account_id()
310 {
311 $this->build_account_id();
312 return($this->account_id);
313 }
315 /*! \brief Create a new account id, like 'user/name@domain.com'.
316 */
317 protected function build_account_id()
318 {
319 /* Build account identicator */
320 if($this->type == "user"){
321 $prefix = $this->user_prefix;
322 $acc_string = $this->user_id;
323 }else{
324 $prefix = $this->share_prefix;
325 $acc_string = $this->share_id;
326 }
328 /* Create account prefix and respect "cyrusUseSlashes"
329 Do not replace escaped dots for cyrusUseSlashes.
330 */
331 $uattrib = $this->uattrib;
332 if($this->cyrusUseSlashes){
333 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
334 $acc_string = preg_replace('/([^\\\\])\./',"\\1/",$acc_string);
335 }
336 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
337 $acc_string = preg_replace("/\\\\([\.\/])/","\\1",$acc_string);
339 $domain = $mailpart = "";
340 $mail = $this->parent->mail;
341 if(preg_match("/\@/",$mail)){
342 list($mailpart,$domain) = split("\@",$mail);
343 }
345 /* Create account_id
346 */
347 $from = array("/%cn%/i","/%uid%/i","/%prefix%/i","/%uattrib%/i","/%domain%/i","/%mailpart%/i","/%mail%/i");
348 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
349 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
351 /* Check for not replaced pattern.
352 */
353 if(preg_match("/%/",$acc_id)){
354 $notr = preg_replace("/^[^%]*/","",$acc_id);
355 if(!empty($notr)){
356 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Warning</b>",
357 sprintf("<b>MAIL: WARNING unknown pattern in account creation string '%s' near '%s'</b>", $acc_id, $notr));
359 /* Remove incomprehensible patterns */
360 $acc_id = preg_replace("/%[^%]+%/","",$acc_id);
361 }
362 }
365 if($this->account_id != $acc_id){
366 $this->account_id = $acc_id;
367 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> AccountID generated: <b>".$acc_id."</b>");
368 }
369 }
372 /*! \brief Creates a valid folder id for a given folder name.
373 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
374 will result in "share/mailbox/test@domain.de"
375 This function is mainly used to read and write folder permissions.
376 @return String A valid folder id
377 */
378 public function create_folder_id($folder, $type = "")
379 {
381 if(!empty($folder)){
382 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
383 }
384 if(!empty($folder)){
385 $folder = "/".$folder;
386 }
388 /* Build account identicator */
389 if($this->type == "user"){
390 $prefix = $this->user_prefix;
391 $acc_string = $this->user_id;
392 }else{
393 $prefix = $this->share_prefix;
394 $acc_string = $this->share_id;
395 }
397 /* Create account prefix and respect "cyrusUseSlashes"
398 Do not replace escaped dots for cyrusUseSlashes.
399 */
400 $uattrib = $this->uattrib;
401 if($this->cyrusUseSlashes){
402 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
403 $acc_string = preg_replace('/([^\\\\])\./',"\\1/",$acc_string);
404 }
405 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
406 $acc_string = preg_replace("/\\\\([\.\/])/","\\1",$acc_string);
408 $domain = $mailpart = "";
409 $mail = $this->parent->mail;
410 if(preg_match("/\@/",$mail)){
411 list($mailpart,$domain) = split("\@",$mail);
412 }
414 /* Create account_id
415 */
416 $from = array("/%cn%/i","/%uid%/i","/%prefix%/i","/%uattrib%/i","/%domain%/i","/%mailpart%/i","/%mail%/i");
417 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
418 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
420 /* Check for not replaced pattern.
421 */
422 if(preg_match("/%/",$acc_id)){
423 $notr = preg_replace("/^[^%]*/","",$acc_id);
424 if(!empty($notr)){
425 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Warning</b>",
426 sprintf("<b>MAIL: WARNING unknown pattern in account creation string '%s' near '%s'</b>", $acc_id, $notr));
428 /* Remove incomprehensible patterns */
429 $acc_id = preg_replace("/%[^%]+%/","",$acc_id);
430 }
431 }
433 if(preg_match("/\@/",$acc_id)){
434 list($mail,$domain) = split("\@",$acc_id);
435 $str = trim($mail . $folder . "@" . $domain);
436 }else{
437 $str = trim($acc_id . $folder);
438 }
439 return($str) ;
440 }
443 /*! \brief Returns the configured mail method for the given parent object,
444 initialized and read for use.
445 @return mailMethod The configured mailMethod.
446 */
447 public function get_method()
448 {
449 $methods = mailMethod::get_methods();
450 if ($this->config->get_cfg_value("mailmethod") != ""){
451 $method= $this->config->get_cfg_value("mailmethod");
452 $cls = get_correct_class_name("mailMethod$method");
453 if(isset($methods[$cls])){
454 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> Selected mailMethod: <b>".$cls."</b>");
455 $tmp = new $cls($this->config,$this->parent,$this->type);
456 $tmp->init();
457 return($tmp);
458 }else{
459 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL: Invalid mailMethod defined: ".$cls.
460 " falling back to ".get_class($this)."</b>");
462 /* Print out configuration errors directly, we can't catch them everywhere.
463 */
464 msg_dialog::display(_("Configuration error"),
465 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
466 }
467 }
469 /* If no valued mailMethod could be detected, return the base class.
470 */
471 $this->init();
472 return($this);
473 }
476 /*! \brief Saves sieve settings
477 */
478 public function saveSieveSettings()
479 {
480 $this->reset_error();
481 return(TRUE);
482 }
485 /*! \brief Creates or Updates the mailAccount represented by this class.
486 */
487 public function updateMailbox()
488 {
489 $this->reset_error();
490 return(TRUE);
491 }
494 /*! \brief Update shared folder dependencies
495 */
496 public function updateSharedFolder()
497 {
498 $this->reset_error();
499 return(TRUE);
500 }
503 /*! \brief Removes the mailbox represented by this class,
504 and update shared folder ACLs .
505 */
506 public function deleteMailbox()
507 {
508 $this->reset_error();
510 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
511 "<b>MAIL: Remove account</b> from server :".$this->MailServer);
513 return(TRUE);
514 }
517 /*! \brief Returns the used mail attribute (mail,uid)
518 @param String One out of 'mail','uid'
519 */
520 public function getUAttrib()
521 {
522 return($this->uattrib);
523 }
526 /*! \brief Returns the used mail attribute (mail,uid)
527 @param String One out of 'mail','uid'
528 */
529 public function getUAttribValue()
530 {
531 $uattrib = $this->getUAttrib();
532 return($this->parent->$uattrib);
533 }
536 /*! \brief Returns whether the quota settings are enabled or not
537 @return Boolean TRUE if enabled else FALSE
538 */
539 public function quotaEnabled()
540 {
541 return($this->enableQuota);
542 }
545 /*! \brief Returns the used quota
546 @return Integer Quota used.
547 */
548 public function getQuotaUsage()
549 {
550 return(-1);
551 }
554 /*! \brief Returns the quota restrictions.
555 @return Integer Quota restrictions.
556 */
557 public function getQuota($quotaValue)
558 {
559 return($quotaValue);
560 }
563 /*! \brief Sets the mail quota
564 */
565 public function setQuota($number)
566 {
567 if(!is_numeric($number)){
568 $number = (int) $number;
569 if(!$number){
570 $number = 0;
571 }
572 }
573 $this->quotaValue = $number;
574 return(TRUE);
575 }
578 /*! \brief Returns true whether the domain is selectable or not
579 */
580 public function domainSelectionEnabled()
581 {
582 return($this->enableDomainSelection);
583 }
586 /*! \brief Returns a list of configured mail domains
587 @return Array A list of mail domains
588 */
589 public function getMailDomains()
590 {
591 return(array("Unconfigured"));
592 }
595 /*! \brief Returns the used Spamlevels for this mailmethod
596 */
597 public function getSpamLevels()
598 {
599 $spamlevel= array();
600 for ($i= 0; $i<21; $i++){
601 $spamlevel[]= $i;
602 }
603 return($spamlevel);
604 }
607 /*! \brief Returns the list of configured mailbox folders
608 @return Array The mailbox folders.
609 */
610 public function getMailboxList()
611 {
612 return(array("INBOX"));
613 }
616 /*! \brief Returns whether the vacation range is selectable or not
617 @return Boolean TRUE, FALSE
618 */
619 public function vacationRangeEnabled()
620 {
621 return($this->enableVacationRange);
622 }
625 /*! \brief Returns true if the sieveManagement is allowed
626 @return Boolean TRUE, FALSE
627 */
628 public function allowSieveManagement()
629 {
630 return($this->enableSieveManager);
631 }
634 /*! \brief Checks dependencies to other GOsa plugins.
635 */
636 public function accountCreateable(&$reason = ""){
637 return(TRUE);
638 }
641 /*! \brief Checks whether this account is removeable or not.
642 There may be some dependencies left, eg. kolab.
643 */
644 public function accountRemoveable(&$reason = ""){
645 return(TRUE);
646 }
649 /*! \brief Returns all mail servers configured in GOsa
650 that are useable with this mailMethod.
651 @return Array All useable mail servers.
652 */
653 public function getMailServers()
654 {
655 $mailserver = array();
656 $ui = get_userinfo();
657 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
658 if( $this->MailServer == $key ||
659 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
660 $mailserver[]= $key;
661 }
662 }
663 return($mailserver);
664 }
667 /*! \brief Returns the available mailMethods
668 @return Array A list of all avaialable mailMethods_
669 */
670 static protected function get_methods()
671 {
672 global $class_mapping;
673 $available = array();
674 foreach($class_mapping as $class => $path){
675 if($class == "mailMethod") continue;
676 if(preg_match("/^mailMethod/",$class)){
677 $available[$class] = $class;
678 }
679 }
680 return($available);
681 }
684 /* \brief Some method require special folder types, "kolab" for example.
685 !! Those values are dummy values, the base class doesn't use folder types;
686 @return Array Return folder types.
687 */
688 public function getAvailableFolderTypes()
689 {
690 $ret = array();
691 $ret['CAT'][''] = _("None");
692 $ret['SUB_CAT'][''][''] = _("None");
693 return($ret);
694 }
697 /* \brief Returns the selected folder type.
698 !! Those values are dummy values, the base class doesn't use folder types;
699 @return Array The folde type.
700 */
701 public function getFolderType($default)
702 {
703 return($default);
704 }
707 /* \brief Returns the selected folder type.
708 !! Those values are dummy values, the base class doesn't use folder types;
709 @return Array The folde type.
710 */
711 public function setFolderType($type)
712 {
713 return(TRUE) ;
714 }
717 /*! \brief Returns configured acls
718 */
719 public function getFolderACLs($folder_acls)
720 {
721 /* Merge given ACL with acl mapping
722 This ensures that no ACL will accidentally overwritten by gosa.
723 */
724 foreach($folder_acls as $user => $acl){
725 if(!isset($this->acl_mapping[$acl])){
726 $this->acl_mapping[$acl] = $acl;
727 }
728 }
730 return($folder_acls);
731 }
734 /*! \brief Write ACLs back to imap or what ever
735 */
736 public function setFolderACLs($array)
737 {
738 return(TRUE);
739 }
742 /*! \brief Returns a list of all possible acls.
743 @return Array ACLs.
744 */
745 public function getAclTypes()
746 {
747 return( $this->acl_mapping);
748 }
750 public function folderTypesEnabled()
751 {
752 return($this->enableFolderTypes);
753 }
755 public function allow_remove(&$reason)
756 {
757 return(TRUE);
758 }
761 /*! \brief Returns the configured mailMethod
762 @return String the configured mail method or ""
763 */
764 static public function get_current_method($config)
765 {
766 global $class_mapping;
767 $method= $config->get_cfg_value("mailmethod");
768 $cls = get_correct_class_name("mailMethod$method");
769 foreach($class_mapping as $class => $path){
770 if($class == $cls){
771 return($class);
772 }
773 }
774 return("");
775 }
778 static function quota_to_image($use,$quota)
779 {
780 if($use == -1){
781 return(" "._("Unknown"));
782 }elseif(empty($quota)){
783 return(" "._("Unlimited"));
784 }else{
785 $usage =round(($use/$quota) * 100);
786 return("<img src='progress.php?x=100&y=17&p=$usage'>");
787 }
788 }
791 /*! \brief Returns the default sharedFolder ACLs for this method.
792 @return Array Returns an array containg acls for __member__ and __anyone__
793 */
794 public function getDefaultACLs()
795 {
796 $tmp = $this->default_acls;
797 if(!isset($tmp['__member__'])) $tmp['__member__'] = " ";
798 if(!isset($tmp['__anyone__'])) $tmp['__anyone__'] = " ";
799 return($tmp);
800 }
801 }
804 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
805 ?>