jabberd2  2.3.1
jid.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "util.h"
22 #include <stringprep.h>
23 
25 static jid_t jid_reset_components_internal(jid_t jid, const char *node, const char *domain, const char *resource, int prepare);
26 
28 static int jid_prep_pieces(char *node, char *domain, char *resource) {
29  if(node[0] != '\0')
30  if(stringprep_xmpp_nodeprep(node, 1024) != 0)
31  return 1;
32 
33  if(stringprep_nameprep(domain, 1024) != 0)
34  return 1;
35 
36  if(resource[0] != '\0')
37  if(stringprep_xmpp_resourceprep(resource, 1024) != 0)
38  return 1;
39 
40  return 0;
41 }
42 
44 int jid_prep(jid_t jid)
45 {
46  char node[MAXLEN_JID_COMP+1];
47  char domain[MAXLEN_JID_COMP+1];
48  char resource[MAXLEN_JID_COMP+1];
49 
50  if(jid->node != NULL) {
51  strncpy(node, jid->node, MAXLEN_JID_COMP);
52  node[MAXLEN_JID_COMP]='\0';
53  }
54  else
55  node[0] = '\0';
56 
57  if(jid->domain != NULL) {
58  strncpy(domain, jid->domain, MAXLEN_JID_COMP);
59  domain[MAXLEN_JID_COMP]='\0';
60  }
61  else
62  domain[0] = '\0';
63 
64  if(jid->resource != NULL) {
65  strncpy(resource, jid->resource, MAXLEN_JID_COMP);
66  resource[MAXLEN_JID_COMP]='\0';
67  }
68  else
69  resource[0] = '\0';
70 
71  if(jid_prep_pieces(node, domain, resource) != 0)
72  return 1;
73 
74  /* put prepared components into jid */
75  jid_reset_components_internal(jid, node, domain, resource, 0);
76 
77  return 0;
78 }
79 
81 jid_t jid_new(const char *id, int len) {
82  jid_t jid, ret;
83 
84  jid = malloc(sizeof(struct jid_st));
85  jid->jid_data = NULL;
86 
87  ret = jid_reset(jid, id, len);
88  if(ret == NULL) {
89  if(len < 0) {
90  log_debug(ZONE, "invalid jid: %s", id);
91  } else {
92  log_debug(ZONE, "invalid jid: %.*s", len, id);
93  }
94  free(jid);
95  }
96 
97  return ret;
98 }
99 
103 {
104  /* clear jid */
105  memset(jid, 0, sizeof(*jid));
106 
107  /* set buffer */
108  jid->jid_data = (char *)buf;
109 }
110 
111 
113 jid_t jid_reset(jid_t jid, const char *id, int len) {
114  char *myid, *cur, *olddata=NULL;
115 
116  assert((int) (jid != NULL));
117 
118  if (jid->jid_data != NULL) {
119  if(jid->jid_data_len != 0)
120  free(jid->jid_data);
121  else
122  olddata = jid->jid_data; /* store pointer to old data */
123  }
124  memset(jid, 0, sizeof(struct jid_st));
125  jid->dirty = 1;
126  jid->node = "";
127  jid->domain = "";
128  jid->resource = "";
129 
130  /* nice empty jid */
131  if(id == NULL)
132  return jid;
133 
134  if(len < 0)
135  len = strlen(id);
136 
137  if((len == 0) || (len > MAXLEN_JID))
138  return NULL;
139 
140  if(olddata != NULL)
141  myid = olddata; /* use static buffer */
142  else {
143  jid->jid_data_len = sizeof(char) * (len + 1);
144  myid = (char *) malloc(jid->jid_data_len);
145  }
146  sprintf(myid, "%.*s", len, id);
147 
148  /* fail - only a resource or leading @ */
149  if(myid[0] == '/' || myid[0] == '@') {
150  if(olddata == NULL) free(myid);
151  return NULL;
152  }
153 
154  /* get the resource first */
155  cur = strstr(myid, "/");
156 
157  if(cur != NULL)
158  {
159  *cur = '\0';
160  cur++;
161  if(strlen(cur) > 0) {
162  jid->resource = cur;
163  } else {
164  /* fail - a resource separator but nothing after it */
165  if(olddata == NULL) free(myid);
166  return NULL;
167  }
168  }
169 
170  /* find the domain */
171  cur = strstr(myid, "@");
172  if(cur != NULL) {
173  *cur = '\0';
174  cur++;
175  if(strlen(cur) == 0) {
176  /* no domain part, bail out */
177  if(olddata == NULL) free(myid);
178  return NULL;
179  }
180  jid->domain = cur;
181  jid->node = myid;
182  } else {
183  /* no @, so it's a domain only */
184  jid->domain = myid;
185  }
186 
187  jid->jid_data = myid;
188 
189  if(jid_prep(jid) != 0) {
190  if(olddata == NULL) free(myid);
191  jid->jid_data = NULL;
192  return NULL;
193  }
194 
195  return jid;
196 }
197 
199 static jid_t jid_reset_components_internal(jid_t jid, const char *node, const char *domain, const char *resource, int prepare) {
200  char *olddata=NULL;
201  int node_l,domain_l,resource_l;
202  int dataStatic;
203  jid_static_buf staticTmpBuf;
204 
205  assert((int) (jid != NULL));
206 
207  if(jid->jid_data != NULL)
208  olddata = jid->jid_data; /* Store old data before clearing JID */
209 
210  dataStatic = ((jid->jid_data != NULL) && (jid->jid_data_len == 0));
211 
212  if (jid->_user != NULL )
213  free(jid->_user);
214  if (jid->_full != NULL )
215  free(jid->_full);
216 
217  memset(jid, 0, sizeof(struct jid_st));
218 
219  /* get lengths */
220  node_l = strlen(node);
221  domain_l = strlen(domain);
222  resource_l = strlen(resource);
223 
224  if(node_l > MAXLEN_JID_COMP)
225  node_l = MAXLEN_JID_COMP;
226 
227  if(domain_l > MAXLEN_JID_COMP)
228  domain_l = MAXLEN_JID_COMP;
229 
230  if(resource_l > MAXLEN_JID_COMP)
231  resource_l = MAXLEN_JID_COMP;
232 
233  if(dataStatic) {
234  /* use static buffer */
235  jid->jid_data = staticTmpBuf;
236  }
237  else {
238  /* allocate new data buffer */
239  jid->jid_data_len = node_l+domain_l+resource_l+3;
240  jid->jid_data = realloc(jid->jid_data, jid->jid_data_len);
241  }
242 
243  /* copy to buffer */
244  jid->node = jid->jid_data;
245  strncpy(jid->node, node, node_l);
246  jid->node[node_l] = 0;
247 
248  jid->domain = jid->node + node_l + 1;
249  strncpy(jid->domain, domain, domain_l);
250  jid->domain[domain_l] = 0;
251 
252  jid->resource = jid->domain + domain_l + 1;
253  strncpy(jid->resource, resource, resource_l);
254  jid->resource[resource_l] = 0;
255 
256  /* Free old data buffer. Postponed to this point so that arguments may point (in)to old jid data. */
257  if((!dataStatic) && (olddata != NULL))
258  free(olddata);
259 
260  if(prepare) {
261  if(jid_prep(jid) != 0)
262  return NULL;
263  }
264 
265  jid->dirty = 1;
266 
267  if (dataStatic) {
268  jid->jid_data = olddata; /* Return pointer to the original static buffer */
269  memcpy(jid->jid_data,staticTmpBuf,node_l+domain_l+resource_l+3); /* Copy data from tmp buf to original buffer */
270 
271  /* Relocate pointers */
272  jid->node = olddata+(jid->node-(char *)staticTmpBuf);
273  jid->domain = olddata+(jid->domain-(char *)staticTmpBuf);
274  jid->resource = olddata+(jid->resource-(char *)staticTmpBuf);
275  }
276 
277  return jid;
278 }
279 
281 jid_t jid_reset_components(jid_t jid, const char *node, const char *domain, const char *resource) {
282  return jid_reset_components_internal(jid, node, domain, resource, 1);
283 }
284 
286 void jid_free(jid_t jid)
287 {
288  if((jid->jid_data != NULL) && (jid->jid_data_len != 0))
289  free(jid->jid_data);
290  if (jid->_user != NULL )
291  free(jid->_user);
292  if (jid->_full != NULL )
293  free(jid->_full);
294  if (jid != NULL )
295  free(jid);
296 }
297 
299 void jid_expand(jid_t jid)
300 {
301  int nlen, dlen, rlen, ulen;
302 
303  if((!jid->dirty) && (jid->_full))
304  return; /* Not dirty & already expanded */
305 
306  if(*jid->domain == '\0') {
307  /* empty */
308  jid->_full = (char*) realloc(jid->_full, 1);
309  jid->_full[0] = 0;
310  return;
311  }
312 
313  nlen = strlen(jid->node);
314  dlen = strlen(jid->domain);
315  rlen = strlen(jid->resource);
316 
317  if(nlen == 0) {
318  ulen = dlen+1;
319  jid->_user = (char*) realloc(jid->_user, ulen);
320  strcpy(jid->_user, jid->domain);
321  } else {
322  ulen = nlen+1+dlen+1;
323  jid->_user = (char*) realloc(jid->_user, ulen);
324  snprintf(jid->_user, ulen, "%s@%s", jid->node, jid->domain);
325  }
326 
327  if(rlen == 0) {
328  jid->_full = (char*) realloc(jid->_full, ulen);
329  strcpy(jid->_full, jid->_user);
330  } else {
331  jid->_full = (char*) realloc(jid->_full, ulen+1+rlen);
332  snprintf(jid->_full, ulen+1+rlen, "%s/%s", jid->_user, jid->resource);
333  }
334 
335  jid->dirty = 0;
336 }
337 
339 const char *jid_user(jid_t jid)
340 {
341  jid_expand(jid);
342 
343  return jid->_user;
344 }
345 
347 const char *jid_full(jid_t jid)
348 {
349  jid_expand(jid);
350 
351  return jid->_full;
352 }
353 
356 {
357  jid_expand(a);
358  jid_expand(b);
359 
360  return strcmp(a->_user, b->_user);
361 }
362 
365 {
366  jid_expand(a);
367  jid_expand(b);
368 
369  return strcmp(a->_full, b->_full);
370 }
371 
374 {
375  jid_t new;
376 
377  new = (jid_t) malloc(sizeof(struct jid_st));
378  memcpy(new, jid, sizeof(struct jid_st));
379  if(jid->jid_data != NULL) {
380  if(jid->jid_data_len == 0) {
381  /* when original jid had static buffer, allocate new dynamic buffer
382  * of the same size as has the static buffer */
383  jid->jid_data_len = sizeof(jid_static_buf);
384  }
385 
386  /* allocate & populate new dynamic buffer */
387  new->jid_data = malloc(new->jid_data_len);
388  memcpy(new->jid_data, jid->jid_data, new->jid_data_len);
389 
390  /* relocate pointers */
391  if(jid->node[0] == '\0')
392  new->node = "";
393  else
394  new->node = new->jid_data + (jid->node - jid->jid_data);
395  if(jid->domain[0] == '\0')
396  new->domain = "";
397  else
398  new->domain = new->jid_data + (jid->domain - jid->jid_data);
399  if(jid->resource[0] == '\0')
400  new->resource = "";
401  else
402  new->resource = new->jid_data + (jid->resource - jid->jid_data);
403  }
404  if(jid->_user)
405  new->_user = strdup(jid->_user);
406  if(jid->_full)
407  new->_full = strdup(jid->_full);
408 
409  return new;
410 }
411 
413 int jid_search(jid_t list, jid_t jid)
414 {
415  jid_t cur;
416  for(cur = list; cur != NULL; cur = cur->next)
417  if(jid_compare_full(cur,jid) == 0)
418  return 1;
419  return 0;
420 }
421 
424 {
425  jid_t cur, dead;
426 
427  if(jid == NULL || list == NULL)
428  return NULL;
429 
430  /* check first */
431  if(jid_compare_full(jid,list) == 0) {
432  cur = list->next;
433  jid_free(list);
434  return cur;
435  }
436 
437  /* check through the list, stopping at the previous list entry to a matching one */
438  cur = list;
439  while(cur != NULL)
440  {
441  if(cur->next == NULL)
442  /* none match, so we're done */
443  return list;
444 
445  if(jid_compare_full(cur->next, jid) == 0)
446  {
447  /* match, kill it */
448  dead = cur->next;
449  cur->next = cur->next->next;
450  jid_free(dead);
451 
452  return list;
453  }
454 
455  /* loop */
456  cur = cur->next;
457  }
458 
459  /* shouldn't get here */
460  return list;
461 }
462 
465 {
466  jid_t scan;
467 
468  if(list == NULL)
469  return jid_dup(jid);
470 
471  scan = list;
472  while(scan != NULL)
473  {
474  /* check for dups */
475  if(jid_compare_full(scan, jid) == 0)
476  return list;
477 
478  /* tack it on to the end of the list */
479  if(scan->next == NULL)
480  {
481  scan->next = jid_dup(jid);
482  return list;
483  }
484 
485  scan = scan->next;
486  }
487 
488  return list;
489 }
490 
493 {
494  char hashBuf[41];
495  char randomBuf[257];
496  int i,r;
497 
498  /* create random string */
499  for(i = 0; i < 256; i++) {
500  r = (int) (36.0 * rand() / RAND_MAX);
501  randomBuf[i] = (r >= 0 && r <= 0) ? (r + 48) : (r + 87);
502  }
503  randomBuf[256] = 0;
504 
505  /* hash it */
506  shahash_r(randomBuf, hashBuf);
507 
508  /* change jid */
509  switch(part) {
510  case jid_NODE:
511  jid_reset_components(jid, hashBuf, jid->domain, jid->resource);
512  break;
513 
514  case jid_DOMAIN: /* unused */
515  jid_reset_components(jid, jid->node, hashBuf, jid->resource);
516  break;
517 
518  case jid_RESOURCE:
519  jid_reset_components(jid, jid->node, jid->domain, hashBuf);
520  break;
521  }
522 
523  /* prepare */
524  jid_prep(jid);
525 }
526 
struct jid_st * jid_t
char * _user
Definition: jid.h:58
jid_t jid_reset(jid_t jid, const char *id, int len)
build a jid from an id
Definition: jid.c:113
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:339
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
void jid_static(jid_t jid, jid_static_buf *buf)
Make jid to use static buffer (jid data won&#39;t be allocated dynamically, but given buffer will be alwa...
Definition: jid.c:102
int dirty
Definition: jid.h:64
void shahash_r(const char *str, char hashbuf[41])
convenience (originally by Thomas Muldowney)
Definition: str.c:358
jid_t jid_zap(jid_t list, jid_t jid)
remove a jid_t from a list, returning the new list
Definition: jid.c:423
char * resource
Definition: jid.h:46
jid_part_t
Definition: jid.h:70
void jid_random_part(jid_t jid, jid_part_t part)
create random resource
Definition: jid.c:492
void jid_expand(jid_t jid)
build user and full if they&#39;re out of date
Definition: jid.c:299
int jid_prep(jid_t jid)
do stringprep on the piece
Definition: jid.c:44
char * _full
Definition: jid.h:61
jid_t jid_reset_components(jid_t jid, const char *node, const char *domain, const char *resource)
build a jid from components
Definition: jid.c:281
#define MAXLEN_JID
Definition: jid.h:40
char jid_static_buf[3 *1025]
JID static buffer.
Definition: jid.h:77
Definition: jid.h:71
int jid_search(jid_t list, jid_t jid)
util to search through jids
Definition: jid.c:413
void jid_free(jid_t jid)
free a jid
Definition: jid.c:286
char * domain
Definition: jid.h:45
Definition: jid.h:42
#define MAXLEN_JID_COMP
these sizings come from xmpp-core
Definition: jid.h:39
int jid_compare_full(jid_t a, jid_t b)
compare two full jids
Definition: jid.c:364
#define log_debug(...)
Definition: log.h:65
jid_t jid_append(jid_t list, jid_t jid)
make a copy of jid, link into list (avoiding dups)
Definition: jid.c:464
int jid_compare_user(jid_t a, jid_t b)
compare the user portion of two jids
Definition: jid.c:355
static int jid_prep_pieces(char *node, char *domain, char *resource)
do stringprep on the pieces
Definition: jid.c:28
char * jid_data
Definition: jid.h:51
jid_t jid_dup(jid_t jid)
duplicate a jid
Definition: jid.c:373
#define ZONE
Definition: mio_impl.h:76
struct jid_st * next
Definition: jid.h:67
static jid_t jid_reset_components_internal(jid_t jid, const char *node, const char *domain, const char *resource, int prepare)
Forward declaration.
Definition: jid.c:199
size_t jid_data_len
Definition: jid.h:55
Definition: jid.h:72
char * node
Definition: jid.h:44