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 |