added small static content replay (channels will follow)
[TransparentIRC.git] / src / UserClient.c
index c0d3af58daa4cf33e4cfaaebd0a8aee2325ce635..bb43793981b87fa6fdadf84f9d64aa5670fd2085 100644 (file)
  * You should have received a copy of the GNU General Public License 
  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
  */
-#include "UserClient.c"
+#include "UserClient.h"
 #include "IOHandler.h"
+#include "ServerSocket.h"
+#include "UserSession.h"
+#include "tools.h"
+#include "IRCClient.h"
 
 static void userclient_callback(struct IOEvent *event);
 
@@ -28,22 +32,54 @@ void userclient_accepted(struct ServerSocket *server, int sockfd) {
     iofd->state = IO_CONNECTED;
     iofd->read_lines = 1;
     iohandler_update(iofd);
-    client = malloc(sizeof(*client));
+    client = calloc(1, sizeof(*client));
     client->iofd = iofd;
+    iofd->data = client;
     client->server = server;
     server->clientcount++;
     
+    struct UserLogin *login = calloc(1, sizeof(*login));
+    client->user = login;
+    login->client = client;
+    
+    
     //add UserClient to the list
-    sock->prev = NULL;
-    sock->next = serversockets;
-    serversockets->prev = sock;
-    serversockets = sock;
+    client->prev = NULL;
+    client->next = userclients;
+    if(userclients)
+        userclients->prev = client;
+    userclients = client;
     
     //let's say hello to the client
-    iohandler_printf(iofd, "NOTICE AUTH :*** TransparentIRC " TRANSIRC_VERSION " (use /quote transirc for more information)");
+    iohandler_printf(iofd, "NOTICE AUTH :*** [TransparentIRC] TransparentIRC v" TRANSIRC_VERSION " (use /quote transirc for more information)");
 }
 
 void userclient_close(struct UserClient *client) {
+    if(client->flags & USERCLIENT_LOGGED_IN) {
+        usersession_client_close(client->user);
+    } else {
+        struct UserLogin *login = client->user;
+        if(client->flags & USERCLIENT_LOGIN_PROCESSING) {
+            usersession_login_abort(login);
+        }
+        if(login->username)
+            free(login->username);
+        if(login->realname)
+            free(login->realname);
+        if(login->password)
+            free(login->password);
+        if(login->nick)
+            free(login->nick);
+        if(login->reject_reason)
+            free(login->reject_reason);
+        if(login->session_class)
+            free(login->session_class);
+        if(login->bind_address)
+            free(login->bind_address);
+        if(login->server_address)
+            free(login->server_address);
+        free(login);
+    }
     iohandler_close(client->iofd);
     client->server->clientcount--;
     if(client->prev)
@@ -52,12 +88,14 @@ void userclient_close(struct UserClient *client) {
         userclients = client->next;
     if(client->next)
         client->next->prev = client->prev;
+    
     free(client);
 }
 
 void userclient_close_server(struct ServerSocket *server, int keep_clients) {
     struct UserClient *client, *next_client;
     for(client = userclients; client; client = next_client) {
+        next_client = client->next;
         if(client->server == server) {
             if(keep_clients)
                 client->server = NULL;
@@ -67,14 +105,91 @@ void userclient_close_server(struct ServerSocket *server, int keep_clients) {
     }
 }
 
+static void userclient_recv(struct UserClient *client, char *line) {
+    if(!stricmplen(line, "TRANSIRC ", 9)) {
+        /*
+        char *argv[MAXNUMPARAMS];
+        int argc = parse_line(line, argv, 1);
+        */
+        
+    } else if(!(client->flags & USERCLIENT_LOGGED_IN)) {
+        struct UserLogin *login = client->user;
+        char *argv[MAXNUMPARAMS];
+        int argc = parse_line(line, argv, 1);
+        if(argc < 3) return;
+        if(!stricmp(argv[1], "PASS")) {
+            char *delimiter = strchr(argv[2], ':');
+            if(login->password)
+                free(login->password);
+            if(delimiter) {
+                *delimiter = '\0';
+                delimiter++;
+                if(login->username)
+                    free(login->username);
+                login->username = strdup(argv[2]);
+                login->password = strdup(delimiter);
+            } else 
+                login->password = strdup(argv[2]);
+        } else if(!stricmp(argv[1], "USER") && argc >= 6) {
+            if(!login->username)
+                login->username = strdup(argv[2]);
+            login->realname = strdup(argv[5]);
+        } else if(!stricmp(argv[1], "NICK")) {
+            if(login->nick)
+                free(login->nick);
+            login->nick = strdup(argv[2]);
+            if(!login->password) {
+                iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] You need to send your LOC data. Try /quote PASS <username>:<password>");
+            }
+        }
+        if(login->username && login->password && login->nick && login->realname && !(client->flags & USERCLIENT_LOGIN_PROCESSING)) {
+            //try to login
+            iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Checking login...");
+            usersession_login(login);
+        }
+    } else {
+        struct UserSession *session = client->user;
+        if(!stricmplen(line, "QUIT", 4))
+            return;
+        
+        if(session->irc)
+            ircclient_send(session->irc, line);
+    }
+}
+
+void userclient_login_failed(struct UserLogin *login, char *reason) {
+    iohandler_printf(login->client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login rejected");
+    userclient_close(login->client);
+}
+
+void userclient_login_successful(struct UserLogin *login, struct UserSession *session, int recover) {
+    struct UserClient *client = login->client;
+    iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login accepted.");
+    if(login->username)
+        free(login->username);
+    if(login->password)
+        free(login->password);
+    if(login->nick)
+        free(login->nick);
+    free(login);
+    client->user = session;
+    client->flags |= USERCLIENT_LOGGED_IN;
+    if(recover) {
+        iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Recovering previous link (Nick: %s).", session->nick);
+        ircclient_recover_session(session);
+    }
+}
+
 static void userclient_callback(struct IOEvent *event) {
+    struct UserClient *client = event->iofd->data;
     switch(event->type) {
         case IOEVENT_RECV:
-            char *line = event->data.recv_str;
-            iohandler_printf(event->iofd, "reply: %s", line);
+            userclient_recv(client, event->data.recv_str);
             break;
         case IOEVENT_CLOSED:
-            userclient_close(event->iofd);
+            userclient_close(client);
+            break;
+        default:
             break;
     }
 }