added small static content replay (channels will follow)
[TransparentIRC.git] / src / UserClient.c
1 /* UserClient.c - TransparentIRC 0.1
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "UserClient.h"
18 #include "IOHandler.h"
19 #include "ServerSocket.h"
20 #include "UserSession.h"
21 #include "tools.h"
22 #include "IRCClient.h"
23
24 static void userclient_callback(struct IOEvent *event);
25
26 static struct UserClient *userclients = NULL;
27
28 void userclient_accepted(struct ServerSocket *server, int sockfd) {
29     struct UserClient *client;
30     struct IODescriptor *iofd = iohandler_add(sockfd, IOTYPE_CLIENT, userclient_callback);
31     if(!iofd) return;
32     iofd->state = IO_CONNECTED;
33     iofd->read_lines = 1;
34     iohandler_update(iofd);
35     client = calloc(1, sizeof(*client));
36     client->iofd = iofd;
37     iofd->data = client;
38     client->server = server;
39     server->clientcount++;
40     
41     struct UserLogin *login = calloc(1, sizeof(*login));
42     client->user = login;
43     login->client = client;
44     
45     
46     //add UserClient to the list
47     client->prev = NULL;
48     client->next = userclients;
49     if(userclients)
50         userclients->prev = client;
51     userclients = client;
52     
53     //let's say hello to the client
54     iohandler_printf(iofd, "NOTICE AUTH :*** [TransparentIRC] TransparentIRC v" TRANSIRC_VERSION " (use /quote transirc for more information)");
55 }
56
57 void userclient_close(struct UserClient *client) {
58     if(client->flags & USERCLIENT_LOGGED_IN) {
59         usersession_client_close(client->user);
60     } else {
61         struct UserLogin *login = client->user;
62         if(client->flags & USERCLIENT_LOGIN_PROCESSING) {
63             usersession_login_abort(login);
64         }
65         if(login->username)
66             free(login->username);
67         if(login->realname)
68             free(login->realname);
69         if(login->password)
70             free(login->password);
71         if(login->nick)
72             free(login->nick);
73         if(login->reject_reason)
74             free(login->reject_reason);
75         if(login->session_class)
76             free(login->session_class);
77         if(login->bind_address)
78             free(login->bind_address);
79         if(login->server_address)
80             free(login->server_address);
81         free(login);
82     }
83     iohandler_close(client->iofd);
84     client->server->clientcount--;
85     if(client->prev)
86         client->prev->next = client->next;
87     else
88         userclients = client->next;
89     if(client->next)
90         client->next->prev = client->prev;
91     
92     free(client);
93 }
94
95 void userclient_close_server(struct ServerSocket *server, int keep_clients) {
96     struct UserClient *client, *next_client;
97     for(client = userclients; client; client = next_client) {
98         next_client = client->next;
99         if(client->server == server) {
100             if(keep_clients)
101                 client->server = NULL;
102             else
103                 userclient_close(client);
104         }
105     }
106 }
107
108 static void userclient_recv(struct UserClient *client, char *line) {
109     if(!stricmplen(line, "TRANSIRC ", 9)) {
110         /*
111         char *argv[MAXNUMPARAMS];
112         int argc = parse_line(line, argv, 1);
113         */
114         
115     } else if(!(client->flags & USERCLIENT_LOGGED_IN)) {
116         struct UserLogin *login = client->user;
117         char *argv[MAXNUMPARAMS];
118         int argc = parse_line(line, argv, 1);
119         if(argc < 3) return;
120         if(!stricmp(argv[1], "PASS")) {
121             char *delimiter = strchr(argv[2], ':');
122             if(login->password)
123                 free(login->password);
124             if(delimiter) {
125                 *delimiter = '\0';
126                 delimiter++;
127                 if(login->username)
128                     free(login->username);
129                 login->username = strdup(argv[2]);
130                 login->password = strdup(delimiter);
131             } else 
132                 login->password = strdup(argv[2]);
133         } else if(!stricmp(argv[1], "USER") && argc >= 6) {
134             if(!login->username)
135                 login->username = strdup(argv[2]);
136             login->realname = strdup(argv[5]);
137         } else if(!stricmp(argv[1], "NICK")) {
138             if(login->nick)
139                 free(login->nick);
140             login->nick = strdup(argv[2]);
141             if(!login->password) {
142                 iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] You need to send your LOC data. Try /quote PASS <username>:<password>");
143             }
144         }
145         if(login->username && login->password && login->nick && login->realname && !(client->flags & USERCLIENT_LOGIN_PROCESSING)) {
146             //try to login
147             iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Checking login...");
148             usersession_login(login);
149         }
150     } else {
151         struct UserSession *session = client->user;
152         if(!stricmplen(line, "QUIT", 4))
153             return;
154         
155         if(session->irc)
156             ircclient_send(session->irc, line);
157     }
158 }
159
160 void userclient_login_failed(struct UserLogin *login, char *reason) {
161     iohandler_printf(login->client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login rejected");
162     userclient_close(login->client);
163 }
164
165 void userclient_login_successful(struct UserLogin *login, struct UserSession *session, int recover) {
166     struct UserClient *client = login->client;
167     iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login accepted.");
168     if(login->username)
169         free(login->username);
170     if(login->password)
171         free(login->password);
172     if(login->nick)
173         free(login->nick);
174     free(login);
175     client->user = session;
176     client->flags |= USERCLIENT_LOGGED_IN;
177     if(recover) {
178         iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Recovering previous link (Nick: %s).", session->nick);
179         ircclient_recover_session(session);
180     }
181 }
182
183 static void userclient_callback(struct IOEvent *event) {
184     struct UserClient *client = event->iofd->data;
185     switch(event->type) {
186         case IOEVENT_RECV:
187             userclient_recv(client, event->data.recv_str);
188             break;
189         case IOEVENT_CLOSED:
190             userclient_close(client);
191             break;
192         default:
193             break;
194     }
195 }