/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Author: Ricardo I. Vieitez
Release date: 01-May-2006 (XXI)
Designed for GNU/Linux
*/
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#include "irc.h" /* irc Class */
using namespace std;
int cij;
bool irc::copyval(char* &dest, const char* src)
{
if(dest) {
if (strlen(src) > strlen(dest)) {
delete [] dest;
dest=new char[strlen(src)+1];
// If can't obtain memory, return false
if (!dest)
return false;
}
} else {
dest=new char[strlen(src)+1];
// If can't obtain memory, return false
if (!dest)
return false;
}
strcpy(dest,src);
return true;
}
irc::irc() : m_iPort(0), m_pszServer(NULL), m_pszNick(NULL),
m_pszUsern(NULL), m_pszRealn(NULL), m_pszNS(NULL),
m_pszChannel(NULL), m_bQ(false) {}
bool irc::setServer(const char * pszArray) {
return copyval(m_pszServer,pszArray);
}
bool irc::setPort(const int num) {
m_iPort=num;
if (m_iPort==num) return true; else return false;
}
bool irc::setNick(const char * pszArray) {
return copyval(m_pszNick,pszArray);
}
bool irc::Name(const char * pszArray1, const char * pszArray2) {
return copyval(m_pszUsern,pszArray1) && copyval(m_pszRealn,pszArray2);
}
bool irc::setNS(const char * pszArray) {
return copyval(m_pszNS,pszArray);
}
bool irc::setChannel(const char * pszArray) {
return copyval(m_pszChannel,pszArray);
}
void irc::receive(int m_iSock, char *pszRBuff)
{
int cii=0;char cchar[2];
while (cchar[0]!= '\n')
{
if (read(m_iSock, cchar, 1) == -1)
return;
strcpy (pszRBuff + cii, cchar);
pszRBuff[++cii] = 0;
}
}
void irc::ssend(int m_iSock,char *pszSBuff,bool bOut)
{
write(m_iSock,pszSBuff,strlen(pszSBuff));
if (bOut) cout << "-> " << pszSBuff << "\n";
}
bool irc::servConnect() {
fstream unBFile; // Files to open
unBFile.open("./noubuntu.bot.log",ios::out); // Open the file
unBFile.seekg(0,ios::end);
start:
printf("***\n*** STARTING BOT...\n***\n");
// Start socket
// Iniciar socket
m_iSoc=socket(AF_INET,SOCK_STREAM,0);
// If could'n open socket
// Si no se pudo abrir el socket
if(m_iSoc==-1) {
cerr << "Couldn't open socket";
return false;
}
// If couldn't resolve server address
// Si no se pudo resolver la direccin del servidor
m_server=gethostbyname(m_pszServer);
if(m_server==NULL) {
cerr << "Couldn't resolve server address";
return false;
}
// Opening connection
// Abriendo conexin
m_connection.sin_family=AF_INET;
m_connection.sin_addr=*(struct in_addr *)m_server->h_addr;
m_connection.sin_port=htons(m_iPort);
// Connect
// Conectar
m_iStatus=connect(m_iSoc,(struct sockaddr *)&m_connection,sizeof(m_connection));
// If there was a connection error
// Si hubo un error de conexin
if(m_iStatus==-1) {
cerr << "Connection error. Trying again...";
close(m_iSoc);
sleep(5);
goto start;
}
// Change to Identify mode
// Cambiar al modo Identificacin
m_mode=IDENTIFY;
// Main loop
// Bucle principal
while(1) {
switch(m_mode) {
// If Restart needed
// En el modo Restart
case RESTART:
goto start;
break;
// Identify mode
// Modo Identificacin
case IDENTIFY:
// Send Nick information
// Enviar informacin de Nick
sprintf(cBuf,"NICK %s\n",m_pszNick);
ssend(m_iSoc,cBuf);
// Send user info (such as username and realname)
// Enviar informacin de usuario (como nombre de usuario y nombre real)
sprintf(cBuf,"USER %s %s %s %s\n",m_pszUsern,m_pszNick,m_pszNick,m_pszRealn);
ssend(m_iSoc,cBuf);
p=cBuf;
m_eFlag=OK;
// Change to Idle mode
// Cambiar a modo Idle
m_mode=IDLE;
// Idle mode
// En modo Idle
case IDLE:
// Read buffer
// Leer del buffer
m_iStatus=read(m_iSoc,p,1);
if(!m_iStatus && !m_bQ) {
close(m_iSoc);
m_mode=RESTART;
}
// If bot is exiting
// Si el bot est terminando
if (m_bQ) {
close(m_iSoc);
printf("***\n*** QUITING (requested)...\n***\n");
exit(0);
}
// If there are too much lines, set flag Overflow
// Si hay muchas lneas, marcar con bandera "desbordamiento"
if(p-cBuf>=BUF_LEN-3) {
m_eFlag=OVERFLOW;
if(*p!='\n') {
p=cBuf;
break;
}
}
// Overflow mode
// Si est la bandera Desbordamiento
if (m_eFlag==OVERFLOW) {
cout << "-> __OVERFLOW__\n";
unBFile.write("-> __OVERFLOW__\n",sizeof("-> __OVERFLOW__\n"));
bzero(cBuf,sizeof(cBuf));
m_eFlag=OK;
break;
}
// Clean buffer
// Limpiar buffer
bzero(cBuf,sizeof(cBuf));
// Receive buffer
// Recibir buffer
receive(m_iSoc,cBuf);
// PONG server
// PONG al servidor
// sprintf(cBuf2,"%s PONG %s :475869159",m_pszServer,m_pszServer);
// sprintf(cBuf3,":%s PONG %s :475869159",m_pszServer,m_pszServer);
if (strstr(cBuf,cBuf2) == NULL || strstr(cBuf,cBuf3) != NULL) {
cout << cBuf; // Output buf
if (strstr(cBuf,"PRIVMSG") && strstr(cBuf,"@") && strstr(cBuf,"!") && strstr(cBuf," ") && strstr(cBuf,":")
&& strcasestr(cBuf,m_pszChannel)) {
bzero(cBuf2,sizeof(cBuf2));
sprintf(cBuf2,"<%s> %s",msgInfo().nick,(msgInfo().msg)+1);
unBFile.write(cBuf2,sizeof(cBuf2));
cout << cBuf2;
}
}
// Intelligent bot
BotAction();
bzero(cBuf2,sizeof(cBuf2));
bzero(cBuf3,sizeof(cBuf3));
if (strstr(cBuf,"MOTD")) // MODT Received
{
ssend(m_iSoc,"USERHOST GNU-A-CPP-Bot\n"); // Send User host
ssend(m_iSoc,"PING :475869159\n"); // Ping server
if (m_pszNS) {
sprintf(cBuf,"NS IDENTIFY %s\n",m_pszNS); // Send NickServ info
ssend(m_iSoc,cBuf,false);
cout << "Sent NickServ information\n";sleep(2);
}
sprintf(cBuf,"JOIN %s\n",m_pszChannel); // Join a channel
ssend(m_iSoc,cBuf);
sprintf(cBuf,"NOTICE %s :%s bot activated\n",m_pszChannel,m_pszNick);
ssend(m_iSoc,cBuf);
}
// ssend(m_iSoc,"PING :475869159\n",false); // Ping server
// Ping mode
// Modo PING
if (strstr(cBuf,"PING"))
{
bzero(cBuf2,sizeof(cBuf2));
cij=0;
while(cBuf[cij] != ':') cij++;
memcpy(cBuf2,&cBuf[cij],strlen(cBuf)-cij-1);
sprintf(cBuf,"PONG %s\n",cBuf2);
cout << "---------- " << cBuf;
ssend(m_iSoc,cBuf);
}
break;
default:
break;
}
}
return 0;
}