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 /* gosaSharedFolderTarget settings,
43 * E.g.
44 * For an accountID like: 'share/herberts.folder@gonicus.de' the value 'dummy+'
45 * will result in gosaSharedFolderTarget: dummy+share/herberts.folder@gonicus.de
46 */
47 protected $gosaSharedPrefix = '';
49 /* The atribute mapping for this class Source --> Destination */
50 protected $attributes = array();
51 protected $userObjectClasses = array();
52 protected $shareObjectClasses = array();
54 /* Enabled mail domain selection. If enabled getMailDomains() have to return an array
55 * with the domain parts.
56 */
57 protected $enableDomainSelection= FALSE;
58 protected $enableQuota = TRUE;
59 protected $enableSieveManager = FALSE;
60 protected $enableVacationRange = TRUE;
61 protected $enableFolderTypes = FALSE;
63 /* Default values */
64 protected $quotaValue = 0;
65 protected $quotaUsage = 0;
67 /* Method internal */
68 protected $type = "user";
69 protected $account_id = "";
70 protected $initial_account_id = "";
71 protected $connected = FALSE;
72 protected $error = "";
73 protected $parent = NULL;
74 protected $MailServer = "";
76 protected $default_acls = array("__anyone__" => "p", "__member__" => "lrswp");
78 protected $acl_map = array(
79 "lrsw" => "read",
80 "lrswp" => "post",
81 "p" => "external post",
82 "lrswip" => "append",
83 "lrswipcd" => "write",
84 "lrswipcda"=> "admin",
85 " " => "none");
87 protected $acl_mapping = array();
90 /*! \brief Constructs the mail class
91 @param Object Config The GOsa configuration object
92 @param Object Plugin The initator
93 @param String Open "user" or "group" account.
94 */
95 function __construct(&$config, &$parent, $type = "user")
96 {
97 $this->parent = $parent;
98 $this->config = $config;
100 /* Create a refernce to the mail selected server
101 */
102 if(isset($this->parent->gosaMailServer)){
103 $this->MailServer = &$this->parent->gosaMailServer;
104 }else{
105 trigger_error("mailMethod with invalid parent object initialized.");
106 }
108 if(!in_array($this->type,array("user","group"))){
109 trigger_error("Unknown mail class type used '".$type."'.");
110 }else{
111 $this->type = $type;
112 }
114 }
117 /*! \brief Intialize attributes and config settings.
118 */
119 protected function init()
120 {
121 /* Get config value for cyrusUseSlashes
122 */
123 if ($this->config->get_cfg_value("cyrusUseSlashes") == "true"){
124 $this->cyrusUseSlashes = TRUE;
125 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Enabled</b>");
126 }else{
127 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL:</b> cyrusUseSlashes: <b>Disabled</b>");
128 }
130 /* Check if the mail account identification attribute
131 is overridden in the configuration file
132 */
133 if($this->config->get_cfg_value("mailAttribute","mail") != ""){
134 $new_uattrib= strtolower($this->config->get_cfg_value("mailAttribute"));
135 if(in_array($new_uattrib,array("mail","uid"))){
136 $this->uattrib = $new_uattrib;
137 }else{
138 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$new_uattrib."</b>",
139 "<b>MAIL:</b> Unsupported 'mailAttribute' in gosa configuration specified");
140 msg_dialog::display(_("Configuration error"),
141 sprintf(_("The configured mail attribute '%s' is unsupported!"), $new_uattrib), ERROR_DIALOG);
142 }
143 }
145 /* Create ACL map */
146 foreach($this->acl_map as $acl => $name){
147 $this->acl_mapping[$acl] = _($name);
148 }
150 /* Check if we have an individual user/folder creation syntax
151 */
152 $tmp = $this->config->get_cfg_value("mailUserCreation");
153 if(!empty($tmp)){
154 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<i>".$tmp."</i>",
155 "<b>MAIL:</b> User creation set to");
156 $this->user_id = $tmp;
157 }
158 $tmp = $this->config->get_cfg_value("mailFolderCreation");
159 if(!empty($tmp)){
160 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<i>".$tmp."</i>",
161 "<b>MAIL:</b> Shared folder creation set to");
162 $this->share_id = $tmp;
163 }
165 $this->build_account_id();
166 $this->initial_account_id = $this->account_id;
167 }
170 public function fixAttributesOnLoad()
171 {
172 foreach($this->attributes as $source => $dest){
173 if(isset($this->parent->attrs[$source])){
174 $this->parent->attrs[$dest] = $this->parent->attrs[$source];
175 }
176 if(isset($this->parent->$source)){
177 $this->parent->$dest = $this->parent->$source;
178 }
179 if(isset($this->parent->attrs[$source][0])){
180 $this->parent->saved_attributes[$source] = $this->parent->attrs[$source][0];
181 }
182 }
183 }
186 public function mailEqualsCN()
187 {
188 return($this->mailEqualsCN);
189 }
192 public function fixAttributesOnRemove()
193 {
194 /* Remove objectClasses
195 */
196 if($this->type == "user"){
197 $this->parent->attrs['objectClass'] =
198 array_remove_entries_ics($this->userObjectClasses, $this->parent->attrs['objectClass']);
199 }else{
200 $this->parent->attrs['objectClass'] =
201 array_remove_entries_ics($this->shareObjectClasses, $this->parent->attrs['objectClass']);
202 $this->parent->attrs['gosaSharedFolderTarget'] =array();
203 }
204 foreach($this->attributes as $source => $dest){
205 $this->attrs[$dest] = array();
206 $this->attrs[$source] = array();
207 }
208 }
210 public function fixAttributesOnStore()
211 {
212 foreach($this->attributes as $source => $dest){
213 if(isset($this->parent->attrs[$dest])){
214 $this->parent->attrs[$source] = $this->parent->attrs[$dest ];
215 }
216 if(isset($this->parent->$dest)){
217 $this->parent->$source = $this->parent->$dest;
218 }
219 }
221 if($this->type == "user"){
222 $ocs = $this->userObjectClasses;
223 }else{
224 $ocs = $this->shareObjectClasses;
225 }
226 foreach($ocs as $oc){
227 if(!in_array($oc, $this->parent->attrs['objectClass'])){
228 $this->parent->attrs['objectClass'][] = $oc;
229 }
230 }
232 // Add gosaSharedFolderTarget for groups.
233 $this->build_account_id();
234 if($this->type == "group"){
235 $this->parent->attrs['gosaSharedFolderTarget'] =
236 $this->gosaSharedPrefix.$this->account_id;
237 }
238 }
241 /*! \brief Connect services like imap.
242 Not necessary for the base class.
243 @return Boolean True if this method is connected else false.
244 */
245 public function connect()
246 {
247 $this->reset_error();
248 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Connect method</b>: ".get_class($this));
249 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Current server</b>: ".$this->MailServer);
251 $this->connected = TRUE;
252 return(TRUE);
253 }
256 /*! \brief Returns the connection status of this method.
257 @return Boolean True if this method is connected else false.
258 */
259 public function is_connected()
260 {
261 return($this->connected);
262 }
265 /*! \brief Disconnect this method. Close services like imap connection.
266 Not necessary for the base class.
267 */
268 public function disconnect()
269 {
270 $this->reset_error();
271 if($this->is_connected()){
272 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"","<b>MAIL: Disconnect method</b>: ".get_class($this));
273 $this->connected =FALSE;
274 }
275 }
278 /*! \brief Returns true the current object represents a valid account
279 (Some methods may check imap accounts here.)
280 @return Boolean TRUE if this is a valid account else FALSE
281 */
282 public function account_exists()
283 {
284 $this->reset_error();
285 return(TRUE);
286 }
289 /*! \brief Returns the last error occurred
290 @return String The last error message.
291 */
292 public function get_error(){
293 return($this->error);
294 }
297 public function isModifyableMail()
298 {
299 return($this->modifyableMail);
300 }
303 public function isModifyableServer()
304 {
305 return($this->modifyableServer);
306 }
309 /*! \brief Returns TRUE if the action caused an error.
310 @return Boolean TRUE on error else FALSE
311 */
312 public function is_error(){
313 return($this->error != "");
314 }
317 /*! \brief Resets the error message.
318 */
319 public function reset_error(){
320 $this->error = "";
321 }
324 public function get_account_id()
325 {
326 $this->build_account_id();
327 return($this->account_id);
328 }
330 /*! \brief Create a new account id, like 'user/name@domain.com'.
331 */
332 protected function build_account_id()
333 {
334 /* Build account identicator */
335 if($this->type == "user"){
336 $prefix = $this->user_prefix;
337 $acc_string = $this->user_id;
338 }else{
339 $prefix = $this->share_prefix;
340 $acc_string = $this->share_id;
341 }
343 /* Create account prefix and respect "cyrusUseSlashes"
344 Do not replace escaped dots for cyrusUseSlashes.
345 */
346 $uattrib = $this->uattrib;
347 if($this->cyrusUseSlashes){
348 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
349 $acc_string = preg_replace('/([^\\\\])\./',"\\1/",$acc_string);
350 }
351 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
352 $acc_string = preg_replace("/\\\\([\.\/])/","\\1",$acc_string);
354 $domain = $mailpart = "";
355 $mail = $this->parent->mail;
356 if(preg_match("/\@/",$mail)){
357 list($mailpart,$domain) = split("\@",$mail);
358 }
360 /* Create account_id
361 */
362 $from = array("/%cn%/i","/%uid%/i","/%prefix%/i","/%uattrib%/i","/%domain%/i","/%mailpart%/i","/%mail%/i");
363 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
364 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
366 /* Check for not replaced pattern.
367 */
368 if(preg_match("/%/",$acc_id)){
369 $notr = preg_replace("/^[^%]*/","",$acc_id);
370 if(!empty($notr)){
371 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Warning</b>",
372 sprintf("<b>MAIL: WARNING unknown pattern in account creation string '%s' near '%s'</b>", $acc_id, $notr));
374 /* Remove incomprehensible patterns */
375 $acc_id = preg_replace("/%[^%]+%/","",$acc_id);
376 }
377 }
380 if($this->account_id != $acc_id){
381 $this->account_id = $acc_id;
382 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> AccountID generated: <b>".$acc_id."</b>");
383 }
384 }
387 /*! \brief Creates a valid folder id for a given folder name.
388 e.g. $folder_id = "INBOX/test" && $this->account_id = "share/mailbox@domain.de"
389 will result in "share/mailbox/test@domain.de"
390 This function is mainly used to read and write folder permissions.
391 @return String A valid folder id
392 */
393 public function create_folder_id($folder, $type = "")
394 {
396 if(!empty($folder)){
397 $folder = trim(preg_replace("/^INBOX[\.\/]*/i","",$folder));
398 }
399 if(!empty($folder)){
400 $folder = "/".$folder;
401 }
403 /* Build account identicator */
404 if($this->type == "user"){
405 $prefix = $this->user_prefix;
406 $acc_string = $this->user_id;
407 }else{
408 $prefix = $this->share_prefix;
409 $acc_string = $this->share_id;
410 }
412 /* Create account prefix and respect "cyrusUseSlashes"
413 Do not replace escaped dots for cyrusUseSlashes.
414 */
415 $uattrib = $this->uattrib;
416 if($this->cyrusUseSlashes){
417 $prefix = preg_replace('/([^\\\\])\./',"\\1/",$prefix);
418 $acc_string = preg_replace('/([^\\\\])\./',"\\1/",$acc_string);
419 }
420 $prefix = preg_replace("/\\\\([\.\/])/","\\1",$prefix);
421 $acc_string = preg_replace("/\\\\([\.\/])/","\\1",$acc_string);
423 $domain = $mailpart = "";
424 $mail = $this->parent->mail;
425 if(preg_match("/\@/",$mail)){
426 list($mailpart,$domain) = split("\@",$mail);
427 }
429 /* Create account_id
430 */
431 $from = array("/%cn%/i","/%uid%/i","/%prefix%/i","/%uattrib%/i","/%domain%/i","/%mailpart%/i","/%mail%/i");
432 $to = array($this->parent->cn,$this->parent->uid,$prefix,$this->parent->$uattrib, $domain, $mailpart,$mail);
433 $acc_id = trim(strtolower(preg_replace($from,$to,$acc_string)));
435 /* Check for not replaced pattern.
436 */
437 if(preg_match("/%/",$acc_id)){
438 $notr = preg_replace("/^[^%]*/","",$acc_id);
439 if(!empty($notr)){
440 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"<b>Warning</b>",
441 sprintf("<b>MAIL: WARNING unknown pattern in account creation string '%s' near '%s'</b>", $acc_id, $notr));
443 /* Remove incomprehensible patterns */
444 $acc_id = preg_replace("/%[^%]+%/","",$acc_id);
445 }
446 }
448 if(preg_match("/\@/",$acc_id)){
449 list($mail,$domain) = split("\@",$acc_id);
450 $str = trim($mail . $folder . "@" . $domain);
451 }else{
452 $str = trim($acc_id . $folder);
453 }
454 return($str) ;
455 }
458 /*! \brief Returns the configured mail method for the given parent object,
459 initialized and read for use.
460 @return mailMethod The configured mailMethod.
461 */
462 public function get_method()
463 {
464 $methods = mailMethod::get_methods();
465 if ($this->config->get_cfg_value("mailmethod") != ""){
466 $method= $this->config->get_cfg_value("mailmethod");
467 $cls = get_correct_class_name("mailMethod$method");
468 if(isset($methods[$cls])){
469 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"", "<b>MAIL:</b> Selected mailMethod: <b>".$cls."</b>");
470 $tmp = new $cls($this->config,$this->parent,$this->type);
471 $tmp->init();
472 return($tmp);
473 }else{
474 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "","<b>MAIL: Invalid mailMethod defined: ".$cls.
475 " falling back to ".get_class($this)."</b>");
477 /* Print out configuration errors directly, we can't catch them everywhere.
478 */
479 msg_dialog::display(_("Configuration error"),
480 sprintf(_("Mail method '%s' is unknown!"), $method), ERROR_DIALOG);
481 }
482 }
484 /* If no valued mailMethod could be detected, return the base class.
485 */
486 $this->init();
487 return($this);
488 }
491 /*! \brief Saves sieve settings
492 */
493 public function saveSieveSettings()
494 {
495 $this->reset_error();
496 return(TRUE);
497 }
500 /*! \brief Creates or Updates the mailAccount represented by this class.
501 */
502 public function updateMailbox()
503 {
504 $this->reset_error();
505 return(TRUE);
506 }
509 /*! \brief Update shared folder dependencies
510 */
511 public function updateSharedFolder()
512 {
513 $this->reset_error();
514 return(TRUE);
515 }
518 /*! \brief Removes the mailbox represented by this class,
519 and update shared folder ACLs .
520 */
521 public function deleteMailbox()
522 {
523 $this->reset_error();
525 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, "<b>".$this->account_id."</b>" ,
526 "<b>MAIL: Remove account</b> from server :".$this->MailServer);
528 return(TRUE);
529 }
532 /*! \brief Returns the used mail attribute (mail,uid)
533 @param String One out of 'mail','uid'
534 */
535 public function getUAttrib()
536 {
537 return($this->uattrib);
538 }
541 /*! \brief Returns the used mail attribute (mail,uid)
542 @param String One out of 'mail','uid'
543 */
544 public function getUAttribValue()
545 {
546 $uattrib = $this->getUAttrib();
547 return($this->parent->$uattrib);
548 }
551 /*! \brief Returns whether the quota settings are enabled or not
552 @return Boolean TRUE if enabled else FALSE
553 */
554 public function quotaEnabled()
555 {
556 return($this->enableQuota);
557 }
560 /*! \brief Returns the used quota
561 @return Integer Quota used.
562 */
563 public function getQuotaUsage()
564 {
565 return(-1);
566 }
569 /*! \brief Returns the quota restrictions.
570 @return Integer Quota restrictions.
571 */
572 public function getQuota($quotaValue)
573 {
574 return($quotaValue);
575 }
578 /*! \brief Sets the mail quota
579 */
580 public function setQuota($number)
581 {
582 if(!is_numeric($number)){
583 $number = (int) $number;
584 if(!$number){
585 $number = 0;
586 }
587 }
588 $this->quotaValue = $number;
589 return(TRUE);
590 }
593 /*! \brief Returns true whether the domain is selectable or not
594 */
595 public function domainSelectionEnabled()
596 {
597 return($this->enableDomainSelection);
598 }
601 /*! \brief Returns a list of configured mail domains
602 @return Array A list of mail domains
603 */
604 public function getMailDomains()
605 {
606 return(array("Unconfigured"));
607 }
610 /*! \brief Returns the used Spamlevels for this mailmethod
611 */
612 public function getSpamLevels()
613 {
614 $spamlevel= array();
615 for ($i= 0; $i<21; $i++){
616 $spamlevel[]= $i;
617 }
618 return($spamlevel);
619 }
622 /*! \brief Returns the list of configured mailbox folders
623 @return Array The mailbox folders.
624 */
625 public function getMailboxList()
626 {
627 return(array("INBOX"));
628 }
631 /*! \brief Returns whether the vacation range is selectable or not
632 @return Boolean TRUE, FALSE
633 */
634 public function vacationRangeEnabled()
635 {
636 return($this->enableVacationRange);
637 }
640 /*! \brief Returns true if the sieveManagement is allowed
641 @return Boolean TRUE, FALSE
642 */
643 public function allowSieveManagement()
644 {
645 return($this->enableSieveManager);
646 }
649 /*! \brief Checks dependencies to other GOsa plugins.
650 */
651 public function accountCreateable(&$reason = ""){
652 return(TRUE);
653 }
656 /*! \brief Checks whether this account is removeable or not.
657 There may be some dependencies left, eg. kolab.
658 */
659 public function accountRemoveable(&$reason = ""){
660 return(TRUE);
661 }
664 /*! \brief Returns all mail servers configured in GOsa
665 that are useable with this mailMethod.
666 @return Array All useable mail servers.
667 */
668 public function getMailServers()
669 {
670 $mailserver = array();
671 $ui = get_userinfo();
672 foreach ($this->config->data['SERVERS']['IMAP'] as $key => $val){
673 if( $this->MailServer == $key ||
674 preg_match("/r/",$ui->get_permissions($val['server_dn'],"server/goImapServer",""))){
675 $mailserver[]= $key;
676 }
677 }
678 return($mailserver);
679 }
682 /*! \brief Returns the available mailMethods
683 @return Array A list of all avaialable mailMethods_
684 */
685 static protected function get_methods()
686 {
687 global $class_mapping;
688 $available = array();
689 foreach($class_mapping as $class => $path){
690 if($class == "mailMethod") continue;
691 if(preg_match("/^mailMethod/",$class)){
692 $available[$class] = $class;
693 }
694 }
695 return($available);
696 }
699 /* \brief Some method require special folder types, "kolab" for example.
700 !! Those values are dummy values, the base class doesn't use folder types;
701 @return Array Return folder types.
702 */
703 public function getAvailableFolderTypes()
704 {
705 $ret = array();
706 $ret['CAT'][''] = _("None");
707 $ret['SUB_CAT'][''][''] = _("None");
708 return($ret);
709 }
712 /* \brief Returns the selected folder type.
713 !! Those values are dummy values, the base class doesn't use folder types;
714 @return Array The folde type.
715 */
716 public function getFolderType($default)
717 {
718 return($default);
719 }
722 /* \brief Returns the selected folder type.
723 !! Those values are dummy values, the base class doesn't use folder types;
724 @return Array The folde type.
725 */
726 public function setFolderType($type)
727 {
728 return(TRUE) ;
729 }
732 /*! \brief Returns configured acls
733 */
734 public function getFolderACLs($folder_acls)
735 {
736 /* Merge given ACL with acl mapping
737 This ensures that no ACL will accidentally overwritten by gosa.
738 */
739 foreach($folder_acls as $user => $acl){
740 if(!isset($this->acl_mapping[$acl])){
741 $this->acl_mapping[$acl] = $acl;
742 }
743 }
745 return($folder_acls);
746 }
749 /*! \brief Write ACLs back to imap or what ever
750 */
751 public function setFolderACLs($array)
752 {
753 return(TRUE);
754 }
757 /*! \brief Returns a list of all possible acls.
758 @return Array ACLs.
759 */
760 public function getAclTypes()
761 {
762 return( $this->acl_mapping);
763 }
765 public function folderTypesEnabled()
766 {
767 return($this->enableFolderTypes);
768 }
770 public function allow_remove(&$reason)
771 {
772 return(TRUE);
773 }
776 /*! \brief Returns the configured mailMethod
777 @return String the configured mail method or ""
778 */
779 static public function get_current_method($config)
780 {
781 global $class_mapping;
782 $method= $config->get_cfg_value("mailmethod");
783 $cls = get_correct_class_name("mailMethod$method");
784 foreach($class_mapping as $class => $path){
785 if($class == $cls){
786 return($class);
787 }
788 }
789 return("");
790 }
793 static function quota_to_image($use,$quota)
794 {
795 if($use == -1){
796 return(" "._("Unknown"));
797 }elseif(empty($quota)){
798 return(" "._("Unlimited"));
799 }else{
800 $usage =round(($use/$quota) * 100);
801 return("<img src='progress.php?x=100&y=17&p=$usage'>");
802 }
803 }
806 /*! \brief Returns the default sharedFolder ACLs for this method.
807 @return Array Returns an array containg acls for __member__ and __anyone__
808 */
809 public function getDefaultACLs()
810 {
811 $tmp = $this->default_acls;
812 if(!isset($tmp['__member__'])) $tmp['__member__'] = " ";
813 if(!isset($tmp['__anyone__'])) $tmp['__anyone__'] = " ";
814 return($tmp);
815 }
816 }
819 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
820 ?>