• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* MIT License
2  *
3  * Copyright (c) 2024 Brad House
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * SPDX-License-Identifier: MIT
25  */
26 #ifndef __ARES_URI_H
27 #define __ARES_URI_H
28 
29 /*! \addtogroup ares_uri URI parser and writer implementation
30  *
31  * This is a fairly complete URI parser and writer implementation (RFC 3986) for
32  * schemes which use the :// syntax. Does not currently support URIs without an
33  * authority section, such as "mailto:person@example.com".
34  *
35  * Its implementation is overkill for our current needs to be able to express
36  * DNS server configuration, but there was really no reason not to support
37  * a greater subset of the specification.
38  *
39  * @{
40  */
41 
42 
43 struct ares_uri;
44 
45 /*! URI object */
46 typedef struct ares_uri ares_uri_t;
47 
48 /*! Create a new URI object
49  *
50  *  \return new ares_uri_t, must be freed with ares_uri_destroy()
51  */
52 ares_uri_t             *ares_uri_create(void);
53 
54 /*! Destroy an initialized URI object
55  *
56  *  \param[in] uri  Initialized URI object
57  */
58 void                    ares_uri_destroy(ares_uri_t *uri);
59 
60 /*! Set the URI scheme.  Automatically lower-cases the scheme provided.
61  *  Only allows Alpha, Digit, +, -, and . characters.  Maximum length is
62  *  15 characters.  This is required to be set to write a URI.
63  *
64  *  \param[in] uri    Initialized URI object
65  *  \param[in] scheme Scheme to set the object to use
66  *  \return ARES_SUCCESS on success
67  */
68 ares_status_t  ares_uri_set_scheme(ares_uri_t *uri, const char *scheme);
69 
70 /*! Retrieve the currently configured URI scheme.
71  *
72  *  \param[in] uri    Initialized URI object
73  *  \return string containing URI scheme
74  */
75 const char    *ares_uri_get_scheme(const ares_uri_t *uri);
76 
77 /*! Set the username in the URI object
78  *
79  *  \param[in] uri      Initialized URI object
80  *  \param[in] username Username to set. May be NULL to unset existing username.
81  *  \return ARES_SUCCESS on success
82  */
83 ares_status_t  ares_uri_set_username(ares_uri_t *uri, const char *username);
84 
85 /*! Retrieve the currently configured username.
86  *
87  *  \param[in] uri    Initialized URI object
88  *  \return string containing username, maybe NULL if not set.
89  */
90 const char    *ares_uri_get_username(const ares_uri_t *uri);
91 
92 /*! Set the password in the URI object
93  *
94  *  \param[in] uri      Initialized URI object
95  *  \param[in] password Password to set. May be NULL to unset existing password.
96  *  \return ARES_SUCCESS on success
97  */
98 ares_status_t  ares_uri_set_password(ares_uri_t *uri, const char *password);
99 
100 /*! Retrieve the currently configured password.
101  *
102  *  \param[in] uri    Initialized URI object
103  *  \return string containing password, maybe NULL if not set.
104  */
105 const char    *ares_uri_get_password(const ares_uri_t *uri);
106 
107 /*! Set the host or ip address in the URI object.  This is required to be
108  *  set to write a URI.  The character set is strictly validated.
109  *
110  *  \param[in] uri      Initialized URI object
111  *  \param[in] host     IPv4, IPv6, or hostname to set.
112  *  \return ARES_SUCCESS on success
113  */
114 ares_status_t  ares_uri_set_host(ares_uri_t *uri, const char *host);
115 
116 /*! Retrieve the currently configured host (or ip address).  IPv6 addresses
117  *  May include a link-local scope (e.g. fe80::b542:84df:1719:65e3%en0).
118  *
119  *  \param[in] uri    Initialized URI object
120  *  \return string containing host, maybe NULL if not set.
121  */
122 const char    *ares_uri_get_host(const ares_uri_t *uri);
123 
124 /*! Set the port to use in the URI object.  A port value of 0 will omit
125  *  the port from the URI when written, thus using the scheme's default.
126  *
127  *  \param[in] uri  Initialized URI object
128  *  \param[in] port Port to set. Use 0 to unset.
129  *  \return ARES_SUCCESS on success
130  */
131 ares_status_t  ares_uri_set_port(ares_uri_t *uri, unsigned short port);
132 
133 /*! Retrieve the currently configured port
134  *
135  *  \param[in] uri    Initialized URI object
136  *  \return port number, or 0 if not set.
137  */
138 unsigned short ares_uri_get_port(const ares_uri_t *uri);
139 
140 /*! Set the path in the URI object.  Unsupported characters will be URI-encoded
141  *  when written.
142  *
143  *  \param[in] uri  Initialized URI object
144  *  \param[in] path Path to set. May be NULL to unset existing path.
145  *  \return ARES_SUCCESS on success
146  */
147 ares_status_t  ares_uri_set_path(ares_uri_t *uri, const char *path);
148 
149 /*! Retrieves the path in the URI object.  If retrieved after parse, this
150  *  value will be URI-decoded already.
151  *
152  *  \param[in] uri Initialized URI object
153  *  \return path string, or NULL if not set.
154  */
155 const char    *ares_uri_get_path(const ares_uri_t *uri);
156 
157 /*! Set a new query key/value pair.  There is no set order for query keys
158  *  when output in the URI, they will be emitted in a random order.  Keys are
159  *  case-insensitive. Query keys and values will be automatically URI-encoded
160  *  when written.
161  *
162  *  \param[in] uri  Initialized URI object
163  *  \param[in] key  Query key to use, must be non-zero length.
164  *  \param[in] val  Query value to use, may be NULL.
165  *  \return ARES_SUCCESS on success
166  */
167 ares_status_t  ares_uri_set_query_key(ares_uri_t *uri, const char *key,
168                                       const char *val);
169 
170 /*! Delete a specific query key.
171  *
172  *  \param[in] uri Initialized URI object
173  *  \param[in] key Key to delete.
174  *  \return ARES_SUCCESS if deleted, ARES_ENOTFOUND if not found
175  */
176 ares_status_t  ares_uri_del_query_key(ares_uri_t *uri, const char *key);
177 
178 /*! Retrieve the value associated with a query key. Keys are case-insensitive.
179  *
180  *  \param[in] uri Initialized URI object
181  *  \param[in] key Key to retrieve.
182  *  \return string representing value, may be NULL if either not found or
183  *          NULL value set.  There is currently no way to indicate the
184  *          difference.
185  */
186 const char    *ares_uri_get_query_key(const ares_uri_t *uri, const char *key);
187 
188 /*! Retrieve a complete list of query keys.
189  *
190  *  \param[in]  uri Initialized URI object
191  *  \param[out] num Number of keys.
192  *  \return NULL on failure or no keys. Use
193  *          ares_free_array(keys, num, ares_free) when done with array.
194  */
195 char         **ares_uri_get_query_keys(const ares_uri_t *uri, size_t *num);
196 
197 /*! Set the fragment in the URI object.  Unsupported characters will be
198  *  URI-encoded when written.
199  *
200  *  \param[in] uri      Initialized URI object
201  *  \param[in] fragment Fragment to set. May be NULL to unset existing fragment.
202  *  \return ARES_SUCCESS on success
203  */
204 ares_status_t  ares_uri_set_fragment(ares_uri_t *uri, const char *fragment);
205 
206 /*! Retrieves the fragment in the URI object.  If retrieved after parse, this
207  *  value will be URI-decoded already.
208  *
209  *  \param[in] uri Initialized URI object
210  *  \return fragment string, or NULL if not set.
211  */
212 const char    *ares_uri_get_fragment(const ares_uri_t *uri);
213 
214 /*! Parse the provided URI buffer into a new URI object.
215  *
216  *  \param[out] out  Returned new URI object. free with ares_uri_destroy().
217  *  \param[in]  buf  Buffer object containing the URI
218  *  \return ARES_SUCCESS on successful parse. On failure the 'buf' object will
219  *          be restored to its initial state in case another parser needs to
220  *          be attempted.
221  */
222 ares_status_t  ares_uri_parse_buf(ares_uri_t **out, ares_buf_t *buf);
223 
224 /*! Parse the provided URI string into a new URI object.
225  *
226  *  \param[out] out  Returned new URI object. free with ares_uri_destroy().
227  *  \param[in]  uri  URI string to parse
228  *  \return ARES_SUCCESS on successful parse
229  */
230 ares_status_t  ares_uri_parse(ares_uri_t **out, const char *uri);
231 
232 /*! Write URI object to a new string buffer.  Requires at least the scheme
233  *  and host to be set for this to succeed.
234  *
235  *  \param[out] out  Returned new URI string. Free with ares_free().
236  *  \param[in]  uri  Initialized URI object.
237  *  \return ARES_SUCCESS on successful write.
238  */
239 ares_status_t  ares_uri_write(char **out, const ares_uri_t *uri);
240 
241 /*! Write URI object to an existing ares_buf_t object.  Requires at least the
242  *  scheme and host to be set for this to succeed.
243  *
244  *  \param[in]     uri  Initialized URI object.
245  *  \param[in,out] buf  Destination buf object.
246  *  \return ARES_SUCCESS on successful write.
247  */
248 ares_status_t  ares_uri_write_buf(const ares_uri_t *uri, ares_buf_t *buf);
249 
250 /*! @} */
251 
252 #endif /* __ARES_URI_H */
253