Mercurial > hg
comparison mcabber/src/server.c @ 24:e88b15cbf2de
[/trunk] Changeset 40 by mikael
* Change structure -> src directory for mcabber source code...
author | mikael |
---|---|
date | Sun, 27 Mar 2005 20:16:02 +0000 |
parents | |
children | 8588f5a4b638 |
comparison
equal
deleted
inserted
replaced
23:d7107507424b | 24:e88b15cbf2de |
---|---|
1 #include <arpa/inet.h> | |
2 #include <netdb.h> | |
3 #include <stdio.h> | |
4 #include <stdlib.h> | |
5 #include <string.h> | |
6 #include <sys/poll.h> | |
7 | |
8 #include "list.h" | |
9 #include "parsecfg.h" | |
10 #include "screen.h" | |
11 #include "socket.h" | |
12 #include "utf8.h" | |
13 #include "server.h" | |
14 #include "harddefines.h" | |
15 #include "utils.h" | |
16 #include "buddies.h" | |
17 | |
18 #define JABBERPORT 5222 | |
19 | |
20 | |
21 /* Desc: poll data from server | |
22 * | |
23 * In : socket | |
24 * Out : pending buffer (or NULL if no incoming data) | |
25 * | |
26 * Note: it is up to the caller to free the returned string | |
27 */ | |
28 char *srv_poll(int sock) | |
29 { | |
30 struct pollfd sock_p; | |
31 sock_p.fd = sock; | |
32 sock_p.events = POLLIN | POLLPRI; | |
33 sock_p.revents = 0; | |
34 poll(&sock_p, 1, 0); | |
35 | |
36 if (sock_p.revents) { | |
37 return sk_recv(sock); | |
38 } | |
39 | |
40 return NULL; | |
41 } | |
42 | |
43 | |
44 /* Desc: resolve host | |
45 * | |
46 * In : hostname | |
47 * Out : 32bit address (or 0 if error) | |
48 * | |
49 * Note: - | |
50 */ | |
51 static u_long srv_resolve(const char *host) | |
52 { | |
53 long i; | |
54 struct hostent *he; | |
55 | |
56 if ((i = inet_addr(host)) == -1) { | |
57 if (!(he = gethostbyname(host))) | |
58 return 0; | |
59 else | |
60 return (*(u_long *) he->h_addr); | |
61 } | |
62 | |
63 return i; | |
64 } | |
65 | |
66 | |
67 /* Desc: connect to jabber server | |
68 * | |
69 * In : config | |
70 * Out : socket (or -1 on error) | |
71 * | |
72 * Note: if port is -1, the default Jabber port will be used | |
73 */ | |
74 int srv_connect(const char *server, unsigned int port) | |
75 { | |
76 struct sockaddr_in name; | |
77 int sock; | |
78 | |
79 if (server == NULL) { | |
80 fprintf(stderr, "You must supply a server name\n\r"); | |
81 return -1; | |
82 } | |
83 | |
84 if (port == -1U) { | |
85 port = JABBERPORT; | |
86 } | |
87 | |
88 name.sin_family = AF_INET; | |
89 name.sin_port = htons(port); | |
90 | |
91 if (!(name.sin_addr.s_addr = srv_resolve(server))) { | |
92 fprintf(stderr, "Cant resolve \"%s\"\n", server); | |
93 return -1; | |
94 } | |
95 | |
96 if ((sock = sk_conn((struct sockaddr *) &name)) < 0) { | |
97 fprintf(stderr, "Can't connect to \"%s:%u\"\n", server, port); | |
98 return -1; | |
99 } | |
100 | |
101 return sock; | |
102 } | |
103 | |
104 | |
105 /* Desc: login into jabber server | |
106 * | |
107 * In : socket, servername, user, password, resource | |
108 * Out : idsession | |
109 * | |
110 * Note: it is up to the caller to free the returned string | |
111 */ | |
112 char *srv_login(int sock, const char *server, const char *user, | |
113 const char *pass, const char *resource) | |
114 { | |
115 char *stringtosend = malloc(2048); | |
116 char *response, *aux; | |
117 char *idsession = malloc(128); | |
118 int pos = 0; | |
119 | |
120 memset(stringtosend, 0, 2048); | |
121 strcpy(stringtosend, "<?xml version='1.0' encoding='UTF-8' ?>"); | |
122 strcat(stringtosend, "<stream:stream to='"); | |
123 strcat(stringtosend, server); | |
124 strcat(stringtosend, "' xmlns='jabber:client' xmlns:stream='"); | |
125 strcat(stringtosend, "http://etherx.jabber.org/streams'>\n"); | |
126 | |
127 if (!sk_send(sock, stringtosend)) { | |
128 perror("senddata (server.c:132)"); | |
129 return NULL; | |
130 } | |
131 response = sk_recv(sock); | |
132 if (strstr(response, "error")) { | |
133 /* fprintf(stderr, "Response not valid:\n%s\n\n", response); */ | |
134 scr_CreatePopup("Error", | |
135 "Bad answer from the server", 60, 0, NULL); | |
136 return NULL; | |
137 } | |
138 aux = response; | |
139 while (strncmp(aux, "id", 2)) | |
140 aux++; | |
141 pos = 0; | |
142 aux += 4; | |
143 while (strncmp(aux, "'", 1)) { | |
144 aux++; | |
145 pos++; | |
146 } | |
147 aux -= pos; | |
148 strncpy(idsession, aux, pos); | |
149 | |
150 free(response); | |
151 | |
152 strcpy(stringtosend, "<iq type='set' id='1000'>"); | |
153 strcat(stringtosend, "<query xmlns='jabber:iq:auth'>"); | |
154 strcat(stringtosend, "<username>"); | |
155 strcat(stringtosend, user); | |
156 strcat(stringtosend, "</username><password>"); | |
157 strcat(stringtosend, pass); | |
158 strcat(stringtosend, "</password><resource>"); | |
159 strcat(stringtosend, resource); | |
160 strcat(stringtosend, "</resource></query></iq>\n"); | |
161 if (!sk_send(sock, stringtosend)) { | |
162 perror("senddata (server.c:167)"); | |
163 return NULL; | |
164 } | |
165 response = sk_recv(sock); | |
166 if (strstr(response, "error")) { | |
167 /* fprintf(stderr, "Response not valid:\n%s\n\n", response);*/ | |
168 scr_CreatePopup("Error", | |
169 "Account doesn't exist, or bad password", 60, 0, | |
170 NULL); | |
171 | |
172 /* | |
173 scr_CreatePopup("Info", "Trying to create the account...", 60, 0, NULL); | |
174 | |
175 strcpy(stringtosend, "<iq type='set' id='reg' to='"); | |
176 strcat(stringtosend, server); | |
177 strcat(stringtosend, "'>"); | |
178 strcat(stringtosend, "<query xmlns='jabber:iq:register'>"); | |
179 strcat(stringtosend, "<username>"); | |
180 strcat(stringtosend, user); | |
181 strcat(stringtosend, "</username><password>"); | |
182 strcat(stringtosend, pass); | |
183 strcat(stringtosend, "</password>"); | |
184 strcat(stringtosend, "</query></iq>\n"); | |
185 if (!sk_send(sock, stringtosend)) { | |
186 perror("senddata (server.c:167)"); | |
187 return NULL; | |
188 } | |
189 | |
190 response = sk_recv(sock); | |
191 */ | |
192 scr_TerminateCurses(); | |
193 printf("Reinicie cabber!\n\n"); | |
194 return NULL; | |
195 } | |
196 free(response); | |
197 free(stringtosend); | |
198 | |
199 return idsession; | |
200 } | |
201 | |
202 | |
203 /* Desc: broadcast presence | |
204 * | |
205 * In : socket, presence string | |
206 * Out : ? | |
207 * | |
208 * Note: see `sk_send' for output values | |
209 */ | |
210 int srv_setpresence(int sock, const char *type) | |
211 { | |
212 int rv; | |
213 char *str = malloc(1024); | |
214 | |
215 sprintf(str, "<presence><status>%s</status></presence>", type); | |
216 if (!(rv = sk_send(sock, str))) { | |
217 perror("senddata (server.c:199)"); | |
218 } | |
219 free(str); | |
220 | |
221 return rv; | |
222 } | |
223 | |
224 | |
225 /* Desc: request roster | |
226 * | |
227 * In : socket | |
228 * Out : roster string | |
229 * | |
230 * Note: it is up to the caller to free the returned string | |
231 */ | |
232 char *srv_getroster(int sock) | |
233 { | |
234 char *str = malloc(1024); | |
235 | |
236 strcpy(str, "<iq type='get' id='1001'><query xmlns='"); | |
237 strcat(str, "jabber:iq:roster'/></iq>\n"); | |
238 if (!sk_send(sock, str)) { | |
239 perror("senddata (server.c:222)"); | |
240 return NULL; | |
241 } | |
242 free(str); | |
243 | |
244 return sk_recv(sock); | |
245 } | |
246 | |
247 | |
248 /* Desc: send text to buddy | |
249 * | |
250 * In : socket, destination jid, text, source jid | |
251 * Out : 0 = ok | |
252 * | |
253 * Note: - | |
254 */ | |
255 int | |
256 srv_sendtext(int sock, const char *to, const char *text, const char *from) | |
257 { | |
258 char *stringtosend = malloc(2048); | |
259 char *utf8inputline = utf8_encode(text); | |
260 | |
261 sprintf(stringtosend, | |
262 "<message from='%s' to='%s' type='chat'><body>%s</body></message>", | |
263 from, to, utf8inputline); | |
264 if (!sk_send(sock, stringtosend)) { | |
265 perror("senddata (server.c:247)"); | |
266 return -1; | |
267 } | |
268 | |
269 free(stringtosend); | |
270 free(utf8inputline); | |
271 return 0; | |
272 } | |
273 | |
274 int check_io(int fd1, int fd2) | |
275 { | |
276 int n = 0, i; | |
277 fd_set fds; | |
278 int io_pending = 0; | |
279 | |
280 i = fd1; | |
281 if (fd2 > fd1) | |
282 i = fd2; | |
283 | |
284 FD_ZERO(&fds); | |
285 if (fd1 >= 0) | |
286 FD_SET(fd1, &fds); | |
287 else | |
288 fd1 = 0; | |
289 if (fd2 >= 0) | |
290 FD_SET(fd2, &fds); | |
291 else | |
292 fd2 = 0; | |
293 | |
294 if (fd2 == 0 && io_pending) | |
295 n = 2; | |
296 else if (select(i + 1, &fds, NULL, NULL, NULL) > 0) | |
297 n = 1 * (FD_ISSET(fd1, &fds) > 0) + 2 * (FD_ISSET(fd2, &fds) > 0); | |
298 | |
299 return (n); | |
300 } | |
301 | |
302 /* Desc: read data from server | |
303 * | |
304 * In : socket | |
305 * Out : ptr to newly allocated srv_msg struct | |
306 * | |
307 * Note: returns NULL if no input from server | |
308 */ | |
309 srv_msg *readserver(int sock) | |
310 { | |
311 char *buffer = sk_recv(sock); | |
312 | |
313 if (buffer != NULL) { | |
314 srv_msg *msg = calloc(1, sizeof(srv_msg)); | |
315 char *to = getattr(buffer, "to='"); | |
316 char *from = getattr(buffer, "from='"); | |
317 char *id = getattr(buffer, "id='"); | |
318 char *type = getattr(buffer, "type='"); | |
319 char *body = gettag(buffer, "body"); | |
320 char *status = gettag(buffer, "status"); | |
321 char *show = gettag(buffer, "show"); | |
322 char *line = (char *) malloc(1024); | |
323 memset(line, 0, 1024); | |
324 | |
325 /* scan for buffer */ | |
326 if (!strncmp(buffer, "<message", 8)) { /* manage messages */ | |
327 msg->m = SM_MESSAGE; | |
328 } else if (!strncmp(buffer, "<presence", 9)) { /* manage presences */ | |
329 msg->m = SM_PRESENCE; | |
330 if (!strncmp(type, "UNK", 3)) { /* assume online */ | |
331 msg->connected = FLAG_BUDDY_CONNECTED; | |
332 } else if (!strncmp(type, "unavailable", 11)) { /* offline */ | |
333 msg->connected = 0; | |
334 } | |
335 } else { | |
336 msg->m = SM_UNHANDLED; | |
337 } | |
338 | |
339 /* write the parsed buffer */ | |
340 switch (msg->m) { | |
341 case SM_MESSAGE: | |
342 { | |
343 char *aux = strstr(from, "/"); | |
344 if (aux) | |
345 *aux = '\0'; | |
346 msg->from = from; | |
347 msg->body = utf8_decode(body); | |
348 ut_WriteLog("+OK [%s]\n", buffer); | |
349 } | |
350 break; | |
351 | |
352 case SM_PRESENCE: | |
353 { | |
354 char *aux = strstr(from, "/"); | |
355 if (aux) | |
356 *aux = '\0'; | |
357 msg->from = from; | |
358 } | |
359 break; | |
360 | |
361 case SM_UNHANDLED: | |
362 ut_WriteLog("BAD [%s]\n", buffer); | |
363 break; | |
364 | |
365 } | |
366 free(line); | |
367 if (strncmp(to, "UNK", 3)) | |
368 free(to); | |
369 if (strncmp(from, "UNK", 3) && (msg->m != SM_MESSAGE) | |
370 && (msg->m != SM_PRESENCE)) | |
371 free(from); | |
372 if (strncmp(id, "UNK", 3)) | |
373 free(id); | |
374 if (strncmp(type, "UNK", 3)) | |
375 free(type); | |
376 if (strncmp(body, "UNK", 3)) | |
377 free(body); | |
378 if (strncmp(status, "UNK", 3)) | |
379 free(status); | |
380 if (strncmp(show, "UNK", 3)) | |
381 free(show); | |
382 free(buffer); | |
383 | |
384 return msg; | |
385 } | |
386 | |
387 return NULL; | |
388 } | |
389 | |
390 void srv_AddBuddy(int sock, char *jidname) | |
391 { | |
392 char *buffer = (char *) malloc(1024); | |
393 char *p, *str; | |
394 int i; | |
395 | |
396 memset(buffer, 0, 1024); | |
397 strcpy(buffer, "<iq type='set'>"); | |
398 strcat(buffer, " <query xmlns='jabber:iq:roster'>"); | |
399 strcat(buffer, " <item"); | |
400 strcat(buffer, " jid='"); | |
401 strcat(buffer, jidname); | |
402 strcat(buffer, "' name='"); | |
403 | |
404 str = strdup(jidname); | |
405 p = strstr(str, "@"); | |
406 if (p) | |
407 *p = '\0'; | |
408 strcat(buffer, str); | |
409 strcat(buffer, "'/></query></iq>"); | |
410 sk_send(sock, buffer); | |
411 free(buffer); | |
412 | |
413 for (i = 0; i < 2; i++) { | |
414 buffer = sk_recv(sock); | |
415 ut_WriteLog("[Subscription]: %s\n", buffer); | |
416 free(buffer); | |
417 } | |
418 | |
419 buffer = (char *) malloc(1024); | |
420 memset(buffer, 0, 1024); | |
421 strcpy(buffer, "<presence to='"); | |
422 strcat(buffer, jidname); | |
423 strcat(buffer, "' type='subscribe'>"); | |
424 strcat(buffer, "<status>I would like to add you!</status></presence>"); | |
425 sk_send(sock, buffer); | |
426 free(buffer); | |
427 | |
428 buffer = sk_recv(sock); | |
429 ut_WriteLog("[Subscription]: %s\n", buffer); | |
430 free(buffer); | |
431 | |
432 buffer = (char *) malloc(1024); | |
433 memset(buffer, 0, 1024); | |
434 strcpy(buffer, "<presence to='"); | |
435 strcat(buffer, jidname); | |
436 strcat(buffer, "' type='subscribed'/>"); | |
437 sk_send(sock, buffer); | |
438 free(buffer); | |
439 | |
440 buffer = sk_recv(sock); | |
441 ut_WriteLog("[Subscription]: %s\n", buffer); | |
442 free(buffer); | |
443 } | |
444 | |
445 void srv_DelBuddy(int sock, char *jidname) | |
446 { | |
447 char *buffer = (char *) malloc(1024); | |
448 | |
449 strcpy(buffer, "<iq type='set'><query xmlns='jabber:iq:roster'>"); | |
450 strcat(buffer, "<item jid='"); | |
451 strcat(buffer, jidname); | |
452 strcat(buffer, "' subscription='remove'/></query></iq>"); | |
453 | |
454 sk_send(sock, buffer); | |
455 free(buffer); | |
456 | |
457 buffer = sk_recv(sock); | |
458 ut_WriteLog("[SubscriptionRemove]: %s\n", buffer); | |
459 free(buffer); | |
460 } |