irc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. #include <ctype.h>
  2. #include <string.h>
  3. #ifdef __WIN32
  4. #define __USE_W32_SOCKETS
  5. #include <windows.h>
  6. #include <io.h>
  7. typedef int socklen_t;
  8. #else
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <sys/time.h>
  12. #include <unistd.h>
  13. #include <sys/ioctl.h>
  14. #include <netdb.h>
  15. #include <arpa/inet.h>
  16. #include <ctype.h>
  17. #include <stdlib.h>
  18. #ifndef SIOCGIFCONF
  19. #include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori]
  20. #endif
  21. #endif
  22. #include "../common/core.h"
  23. #include "../common/socket.h"
  24. #include "../common/malloc.h"
  25. #include "../common/db.h"
  26. #include "../common/timer.h"
  27. #include "../common/strlib.h"
  28. #include "../common/mmo.h"
  29. #include "../common/showmsg.h"
  30. #include "../common/version.h"
  31. #include "../common/nullpo.h"
  32. #include "map.h"
  33. #include "pc.h"
  34. #include "irc.h"
  35. #include "intif.h" //For GM Broadcast [Zido]
  36. short use_irc=0;
  37. short irc_announce_flag=1;
  38. short irc_announce_mvp_flag=1;
  39. short irc_announce_jobchange_flag=1;
  40. short irc_announce_shop_flag=1;
  41. IRC_SI *irc_si=NULL;
  42. char irc_nick[30]="";
  43. char irc_password[32]="";
  44. char irc_channel[32]="";
  45. char irc_trade_channel[32]="";
  46. unsigned char irc_ip_str[128]="";
  47. unsigned long irc_ip=0;
  48. unsigned short irc_port = 6667;
  49. int irc_fd=0;
  50. struct channel_data cd;
  51. int last_cd_user=0;
  52. int irc_connect_timer(int tid, unsigned int tick, int id, int data)
  53. {
  54. if(irc_si && session[irc_si->fd])
  55. return 0;
  56. irc_fd = make_connection(irc_ip,irc_port);
  57. if(irc_fd > 0){
  58. session[irc_fd]->func_parse = irc_parse;
  59. }
  60. return 0;
  61. }
  62. void irc_announce(char *buf)
  63. {
  64. char send_string[256];
  65. memset(send_string,'\0',256);
  66. sprintf(send_string,"PRIVMSG %s :%s",irc_channel, buf);
  67. irc_send(send_string);
  68. }
  69. void irc_announce_jobchange(struct map_session_data *sd)
  70. {
  71. char send_string[256];
  72. nullpo_retv(sd);
  73. memset(send_string,'\0',256);
  74. sprintf(send_string,"PRIVMSG %s :%s has changed into a %s.",irc_channel,sd->status.name,job_name(sd->status.class_));
  75. irc_send(send_string);
  76. }
  77. void irc_announce_shop(struct map_session_data *sd, int flag)
  78. {
  79. char send_string[256];
  80. char mapname[16];
  81. int maplen = 0;
  82. nullpo_retv(sd);
  83. memset(send_string,'\0',256);
  84. memset(mapname,'\0',16);
  85. if(flag){
  86. strcpy(mapname, map[sd->bl.m].name);
  87. maplen = strcspn(mapname,".");
  88. mapname[maplen] = '\0';
  89. mapname[0]=toupper(mapname[0]);
  90. sprintf(send_string,"PRIVMSG %s :%s has opened a shop, %s, at <%d,%d> in %s.",irc_trade_channel,sd->status.name,sd->message,sd->bl.x,sd->bl.y,mapname);
  91. } else
  92. sprintf(send_string,"PRIVMSG %s :%s has closed their shop.",irc_trade_channel,sd->status.name);
  93. irc_send(send_string);
  94. }
  95. void irc_announce_mvp(struct map_session_data *sd, struct mob_data *md)
  96. {
  97. char send_string[256];
  98. char mapname[16];
  99. int maplen = 0;
  100. nullpo_retv(sd);
  101. nullpo_retv(md);
  102. memset(send_string,'\0',256);
  103. memset(mapname,'\0',16);
  104. mapname[16]='\0';
  105. strcpy(mapname, map[md->bl.m].name);
  106. maplen = strcspn(mapname,".");
  107. mapname[maplen] = '\0';
  108. mapname[0]=toupper(mapname[0]);
  109. sprintf(send_string,"PRIVMSG %s :%s the %s has MVP'd %s in %s.",irc_channel,sd->status.name,job_name(sd->status.class_),md->name, mapname);
  110. irc_send(send_string);
  111. }
  112. int irc_parse(int fd)
  113. {
  114. if (session[fd]->eof){
  115. do_close(fd);
  116. irc_si = NULL;
  117. add_timer(gettick() + 15000, irc_connect_timer, 0, 0);
  118. return 0;
  119. }
  120. if (session[fd]->session_data == NULL){
  121. irc_si = (struct IRC_Session_Info*)aCalloc(1, sizeof(struct IRC_Session_Info));
  122. irc_si->fd = fd;
  123. irc_si->state = 0;
  124. session[fd]->session_data = irc_si;
  125. } else if (!irc_si) {
  126. irc_si = (struct IRC_Session_Info*)session[fd]->session_data;
  127. irc_si->fd = fd;
  128. }
  129. if(RFIFOREST(fd) > 0){
  130. char *incoming_string=aCalloc(RFIFOREST(fd),sizeof(char));
  131. memcpy(incoming_string,RFIFOP(fd,0),RFIFOREST(fd));
  132. send_to_parser(fd,incoming_string,"\n");
  133. RFIFOSKIP(fd,RFIFOREST(fd));
  134. aFree(incoming_string);
  135. }
  136. return 0;
  137. }
  138. int irc_keepalive_timer(int tid, unsigned int tick, int id, int data)
  139. {
  140. char send_string[128];
  141. memset(send_string,'\0',128);
  142. sprintf(send_string,"PRIVMSG %s : ", irc_nick);
  143. irc_send(send_string);
  144. add_timer(gettick() + 30000, irc_keepalive_timer, 0, 0);
  145. return 0;
  146. }
  147. void irc_send_sub(int fd, char transmit[4096])
  148. {
  149. sprintf(transmit,"%s%c",transmit,10);
  150. WFIFOHEAD(fd,strlen(transmit));
  151. memcpy(WFIFOP(fd,0),transmit, strlen(transmit));
  152. WFIFOSET(fd,strlen(transmit));
  153. }
  154. void irc_send(char *buf)
  155. {
  156. char transmit[4096];
  157. if(!irc_si || !session[irc_si->fd])
  158. return;
  159. memset(transmit,'\0',4096);
  160. sprintf(transmit,buf);
  161. irc_send_sub(irc_si->fd,transmit);
  162. }
  163. void irc_parse_sub(int fd, char *incoming_string)
  164. {
  165. char source[256];
  166. char command[256];
  167. char target[256];
  168. char message[8192];
  169. char send_string[8192];
  170. char *source_nick=NULL;
  171. char *source_ident=NULL;
  172. char *source_host=NULL;
  173. char *state_mgr=NULL;
  174. char cmd1[256];
  175. char cmd2[256];
  176. char cmdname[256];
  177. char cmdargs[256];
  178. int users=0;
  179. memset(source,'\0',256);
  180. memset(command,'\0',256);
  181. memset(target,'\0',256);
  182. memset(message,'\0',8192);
  183. memset(send_string,'\0',8192);
  184. memset(cmd1,'\0',256);
  185. memset(cmd2,'\0',256);
  186. memset(cmdname,'\0',256);
  187. memset(cmdargs,'\0',256);
  188. sscanf(incoming_string, ":%255s %255s %255s :%4095[^\r\n]", source, command, target, message);
  189. if (source != NULL) {
  190. if (strstr(source,"!") != NULL) {
  191. source_nick = strtok_r(source,"!",&state_mgr);
  192. source_ident = strtok_r(NULL,"@",&state_mgr);
  193. source_host = strtok_r(NULL,"%%",&state_mgr);
  194. }
  195. }
  196. if (irc_si->state == 0){
  197. sprintf(send_string, "NICK %s", irc_nick);
  198. irc_send(send_string);
  199. sprintf(send_string, "USER eABot 8 * : eABot");
  200. irc_send(send_string);
  201. irc_si->state = 1;
  202. }
  203. else if (irc_si->state == 1){
  204. if(!strcmp(command,"001")){
  205. ShowStatus("IRC: Connected to IRC.\n");
  206. sprintf(send_string, "PRIVMSG nickserv :identify %s", irc_password);
  207. irc_send(send_string);
  208. sprintf(send_string, "JOIN %s", irc_channel);
  209. irc_send(send_string);
  210. sprintf(send_string,"NAMES %s",irc_channel);
  211. irc_send(send_string);
  212. irc_si->state = 2;
  213. }
  214. else if(!strcmp(command,"433")){
  215. ShowError("IRC: Nickname %s is already taken, IRC Client unable to connect.\n", irc_nick);
  216. sprintf(send_string, "QUIT");
  217. irc_send(send_string);
  218. if(session[fd])
  219. session[fd]->eof=1;
  220. }
  221. }
  222. else if (irc_si->state == 2){
  223. if(!strcmp(source, "PING")){
  224. sprintf(send_string, "PONG %s", command);
  225. irc_send(send_string);
  226. }
  227. else if((strcmpi(target,irc_channel)==0)||(strcmpi(target,irc_channel+1)==0)) {
  228. // Broadcast [Zido] (Work in Progress)
  229. if((strcmpi(command,"privmsg")==0)&&(sscanf(message,"@%255s %255[^\r\n]",cmdname,cmdargs)>0)&&(target[0]=='#')) {
  230. if(strcmpi(cmdname,"kami")==0) {
  231. if(get_access(source_nick)<ACCESS_OP)
  232. sprintf(send_string,"NOTICE %s :Access Denied",source_nick);
  233. else {
  234. sprintf(send_string,"%s: %s",source_nick,cmdargs);
  235. intif_GMmessage(send_string,strlen(send_string)+1,0);
  236. sprintf(send_string,"NOTICE %s :Message Sent",source_nick);
  237. }
  238. irc_send(send_string);
  239. } else if(strcmpi(cmdname,"users")==0) {
  240. map_getallusers(&users);
  241. sprintf(send_string,"PRIVMSG %s :Users Online: %d",irc_channel,users);
  242. irc_send(send_string);
  243. }
  244. }
  245. // Refresh Names [Zido]
  246. else if((strcmpi(command,"join")==0)||(strcmpi(command,"part")==0)||(strcmpi(command,"mode")==0)||(strcmpi(command,"nick")==0)) {
  247. ShowInfo("IRC: Refreshing User List");
  248. irc_rmnames();
  249. printf("...");
  250. sprintf(send_string,"NAMES %s",irc_channel);
  251. printf("...");
  252. irc_send(send_string);
  253. printf("Done\n");
  254. }
  255. }
  256. // Names Reply [Zido]
  257. else if((strcmpi(command,"353")==0)) {
  258. ShowInfo("IRC: NAMES recieved\n");
  259. parse_names_packet(incoming_string);
  260. }
  261. }
  262. return;
  263. }
  264. int send_to_parser(int fd, char *input,char key[2])
  265. {
  266. char *temp_string=NULL;
  267. char *state_mgr=NULL;
  268. int total_loops=0;
  269. temp_string = strtok_r(input,key,&state_mgr);
  270. while (temp_string != NULL){
  271. total_loops = total_loops+1;
  272. irc_parse_sub(fd,temp_string);
  273. temp_string = strtok_r(NULL,key,&state_mgr);
  274. }
  275. return total_loops;
  276. }
  277. void do_final_irc(void)
  278. {
  279. }
  280. void do_init_irc(void)
  281. {
  282. struct hostent *irc_hostname;
  283. if(!use_irc)
  284. return;
  285. if (irc_ip_str[strlen(irc_ip_str)-1] == '\n')
  286. irc_ip_str[strlen(irc_ip_str)-1] = '\0';
  287. irc_hostname=gethostbyname(irc_ip_str);
  288. irc_ip_str[0]='\0';
  289. sprintf(irc_ip_str, "%d.%d.%d.%d", (unsigned char)irc_hostname->h_addr[0], (unsigned char)irc_hostname->h_addr[1],
  290. (unsigned char)irc_hostname->h_addr[2], (unsigned char)irc_hostname->h_addr[3]);
  291. irc_ip=inet_addr(irc_ip_str);
  292. irc_connect_timer(0, 0, 0, 0);
  293. add_timer_func_list(irc_connect_timer, "irc_connect_timer");
  294. add_timer_func_list(irc_keepalive_timer, "irc_keepalive_timer");
  295. add_timer(gettick() + 30000, irc_keepalive_timer, 0, 0);
  296. }
  297. //NAMES Packet(353) parser [Zido]
  298. int parse_names_packet(char *str) {
  299. char *tok;
  300. char source[256];
  301. char numeric[10];
  302. char target[256];
  303. char channel[256];
  304. char names[1024];
  305. memset(source,'\0',256);
  306. memset(numeric,'\0',10);
  307. memset(target,'\0',256);
  308. memset(channel,'\0',256);
  309. memset(names,'\0',1024);
  310. tok=strtok(str,"\r\n");
  311. sscanf(tok,":%255s %10s %255s = %255s :%1023[^\r\n]",source,numeric,target,channel,names);
  312. if(strcmpi(numeric,"353")==0)
  313. parse_names(names);
  314. while((tok=strtok(NULL,"\r\n"))!=NULL) {
  315. sscanf(tok,":%255s %10s %255s = %255s :%1023[^\r\n]",source,numeric,target,channel,names);
  316. if(strcmpi(numeric,"353")==0)
  317. parse_names(names);
  318. }
  319. return 0;
  320. }
  321. //User access level prefix parser [Zido]
  322. int parse_names(char *str) {
  323. char *tok;
  324. tok=strtok(str," ");
  325. switch(tok[0]) {
  326. case '~':
  327. set_access(tok+1,ACCESS_OWNER);
  328. break;
  329. case '&':
  330. set_access(tok+1,ACCESS_SOP);
  331. break;
  332. case '@':
  333. set_access(tok+1,ACCESS_OP);
  334. break;
  335. case '%':
  336. set_access(tok+1,ACCESS_HOP);
  337. break;
  338. case '+':
  339. set_access(tok+1,ACCESS_VOICE);
  340. break;
  341. default:
  342. set_access(tok,ACCESS_NORM);
  343. break;
  344. }
  345. while((tok=strtok(NULL," "))!=NULL) {
  346. switch(tok[0]) {
  347. case '~':
  348. set_access(tok+1,ACCESS_OWNER);
  349. break;
  350. case '&':
  351. set_access(tok+1,ACCESS_SOP);
  352. break;
  353. case '@':
  354. set_access(tok+1,ACCESS_OP);
  355. break;
  356. case '%':
  357. set_access(tok+1,ACCESS_HOP);
  358. break;
  359. case '+':
  360. set_access(tok+1,ACCESS_VOICE);
  361. break;
  362. default:
  363. set_access(tok,ACCESS_NORM);
  364. break;
  365. }
  366. }
  367. return 0;
  368. }
  369. //Store user's access level [Zido]
  370. int set_access(char *nick,int newlevel) {
  371. int i=0;
  372. for(i=0;i<=MAX_CHANNEL_USERS;i++) {
  373. if(strcmpi(cd.user[i].name,nick)==0) {
  374. cd.user[i].level=newlevel;
  375. return 1;
  376. }
  377. }
  378. strcpy(cd.user[last_cd_user].name,nick);
  379. cd.user[last_cd_user].level=newlevel;
  380. last_cd_user++;
  381. return 0;
  382. }
  383. //Returns users access level [Zido]
  384. int get_access(char *nick) {
  385. int i=0;
  386. for(i=0;i<=MAX_CHANNEL_USERS;i++) {
  387. if(strcmpi(cd.user[i].name,nick)==0) {
  388. return (cd.user[i].level);
  389. }
  390. }
  391. return -1;
  392. }
  393. int irc_rmnames() {
  394. int i=0;
  395. for(i=0;i<=MAX_CHANNEL_USERS;i++) {
  396. //memset(cd.user[i].name,'\0',256);
  397. cd.user[i].level=0;
  398. }
  399. last_cd_user=0;
  400. return 0;
  401. }
  402. int irc_read_conf(char *file) {
  403. FILE *fp=NULL;
  404. char w1[256];
  405. char w2[256];
  406. char path[256];
  407. char row[1024];
  408. memset(w1,'\0',256);
  409. memset(w2,'\0',256);
  410. memset(path,'\0',256);
  411. memset(row,'\0',256);
  412. sprintf(path,"conf/%s",file);
  413. if(!(fp=fopen(path,"r"))) {
  414. ShowError("Cannot find file: %s\n",path);
  415. return 0;
  416. }
  417. while(fgets(row,1023,fp)!=NULL) {
  418. if(row[0]=='/'&&row[1]=='/')
  419. continue;
  420. sscanf(row,"%[^:]: %255[^\r\n]",w1,w2);
  421. if(strcmpi(w1,"use_irc")==0) {
  422. if(strcmpi(w2,"on")==0)
  423. use_irc=1;
  424. else
  425. use_irc=0;
  426. }
  427. else if(strcmpi(w1,"irc_server")==0)
  428. strcpy(irc_ip_str,w2);
  429. else if(strcmpi(w1,"irc_port")==0)
  430. irc_port=atoi(w2);
  431. else if(strcmpi(w1,"irc_channel")==0)
  432. strcpy(irc_channel,w2);
  433. else if(strcmpi(w1,"irc_trade_channel")==0)
  434. strcpy(irc_trade_channel,w2);
  435. else if(strcmpi(w1,"irc_nick")==0)
  436. strcpy(irc_nick,w2);
  437. else if(strcmpi(w1,"irc_pass")==0) {
  438. if(strcmpi(w2,"0")!=0)
  439. strcpy(irc_password,w2);
  440. }
  441. }
  442. ShowInfo("IRC Config read successfully\n");
  443. return 1;
  444. }