~ubuntu-branches/ubuntu/hardy/steam/hardy

« back to all changes in this revision

Viewing changes to server/modules/forward.pike

  • Committer: Bazaar Package Importer
  • Author(s): Alain Schroeder
  • Date: 2006-11-21 16:03:12 UTC
  • mfrom: (2.1.4 feisty)
  • Revision ID: james.westby@ubuntu.com-20061121160312-nf96y6nihzsyd2uv
Tags: 2.2.31-3
Add patch to prevent inconsistent data after shutdown.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 */
17
17
 
18
 
#include <attributes.h>
19
 
 
20
18
/**
21
 
 * This module is responsible for sending messages to users/groups/... and e-mails to 
22
 
 * remote adresses. It also keeps track of system-wide alias-adresses and of user-forwards.
 
19
 * This module is responsible for sending messages to users/groups/... and
 
20
 * e-mails to remote adresses. It also keeps track of system-wide
 
21
 * alias-adresses and of user-forwards.
23
22
 */
24
23
 
25
24
inherit "/kernel/module";
26
25
 
27
 
import Messaging;
28
 
 
29
26
#include <database.h>
30
27
#include <macros.h>
31
28
#include <classes.h>
32
29
#include <config.h>
33
30
#include <attributes.h>
 
31
#include <events.h>
34
32
 
35
 
#define DEBUG_FORWARD
 
33
//#define DEBUG_FORWARD
36
34
 
37
35
#ifdef DEBUG_FORWARD
38
36
#define LOG_FORWARD(s, args...) werror("forward: "+s+"\n", args)
48
46
 
49
47
//stores aliases & forwards
50
48
static mapping(string:array) mAliases, mForwards;
51
 
static object modgroups = get_module("groups");
 
49
static mapping(object:object) mListeners;
52
50
 
53
51
string _mailserver;
54
52
int _mailport;
59
57
{
60
58
    mAliases=([]);
61
59
    mForwards=([]);
 
60
    mListeners=([]);
62
61
    add_data_storage(STORE_FORWARD,retrieve_aliases,restore_aliases);
63
62
}
64
63
 
 
64
static array|void get_parent_groups(object group)
 
65
{
 
66
  object parent = group->get_parent();
 
67
  array parents = ({});
 
68
  if(!objectp(parent))
 
69
    return;
 
70
  else
 
71
    parents += ({ parent });
 
72
  array grandparents=get_parent_groups(parent);
 
73
  if(arrayp(grandparents) )
 
74
    parents += grandparents;
 
75
  return parents;
 
76
}
 
77
 
 
78
static array get_user_groups(object user)
 
79
{
 
80
    array groups;
 
81
    array usergroups = groups = user->get_groups();
 
82
    foreach(usergroups;; object group)
 
83
    {
 
84
      array parents = get_parent_groups(group);
 
85
      if(arrayp(parents))
 
86
        groups += parents;
 
87
    }
 
88
    return(Array.uniq(groups));
 
89
}
 
90
 
 
91
void load_module()
 
92
 
93
  add_global_event(EVENT_ADD_MEMBER, user_join_group, PHASE_NOTIFY);
 
94
  array groups = ({});
 
95
  LOG_FORWARD("forwards are: %O\n", mForwards);
 
96
  foreach(mForwards; string user;)
 
97
  {
 
98
    groups += get_user_groups(MODULE_USERS->lookup(user));
 
99
  }
 
100
  groups = Array.uniq(groups);
 
101
  LOG_FORWARD("listen to groups: %O\n", groups->get_identifier());
 
102
  foreach(groups;; object group)
 
103
  {
 
104
    listen_annotations(group);
 
105
  }
 
106
  // always provide an abuse adress:
 
107
  add_alias( "abuse", "admin" );
 
108
}
 
109
 
 
110
static void user_join_group(int event, object group, object caller, object user)
 
111
{
 
112
  if(!objectp(mListeners[group]) && mForwards[user->get_user_name()])
 
113
    listen_annotations(group);
 
114
}
 
115
 
 
116
void listen_annotations(object group)
 
117
{
 
118
  if(!objectp(mListeners[group]))
 
119
  {
 
120
    mListeners[group] = 
 
121
      add_event(group->query_attribute(GROUP_WORKROOM), 
 
122
                EVENT_ANNOTATE|EVENTS_MONITORED, PHASE_NOTIFY, 
 
123
                lambda(int event, mixed ... args)
 
124
                { 
 
125
                    send_annotation_remote(event, group, @args); 
 
126
                });
 
127
  }
 
128
  else
 
129
  {
 
130
    werror("already listening for %s in %s:\n%O", group->get_identifier(), 
 
131
           group->query_attribute(GROUP_WORKROOM)->get_identifier(), 
 
132
           mListeners[group]->get_listening());
 
133
  }
 
134
}
 
135
 
 
136
static void send_annotation_remote(int event, object group, object annotated, 
 
137
                                   object caller, object ... thread)
 
138
{
 
139
  // find root of thread...
 
140
  object parent = thread[-1];
 
141
  while ( objectp(parent->get_annotating()) ) 
 
142
  {
 
143
    parent = parent->get_annotating();
 
144
  }
 
145
 
 
146
  LOG_FORWARD("send_annotation_remote(event: %d, group: %O, annotated: %O, caller: %O, thread: %s) - parent: %O\n", 
 
147
         event, group->get_identifier(), annotated->get_identifier(),
 
148
         caller->get_identifier(), thread->get_identifier()*", ",
 
149
         parent->get_identifier());
 
150
 
 
151
  if(parent==annotated)
 
152
    send_group(group, thread[-1]); 
 
153
}
 
154
 
65
155
void install_module()
66
156
{
67
157
    _mailserver = _Server->query_config(CFG_MAILSERVER);
71
161
 
72
162
string get_identifier() { return "forward"; }
73
163
 
74
 
mapping get_aliases()
75
 
{
76
 
    return mAliases;
77
 
}
 
164
mapping get_aliases()
 
165
{
 
166
    return mAliases;
 
167
}
 
168
 
 
169
array get_alias ( string key ) {
 
170
  if ( arrayp(mAliases[key]) )
 
171
    return copy_value( mAliases[key] );
 
172
  else
 
173
    return UNDEFINED;
 
174
}
78
175
 
79
176
mapping retrieve_aliases()
80
177
{
92
189
    mAliases=data["aliases"];
93
190
    mForwards=data["forwards"];
94
191
    
95
 
    MESSAGE("FORWARD: loaded "+sizeof(mAliases)+" aliases and "
 
192
    LOG_FORWARD("loaded "+sizeof(mAliases)+" aliases and "
96
193
                +sizeof(mForwards)+" forwards");
97
194
}
98
195
 
113
210
    if(objectp(MODULE_USERS->lookup(address)))
114
211
        return 1; //address is single user
115
212
    LOG_FORWARD("no - trying group...");
 
213
    if ( address == "steam" )
 
214
      return 0; // no mailing to steam-group allowed
116
215
    if(objectp(MODULE_GROUPS->lookup(address)))
117
216
        return 1; //adress is a group
 
217
    LOG_FORWARD("no - trying to replace - with space...");
 
218
    if(objectp(MODULE_GROUPS->lookup(replace(address, "-", " "))))
 
219
        return 1; //adress is a group
118
220
    LOG_FORWARD("no - trying object-id...");
119
221
    if(sscanf(address,"%d",int oid))
120
222
    {
161
263
}
162
264
 
163
265
/**
 
266
 * split targets into remote, groups, users, and objects
 
267
 *
 
268
 * @author Martin B�hr
 
269
 * @param array(string) names - the addresses to work with
 
270
 * @return mapping - containing the different recipient types
 
271
 */
 
272
private mapping resolve_recipients(array(string) names)
 
273
{
 
274
    array unresolved=({});
 
275
    array(string) resolved=replace_aliases(names);
 
276
    resolved=replace_forwards(resolved);
 
277
   
 
278
    mapping result =([ "groups":({}), "remote":({}), "users":({}), 
 
279
                       "objects":({}) ]);
 
280
    object target_obj;
 
281
    int oid;
 
282
   
 
283
    foreach(resolved;; string target)
 
284
    {
 
285
        if ( !stringp(target) )
 
286
            continue;
 
287
        if(search(target,"@")!=-1)
 
288
            result->remote += ({ target });
 
289
        else if ( objectp(target_obj=MODULE_GROUPS->lookup(target)) ) 
 
290
            result->groups += ({ target_obj });
 
291
        // groupnames may have spaces, but those don't work well with email.
 
292
        else if ( objectp(target_obj=MODULE_GROUPS->lookup(replace(target, "-", " "))) ) 
 
293
            result->groups += ({ target_obj });
 
294
        else if ( objectp(target_obj=MODULE_USERS->lookup(target)) )
 
295
            result->users += ({ target_obj });
 
296
        else if ( sscanf(target,"%d",oid) 
 
297
                  && objectp(target_obj=_Database->find_object(oid)) )
 
298
            result->objects += ({ target_obj });
 
299
        else
 
300
            unresolved += ({ target });
 
301
    }
 
302
   
 
303
    if(sizeof(unresolved))
 
304
        FATAL("Warning! unresolved addresses: %O", unresolved);
 
305
    return result;
 
306
}
 
307
 
 
308
/**
164
309
 * within an array of adresses, search for aliases and replace them with 
165
310
 * their targets
166
311
 *
171
316
private array(string) replace_aliases(array(string) names)
172
317
{
173
318
    array(string) result=({});
174
 
    if ( !objectp(modgroups) )
175
 
      modgroups = get_module("groups");
176
 
    
177
 
    object grp;
178
 
 
179
 
    for(int i=0;i<sizeof(names);i++)
 
319
    foreach(names;; string name)
180
320
    {
181
 
        if(arrayp(mAliases[names[i]])) //add code for checking aliases on aliases here...
182
 
            result+=mAliases[names[i]];
183
 
        else {
184
 
          if ( objectp(grp=modgroups->lookup(names[i])) ) {
185
 
            array res = map(grp->get_members(), resolve_name);
186
 
            foreach( res, string email ) {
187
 
              if ( stringp(email)  )
188
 
                result += ({ email });
189
 
            }
190
 
          }
191
 
          else
192
 
            result+=({names[i]});
193
 
        }
 
321
        if(arrayp(mAliases[name])) //add code for checking aliases on aliases here...
 
322
            result+=mAliases[name];
 
323
        else 
 
324
           result+=({name});
194
325
    }
195
 
    return result;
 
326
    return Array.uniq(result);
196
327
}
197
328
 
 
329
 
198
330
/**
199
331
 * within an array of adresses, search for forwards and replace them with 
200
332
 * their targets
219
351
            array(string) tmp=mForwards[names[i]];
220
352
            for(int j=0;j<sizeof(tmp);j++)
221
353
            {
 
354
                if ( !stringp(tmp[j]) )
 
355
                    continue;
 
356
                
222
357
                fwd_done[tmp[j]] = 1;
223
358
                if(search(tmp[j],"@")!=-1) //remote address
224
359
                    result+=({tmp[j]});
252
387
    int hasLocal=0;
253
388
    string rawText=msg->complete_text();
254
389
    string sSender=msg->sender();
255
 
    array(string) resolved=replace_aliases(Array.uniq(target));
256
 
    resolved=replace_forwards(Array.uniq(resolved));
257
 
    array(string) asRemote=get_remote_addresses(Array.uniq(resolved));
 
390
    array(string) resolved=replace_aliases(target);
 
391
    resolved=replace_forwards(resolved);
 
392
    array(string) asRemote=get_remote_addresses(resolved);
 
393
 
258
394
    array(string) asLocal=resolved-asRemote;
259
395
    if(sizeof(asLocal)>0) hasLocal=1;
260
396
    if(hasLocal)
264
400
    
265
401
    LOG_FORWARD("Sending to " + sizeof(asRemote) + " Remote Recipients !");
266
402
    
 
403
    asRemote = Array.uniq(asRemote);
 
404
    send_remote(asRemote, rawText, sSender);
 
405
    return 1;
267
406
    for(int i=0;i<sizeof(asRemote);i++)
268
407
        send_remote(asRemote[i],rawText,sSender);
269
408
        
282
421
int send_message_raw(array(string) target, string rawText, string envFrom)
283
422
{
284
423
    mixed err;
 
424
    LOG_FORWARD("Forward: send_message_raw(%O)", target);
 
425
    mapping sendAs = resolve_recipients(target);
285
426
    int res=1; //success
286
 
    int hasLocal=0;
287
 
    array(string) resolved=replace_aliases(target);
288
 
    MESSAGE("Aliases replaced");
289
 
    resolved=replace_forwards(resolved);
290
 
    MESSAGE("Forwards are: %O", resolved);
291
 
    array(string) asRemote=get_remote_addresses(Array.uniq(resolved));
292
 
    MESSAGE("Remote adresses are: %O", asRemote);
293
 
    array(string) asLocal=resolved-asRemote;
294
 
 
295
 
    MESSAGE("Local addresses are: %O", asLocal);
296
 
    if(sizeof(asLocal)>0) hasLocal=1;
297
 
    if(hasLocal)
298
 
      err = catch(res=send_local(asLocal,Messaging.MIME2Message(rawText)));
299
 
    
300
 
    if ( err ) 
301
 
      FATAL("Error while sending message local: %O", err);
302
 
 
303
 
    if (res==0) 
304
 
      LOG_FORWARD("Warning! send_message_raw failed on one ore more local recipients!");
305
 
 
306
 
    for(int i=0;i<sizeof(asRemote);i++)
307
 
        send_remote(asRemote[i],rawText,envFrom);
308
 
        
 
427
    if(sizeof(sendAs->users))
 
428
        err = catch(res=send_users(sendAs->users,Messaging.MIME2Message(rawText)));   
 
429
    if ( err ) 
 
430
      FATAL("Error while sending message to users: %O, %O", err[0], err[1]);
 
431
    if (res==0) 
 
432
      LOG_FORWARD("Warning! send_message_raw failed on one ore more recipient users!");
 
433
    res=1;
 
434
 
 
435
    if(sizeof(sendAs->objects))
 
436
        err = catch(res=send_objects(sendAs->objects,Messaging.MIME2Message(rawText)));   
 
437
    if ( err ) 
 
438
      FATAL("Error while sending message to objects: %O,%O", err[0], err[1]);
 
439
 
 
440
    if (res==0) 
 
441
      LOG_FORWARD("Warning! send_message_raw failed on one ore more recipient objects!");
 
442
 
 
443
    send_remote(sendAs->remote, rawText, envFrom);
 
444
    foreach(sendAs->groups;; object target)
 
445
        send_group(target,rawText,envFrom);
 
446
 
309
447
    return res;
310
448
}
311
449
 
312
450
/**
 
451
 * send a message to objects
 
452
 *
 
453
 * @author Martin B�hr
 
454
 * @param array(object) targets - the objects to send the message to
 
455
 * @param string msg - the message to send
 
456
 * @return int 1 if successful
 
457
 */
 
458
private int send_objects(array(object) targets, Messaging.Message msg)
 
459
{
 
460
    LOG_FORWARD("send_objects(%O, %O)\n", targets, msg->header()->subject);
 
461
    if(sizeof(targets)==0 || !arrayp(targets)) return 0;
 
462
 
 
463
    int errors;
 
464
 
 
465
    seteuid(USER("root"));
 
466
    foreach(targets; int count; object target)
 
467
    {
 
468
        Messaging.Message copy;
 
469
        if(count<sizeof(targets)-1)
 
470
            // duplicate message if more than one recipient
 
471
            copy=msg->duplicate();
 
472
        else
 
473
            // last recipient gets original
 
474
            copy=msg;
 
475
 
 
476
        mixed err=catch{Messaging.add_message_to_object(copy,target);};
 
477
        if(err)
 
478
        {
 
479
            copy->delete();
 
480
            destruct(copy);
 
481
            errors++;
 
482
            FATAL("unable to add message to: %s(%d):%O", target->get_identifier(), target->get_object_id(), err);
 
483
        }
 
484
    }
 
485
 
 
486
    if(errors) 
 
487
    {
 
488
      LOG_FORWARD("Warning!! send_objects encountered errors - some recipients failed!");
 
489
      return 0;
 
490
    }
 
491
 
 
492
    return 1;
 
493
}
 
494
 
 
495
/**
 
496
 * send a message to users
 
497
 *
 
498
 * @author Martin B�hr
 
499
 * @param array(object) users - the users to send the message to
 
500
 * @param string msg - the message to send
 
501
 * @return int 1 if successful
 
502
 */
 
503
private int send_users(array(object) targets, Messaging.Message msg)
 
504
{
 
505
    if(sizeof(targets)==0 || !arrayp(targets)) return 0;
 
506
 
 
507
    foreach(targets; int count; object user)
 
508
    {
 
509
        if ( !objectp(user) )
 
510
            continue;
 
511
        Messaging.Message copy=msg->duplicate();
 
512
        if(count<sizeof(targets)-1)
 
513
            // duplicate message if more than one recipient
 
514
            copy=msg->duplicate();
 
515
        else
 
516
            // last recipient gets original
 
517
            copy=msg;
 
518
 
 
519
        //the recipient gets all rights on his/her copy
 
520
        copy->grant_access(user); 
 
521
 
 
522
        Messaging.BaseMailBox box = Messaging.get_mailbox(user);
 
523
        copy->this()->set_acquire(box->this());
 
524
        box->add_message(copy);
 
525
    }
 
526
 
 
527
    seteuid(0);
 
528
    return 1;
 
529
}
 
530
 
 
531
/**
 
532
 * create headers to be added to annotations sent as mails
 
533
 *
 
534
 * @author Martin B�hr
 
535
 * @param object group - the group to send the message to
 
536
 * @return mapping of headers
 
537
 */
 
538
mapping create_list_headers(object group)
 
539
{
 
540
    mapping headers = ([]);
 
541
    headers["X-Steam-Group"] = group->get_identifier();
 
542
    headers["List-Id"] = replace(group->get_identifier(), " ", "-")+"@"+
 
543
                         (_Server->query_config("smtp_host")||(_Server->query_config("machine")+"."+_Server->query_config("domain")));
 
544
  
 
545
    object group_workroom = group->query_attribute("GROUP_WORKROOM");
 
546
    object modpath=get_module("filepath:tree");
 
547
    headers["X-Steam-Path"] = _Server->query_config("web_server")+
 
548
          modpath->object_to_filename(group_workroom);
 
549
  
 
550
    headers["X-Steam-Annotates"] = _Server->query_config("web_server")+":"
 
551
                                   +(string)group_workroom->get_object_id();
 
552
    return headers;
 
553
}
 
554
 
 
555
/**
 
556
 * send a message to a group
 
557
 *
 
558
 * @author Martin B�hr
 
559
 * @param object group - the group to send the message to
 
560
 * @param string|object msg - the message to send
 
561
 * @return int 1 if successful
 
562
 */
 
563
private int send_group(object group, string|object msg, string|void envFrom)
 
564
{
 
565
    LOG_FORWARD("send_group(%O)\n", group);
 
566
    mapping headers = create_list_headers(group);
 
567
    string rawmessage;
 
568
    object messageobj;
 
569
    if(stringp(msg))
 
570
    {
 
571
        rawmessage = (((array)headers)[*]*": ")*"\r\n" + "\r\n" + msg;
 
572
        messageobj = Messaging.MIME2Message(rawmessage);
 
573
 
 
574
        //string messages come from outside, need to be added to group
 
575
        send_objects( ({ group->query_attribute(GROUP_WORKROOM) }), messageobj);
 
576
    }
 
577
    else if(objectp(msg))
 
578
    {
 
579
        messageobj = Messaging.Message(msg);
 
580
        if(!envFrom)
 
581
            envFrom = "<"+messageobj->sender()+">";
 
582
        LOG_FORWARD("sender is: %O\n", messageobj->sender());
 
583
        messageobj->add_to_header(headers);
 
584
        messageobj->add_to_header(([ "to":headers["List-Id"] ]));
 
585
        rawmessage = (string)messageobj->mime_message();
 
586
    }
 
587
    else
 
588
    {
 
589
        FATAL("Warning! unknown message format: %O", msg);
 
590
        return 0;
 
591
    }
 
592
    
 
593
    //TODO: only send to users that want a copy of group mails
 
594
    array(string) members = group->get_members_recursive(CLASS_USER)->get_user_name();
 
595
    send_message_raw(members, rawmessage, envFrom);  
 
596
    
 
597
    return 1;
 
598
}
 
599
 
 
600
/**
 
601
 * send a message to a subgroup
 
602
 *
 
603
 * @author Martin B�hr
 
604
 * @param object group - the group to send the message to
 
605
 * @param object parent - the group that the message was initially sent to
 
606
 * @param string msg - the message to send
 
607
 * @return int 1 if successful
 
608
 */
 
609
private int send_subgroup(object group, object parent, string msg, string envFrom)
 
610
{
 
611
  mapping headers = ([]);
 
612
  headers["X-sTeam-Subgroup"] = group->get_identifier();
 
613
  msg = (((array)headers)[*]*": ")*"\r\n" + "\r\n" + msg;
 
614
 
 
615
  //TODO: only send to users that want a copy of group mails
 
616
  array(string) members = group->get_members(CLASS_USER)->get_user_name();
 
617
  send_message_raw(members, msg, envFrom);  
 
618
  
 
619
  array subgroups = group->get_sub_groups();
 
620
  foreach(subgroups;; object subgroup)
 
621
    send_subgroup(subgroup, parent, msg, envFrom);
 
622
}
 
623
 
 
624
 
 
625
/**
313
626
 * send a simple message (subject & text) to multiple recipients
314
627
 *
315
628
 * @author <a href="mailto:sepp@upb.de">Christian Schmidt</a>
333
646
        send_local(asLocal,msg);
334
647
    else destruct(msg);
335
648
 
 
649
    asRemote = Array.uniq(asRemote);
 
650
    send_remote(asRemote, rawText, sSender);
 
651
    return 1;
336
652
    for(int i=0;i<sizeof(asRemote);i++)
337
653
        send_remote(asRemote[i],rawText,sSender);
338
654
        
357
673
            result+=({target[i]});
358
674
            continue;
359
675
        }
 
676
        // FIXME: this is dead code! all groups should have been removed by now.
360
677
        object tmp=MODULE_GROUPS->lookup(target[i]);
361
678
        if(objectp(tmp))
362
679
        {
389
706
            object target=_Database->find_object(oid);
390
707
            if(!objectp(target)) return 0; //invalid object-id, do nothing
391
708
//            msg->grant_access(target->query_attribute(OBJ_OWNER));
392
 
            msg->this()->set_acquire(target); //"inherit" access-rights of parent object
 
709
            msg->this()->set_acquire(target); 
393
710
            Messaging.BaseMailBox box = Messaging.get_mailbox(target);
394
711
            if(objectp(box)) //target can be accessed as mailbox
395
712
                box->add_message(msg);
412
729
    
413
730
    int result=1; //success
414
731
 
 
732
    // FIXME: expand_local_addresses should not be needed anymore:
415
733
    array(string) asLocal=expand_local_addresses(target); //resolve aliases & forwards
416
 
    if(sizeof(asLocal)==0) return 0;
417
734
    LOG_FORWARD("expanded local adresses are:%O",asLocal);
 
735
 
418
736
    for(int i=sizeof(asLocal)-1;i>0;i--) //duplicate message if more than one recipient
419
737
    {
420
738
        Messaging.Message copy=msg->duplicate();
448
766
 * @param string|void envFrom - the sender-value of the SMTP-envelope
449
767
 * @return int 1 if successful, 0 if not
450
768
 */
451
 
private int send_remote(string address, string rawText, string envFrom)
 
769
private int send_remote(string|array address, string rawText, string envFrom)
452
770
{
453
771
    string fixed;
 
772
    if( arrayp(address) && sizeof(address)==0 ) return 1;
 
773
    if( stringp(address) && strlen(address) == 0 ) return 1;
 
774
 
454
775
    if( sscanf(envFrom,"%*s<%s>",fixed) == 0 )
455
776
    {
456
777
        LOG_FORWARD("send_remote: illegal envFrom! : "+envFrom);
457
778
        return 0;
458
779
    }
459
 
    get_module("smtp")->send_mail_raw(address, rawText, fixed);
460
 
    LOG_FORWARD("Message delivered to " + address);
 
780
    int l;
 
781
    if ( arrayp(address) && (l=sizeof(address)) > 10 ) {
 
782
        for ( int i = 0; i < sizeof(address); i+=10 ) {
 
783
            array users;
 
784
            if ( i + 10 >= l )
 
785
                users = address[i..];
 
786
            else
 
787
                users = address[i..i+9];
 
788
            get_module("smtp")->send_mail_raw(users, rawText, fixed);
 
789
            LOG_FORWARD("Message chunked delivered to "+sprintf("%O", users));
 
790
        }
 
791
    }
 
792
    else {
 
793
        get_module("smtp")->send_mail_raw(address, rawText, fixed);
 
794
        LOG_FORWARD("Message delivered to " + sprintf("%O", address));
 
795
    }
 
796
    
461
797
    return 1;
462
798
}
463
799
 
464
800
/**
465
 
 * add an alias to system-aliases
466
 
 * if an alias with the given name already exists, the alias
467
 
 * will point to a list of targets; if you want to replace an alias
468
 
 * completely, you'll have to delete it first
 
801
 * Adds an alias to the system-aliases.
 
802
 * If an alias with the given name already exists, the alias
 
803
 * will point to a list of targets. The target will be added to the
 
804
 * alias if it hasn't been added before. If you want to replace an alias
 
805
 * completely, you'll have to delete it first.
469
806
 *
470
807
 * @author <a href="mailto:sepp@upb.de">Christian Schmidt</a>
471
808
 * @param string alias - the name of the alias to add
475
812
 */
476
813
int add_alias(string alias, string target)
477
814
{
 
815
  if ( (arrayp(mAliases[alias]) && search(mAliases[alias], target)>=0) )
 
816
    return 1;  // target was already set for that alias
 
817
 
 
818
    if ( !arrayp(mAliases[alias]) )
 
819
        mAliases[alias] = ({ });
 
820
 
478
821
    mAliases[alias]+=({target});
479
822
    require_save();
480
823
    return 1;
514
857
 */
515
858
int add_forward(object user, string forward, int|void no_more)
516
859
{
 
860
    LOG_FORWARD("adding forward for %s:%s", user->get_user_name(), forward);
 
861
    if ( ! stringp(forward) ) {
 
862
      LOG_FORWARD("invalid forward: %O", forward);
 
863
      return 0;
 
864
    }
 
865
 
517
866
    if(intp(no_more) && no_more==1) forward="/"+forward;
518
867
    if(user->get_object_class() && CLASS_USER)
519
868
    {
520
869
        string name=user->get_identifier();
521
870
        if ( forward == name )
522
871
          steam_error("add_forward: Unable to resolve forward to itself !");
 
872
#if 0
 
873
        if(!mForwards[name]) //new user may be in groups we are not listening to
 
874
        {
 
875
          foreach(get_user_groups(user);; object group)
 
876
          {
 
877
            if(!mListeners[group])
 
878
              listen_annotations(group);
 
879
          }
 
880
        }
 
881
#endif 
 
882
        if ( mForwards[name] && search( mForwards[name], forward ) >= 0 ) {
 
883
          LOG_FORWARD("add_forward(%s : %s) : forward already exists",
 
884
                      name, forward);
 
885
          return 0;  // forward already exists
 
886
        }
523
887
        mForwards[name]+=({forward});
524
888
        require_save();
525
889
        return 1;
537
901
 *
538
902
 * @author <a href="mailto:sepp@upb.de">Christian Schmidt</a>
539
903
 * @param object user - the user to remove forwarding for
 
904
 * @param forward - the forward to remove (if not specified, all forwards
 
905
 *   for that user will be removed)
540
906
 * @return int 1 if successful, 0 otherwise
541
907
 */
542
 
int delete_forward(object user)
 
908
int delete_forward(object user, void|string forward)
543
909
{
544
 
    if(user->get_object_class() && CLASS_USER)
545
 
    {
546
 
        if(arrayp(mForwards[user->get_identifier()]))
547
 
        {
548
 
            m_delete(mForwards,user->get_identifier());
549
 
            require_save();
550
 
            return 1;
551
 
        }
552
 
        else return 0; //no forward for this user
 
910
  if ( ! objectp(user) || !(user->get_object_class() && CLASS_USER) ) {
 
911
    LOG_FORWARD("delete_forward: invalid user %O", user);
 
912
    return 0;
 
913
  }
 
914
 
 
915
  string name = user->get_identifier();
 
916
  if ( ! arrayp(mForwards[name] ) ) {
 
917
    LOG_FORWARD("delete_forward: user %s has no forwards", name);
 
918
    return 0;  // no forwards for this user
 
919
  }
 
920
 
 
921
  if ( zero_type(forward) ) {  // delete all forwards for user
 
922
    LOG_FORWARD("deleting forwards for %s", name);
 
923
    m_delete(mForwards,name);
 
924
  }
 
925
  else {  // delete single forward
 
926
    LOG_FORWARD("deleting forward %O for %s", forward, name);
 
927
    if ( search( mForwards[name], forward ) < 0 ) {
 
928
      LOG_FORWARD("forward %O not found for %s", forward, name);
 
929
      return 0;
553
930
    }
554
 
    else return 0; //user is no sTeam-user-object
 
931
    mForwards[name] -= ({ forward });
 
932
  }
 
933
  require_save();
 
934
  return 1;
555
935
}
556
936
 
557
937
/**
563
943
 */
564
944
array(string) get_forward(object user)
565
945
{
566
 
    if(user->get_object_class() && CLASS_USER)
 
946
    if(user->get_object_class() & CLASS_USER)
567
947
        return mForwards[user->get_identifier()];
568
948
    else return 0;
569
949
}