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/
//#pragma save_binary
//      File    :  /adm/daemons/network/nntp.c
//     Creator  :  Leto@Earth (Earth  Meister) [29/03/94]
//               Drizzt@TMI-2 (Socket Meister) [01/04/95]
// 
 
#include <priv.h>
#include <uid.h>
#include <config.h>
#include <net/nntp.h>
#include <net/socket.h>
#include <net/daemons.h>
#include <net/macros.h>
#include <mudlib.h>
 
inherit DAEMON ;
#define DEBUG(x) tell_object(find_player("leto"),"NNTP:"+x)

 
int mysocket;
mapping sockets;
 
/* Retrieval prototypes */
 
string get_article(string message_id);
string get_head(string message_id);
string get_body(string message_id);
int check_article(string message_id);
string nntp_time(int mudtime);
void nntp_post(mapping msg,string board_name, string poster);
 
/* Networking prototypes */
 
void read_callback(int fd, string str);
void close_callback(int fd);
void write_callback(int fd);
void listen_callback(int fd);
void write_callback(int fd);
 
/* NNTP commands prototypes */
 
void cmd_list(int fd, string rest);
void cmd_quit(int fd);
void cmd_get(int fd, string rest);
void cmd_next(int fd);
void cmd_stat(int fd, string rest);
void cmd_body(int fd, string rest);
void cmd_head(int fd, string rest);
void cmd_help(int fd);
void cmd_slave(int fd);
void cmd_newnews(int fd, string parsedate);
void cmd_article(int fd, string mesg_id);
void cmd_ihave(int fd, string mesg_id);
 
/*              -=] Begin Article Manipulation Section [=-                 */
 
/* 
        Name: get_article()
     Purpose: Returns an article with given id, and newsgroup
*/
string get_article(string message_id) {
   string article;
   
   DEBUG("IN GET ARTICLE");
   // Just in case, let's check if we have one.
   if (check_article(message_id)) {
      DEBUG("file:"+NNTP_DIR+"/"+message_id);
      article = read_file(NNTP_DIR+"/"+message_id);   
      return article;  
   } else 
        return("999 Unknown message-id or group.\n"); // 999 is wrong 
        // You shouldn't ask for something that's not there
}
 
/*
        Name: check_article()
     Purpose: To check for an existance of an article
*/
int check_article(string message_id) {
                // Check to see if we have a certain article.
                // To reject a duplicate article from an nntp server
 
    // first check if we have that newsgroup 
    DEBUG("IN CHECKARTICLE:group=");
    if (!directory_exists(NNTP_DIR)){
        // Looks like we dont have it
        DEBUG("newsgroup DOESN'T exist:\n");
        DEBUG(NNTP_DIR);
        return 0;
    } else if (file_exists(NNTP_DIR+"/"+message_id)) {
        DEBUG("article exists\n");
        return 1;
    }
    else return 0; // group ok, no such article though
}
 
/*              -=] Begin NNTP utilities Section [=-                      */
 
/*
        Name: nntp_time()
     Purpose: To make a time format suitable for NNTP usage
*/
 
string nntp_time(int mudtime){
        string wrong,day,monthname,month,time,year;
        
        wrong = ctime(mudtime);
        sscanf(wrong,"%s %s  %s %s %s",day,monthname,month,time,year);
        if (!month) { 
                sscanf(wrong,"%s %s %s %s %s",day,monthname,month,time,year);
        }
        return (day+", "+month+" "+monthname+" "+year+" "+time+" "+TIME_ZONE);
}
 
/*
        Name: nntp_post()
     Purpose: Write an article to file
              Use RFC822, and RFC950
*/
void nntp_post(mapping msg, string board_name, string poster) {
        string NNTP_OUT;
 
        DEBUG("Intermud posting:"+NNTP_DIR + board_name+"/"+(string)msg["id_long"]);
        NNTP_OUT = NNTP_DIR + board_name+"/"+(string)msg["id_long"];
        write_file(NNTP_OUT,"Path: "+"@"+capitalize(MUD_NAME)+".org!"+poster+"\n");
        write_file(NNTP_OUT,"From: "+msg["poster"]+".org\n");
        write_file(NNTP_OUT,"Newsgroups: "+board_name+"\n");
        write_file(NNTP_OUT,"Subject: "+msg["title"]+"\n");
        write_file(NNTP_OUT,"Message-ID: "+msg["id_long"]+"\n");
        write_file(NNTP_OUT,"Date: "+NNTP_D->nntp_time(msg["time"])+"\n");
        write_file(NNTP_OUT,"Reply-to: "+NNTP_ACCOUNT+ "\n");
        write_file(NNTP_OUT,"Distribution: "+ "World"+"\n");
        write_file(NNTP_OUT,"Organisation: A mud called "+capitalize(MUD_NAME)+"\n");
        write_file(NNTP_OUT,"Comment: For problems contact "+ADMIN_EMAIL+"\n");
        write_file(NNTP_OUT,"NNTP-POSTING-HOST: "+"LPNNTP version " +           
                NNTP_VERSION + " at "+ capitalize(MUD_NAME)+"\n");
        write_file(NNTP_OUT,"\n");
        write_file(NNTP_OUT,msg["body"]);
        write_file(NNTP_OUT,".\n"); 
} 
 
/*              -=] Begin Socket Section [=-                               */
/* 
    Drizzt Note: 
        For right now, we will not make this NM compatable.. #1, I do not
        Know NM code, and #2, they can do it themselves (or someone who 
        wants to make a bi-compatable version (Leto)
*/  
 
/*
        Name: create()
     Purpose: Setup sockets, etc.  Initialize object variables
*/
 
create(){
        int i;
 
        mysocket = 0;
        sockets = ([]);
        /* Sockets looks like:
                ([ fd : logintime ])
                                     */
        mysocket = socket_create(STREAM, "read_callback", "close_callback");
        if(mysocket < 0){
                log_file("nntpd", sprintf("%25-s: %s\n",
                        "Create Error",socket_error(mysocket)));
                return 0;
        }
        i = socket_bind(mysocket, PORT_NNTP);
        if(i < 0){
                socket_close(mysocket);
                log_file("nntpd",sprintf("%25-s: %s\n",
                        "Bind Error",socket_error(i)));
                return 0;
        }
        i = socket_listen(mysocket, "listen_callback");
        if(i < 0){        
                socket_close(mysocket);
                log_file("nntpd",sprintf("%25-s: %s\n",
                        "Listen Error",socket_error(i)));
                return 0;
        }
}
 
/*
        Name: close_callback()
     Purpose: Closes a connection with a socket
*/
 
void close_callback(int fd) {
   log_file("nntpd", sprintf("%25-s: %23-s %s\n",
        "Close",socket_address(fd),(time() - sockets[fd])/60+" minutes logged"));
    socket_close(fd);
    map_delete(sockets, fd);
}
 
/* 
        Name: listen_callback()
     Purpose: To listen for incoming connections, and send them on their
              way when they get here
*/
 
void listen_callback(int fd){
        int socket;
 
        socket = socket_accept(fd, "read_callback", "write_callback");
        if(socket < 0){
                log_file("nntpd",sprintf("%25-s: %s\n",
                        "Accept Error",socket_error(socket)));
                return;
        }
        sockets += ([ socket : time() ]);
        write_callback(socket);
}
 
/*
        Name: write_callback()
     Purpose: Dont really know the purpose of this in a "listening" object
              In clients its used to tell the object when its ok to write
              to the socket
*/
void write_callback(int fd){
        socket_write(fd, "201 "+capitalize(MUD_NAME)+
                "LPNNTP server ready (No Posting Yet [Kick Leto])\n");
        log_file("nntpd",sprintf("%25-s: %s\n",
                "Accepted",socket_address(fd)));
}
 
/*
        Name: read_callback()
     Purpose: Called whenever the server receives information from the
              Client
*/
void read_callback(int fd, string str) {
        string cmd, rest, mesg_id, newsgroup;
 
        if(!str || str == "") {
                socket_write(fd, NNTP_BAD_CMD);        
                return;
        }
   //str = replace_string(str,"\r","\n");
    str = explode(replace_string(str, "\r", ""), "\n")[0];
        DEBUG("NNTP:"+str+"\n");
        sscanf(str, "%s %s", cmd, rest);
        if (!cmd || (cmd=="")) cmd = str;
      DEBUG("nntpcmd="+cmd+".\n");
    DEBUG("nntprest="+rest+".\n");
        switch(lower_case(cmd)) {
                case "quit": cmd_quit(fd);return; 
                case "list": cmd_list(fd,rest); return;
                case "newnews": cmd_newnews(fd,rest); return;
                case "help": cmd_help(fd); return;
                case "article": cmd_article(fd, rest); return;
                case "head": cmd_head(fd, rest); return;
                case "body": cmd_body(fd, rest); return;
                case "ihave": cmd_ihave(fd, rest); return;
                case "stat": cmd_stat(fd, rest); return;
                case "next": cmd_next(fd); return;
                case "slave": cmd_slave(fd); return;
                default: socket_write(fd, "500 Command unrecognized.\n"); return;
        }
}
 
/*
        Name: cmd_next()
     Purpose: To return the next mesg_id header
*/
 
void cmd_next(int fd) {
        // this should display the next mesg_id header as follows
        // "223 <article#, local# to the server> <mesg_id> "+
        // "Article retrieved; request text separately.\n"
        return ;
}
 
/*
        Name: cmd_body()
     Purpose: Return the body of an article
*/
void cmd_body(int fd, string rest) {
        if(!check_article(rest)) {
                socket_write(fd,"430 No article by "+rest+", sorry.\n");
                return;
        } else {
                socket_write(fd,
             "222 0 "+rest+"Article retrieved, body follows.\n");
                get_body(rest);
                return;
        }
}
       
/*
        Name: cmd_head()
     Purpose: Return the headers of an article
*/
void cmd_head(int fd, string rest) {
 
        if(!check_article(rest)) {
                socket_write(fd,"430 No article by "+rest+", sorry.\n");
                return;
        } else {
                socket_write(fd,
              "221 0 "+rest+"Article retrieved, head follows.\n");
                get_head(rest);
                return;
        }
}
 
/*
        Name: cmd_article
     Purpose: return both headers, and body of an article
*/
        
void cmd_article(int fd, string rest) {
 
        if(!check_article(rest)) {
                socket_write(fd,"430 No article by "+rest+", sorry.\n");
                return;
        } else {
                socket_write(fd,
      "220 0 "+rest+"Article retrieved, head and body folow.\n"+
               get_article(rest) );
                return;
        }
}       
 
/*
        Name: cmd_stat()
     Purpose: To retrieve an article, and possible ensure its existance
*/
void cmd_stat(int fd, string rest) {
        // return current mesg id
        if(!check_article(rest)) {
                socket_write(fd,"430 No article by "+rest+", sorry.\n");
                return;
        } else {
                socket_write(fd,
                        "203 0 "+rest+" Article retrieved, request text separately.\n");
                return;
        }
}
 
/*
        Name: cmd_slave()
     Purpose: To write about leto's sex life :)
*/
void cmd_slave(int fd) {
DEBUG("In slave cmd\n");
        socket_write(fd,
        "202 Kinky, kinky.  I don't support such perversions.\n");
        return;
}
 
/*
        Name: cmd_help()
     Purpose: List help (probably for people telneting to server)
*/
void cmd_help(int fd) {
        socket_write(fd,
                "100 This server accepts the following commands:\n"+
                "ARTICLE     BODY         GROUP\n"+
                "HEAD        LAST         LIST\n"+
                "NEXT        POST         QUIT\n"+
                "STAT        NEWGROUPS    HELP\n"+
                "IHAVE       NEWNEWS      SLAVE\n"+
                "\n"+
                "Send bug reports to Leto@Tmi-2   (earth@borg.xs4all.nl)\n"+
                "                    Drizzt@Tmi-2 (jtravis@herbie.unl.edu)\n"+
                ".\n");
        return;
}
 
/*
        Name: cmd_list()
     Purpose: To list the NNTP groups currently available
*/
void cmd_list(int fd, string rest) {
 
        //if (!rest || rest=="")  
                //socket_write(fd,  implode(NNTP_GROUPS, "\n")); 
          shout("dummy\n");
 
        return;
}
 
/*
        Name: cmd_quit()
     Purpose: To disconnect the client from the server
*/
void cmd_quit(int fd) {
        socket_write(fd, "205 Thanks for using "+ capitalize(MUD_NAME) +
                "'s LPnntp, Goodbye\n" );
        close_callback(fd);
        return;
}
 
void cmd_newnews(int fd, string parsedate) {
 
	int date,time;
	sscanf(parsedate,"%d %d",date,time);
 
   // format is  ddmmyy hhmmss  in two ints
return;
}
 
/*
void cmd_article(int fd, string mesg_id) {
 
		if(!check_article(mesg_id)) {
			socket_write(fd,"430 No article by "+mesg_id+", sorry.\n");
			return;
		} else {
		socket_write(fd,
		// 221 is a wild guess, needs to be checked !! Leto
			 "221 0 "+mesg_id+"Article retrieved, body follows.\n"+
			 get_article(mesg_id));
		return;
		}
}
*/
void cmd_ihave(int fd, string mesg_id) {
 
   //check existence of mesg_id, and ask article if not
   //here, else, tell em we don't want it
	 return;
}