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