LOP/area/
LOP/boards/
LOP/channels/
LOP/clans/
LOP/color/
LOP/councils/
LOP/deity/
LOP/src/specials/
/*****************************************************************************
 * DikuMUD (C) 1990, 1991 by:                                                *
 *   Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen,   *
 *   and Katja Nyboe.                                                        *
 *---------------------------------------------------------------------------*
 * MERC 2.1 (C) 1992, 1993 by:                                               *
 *   Michael Chastain, Michael Quan, and Mitchell Tse.                       *
 *---------------------------------------------------------------------------*
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider.                    *
 *   Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, *
 *         gorog, Grishnakh, Nivek, Tricops, and Fireblade.                  *
 *---------------------------------------------------------------------------*
 * SMAUG 1.7 FUSS by: Samson and others of the SMAUG community.              *
 *                    Their contributions are greatly appreciated.           *
 *---------------------------------------------------------------------------*
 * LoP (C) 2006, 2007, 2008, 2009 by: the LoP team.                          *
 *---------------------------------------------------------------------------*
 *			     Host Log File       			     *
 *****************************************************************************/

#include <ctype.h>
#include <stdio.h>
#include "h/mud.h"

typedef struct iplog_data IPLOG_DATA;
struct iplog_data
{
   IPLOG_DATA *next, *prev;
   char *host;
   char *message;
   time_t mtime;
};

typedef struct hostlog_data HOSTLOG_DATA;
struct hostlog_data
{
   HOSTLOG_DATA *next, *prev;
   IPLOG_DATA *first_information, *last_information;
   char *name;
};

HOSTLOG_DATA *first_hostlog, *last_hostlog;

void free_iplog_data( IPLOG_DATA *iplog )
{
   if( !iplog )
      return;
   STRFREE( iplog->host );
   STRFREE( iplog->message );
   DISPOSE( iplog );
}

void free_iplogs( HOSTLOG_DATA *host )
{
   IPLOG_DATA *iplog, *iplog_next;

   if( !host )
      return;
   for( iplog = host->first_information; iplog; iplog = iplog_next )
   {
      iplog_next = iplog->next;
      UNLINK( iplog, host->first_information, host->last_information, next, prev );
      free_iplog_data( iplog );
   }
}

void free_one_hostlog( HOSTLOG_DATA *host )
{
   if( !host )
      return;
   free_iplogs( host );
   UNLINK( host, first_hostlog, last_hostlog, next, prev );
   STRFREE( host->name );
   DISPOSE( host );
}

void free_all_hostlogs( void )
{
   HOSTLOG_DATA *host, *host_next;

   for( host = first_hostlog; host; host = host_next )
   {
      host_next = host->next;
      free_one_hostlog( host );
   }
}

HOSTLOG_DATA *find_hostlog( char *argument )
{
   HOSTLOG_DATA *host;

   for( host = first_hostlog; host; host = host->next )
   {
      if( host && host->name && argument && !str_cmp( host->name, argument ) )
         return host;
   }

   return NULL;
}

void save_hostlogs( void )
{
   HOSTLOG_DATA *host;
   IPLOG_DATA *iplog;
   FILE *fp;

   if( !first_hostlog )
   {
      remove_file( HOSTLOG_FILE );
      return;
   }
   if( !( fp = fopen( HOSTLOG_FILE, "w" ) ) )
   {
      bug( "%s: Can't open %s for writing.", __FUNCTION__, HOSTLOG_FILE );
      perror( HOSTLOG_FILE );
      return;
   }
   for( host = first_hostlog; host; host = host->next )
   {
      fprintf( fp, "%s", "#HOST\n" );
      fprintf( fp, "Name      %s~\n", host->name );
      for( iplog = host->first_information; iplog; iplog = iplog->next )
         fprintf( fp, "IPLOG     %s~ %s~ %ld\n", iplog->message, iplog->host, iplog->mtime );
      fprintf( fp, "%s", "End\n\n" );
   }
   fprintf( fp, "%s", "#END\n" );
   fclose( fp );
   fp = NULL;
}

void handle_hostlog( const char *message, CHAR_DATA *ch )
{
   HOSTLOG_DATA *host;
   IPLOG_DATA *iplog;

   if( !( host = find_hostlog( ch->name ) ) )
   {
      CREATE( host, HOSTLOG_DATA, 1 );
      if( !host )
      {
         bug( "%s: host is NULL after create.", __FUNCTION__ );
         return;
      }
      host->name = STRALLOC( ch->name );
      LINK( host, first_hostlog, last_hostlog, next, prev );

      CREATE( iplog, IPLOG_DATA, 1 );
      if( !iplog )
      {
         bug( "%s: iplog is NULL after create.", __FUNCTION__ );
         return;
      }
      if( !ch || !ch->desc || !ch->desc->host )
         iplog->host = STRALLOC( "Unknown" );
      else
         iplog->host = STRALLOC( ch->desc->host );
      iplog->mtime = current_time;
      iplog->message = STRALLOC( message );
      LINK( iplog, host->first_information, host->last_information, next, prev );
      save_hostlogs( );
      return;
   }

   /* In order to keep the list smaller we will only keep the last 10 from each ip address ( Keep 9 and then adding 1 to it ) */
   {
      IPLOG_DATA *iplog_next;
      int count = 0;

      for( iplog = host->first_information; iplog; iplog = iplog_next )
      {
         iplog_next = iplog->next;
         if( !ch || !ch->desc || !ch->desc->host )
            continue;
         if( str_cmp( iplog->host, ch->desc->host ) )
            continue;
         if( ++count < 9 )
            continue;
         UNLINK( iplog, host->first_information, host->last_information, next, prev );
         free_iplog_data( iplog );
      }
   }

   CREATE( iplog, IPLOG_DATA, 1 );
   if( !iplog )
   {
      bug( "%s: iplog is NULL after create.", __FUNCTION__ );
      return;
   }

   if( !ch || !ch->desc || !ch->desc->host )
      iplog->host = STRALLOC( "Unknown" );
   else
      iplog->host = STRALLOC( ch->desc->host );
   iplog->mtime = current_time;
   iplog->message = STRALLOC( message );
   /* Always put the new ones at the top of the list when possible */
   if( host->first_information )
   {
      iplog->prev = NULL;
      iplog->next = host->first_information;
      host->first_information->prev = iplog;
      host->first_information = iplog;
   }
   else
      LINK( iplog, host->first_information, host->last_information, next, prev );
   save_hostlogs( );
}

CMDF( do_hsearch )
{
   HOSTLOG_DATA *host;
   IPLOG_DATA *iplog;
   int count = 0;
   bool found = false;

   if( !argument || argument[0] == '\0' )
   {
      send_to_char( "Syntax: hsearch <ip address>\r\n", ch );
      return;
   }

   for( host = first_hostlog; host; host = host->next )
   {
      for( iplog = host->first_information; iplog; iplog = iplog->next )
      {
         if( !str_cmp( iplog->host, argument ) )
         {
            if( !found )
               ch_printf( ch, "Characters accessed from host %s.\r\n", argument );
            found = true;
            ch_printf( ch, "%18s", host->name );
            if( ++count == 4 )
            {
               send_to_char( "\r\n", ch );
               count = 0;
            }
            else
               send_to_char( "  ", ch );
            break;
         }
      }
   }
   if( !found )
      ch_printf( ch, "No characters accessed from host %s.\r\n", argument );
   else if( count != 0 )
      send_to_char( "\r\n", ch );
}

CMDF( do_hlog )
{
   HOSTLOG_DATA *host;
   IPLOG_DATA *iplog;
   int count;

   if( !argument || argument[0] == '\0' )
   {
      for( host = first_hostlog; host; host = host->next )
      {
         ch_printf( ch, "%s:\r\n", host->name );
         count = 0;
         for( iplog = host->first_information; iplog; iplog = iplog->next )
         {
            ch_printf( ch, "   %s on %s from %s\r\n", iplog->message, distime( iplog->mtime ), iplog->host );
            if( count++ == 4 )
               break;
         }
      }
      return;
   }
   if( !( host = find_hostlog( argument ) ) )
   {
      send_to_char( "There is no such hostlog information to display.\r\n", ch );
      return;
   }

   ch_printf( ch, "%s: \r\n", host->name );
   for( iplog = host->first_information; iplog; iplog = iplog->next )
      ch_printf( ch, "   %s on %s from %s\r\n", iplog->message, distime( iplog->mtime ), iplog->host );
}

void fread_hostlog( FILE *fp )
{
   HOSTLOG_DATA *host;
   IPLOG_DATA *iplog;
   const char *word;
   bool fMatch;

   CREATE( host, HOSTLOG_DATA, 1 );
   host->name = NULL;
   host->first_information = host->last_information = NULL;

   for( ;; )
   {
      word = feof( fp ) ? "End" : fread_word( fp );
      fMatch = false;

      switch( UPPER( word[0] ) )
      {
         case '*':
            fMatch = true;
            fread_to_eol( fp );
            break;

         case 'E':
            if( !str_cmp( word, "End" ) )
            {
               LINK( host, first_hostlog, last_hostlog, next, prev );
               return;
	    }
	    break;

         case 'I':
            if( !str_cmp( word, "IPLOG" ) )
            {
               CREATE( iplog, IPLOG_DATA, 1 );
               if( !iplog )
               {
                  bug( "%s: iplog is NULL after create.", __FUNCTION__ );
                  fread_flagstring( fp );
                  fread_flagstring( fp );
                  fread_number( fp );
                  continue;
               }
               iplog->message = fread_string( fp );
               iplog->host = fread_string( fp );
               iplog->mtime = fread_time( fp );
               LINK( iplog, host->first_information, host->last_information, next, prev );
               fMatch = true;
               break;
            }
            break;

         case 'N':
            KEY( "Name", host->name, fread_string( fp ) );
            break;
      }

      if( !fMatch )
      {
         bug( "%s: no match: %s", __FUNCTION__, word );
         fread_to_eol( fp );
      }
   }
   free_one_hostlog( host );
}

void load_hostlog( void )
{
   FILE *fp;

   first_hostlog = last_hostlog = NULL;
   if( !( fp = fopen( HOSTLOG_FILE, "r" ) ) )
      return;
   for( ;; )
   {
      char letter;
      char *word;

      letter = fread_letter( fp );
      if( letter == '*' )
      {
         fread_to_eol( fp );
         continue;
      }
      if( letter != '#' )
      {
         bug( "%s: # not found.", __FUNCTION__ );
         break;
      }
      word = fread_word( fp );
      if( !str_cmp( word, "HOST" ) )
      {
         fread_hostlog( fp );
         continue;
      }
      else if( !str_cmp( word, "END" ) )
         break;
      else
      {
         bug( "%s: bad section (%s).", __FUNCTION__, word );
         fread_to_eol( fp );
         continue;
      }
   }
   fclose( fp );
   fp = NULL;
}