Line data Source code
1 : /* jid.c
2 : ** strophe XMPP client library -- helper functions for parsing JIDs
3 : **
4 : ** Copyright (C) 2005-2009 Collecta, Inc.
5 : **
6 : ** This software is provided AS-IS with no warranty, either express
7 : ** or implied.
8 : **
9 : ** This program is dual licensed under the MIT and GPLv3 licenses.
10 : */
11 :
12 : /** @file
13 : * JID creation and parsing.
14 : */
15 :
16 : #include <string.h>
17 :
18 : #include "strophe.h"
19 : #include "common.h"
20 :
21 : /** Create a JID string from component parts node, domain, and resource.
22 : *
23 : * @param ctx the Strophe context object
24 : * @param node a string representing the node
25 : * @param domain a string representing the domain. Required.
26 : * @param resource a string representing the resource
27 : *
28 : * @return an allocated string with the full JID or NULL if no domain
29 : * is specified
30 : */
31 0 : char *xmpp_jid_new(xmpp_ctx_t *ctx,
32 : const char *node,
33 : const char *domain,
34 : const char *resource)
35 : {
36 0 : char *result;
37 0 : size_t len, nlen, dlen, rlen;
38 :
39 : /* jid must at least have a domain */
40 0 : if (domain == NULL) {
41 0 : strophe_error(ctx, "jid", "domainpart missing.");
42 0 : return NULL;
43 : }
44 :
45 : /* accumulate lengths */
46 0 : dlen = strlen(domain);
47 0 : nlen = (node) ? strlen(node) + 1 : 0;
48 0 : rlen = (resource) ? strlen(resource) + 1 : 0;
49 0 : len = nlen + dlen + rlen;
50 :
51 0 : if (dlen > 1023) {
52 0 : strophe_error(ctx, "jid", "domainpart too long.");
53 0 : return NULL;
54 : }
55 0 : if (nlen > 1024) {
56 0 : strophe_error(ctx, "jid", "localpart too long.");
57 0 : return NULL;
58 : }
59 0 : if (rlen > 1024) {
60 0 : strophe_error(ctx, "jid", "resourcepart too long.");
61 0 : return NULL;
62 : }
63 :
64 0 : if (node) {
65 0 : if (strcspn(node, "\"&'/:<>@") != nlen - 1) {
66 0 : strophe_error(ctx, "jid", "localpart contained invalid character.");
67 0 : return NULL;
68 : }
69 : }
70 :
71 : /* concat components */
72 0 : result = strophe_alloc(ctx, len + 1);
73 0 : if (result != NULL) {
74 0 : if (node != NULL) {
75 0 : memcpy(result, node, nlen - 1);
76 0 : result[nlen - 1] = '@';
77 : }
78 0 : memcpy(result + nlen, domain, dlen);
79 0 : if (resource != NULL) {
80 0 : result[nlen + dlen] = '/';
81 0 : memcpy(result + nlen + dlen + 1, resource, rlen - 1);
82 : }
83 0 : result[len] = '\0';
84 : }
85 :
86 : return result;
87 : }
88 :
89 : /** Create a bare JID from a JID.
90 : *
91 : * @param ctx the Strophe context object
92 : * @param jid the JID
93 : *
94 : * @return an allocated string with the bare JID or NULL on an error
95 : */
96 0 : char *xmpp_jid_bare(xmpp_ctx_t *ctx, const char *jid)
97 : {
98 0 : char *result;
99 0 : size_t len;
100 :
101 0 : len = strcspn(jid, "/");
102 0 : result = strophe_alloc(ctx, len + 1);
103 0 : if (result != NULL) {
104 0 : memcpy(result, jid, len);
105 0 : result[len] = '\0';
106 : }
107 :
108 0 : return result;
109 : }
110 :
111 : /** Create a node string from a JID.
112 : *
113 : * @param ctx a Strophe context object
114 : * @param jid the JID
115 : *
116 : * @return an allocated string with the node or NULL if no node is found
117 : * or an error occurs
118 : */
119 0 : char *xmpp_jid_node(xmpp_ctx_t *ctx, const char *jid)
120 : {
121 0 : char *dup_jid = strophe_strdup(ctx, jid);
122 0 : char *result = NULL;
123 0 : const char *c;
124 :
125 : /* Apply the same parsing rules from rfc7622 Section 3.2
126 : * 1. Strip resource
127 : * 2. take part before the '@'
128 : */
129 :
130 0 : char *resource = strchr(dup_jid, '/');
131 0 : if (resource != NULL) {
132 0 : *resource = '\0';
133 : }
134 :
135 0 : c = strchr(dup_jid, '@');
136 0 : if (c != NULL) {
137 0 : result = strophe_alloc(ctx, (c - dup_jid) + 1);
138 0 : if (result != NULL) {
139 0 : memcpy(result, dup_jid, (c - dup_jid));
140 0 : result[c - dup_jid] = '\0';
141 : }
142 : }
143 0 : strophe_free(ctx, dup_jid);
144 :
145 0 : return result;
146 : }
147 :
148 : /** Create a domain string from a JID.
149 : *
150 : * @param ctx the Strophe context object
151 : * @param jid the JID
152 : *
153 : * @return an allocated string with the domain or NULL on an error
154 : */
155 0 : char *xmpp_jid_domain(xmpp_ctx_t *ctx, const char *jid)
156 : {
157 0 : char *dup_jid = strophe_strdup(ctx, jid);
158 :
159 : /* rfc7622 Section 3.2
160 : * 1. Remove any portion from the first '/' character to the end of the
161 : * string (if there is a '/' character present).
162 : */
163 :
164 0 : char *resource = strchr(dup_jid, '/');
165 0 : if (resource != NULL) {
166 0 : *resource = '\0';
167 : }
168 :
169 : /* 2. Remove any portion from the beginning of the string to the first
170 : * '@' character (if there is an '@' character present).
171 : */
172 0 : char *at_sign = strchr(dup_jid, '@');
173 0 : char *result = NULL;
174 0 : if (at_sign != NULL) {
175 0 : result = strophe_strdup(ctx, (at_sign + 1));
176 : } else {
177 0 : result = strophe_strdup(ctx, dup_jid);
178 : }
179 0 : strophe_free(ctx, dup_jid);
180 :
181 0 : return result;
182 : }
183 :
184 : /** Create a resource string from a JID.
185 : *
186 : * @param ctx a Strophe context object
187 : * @param jid the JID
188 : *
189 : * @return an allocated string with the resource or NULL if no resource
190 : * is found or an error occurs
191 : */
192 0 : char *xmpp_jid_resource(xmpp_ctx_t *ctx, const char *jid)
193 : {
194 0 : const char *c;
195 :
196 0 : c = strchr(jid, '/');
197 0 : return c != NULL ? strophe_strdup(ctx, c + 1) : NULL;
198 : }
|