File Coverage

amqp_url.c
Criterion Covered Total %
statement 0 85 0.0
branch 0 52 0.0
condition n/a
subroutine n/a
pod n/a
total 0 137 0.0


line stmt bran cond sub pod time code
1             // Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
2             // SPDX-License-Identifier: mit
3              
4             #ifdef HAVE_CONFIG_H
5             #include "config.h"
6             #endif
7              
8             #ifdef _MSC_VER
9             #define _CRT_SECURE_NO_WARNINGS
10             #endif
11              
12             #include "amqp_private.h"
13             #include
14             #include
15             #include
16             #include
17             #include
18              
19 0           void amqp_default_connection_info(struct amqp_connection_info *ci) {
20             /* Apply defaults */
21 0           ci->user = "guest";
22 0           ci->password = "guest";
23 0           ci->host = "localhost";
24 0           ci->port = 5672;
25 0           ci->vhost = "/";
26 0           ci->ssl = 0;
27 0           }
28              
29             /* Scan for the next delimiter, handling percent-encodings on the way. */
30 0           static char find_delim(char **pp, int colon_and_at_sign_are_delims) {
31 0           char *from = *pp;
32 0           char *to = from;
33              
34 0           for (;;) {
35 0           char ch = *from++;
36              
37 0           switch (ch) {
38 0           case ':':
39             case '@':
40 0 0         if (!colon_and_at_sign_are_delims) {
41 0           *to++ = ch;
42 0           break;
43             }
44              
45             /* fall through */
46             case 0:
47             case '/':
48             case '?':
49             case '#':
50             case '[':
51             case ']':
52 0           *to = 0;
53 0           *pp = from;
54 0           return ch;
55              
56 0           case '%': {
57             unsigned int val;
58             int chars;
59 0           int res = sscanf(from, "%2x%n", &val, &chars);
60              
61 0 0         if (res == EOF || res < 1 || chars != 2 || val > CHAR_MAX)
    0          
    0          
    0          
62             /* Return a surprising delimiter to
63             force an error. */
64             {
65 0           return '%';
66             }
67              
68 0           *to++ = (char)val;
69 0           from += 2;
70 0           break;
71             }
72              
73 0           default:
74 0           *to++ = ch;
75 0           break;
76             }
77             }
78             }
79              
80             /* Parse an AMQP URL into its component parts. */
81 0           int amqp_parse_url(char *url, struct amqp_connection_info *parsed) {
82 0           int res = AMQP_STATUS_BAD_URL;
83             char delim;
84             char *start;
85             char *host;
86 0           char *port = NULL;
87              
88 0           amqp_default_connection_info(parsed);
89              
90             /* check the prefix */
91 0 0         if (!strncmp(url, "amqp://", 7)) {
92             /* do nothing */
93 0 0         } else if (!strncmp(url, "amqps://", 8)) {
94 0           parsed->port = 5671;
95 0           parsed->ssl = 1;
96             } else {
97 0           goto out;
98             }
99              
100 0 0         host = start = url += (parsed->ssl ? 8 : 7);
101 0           delim = find_delim(&url, 1);
102              
103 0 0         if (delim == ':') {
104             /* The colon could be introducing the port or the
105             password part of the userinfo. We don't know yet,
106             so stash the preceding component. */
107 0           port = start = url;
108 0           delim = find_delim(&url, 1);
109             }
110              
111 0 0         if (delim == '@') {
112             /* What might have been the host and port were in fact
113             the username and password */
114 0           parsed->user = host;
115 0 0         if (port) {
116 0           parsed->password = port;
117             }
118              
119 0           port = NULL;
120 0           host = start = url;
121 0           delim = find_delim(&url, 1);
122             }
123              
124 0 0         if (delim == '[') {
125             /* IPv6 address. The bracket should be the first
126             character in the host. */
127 0 0         if (host != start || *host != 0) {
    0          
128 0           goto out;
129             }
130              
131 0           start = url;
132 0           delim = find_delim(&url, 0);
133              
134 0 0         if (delim != ']') {
135 0           goto out;
136             }
137              
138 0           parsed->host = start;
139 0           start = url;
140 0           delim = find_delim(&url, 1);
141              
142             /* Closing bracket should be the last character in the
143             host. */
144 0 0         if (*start != 0) {
145 0           goto out;
146             }
147             } else {
148             /* If we haven't seen the host yet, this is it. */
149 0 0         if (*host != 0) {
150 0           parsed->host = host;
151             }
152             }
153              
154 0 0         if (delim == ':') {
155 0           port = url;
156 0           delim = find_delim(&url, 1);
157             }
158              
159 0 0         if (port) {
160             char *end;
161 0           long portnum = strtol(port, &end, 10);
162              
163 0 0         if (port == end || *end != 0 || portnum < 0 || portnum > 65535) {
    0          
    0          
    0          
164 0           goto out;
165             }
166              
167 0           parsed->port = portnum;
168             }
169              
170 0 0         if (delim == '/') {
171 0           start = url;
172 0           delim = find_delim(&url, 1);
173              
174 0 0         if (delim != 0) {
175 0           goto out;
176             }
177              
178 0           parsed->vhost = start;
179 0           res = AMQP_STATUS_OK;
180 0 0         } else if (delim == 0) {
181 0           res = AMQP_STATUS_OK;
182             }
183              
184             /* Any other delimiter is bad, and we will return AMQP_STATUS_BAD_AMQP_URL. */
185              
186 0           out:
187 0           return res;
188             }