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 = "";
47 protected $acl_map = array(
48 "lrsw" => "read",
49 "lrswp" => "post",
50 "p" => "external post",
51 "lrswip" => "append",
52 "lrswipcd" => "write",
53 "lrswipcda"=> "admin",
54 " " => "none");
56 protected $acl_mapping = array();
59 /*! \brief Constructs the mail class
60 @param Object Config The GOsa configuration object
61 @param Object Plugin The initator
62 @param String Open "user" or "group" account.
63 */
64 function __construct(&$config, &$parent, $type = "user")
65 {
66 $this->parent = $parent;
67 $this->config = $config;
69 /* Create a refernce to the mail selected server
70 */
71 if(isset($this->parent->gosaMailServer)){
72 $this->MailServer = &$this->parent->gosaMailServer;
73 }else{
74 trigger_error("mailMethod with invalid parent object initialized.");
75 }
77 if(!in_array($this->type,array("user","group"))){
78 trigger_error("Unknown mail class type used '".$type."'.");
79 }else{
80 $this->type = $type;
81 }
82 }
85 /*! \brief Intialize attributes and config settings.
86 */
87 protected function init()
88 {
89 /* Get config value for cyrusUseSlashes
90 */
91 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
92 $this->cyrusUseSlashes = TRUE;
93 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "cyrusUseSlashes: <b>Enabled</b>","");
94 }else{
95 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "cyrusUseSlashes: <b>Disabled</b>","");
96 }
98 /* Check if the mail account identification attribute
99 is overridden in the configuration file
100 */
101 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
102 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
103 if(in_array($new_uattrib,array("mail","uid"))){
104 $this->uattrib = $new_uattrib;
105 }else{
106 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
107 "Unsupported 'mailAttribute' in gosa configuration specified");
108 msg_dialog::display(_("Configuration error"),
109 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
110 }
111 }
113 /* Create ACL map */
114 foreach($this->acl_map as $acl => $name){
115 $this->acl_mapping[$acl] = _($name);
116 }
118 $this->build_account_id();
119 $this->initial_account_id = $this->account_id;
120 }
123 public function fixAttributesOnLoad()
124 {
125 foreach($this->attributes as $source => $dest){
126 if(isset($this->parent->attrs[$source])){
127 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
128 }
129 if(isset($this->parent->$source)){
130 $this->parent->$dest = $this->parent->$source;
131 }
132 if(isset($this->parent->attrs[$source][0])){
133 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
134 }
135 }
136 }
139 public function mailEqualsCN()
140 {
141 return($this->mailEqualsCN);
142 }
145 public function fixAttributesOnRemove()
146 {
147 /* Remove objectClasses
148 */
149 if($this->type == "user"){
150 $this->parent->attrs['objectClass'] =
151 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
152 }else{
153 $this->parent->attrs['objectClass'] =
154 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
155 }
156 foreach($this->attributes as $source => $dest){
157 $this->attrs[$dest] = array();
158 $this->attrs[$source] = array();
159 }
160 }
162 public function fixAttributesOnStore()
163 {
164 foreach($this->attributes as $source => $dest){
165 if(isset($this->parent->attrs[$dest])){
166 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
167 }
168 if(isset($this->parent->$dest)){
169 $this->parent->$source = $this->parent->$dest;
170 }
171 }
173 if($this->type == "user"){
174 $ocs = $this->userObjectClasses;
175 }else{
176 $ocs = $this->shareObjectClasses;
177 }
178 foreach($ocs as $oc){
179 if(!in_array($oc, $this->parent->attrs['objectClass'])){
180 $this->parent->attrs['objectClass'][] = $oc;
181 }
182 }
183 }
186 /*! \brief Connect services like imap.
187 Not necessary for the base class.
188 @return Boolean True if this method is connected else false.
189 */
190 public function connect()
191 {
192 $this->reset_error();
193 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Connect method</b>: ".get_class($this),"");
194 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Current server</b>: ".$this->MailServer,"");
196 $this->connected = TRUE;
197 return(TRUE);
198 }
201 /*! \brief Returns the connection status of this method.
202 @return Boolean True if this method is connected else false.
203 */
204 public function is_connected()
205 {
206 return($this->connected);
207 }
210 /*! \brief Disconnect this method. Close services like imap connection.
211 Not necessary for the base class.
212 */
213 public function disconnect()
214 {
215 $this->reset_error();
216 if($this->is_connected()){
217 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Disconnect method</b>: ".get_class($this),"");
218 $this->connected =FALSE;
219 }
220 }
223 /*! \brief Returns true the current object represents a valid account
224 (Some methods may check imap accounts here.)
225 @return Boolean TRUE if this is a valid account else FALSE
226 */
227 public function account_exists()
228 {
229 $this->reset_error();
230 return(TRUE);
231 }
234 /*! \brief Returns the last error occurred
235 @return String The last error message.
236 */
237 public function get_error(){
238 return($this->error);
239 }
242 public function isModifyableMail()
243 {
244 return($this->modifyableMail);
245 }
248 /*! \brief Returns TRUE if the action caused an error.
249 @return Boolean TRUE on error else FALSE
250 */
251 public function is_error(){
252 return($this->error != "");
253 }
256 /*! \brief Resets the error message.
257 */
258 public function reset_error(){
259 $this->error = "";
260 }
263 public function get_account_id()
264 {
265 $this->build_account_id();
266 return($this->account_id);
267 }
269 /*! \brief Create a new account id, like 'user/name@domain.com'.
270 */
271 protected function build_account_id()
272 {
273 /* Build account identicator */
274 if($this->type == "user"){
275 $str = $this->user_prefix;
276 }else{
277 $str = $this->share_prefix;
278 }
280 /* Create account prefix and respect "cyrusUseSlashes"
281 Do not replace escaped dots for cyrusUseSlashes.
282 */
283 $uattrib = $this->uattrib;
284 if($this->cyrusUseSlashes){
285 $str = preg_replace('/([^\\\\])\./',"\\1/",$str);
286 }
287 $str = preg_replace("/\\\\([\.\/])/","\\1",$str);
288 $str = trim(strtolower($str . $this->parent->$uattrib));
290 if($this->account_id != $str){
291 $this->account_id = $str;
292 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "accountID generated: <b>".$str."</b>","");
293 }
294 }
297 /*! \brief Creates a valid folder id for a given folder name.
298 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
299 will result in "share/mailbox/test@domain.de"
300 This function is mainly used to read and write folder permissions.
301 @return String A valid folder id
302 */
303 public function create_folder_id($folder, $type = "")
304 {
306 if(!empty($folder)){
307 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
308 }
309 if(!empty($folder)){
310 $folder = "/".$folder;
311 }
313 /* Build account identicator */
314 if($type == ""){
315 $type = $this->type;
316 }
317 if($type == "user"){
318 $str = $this->user_prefix;
319 }else{
320 $str = $this->share_prefix;
321 }
323 /* Create account prefix and respect "cyrusUseSlashes"
324 Do not replace escaped dots for cyrusUseSlashes.
325 */
326 $uattrib = $this->uattrib;
327 if($this->cyrusUseSlashes){
328 $str = preg_replace('/([^\\\\])\./',"\\1/",$str);
329 }
330 $str = preg_replace("/\\\\([\.\/])/","\\1",$str);
331 $str = trim(strtolower($str . $this->parent->$uattrib));
333 if(preg_match("/\@/",$this->parent->$uattrib)){
334 list($mail,$domain) = split("\@",$this->parent->$uattrib);
335 $str = trim(strtolower($str . $mail . $folder . "@" . $domain));
336 }else{
337 $str = trim(strtolower($str . $this->parent->$uattrib));
338 }
339 return($str) ;
340 }
343 /*! \brief Returns the configured mail method for the given parent object,
344 initialized and read for use.
345 @return mailMethod The configured mailMethod.
346 */
347 public function get_method()
348 {
349 $methods = mailMethod::get_methods();
350 if ($this->config->get_cfg_value("mailmethod") != ""){
351 $method= $this->config->get_cfg_value("mailmethod");
352 $cls = get_correct_class_name("mailMethod$method");
353 if(isset($methods[$cls])){
354 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "Selected mailMethod: <b>".$cls."</b>","");
355 $tmp = new $cls($this->config,$this->parent,$this->type);
356 $tmp->init();
357 return($tmp);
358 }else{
359 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "Invalid mailMethod defined <b>".$cls.
360 "</b> falling back to <b>".get_class($this)."</b>","");
362 /* Print out configuration errors directly, we can't catch them everywhere.
363 */
364 msg_dialog::display(_("Configuration error"),
365 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
366 }
367 }
369 /* If no valued mailMethod could be detected, return the base class.
370 */
371 $this->init();
372 return($this);
373 }
376 /*! \brief Saves sieve settings
377 */
378 public function saveSieveSettings()
379 {
380 $this->reset_error();
381 return(TRUE);
382 }
385 /*! \brief Creates or Updates the mailAccount represented by this class.
386 */
387 public function updateMailbox()
388 {
389 $this->reset_error();
390 return(TRUE);
391 }
394 /*! \brief Update shared folder dependencies
395 */
396 public function updateSharedFolder()
397 {
398 $this->reset_error();
399 return(TRUE);
400 }
403 /*! \brief Removes the mailbox represented by this class,
404 and update shared folder ACLs .
405 */
406 public function deleteMailbox()
407 {
408 $this->reset_error();
410 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
411 "<b>Remove account</b> from server :".$this->MailServer);
413 return(TRUE);
415 /* No imap actions here, just updated shared folder membership
416 */
417 $ldap = $this->config->get_ldap_link();
418 $ldap->cd($this->config->current['BASE']);
419 $ldap->search("(&(objectClass=posixGroup)(objectClass=gosaMailAccount)(memberUid=".$account."))",array('dn','cn'));
420 if(class_exists("grouptabs")){
421 while($attrs = $ldap->fetch()){
422 $tmp = new grouptabs($this->config, $this->config->data['TABS']['GROUPTABS'], $attrs['dn']);
423 if(isset($tmp->by_object['mailgroup'])){
424 $tmp->by_object['mailgroup']->members= $tmp->by_object['group']->memberUid;
425 if(!$this->is_account){
426 $tmp->by_object['mailgroup']->removeUserAcl($account);
427 $tmp->by_object['mailgroup']->removeUserAcl($this->mail);
428 }
429 $tmp->by_object['mailgroup']->save();
430 }
431 }
432 }
433 return(TRUE);
434 }
437 /*! \brief Returns the used mail attribute (mail,uid)
438 @param String One out of 'mail','uid'
439 */
440 public function getUAttrib()
441 {
442 return($this->uattrib);
443 }
446 /*! \brief Returns the used mail attribute (mail,uid)
447 @param String One out of 'mail','uid'
448 */
449 public function getUAttribValue()
450 {
451 $uattrib = $this->getUAttrib();
452 return($this->parent->$uattrib);
453 }
456 /*! \brief Returns whether the quota settings are enabled or not
457 @return Boolean TRUE if enabled else FALSE
458 */
459 public function quotaEnabled()
460 {
461 return($this->enableQuota);
462 }
465 /*! \brief Returns the used quota
466 @return Integer Quota used.
467 */
468 public function getQuotaUsage()
469 {
470 return(-1);
471 }
474 /*! \brief Returns the quota restrictions.
475 @return Integer Quota restrictions.
476 */
477 public function getQuota($quotaValue)
478 {
479 return($quotaValue);
480 }
483 /*! \brief Sets the mail quota
484 */
485 public function setQuota($number)
486 {
487 if(!is_numeric($number)){
488 $number = (int) $number;
489 if(!$number){
490 $number = 0;
491 }
492 }
493 $this->quotaValue = $number;
494 return(TRUE);
495 }
498 /*! \brief Returns true whether the domain is selectable or not
499 */
500 public function domainSelectionEnabled()
501 {
502 return($this->enableDomainSelection);
503 }
506 /*! \brief Returns a list of configured mail domains
507 @return Array A list of mail domains
508 */
509 public function getMailDomains()
510 {
511 return(array("Unconfigured"));
512 }
515 /*! \brief Returns the used Spamlevels for this mailmethod
516 */
517 public function getSpamLevels()
518 {
519 $spamlevel= array();
520 for ($i= 0; $i<21; $i++){
521 $spamlevel[]= $i;
522 }
523 return($spamlevel);
524 }
527 /*! \brief Returns the list of configured mailbox folders
528 @return Array The mailbox folders.
529 */
530 public function getMailboxList()
531 {
532 return(array("INBOX"));
533 }
536 /*! \brief Returns whether the vacation range is selectable or not
537 @return Boolean TRUE, FALSE
538 */
539 public function vacationRangeEnabled()
540 {
541 return($this->enableVacationRange);
542 }
545 /*! \brief Returns true if the sieveManagement is allowed
546 @return Boolean TRUE, FALSE
547 */
548 public function allowSieveManagement()
549 {
550 return($this->enableSieveManager);
551 }
554 /*! \brief Checks dependencies to other GOsa plugins.
555 */
556 public function accountCreateable(&$reason = ""){
557 return(TRUE);
558 }
561 /*! \brief Checks whether this account is removeable or not.
562 There may be some dependencies left, eg. kolab.
563 */
564 public function accountRemoveable(&$reason = ""){
565 return(TRUE);
566 }
569 /*! \brief Returns all mail servers configured in GOsa
570 that are useable with this mailMethod.
571 @return Array All useable mail servers.
572 */
573 public function getMailServers()
574 {
575 $mailserver = array();
576 $ui = get_userinfo();
577 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
578 if( $this->MailServer == $key ||
579 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
580 $mailserver[]= $key;
581 }
582 }
583 return($mailserver);
584 }
587 /*! \brief Returns the available mailMethods
588 @return Array A list of all avaialable mailMethods_
589 */
590 static protected function get_methods()
591 {
592 global $class_mapping;
593 $available = array();
594 foreach($class_mapping as $class => $path){
595 if($class == "mailMethod") continue;
596 if(preg_match("/^mailMethod/",$class)){
597 $available[$class] = $class;
598 }
599 }
600 return($available);
601 }
604 /* \brief Some method require special folder types, "kolab" for example.
605 !! Those values are dummy values, the base class doesn't use folder types;
606 @return Array Return folder types.
607 */
608 public function getAvailableFolderTypes()
609 {
610 $ret = array();
611 $ret['CAT'][''] = _("None");
612 $ret['SUB_CAT'][''][''] = _("None");
613 return($ret);
614 }
617 /* \brief Returns the selected folder type.
618 !! Those values are dummy values, the base class doesn't use folder types;
619 @return Array The folde type.
620 */
621 public function getFolderType($default)
622 {
623 return($default);
624 }
627 /* \brief Returns the selected folder type.
628 !! Those values are dummy values, the base class doesn't use folder types;
629 @return Array The folde type.
630 */
631 public function setFolderType($type)
632 {
633 return(TRUE) ;
634 }
637 /*! \brief Returns configured acls
638 */
639 public function getFolderACLs($folder_acls)
640 {
641 /* Merge given ACL with acl mapping
642 This ensures that no ACL will accidentally overwritten by gosa.
643 */
644 foreach($folder_acls as $user => $acl){
645 if(!isset($this->acl_mapping[$acl])){
646 $this->acl_mapping[$acl] = $acl;
647 }
648 }
650 return($folder_acls);
651 }
654 /*! \brief Write ACLs back to imap or what ever
655 */
656 public function setFolderACLs($array)
657 {
658 return(TRUE);
659 }
662 /*! \brief Returns a list of all possible acls.
663 @return Array ACLs.
664 */
665 public function getAclTypes()
666 {
667 return( $this->acl_mapping);
668 }
670 public function folderTypesEnabled()
671 {
672 return($this->enableFolderTypes);
673 }
675 public function allow_remove(&$reason)
676 {
677 return(TRUE);
678 }
679 }
682 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
683 ?>