GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/webapis_ipwhois.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 89 115 77.4%
Functions: 4 4 100.0%
Branches: 30 54 55.6%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, 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 static gate_struct_descriptor_t const ipwhois_request_descriptor =
44 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_ipwhois_request_t, GATE_WEBAPIS_IPWHOIS_REQUEST_NAME, ipwhois_request_members);
45
46 1 GATE_TECH_API void gate_tech_webapi_ipwhois_request_init(gate_tech_webapi_ipwhois_request_t* request)
47 {
48 1 gate_mem_clear(request, sizeof(gate_tech_webapi_ipwhois_request_t));
49 1 request->struct_base.struct_descriptor = &ipwhois_request_descriptor;
50 1 }
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 static gate_struct_descriptor_t const ipwhois_response_descriptor =
84 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_ipwhois_response_t, GATE_WEBAPIS_IPWHOIS_RESPONSE_NAME, ipwhois_response_members);
85
86 1 GATE_TECH_API void gate_tech_webapi_ipwhois_response_init(gate_tech_webapi_ipwhois_response_t* response)
87 {
88 1 gate_mem_clear(response, sizeof(gate_tech_webapi_ipwhois_response_t));
89 1 response->struct_base.struct_descriptor = &ipwhois_response_descriptor;
90 1 }
91
92
93 10 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 static gate_string_t const attr_name = GATE_STRING_INIT_STATIC("name");
97 static gate_string_t const attr_value = GATE_STRING_INIT_STATIC("value");
98 10 gate_size_t ret = 0;
99 10 gate_strbuilder_t builder = GATE_INIT_EMPTY;
100 gate_size_t length;
101 gate_size_t index;
102 gate_property_t const* prop_entry;
103 gate_property_t const* prop_name;
104 gate_property_t const* prop_value;
105 10 gate_string_t value = GATE_STRING_INIT_EMPTY;
106 gate_result_t result;
107
108 do
109 {
110
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (!gate_string_is_empty(output))
111 {
112 // value already received
113 break;
114 }
115
116 10 gate_strbuilder_create(&builder, 0);
117
118 10 length = gate_property_array_length(prop_attributes);
119
2/2
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 10 times.
235 for (index = 0; index != length; ++index)
120 {
121 225 prop_entry = gate_property_array_get(prop_attributes, index);
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 225 times.
225 if (!prop_entry) continue;
123
124 225 prop_name = gate_property_resolve_path(prop_entry, &attr_name);
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 225 times.
225 if (!prop_name) continue;
126 225 prop_value = gate_property_resolve_path(prop_entry, &attr_value);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 225 times.
225 if (!prop_value) continue;
128
129
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 217 times.
225 if (gate_property_equals_str(prop_name, name))
130 {
131 8 result = gate_property_get_string(prop_value, &value);
132
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (GATE_SUCCEEDED(result))
133 {
134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (gate_strbuilder_length(&builder) > 0)
135 {
136 gate_strbuilder_append_text(&builder, "\n", 1);
137 }
138 8 gate_strbuilder_append_string(&builder, &value);
139 8 gate_string_release(&value);
140 8 ++ret;
141 }
142 }
143 }
144 } while (0);
145
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (ret > 0)
146 {
147 8 gate_strbuilder_to_string(&builder, output);
148 }
149 10 gate_strbuilder_release(&builder);
150 10 return ret;
151 }
152
153 1 GATE_TECH_API gate_result_t gate_tech_webapi_ipwhois(gate_tech_webapi_context_t* context,
154 gate_tech_webapi_ipwhois_request_t* request,
155 gate_tech_webapi_ipwhois_response_t* response)
156 {
157 1 gate_result_t ret = GATE_RESULT_FAILED;
158 static gate_string_t const server = GATE_STRING_INIT_STATIC("rest.db.ripe.net");
159 static gate_uint16_t const port = GATE_HTTP_DEFAULT_HTTP_PORT;
160 static gate_string_t const attributes_subpath = GATE_STRING_INIT_STATIC("attributes.attribute");
161 static gate_string_t const objects_subpath = GATE_STRING_INIT_STATIC("objects.object");
162 char buffer[1024];
163 1 gate_http_request_t http_request = GATE_INIT_EMPTY;
164 1 gate_http_response_t http_response = GATE_INIT_EMPTY;
165 1 gate_httpclient_t http_client = GATE_INIT_EMPTY;
166 1 gate_strbuilder_t path_builder = GATE_INIT_EMPTY;
167 1 gate_property_t prop = GATE_INIT_EMPTY;
168 1 gate_property_t const* subprop = NULL;
169 1 gate_property_t const* prop_item = NULL;
170 1 gate_json_result_t json_result = GATE_INIT_EMPTY;
171 gate_size_t length;
172 gate_size_t index;
173 gate_property_t const* ptr_prop;
174 gate_property_t const* ptr_attributes;
175
176 do
177 {
178 1 gate_strbuilder_create_static(&path_builder, buffer, sizeof(buffer), 0);
179 1 gate_strbuilder_append_cstr(&path_builder, "/search.json?query-string=");
180 1 gate_strbuilder_append_string(&path_builder, &request->ip_address);
181
182 1 ret = gate_http_request_init_str(&http_request, GATE_HTTP_METHOD_GET, gate_strbuilder_ptr(&path_builder, 0));
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
184
185 1 ret = gate_httpclient_create(&http_client, &server, port, 0);
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
187
188 1 ret = gate_httpclient_send_request(&http_client, &http_request, &http_response);
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
190
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (http_response.status_code != 200)
192 {
193 ret = GATE_RESULT_INVALIDSTATE;
194 break;
195 }
196
197 1 ret = gate_json_parse(http_response.response_stream, &prop, &json_result);
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
199
200 1 subprop = gate_property_resolve_path(&prop, &objects_subpath);
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!subprop)
202 {
203 ret = GATE_RESULT_INVALIDOUTPUT;
204 break;
205 }
206 1 length = gate_property_array_length(subprop);
207
208 1 ret = GATE_RESULT_OK;
209
210 1 gate_string_duplicate(&response->ip_address, &request->ip_address);
211
212
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (index = 0; index != length; ++index)
213 {
214 2 prop_item = gate_property_array_get(subprop, index);
215
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (prop_item)
216 {
217 2 ptr_prop = gate_property_resolve_path_str(prop_item, "type");
218
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_property_equals_str(ptr_prop, "inetnum"))
219 {
220 1 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
221
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_attributes)
222 {
223 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "inetnum", &response->range);
224 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "org", &response->inet_org);
225 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "netname", &response->inet_netname);
226 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "descr", &response->inet_descr);
227 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "country", &response->inet_country);
228 //gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "created", &response->inet_created);
229 //gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "last-modified", &response->inet_modified);
230 }
231 }
232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_property_equals_str(ptr_prop, "organisation"))
233 {
234 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
235 if (ptr_attributes)
236 {
237 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "org-name", &response->org_name);
238 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "country", &response->org_country);
239 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "org-type", &response->org_type);
240 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "address", &response->org_address);
241 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "phone", &response->org_phone);
242 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "e-mail", &response->org_mail);
243 }
244 }
245
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_property_equals_str(ptr_prop, "person"))
246 {
247 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
248 if (ptr_attributes)
249 {
250 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "person", &response->org_name);
251 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "country", &response->org_country);
252 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "nic-hdl", &response->org_type);
253 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "address", &response->org_address);
254 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "phone", &response->org_phone);
255 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "e-mail", &response->org_mail);
256 }
257 }
258
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_property_equals_str(ptr_prop, "role"))
259 {
260 1 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
261
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_attributes)
262 {
263 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "role", &response->role_name);
264 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "address", &response->role_address);
265 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "e-mail", &response->role_mail);
266 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "admin-c", &response->role_admin_c);
267 1 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "tech-c", &response->role_tech_c);
268 }
269 }
270
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_property_equals_str(ptr_prop, "route"))
271 {
272 ptr_attributes = gate_property_resolve_path(prop_item, &attributes_subpath);
273 if (ptr_attributes)
274 {
275 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "route", &response->route_name);
276 gate_tech_webapi_ipwhois_extract_attribute_values(ptr_attributes, "descr", &response->route_descr);
277 }
278 }
279 }
280 }
281
282 } while (0);
283
284 1 gate_property_destroy(&prop);
285 1 gate_httpclient_release(&http_client);
286 1 gate_strbuilder_release(&path_builder);
287 1 gate_http_response_release(&http_response);
288 1 gate_http_request_release(&http_request);
289
290 1 return ret;
291 }
292