// IRCBot.h #ifndef _IRCBOT_H_ #define _IRCBOT_H_ /* Structs and Classes */ struct IRCName{ char *username, *hostname, *host; }; struct IRCMessage{ IRCName *sender; char *command, *parameters, *text; }; /* Outputting functions */ void error(char* pszError){ std::cerr << "[ERR] " << pszError << std::endl; } void debug(char* pszDebug){ std::cout << "[DBG] " << pszDebug << std::endl; } void info(char* pszData, bool bReceive){ if(bReceive) std::cout << "[RCV] "; else std::cout << "[SND] "; std::cout << pszData << std::endl; } /* Socket connection, reading and writing */ int connect(SOCKET &sSocket, char* pszIP, int iPort){ WSADATA t_wsa; int* piError = new int; *piError = WSAStartup(MAKEWORD(2, 2), &t_wsa); if(*piError != NO_ERROR || *piError == 1){ error("Error at WSAStartup()"); return 1; } sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sSocket == INVALID_SOCKET || *piError == 1){ error("Invalid Socket!"); return 1; } delete piError; SOCKADDR_IN sinSockaddr; memset(&sinSockaddr, 0, sizeof(sinSockaddr)); char* pszDebug = new char[250]; sprintf(pszDebug, "Connecting to %s:%d...", pszIP, iPort); debug(pszDebug); delete[] pszDebug; sinSockaddr.sin_family = AF_INET; sinSockaddr.sin_addr.s_addr = inet_addr(pszIP); sinSockaddr.sin_port = htons(iPort); if(connect(sSocket, (LPSOCKADDR)&sinSockaddr, sizeof(sinSockaddr)) == SOCKET_ERROR){ error("Could not connect to the server!"); return 1; } return NO_ERROR; } int send(SOCKET &sSocket, char* pszData){ info(pszData, false); char* pszDataNL = new char[516]; sprintf(pszDataNL, "%s\r\n\0", pszData); if(send(sSocket, pszDataNL, strlen(pszDataNL), 0) == SOCKET_ERROR){ error("Could not send data!"); delete[] pszDataNL; return 1; } delete[] pszDataNL; return NO_ERROR; } int recv(SOCKET &sSocket, char* buf, int bufsz, char *delim){ int ret, len, i, j; char *bufp, *p; if (delim == NULL) delim = ""; /* use '\0' as the delim */ len = strlen (delim); if (len < 1) len = 1; /* special case to handle '\0' delim */ for (ret = 0, bufp = buf; ret < bufsz; ) { /* peek at the data */ do { i = recv (sSocket, bufp, bufsz - ret, MSG_PEEK); } while ((i < 0) && (errno == EINTR)); if (i < 0) { ret = i; break; /* error of some sort */ } else if (i == 0) { break; /* at EOF; stop with what we've got so far */ } /* look for the delim string in the peeked at data */ for (p = (char*)memchr (bufp, *delim, i); p; ) { if ((len > 1) && memcmp (p, delim, len)) { /* not really the whole delim string; keep looking */ p++; j = i - (p - bufp); if (j > 0) p = (char*)memchr (p, *delim, j); else p = NULL; } else { /* we found the whole delim string */ p += len; i = p - bufp; break; } } /* really read the data now */ do { i = recv (sSocket, bufp, i, 0); } while ((i < 0) && (errno == EINTR)); if (i < 0) { ret = i; break; /* error of some sort */ } else if (i == 0) { break; /* at EOF; stop with what we've got so far */ } else { bufp += i; ret += i; if (p) break; /* we've found the delim */ } } return (ret); } /* IRC-specific things */ int nick(SOCKET sSocket, char* pszNick){ char* pszNickMSG = new char[510]; sprintf(pszNickMSG, "NICK %s", pszNick); int iR = send(sSocket, pszNickMSG); delete[] pszNickMSG; return iR; } int user(SOCKET sSocket, char* pszUsername, char* pszRealName){ char* pszUserMSG = new char[510]; sprintf(pszUserMSG, "USER %s 0 0 :%s", pszUsername, pszRealName); int iR = send(sSocket, pszUserMSG); delete[] pszUserMSG; return iR; } int join(SOCKET sSocket, char* pszChannel){ char* pszJoinMSG = new char[510]; sprintf(pszJoinMSG, "JOIN %s", pszChannel); int iR = send(sSocket, pszJoinMSG); delete[] pszJoinMSG; return iR; } int leave(SOCKET sSocket, char* pszChannel){ char* pszLeaveMSG = new char[510]; sprintf(pszLeaveMSG, "PART %s", pszChannel); int iR = send(sSocket, pszLeaveMSG); delete[] pszLeaveMSG; return iR; } int msg(SOCKET sSocket, char* pszWho, char* pszMessage){ char* pszPrivMSG = new char[510]; sprintf(pszPrivMSG, "PRIVMSG %s :%s", pszWho, pszMessage); int iR = send(sSocket, pszPrivMSG); delete[] pszPrivMSG; return iR; } int pong(SOCKET sSocket, IRCMessage *ping){ char* pszPingMSG = new char[510]; sprintf(pszPingMSG, "PONG %s", ping->parameters); int iR = send(sSocket, pszPingMSG); delete[] pszPingMSG; return iR; } int action(SOCKET sSocket, char* pszWho, char* pszAction){ char* pszActionMSG = new char[508]; sprintf(pszActionMSG, "\001ACTION %s\001", pszAction); int iR = msg(sSocket, pszWho, pszActionMSG); delete[] pszActionMSG; return iR; } IRCName* parseIRCName(char *full){ IRCName *ret; ret = new IRCName; full++; ret->username = strtok(full, "!"); ret->hostname = strtok(NULL, "@"); if(ret->hostname == NULL){ ret->hostname = new char[4]; ret->hostname = "\007\0"; } ret->host = strtok(NULL, "\r"); if(ret->host == NULL){ ret->host = new char[4]; ret->host = "\007\0"; } return ret; } IRCMessage* parseIRCData(char *full){ IRCMessage *ret; ret = new IRCMessage; char* tmp = new char[512]; tmp = strtok(full, " "); ret->command = strtok(NULL, " "); ret->parameters = strtok(NULL, ":"); if(ret->parameters == NULL){ ret->parameters = new char[4]; ret->parameters = "\007\0"; } ret->text = strtok(NULL, "\n"); if(ret->text == NULL){ ret->text = new char[4]; ret->text = "\007\0"; } ret->sender = parseIRCName(tmp); //delete[] tmp; return ret; } // Various functions char* tolower(char* text){ int max = strlen(text); char* ret = new char[strlen(text)+1]; strcpy(ret, text); for(int i=0;i<=max;i++){ if(isalpha(ret[i])) ret[i] = tolower(ret[i]); } return ret; } int strccmp(char* first, char* second){ return strcmp(tolower(first), tolower(second)); } #endif /* _IRCBOT_H_ */