--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/server.c Thu Jun 30 21:39:31 2005 +0000
@@ -0,0 +1,459 @@
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/poll.h>
+
+#include "list.h"
+#include "parsecfg.h"
+#include "screen.h"
+#include "socket.h"
+#include "utf8.h"
+#include "server.h"
+#include "harddefines.h"
+#include "utils.h"
+#include "buddies.h"
+
+#define JABBERPORT 5222
+
+
+/* Desc: poll data from server
+ *
+ * In : socket
+ * Out : pending buffer (or NULL if no incoming data)
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *srv_poll(int sock)
+{
+ struct pollfd sock_p;
+ sock_p.fd = sock;
+ sock_p.events = POLLIN | POLLPRI;
+ sock_p.revents = 0;
+ poll(&sock_p, 1, 0);
+
+ if (sock_p.revents) {
+ return sk_recv(sock);
+ }
+
+ return NULL;
+}
+
+
+/* Desc: resolve host
+ *
+ * In : hostname
+ * Out : 32bit address (or 0 if error)
+ *
+ * Note: -
+ */
+static u_long srv_resolve(const char *host)
+{
+ long i;
+ struct hostent *he;
+
+ if ((i = inet_addr(host)) == -1) {
+ if (!(he = gethostbyname(host)))
+ return 0;
+ else
+ return (*(u_long *) he->h_addr);
+ }
+
+ return i;
+}
+
+
+/* Desc: connect to jabber server
+ *
+ * In : config
+ * Out : socket (or -1 on error)
+ *
+ * Note: if port is -1, the default Jabber port will be used
+ */
+int srv_connect(const char *server, unsigned int port)
+{
+ struct sockaddr_in name;
+ int sock;
+
+ if (server == NULL) {
+ fprintf(stderr, "You must supply a server name\n\r");
+ return -1;
+ }
+
+ if (port == -1U) {
+ port = JABBERPORT;
+ }
+
+ name.sin_family = AF_INET;
+ name.sin_port = htons(port);
+
+ if (!(name.sin_addr.s_addr = srv_resolve(server))) {
+ fprintf(stderr, "Cant resolve \"%s\"\n", server);
+ return -1;
+ }
+
+ if ((sock = sk_conn((struct sockaddr *) &name)) < 0) {
+ fprintf(stderr, "Cant connect to \"%s:%u\"\n", server, port);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+/* Desc: login into jabber server
+ *
+ * In : socket, servername, user, password, resource
+ * Out : idsession
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *srv_login(int sock, const char *server, const char *user,
+ const char *pass, const char *resource)
+{
+ char *stringtosend = malloc(2048);
+ char *response, *aux;
+ char *idsession = malloc(128);
+ int pos = 0;
+
+ memset(stringtosend, 0, 2048);
+ strcpy(stringtosend, "<?xml version='1.0' encoding='UTF-8' ?>");
+ strcat(stringtosend, "<stream:stream to='");
+ strcat(stringtosend, server);
+ strcat(stringtosend, "' xmlns='jabber:client' xmlns:stream='");
+ strcat(stringtosend, "http://etherx.jabber.org/streams'>\n");
+
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:132)");
+ return NULL;
+ }
+ response = sk_recv(sock);
+ if (strstr(response, "error")) {
+ /* fprintf(stderr, "Response not valid:\n%s\n\n", response); */
+ scr_CreatePopup("Error",
+ "El servidor no esta respondiendo correctamente",
+ 60, 0, NULL);
+ return NULL;
+ }
+ aux = response;
+ while (strncmp(aux, "id", 2))
+ aux++;
+ pos = 0;
+ aux += 4;
+ while (strncmp(aux, "'", 1)) {
+ aux++;
+ pos++;
+ }
+ aux -= pos;
+ strncpy(idsession, aux, pos);
+
+ free(response);
+
+ strcpy(stringtosend, "<iq type='set' id='1000'>");
+ strcat(stringtosend, "<query xmlns='jabber:iq:auth'>");
+ strcat(stringtosend, "<username>");
+ strcat(stringtosend, user);
+ strcat(stringtosend, "</username><password>");
+ strcat(stringtosend, pass);
+ strcat(stringtosend, "</password><resource>");
+ strcat(stringtosend, resource);
+ strcat(stringtosend, "</resource></query></iq>\n");
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:167)");
+ return NULL;
+ }
+ response = sk_recv(sock);
+ if (strstr(response, "error")) {
+/* fprintf(stderr, "Response not valid:\n%s\n\n", response);*/
+ scr_CreatePopup("Error",
+ "Cuenta no creada o contraseņa incorrecta", 60, 0,
+ NULL);
+ scr_CreatePopup("Info", "Intentando crear la cuenta...", 60, 0, NULL);
+
+
+ strcpy(stringtosend, "<iq type='set' id='reg' to='");
+ strcat(stringtosend, server);
+ strcat(stringtosend, "'>");
+ strcat(stringtosend, "<query xmlns='jabber:iq:register'>");
+ strcat(stringtosend, "<username>");
+ strcat(stringtosend, user);
+ strcat(stringtosend, "</username><password>");
+ strcat(stringtosend, pass);
+ strcat(stringtosend, "</password>");
+ strcat(stringtosend, "</query></iq>\n");
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:167)");
+ return NULL;
+ }
+
+ response = sk_recv(sock);
+ scr_TerminateCurses();
+ printf("Reinicie cabber!\n\n");
+ return NULL;
+ }
+ free(response);
+ free(stringtosend);
+
+ return idsession;
+}
+
+
+/* Desc: broadcast presence
+ *
+ * In : socket, presence string
+ * Out : ?
+ *
+ * Note: see `sk_send' for output values
+ */
+int srv_setpresence(int sock, const char *type)
+{
+ int rv;
+ char *str = malloc(1024);
+
+ sprintf(str, "<presence><status>%s</status></presence>", type);
+ if (!(rv = sk_send(sock, str))) {
+ perror("senddata (server.c:199)");
+ }
+ free(str);
+
+ return rv;
+}
+
+
+/* Desc: request roster
+ *
+ * In : socket
+ * Out : roster string
+ *
+ * Note: it is up to the caller to free the returned string
+ */
+char *srv_getroster(int sock)
+{
+ char *str = malloc(1024);
+
+ strcpy(str, "<iq type='get' id='1001'><query xmlns='");
+ strcat(str, "jabber:iq:roster'/></iq>\n");
+ if (!sk_send(sock, str)) {
+ perror("senddata (server.c:222)");
+ return NULL;
+ }
+ free(str);
+
+ return sk_recv(sock);
+}
+
+
+/* Desc: send text to buddy
+ *
+ * In : socket, destination jid, text, source jid
+ * Out : 0 = ok
+ *
+ * Note: -
+ */
+int
+srv_sendtext(int sock, const char *to, const char *text, const char *from)
+{
+ char *stringtosend = malloc(2048);
+ char *utf8inputline = utf8_encode(text);
+
+ sprintf(stringtosend,
+ "<message from='%s' to='%s' type='chat'><body>%s</body></message>",
+ from, to, utf8inputline);
+ if (!sk_send(sock, stringtosend)) {
+ perror("senddata (server.c:247)");
+ return -1;
+ }
+
+ free(stringtosend);
+ free(utf8inputline);
+ return 0;
+}
+
+int check_io(int fd1, int fd2)
+{
+ int n = 0, i;
+ fd_set fds;
+ int io_pending = 0;
+
+ i = fd1;
+ if (fd2 > fd1)
+ i = fd2;
+
+ FD_ZERO(&fds);
+ if (fd1 >= 0)
+ FD_SET(fd1, &fds);
+ else
+ fd1 = 0;
+ if (fd2 >= 0)
+ FD_SET(fd2, &fds);
+ else
+ fd2 = 0;
+
+ if (fd2 == 0 && io_pending)
+ n = 2;
+ else if (select(i + 1, &fds, NULL, NULL, NULL) > 0)
+ n = 1 * (FD_ISSET(fd1, &fds) > 0) + 2 * (FD_ISSET(fd2, &fds) > 0);
+
+ return (n);
+}
+
+/* Desc: read data from server
+ *
+ * In : socket
+ * Out : ptr to newly allocated srv_msg struct
+ *
+ * Note: returns NULL if no input from server
+ */
+srv_msg *readserver(int sock)
+{
+ char *buffer = sk_recv(sock);
+
+ if (buffer != NULL) {
+ srv_msg *msg = calloc(1, sizeof(srv_msg));
+ char *to = getattr(buffer, "to='");
+ char *from = getattr(buffer, "from='");
+ char *id = getattr(buffer, "id='");
+ char *type = getattr(buffer, "type='");
+ char *body = gettag(buffer, "body");
+ char *status = gettag(buffer, "status");
+ char *show = gettag(buffer, "show");
+ char *line = (char *) malloc(1024);
+ memset(line, 0, 1024);
+
+ /* scan for buffer */
+ if (!strncmp(buffer, "<message", 8)) { /* manage messages */
+ msg->m = SM_MESSAGE;
+ } else if (!strncmp(buffer, "<presence", 9)) { /* manage presences */
+ msg->m = SM_PRESENCE;
+ if (!strncmp(type, "UNK", 3)) { /* assume online */
+ msg->connected = FLAG_BUDDY_CONNECTED;
+ } else if (!strncmp(type, "unavailable", 11)) { /* offline */
+ msg->connected = 0;
+ }
+ } else {
+ msg->m = SM_UNHANDLED;
+ }
+
+ /* write the parsed buffer */
+ switch (msg->m) {
+ case SM_MESSAGE:
+ {
+ char *aux = strstr(from, "/");
+ if (aux)
+ *aux = '\0';
+ msg->from = from;
+ msg->body = utf8_decode(body);
+ ut_WriteLog("+OK [%s]\n", buffer);
+ }
+ break;
+
+ case SM_PRESENCE:
+ {
+ char *aux = strstr(from, "/");
+ if (aux)
+ *aux = '\0';
+ msg->from = from;
+ }
+ break;
+
+ case SM_UNHANDLED:
+ ut_WriteLog("BAD [%s]\n", buffer);
+ break;
+
+ }
+ free(line);
+ if (strncmp(to, "UNK", 3))
+ free(to);
+ if (strncmp(from, "UNK", 3) && (msg->m != SM_MESSAGE)
+ && (msg->m != SM_PRESENCE))
+ free(from);
+ if (strncmp(id, "UNK", 3))
+ free(id);
+ if (strncmp(type, "UNK", 3))
+ free(type);
+ if (strncmp(body, "UNK", 3))
+ free(body);
+ if (strncmp(status, "UNK", 3))
+ free(status);
+ if (strncmp(show, "UNK", 3))
+ free(show);
+ free(buffer);
+
+ return msg;
+ }
+
+ return NULL;
+}
+
+void srv_AddBuddy(int sock, char *jidname)
+{
+ char *buffer = (char *) malloc(1024);
+ char *p, *str;
+ int i;
+
+ memset(buffer, 0, 1024);
+ strcpy(buffer, "<iq type='set'>");
+ strcat(buffer, " <query xmlns='jabber:iq:roster'>");
+ strcat(buffer, " <item");
+ strcat(buffer, " jid='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' name='");
+
+ str = strdup(jidname);
+ p = strstr(str, "@");
+ if (p)
+ *p = '\0';
+ strcat(buffer, str);
+ strcat(buffer, "'/></query></iq>");
+ sk_send(sock, buffer);
+ free(buffer);
+
+ for (i = 0; i < 2; i++) {
+ buffer = sk_recv(sock);
+ ut_WriteLog("[Subscription]: %s\n", buffer);
+ free(buffer);
+ }
+
+ buffer = (char *) malloc(1024);
+ memset(buffer, 0, 1024);
+ strcpy(buffer, "<presence to='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' type='subscribe'>");
+ strcat(buffer, "<status>I would like to add you!</status></presence>");
+ sk_send(sock, buffer);
+ free(buffer);
+
+ buffer = sk_recv(sock);
+ ut_WriteLog("[Subscription]: %s\n", buffer);
+ free(buffer);
+
+ buffer = (char *) malloc(1024);
+ memset(buffer, 0, 1024);
+ strcpy(buffer, "<presence to='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' type='subscribed'/>");
+ sk_send(sock, buffer);
+ free(buffer);
+
+ buffer = sk_recv(sock);
+ ut_WriteLog("[Subscription]: %s\n", buffer);
+ free(buffer);
+}
+
+void srv_DelBuddy(int sock, char *jidname)
+{
+ char *buffer = (char *) malloc(1024);
+
+ strcpy(buffer, "<iq type='set'><query xmlns='jabber:iq:roster'>");
+ strcat(buffer, "<item jid='");
+ strcat(buffer, jidname);
+ strcat(buffer, "' subscription='remove'/></query></iq>");
+
+ sk_send(sock, buffer);
+ free(buffer);
+
+ buffer = sk_recv(sock);
+ ut_WriteLog("[SubscriptionRemove]: %s\n", buffer);
+ free(buffer);
+}