/*
Program: irc2html
Program by: lockdown (www.lockeddown.net)
Date: November 9, 2001

This program will logon to an irc server and join the specified channels and log that # to an html file.  It is pretty crude!

BUGS: Joins and parts will show up but a quit will not.  This program also depends on browsers recognizing the <xmp> tag.  If a user does </xmp> or more specifically /xmp the / will be replaces with \.  Also on some server like unreal when the bot joins the line is split up so the bot name will not appear but garbage will instead, usually a # name and this should be harmless.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>

#define REALNAME "www.lockeddown.net/code.html"
#define BUF_SIZE 512

typedef struct chan
{
  struct chan *next;
  int file;
  char channame[30];
  char chancap[30];
} chanstruct;

chanstruct *add_entry(int i,int sockfd,char chan[],chanstruct *head);
int useage(char *name);

int main(int argc,char *argv[])
{
  int i,sockfd,numbytes,j;
  int port = atoi(argv[3]);
  char buf[BUF_SIZE +1];
  char out[BUF_SIZE +100];
  char name[30],data[BUF_SIZE +1];
  char *msg,*match;
  chanstruct *chanfo=NULL,*head=NULL;
  struct hostent *host;
  struct sockaddr_in server;

  if(argc < 5)
  {
    useage(argv[0]);
    return 1;
  }

  if((host=gethostbyname(argv[2]))==NULL)
  {
    perror("gethostbyname");
    return 1;
  }

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
  {
    perror("socket");
    return 1;
  }

  memset(&server,'\0',sizeof(server));
  server.sin_family=AF_INET;
  server.sin_port=htons(port);
  server.sin_addr = *((struct in_addr *)host->h_addr);

  if(connect(sockfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1)
  {
    perror("connect");
    return 1;
  }

  msg=(char *)malloc(strlen(argv[1])+8);
  snprintf(msg,strlen(argv[1])+8,"NICK %s\r\n",argv[1]);
  write(sockfd,msg,strlen(msg));
  realloc((char *)msg,strlen(REALNAME)+strlen(argv[1])+strlen(argv[2])+22);
  snprintf(msg,(strlen(REALNAME)+strlen(argv[1])+strlen(argv[2])+22),
		"USER %s 127.0.0.1 %s :%s\r\n",argv[1],argv[2],REALNAME);
  write(sockfd,msg,strlen(msg));
  free(msg);

  for(i=4;i<argc;i++)
  {
    head =add_entry(i,sockfd,argv[i],head);
  }
  while(1)
  {
    if((numbytes=recv(sockfd,buf,BUF_SIZE,0))==-1)
    {
      perror("recv");
      return 1;
    }
    if(strstr(buf,"PRIVMSG")!=NULL)
    {
      chanfo=head;
      for(j=4;j<argc && chanfo !=NULL;j++)
      {
        if((strstr(buf,chanfo->channame)!=NULL) ||
            (strstr(buf,chanfo->chancap)!=NULL))
        {
          match=strstr(buf,":");
          match++;
          for(i=0;*match!='!' ;i++,match++)
            name[i]=*match;
          name[i+1]='\0';
          match=strstr(match,":");
          match++;
          for(i=0;*match!='\r' && *match!='\0';i++,match++)
            data[i]=*match;
          data[i+1]='\0';

          while((match=strstr(data,"/xmp"))!=NULL)
            *match='\\';

          snprintf(out,(strlen(name)+strlen(data)+4),"<%s>%s\n",name,data);
          if(write(chanfo->file,out,strlen(out))==-1)
            perror("write");
          j=argc;
        }/* if */
      chanfo=chanfo->next;
      }/* for */
    }/* if */
    else if(strstr(buf,"PING")!=NULL)
    {
      buf[1]='O';
      if(write(sockfd,buf,strlen(buf))==-1)
        perror("write");
    }
    else if(strstr(buf,"JOIN")!=NULL)
    {
      chanfo=head;
      for(j=4;j<argc && chanfo!=NULL;j++)
      {
        if((strstr(buf,chanfo->channame)!=NULL) ||
           (strstr(buf,chanfo->chancap)!=NULL))
        {
          match=strstr(buf,":");
          match++;
          for(i=0;*match!='!'&& *match!='\r' && *match!='\0';i++,match++)
            name[i]=*match;
          snprintf(out,(strlen(name)+strlen(chanfo->channame)+18),
                   "*** %s has joined %s\n",name,chanfo->channame);
          if(write(chanfo->file,out,strlen(out))==-1)
            perror("write");
          j=argc;
        }/* if */
        chanfo=chanfo->next;
      }/* for */
    }/* if */
    else if(strstr(buf,"PART")!=NULL)
    {
      chanfo=head;
      for(j=4;j<argc && chanfo!=NULL;j++)
      {
        if((strstr(buf,chanfo->channame)!=NULL) ||
           (strstr(buf,chanfo->chancap)!=NULL))
        {
          match=strtok(buf,":");
          for(i=0;*match!='!' &&*match!='\r' && *match!='\0';i++,match++)
            name[i]=*match;
          snprintf(out,(strlen(name)+strlen(chanfo->channame)+16),
                   "*** %s has left %s\n",name,chanfo->channame);
          if(write(chanfo->file,out,strlen(out))==-1)
            perror("write");
          j=argc;
        }/* if */
        chanfo=chanfo->next;
      }/* for */
    }/* if */    

    memset(buf,'\0',BUF_SIZE+1);
    memset(out,'\0',BUF_SIZE+100);
    memset(name,'\0',30);
    memset(data,'\0',BUF_SIZE+1);
  }/* while */
}/* main */

chanstruct *add_entry(int i,int sockfd,char chan[],chanstruct *head)
{
  int j;
  char *msg,logf[50],nowbuf[100];
  time_t now;
  chanstruct *new_entry;
  struct stat statf;

  new_entry=(chanstruct *)malloc(sizeof(chanstruct));
  snprintf(logf,sizeof(logf),"%s.html",chan);
  if((new_entry->file=open(logf,O_WRONLY | O_APPEND | O_CREAT,
                     S_IREAD | S_IWRITE | S_IROTH))==-1)
  {
    perror("open");
    exit(1);
  }
  for(j=0;j<sizeof(chan);j++)
    chan[j]=tolower(chan[j]);
  strncpy(new_entry->channame,chan,sizeof(new_entry->channame));
  for(j=0;j<sizeof(chan);j++)
    chan[j]=toupper(chan[j]);
  strncpy(new_entry->chancap,chan,sizeof(new_entry->chancap));
  new_entry->next=head;
  msg =(char *)malloc(strlen(new_entry->channame)+8);
  snprintf(msg,strlen(new_entry->channame)+8,"JOIN %s\r\n",new_entry->channame);
  write(sockfd,msg,strlen(msg));
  fstat(new_entry->file,&statf);
  if(statf.st_size == 0)
  {
    if(write(new_entry->file,"<html><body><pre><xmp>\n",23)==-1)
      perror("write");
  }
  now=time(NULL);
  strftime(nowbuf,sizeof(nowbuf),"%D %H:%M:%S GMT",gmtime(&now));
  free(msg);
  msg=(char *)malloc(500);
  snprintf(msg,500,"%s:  Logging %s\n",nowbuf,new_entry->channame);
  if(write(new_entry->file,msg,strlen(msg))==-1)
    perror("write");
  free(msg);

  return new_entry;
}

int useage(char *name)
{
  printf("Usage: %s <nick> <server> <port> <channel>\n",name);
  printf("\tnick - nick the bot should use\n");
  printf("\tserver - irc server to connect to\n");
  printf("\tport - port number the irc server uses (6667 usually)\n");
  printf("\tchannel - channel(s) to join and log to html\n");
  printf("\n\tNOTE: You must escape channel names on the command line\n");
  return;
}/* useage */

