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 */
23 protected $user_id = "__PREFIX____UATTRIB__";
24 protected $share_id = "__PREFIX____UATTRIB__";
26 /* Create accounts in cyrus style with '/' instead of '.' */
27 protected $cyrusUseSlashes= FALSE;
29 /* The atribute mapping for this class Source --> Destination */
30 protected $attributes = array();
31 protected $userObjectClasses = array();
32 protected $shareObjectClasses = array();
34 /* Enabled mail domain selection. If enabled getMailDomains must the domain parts */
35 protected $enableDomainSelection= FALSE;
36 protected $enableQuota = TRUE;
37 protected $enableSieveManager = FALSE;
38 protected $enableVacationRange = TRUE;
39 protected $enableFolderTypes = FALSE;
41 /* Default values */
42 protected $quotaValue = 0;
43 protected $quotaUsage = 0;
45 /* Method internal */
46 protected $type = "user";
47 protected $account_id = "";
48 protected $initial_account_id = "";
49 protected $connected = FALSE;
50 protected $error = "";
51 protected $parent = NULL;
52 protected $MailServer = "";
54 protected $acl_map = array(
55 "lrsw" => "read",
56 "lrswp" => "post",
57 "p" => "external post",
58 "lrswip" => "append",
59 "lrswipcd" => "write",
60 "lrswipcda"=> "admin",
61 " " => "none");
63 protected $acl_mapping = array();
66 /*! \brief Constructs the mail class
67 @param Object Config The GOsa configuration object
68 @param Object Plugin The initator
69 @param String Open "user" or "group" account.
70 */
71 function __construct(&$config, &$parent, $type = "user")
72 {
73 $this->parent = $parent;
74 $this->config = $config;
76 /* Create a refernce to the mail selected server
77 */
78 if(isset($this->parent->gosaMailServer)){
79 $this->MailServer = &$this->parent->gosaMailServer;
80 }else{
81 trigger_error("mailMethod with invalid parent object initialized.");
82 }
84 if(!in_array($this->type,array("user","group"))){
85 trigger_error("Unknown mail class type used '".$type."'.");
86 }else{
87 $this->type = $type;
88 }
89 }
92 /*! \brief Intialize attributes and config settings.
93 */
94 protected function init()
95 {
96 /* Get config value for cyrusUseSlashes
97 */
98 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
99 $this->cyrusUseSlashes = TRUE;
100 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Enabled</b>");
101 }else{
102 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Disabled</b>");
103 }
105 /* Check if the mail account identification attribute
106 is overridden in the configuration file
107 */
108 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
109 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
110 if(in_array($new_uattrib,array("mail","uid"))){
111 $this->uattrib = $new_uattrib;
112 }else{
113 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
114 "<b>MAIL:</b> Unsupported 'mailAttribute' in gosa configuration specified");
115 msg_dialog::display(_("Configuration error"),
116 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
117 }
118 }
120 /* Create ACL map */
121 foreach($this->acl_map as $acl => $name){
122 $this->acl_mapping[$acl] = _($name);
123 }
125 $this->build_account_id();
126 $this->initial_account_id = $this->account_id;
127 }
130 public function fixAttributesOnLoad()
131 {
132 foreach($this->attributes as $source => $dest){
133 if(isset($this->parent->attrs[$source])){
134 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
135 }
136 if(isset($this->parent->$source)){
137 $this->parent->$dest = $this->parent->$source;
138 }
139 if(isset($this->parent->attrs[$source][0])){
140 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
141 }
142 }
143 }
146 public function mailEqualsCN()
147 {
148 return($this->mailEqualsCN);
149 }
152 public function fixAttributesOnRemove()
153 {
154 /* Remove objectClasses
155 */
156 if($this->type == "user"){
157 $this->parent->attrs['objectClass'] =
158 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
159 }else{
160 $this->parent->attrs['objectClass'] =
161 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
162 }
163 foreach($this->attributes as $source => $dest){
164 $this->attrs[$dest] = array();
165 $this->attrs[$source] = array();
166 }
167 }
169 public function fixAttributesOnStore()
170 {
171 foreach($this->attributes as $source => $dest){
172 if(isset($this->parent->attrs[$dest])){
173 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
174 }
175 if(isset($this->parent->$dest)){
176 $this->parent->$source = $this->parent->$dest;
177 }
178 }
180 if($this->type == "user"){
181 $ocs = $this->userObjectClasses;
182 }else{
183 $ocs = $this->shareObjectClasses;
184 }
185 foreach($ocs as $oc){
186 if(!in_array($oc, $this->parent->attrs['objectClass'])){
187 $this->parent->attrs['objectClass'][] = $oc;
188 }
189 }
190 }
193 /*! \brief Connect services like imap.
194 Not necessary for the base class.
195 @return Boolean True if this method is connected else false.
196 */
197 public function connect()
198 {
199 $this->reset_error();
200 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Connect method</b>: ".get_class($this));
201 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Current server</b>: ".$this->MailServer);
203 $this->connected = TRUE;
204 return(TRUE);
205 }
208 /*! \brief Returns the connection status of this method.
209 @return Boolean True if this method is connected else false.
210 */
211 public function is_connected()
212 {
213 return($this->connected);
214 }
217 /*! \brief Disconnect this method. Close services like imap connection.
218 Not necessary for the base class.
219 */
220 public function disconnect()
221 {
222 $this->reset_error();
223 if($this->is_connected()){
224 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Disconnect method</b>: ".get_class($this));
225 $this->connected =FALSE;
226 }
227 }
230 /*! \brief Returns true the current object represents a valid account
231 (Some methods may check imap accounts here.)
232 @return Boolean TRUE if this is a valid account else FALSE
233 */
234 public function account_exists()
235 {
236 $this->reset_error();
237 return(TRUE);
238 }
241 /*! \brief Returns the last error occurred
242 @return String The last error message.
243 */
244 public function get_error(){
245 return($this->error);
246 }
249 public function isModifyableMail()
250 {
251 return($this->modifyableMail);
252 }
255 public function isModifyableServer()
256 {
257 return($this->modifyableServer);
258 }
261 /*! \brief Returns TRUE if the action caused an error.
262 @return Boolean TRUE on error else FALSE
263 */
264 public function is_error(){
265 return($this->error != "");
266 }
269 /*! \brief Resets the error message.
270 */
271 public function reset_error(){
272 $this->error = "";
273 }
276 public function get_account_id()
277 {
278 $this->build_account_id();
279 return($this->account_id);
280 }
282 /*! \brief Create a new account id, like 'user/name@domain.com'.
283 */
284 protected function build_account_id()
285 {
286 /* Build account identicator */
287 if($this->type == "user"){
288 $prefix = $this->user_prefix;
289 $acc_string = $this->user_id;
290 }else{
291 $prefix = $this->share_prefix;
292 $acc_string = $this->share_id;
293 }
295 /* Create account prefix and respect "cyrusUseSlashes"
296 Do not replace escaped dots for cyrusUseSlashes.
297 */
298 $uattrib = $this->uattrib;
299 if($this->cyrusUseSlashes){
300 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
301 }
302 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
304 $domain = $mailpart = "";
305 if(preg_match("/\@/",$this->parent->$uattrib)){
306 $mailpart = preg_replace("/\@.*$/","",$this->parent->$uattrib);
307 $domain = preg_replace("/^[^\@]*+\@(.*)$/","\\1",$this->parent->$uattrib);
308 }
310 /* Create account_id
311 */
312 $from = array("/__CN__/","/__UID__/","/__PREFIX__/","/__UATTRIB__/","/__DOMAIN__/","/__MAILPART__/");
313 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart);
315 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
317 if($this->account_id != $acc_id){
318 $this->account_id = $acc_id;
319 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> AccountID generated: <b>".$acc_id."</b>");
320 }
321 }
324 /*! \brief Creates a valid folder id for a given folder name.
325 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
326 will result in "share/mailbox/test@domain.de"
327 This function is mainly used to read and write folder permissions.
328 @return String A valid folder id
329 */
330 public function create_folder_id($folder, $type = "")
331 {
333 if(!empty($folder)){
334 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
335 }
336 if(!empty($folder)){
337 $folder = "/".$folder;
338 }
340 /* Build account identicator */
341 if($this->type == "user"){
342 $prefix = $this->user_prefix;
343 $acc_string = $this->user_id;
344 }else{
345 $prefix = $this->share_prefix;
346 $acc_string = $this->share_id;
347 }
349 /* Create account prefix and respect "cyrusUseSlashes"
350 Do not replace escaped dots for cyrusUseSlashes.
351 */
352 $uattrib = $this->uattrib;
353 if($this->cyrusUseSlashes){
354 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
355 }
356 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
358 $domain = $mailpart = "";
359 if(preg_match("/\@/",$this->parent->$uattrib)){
360 list($mailpart,$domain) = split("\@",$this->parent->$uattrib);
361 }
363 /* Create account_id
364 */
365 $from = array("/__CN__/","/__UID__/","/__PREFIX__/","/__UATTRIB__/","/__DOMAIN__/","/__MAILPART__/");
366 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart);
368 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
370 if(preg_match("/\@/",$acc_id)){
371 list($mail,$domain) = split("\@",$acc_id);
372 $str = trim(strtolower($mail . $folder . "@" . $domain));
373 }else{
374 $str = trim(strtolower($acc_id . $folder));
375 }
376 return($str) ;
377 }
380 /*! \brief Returns the configured mail method for the given parent object,
381 initialized and read for use.
382 @return mailMethod The configured mailMethod.
383 */
384 public function get_method()
385 {
386 $methods = mailMethod::get_methods();
387 if ($this->config->get_cfg_value("mailmethod") != ""){
388 $method= $this->config->get_cfg_value("mailmethod");
389 $cls = get_correct_class_name("mailMethod$method");
390 if(isset($methods[$cls])){
391 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> Selected mailMethod: <b>".$cls."</b>");
392 $tmp = new $cls($this->config,$this->parent,$this->type);
393 $tmp->init();
394 return($tmp);
395 }else{
396 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL: Invalid mailMethod defined: <b>".$cls.
397 "</b> falling back to <b>".get_class($this)."</b>");
399 /* Print out configuration errors directly, we can't catch them everywhere.
400 */
401 msg_dialog::display(_("Configuration error"),
402 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
403 }
404 }
406 /* If no valued mailMethod could be detected, return the base class.
407 */
408 $this->init();
409 return($this);
410 }
413 /*! \brief Saves sieve settings
414 */
415 public function saveSieveSettings()
416 {
417 $this->reset_error();
418 return(TRUE);
419 }
422 /*! \brief Creates or Updates the mailAccount represented by this class.
423 */
424 public function updateMailbox()
425 {
426 $this->reset_error();
427 return(TRUE);
428 }
431 /*! \brief Update shared folder dependencies
432 */
433 public function updateSharedFolder()
434 {
435 $this->reset_error();
436 return(TRUE);
437 }
440 /*! \brief Removes the mailbox represented by this class,
441 and update shared folder ACLs .
442 */
443 public function deleteMailbox()
444 {
445 $this->reset_error();
447 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
448 "<b>MAIL: Remove account</b> from server :".$this->MailServer);
450 return(TRUE);
451 }
454 /*! \brief Returns the used mail attribute (mail,uid)
455 @param String One out of 'mail','uid'
456 */
457 public function getUAttrib()
458 {
459 return($this->uattrib);
460 }
463 /*! \brief Returns the used mail attribute (mail,uid)
464 @param String One out of 'mail','uid'
465 */
466 public function getUAttribValue()
467 {
468 $uattrib = $this->getUAttrib();
469 return($this->parent->$uattrib);
470 }
473 /*! \brief Returns whether the quota settings are enabled or not
474 @return Boolean TRUE if enabled else FALSE
475 */
476 public function quotaEnabled()
477 {
478 return($this->enableQuota);
479 }
482 /*! \brief Returns the used quota
483 @return Integer Quota used.
484 */
485 public function getQuotaUsage()
486 {
487 return(-1);
488 }
491 /*! \brief Returns the quota restrictions.
492 @return Integer Quota restrictions.
493 */
494 public function getQuota($quotaValue)
495 {
496 return($quotaValue);
497 }
500 /*! \brief Sets the mail quota
501 */
502 public function setQuota($number)
503 {
504 if(!is_numeric($number)){
505 $number = (int) $number;
506 if(!$number){
507 $number = 0;
508 }
509 }
510 $this->quotaValue = $number;
511 return(TRUE);
512 }
515 /*! \brief Returns true whether the domain is selectable or not
516 */
517 public function domainSelectionEnabled()
518 {
519 return($this->enableDomainSelection);
520 }
523 /*! \brief Returns a list of configured mail domains
524 @return Array A list of mail domains
525 */
526 public function getMailDomains()
527 {
528 return(array("Unconfigured"));
529 }
532 /*! \brief Returns the used Spamlevels for this mailmethod
533 */
534 public function getSpamLevels()
535 {
536 $spamlevel= array();
537 for ($i= 0; $i<21; $i++){
538 $spamlevel[]= $i;
539 }
540 return($spamlevel);
541 }
544 /*! \brief Returns the list of configured mailbox folders
545 @return Array The mailbox folders.
546 */
547 public function getMailboxList()
548 {
549 return(array("INBOX"));
550 }
553 /*! \brief Returns whether the vacation range is selectable or not
554 @return Boolean TRUE, FALSE
555 */
556 public function vacationRangeEnabled()
557 {
558 return($this->enableVacationRange);
559 }
562 /*! \brief Returns true if the sieveManagement is allowed
563 @return Boolean TRUE, FALSE
564 */
565 public function allowSieveManagement()
566 {
567 return($this->enableSieveManager);
568 }
571 /*! \brief Checks dependencies to other GOsa plugins.
572 */
573 public function accountCreateable(&$reason = ""){
574 return(TRUE);
575 }
578 /*! \brief Checks whether this account is removeable or not.
579 There may be some dependencies left, eg. kolab.
580 */
581 public function accountRemoveable(&$reason = ""){
582 return(TRUE);
583 }
586 /*! \brief Returns all mail servers configured in GOsa
587 that are useable with this mailMethod.
588 @return Array All useable mail servers.
589 */
590 public function getMailServers()
591 {
592 $mailserver = array();
593 $ui = get_userinfo();
594 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
595 if( $this->MailServer == $key ||
596 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
597 $mailserver[]= $key;
598 }
599 }
600 return($mailserver);
601 }
604 /*! \brief Returns the available mailMethods
605 @return Array A list of all avaialable mailMethods_
606 */
607 static protected function get_methods()
608 {
609 global $class_mapping;
610 $available = array();
611 foreach($class_mapping as $class => $path){
612 if($class == "mailMethod") continue;
613 if(preg_match("/^mailMethod/",$class)){
614 $available[$class] = $class;
615 }
616 }
617 return($available);
618 }
621 /* \brief Some method require special folder types, "kolab" for example.
622 !! Those values are dummy values, the base class doesn't use folder types;
623 @return Array Return folder types.
624 */
625 public function getAvailableFolderTypes()
626 {
627 $ret = array();
628 $ret['CAT'][''] = _("None");
629 $ret['SUB_CAT'][''][''] = _("None");
630 return($ret);
631 }
634 /* \brief Returns the selected folder type.
635 !! Those values are dummy values, the base class doesn't use folder types;
636 @return Array The folde type.
637 */
638 public function getFolderType($default)
639 {
640 return($default);
641 }
644 /* \brief Returns the selected folder type.
645 !! Those values are dummy values, the base class doesn't use folder types;
646 @return Array The folde type.
647 */
648 public function setFolderType($type)
649 {
650 return(TRUE) ;
651 }
654 /*! \brief Returns configured acls
655 */
656 public function getFolderACLs($folder_acls)
657 {
658 /* Merge given ACL with acl mapping
659 This ensures that no ACL will accidentally overwritten by gosa.
660 */
661 foreach($folder_acls as $user => $acl){
662 if(!isset($this->acl_mapping[$acl])){
663 $this->acl_mapping[$acl] = $acl;
664 }
665 }
667 return($folder_acls);
668 }
671 /*! \brief Write ACLs back to imap or what ever
672 */
673 public function setFolderACLs($array)
674 {
675 return(TRUE);
676 }
679 /*! \brief Returns a list of all possible acls.
680 @return Array ACLs.
681 */
682 public function getAclTypes()
683 {
684 return( $this->acl_mapping);
685 }
687 public function folderTypesEnabled()
688 {
689 return($this->enableFolderTypes);
690 }
692 public function allow_remove(&$reason)
693 {
694 return(TRUE);
695 }
698 /*! \brief Returns the configured mailMethod
699 @return String the configured mail method or ""
700 */
701 static public function get_current_method($config)
702 {
703 global $class_mapping;
704 $method= $config->get_cfg_value("mailmethod");
705 $cls = get_correct_class_name("mailMethod$method");
706 foreach($class_mapping as $class => $path){
707 if($class == $cls){
708 return($class);
709 }
710 }
711 return("");
712 }
714 }
717 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
718 ?>