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