CAEN Utility  2.0.2
Utilities for CAEN projects
CAENUrl.c
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * CAEN SpA - Software Division
4 * Via Vetraia, 11 - 55049 - Viareggio ITALY
5 * +39 0594 388 398 - www.caen.it
6 *
7 *******************************************************************************
8 *
9 * Copyright (C) 2014, Xsoda
10 *
11 * This file is part of the CAEN Utility.
12 *
13 * This file is distributed under the BSD 2-Clause "Simplified" License.
14 *
15 * SPDX-License-Identifier: BSD-2-Clause
16 *
17 ***************************************************************************/
25 #include <CAENUrl.h>
26 
27 #include <CAENLogger.h>
28 #include <CAENMultiplatform.h>
29 
30 INIT_C_LOGGER("CAENUrlLog.txt", "CAENUrl.c");
31 
32 static bool host_is_ipv4(const char *str) {
33  if (str == NULL)
34  return FALSE;
35  while (*str != '\0') {
36  if ((*str >= '0' && *str <= '9') || *str == '.')
37  str++;
38  else
39  return FALSE;
40  }
41  return TRUE;
42 }
43 
44 static void parse_query(c_url_field_t *url, const char *query) {
45  const char *chr = strchr(query, '=');
46  while (chr != NULL) {
47 
48  void *ptr = c_realloc(url->query, (url->query_num + 1) * sizeof(*url->query));
49  if (ptr == NULL)
50  return;
51  url->query = ptr;
52  url->query[url->query_num].name = c_strndup(query, chr - query);
53  query = chr + 1;
54  chr = strchr(query, '&');
55  if (chr != NULL) {
56  url->query[url->query_num].value = c_strndup(query, chr - query);
57  url->query_num++;
58  query = chr + 1;
59  chr = strchr(query, '=');
60  }
61  else {
62  url->query[url->query_num].value = c_strdup(query);
63  url->query_num++;
64  break;
65  }
66  }
67 }
68 
70  const char *pch;
71  char *query = NULL;
72  c_url_field_t *url = c_calloc(1, sizeof(*url));
73  if (url == NULL) {
74  return NULL;
75  }
76 
77  if (str != NULL && str[0] != '\0') {
78  url->href = c_strdup(str);
79  pch = strchr(str, ':'); /* parse schema */
80  if (pch != NULL && pch[1] == '/' && pch[2] == '/') {
81  url->schema = c_strndup(str, pch - str);
82  str = pch + 3;
83  }
84  else
85  goto Fail;
86  pch = strchr(str, '@'); /* parse user info */
87  if (pch != NULL) {
88  pch = strchr(str, ':');
89  if (pch != NULL) {
90  url->username = c_strndup(str, pch - str);
91  str = pch + 1;
92  pch = strchr(str, '@');
93  if (pch != NULL) {
94  url->password = c_strndup(str, pch - str);
95  str = pch + 1;
96  }
97  else
98  goto Fail;
99  }
100  else
101  goto Fail;
102  }
103  if (str[0] == '[') { /* parse host info */
104  str++;
105  pch = strchr(str, ']');
106  if (pch != NULL) {
107  url->host = c_strndup(str, pch - str);
108  str = pch + 1;
109  if (str[0] == ':') {
110  str++;
111  pch = strchr(str, '/');
112  if (pch) {
113  url->port = c_strndup(str, pch - str);
114  str = pch + 1;
115  }
116  else {
117  url->port = c_strdup(str);
118  str += strlen(str);
119  }
120  }
121  url->host_type = HOST_IPV6;
122  }
123  else
124  goto Fail;
125  }
126  else {
127  const char *pch_slash;
128  pch = strchr(str, ':');
129  pch_slash = strchr(str, '/');
130  if (pch != NULL && ((pch_slash == NULL) || (pch < pch_slash))) {
131  url->host = c_strndup(str, pch - str);
132  str = pch + 1;
133  pch = strchr(str, '/');
134  if (pch != NULL) {
135  url->port = c_strndup(str, pch - str);
136  str = pch + 1;
137  }
138  else {
139  url->port = c_strdup(str);
140  str += strlen(str);
141  }
142  }
143  else {
144  pch = strchr(str, '/');
145  if (pch != NULL) {
146  url->host = c_strndup(str, pch - str);
147  str = pch + 1;
148  }
149  else {
150  url->host = c_strdup(str);
151  str += strlen(str);
152  }
153  }
155  }
156  if (str[0] != '\0') { /* parse path, query and fragment */
157  pch = strchr(str, '?');
158  if (pch != NULL) {
159  url->path = c_strndup(str, pch - str);
160  str = pch + 1;
161  pch = strchr(str, '#');
162  if (pch != NULL) {
163  query = c_strndup(str, pch - str);
164  str = pch + 1;
165  url->fragment = c_strdup(str);
166  }
167  else {
168  query = c_strdup(str);
169  str += strlen(str);
170  }
171  parse_query(url, query);
172  c_free(query);
173  }
174  else {
175  pch = strchr(str, '#');
176  if (pch != NULL) {
177  url->path = c_strndup(str, pch - str);
178  str = pch + 1;
179  url->fragment = c_strdup(str);
180  str += strlen(str);
181  }
182  else {
183  url->path = c_strdup(str);
184  str += strlen(str);
185  }
186  }
187  }
188  }
189  else {
190 Fail:
191  logMsg(c_logger_Severity_ERROR, "%s(): failed.", __func__);
192  c_url_free(url);
193  url = NULL;
194  }
195  return url;
196 }
197 
199  if (url == NULL)
200  return;
201 
202  c_free(url->href);
203  c_free(url->schema);
204  c_free(url->username);
205  c_free(url->password);
206  c_free(url->host);
207  c_free(url->port);
208  c_free(url->path);
209  if (url->query != NULL) {
210  for (uint32_t i = 0; i < url->query_num; ++i) {
211  c_free(url->query[i].name);
212  c_free(url->query[i].value);
213  }
214  c_free(url->query);
215  }
216  c_free(url->fragment);
217  c_free(url);
218 }
void c_free(void *ptr)
void * c_calloc(size_t nmemb, size_t size)
char * username
Definition: CAENUrlTypes.h:53
char * password
Definition: CAENUrlTypes.h:54
uint32_t query_num
Definition: CAENUrlTypes.h:50
static void parse_query(c_url_field_t *url, const char *query)
Definition: CAENUrl.c:44
c_host_type_t host_type
Definition: CAENUrlTypes.h:49
char * fragment
Definition: CAENUrlTypes.h:62
#define TRUE
void c_url_free(c_url_field_t *url)
Definition: CAENUrl.c:198
#define FALSE
Generic wrappers to platform-dependent functions.
#define INIT_C_LOGGER(fname, mname)
Definition: CAENLogger.h:139
Utilities to parse a standard URL.
Logger implemented in C.
#define logMsg(s,...)
Definition: CAENLogger.h:157
#define c_use_decl_annotations
Definition: CAENUtility.h:278
c_url_field_t * c_url_parse(const char *str)
Definition: CAENUrl.c:69
char * c_strndup(const char *str, size_t size)
Wrapper to strndup(str, size), with check for NULL arguments. To be freed with c_free().
void * c_realloc(void *ptr, size_t size)
char * c_strdup(const char *str)
Wrapper to strdup(str), with check for NULL arguments. To be freed with c_free(). ...
static bool host_is_ipv4(const char *str)
Definition: CAENUrl.c:32
struct c_url_field_t::@0 * query