diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2013-08-10 12:50:50 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2013-08-10 12:50:50 -0400 |
commit | 17dec0f70d683ffe217173f9de4ad2a92128487c (patch) | |
tree | b0b3d3ea999e5a4790e39b15e7877f548cef37dd | |
download | kankri-17dec0f70d683ffe217173f9de4ad2a92128487c.tar.gz kankri-17dec0f70d683ffe217173f9de4ad2a92128487c.tar.bz2 kankri-17dec0f70d683ffe217173f9de4ad2a92128487c.zip |
first commit
-rwxr-xr-x | IRC.cc | 877 | ||||
-rwxr-xr-x | IRC.h | 101 | ||||
-rw-r--r-- | main.cpp | 81 |
3 files changed, 1059 insertions, 0 deletions
diff --git a/IRC.cc b/IRC.cc new file mode 100755 index 0000000..b6b4da4 --- /dev/null +++ b/IRC.cc | |||
@@ -0,0 +1,877 @@ | |||
1 | /* | ||
2 | cpIRC - C++ class based IRC protocol wrapper | ||
3 | Copyright (C) 2003 Iain Sheppard | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Contacting the author: | ||
20 | ~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | |||
22 | email: iainsheppard@yahoo.co.uk | ||
23 | IRC: #magpie @ irc.quakenet.org | ||
24 | */ | ||
25 | |||
26 | #include "IRC.h" | ||
27 | #ifdef WIN32 | ||
28 | #include <windows.h> | ||
29 | #else | ||
30 | #include <stdlib.h> | ||
31 | #include <unistd.h> | ||
32 | #include <errno.h> | ||
33 | #include <string.h> | ||
34 | #include <netdb.h> | ||
35 | #include <sys/types.h> | ||
36 | #include <netinet/in.h> | ||
37 | #include <sys/socket.h> | ||
38 | #define closesocket(s) close(s) | ||
39 | #define SOCKET_ERROR -1 | ||
40 | #define INVALID_SOCKET -1 | ||
41 | #endif | ||
42 | |||
43 | IRC::IRC() | ||
44 | { | ||
45 | hooks=0; | ||
46 | chan_users=0; | ||
47 | connected=false; | ||
48 | sentnick=false; | ||
49 | sentpass=false; | ||
50 | sentuser=false; | ||
51 | cur_nick=0; | ||
52 | } | ||
53 | |||
54 | IRC::~IRC() | ||
55 | { | ||
56 | if (hooks) | ||
57 | delete_irc_command_hook(hooks); | ||
58 | } | ||
59 | |||
60 | void IRC::insert_irc_command_hook(irc_command_hook* hook, char* cmd_name, int (*function_ptr)(char*, irc_reply_data*, void*)) | ||
61 | { | ||
62 | if (hook->function) | ||
63 | { | ||
64 | if (!hook->next) | ||
65 | { | ||
66 | hook->next=new irc_command_hook; | ||
67 | hook->next->function=0; | ||
68 | hook->next->irc_command=0; | ||
69 | hook->next->next=0; | ||
70 | } | ||
71 | insert_irc_command_hook(hook->next, cmd_name, function_ptr); | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | hook->function=function_ptr; | ||
76 | hook->irc_command=new char[strlen(cmd_name)+1]; | ||
77 | strcpy(hook->irc_command, cmd_name); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | void IRC::hook_irc_command(char* cmd_name, int (*function_ptr)(char*, irc_reply_data*, void*)) | ||
82 | { | ||
83 | if (!hooks) | ||
84 | { | ||
85 | hooks=new irc_command_hook; | ||
86 | hooks->function=0; | ||
87 | hooks->irc_command=0; | ||
88 | hooks->next=0; | ||
89 | insert_irc_command_hook(hooks, cmd_name, function_ptr); | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | insert_irc_command_hook(hooks, cmd_name, function_ptr); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void IRC::delete_irc_command_hook(irc_command_hook* cmd_hook) | ||
98 | { | ||
99 | if (cmd_hook->next) | ||
100 | delete_irc_command_hook(cmd_hook->next); | ||
101 | if (cmd_hook->irc_command) | ||
102 | delete cmd_hook->irc_command; | ||
103 | delete cmd_hook; | ||
104 | } | ||
105 | |||
106 | int IRC::start(char* server, int port, char* nick, char* user, char* name, char* pass) | ||
107 | { | ||
108 | #ifdef WIN32 | ||
109 | HOSTENT* resolv; | ||
110 | #else | ||
111 | hostent* resolv; | ||
112 | #endif | ||
113 | sockaddr_in rem; | ||
114 | |||
115 | if (connected) | ||
116 | return 1; | ||
117 | |||
118 | irc_socket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
119 | if (irc_socket==INVALID_SOCKET) | ||
120 | { | ||
121 | return 1; | ||
122 | } | ||
123 | resolv=gethostbyname(server); | ||
124 | if (!resolv) | ||
125 | { | ||
126 | closesocket(irc_socket); | ||
127 | return 1; | ||
128 | } | ||
129 | memcpy(&rem.sin_addr, resolv->h_addr, 4); | ||
130 | rem.sin_family=AF_INET; | ||
131 | rem.sin_port=htons(port); | ||
132 | |||
133 | if (connect(irc_socket, (const sockaddr*)&rem, sizeof(rem))==SOCKET_ERROR) | ||
134 | { | ||
135 | #ifdef WIN32 | ||
136 | printf("Failed to connect: %d\n", WSAGetLastError()); | ||
137 | #endif | ||
138 | closesocket(irc_socket); | ||
139 | return 1; | ||
140 | } | ||
141 | |||
142 | dataout=fdopen(irc_socket, "w"); | ||
143 | //datain=fdopen(irc_socket, "r"); | ||
144 | |||
145 | if (!dataout /*|| !datain*/) | ||
146 | { | ||
147 | printf("Failed to open streams!\n"); | ||
148 | closesocket(irc_socket); | ||
149 | return 1; | ||
150 | } | ||
151 | |||
152 | connected=true; | ||
153 | |||
154 | cur_nick=new char[strlen(nick)+1]; | ||
155 | strcpy(cur_nick, nick); | ||
156 | |||
157 | fprintf(dataout, "PASS %s\r\n", pass); | ||
158 | fprintf(dataout, "NICK %s\r\n", nick); | ||
159 | fprintf(dataout, "USER %s * 0 :%s\r\n", user, name); | ||
160 | fflush(dataout); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | void IRC::disconnect() | ||
166 | { | ||
167 | if (connected) | ||
168 | { | ||
169 | fclose(dataout); | ||
170 | printf("Disconnected from server.\n"); | ||
171 | connected=false; | ||
172 | quit("Leaving"); | ||
173 | #ifdef WIN32 | ||
174 | shutdown(irc_socket, 2); | ||
175 | #endif | ||
176 | closesocket(irc_socket); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | int IRC::quit(char* quit_message) | ||
181 | { | ||
182 | if (connected) | ||
183 | { | ||
184 | if (quit_message) | ||
185 | fprintf(dataout, "QUIT %s\r\n", quit_message); | ||
186 | else | ||
187 | fprintf(dataout, "QUIT\r\n"); | ||
188 | if (fflush(dataout)) | ||
189 | return 1; | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | int IRC::message_loop() | ||
195 | { | ||
196 | char buffer[1024]; | ||
197 | int ret_len; | ||
198 | |||
199 | if (!connected) | ||
200 | { | ||
201 | printf("Not connected!\n"); | ||
202 | return 1; | ||
203 | } | ||
204 | |||
205 | while (1) | ||
206 | { | ||
207 | ret_len=recv(irc_socket, buffer, 1023, 0); | ||
208 | if (ret_len==SOCKET_ERROR || !ret_len) | ||
209 | { | ||
210 | return 1; | ||
211 | } | ||
212 | buffer[ret_len]='\0'; | ||
213 | split_to_replies(buffer); | ||
214 | } | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | void IRC::split_to_replies(char* data) | ||
220 | { | ||
221 | char* p; | ||
222 | |||
223 | while (p=strstr(data, "\r\n")) | ||
224 | { | ||
225 | *p='\0'; | ||
226 | parse_irc_reply(data); | ||
227 | data=p+2; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | int IRC::is_op(char* channel, char* nick) | ||
232 | { | ||
233 | channel_user* cup; | ||
234 | |||
235 | cup=chan_users; | ||
236 | |||
237 | while (cup) | ||
238 | { | ||
239 | if (!strcmp(cup->channel, channel) && !strcmp(cup->nick, nick)) | ||
240 | { | ||
241 | return cup->flags&IRC_USER_OP; | ||
242 | } | ||
243 | cup=cup->next; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | int IRC::is_voice(char* channel, char* nick) | ||
250 | { | ||
251 | channel_user* cup; | ||
252 | |||
253 | cup=chan_users; | ||
254 | |||
255 | while (cup) | ||
256 | { | ||
257 | if (!strcmp(cup->channel, channel) && !strcmp(cup->nick, nick)) | ||
258 | { | ||
259 | return cup->flags&IRC_USER_VOICE; | ||
260 | } | ||
261 | cup=cup->next; | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | void IRC::parse_irc_reply(char* data) | ||
268 | { | ||
269 | char* hostd; | ||
270 | char* cmd; | ||
271 | char* params; | ||
272 | char buffer[514]; | ||
273 | irc_reply_data hostd_tmp; | ||
274 | channel_user* cup; | ||
275 | char* p; | ||
276 | char* chan_temp; | ||
277 | |||
278 | hostd_tmp.target=0; | ||
279 | |||
280 | printf("%s\n", data); | ||
281 | |||
282 | if (data[0]==':') | ||
283 | { | ||
284 | hostd=&data[1]; | ||
285 | cmd=strchr(hostd, ' '); | ||
286 | if (!cmd) | ||
287 | return; | ||
288 | *cmd='\0'; | ||
289 | cmd++; | ||
290 | params=strchr(cmd, ' '); | ||
291 | if (params) | ||
292 | { | ||
293 | *params='\0'; | ||
294 | params++; | ||
295 | } | ||
296 | if (params[0]==':') | ||
297 | { | ||
298 | *params='\0'; | ||
299 | params++; | ||
300 | } | ||
301 | hostd_tmp.nick=hostd; | ||
302 | hostd_tmp.ident=strchr(hostd, '!'); | ||
303 | if (hostd_tmp.ident) | ||
304 | { | ||
305 | *hostd_tmp.ident='\0'; | ||
306 | hostd_tmp.ident++; | ||
307 | hostd_tmp.host=strchr(hostd_tmp.ident, '@'); | ||
308 | if (hostd_tmp.host) | ||
309 | { | ||
310 | *hostd_tmp.host='\0'; | ||
311 | hostd_tmp.host++; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | if (!strcmp(cmd, "JOIN")) | ||
316 | { | ||
317 | |||
318 | |||
319 | cup=chan_users; | ||
320 | if (cup) | ||
321 | { | ||
322 | while (cup->nick) | ||
323 | { | ||
324 | if (!cup->next) | ||
325 | { | ||
326 | cup->next=new channel_user; | ||
327 | cup->next->channel=0; | ||
328 | cup->next->flags=0; | ||
329 | cup->next->next=0; | ||
330 | cup->next->nick=0; | ||
331 | } | ||
332 | cup=cup->next; | ||
333 | } | ||
334 | cup->channel=new char[strlen(params)+1]; | ||
335 | strcpy(cup->channel, params); | ||
336 | cup->nick=new char[strlen(hostd_tmp.nick)+1]; | ||
337 | strcpy(cup->nick, hostd_tmp.nick); | ||
338 | } | ||
339 | } | ||
340 | else if (!strcmp(cmd, "PART")) | ||
341 | { | ||
342 | channel_user* d; | ||
343 | channel_user* prev; | ||
344 | |||
345 | d=0; | ||
346 | prev=0; | ||
347 | cup=chan_users; | ||
348 | while (cup) | ||
349 | { | ||
350 | if (!strcmp(cup->channel, params) && !strcmp(cup->nick, hostd_tmp.nick)) | ||
351 | { | ||
352 | d=cup; | ||
353 | break; | ||
354 | } | ||
355 | else | ||
356 | { | ||
357 | prev=cup; | ||
358 | } | ||
359 | cup=cup->next; | ||
360 | } | ||
361 | if (d) | ||
362 | { | ||
363 | if (d==chan_users) | ||
364 | { | ||
365 | chan_users=d->next; | ||
366 | if (d->channel) | ||
367 | delete [] d->channel; | ||
368 | if (d->nick) | ||
369 | delete [] d->nick; | ||
370 | delete d; | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | if (prev) | ||
375 | { | ||
376 | prev->next=d->next; | ||
377 | } | ||
378 | chan_users=d->next; | ||
379 | if (d->channel) | ||
380 | delete [] d->channel; | ||
381 | if (d->nick) | ||
382 | delete [] d->nick; | ||
383 | delete d; | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | else if (!strcmp(cmd, "QUIT")) | ||
388 | { | ||
389 | channel_user* d; | ||
390 | channel_user* prev; | ||
391 | |||
392 | d=0; | ||
393 | prev=0; | ||
394 | cup=chan_users; | ||
395 | while (cup) | ||
396 | { | ||
397 | if (!strcmp(cup->nick, hostd_tmp.nick)) | ||
398 | { | ||
399 | d=cup; | ||
400 | if (d==chan_users) | ||
401 | { | ||
402 | chan_users=d->next; | ||
403 | if (d->channel) | ||
404 | delete [] d->channel; | ||
405 | if (d->nick) | ||
406 | delete [] d->nick; | ||
407 | delete d; | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | if (prev) | ||
412 | { | ||
413 | prev->next=d->next; | ||
414 | } | ||
415 | if (d->channel) | ||
416 | delete [] d->channel; | ||
417 | if (d->nick) | ||
418 | delete [] d->nick; | ||
419 | delete d; | ||
420 | } | ||
421 | break; | ||
422 | } | ||
423 | else | ||
424 | { | ||
425 | prev=cup; | ||
426 | } | ||
427 | cup=cup->next; | ||
428 | } | ||
429 | } | ||
430 | else if (!strcmp(cmd, "MODE")) | ||
431 | { | ||
432 | char* chan; | ||
433 | char* changevars; | ||
434 | channel_user* cup; | ||
435 | channel_user* d; | ||
436 | char* tmp; | ||
437 | int i; | ||
438 | bool plus; | ||
439 | |||
440 | chan=params; | ||
441 | params=strchr(chan, ' '); | ||
442 | *params='\0'; | ||
443 | params++; | ||
444 | changevars=params; | ||
445 | params=strchr(changevars, ' '); | ||
446 | if (!params) | ||
447 | { | ||
448 | return; | ||
449 | } | ||
450 | if (chan[0]!='#') | ||
451 | { | ||
452 | return; | ||
453 | } | ||
454 | *params='\0'; | ||
455 | params++; | ||
456 | |||
457 | plus=false; | ||
458 | for (i=0; i<(signed)strlen(changevars); i++) | ||
459 | { | ||
460 | switch (changevars[i]) | ||
461 | { | ||
462 | case '+': | ||
463 | plus=true; | ||
464 | break; | ||
465 | case '-': | ||
466 | plus=false; | ||
467 | break; | ||
468 | case 'q': | ||
469 | break; | ||
470 | case 'o': | ||
471 | tmp=strchr(params, ' '); | ||
472 | if (tmp) | ||
473 | { | ||
474 | *tmp='\0'; | ||
475 | tmp++; | ||
476 | } | ||
477 | tmp=params; | ||
478 | if (plus) | ||
479 | { | ||
480 | // user has been opped (chan, params) | ||
481 | cup=chan_users; | ||
482 | d=0; | ||
483 | while (cup) | ||
484 | { | ||
485 | if (!strcmp(cup->channel, chan) && !strcmp(cup->nick, tmp)) | ||
486 | { | ||
487 | d=cup; | ||
488 | break; | ||
489 | } | ||
490 | cup=cup->next; | ||
491 | } | ||
492 | if (d) | ||
493 | { | ||
494 | d->flags=d->flags|IRC_USER_OP; | ||
495 | printf("MODE FOR %s ON %s IS %d\n", tmp, chan, d->flags); | ||
496 | } | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | // user has been deopped (chan, params) | ||
501 | cup=chan_users; | ||
502 | d=0; | ||
503 | while (cup) | ||
504 | { | ||
505 | if (!strcmp(cup->channel, chan) && !strcmp(cup->nick, tmp)) | ||
506 | { | ||
507 | d=cup; | ||
508 | break; | ||
509 | } | ||
510 | cup=cup->next; | ||
511 | } | ||
512 | if (d) | ||
513 | { | ||
514 | d->flags=d->flags^IRC_USER_OP; | ||
515 | } | ||
516 | } | ||
517 | params=tmp; | ||
518 | break; | ||
519 | case 'v': | ||
520 | tmp=strchr(params, ' '); | ||
521 | if (tmp) | ||
522 | { | ||
523 | *tmp='\0'; | ||
524 | tmp++; | ||
525 | } | ||
526 | tmp=params; | ||
527 | if (plus) | ||
528 | { | ||
529 | // user has been voiced | ||
530 | cup=chan_users; | ||
531 | d=0; | ||
532 | while (cup) | ||
533 | { | ||
534 | if (!strcmp(cup->channel, params) && !strcmp(cup->nick, hostd_tmp.nick)) | ||
535 | { | ||
536 | d=cup; | ||
537 | break; | ||
538 | } | ||
539 | cup=cup->next; | ||
540 | } | ||
541 | if (d) | ||
542 | { | ||
543 | d->flags=d->flags|IRC_USER_VOICE; | ||
544 | } | ||
545 | } | ||
546 | else | ||
547 | { | ||
548 | // user has been devoiced | ||
549 | cup=chan_users; | ||
550 | d=0; | ||
551 | while (cup) | ||
552 | { | ||
553 | if (!strcmp(cup->channel, params) && !strcmp(cup->nick, hostd_tmp.nick)) | ||
554 | { | ||
555 | d=cup; | ||
556 | break; | ||
557 | } | ||
558 | cup=cup->next; | ||
559 | } | ||
560 | if (d) | ||
561 | { | ||
562 | d->flags=d->flags^IRC_USER_VOICE; | ||
563 | } | ||
564 | } | ||
565 | params=tmp; | ||
566 | break; | ||
567 | default: | ||
568 | return; | ||
569 | break; | ||
570 | } | ||
571 | // ------------ END OF MODE --------------- | ||
572 | } | ||
573 | } | ||
574 | else if (!strcmp(cmd, "353")) | ||
575 | { | ||
576 | // receiving channel names list | ||
577 | if (!chan_users) | ||
578 | { | ||
579 | chan_users=new channel_user; | ||
580 | chan_users->next=0; | ||
581 | chan_users->nick=0; | ||
582 | chan_users->flags=0; | ||
583 | chan_users->channel=0; | ||
584 | } | ||
585 | cup=chan_users; | ||
586 | chan_temp=strchr(params, '#'); | ||
587 | if (chan_temp) | ||
588 | { | ||
589 | //chan_temp+=3; | ||
590 | p=strstr(chan_temp, " :"); | ||
591 | if (p) | ||
592 | { | ||
593 | *p='\0'; | ||
594 | p+=2; | ||
595 | while (strchr(p, ' ')) | ||
596 | { | ||
597 | char* tmp; | ||
598 | |||
599 | tmp=strchr(p, ' '); | ||
600 | *tmp='\0'; | ||
601 | tmp++; | ||
602 | while (cup->nick) | ||
603 | { | ||
604 | if (!cup->next) | ||
605 | { | ||
606 | cup->next=new channel_user; | ||
607 | cup->next->channel=0; | ||
608 | cup->next->flags=0; | ||
609 | cup->next->next=0; | ||
610 | cup->next->nick=0; | ||
611 | } | ||
612 | cup=cup->next; | ||
613 | } | ||
614 | if (p[0]=='@') | ||
615 | { | ||
616 | cup->flags=cup->flags|IRC_USER_OP; | ||
617 | p++; | ||
618 | } | ||
619 | else if (p[0]=='+') | ||
620 | { | ||
621 | cup->flags=cup->flags|IRC_USER_VOICE; | ||
622 | p++; | ||
623 | } | ||
624 | cup->nick=new char[strlen(p)+1]; | ||
625 | strcpy(cup->nick, p); | ||
626 | cup->channel=new char[strlen(chan_temp)+1]; | ||
627 | strcpy(cup->channel, chan_temp); | ||
628 | p=tmp; | ||
629 | } | ||
630 | while (cup->nick) | ||
631 | { | ||
632 | if (!cup->next) | ||
633 | { | ||
634 | cup->next=new channel_user; | ||
635 | cup->next->channel=0; | ||
636 | cup->next->flags=0; | ||
637 | cup->next->next=0; | ||
638 | cup->next->nick=0; | ||
639 | } | ||
640 | cup=cup->next; | ||
641 | } | ||
642 | if (p[0]=='@') | ||
643 | { | ||
644 | cup->flags=cup->flags|IRC_USER_OP; | ||
645 | p++; | ||
646 | } | ||
647 | else if (p[0]=='+') | ||
648 | { | ||
649 | cup->flags=cup->flags|IRC_USER_VOICE; | ||
650 | p++; | ||
651 | } | ||
652 | cup->nick=new char[strlen(p)+1]; | ||
653 | strcpy(cup->nick, p); | ||
654 | cup->channel=new char[strlen(chan_temp)+1]; | ||
655 | strcpy(cup->channel, chan_temp); | ||
656 | } | ||
657 | } | ||
658 | } | ||
659 | else if (!strcmp(cmd, "NOTICE")) | ||
660 | { | ||
661 | hostd_tmp.target=params; | ||
662 | params=strchr(hostd_tmp.target, ' '); | ||
663 | if (params) | ||
664 | *params='\0'; | ||
665 | params++; | ||
666 | #ifdef __IRC_DEBUG__ | ||
667 | printf("%s >-%s- %s\n", hostd_tmp.nick, hostd_tmp.target, ¶ms[1]); | ||
668 | #endif | ||
669 | } | ||
670 | else if (!strcmp(cmd, "PRIVMSG")) | ||
671 | { | ||
672 | hostd_tmp.target=params; | ||
673 | params=strchr(hostd_tmp.target, ' '); | ||
674 | if (!params) | ||
675 | return; | ||
676 | *(params++)='\0'; | ||
677 | #ifdef __IRC_DEBUG__ | ||
678 | printf("%s: <%s> %s\n", hostd_tmp.target, hostd_tmp.nick, ¶ms[1]); | ||
679 | #endif | ||
680 | } | ||
681 | else if (!strcmp(cmd, "NICK")) | ||
682 | { | ||
683 | if (!strcmp(hostd_tmp.nick, cur_nick)) | ||
684 | { | ||
685 | delete [] cur_nick; | ||
686 | cur_nick=new char[strlen(params)+1]; | ||
687 | strcpy(cur_nick, params); | ||
688 | } | ||
689 | |||
690 | cup=chan_users; | ||
691 | while (cup) | ||
692 | { | ||
693 | if (!strcmp(cup->nick, hostd_tmp.nick)) | ||
694 | { | ||
695 | cup->nick=new char[strlen(params)+1]; | ||
696 | strcpy(cup->nick, params); | ||
697 | } | ||
698 | cup=cup->next; | ||
699 | } | ||
700 | } | ||
701 | /* else if (!strcmp(cmd, "")) | ||
702 | { | ||
703 | #ifdef __IRC_DEBUG__ | ||
704 | #endif | ||
705 | } */ | ||
706 | call_hook(cmd, params, &hostd_tmp); | ||
707 | } | ||
708 | else | ||
709 | { | ||
710 | cmd=data; | ||
711 | data=strchr(cmd, ' '); | ||
712 | if (!data) | ||
713 | return; | ||
714 | *data='\0'; | ||
715 | params=data+1; | ||
716 | |||
717 | if (!strcmp(cmd, "PING")) | ||
718 | { | ||
719 | if (!params) | ||
720 | return; | ||
721 | fprintf(dataout, "PONG %s\r\n", ¶ms[1]); | ||
722 | #ifdef __IRC_DEBUG__ | ||
723 | printf("Ping received, pong sent.\n"); | ||
724 | #endif | ||
725 | fflush(dataout); | ||
726 | } | ||
727 | else | ||
728 | { | ||
729 | hostd_tmp.host=0; | ||
730 | hostd_tmp.ident=0; | ||
731 | hostd_tmp.nick=0; | ||
732 | hostd_tmp.target=0; | ||
733 | call_hook(cmd, params, &hostd_tmp); | ||
734 | } | ||
735 | } | ||
736 | } | ||
737 | |||
738 | void IRC::call_hook(char* irc_command, char* params, irc_reply_data* hostd) | ||
739 | { | ||
740 | irc_command_hook* p; | ||
741 | |||
742 | if (!hooks) | ||
743 | return; | ||
744 | |||
745 | p=hooks; | ||
746 | while (p) | ||
747 | { | ||
748 | if (!strcmp(p->irc_command, irc_command)) | ||
749 | { | ||
750 | (*(p->function))(params, hostd, this); | ||
751 | p=0; | ||
752 | } | ||
753 | else | ||
754 | { | ||
755 | p=p->next; | ||
756 | } | ||
757 | } | ||
758 | } | ||
759 | |||
760 | int IRC::notice(char* target, char* message) | ||
761 | { | ||
762 | if (!connected) | ||
763 | return 1; | ||
764 | fprintf(dataout, "NOTICE %s :%s\r\n", target, message); | ||
765 | return fflush(dataout); | ||
766 | } | ||
767 | |||
768 | int IRC::notice(char* fmt, ...) | ||
769 | { | ||
770 | va_list argp; | ||
771 | char* target; | ||
772 | |||
773 | if (!connected) | ||
774 | return 1; | ||
775 | va_start(argp, fmt); | ||
776 | fprintf(dataout, "NOTICE %s :", fmt); | ||
777 | vfprintf(dataout, va_arg(argp, char*), argp); | ||
778 | va_end(argp); | ||
779 | fprintf(dataout, "\r\n"); | ||
780 | return fflush(dataout); | ||
781 | } | ||
782 | |||
783 | int IRC::privmsg(char* target, char* message) | ||
784 | { | ||
785 | if (!connected) | ||
786 | return 1; | ||
787 | fprintf(dataout, "PRIVMSG %s :%s\r\n", target, message); | ||
788 | return fflush(dataout); | ||
789 | } | ||
790 | |||
791 | int IRC::privmsg(char* fmt, ...) | ||
792 | { | ||
793 | va_list argp; | ||
794 | char* target; | ||
795 | |||
796 | if (!connected) | ||
797 | return 1; | ||
798 | va_start(argp, fmt); | ||
799 | fprintf(dataout, "PRIVMSG %s :", fmt); | ||
800 | vfprintf(dataout, va_arg(argp, char*), argp); | ||
801 | va_end(argp); | ||
802 | fprintf(dataout, "\r\n"); | ||
803 | return fflush(dataout); | ||
804 | } | ||
805 | |||
806 | |||
807 | int IRC::join(char* channel) | ||
808 | { | ||
809 | if (!connected) | ||
810 | return 1; | ||
811 | fprintf(dataout, "JOIN %s\r\n", channel); | ||
812 | return fflush(dataout); | ||
813 | } | ||
814 | |||
815 | int IRC::part(char* channel) | ||
816 | { | ||
817 | if (!connected) | ||
818 | return 1; | ||
819 | fprintf(dataout, "PART %s\r\n", channel); | ||
820 | return fflush(dataout); | ||
821 | } | ||
822 | |||
823 | int IRC::kick(char* channel, char* nick) | ||
824 | { | ||
825 | if (!connected) | ||
826 | return 1; | ||
827 | fprintf(dataout, "KICK %s %s\r\n", channel, nick); | ||
828 | return fflush(dataout); | ||
829 | } | ||
830 | |||
831 | int IRC::raw(char* data) | ||
832 | { | ||
833 | if (!connected) | ||
834 | return 1; | ||
835 | fprintf(dataout, "%s\r\n", data); | ||
836 | return fflush(dataout); | ||
837 | } | ||
838 | |||
839 | int IRC::kick(char* channel, char* nick, char* message) | ||
840 | { | ||
841 | if (!connected) | ||
842 | return 1; | ||
843 | fprintf(dataout, "KICK %s %s :%s\r\n", channel, nick, message); | ||
844 | return fflush(dataout); | ||
845 | } | ||
846 | |||
847 | int IRC::mode(char* channel, char* modes, char* targets) | ||
848 | { | ||
849 | if (!connected) | ||
850 | return 1; | ||
851 | if (!targets) | ||
852 | fprintf(dataout, "MODE %s %s\r\n", channel, modes); | ||
853 | else | ||
854 | fprintf(dataout, "MODE %s %s %s\r\n", channel, modes, targets); | ||
855 | return fflush(dataout); | ||
856 | } | ||
857 | |||
858 | int IRC::mode(char* modes) | ||
859 | { | ||
860 | if (!connected) | ||
861 | return 1; | ||
862 | mode(cur_nick, modes, 0); | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | int IRC::nick(char* newnick) | ||
867 | { | ||
868 | if (!connected) | ||
869 | return 1; | ||
870 | fprintf(dataout, "NICK %s\r\n", newnick); | ||
871 | return fflush(dataout); | ||
872 | } | ||
873 | |||
874 | char* IRC::current_nick() | ||
875 | { | ||
876 | return cur_nick; | ||
877 | } | ||
diff --git a/IRC.h b/IRC.h new file mode 100755 index 0000000..09df766 --- /dev/null +++ b/IRC.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | cpIRC - C++ class based IRC protocol wrapper | ||
3 | Copyright (C) 2003 Iain Sheppard | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Contacting the author: | ||
20 | ~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | |||
22 | email: iainsheppard@yahoo.co.uk | ||
23 | IRC: #magpie @ irc.quakenet.org | ||
24 | */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | #include <stdarg.h> | ||
28 | |||
29 | #define __CPIRC_VERSION__ 0.1 | ||
30 | #define __IRC_DEBUG__ 1 | ||
31 | |||
32 | #define IRC_USER_VOICE 1 | ||
33 | #define IRC_USER_HALFOP 2 | ||
34 | #define IRC_USER_OP 4 | ||
35 | |||
36 | struct irc_reply_data | ||
37 | { | ||
38 | char* nick; | ||
39 | char* ident; | ||
40 | char* host; | ||
41 | char* target; | ||
42 | }; | ||
43 | |||
44 | struct irc_command_hook | ||
45 | { | ||
46 | char* irc_command; | ||
47 | int (*function)(char*, irc_reply_data*, void*); | ||
48 | irc_command_hook* next; | ||
49 | }; | ||
50 | |||
51 | struct channel_user | ||
52 | { | ||
53 | char* nick; | ||
54 | char* channel; | ||
55 | char flags; | ||
56 | channel_user* next; | ||
57 | }; | ||
58 | |||
59 | class IRC | ||
60 | { | ||
61 | public: | ||
62 | IRC(); | ||
63 | ~IRC(); | ||
64 | int start(char* server, int port, char* nick, char* user, char* name, char* pass); | ||
65 | void disconnect(); | ||
66 | int privmsg(char* target, char* message); | ||
67 | int privmsg(char* fmt, ...); | ||
68 | int notice(char* target, char* message); | ||
69 | int notice(char* fmt, ...); | ||
70 | int join(char* channel); | ||
71 | int part(char* channel); | ||
72 | int kick(char* channel, char* nick); | ||
73 | int kick(char* channel, char* nick, char* message); | ||
74 | int mode(char* modes); | ||
75 | int mode(char* channel, char* modes, char* targets); | ||
76 | int nick(char* newnick); | ||
77 | int quit(char* quit_message); | ||
78 | int raw(char* data); | ||
79 | void hook_irc_command(char* cmd_name, int (*function_ptr)(char*, irc_reply_data*, void*)); | ||
80 | int message_loop(); | ||
81 | int is_op(char* channel, char* nick); | ||
82 | int is_voice(char* channel, char* nick); | ||
83 | char* current_nick(); | ||
84 | private: | ||
85 | void call_hook(char* irc_command, char*params, irc_reply_data* hostd); | ||
86 | /*void call_the_hook(irc_command_hook* hook, char* irc_command, char*params, irc_host_data* hostd);*/ | ||
87 | void parse_irc_reply(char* data); | ||
88 | void split_to_replies(char* data); | ||
89 | void insert_irc_command_hook(irc_command_hook* hook, char* cmd_name, int (*function_ptr)(char*, irc_reply_data*, void*)); | ||
90 | void delete_irc_command_hook(irc_command_hook* cmd_hook); | ||
91 | int irc_socket; | ||
92 | bool connected; | ||
93 | bool sentnick; | ||
94 | bool sentpass; | ||
95 | bool sentuser; | ||
96 | char* cur_nick; | ||
97 | FILE* dataout; | ||
98 | FILE* datain; | ||
99 | channel_user* chan_users; | ||
100 | irc_command_hook* hooks; | ||
101 | }; | ||
diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..99f8cad --- /dev/null +++ b/main.cpp | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * File: main.cpp | ||
3 | * Author: hatkirby | ||
4 | * | ||
5 | * Created on August 10, 2013, 12:32 PM | ||
6 | */ | ||
7 | |||
8 | #include <stdlib.h> | ||
9 | #include "IRC.h" | ||
10 | #include <time.h> | ||
11 | #include <signal.h> | ||
12 | #include <cstring> | ||
13 | #include <string> | ||
14 | #include <dirent.h> | ||
15 | #include <deque> | ||
16 | #include <algorithm> | ||
17 | #include <yaml-cpp/yaml.h> | ||
18 | |||
19 | /* | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | char* hostname, nick, port, password, channel; | ||
24 | |||
25 | char* _(const char* str) | ||
26 | { | ||
27 | char* res = new char[strlen(str)+1]; | ||
28 | strcpy(res, str); | ||
29 | return res; | ||
30 | } | ||
31 | |||
32 | int message(char* params, irc_reply_data* hostd, void* conn) | ||
33 | { | ||
34 | std::string str(params); | ||
35 | std::string thetime(asctime(gettime())); | ||
36 | thetime = thetime.substr(4,15); | ||
37 | |||
38 | if (*hostd->target != '#') | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | // Examine content of strings | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | int end_of_motd(char* params, irc_reply_data* hostd, void* conn) | ||
49 | { | ||
50 | IRC* irc_conn = (IRC*) conn; | ||
51 | irc_conn->privmsg(_("NickServ"), strcat(_("Identify "), password)); | ||
52 | irc_conn->join(channel); | ||
53 | irc_conn->hook_irc_command(_("PRIVMSG"), &message); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | void terminate(int param) | ||
59 | { | ||
60 | exit(1); | ||
61 | } | ||
62 | |||
63 | int main(int argc, char** argv) | ||
64 | { | ||
65 | atexit(end_logging); | ||
66 | signal(SIGTERM, terminate); | ||
67 | |||
68 | YAML::Node config = YAML::LoadFile("config.yml"); | ||
69 | hostname = _(config["hostname"].as<std::string>().c_str()); | ||
70 | port = _(config["port"].as<std::string>().c_str()); | ||
71 | nick = _(config["nick"].as<std::string>().c_str()); | ||
72 | password = _(config["password"].as<std::string>().c_str()); | ||
73 | channel = _(config["password"].as<std::string>().c_str()); | ||
74 | |||
75 | IRC conn; | ||
76 | conn.hook_irc_command("266", &end_of_motd); | ||
77 | conn.start(hostname, port, nick, nick, nick, password); | ||
78 | conn.message_loop(); | ||
79 | |||
80 | return (EXIT_SUCCESS); | ||
81 | } | ||