tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
// file: mailbox.
// By inspiral, ported from Pinkfish ??
// No, originally written by Huthar, rewritten by Inspiral.
// Leto added checks for when there is prev_obj anymore with never drivers 
// Leto changed logging to us elogs.h
#pragma save_binary
#define LOCAL_TZONE	"CET"

 
#define MONITOR_TIME 2500

#include <uid.h>
#include <config.h>
#include <mailer.h>
#include <net/macros.h>
#include <logs.h>
 
#define QUERY_NAME link_data( "name" )  // XXX: for TMI 1.0 mudlibs
 
// The following are the variables that will be saved as the datafiles
mapping         *mailbox, my_groups;
static  string  file, *dir_list;
static  int     maxmsg, dir_idx;
 
 
int
valid_access( string frm ) {
  string accessor;
  mixed owner;
  
  if( previous_object() ) {
    if( geteuid( previous_object() ) == ROOT_UID )
      return 1;
  
// Next two ifs check to see if this is a trusted mailer
    accessor = base_name( previous_object() );
 
    if( member_array( accessor, TRUSTED_MAILERS ) > -1 )
      return 1;
  }
  
// If a frm == 0 then this is a read operation. If the player may
// always read mail if he is the owner of the box.
  if( file )  {
    owner = explode( file, "/" );
    if ( !owner || !owner[<1] )
      return 0;
    owner = owner[<1];

    if ( (string)this_player(1)->QUERY_NAME == owner && !frm )
      return 1;
  }
  
// If frm != 0 then make sure that frm == this_player(1) to
// prevent forgeries...
  if( frm == ( string ) this_player( 1 ) -> QUERY_NAME )
    return 1;
  
  return 0; // Not a legal operation!
} // valid_access
 
 
create() {
  seteuid( ROOT_UID );
  mailbox = ({  });
  maxmsg = 0;
  file = 0;    
  dir_idx = sizeof( dir_list = get_dir( MBOXDIR ) ) - 1;
// Mobydick commented out the monitor call to save CPU and file access.
// This, he thinks, is probably something we should run only when we
// think a lot of mailboxes have had users deleted out from under them..
// Right after a purge, perhaps.
// call_out( "monitor_boxes", 10 );
} // create
 
 
void
update_box( string owner ) {
  if( file != user_mbox_file( owner ) ) {
    if( file ) {
      if( sizeof( mailbox ) )
         save_object( file );
      else rm( file + __SAVE_EXTENSION__ );
    }
    
    file = user_mbox_file( owner );
    mailbox = ({  });    if( file_exists( file + __SAVE_EXTENSION__ ) )
       restore_object( file );
    if( !mailbox )
      mailbox = ({  });
    maxmsg = sizeof( mailbox );
  }
} // update_box
 
 
int remote_mail( string rcvr, mapping data ) {
  string own, mud;
  
  if( sscanf( rcvr, "%s@%s", own, mud ) != 2 )
    return 0;
 
  if( htonn( mud ) == mud_nname() )
    return 0;
 
/*
  if( previous_object() != find_object_or_load( NETMAIL_D ) )
     NETMAIL_D -> push_mail( copy( data ) );
*/
  return 1;
} // remote_mail
 
 
varargs void
remove_message( string owner, int num ) {
  update_box( owner );
  
/*
  if( !valid_access( 0 ) )  {
    printf( "Illegal access attempt to mailer_d.\n" );
    return;
  }
*/
  if( num < 0 || num >= maxmsg )
    return;
// remove msg & decrement maxmsg
  MAILMESG_D -> delete_mesg( mailbox[num]["idx"], owner );
  mailbox = mailbox[0 .. num - 1] + mailbox[ num + 1 ..--maxmsg];
} // remove_message
 
 
int
add_message( string owner, mapping data ) {
  string own, mud;
  
  owner = lower_case( owner );
  if( remote_mail( owner, data ) )
    return 1;
 
  if( !user_exists( owner ) )
    return 0;
  update_box( owner );
 
  if( !valid_access( data["from"] ) )  {
    printf( "Illegal access attempt to mailer_d.\n" );
    return 0;
  }
  mailbox += ({ data });
  maxmsg++;
  update_box( owner );
  return 1;
} // add_message
 
 
mixed
mail_status( string owner ) {
  int cnt, i;
  
  update_box( owner );
  i = maxmsg;
 
  while( i-- )  {
    if( !( mailbox[i]["flags"]&MAIL_READ ) )
      cnt++;
  }
  return([  "unread" : cnt, "total" : maxmsg  ]);
} // mail_status
 
 
void
set_flags( string owner, int num, int flags ) {
  update_box( owner );
 
  if( !valid_access( 0 ) )  {
    printf( "Illegal access attempt to mailer_d.\n" );
    return;
  }
  if( num < 0 || num >= maxmsg )
    return;
  if( !mailbox[num]["idx"] ) mailbox[num]["idx"] = mailbox[num]["date"];
  mailbox[num]["flags"] = flags;
} // set_flags
 
 
void
biff( string str, string from, string subject ) {
  string        grp, *grparr;
  object        ob;
  int   i;
  
  if( sscanf( str, "(%s)", grp ) )  {
    grparr = ( ( mapping ) GROUP_OB -> query_groups() )[grp];
    i = sizeof( grparr );
    while( i-- )
      biff( grparr[i], from, subject );
    return;
  }
  
  if( ( ob = find_player( str ) ) && ( ob -> getenv( "mail_notification" ) ) )
    message( "system", sprintf( "\
      \n>>> New mail has arrived from: %s.\n>>> Subject: %s\n",
      capitalize( from ), subject ), ob );
} // biff
 
 
string *
expand_to( mixed str ) {
  string grp, *rtn;
  int i, max;
  mapping grps;
  string t1, t2;
  
  rtn = ({  });
  i = sizeof( str );
 
  while( i-- )  {
    if( !str[i] )
      continue;
    str[i] = lower_case( str[i] );
 
    if( sscanf( str[i], "%s@%s", t1, t2 ) == 2 )    {
      rtn += ({ str[i] });
      continue;
    }
 
    if( sscanf( str[i], "(%s)", grp ) )    {
      grps = ( mapping ) GROUP_OB -> query_groups();
      if( sizeof( grps[grp] ) )
        rtn += expand_to( grps[grp] );
      else
        printf( "Group `%s' doesn't exist.\n", grp );
      continue;
    }
    if( user_exists( str[i] ) )
      rtn += ({ str[i] });
    else
      printf( "User `%s' not found.\n", str[i] );
  }
  return rtn;
} // expand_to
 
 
string *
send_mail( mapping newmsg ) {
  int   i, j;
  string        *tmpto, *rtn, previous;
  mapping       bouncemsg;
  string        mesg;
  
  newmsg += ([ ]);
  previous = base_name( previous_object() );
 
  if( !valid_access( newmsg["from"] ) ) {
        log_file( "MAILER_LOG", "Illegal access by: " + 
                identify( previous_object() ) + "\n" );
        return ({ });
  }
 
  tmpto = expand_to( newmsg["to"] ) + expand_to( newmsg["cc"] );
  tmpto = uniq_array( tmpto );
  
  i = sizeof( tmpto );
  rtn = allocate( i );
  j = 0;
 
  while( i-- ) {
        if( !remote_mail( tmpto[i], newmsg ) )
            rtn[j++] = tmpto[i];
  }
  
  if( j != sizeof( tmpto ) ) 
     if( previous_object() != find_object_or_load( NETMAIL_D ) )
        NETMAIL_D -> push_mail( copy( newmsg ) );

  rtn = rtn[0..j - 1];
  
  mesg = copy( newmsg["message"] );
  map_delete( newmsg, "message" );

  newmsg["idx"] = (int) MAILMESG_D -> add_mesg( rtn, mesg );

  while( j-- )  {
    // Messages coming in from NETMAIL_D look like "<user>@Tabor"
    sscanf( rtn[j], "%s@%*s", rtn[j] );
 
        // If we fail sending the message to the user on this mud, then
        // we prepare and send out a bounced message report.
    if( !add_message( rtn[j], newmsg ) ) {
		bouncemsg = allocate_mapping( 6 );
           // We have to make a copy because we're still needing newmsg 
           // fully intact, and here, we plan towmsg );
           bouncemsg["message"] = "> " + 
                replace_string( mesg, "\n", "\n> " );
           bouncemsg[ "message" ] =
                "Date: " + ctime( time() ) + " " LOCAL_TZONE + ".\n" +
                "Message from POSTMASTER@" + Mud_name() + ":\n" +
                "Unable to send to user: " + capitalize( rtn[j] ) +
		"@" + Mud_name() + ".\n\n" +
                read_file( MAIL_BOUNCE_FILE ) +
                "Original Subject: " + newmsg["subject"] + "\n" +
                bouncemsg[ "message" ] +
                "\n**** End of Message ****\n";
           bouncemsg[ "subject" ] = "User \"" + rtn[j] + "\" doesn't exist.";
           bouncemsg[ "date" ] = time();
           map_delete( bouncemsg, "cc" );
           bouncemsg[ "to" ] = ({ newmsg[ "from" ] });
           bouncemsg[ "from" ] = "POSTMASTER";
       log_file( "MAILER_LOG", sprintf(
          "%s unable to send to %s\n", newmsg["from"], rtn[j] ) );
           NETMAIL_D -> push_mail( bouncemsg );
           continue;
        }
 
    call_out( "biff", 0, rtn[j], newmsg["from"], newmsg["subject"] );
  }
 
  // If i > j, then there's a mud to send to.  First, make sure
  // we aren't the netmail daemon sending us a message to process.
  // We stick this at the end because we don't have to send it immediately,
  // and because otherwise, since netmail does some funky things with
  // the mapping, we'd have to copy() the mapping before we sent if off.
 if( ( previous != NETMAIL_D ) && ( i > j ) )
        NETMAIL_D -> push_mail( newmsg );
 
  return tmpto;
} // send_mail
 
 
int valid_shadow() {
  return 1;
}
 
 
void flush_files( mapping groups ) {
   if( !file ) return;
   if( sizeof( mailbox ) )
      save_object( file );
   else
      if( file_exists( file + __SAVE_EXTENSION__ ) )
         rm( file + __SAVE_EXTENSION__ );
}
 
int
fix_message( string owner, mapping data ) {
  string own, mud;
  string mesg;
  string *tmpto;
  
  owner = lower_case( owner );
  if( !user_exists( owner ) )
    return 0;
  update_box( owner );
 
  mesg = copy( data["message"] );
  tmpto = expand_to( data["to"] ) + expand_to( data["cc"] );
  tmpto = uniq_array( tmpto );
  tmpto = filter_array( tmpto, "not_saved", this_object() );
  data["idx"] = (int) MAILMESG_D -> add_mesg( tmpto, mesg );
  map_delete( data, "message" );
  mailbox += ({ data });
  maxmsg++;
  update_box( owner );
  MAILMESG_D -> save_mesg();
  return 1;
} // fix_message
 
int not_saved( string name ) {
  if( strsrch( name, "@" ) == -1 ) 
     if( user_exists( lower_case( name ) ) )
        return 1;
  return 0;
}
 
static void
remove_box( string owner ) {
   int i;
 
   update_box( owner );
   i = sizeof( mailbox );
   while( i-- ) 
      remove_message( owner, i );
   rm( user_mbox_file( owner ) + __SAVE_EXTENSION__ );
}
    
int monitor_boxes() {
  int i, out;
  string *names;

  names = get_dir( MBOXDIR + "/" + dir_list[dir_idx] + "/" );
  i = sizeof( names );

  while( i-- ) {                                
     names[i] = replace_string( names[i], __SAVE_EXTENSION__, "" );
     if( !user_exists( names[i] ) ) {
         out++;
  message( "debug", "notuser: " + names[i] + "\n",
		find_player( "inspiral" ) );
         remove_box( names[i] );
         continue;
     }
     call_out( "clean_box", 4+(3*i), names[i] );
  }  
 
  if( --dir_idx < 0 )
      dir_idx = sizeof( dir_list = get_dir( MBOXDIR ) ) - 1;
 
  call_out( "monitor_boxes", MONITOR_TIME );
  return out;
}                                           
 
int clean_box( string owner ) {
  int i, j;

  update_box( owner );
  i = sizeof( mailbox );
  while( i-- ) {
     if( !file_exists( mail_mesg_file( mailbox[i]["idx"] ) + 
                        __SAVE_EXTENSION__ ) ) {
        remove_message( owner, i );
        j++;
     }
  }
  return j;
}

string *verify_mbox( string *whom, int idx ) {
  int i, j;
  string *tmp;

  tmp = ({ });

  i = sizeof( whom );
  while( i-- ) { 
    update_box( whom[i] );
    j = sizeof( mailbox );
    while( j-- )
       if( mailbox[j]["idx"] == idx ) {
           tmp += ({ whom[i] });
       }
  }
  return tmp;
}

/* EOF */