jabberd2  2.5.0
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  free(jid);
295 }
296 
298 void jid_expand(jid_t jid)
299 {
300  int nlen, dlen, rlen, ulen;
301 
302  if((!jid->dirty) && (jid->_full))
303  return; /* Not dirty & already expanded */
304 
305  if(*jid->domain == '\0') {
306  /* empty */
307  jid->_full = (char*) realloc(jid->_full, 1);
308  jid->_full[0] = 0;
309  return;
310  }
311 
312  nlen = strlen(jid->node);
313  dlen = strlen(jid->domain);
314  rlen = strlen(jid->resource);
315 
316  if(nlen == 0) {
317  ulen = dlen+1;
318  jid->_user = (char*) realloc(jid->_user, ulen);
319  strcpy(jid->_user, jid->domain);
320  } else {
321  ulen = nlen+1+dlen+1;
322  jid->_user = (char*) realloc(jid->_user, ulen);
323  snprintf(jid->_user, ulen, "%s@%s", jid->node, jid->domain);
324  }
325 
326  if(rlen == 0) {
327  jid->_full = (char*) realloc(jid->_full, ulen);
328  strcpy(jid->_full, jid->_user);
329  } else {
330  jid->_full = (char*) realloc(jid->_full, ulen+1+rlen);
331  snprintf(jid->_full, ulen+1+rlen, "%s/%s", jid->_user, jid->resource);
332  }
333 
334  jid->dirty = 0;
335 }
336 
338 const char *jid_user(jid_t jid)
339 {
340  jid_expand(jid);
341 
342  return jid->_user;
343 }
344 
346 const char *jid_full(jid_t jid)
347 {
348  jid_expand(jid);
349 
350  return jid->_full;
351 }
352 
355 {
356  jid_expand(a);
357  jid_expand(b);
358 
359  return strcmp(a->_user, b->_user);
360 }
361 
364 {
365  jid_expand(a);
366  jid_expand(b);
367 
368  return strcmp(a->_full, b->_full);
369 }
370 
373 {
374  jid_t new;
375 
376  new = (jid_t) malloc(sizeof(struct jid_st));
377  memcpy(new, jid, sizeof(struct jid_st));
378  if(jid->jid_data != NULL) {
379  if(jid->jid_data_len == 0) {
380  /* when original jid had static buffer, allocate new dynamic buffer
381  * of the same size as has the static buffer */
382  jid->jid_data_len = sizeof(jid_static_buf);
383  }
384 
385  /* allocate & populate new dynamic buffer */
386  new->jid_data = malloc(new->jid_data_len);
387  memcpy(new->jid_data, jid->jid_data, new->jid_data_len);
388 
389  /* relocate pointers */
390  if(jid->node[0] == '\0')
391  new->node = "";
392  else
393  new->node = new->jid_data + (jid->node - jid->jid_data);
394  if(jid->domain[0] == '\0')
395  new->domain = "";
396  else
397  new->domain = new->jid_data + (jid->domain - jid->jid_data);
398  if(jid->resource[0] == '\0')
399  new->resource = "";
400  else
401  new->resource = new->jid_data + (jid->resource - jid->jid_data);
402  }
403  if(jid->_user)
404  new->_user = strdup(jid->_user);
405  if(jid->_full)
406  new->_full = strdup(jid->_full);
407 
408  return new;
409 }
410 
412 int jid_search(jid_t list, jid_t jid)
413 {
414  jid_t cur;
415  for(cur = list; cur != NULL; cur = cur->next)
416  if(jid_compare_full(cur,jid) == 0)
417  return 1;
418  return 0;
419 }
420 
423 {
424  jid_t cur, dead;
425 
426  if(jid == NULL || list == NULL)
427  return NULL;
428 
429  /* check first */
430  if(jid_compare_full(jid,list) == 0) {
431  cur = list->next;
432  jid_free(list);
433  return cur;
434  }
435 
436  /* check through the list, stopping at the previous list entry to a matching one */
437  cur = list;
438  while(cur != NULL)
439  {
440  if(cur->next == NULL)
441  /* none match, so we're done */
442  return list;
443 
444  if(jid_compare_full(cur->next, jid) == 0)
445  {
446  /* match, kill it */
447  dead = cur->next;
448  cur->next = cur->next->next;
449  jid_free(dead);
450 
451  return list;
452  }
453 
454  /* loop */
455  cur = cur->next;
456  }
457 
458  /* shouldn't get here */
459  return list;
460 }
461 
464 {
465  jid_t scan;
466 
467  if(list == NULL)
468  return jid_dup(jid);
469 
470  scan = list;
471  while(scan != NULL)
472  {
473  /* check for dups */
474  if(jid_compare_full(scan, jid) == 0)
475  return list;
476 
477  /* tack it on to the end of the list */
478  if(scan->next == NULL)
479  {
480  scan->next = jid_dup(jid);
481  return list;
482  }
483 
484  scan = scan->next;
485  }
486 
487  return list;
488 }
489 
492 {
493  char hashBuf[41];
494  char randomBuf[257];
495  int i,r;
496 
497  /* create random string */
498  for(i = 0; i < 256; i++) {
499  r = (int) (36.0 * rand() / RAND_MAX);
500  randomBuf[i] = (r >= 0 && r <= 0) ? (r + 48) : (r + 87);
501  }
502  randomBuf[256] = 0;
503 
504  /* hash it */
505  shahash_r(randomBuf, hashBuf);
506 
507  /* change jid */
508  switch(part) {
509  case jid_NODE:
510  jid_reset_components(jid, hashBuf, jid->domain, jid->resource);
511  break;
512 
513  case jid_DOMAIN: /* unused */
514  jid_reset_components(jid, jid->node, hashBuf, jid->resource);
515  break;
516 
517  case jid_RESOURCE:
518  jid_reset_components(jid, jid->node, jid->domain, hashBuf);
519  break;
520  }
521 
522  /* prepare */
523  jid_prep(jid);
524 }
525 
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:338
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:346
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:422
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:491
void jid_expand(jid_t jid)
build user and full if they&#39;re out of date
Definition: jid.c:298
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:412
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:363
#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:463
int jid_compare_user(jid_t a, jid_t b)
compare the user portion of two jids
Definition: jid.c:354
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:372
#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