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 $acl_map = array(
68 "lrsw" => "read",
69 "lrswp" => "post",
70 "p" => "external post",
71 "lrswip" => "append",
72 "lrswipcd" => "write",
73 "lrswipcda"=> "admin",
74 " " => "none");
76 protected $acl_mapping = array();
79 /*! \brief Constructs the mail class
80 @param Object Config The GOsa configuration object
81 @param Object Plugin The initator
82 @param String Open "user" or "group" account.
83 */
84 function __construct(&$config, &$parent, $type = "user")
85 {
86 $this->parent = $parent;
87 $this->config = $config;
89 /* Create a refernce to the mail selected server
90 */
91 if(isset($this->parent->gosaMailServer)){
92 $this->MailServer = &$this->parent->gosaMailServer;
93 }else{
94 trigger_error("mailMethod with invalid parent object initialized.");
95 }
97 if(!in_array($this->type,array("user","group"))){
98 trigger_error("Unknown mail class type used '".$type."'.");
99 }else{
100 $this->type = $type;
101 }
102 }
105 /*! \brief Intialize attributes and config settings.
106 */
107 protected function init()
108 {
109 /* Get config value for cyrusUseSlashes
110 */
111 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
112 $this->cyrusUseSlashes = TRUE;
113 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Enabled</b>");
114 }else{
115 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Disabled</b>");
116 }
118 /* Check if the mail account identification attribute
119 is overridden in the configuration file
120 */
121 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
122 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
123 if(in_array($new_uattrib,array("mail","uid"))){
124 $this->uattrib = $new_uattrib;
125 }else{
126 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
127 "<b>MAIL:</b> Unsupported 'mailAttribute' in gosa configuration specified");
128 msg_dialog::display(_("Configuration error"),
129 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
130 }
131 }
133 /* Create ACL map */
134 foreach($this->acl_map as $acl => $name){
135 $this->acl_mapping[$acl] = _($name);
136 }
138 $this->build_account_id();
139 $this->initial_account_id = $this->account_id;
140 }
143 public function fixAttributesOnLoad()
144 {
145 foreach($this->attributes as $source => $dest){
146 if(isset($this->parent->attrs[$source])){
147 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
148 }
149 if(isset($this->parent->$source)){
150 $this->parent->$dest = $this->parent->$source;
151 }
152 if(isset($this->parent->attrs[$source][0])){
153 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
154 }
155 }
156 }
159 public function mailEqualsCN()
160 {
161 return($this->mailEqualsCN);
162 }
165 public function fixAttributesOnRemove()
166 {
167 /* Remove objectClasses
168 */
169 if($this->type == "user"){
170 $this->parent->attrs['objectClass'] =
171 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
172 }else{
173 $this->parent->attrs['objectClass'] =
174 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
175 }
176 foreach($this->attributes as $source => $dest){
177 $this->attrs[$dest] = array();
178 $this->attrs[$source] = array();
179 }
180 }
182 public function fixAttributesOnStore()
183 {
184 foreach($this->attributes as $source => $dest){
185 if(isset($this->parent->attrs[$dest])){
186 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
187 }
188 if(isset($this->parent->$dest)){
189 $this->parent->$source = $this->parent->$dest;
190 }
191 }
193 if($this->type == "user"){
194 $ocs = $this->userObjectClasses;
195 }else{
196 $ocs = $this->shareObjectClasses;
197 }
198 foreach($ocs as $oc){
199 if(!in_array($oc, $this->parent->attrs['objectClass'])){
200 $this->parent->attrs['objectClass'][] = $oc;
201 }
202 }
203 }
206 /*! \brief Connect services like imap.
207 Not necessary for the base class.
208 @return Boolean True if this method is connected else false.
209 */
210 public function connect()
211 {
212 $this->reset_error();
213 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Connect method</b>: ".get_class($this));
214 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Current server</b>: ".$this->MailServer);
216 $this->connected = TRUE;
217 return(TRUE);
218 }
221 /*! \brief Returns the connection status of this method.
222 @return Boolean True if this method is connected else false.
223 */
224 public function is_connected()
225 {
226 return($this->connected);
227 }
230 /*! \brief Disconnect this method. Close services like imap connection.
231 Not necessary for the base class.
232 */
233 public function disconnect()
234 {
235 $this->reset_error();
236 if($this->is_connected()){
237 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Disconnect method</b>: ".get_class($this));
238 $this->connected =FALSE;
239 }
240 }
243 /*! \brief Returns true the current object represents a valid account
244 (Some methods may check imap accounts here.)
245 @return Boolean TRUE if this is a valid account else FALSE
246 */
247 public function account_exists()
248 {
249 $this->reset_error();
250 return(TRUE);
251 }
254 /*! \brief Returns the last error occurred
255 @return String The last error message.
256 */
257 public function get_error(){
258 return($this->error);
259 }
262 public function isModifyableMail()
263 {
264 return($this->modifyableMail);
265 }
268 public function isModifyableServer()
269 {
270 return($this->modifyableServer);
271 }
274 /*! \brief Returns TRUE if the action caused an error.
275 @return Boolean TRUE on error else FALSE
276 */
277 public function is_error(){
278 return($this->error != "");
279 }
282 /*! \brief Resets the error message.
283 */
284 public function reset_error(){
285 $this->error = "";
286 }
289 public function get_account_id()
290 {
291 $this->build_account_id();
292 return($this->account_id);
293 }
295 /*! \brief Create a new account id, like 'user/name@domain.com'.
296 */
297 protected function build_account_id()
298 {
299 /* Build account identicator */
300 if($this->type == "user"){
301 $prefix = $this->user_prefix;
302 $acc_string = $this->user_id;
303 }else{
304 $prefix = $this->share_prefix;
305 $acc_string = $this->share_id;
306 }
308 /* Create account prefix and respect "cyrusUseSlashes"
309 Do not replace escaped dots for cyrusUseSlashes.
310 */
311 $uattrib = $this->uattrib;
312 if($this->cyrusUseSlashes){
313 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
314 }
315 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
317 $domain = $mailpart = "";
318 $mail = $this->parent->mail;
319 if(preg_match("/\@/",$mail)){
320 list($mailpart,$domain) = split("\@",$mail);
321 }
323 /* Create account_id
324 */
325 $from = array("/__CN__/","/__UID__/","/__PREFIX__/","/__UATTRIB__/","/__DOMAIN__/","/__MAILPART__/","/__MAIL__/");
326 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
328 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
330 if($this->account_id != $acc_id){
331 $this->account_id = $acc_id;
332 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> AccountID generated: <b>".$acc_id."</b>");
333 }
334 }
337 /*! \brief Creates a valid folder id for a given folder name.
338 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
339 will result in "share/mailbox/test@domain.de"
340 This function is mainly used to read and write folder permissions.
341 @return String A valid folder id
342 */
343 public function create_folder_id($folder, $type = "")
344 {
346 if(!empty($folder)){
347 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
348 }
349 if(!empty($folder)){
350 $folder = "/".$folder;
351 }
353 /* Build account identicator */
354 if($this->type == "user"){
355 $prefix = $this->user_prefix;
356 $acc_string = $this->user_id;
357 }else{
358 $prefix = $this->share_prefix;
359 $acc_string = $this->share_id;
360 }
362 /* Create account prefix and respect "cyrusUseSlashes"
363 Do not replace escaped dots for cyrusUseSlashes.
364 */
365 $uattrib = $this->uattrib;
366 if($this->cyrusUseSlashes){
367 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
368 }
369 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
371 $domain = $mailpart = "";
372 $mail = $this->parent->mail;
373 if(preg_match("/\@/",$mail)){
374 list($mailpart,$domain) = split("\@",$mail);
375 }
377 /* Create account_id
378 */
379 $from = array("/__CN__/","/__UID__/","/__PREFIX__/","/__UATTRIB__/","/__DOMAIN__/","/__MAILPART__/","/__MAIL__/");
380 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
382 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
384 if(preg_match("/\@/",$acc_id)){
385 list($mail,$domain) = split("\@",$acc_id);
386 $str = trim($mail . $folder . "@" . $domain);
387 }else{
388 $str = trim($acc_id . $folder);
389 }
390 return($str) ;
391 }
394 /*! \brief Returns the configured mail method for the given parent object,
395 initialized and read for use.
396 @return mailMethod The configured mailMethod.
397 */
398 public function get_method()
399 {
400 $methods = mailMethod::get_methods();
401 if ($this->config->get_cfg_value("mailmethod") != ""){
402 $method= $this->config->get_cfg_value("mailmethod");
403 $cls = get_correct_class_name("mailMethod$method");
404 if(isset($methods[$cls])){
405 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> Selected mailMethod: <b>".$cls."</b>");
406 $tmp = new $cls($this->config,$this->parent,$this->type);
407 $tmp->init();
408 return($tmp);
409 }else{
410 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL: Invalid mailMethod defined: <b>".$cls.
411 "</b> falling back to <b>".get_class($this)."</b>");
413 /* Print out configuration errors directly, we can't catch them everywhere.
414 */
415 msg_dialog::display(_("Configuration error"),
416 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
417 }
418 }
420 /* If no valued mailMethod could be detected, return the base class.
421 */
422 $this->init();
423 return($this);
424 }
427 /*! \brief Saves sieve settings
428 */
429 public function saveSieveSettings()
430 {
431 $this->reset_error();
432 return(TRUE);
433 }
436 /*! \brief Creates or Updates the mailAccount represented by this class.
437 */
438 public function updateMailbox()
439 {
440 $this->reset_error();
441 return(TRUE);
442 }
445 /*! \brief Update shared folder dependencies
446 */
447 public function updateSharedFolder()
448 {
449 $this->reset_error();
450 return(TRUE);
451 }
454 /*! \brief Removes the mailbox represented by this class,
455 and update shared folder ACLs .
456 */
457 public function deleteMailbox()
458 {
459 $this->reset_error();
461 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
462 "<b>MAIL: Remove account</b> from server :".$this->MailServer);
464 return(TRUE);
465 }
468 /*! \brief Returns the used mail attribute (mail,uid)
469 @param String One out of 'mail','uid'
470 */
471 public function getUAttrib()
472 {
473 return($this->uattrib);
474 }
477 /*! \brief Returns the used mail attribute (mail,uid)
478 @param String One out of 'mail','uid'
479 */
480 public function getUAttribValue()
481 {
482 $uattrib = $this->getUAttrib();
483 return($this->parent->$uattrib);
484 }
487 /*! \brief Returns whether the quota settings are enabled or not
488 @return Boolean TRUE if enabled else FALSE
489 */
490 public function quotaEnabled()
491 {
492 return($this->enableQuota);
493 }
496 /*! \brief Returns the used quota
497 @return Integer Quota used.
498 */
499 public function getQuotaUsage()
500 {
501 return(-1);
502 }
505 /*! \brief Returns the quota restrictions.
506 @return Integer Quota restrictions.
507 */
508 public function getQuota($quotaValue)
509 {
510 return($quotaValue);
511 }
514 /*! \brief Sets the mail quota
515 */
516 public function setQuota($number)
517 {
518 if(!is_numeric($number)){
519 $number = (int) $number;
520 if(!$number){
521 $number = 0;
522 }
523 }
524 $this->quotaValue = $number;
525 return(TRUE);
526 }
529 /*! \brief Returns true whether the domain is selectable or not
530 */
531 public function domainSelectionEnabled()
532 {
533 return($this->enableDomainSelection);
534 }
537 /*! \brief Returns a list of configured mail domains
538 @return Array A list of mail domains
539 */
540 public function getMailDomains()
541 {
542 return(array("Unconfigured"));
543 }
546 /*! \brief Returns the used Spamlevels for this mailmethod
547 */
548 public function getSpamLevels()
549 {
550 $spamlevel= array();
551 for ($i= 0; $i<21; $i++){
552 $spamlevel[]= $i;
553 }
554 return($spamlevel);
555 }
558 /*! \brief Returns the list of configured mailbox folders
559 @return Array The mailbox folders.
560 */
561 public function getMailboxList()
562 {
563 return(array("INBOX"));
564 }
567 /*! \brief Returns whether the vacation range is selectable or not
568 @return Boolean TRUE, FALSE
569 */
570 public function vacationRangeEnabled()
571 {
572 return($this->enableVacationRange);
573 }
576 /*! \brief Returns true if the sieveManagement is allowed
577 @return Boolean TRUE, FALSE
578 */
579 public function allowSieveManagement()
580 {
581 return($this->enableSieveManager);
582 }
585 /*! \brief Checks dependencies to other GOsa plugins.
586 */
587 public function accountCreateable(&$reason = ""){
588 return(TRUE);
589 }
592 /*! \brief Checks whether this account is removeable or not.
593 There may be some dependencies left, eg. kolab.
594 */
595 public function accountRemoveable(&$reason = ""){
596 return(TRUE);
597 }
600 /*! \brief Returns all mail servers configured in GOsa
601 that are useable with this mailMethod.
602 @return Array All useable mail servers.
603 */
604 public function getMailServers()
605 {
606 $mailserver = array();
607 $ui = get_userinfo();
608 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
609 if( $this->MailServer == $key ||
610 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
611 $mailserver[]= $key;
612 }
613 }
614 return($mailserver);
615 }
618 /*! \brief Returns the available mailMethods
619 @return Array A list of all avaialable mailMethods_
620 */
621 static protected function get_methods()
622 {
623 global $class_mapping;
624 $available = array();
625 foreach($class_mapping as $class => $path){
626 if($class == "mailMethod") continue;
627 if(preg_match("/^mailMethod/",$class)){
628 $available[$class] = $class;
629 }
630 }
631 return($available);
632 }
635 /* \brief Some method require special folder types, "kolab" for example.
636 !! Those values are dummy values, the base class doesn't use folder types;
637 @return Array Return folder types.
638 */
639 public function getAvailableFolderTypes()
640 {
641 $ret = array();
642 $ret['CAT'][''] = _("None");
643 $ret['SUB_CAT'][''][''] = _("None");
644 return($ret);
645 }
648 /* \brief Returns the selected folder type.
649 !! Those values are dummy values, the base class doesn't use folder types;
650 @return Array The folde type.
651 */
652 public function getFolderType($default)
653 {
654 return($default);
655 }
658 /* \brief Returns the selected folder type.
659 !! Those values are dummy values, the base class doesn't use folder types;
660 @return Array The folde type.
661 */
662 public function setFolderType($type)
663 {
664 return(TRUE) ;
665 }
668 /*! \brief Returns configured acls
669 */
670 public function getFolderACLs($folder_acls)
671 {
672 /* Merge given ACL with acl mapping
673 This ensures that no ACL will accidentally overwritten by gosa.
674 */
675 foreach($folder_acls as $user => $acl){
676 if(!isset($this->acl_mapping[$acl])){
677 $this->acl_mapping[$acl] = $acl;
678 }
679 }
681 return($folder_acls);
682 }
685 /*! \brief Write ACLs back to imap or what ever
686 */
687 public function setFolderACLs($array)
688 {
689 return(TRUE);
690 }
693 /*! \brief Returns a list of all possible acls.
694 @return Array ACLs.
695 */
696 public function getAclTypes()
697 {
698 return( $this->acl_mapping);
699 }
701 public function folderTypesEnabled()
702 {
703 return($this->enableFolderTypes);
704 }
706 public function allow_remove(&$reason)
707 {
708 return(TRUE);
709 }
712 /*! \brief Returns the configured mailMethod
713 @return String the configured mail method or ""
714 */
715 static public function get_current_method($config)
716 {
717 global $class_mapping;
718 $method= $config->get_cfg_value("mailmethod");
719 $cls = get_correct_class_name("mailMethod$method");
720 foreach($class_mapping as $class => $path){
721 if($class == $cls){
722 return($class);
723 }
724 }
725 return("");
726 }
729 static function quota_to_image($use,$quota)
730 {
731 if($use == -1){
732 return(" "._("Unknown"));
733 }elseif(empty($quota)){
734 return(" "._("Unlimited"));
735 }else{
736 $usage =(int) ($use/$quota) * 100;
737 return("<img src='progress.php?x=100&y=17&p=$usage'>");
738 }
739 }
740 }
743 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
744 ?>