GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/webapis_ipwhois.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 94 115 81.7%
Functions: 4 4 100.0%
Branches: 33 54 61.1%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/tech/webapis.h"
30 #include "gate/results.h"
31 #include "gate/net/httpclients.h"
32 #include "gate/encode/json.h"
33
34 #define GATE_WEBAPIS_IPWHOIS_REQUEST_NAME GATE_STRUCT_WEBAPIS_NAME("ipwhois_request")
35 #define GATE_WEBAPIS_IPWHOIS_RESPONSE_NAME GATE_STRUCT_WEBAPIS_NAME("ipwhois_response")
36
37
38 static gate_struct_item_t const ipwhois_request_members[] =
39 {
40 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_request_t, GATE_TYPE_STRING, ip_address, "IP address", GATE_STRUCT_FLAG_DEFAULT)
41 };
42
43 3 GATE_TECH_API void gate_tech_webapi_ipwhois_request_init(gate_tech_webapi_ipwhois_request_t* request)
44 {
45 static gate_struct_descriptor_t const ipwhois_request_descriptor =
46 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_ipwhois_request_t, GATE_WEBAPIS_IPWHOIS_REQUEST_NAME, ipwhois_request_members);
47
48 3 gate_mem_clear(request, sizeof(gate_tech_webapi_ipwhois_request_t));
49 3 request->struct_base.struct_descriptor = &ipwhois_request_descriptor;
50 3 }
51
52
53
54 static gate_struct_item_t const ipwhois_response_members[] =
55 {
56 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, ip_address, "IP address", GATE_STRUCT_FLAG_DEFAULT),
57 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, range, "IP range", GATE_STRUCT_FLAG_DEFAULT),
58
59 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, inet_org, "Organization", GATE_STRUCT_FLAG_DEFAULT),
60 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, inet_netname,"Name", GATE_STRUCT_FLAG_DEFAULT),
61 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, inet_descr, "Description", GATE_STRUCT_FLAG_DEFAULT),
62 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, inet_country,"Country", GATE_STRUCT_FLAG_DEFAULT),
63 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_TIME, inet_created, "Created", GATE_STRUCT_FLAG_DEFAULT),
64 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_TIME, inet_modified, "Modified", GATE_STRUCT_FLAG_DEFAULT),
65
66 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, org_name, "Org name", GATE_STRUCT_FLAG_DEFAULT),
67 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, org_country, "Org country", GATE_STRUCT_FLAG_DEFAULT),
68 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, org_type, "Org type", GATE_STRUCT_FLAG_DEFAULT),
69 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, org_address, "Org address", GATE_STRUCT_FLAG_DEFAULT),
70 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, org_phone, "Org phone", GATE_STRUCT_FLAG_DEFAULT),
71 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, org_mail, "Org e-mail", GATE_STRUCT_FLAG_DEFAULT),
72
73 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, role_name, "Role name", GATE_STRUCT_FLAG_DEFAULT),
74 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, role_address,"Role address", GATE_STRUCT_FLAG_DEFAULT),
75 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, role_mail, "Role mail", GATE_STRUCT_FLAG_DEFAULT),
76 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, role_admin_c,"Role admin-c", GATE_STRUCT_FLAG_DEFAULT),
77 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, role_tech_c, "Role tech-c", GATE_STRUCT_FLAG_DEFAULT),
78
79 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, route_name, "Route name", GATE_STRUCT_FLAG_DEFAULT),
80 GATE_STRUCT_ITEM_EX(gate_tech_webapi_ipwhois_response_t, GATE_TYPE_STRING, route_descr, "Route description", GATE_STRUCT_FLAG_DEFAULT)
81 };
82
83 3 GATE_TECH_API void gate_tech_webapi_ipwhois_response_init(gate_tech_webapi_ipwhois_response_t* response)
84 {
85 static gate_struct_descriptor_t const ipwhois_response_descriptor =
86 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_ipwhois_response_t, GATE_WEBAPIS_IPWHOIS_RESPONSE_NAME, ipwhois_response_members);
87
88 3 gate_mem_clear(response, sizeof(gate_tech_webapi_ipwhois_response_t));
89 3 response->struct_base.struct_descriptor = &ipwhois_response_descriptor;
90 3 }
91
92
93 32 static gate_size_t gate_tech_webapi_ipwhois_extract_attribute_values(
94 gate_property_t const* prop_attributes, char const* name, gate_string_t* output)
95 {
96 32 gate_size_t ret = 0;
97 32 gate_strbuilder_t builder = GATE_INIT_EMPTY;
98
99 do
100 {
101 static gate_string_t const attr_name = GATE_STRING_INIT_STATIC("name");
102 static gate_string_t const attr_value = GATE_STRING_INIT_STATIC("value");
103 gate_size_t length;
104 gate_size_t index;
105
106
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (!gate_string_is_empty(output))
107 {
108 // value already received
109 break;
110 }
111
112 32 gate_strbuilder_create(&builder, 0);
113
114 32 length = gate_property_array_length(prop_attributes);
115
2/2
✓ Branch 0 taken 629 times.
✓ Branch 1 taken 32 times.
661 for (index = 0; index != length; ++index)
116 {
117 gate_property_t const* prop_entry;
118 gate_property_t const* prop_name;
119 gate_property_t const* prop_value;
120
121 629 prop_entry = gate_property_array_get(prop_attributes, index);
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 629 times.
629 if (!prop_entry) continue;
123
124 629 prop_name = gate_property_resolve_path(prop_entry, &attr_name);
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 629 times.
629 if (!prop_name) continue;
126 629 prop_value = gate_property_resolve_path(prop_entry, &attr_value);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 629 times.
629 if (!prop_value) continue;
128
129
2/2
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 592 times.
629 if (gate_property_equals_str(prop_name, name))
130 {
131 37 gate_string_t value = GATE_STRING_INIT_EMPTY;
132 37 gate_result_t const result = gate_property_get_string(prop_value, &value);
133
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (GATE_SUCCEEDED(result))
134 {
135
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 26 times.
37 if (gate_strbuilder_length(&builder) > 0)
136 {
137 11 gate_strbuilder_append_text(&builder, "\n", 1);
138 }
139 37 gate_strbuilder_append_string(&builder, &value);
140 37 gate_string_release(&value);
141 37 ++ret;
142 }
143 }
144 }
145 } while (0);
146
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
32 if (ret > 0)
147 {
148 26 gate_strbuilder_to_string(&builder, output);
149 }
150 32 gate_strbuilder_release(&builder);
151 32 return ret;
152 }
153
154 3 GATE_TECH_API gate_result_t gate_tech_webapi_ipwhois(gate_tech_webapi_context_t* context,
155 gate_tech_webapi_ipwhois_request_t* request,
156 gate_tech_webapi_ipwhois_response_t* response)
157 {
158 3 gate_result_t ret = GATE_RESULT_FAILED;
159 static gate_string_t const server = GATE_STRING_INIT_STATIC("rest.db.ripe.net");
160 static gate_uint16_t const port = GATE_HTTP_DEFAULT_HTTP_PORT;
161 static gate_string_t const attributes_subpath = GATE_STRING_INIT_STATIC("attributes.attribute");
162 static gate_string_t const objects_subpath = GATE_STRING_INIT_STATIC("objects.object");
163 char buffer[1024];
164 3 gate_http_request_t http_request = GATE_INIT_EMPTY;
165 3 gate_http_response_t http_response = GATE_INIT_EMPTY;
166 3 gate_httpclient_t http_client = GATE_INIT_EMPTY;
167 3 gate_strbuilder_t path_builder = GATE_INIT_EMPTY;
168 3 gate_property_t prop = GATE_INIT_EMPTY;
169
170 GATE_UNUSED_ARG(context);
171
172 do
173 {
174 3 gate_property_t const* subprop = NULL;
175 3 gate_property_t const* prop_item = NULL;
176 3 gate_json_result_t json_result = GATE_INIT_EMPTY;
177 gate_size_t length;
178 gate_size_t index;
179
180 3 gate_strbuilder_create_static(&path_builder, buffer, sizeof(buffer), 0);
181 3 gate_strbuilder_append_cstr(&path_builder, "/search.json?query-string=");
182 3 gate_strbuilder_append_string(&path_builder, &request->ip_address);
183
184 3 ret = gate_http_request_init_str(&http_request, GATE_HTTP_METHOD_GET, server.str, gate_strbuilder_ptr(&path_builder, 0));
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
186
187 3 ret = gate_httpclient_create(&http_client, &server, port, 0);
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
189
190 3 ret = gate_httpclient_send_request(&http_client, &http_request, &http_response);
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
192
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (http_response.status_code != 200)
194 {
195 ret = GATE_RESULT_INVALIDSTATE;
196 break;
197 }
198
199 3 ret = gate_json_parse(http_response.response_stream, &prop, &json_result);
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
201
202 3 subprop = gate_property_resolve_path(&prop, &objects_subpath);
203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!subprop)
204 {
205 ret = GATE_RESULT_INVALIDOUTPUT;
206 break;
207 }
208 3 length = gate_property_array_length(subprop);
209
210 3 ret = GATE_RESULT_OK;
211
212 3 gate_string_duplicate(&response->ip_address, &request->ip_address);
213
214
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 for (index = 0; index != length; ++index)
215 {
216 7 prop_item = gate_property_array_get(subprop, index);
217
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (prop_item)
218 {
219 gate_property_t const* ptr_prop;
220 gate_property_t const* ptr_attributes;
221
222 7 ptr_prop = gate_property_resolve_path_str(prop_item, "type");
223
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
7 if (gate_property_equals_str(ptr_prop, "inetnum"))
224 {
225 3 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
226
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ptr_attributes)
227 {
228 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "inetnum", &response->range);
229 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "org", &response->inet_org);
230 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "netname", &response->inet_netname);
231 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "descr", &response->inet_descr);
232 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "country", &response->inet_country);
233 //gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "created", &response->inet_created);
234 //gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "last-modified", &response->inet_modified);
235 }
236 }
237
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (gate_property_equals_str(ptr_prop, "organisation"))
238 {
239 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
240 if (ptr_attributes)
241 {
242 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "org-name", &response->org_name);
243 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "country", &response->org_country);
244 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "org-type", &response->org_type);
245 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "address", &response->org_address);
246 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "phone", &response->org_phone);
247 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "e-mail", &response->org_mail);
248 }
249 }
250
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (gate_property_equals_str(ptr_prop, "person"))
251 {
252 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
253 if (ptr_attributes)
254 {
255 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "person", &response->org_name);
256 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "country", &response->org_country);
257 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "nic-hdl", &response->org_type);
258 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "address", &response->org_address);
259 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "phone", &response->org_phone);
260 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "e-mail", &response->org_mail);
261 }
262 }
263
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
7 if (gate_property_equals_str(ptr_prop, "role"))
264 {
265 3 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
266
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ptr_attributes)
267 {
268 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "role", &response->role_name);
269 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "address", &response->role_address);
270 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "e-mail", &response->role_mail);
271 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "admin-c", &response->role_admin_c);
272 3 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "tech-c", &response->role_tech_c);
273 }
274 }
275
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
7 if (gate_property_equals_str(ptr_prop, "route"))
276 {
277 1 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
278
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_attributes)
279 {
280 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "route", &response->route_name);
281 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "descr", &response->route_descr);
282 }
283 }
284 }
285 }
286
287 } while (0);
288
289 3 gate_property_destroy(&prop);
290 3 gate_httpclient_release(&http_client);
291 3 gate_strbuilder_release(&path_builder);
292 3 gate_http_response_release(&http_response);
293 3 gate_http_request_release(&http_request);
294
295 3 return ret;
296 }
297