Newer
Older
tuved / src / tuve.c
@Charlie Root Charlie Root on 15 Apr 2019 11 KB Sync
/*
  (c) 2007 Christopher Olsen
  $Id: tuve.c,v 1.60 2008/10/07 12:59:56 reddawg Exp $

*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>

#include "tuved.h"

int tuveProcessData(myConnections_t *userConnection);

int tuveGetData(myConnections_t *userConnection) {


  memset(&userConnection->data,0x0,1024);
  userConnection->recLen = sReadSocket(userConnection->fd,&userConnection->data,1024);
  if (userConnection->recLen <= 0)
    return(-1);

  userConnection->userInfo.pong = time(NULL); // Reset the pong time of the socket
  tuveProcessData(userConnection);

  return(0x0);
  } /* End int tuveGetDatga(myConnections_t *); */


int tuveSendAll(const char *data,int fd) {
  myConnections_t *tmpConnection = 0x0;

  for (tmpConnection = connections;tmpConnection != 0x0;tmpConnection = tmpConnection->next) {
    if (tmpConnection->fd != fd)
      sSendData(tmpConnection,data);
    }

  return(0x0);
  } /* End int tuveSendAll(const char *data,int fd); */ 

int tuveProcessData(myConnections_t *userConnection) {
  char            *chan          = 0x0;
  char            *nick          = 0x0;
  char            *cmd           = 0x0;
  char            *msg           = 0x0;
  char            *data          = 0x0; 
  char            *data2         = 0x0;
  char            *data_tok      = 0x0;
  char            *tok_last      = 0x0;
  char             output[1280];
  char             buffer[1024];
  myConnections_t *tmpConnection = 0x0;

  memset(&output,0x0,1024);
  memset(&buffer,0x0,1024);

  assert(userConnection);

  data = strtok_r(userConnection->data,"\n",&data_tok);
  data2 = strtok_r(NULL,"\n",&data_tok);

  Head:

  if (data == 0x0) {
    data = data2;
    data2 = strtok_r(NULL,"\n",&data_tok);
    }

  cmd = data;

  if (cmd == NULL) {
    // MrOlsen 2017-11-17 TEMP 
    return(0);
  }

  if (cmd[userConnection->recLen - 1] == '\n')
    cmd[userConnection->recLen - 1] = '\0';

  if (cmd[userConnection->recLen - 2] == 13)
    cmd[userConnection->recLen - 2] = '\0';


  if (strstr(cmd," ")) {
    cmd  = strtok_r(cmd," ",&tok_last);
    data = strtok_r(NULL,"\n",&tok_last); 
    tok_last = 0x0;
    writeLog(3,"DATA:  (%s)CMD: [%s], Data: [%s]\n",userConnection->userInfo.username,cmd,data);
    }
  else 
    writeLog(3,"DATA:  (%s)CMD: [%s]\n",userConnection->userInfo.username,cmd);


  if (!strcasecmp(cmd,"IDENT")) {
    writeLog(2,"(ident)\n");
    if (data != 0x0) {
      tok_last = 0x0;
      nick = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,"\n",&tok_last);

      if (tuveVerifyNick(nick) == 0) {
        sprintf(userConnection->userInfo.username, "%s", nick);
        if (msg == 0x0) 
          userConnection->userInfo.uid = time(NULL);
        else
          userConnection->userInfo.uid = atoll(msg);
        userConnection->userInfo.ident = 0x1;

        sSendData(userConnection,"IDENT:0:Success");
        }
      else 
       sSendData(userConnection,"IDENT:1:Nick In Use.");
      }
    else {
      sSendData(userConnection,"IDENT:1:Invalid Ident.");
      }
    goto Tail;
    }
  else if (strcasecmp(cmd,"<policy-file-request/>") == 0x0) {
    /* Command Checked Tested And Approved */
    sprintf(output,"<?xml version=\"1.0\"?>\n<cross-domain-policy>\n<allow-access-from domain=\"*\" to-ports=\"*\" />\n</cross-domain-policy>\n");
    send(userConnection->fd,output,strlen(output)+1,MSG_NOSIGNAL);
    writeLog(2,"Sent CROSSDOMAIN\n");
    return(0x0);
    }
  else if (strcasecmp(cmd,"PONG!") == 0x0) {
    /* Command Checked Test And Approved */
    userConnection->userInfo.pfailed = 0x0;
    goto Tail;
    }
  else if (strcasecmp(cmd,"CLIENT") == 0x0) {
    /* Verify Version */
    if (data == 0x0)
      sSendData(userConnection,"CLIENT:1:Invalid CLIENT");
    else if (atof(data) < MIN_VER)
      sSendData(userConnection,"CLIENT:1:You are running client version %4.2f, our current version is %4.2f. Please upgrade to get the latest features.",atof(data),MIN_VER);
    else {
      sSendData(userConnection,"CLIENT:0:SUCCESSFUL");
      userConnection->userInfo.version = atof(data);
      }

    goto Tail;
    }
  else if (userConnection->userInfo.ident == 0x0) {
    /* Command Checked Tested And Approved */
    sSendData(userConnection,"Please Auth");
    goto Tail;
    }

  userConnection->userInfo.idle = time(NULL);

  if (!strcasecmp(cmd,"LIST")) {
    return(tuveChanList(userConnection));
    }
  else if (!strcasecmp(cmd,"JOIN")) {
    /* Function Checked Tested And Approved */
    if (data == 0x0) {
      sSendData(userConnection,"JOIN:ERROR:Invalid Channel Information");
      }
    else if (!strstr(data,"#") || strlen(data) > MAX_CHAN_LEN)
      sSendData(userConnection,"JOIN:ERROR:Invalid channel.");
    else
      tuveChanJoin(data,userConnection);
    }
  else if (strcasecmp(cmd,"MSG") == 0x0) {
    if (data != 0x0) {
      chan = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,"\n",&tok_last);

      if (msg == 0x0)
        goto Tail;

      if (chan[0] != '#') {
        tmpConnection = findNick(chan);
        if (tmpConnection != 0x0) {
          sSendData(tmpConnection,"MSG:%s:PRIVMSG:%s",userConnection->userInfo.username,msg);
          }
        else
          sSendData(userConnection,"MSG:%s:PRIVMSG:Is Not Available.",chan);
        }
      else if (tuveVerifyBan(chan,userConnection->userInfo.username) == 0x1) {
        sprintf(output,"MSG:TUveD:%s:You can not send text to the channel.",chan);
        sSendData(userConnection,output);
        }
      else if (msg != 0x0) {
        if ((strlen(msg) > 2) && (msg[0] == '.' && msg[1] == 't' && msg[2] == 'v'))
          tuveCMD_CMD(userConnection,chan,msg+3);
        else {
          strncpy(buffer,msg,1024);
          tuveSendAllInChan(chan,userConnection,"MSG:%s:%s:%s",userConnection->userInfo.username,chan,buffer);
          }
        }
      }
    }
  else if (strcasecmp(cmd,"VIDC") == 0x0) {
    if (data != 0x0) {
      chan = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,"\n",&tok_last);
      if (msg == 0x0)
        goto Tail;

      tmpConnection = findNick(chan);
      if (tmpConnection != 0x0)
        sSendData(tmpConnection,"VIDC:%s:%s",userConnection->userInfo.username,msg);
      else
        sSendData(tmpConnection,"MSG:%s:PRIVMSG:Is Not Available.",chan);
      }
    }
  else if (strcasecmp(cmd,"MODE") == 0x0) {
    if (data == 0x0) {
      sSendData(userConnection,"MODE:FAILED");
      goto Tail;
      }

	chan = strtok_r(data,":",&tok_last);
	msg  = strtok_r(NULL,"\n",&tok_last);

	if (msg == 0x0)
	  goto Tail;
	tuveCMD_CMD(userConnection,chan,msg);
    }
  else if (strcasecmp(cmd,"EMOTE") == 0x0) {
    if (data != 0x0) {
      chan = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,"\n",&tok_last);
      if (tuveVerifyBan(chan,userConnection->userInfo.username) == 0x1) {
        sprintf(output,"MSG:TUveD:%s:You can not send text to the channel.",chan);
        sSendData(userConnection,output);
        }
      else if (msg != 0x0) {
        strncpy(buffer,msg,1024);
        sprintf(output,"EMOTE:%s:%s:%s",userConnection->userInfo.username,chan,buffer);
        tuveSendAllInChan(chan,userConnection,output);
        }
      }
    }
  else if (strcasecmp(cmd,"TOPIC") == 0x0) {
    if (data != 0x0) {
      tok_last = 0x0;
      chan = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,"\n",&tok_last);

      if (tuveVerifyBan(chan,userConnection->userInfo.username) == 0x1) {
         sSendData(userConnection,"MSG:TUveD:STATUS:You can not set topic to this channel.");
         }
      else {
        tuveSetTopic(userConnection,chan,msg);
        }
      }
    }
  else if (strcasecmp(cmd,"NICK") == 0x0) {
    if (data != 0x0) {
      if (tuveVerifyNick(data) == 0x0) {
        sprintf(output,"NICK:%s:%s",userConnection->userInfo.username,data);
        sSendData(userConnection,output);
        tuveSendAllInUsersChans(userConnection,output);
        sprintf(output,"MSG:TUveD:STATUS:%s is now known as %s",userConnection->userInfo.username,data);
        tuveSendAllInUsersChans(userConnection,output);
        sprintf(userConnection->userInfo.username, "%s", data);
        }
      else
        sSendData(userConnection,"MSG:TUveD:STATUS:Nick In Use");
      }
    else {
      sSendData(userConnection,"MSG:TUveD:STATUS:Invalid Nick");
      }
    }
  else if (strcasecmp(cmd,"KICK") == 0x0) {
    tok_last = 0x0;

    if (userConnection->userInfo.modes[USER_OVERLORD] != 1) {
      sSendData(userConnection,"MSG:TUveD:KICK:You do not have permission to kick!");
      }
    else {
      if (data == 0x0)
        sSendData(userConnection,"KICK:Invalid Information");
      else {
        chan = strtok_r(data,":",&tok_last);
        nick = strtok_r(NULL,":",&tok_last);
        msg  = strtok_r(NULL,"\n",&tok_last);
        if ((chan != 0x0) && (nick != 0x0) && (msg != 0x0))
          if (msg[0] != '\n')
            tuveKick(userConnection,chan,nick,msg);
          else
            tuveKick(userConnection,chan,nick,"I'm Too Lame To Give A Good Reason!");
        else
          sSendData(userConnection,"KICK:Invalid Information.");
        } 
      }

    }
  else if (strcasecmp(cmd,"VIDEO") == 0x0) {
    if (data != 0x0) {
      tok_last = 0x0;
      chan = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,"\n",&tok_last);
      if (msg == 0x0)
        sSendData(userConnection,"MSG:TuveD:STATUS:Missing VID"); 
      else
        tuveBotSetVideo(chan,userConnection->userInfo.username,atoi(msg));
      }
    else
      sSendData(userConnection,"MSG:TUveD:STATUS:Invalid VIDEO syntax.");
    }
  else if (strcasecmp(cmd,"PART") == 0x0) {
    if (data != 0x0) {
      if (tuveChanPart(data,userConnection) == 0x1) {
        writeLog(0,"ERROR: Unable to remove user from channel: %s list\n",data);
        sSendData(userConnection,"PART:Not In Chan");
        }
      }
    else
      sSendData(userConnection,"PART:Not In Chan");
    }
  else if (strcasecmp(cmd,"WHOIS") == 0x0) {
    if (data != 0x0)
      tuveWhois(userConnection,data);
    }
  else if (strcasecmp(cmd,"STATUS") == 0x0) {
    tuveStatus(userConnection);
    }
  else if (strcasecmp(cmd,"BAN") == 0x0) {
    if (data != 0x0) {
      tok_last = 0x0;
      chan = strtok_r(data,":",&tok_last);
      nick = strtok_r(NULL,":",&tok_last);
      msg = strtok_r(NULL,"\n",&tok_last);
      if (msg != 0x0)
        tuveBan(userConnection,chan,nick,atoi(msg));
      else
        tuveBan(userConnection,chan,nick,600);
      }
    }
  else if (strcasecmp(cmd,"UNBAN") == 0x0) {
    if (userConnection->userInfo.modes[USER_OVERLORD] != 1) {
      sSendData(userConnection,"MSG:TUveD:STATUS:You do not have permission to unban.");
      }
    else if (data != 0x0) {
      tok_last = 0x0;
      chan = strtok_r(data,":",&tok_last);
      nick = strtok_r(NULL,"\n",&tok_last);
      tuveUnBan(chan,nick);
      }
    }
  else if (strcasecmp(cmd,"QUEUE") == 0x0) {
    if (data != 0x0) {
      if (strcasecmp(data,"FULL") == 0x0)
        userConnection->userInfo.queue = 1;
      else
        userConnection->userInfo.queue = 0;
      }
    }
  else if (strcasecmp(cmd,"LIVE") == 0x0) {
    if (data != 0x0) {
      tok_last = 0x0;
      chan = strtok_r(data,":",&tok_last);
      msg  = strtok_r(NULL,":",&tok_last);
      nick = strtok_r(NULL,"\n",&tok_last);    
      if (msg[0] == '0') {
        tuveSendAllInChan(chan,0x0,"LIVE:0:DONE");
        if (tuveChanResume(chan) == 0x1)
          sSendData(userConnection,"MSG:TUveD:STATUS:Sorry Invalid Live Parameters");
        }
      else {
        if (tuveChanLive(chan,msg,nick) == 0x1)
          sSendData(userConnection,"MSG:TUveD:STATUS:Sorry Invalid Live Parameters.");
        }
      }
    }
  else if (strcasecmp(cmd,"QUIT") == 0x0) {
    if (strlen(data) > 0)
      tuveDelUserChans(userConnection,data);
    else
      tuveDelUserChans(userConnection,"Leaving");
    close(userConnection->fd);
    sRemoveConnection(userConnection->fd);
    }
  else {
    sSendData(userConnection,"invalid command");
    writeLog(1,"Invalid CMD: [%s]\n",cmd);
    }

  Tail:
  if (data2 != 0x0) {
    data = 0x0;
    goto Head;
    }

  return(0x0);
  }