stropheruby 0.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/event.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* event.c
2
2
  ** strophe XMPP client library -- event loop and management
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -31,7 +31,7 @@
31
31
  * example, a GUI program will already include an event loop to
32
32
  * process UI events from users, and xmpp_run_once() would be called
33
33
  * from an idle function.
34
- */
34
+ */
35
35
 
36
36
  #include <stdio.h>
37
37
  #include <stdlib.h>
@@ -49,7 +49,6 @@
49
49
 
50
50
  #include "strophe.h"
51
51
  #include "common.h"
52
- #include "parser.h"
53
52
 
54
53
  #ifndef DEFAULT_TIMEOUT
55
54
  /** @def DEFAULT_TIMEOUT
@@ -84,7 +83,6 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
84
83
  int towrite;
85
84
  char buf[4096];
86
85
  uint64_t next;
87
- long usec;
88
86
 
89
87
  if (ctx->loop_status == XMPP_LOOP_QUIT) return -2;
90
88
  ctx->loop_status = XMPP_LOOP_RUNNING;
@@ -130,16 +128,16 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
130
128
  }
131
129
 
132
130
  } else {
133
- ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
131
+ ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
134
132
 
135
- if (ret < 0 && !sock_is_recoverable(sock_error())) {
136
- /* an error occured */
137
- conn->error = sock_error();
138
- break;
139
- } else if (ret < towrite) {
140
- /* not all data could be sent now */
141
- if (ret >= 0) sq->written += ret;
142
- break;
133
+ if (ret < 0 && !sock_is_recoverable(sock_error())) {
134
+ /* an error occured */
135
+ conn->error = sock_error();
136
+ break;
137
+ } else if (ret < towrite) {
138
+ /* not all data could be sent now */
139
+ if (ret >= 0) sq->written += ret;
140
+ break;
143
141
  }
144
142
  }
145
143
 
@@ -170,7 +168,7 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
170
168
  /* reset parsers if needed */
171
169
  for (connitem = ctx->connlist; connitem; connitem = connitem->next) {
172
170
  if (connitem->conn->reset_parser)
173
- conn_parser_reset(connitem->conn);
171
+ parser_reset(connitem->conn);
174
172
  }
175
173
 
176
174
 
@@ -179,7 +177,7 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
179
177
  to be called */
180
178
  next = handler_fire_timed(ctx);
181
179
 
182
- usec = ((next < timeout) ? next : timeout) * 1000;
180
+ long usec = ((next < timeout) ? next : timeout) * 1000;
183
181
  tv.tv_sec = usec / 1000000;
184
182
  tv.tv_usec = usec % 1000000;
185
183
 
@@ -225,15 +223,19 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
225
223
 
226
224
  /* select errored */
227
225
  if (ret < 0) {
228
- if (!sock_is_recoverable(sock_error()))
229
- xmpp_error(ctx, "xmpp", "event watcher internal error %d",
230
- sock_error());
226
+ if (!sock_is_recoverable(sock_error())) {
227
+ xmpp_error(ctx, "xmpp", "event watcher internal error %d",
228
+ sock_error());
229
+ conn->error = sock_error();
231
230
  return -1;
232
231
  }
232
+ }
233
233
 
234
234
  /* no events happened */
235
- if (ret == 0) return 1;
236
-
235
+ if (ret == 0) {
236
+ return 1;
237
+ }
238
+
237
239
  /* process events */
238
240
  connitem = ctx->connlist;
239
241
  while (connitem) {
@@ -245,7 +247,8 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
245
247
  /* connection complete */
246
248
 
247
249
  /* check for error */
248
- if (sock_connect_error(conn->sock) != 0) {
250
+ conn->error = sock_connect_error(conn->sock);
251
+ if (conn->error != 0) {
249
252
  /* connection failed */
250
253
  xmpp_debug(ctx, "xmpp", "connection failed");
251
254
  conn_disconnect(conn);
@@ -266,15 +269,16 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
266
269
  if (conn->tls) {
267
270
  ret = tls_read(conn->tls, buf, 4096);
268
271
  } else {
269
- ret = sock_read(conn->sock, buf, 4096);
272
+ ret = sock_read(conn->sock, buf, 4096);
270
273
  }
271
274
 
272
275
  if (ret > 0) {
273
- ret = parser_feed(conn->parser, buf, ret);
276
+ ret = XML_Parse(conn->parser, buf, ret, 0);
274
277
  if (!ret) {
275
278
  /* parse error, we need to shut down */
276
279
  /* FIXME */
277
280
  xmpp_debug(ctx, "xmpp", "parse error, disconnecting");
281
+ conn -> error = -1;
278
282
  conn_disconnect(conn);
279
283
  }
280
284
  } else {
@@ -286,13 +290,13 @@ int xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
286
290
  conn_disconnect(conn);
287
291
  }
288
292
  } else {
289
- /* return of 0 means socket closed by server */
290
- xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
291
- conn->error = ECONNRESET;
292
- conn_disconnect(conn);
293
- }
293
+ /* return of 0 means socket closed by server */
294
+ xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
295
+ conn->error = ECONNRESET;
296
+ conn_disconnect(conn);
294
297
  }
295
298
  }
299
+ }
296
300
 
297
301
  break;
298
302
  case XMPP_STATE_DISCONNECTED:
data/ext/handler.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* handler.c
2
2
  ** strophe XMPP client library -- event handler management
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -66,7 +66,6 @@ void handler_fire_stanza(xmpp_conn_t * const conn,
66
66
  hash_drop(conn->id_handlers, id);
67
67
  hash_add(conn->id_handlers, id, next);
68
68
  }
69
- xmpp_free(conn->ctx, item->id);
70
69
  xmpp_free(conn->ctx, item);
71
70
  item = NULL;
72
71
  }
@@ -90,7 +89,7 @@ void handler_fire_stanza(xmpp_conn_t * const conn,
90
89
  while (item) {
91
90
  /* skip newly added handlers */
92
91
  if (!item->enabled) {
93
- prev = item;
92
+ prev = item;
94
93
  item = item->next;
95
94
  continue;
96
95
  }
@@ -112,9 +111,6 @@ void handler_fire_stanza(xmpp_conn_t * const conn,
112
111
  prev->next = item->next;
113
112
  else
114
113
  conn->handlers = item->next;
115
- if (item->ns) xmpp_free(conn->ctx, item->ns);
116
- if (item->name) xmpp_free(conn->ctx, item->name);
117
- if (item->type) xmpp_free(conn->ctx, item->type);
118
114
  xmpp_free(conn->ctx, item);
119
115
  item = NULL;
120
116
  }
data/ext/hash.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* hash.c
2
2
  ** strophe XMPP client library -- hash table implementation
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -14,7 +14,7 @@
14
14
 
15
15
  /** @file
16
16
  * Hash tables.
17
- */
17
+ */
18
18
 
19
19
  #include <stdlib.h>
20
20
  #include <string.h>
data/ext/hash.h CHANGED
@@ -1,7 +1,7 @@
1
1
  /* hash.h
2
2
  ** strophe XMPP client library -- hash table interface
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -14,7 +14,7 @@
14
14
 
15
15
  /** @file
16
16
  * Hash table API.
17
- */
17
+ */
18
18
 
19
19
  #ifndef __LIBSTROPHE_HASH_H__
20
20
  #define __LIBSTROPHE_HASH_H__
data/ext/jid.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* jid.c
2
2
  ** strophe XMPP client library -- helper functions for parsing JIDs
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
data/ext/md5.c CHANGED
@@ -47,7 +47,7 @@
47
47
  * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
48
48
  * initialization constants.
49
49
  */
50
- void MD5Init(struct MD5Context *ctx)
50
+ void sasl_MD5Init(struct MD5Context *ctx)
51
51
  {
52
52
  ctx->buf[0] = 0x67452301;
53
53
  ctx->buf[1] = 0xefcdab89;
@@ -64,7 +64,7 @@ void MD5Init(struct MD5Context *ctx)
64
64
  * Update context to reflect the concatenation of another buffer full
65
65
  * of bytes.
66
66
  */
67
- void MD5Update(struct MD5Context *ctx, unsigned char const *buf, uint32_t len)
67
+ void sasl_MD5Update(struct MD5Context *ctx, unsigned char const *buf, uint32_t len)
68
68
  {
69
69
  uint32_t t;
70
70
 
@@ -110,7 +110,7 @@ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, uint32_t len)
110
110
  * Final wrapup - pad to 64-byte boundary with the bit pattern
111
111
  * 1 0* (64-bit count of bits processed, MSB-first)
112
112
  */
113
- void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
113
+ void sasl_MD5Final(unsigned char digest[16], struct MD5Context *ctx)
114
114
  {
115
115
  unsigned count;
116
116
  unsigned char *p;
@@ -272,7 +272,7 @@ void MD5Transform(uint32_t buf[4], const unsigned char inext[64],
272
272
 
273
273
  #include <stdio.h>
274
274
 
275
- void MD5DumpBytes(unsigned char *b, int len)
275
+ void sasl_MD5DumpBytes(unsigned char *b, int len)
276
276
  {
277
277
  int i;
278
278
  for (i=0; i<len; i++) {
data/ext/md5.h CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  /** @file
8
8
  * MD5 hash API.
9
- */
9
+ */
10
10
 
11
11
  #ifndef MD5_H
12
12
  #define MD5_H
@@ -27,15 +27,22 @@ struct MD5Context {
27
27
  unsigned char in[64];
28
28
  };
29
29
 
30
- void MD5Init(struct MD5Context *context);
31
- void MD5Update(struct MD5Context *context, unsigned char const *buf,
30
+ #ifdef __LIBSTROPHE_STROPHE_H__
31
+ #define MD5Init sasl_MD5Init
32
+ #define MD5Update sasl_MD5Update
33
+ #define MD5Final sasl_MD5Final
34
+ #define MD5DumpBytes sasl_MD5DumpBytes
35
+ #endif
36
+
37
+ void sasl_MD5Init(struct MD5Context *context);
38
+ void sasl_MD5Update(struct MD5Context *context, unsigned char const *buf,
32
39
  uint32_t len);
33
- void MD5Final(unsigned char digest[16], struct MD5Context *context);
40
+ void sasl_MD5Final(unsigned char digest[16], struct MD5Context *context);
34
41
  void MD5Transform(uint32_t buf[4], const unsigned char in[64],
35
42
  struct MD5Context *ctx);
36
43
 
37
44
  #ifdef DEBUG_MD5
38
- void MD5DumpBytes(unsigned char *b, int len);
45
+ void sasl_MD5DumpBytes(unsigned char *b, int len);
39
46
  #endif
40
47
 
41
48
  #endif /* !MD5_H */
data/ext/ostypes.h CHANGED
@@ -2,7 +2,7 @@
2
2
  ** strophe XMPP client library -- type definitions for platforms
3
3
  ** without stdint.h
4
4
  **
5
- ** Copyright (C) 2005-2009 Collecta, Inc.
5
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
6
6
  **
7
7
  ** This software is provided AS-IS with no warranty, either express
8
8
  ** or implied.
@@ -15,7 +15,7 @@
15
15
 
16
16
  /** @file
17
17
  * Type definitions for platforms without stdint.h.
18
- */
18
+ */
19
19
 
20
20
  #ifndef __LIBSTROPHE_OSTYPES_H__
21
21
  #define __LIBSTROPHE_OSTYPES_H__
data/ext/parser.c ADDED
@@ -0,0 +1,208 @@
1
+ /* parser.c
2
+ ** strophe XMPP client library -- xml parser handlers and utility functions
3
+ **
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
+ **
6
+ ** This software is provided AS-IS with no warranty, either express
7
+ ** or implied.
8
+ **
9
+ ** This software is distributed under license and may not be copied,
10
+ ** modified or distributed except as expressly authorized under the
11
+ ** terms of the license contained in the file LICENSE.txt in this
12
+ ** distribution.
13
+ */
14
+
15
+ /** @file
16
+ * XML parser handlers.
17
+ */
18
+
19
+ #include <stdio.h>
20
+ #include <stdlib.h>
21
+ #include <string.h>
22
+
23
+ #include "expat.h"
24
+
25
+ #include "strophe.h"
26
+ #include "common.h"
27
+
28
+ static void _log_open_tag(xmpp_conn_t * const conn,
29
+ const XML_Char **attr)
30
+ {
31
+ char buf[4096];
32
+ size_t len, pos;
33
+ int i;
34
+
35
+ pos = 0;
36
+ len = xmpp_snprintf(buf, 4096, "<stream:stream");
37
+ if (len < 0) return;
38
+
39
+ pos += len;
40
+
41
+ for (i = 0; attr[i]; i += 2) {
42
+ len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s=\"%s\"",
43
+ attr[i], attr[i+1]);
44
+ if (len < 0) return;
45
+
46
+ pos += len;
47
+ }
48
+
49
+ len = xmpp_snprintf(&buf[pos], 4096 - pos, ">");
50
+ if (len < 0) return;
51
+
52
+ xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
53
+ }
54
+
55
+ void parser_handle_start(void *userdata,
56
+ const XML_Char *name,
57
+ const XML_Char **attr)
58
+ {
59
+ xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
60
+ xmpp_stanza_t *child;
61
+
62
+ if (conn->depth == 0) {
63
+ /* we're expecting a stream:stream tag. */
64
+ if (strcmp(name, "stream:stream") != 0) {
65
+ xmpp_error(conn->ctx, "xmpp",
66
+ "Server did not open valid stream.");
67
+ conn->error = -3;
68
+ conn_disconnect(conn);
69
+ } else {
70
+ _log_open_tag(conn, attr);
71
+
72
+ if (conn->stream_id) xmpp_free(conn->ctx, conn->stream_id);
73
+ conn->stream_id = xmpp_strdup(conn->ctx, "foo");
74
+ if (!conn->stream_id) {
75
+ xmpp_error(conn->ctx, "xmpp",
76
+ "Memory allocation failure.");
77
+ conn->error = -2;
78
+ conn_disconnect(conn);
79
+ }
80
+
81
+ /* call stream open handler */
82
+ conn->open_handler(conn);
83
+ }
84
+ } else {
85
+ /* build stanzas at depth 1 */
86
+ if (!conn->stanza && conn->depth != 1) {
87
+ /* something terrible happened */
88
+ /* FIXME: shutdown disconnect */
89
+ xmpp_debug(conn->ctx, "xmpp", "oops, where did our stanza go?");
90
+ } else if (!conn->stanza) {
91
+ /* starting a new toplevel stanza */
92
+ conn->stanza = xmpp_stanza_new(conn->ctx);
93
+ if (!conn->stanza) {
94
+ /* FIXME: can't allocate, disconnect */
95
+ }
96
+ xmpp_stanza_set_name(conn->stanza, name);
97
+ xmpp_stanza_set_attributes(conn->stanza, attr);
98
+ } else {
99
+ /* starting a child of conn->stanza */
100
+ child = xmpp_stanza_new(conn->ctx);
101
+ if (!child) {
102
+ /* FIXME: can't allocate, disconnect */
103
+ }
104
+ xmpp_stanza_set_name(child, name);
105
+ xmpp_stanza_set_attributes(child, attr);
106
+
107
+ /* add child to parent */
108
+ xmpp_stanza_add_child(conn->stanza, child);
109
+
110
+ /* the child is owned by the toplevel stanza now */
111
+ xmpp_stanza_release(child);
112
+
113
+ /* make child the current stanza */
114
+ conn->stanza = child;
115
+ }
116
+ }
117
+
118
+ conn->depth++;
119
+ }
120
+
121
+ void parser_handle_end(void *userdata, const XML_Char *name)
122
+ {
123
+ xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
124
+ char *buf;
125
+ size_t len;
126
+ xmpp_stanza_t *stanza;
127
+
128
+ conn->depth--;
129
+
130
+ if (conn->depth == 0) {
131
+ /* got a closing stream tag */
132
+ xmpp_debug(conn->ctx, "xmpp", "RECV: </stream:stream>");
133
+ conn_disconnect_clean(conn);
134
+ } else {
135
+ if (conn->stanza->parent) {
136
+ /* we're finishing a child stanza, so set current to the parent */
137
+ conn->stanza = conn->stanza->parent;
138
+ } else {
139
+ /* we're finishing a toplevel stanza, so fire off handler */
140
+ if (xmpp_stanza_to_text(conn->stanza, &buf, &len) == 0) {
141
+ xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
142
+ xmpp_free(conn->ctx, buf);
143
+ }
144
+
145
+ stanza = xmpp_stanza_clone(conn->stanza);
146
+ xmpp_stanza_release(conn->stanza);
147
+ conn->stanza = NULL;
148
+
149
+ /* fire handlers */
150
+ handler_fire_stanza(conn, stanza);
151
+
152
+ xmpp_stanza_release(stanza);
153
+ }
154
+ }
155
+ }
156
+
157
+ void parser_handle_character(void *userdata, const XML_Char *s, int len)
158
+ {
159
+ xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
160
+ xmpp_stanza_t *stanza;
161
+
162
+ if (conn->depth < 2) return;
163
+
164
+ /* create and populate stanza */
165
+ stanza = xmpp_stanza_new(conn->ctx);
166
+ if (!stanza) {
167
+ /* FIXME: allocation error, disconnect */
168
+ return;
169
+ }
170
+ xmpp_stanza_set_text_with_size(stanza, s, len);
171
+
172
+ xmpp_stanza_add_child(conn->stanza, stanza);
173
+ xmpp_stanza_release(stanza);
174
+ }
175
+
176
+ /* prepares a parser reset. this is called from handlers. we can't
177
+ * reset the parser immediately as it is not reentrant. */
178
+ void parser_prepare_reset(xmpp_conn_t * const conn,
179
+ xmpp_open_handler handler)
180
+ {
181
+ conn->reset_parser = 1;
182
+ conn->open_handler = handler;
183
+ }
184
+
185
+ /* shuts down and restarts XML parser. true on success */
186
+ int parser_reset(xmpp_conn_t * const conn)
187
+ {
188
+ conn->reset_parser = 0;
189
+
190
+ if (conn->parser)
191
+ XML_ParserFree(conn->parser);
192
+
193
+ if (conn->stanza)
194
+ xmpp_stanza_release(conn->stanza);
195
+
196
+ conn->parser = XML_ParserCreate(NULL);
197
+ if (!conn->parser) return 0;
198
+
199
+ conn->depth = 0;
200
+ conn->stanza = NULL;
201
+ XML_SetUserData(conn->parser, conn);
202
+ XML_SetElementHandler(conn->parser, parser_handle_start,
203
+ parser_handle_end);
204
+ XML_SetCharacterDataHandler(conn->parser, parser_handle_character);
205
+
206
+ return 1;
207
+ }
208
+
data/ext/sasl.h CHANGED
@@ -1,7 +1,7 @@
1
1
  /* sasl.h
2
2
  ** strophe XMPP client library -- SASL authentication helpers
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -14,7 +14,7 @@
14
14
 
15
15
  /** @file
16
16
  * SASL authentication helpers.
17
- */
17
+ */
18
18
 
19
19
  #ifndef __LIBSTROPHE_SASL_H__
20
20
  #define __LIBSTROPHE_SASL_H__
@@ -39,6 +39,6 @@ int base64_decoded_len(xmpp_ctx_t *ctx,
39
39
  const char * const buffer, const unsigned len);
40
40
 
41
41
  unsigned char *base64_decode(xmpp_ctx_t *ctx,
42
- const char * const buffer, const unsigned len);
42
+ const char * const buffer, const unsigned len);
43
43
 
44
44
  #endif /* _LIBXMPP_SASL_H__ */
data/ext/sock.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* sock.c
2
2
  ** strophe XMPP client library -- socket abstraction implementation
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
data/ext/sock.h CHANGED
@@ -1,7 +1,7 @@
1
1
  /* sock.h
2
2
  ** strophe XMPP client library -- socket abstraction header
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -14,7 +14,7 @@
14
14
 
15
15
  /** @file
16
16
  * Socket abstraction API.
17
- */
17
+ */
18
18
 
19
19
  #ifndef __LIBSTROPHE_SOCK_H__
20
20
  #define __LIBSTROPHE_SOCK_H__
data/ext/stanza.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* stanza.c
2
2
  ** strophe XMPP client library -- XMPP stanza object and utilities
3
3
  **
4
- ** Copyright (C) 2005-2009 Collecta, Inc.
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -165,13 +165,13 @@ int xmpp_stanza_release(xmpp_stanza_t * const stanza)
165
165
  if (stanza->ref > 1)
166
166
  stanza->ref--;
167
167
  else {
168
- /* release all children */
169
- child = stanza->children;
170
- while (child) {
171
- tchild = child;
172
- child = child->next;
173
- xmpp_stanza_release(tchild);
174
- }
168
+ /* release all children */
169
+ child = stanza->children;
170
+ while (child) {
171
+ tchild = child;
172
+ child = child->next;
173
+ xmpp_stanza_release(tchild);
174
+ }
175
175
 
176
176
  if (stanza->attributes) hash_release(stanza->attributes);
177
177
  if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
@@ -400,6 +400,45 @@ char *xmpp_stanza_get_name(xmpp_stanza_t * const stanza)
400
400
  return stanza->data;
401
401
  }
402
402
 
403
+ /** Set or replace attributes on a stanza.
404
+ * This function replaces all previous attributes (if any) with the
405
+ * attributes given. It is used primarily by the XML parser during
406
+ * stanza creation. All strings in the array are copied before placing them
407
+ * inside the stanza object.
408
+ *
409
+ * @param stanza a Strophe stanza object
410
+ * @param attr an array of strings with the attributes in the following
411
+ * format: attr[i] = attribute name, attr[i+1] = attribute value
412
+ *
413
+ * @return XMPP_EOK on success, a number less than 0 on failure (XMPP_EMEM,
414
+ * XMPP_EINVOP)
415
+ *
416
+ * @ingroup Stanza
417
+ */
418
+ int xmpp_stanza_set_attributes(xmpp_stanza_t * const stanza,
419
+ const char * const * const attr)
420
+ {
421
+ int i;
422
+ char *value;
423
+
424
+ if (stanza->attributes != NULL)
425
+ hash_release(stanza->attributes);
426
+
427
+ stanza->attributes = hash_new(stanza->ctx, 8, xmpp_free);
428
+ if (!stanza->attributes) return XMPP_EMEM;
429
+
430
+ for (i = 0; attr[i]; i += 2) {
431
+ value = xmpp_strdup(stanza->ctx, attr[i + 1]);
432
+ if (!value) {
433
+ /* FIXME: memory allocation error */
434
+ continue;
435
+ }
436
+ hash_add(stanza->attributes, attr[i], value);
437
+ }
438
+
439
+ return XMPP_EOK;
440
+ }
441
+
403
442
  /** Count the attributes in a stanza object.
404
443
  *
405
444
  * @param stanza a Strophe stanza object