2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
22 /* local macros for launching event handlers */
23 #define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); }
25 /* prototypes of the local functions */
26 static void startElement(void *userdata
, const char *name
, const char **attribs
);
27 static void endElement(void *userdata
, const char *name
);
28 static void charData(void *userdata
, const char *s
, int slen
);
31 * jab_new -- initialize a new jabber connection
34 * user -- jabber id of the user
35 * pass -- password of the user
38 * a pointer to the connection structure
39 * or NULL if allocations failed
41 jconn
jab_new(char *user
, char *pass
)
46 if(!user
) return(NULL
);
50 j
= pmalloc_x(p
, sizeof(jconn_struct
), 0);
54 j
->user
= jid_new(p
, user
);
55 j
->pass
= pstrdup(p
, pass
);
57 j
->state
= JCONN_STATE_OFF
;
65 * jab_delete -- free a jabber connection
71 void jab_delete(jconn j
)
80 * jab_state_handler -- set callback handler for state change
84 * h -- name of the handler function
86 void jab_state_handler(jconn j
, jconn_state_h h
)
94 * jab_packet_handler -- set callback handler for incoming packets
98 * h -- name of the handler function
100 void jab_packet_handler(jconn j
, jconn_packet_h h
)
109 * jab_start -- start connection
115 void jab_start(jconn j
)
120 if(!j
|| j
->state
!= JCONN_STATE_OFF
) return;
122 j
->parser
= XML_ParserCreate(NULL
);
123 XML_SetUserData(j
->parser
, (void *)j
);
124 XML_SetElementHandler(j
->parser
, startElement
, endElement
);
125 XML_SetCharacterDataHandler(j
->parser
, charData
);
127 j
->fd
= make_netsocket(5222, j
->user
->server
, NETSOCKET_CLIENT
);
129 STATE_EVT(JCONN_STATE_OFF
)
132 j
->state
= JCONN_STATE_CONNECTED
;
133 STATE_EVT(JCONN_STATE_CONNECTED
)
136 x
= jutil_header(NS_CLIENT
, j
->user
->server
);
138 /* this is ugly, we can create the string here instead of jutil_header */
139 /* what do you think about it? -madcat */
143 jab_send_raw(j
,"<?xml version='1.0'?>");
147 j
->state
= JCONN_STATE_ON
;
148 STATE_EVT(JCONN_STATE_ON
)
153 * jab_stop -- stop connection
158 void jab_stop(jconn j
)
160 if(!j
|| j
->state
== JCONN_STATE_OFF
) return;
162 j
->state
= JCONN_STATE_OFF
;
165 XML_ParserFree(j
->parser
);
169 * jab_getfd -- get file descriptor of connection socket
175 * fd of the socket or -1 if socket was not connected
177 int jab_getfd(jconn j
)
186 * jab_getjid -- get jid structure of user
191 jid
jab_getjid(jconn j
)
199 /* jab_getsid -- get stream id
200 * This is the id of server's <stream:stream> tag and used for
201 * digest authorization.
206 char *jab_getsid(jconn j
)
215 * jab_getid -- get a unique id
220 char *jab_getid(jconn j
)
222 snprintf(j
->idbuf
, 8, "%d", j
->id
++);
227 * jab_send -- send xml data
231 * x -- xmlnode structure
233 void jab_send(jconn j
, xmlnode x
)
235 if (j
&& j
->state
!= JCONN_STATE_OFF
)
237 char *buf
= xmlnode2str(x
);
238 if (buf
) write(j
->fd
, buf
, strlen(buf
));
240 printf ("out: %s\n", buf
);
246 * jab_send_raw -- send a string
252 void jab_send_raw(jconn j
, const char *str
)
254 if (j
&& j
->state
!= JCONN_STATE_OFF
)
255 write(j
->fd
, str
, strlen(str
));
257 printf ("out: %s\n", str
);
262 * jab_recv -- read and parse incoming data
267 void jab_recv(jconn j
)
269 static char buf
[4096];
272 if(!j
|| j
->state
== JCONN_STATE_OFF
)
275 len
= read(j
->fd
, buf
, sizeof(buf
)-1);
280 printf (" in: %s\n", buf
);
282 XML_Parse(j
->parser
, buf
, len
, 0);
286 STATE_EVT(JCONN_STATE_OFF
);
292 * jab_poll -- check socket for incoming data
296 * timeout -- poll timeout
298 void jab_poll(jconn j
, int timeout
)
303 if (!j
|| j
->state
== JCONN_STATE_OFF
)
311 if (select(j
->fd
+ 1, &fds
, NULL
, NULL
, NULL
) > 0)
317 tv
.tv_usec
= timeout
;
318 if (select(j
->fd
+ 1, &fds
, NULL
, NULL
, &tv
) > 0)
324 * jab_auth -- authorize user
330 * id of the iq packet
332 char *jab_auth(jconn j
)
335 char *hash
, *user
, *id
;
339 x
= jutil_iqnew(JPACKET__SET
, NS_AUTH
);
341 xmlnode_put_attrib(x
, "id", id
);
342 y
= xmlnode_get_tag(x
,"query");
344 user
= j
->user
->user
;
348 z
= xmlnode_insert_tag(y
, "username");
349 xmlnode_insert_cdata(z
, user
, -1);
352 z
= xmlnode_insert_tag(y
, "resource");
353 xmlnode_insert_cdata(z
, j
->user
->resource
, -1);
357 z
= xmlnode_insert_tag(y
, "digest");
358 hash
= pmalloc(x
->p
, strlen(j
->sid
)+strlen(j
->pass
)+1);
359 strcpy(hash
, j
->sid
);
360 strcat(hash
, j
->pass
);
361 hash
= shahash(hash
);
362 xmlnode_insert_cdata(z
, hash
, 40);
366 z
= xmlnode_insert_tag(y
, "password");
367 xmlnode_insert_cdata(z
, j
->pass
, -1);
376 * jab_reg -- register user
382 * id of the iq packet
384 char *jab_reg(jconn j
)
387 char *hash
, *user
, *id
;
389 if (!j
) return(NULL
);
391 x
= jutil_iqnew(JPACKET__SET
, NS_REGISTER
);
393 xmlnode_put_attrib(x
, "id", id
);
394 y
= xmlnode_get_tag(x
,"query");
396 user
= j
->user
->user
;
400 z
= xmlnode_insert_tag(y
, "username");
401 xmlnode_insert_cdata(z
, user
, -1);
404 z
= xmlnode_insert_tag(y
, "resource");
405 xmlnode_insert_cdata(z
, j
->user
->resource
, -1);
409 z
= xmlnode_insert_tag(y
, "password");
410 xmlnode_insert_cdata(z
, j
->pass
, -1);
415 j
->state
= JCONN_STATE_ON
;
416 STATE_EVT(JCONN_STATE_ON
)
421 /* local functions */
423 static void startElement(void *userdata
, const char *name
, const char **attribs
)
426 jconn j
= (jconn
)userdata
;
430 /* Append the node to the current one */
431 x
= xmlnode_insert_tag(j
->current
, name
);
432 xmlnode_put_expat_attribs(x
, attribs
);
438 x
= xmlnode_new_tag(name
);
439 xmlnode_put_expat_attribs(x
, attribs
);
440 if(strcmp(name
, "stream:stream") == 0) {
441 /* special case: name == stream:stream */
442 /* id attrib of stream is stored for digest auth */
443 j
->sid
= xmlnode_get_attrib(x
, "id");
444 /* STATE_EVT(JCONN_STATE_AUTH) */
451 static void endElement(void *userdata
, const char *name
)
453 jconn j
= (jconn
)userdata
;
457 if(j
->current
== NULL
) {
458 /* we got </stream:stream> */
459 STATE_EVT(JCONN_STATE_OFF
)
463 x
= xmlnode_get_parent(j
->current
);
467 /* it is time to fire the event */
468 p
= jpacket_new(j
->current
);
471 (j
->on_packet
)(j
, p
);
473 xmlnode_free(j
->current
);
479 static void charData(void *userdata
, const char *s
, int slen
)
481 jconn j
= (jconn
)userdata
;
484 xmlnode_insert_cdata(j
->current
, s
, slen
);