GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/webapis_newsfeed.c
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 151 217 69.6%
Functions: 10 13 76.9%
Branches: 49 108 45.4%

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/encode/xml.h"
32
33 #define GATE_WEBAPIS_NEWSFEED_REQUEST_NAME GATE_STRUCT_WEBAPIS_NAME("newsfeed_request")
34 #define GATE_WEBAPIS_NEWSFEED_RESPONSE_NAME GATE_STRUCT_WEBAPIS_NAME("newsfeed_response")
35 #define GATE_WEBAPIS_NEWSENTRY_NAME GATE_STRUCT_WEBAPIS_NAME("newsfeed_entry")
36
37
38
39 /* newsfeed request initialization */
40
41 static gate_struct_item_t const newsfeed_request_members[] =
42 {
43 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_request_t, GATE_TYPE_STRING, request_url, "Request URL", GATE_STRUCT_FLAG_DEFAULT)
44 };
45
46 static gate_struct_descriptor_t const newsfeed_request_descriptor =
47 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_newsfeed_request_t, GATE_WEBAPIS_NEWSFEED_REQUEST_NAME, newsfeed_request_members);
48
49 1 GATE_TECH_API void gate_tech_webapi_newsfeed_request_init(gate_tech_webapi_newsfeed_request_t* request)
50 {
51 1 gate_mem_clear(request, sizeof(gate_tech_webapi_newsfeed_request_t));
52 1 request->struct_base.struct_descriptor = &newsfeed_request_descriptor;
53 1 }
54
55
56
57 /* newsentry initialization */
58
59 static gate_struct_item_t const newsentry_members[] =
60 {
61 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, uid, "Unique-ID", GATE_STRUCT_FLAG_DEFAULT),
62 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, title, "Title", GATE_STRUCT_FLAG_DEFAULT),
63 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, link, "Link", GATE_STRUCT_FLAG_DEFAULT),
64 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_TIME, update_time, "Updated", GATE_STRUCT_FLAG_DEFAULT),
65 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, author, "Author", GATE_STRUCT_FLAG_DEFAULT),
66 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, category, "Category", GATE_STRUCT_FLAG_DEFAULT),
67 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, summary, "Summary", GATE_STRUCT_FLAG_DEFAULT),
68
69 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsentry_t, GATE_TYPE_STRING, content, "Content", GATE_STRUCT_FLAG_DEFAULT)
70 };
71
72 static gate_struct_descriptor_t const newsentry_descriptor =
73 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_newsentry_t, GATE_WEBAPIS_NEWSENTRY_NAME, newsentry_members);
74
75 20 void gate_tech_webapi_newsentry_init(gate_tech_webapi_newsentry_t* entry)
76 {
77 20 gate_mem_clear(entry, sizeof(gate_tech_webapi_newsentry_t));
78 20 entry->struct_base.struct_descriptor = &newsentry_descriptor;
79 20 }
80 51 static gate_result_t gate_tech_webapi_newsentry_copyctor(void* target, void const* source)
81 {
82 gate_result_t result;
83 51 gate_tech_webapi_newsentry_t* ptr_dst = (gate_tech_webapi_newsentry_t*)target;
84 51 gate_tech_webapi_newsentry_t const* ptr_src = (gate_tech_webapi_newsentry_t const*)source;
85
86
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 if (ptr_src)
87 {
88 51 gate_mem_clear(ptr_dst, sizeof(gate_tech_webapi_newsentry_t));
89 51 result = gate_struct_copy(&ptr_dst->struct_base, &ptr_src->struct_base);
90 }
91 else
92 {
93 ✗ gate_tech_webapi_newsentry_init(ptr_dst);
94 ✗ result = GATE_RESULT_OK;
95 }
96 51 return result;
97 }
98
99
100
101
102 static gate_struct_item_t const newsfeed_response_members[] =
103 {
104 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, request_url,"Request URL", GATE_STRUCT_FLAG_DEFAULT),
105
106 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, uid, "Unique-ID", GATE_STRUCT_FLAG_DEFAULT),
107 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, title, "Title", GATE_STRUCT_FLAG_DEFAULT),
108 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, link, "Link", GATE_STRUCT_FLAG_DEFAULT),
109 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_TIME, update_time, "Updated", GATE_STRUCT_FLAG_DEFAULT),
110
111 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, description,"Description", GATE_STRUCT_FLAG_DEFAULT),
112 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, language, "Language", GATE_STRUCT_FLAG_DEFAULT),
113 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, publisher, "Publisher", GATE_STRUCT_FLAG_DEFAULT),
114 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, contact, "Contact", GATE_STRUCT_FLAG_DEFAULT),
115 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_STRING, image, "Image", GATE_STRUCT_FLAG_DEFAULT),
116
117 GATE_STRUCT_ITEM_EX(gate_tech_webapi_newsfeed_response_t, GATE_TYPE_ARRAYLIST_STRUCT, entries, "Entries", GATE_STRUCT_FLAG_DEFAULT)
118 };
119
120 static gate_struct_descriptor_t const newsfeed_response_descriptor =
121 GATE_STRUCT_DESCRIPTOR(gate_tech_webapi_newsfeed_response_t, GATE_WEBAPIS_NEWSFEED_RESPONSE_NAME, newsfeed_response_members);
122
123 1 GATE_TECH_API void gate_tech_webapi_newsfeed_response_init(gate_tech_webapi_newsfeed_response_t* response)
124 {
125 1 gate_mem_clear(response, sizeof(gate_tech_webapi_newsfeed_response_t));
126 1 response->struct_base.struct_descriptor = &newsfeed_response_descriptor;
127 1 response->entries = gate_arraylist_create(sizeof(gate_tech_webapi_newsentry_t), NULL, 0,
128 &gate_tech_webapi_newsentry_copyctor, &gate_struct_destructor);
129 1 }
130
131
132 460 static gate_bool_t xml_node_is_tag(gate_xml_node_t const* node, gate_string_t const* tagname)
133 {
134 460 return gate_string_equals(&node->tag, tagname);
135 }
136
137 87 static gate_xml_node_t const* get_child_by_tag(gate_xml_node_t const* node, gate_string_t const* tagname)
138 {
139 87 gate_size_t children = gate_xml_node_children_count(node);
140 gate_size_t ndx;
141 87 gate_xml_node_t const* ptr_child = NULL;
142
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 23 times.
455 for (ndx = 0; ndx != children; ++ndx)
143 {
144 432 ptr_child = gate_xml_node_child_ptr(node, ndx);
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 432 times.
432 if (!ptr_child)
146 {
147 ✗ continue;
148 }
149
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 368 times.
432 if (xml_node_is_tag(ptr_child, tagname))
150 {
151 64 return ptr_child;
152 }
153 }
154 23 return NULL;
155 }
156
157 20 static gate_bool_t parse_time(gate_string_t const* str, gate_datetime_t* dt)
158 {
159 /* "Thu, 11 Apr 2024 21:47:03" */
160 20 gate_string_t str_day = GATE_STRING_INIT_STATIC("01");
161 20 gate_string_t str_mon = GATE_STRING_INIT_STATIC("Jan");
162 20 gate_string_t str_year = GATE_STRING_INIT_STATIC("1970");
163 20 gate_string_t str_hour = GATE_STRING_INIT_STATIC("00");
164 20 gate_string_t str_min = GATE_STRING_INIT_STATIC("00");
165 20 gate_string_t str_sec = GATE_STRING_INIT_STATIC("00");
166 20 gate_size_t len = gate_string_length(str);
167 20 char const* ptr = gate_string_ptr(str, 0);
168 gate_uint64_t num;
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (len < 16)
170 {
171 ✗ return false;
172 }
173
4/8
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
20 if ((ptr[3] != ',') || (ptr[4] != ' ') || (ptr[7] != ' ') || (ptr[11] != ' '))
174 {
175 ✗ return false;
176 }
177
178 20 gate_mem_clear(dt, sizeof(gate_datetime_t));
179
180 20 gate_string_create_static_len(&str_day, &ptr[5], 2);
181 20 gate_string_create_static_len(&str_mon, &ptr[8], 3);
182 20 gate_string_create_static_len(&str_year, &ptr[12], 4);
183
184
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (len >= 22)
185 {
186 20 gate_string_create_static_len(&str_hour, &ptr[17], 2);
187 20 gate_string_create_static_len(&str_min, &ptr[20], 2);
188 }
189
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (len >= 25)
190 {
191 20 gate_string_create_static_len(&str_sec, &ptr[23], 2);
192 }
193
194
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (gate_string_parse_uint(&str_day, &num) > 0)
195 {
196 20 dt->date.day = (gate_uint8_t)num;
197 }
198
199 20 gate_date_parse_month(str_mon.str, str_mon.length, &dt->date.month);
200
201
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (gate_string_parse_uint(&str_year, &num) > 0)
202 {
203 20 dt->date.year = (gate_uint16_t)num;
204 }
205
206
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (gate_string_parse_uint(&str_hour, &num) > 0)
207 {
208 20 dt->time.hour = (gate_uint8_t)num;
209 }
210
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (gate_string_parse_uint(&str_min, &num) > 0)
211 {
212 20 dt->time.minute = (gate_uint8_t)num;
213 }
214
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (gate_string_parse_uint(&str_sec, &num) > 0)
215 {
216 20 dt->time.second = (gate_uint8_t)num;
217 }
218 20 return true;
219 }
220
221 66 static gate_bool_t extract_content(gate_xml_node_t const* node, gate_string_t* target)
222 {
223 gate_size_t children, ndx;
224 gate_xml_node_t const* child;
225 66 gate_strbuilder_t builder = GATE_INIT_EMPTY;
226
227
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 22 times.
66 if (node)
228 {
229
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (node->node_type == GATE_XML_NODE_TYPE_ELEMENT)
230 {
231 44 children = gate_array_length(&node->child_nodes);
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (children == 1)
233 {
234 ✗ child = (gate_xml_node_t const*)gate_array_get(&node->child_nodes, 0);
235 ✗ if (child && (child->node_type == GATE_XML_NODE_TYPE_CDATA))
236 {
237 ✗ gate_string_clone(target, &child->content);
238 }
239 }
240
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43 times.
44 else if (children > 1)
241 {
242 1 gate_strbuilder_create(&builder, 0);
243
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (ndx = 0; ndx != children; ++ndx)
244 {
245 3 child = (gate_xml_node_t const*)gate_array_get(&node->child_nodes, ndx);
246
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (child && (child->node_type == GATE_XML_NODE_TYPE_CDATA))
247 {
248 ✗ gate_strbuilder_append_string(&builder, &child->content);
249 }
250 }
251 1 gate_strbuilder_to_string(&builder, target);
252 1 gate_strbuilder_release(&builder);
253 }
254 else
255 {
256 43 gate_xml_decode(&node->content, target);
257 }
258 44 return true;
259 }
260 }
261 22 return false;
262 }
263
264 ✗ static gate_bool_t extract_attribute(gate_xml_node_t const* node, gate_string_t const* attr, gate_string_t* target)
265 {
266 gate_string_t const* ptr_attrvalue;
267 ✗ if (node)
268 {
269 ✗ ptr_attrvalue = gate_xml_node_attribute_ptr_by_name(node, attr);
270 ✗ if (ptr_attrvalue)
271 {
272 ✗ gate_string_clone(target, ptr_attrvalue);
273 ✗ return true;
274 }
275 }
276 ✗ return false;
277 }
278
279 ✗ static gate_bool_t extract_time(gate_xml_node_t const* node, gate_time_t* timestamp)
280 {
281 gate_datetime_t dt;
282 ✗ if (node)
283 {
284 ✗ if (gate_date_parse_string(node->content.str, node->content.length, &dt, NULL) > 0)
285 {
286 ✗ gate_date_to_time(&dt, timestamp);
287 ✗ return true;
288 }
289 }
290 ✗ return false;
291 }
292
293 ✗ static gate_result_t parse_atom(gate_string_t const* url, gate_xml_node_t const* root, gate_tech_webapi_newsfeed_response_t* response)
294 {
295 static gate_string_t const tag_title = GATE_STRING_INIT_STATIC("title");
296 static gate_string_t const tag_subtitle = GATE_STRING_INIT_STATIC("subtitle");
297 static gate_string_t const tag_link = GATE_STRING_INIT_STATIC("link");
298 static gate_string_t const tag_id = GATE_STRING_INIT_STATIC("id");
299 static gate_string_t const tag_updated = GATE_STRING_INIT_STATIC("updated");
300 static gate_string_t const attr_href = GATE_STRING_INIT_STATIC("href");
301
302 static gate_string_t const tag_entry = GATE_STRING_INIT_STATIC("entry");
303 /*static gate_string_t const tag_published = GATE_STRING_INIT_STATIC("published");*/
304 static gate_string_t const tag_summary = GATE_STRING_INIT_STATIC("summary");
305 static gate_string_t const tag_content = GATE_STRING_INIT_STATIC("content");
306 static gate_string_t const tag_author = GATE_STRING_INIT_STATIC("author");
307 static gate_string_t const tag_name = GATE_STRING_INIT_STATIC("name");
308 static gate_string_t const tag_email = GATE_STRING_INIT_STATIC("email");
309
310 ✗ gate_result_t ret = GATE_RESULT_FAILED;
311 gate_size_t root_children, ndx;
312 gate_xml_node_t const* entry;
313 gate_xml_node_t const* subentry;
314 gate_tech_webapi_newsentry_t news_entry;
315
316 do
317 {
318 ✗ gate_string_clone(&response->request_url, url);
319 ✗ extract_content(get_child_by_tag(root, &tag_title), &response->title);
320 ✗ extract_content(get_child_by_tag(root, &tag_subtitle), &response->description);
321 ✗ extract_attribute(get_child_by_tag(root, &tag_link), &attr_href, &response->link);
322 ✗ extract_content(get_child_by_tag(root, &tag_id), &response->uid);
323 ✗ extract_time(get_child_by_tag(root, &tag_updated), &response->update_time);
324 ✗ subentry = get_child_by_tag(root, &tag_author);
325 ✗ if (subentry)
326 {
327 ✗ extract_content(get_child_by_tag(subentry, &tag_email), &response->contact);
328 ✗ extract_content(get_child_by_tag(subentry, &tag_name), &response->publisher);
329 }
330
331 ✗ root_children = gate_xml_node_children_count(root);
332 ✗ for (ndx = 0; ndx != root_children; ++ndx)
333 {
334 ✗ entry = gate_xml_node_child_ptr(root, ndx);
335 ✗ if (!entry)
336 {
337 ✗ continue;
338 }
339 ✗ if (!xml_node_is_tag(entry, &tag_entry))
340 {
341 /* skip non-channels */
342 ✗ continue;
343 }
344
345 ✗ gate_tech_webapi_newsentry_init(&news_entry);
346
347 ✗ extract_content(get_child_by_tag(entry, &tag_title), &news_entry.title);
348 ✗ extract_attribute(get_child_by_tag(entry, &tag_link), &attr_href, &news_entry.link);
349 ✗ extract_content(get_child_by_tag(entry, &tag_id), &news_entry.uid);
350 ✗ extract_content(get_child_by_tag(entry, &tag_summary), &news_entry.summary);
351 ✗ extract_content(get_child_by_tag(entry, &tag_content), &news_entry.content);
352 ✗ extract_time(get_child_by_tag(entry, &tag_updated), &news_entry.update_time);
353 ✗ subentry = get_child_by_tag(entry, &tag_author);
354 ✗ if (subentry)
355 {
356 ✗ if (!extract_content(get_child_by_tag(subentry, &tag_name), &news_entry.author))
357 {
358 ✗ gate_string_clone(&news_entry.author, &response->publisher);
359 }
360 }
361 else
362 {
363 ✗ gate_string_clone(&news_entry.author, &response->publisher);
364 }
365
366 ✗ gate_arraylist_add(response->entries, &news_entry);
367 ✗ gate_struct_release(&news_entry.struct_base);
368 }
369
370 ✗ ret = GATE_RESULT_OK;
371 } while (0);
372
373
374 ✗ return ret;
375 }
376
377
378 1 static gate_result_t parse_rss(gate_string_t const* url, gate_xml_node_t const* root, gate_tech_webapi_newsfeed_response_t* response)
379 {
380 static gate_string_t const tag_channel = GATE_STRING_INIT_STATIC("channel");
381 /*static gate_string_t const tag_category = GATE_STRING_INIT_STATIC("category");*/
382 static gate_string_t const tag_title = GATE_STRING_INIT_STATIC("title");
383 static gate_string_t const tag_link = GATE_STRING_INIT_STATIC("link");
384 static gate_string_t const tag_descr = GATE_STRING_INIT_STATIC("description");
385 static gate_string_t const tag_date = GATE_STRING_INIT_STATIC("pubDate");
386 static gate_string_t const tag_item = GATE_STRING_INIT_STATIC("item");
387 /*static gate_string_t const tag_author = GATE_STRING_INIT_STATIC("author");*/
388 /*static gate_string_t const tag_guid = GATE_STRING_INIT_STATIC("guid");*/
389 /*static gate_string_t const tag_content = GATE_STRING_INIT_STATIC("content");*/
390 static gate_string_t const tag_language = GATE_STRING_INIT_STATIC("language");
391 static gate_string_t const tag_image = GATE_STRING_INIT_STATIC("image");
392 static gate_string_t const tag_webmaster = GATE_STRING_INIT_STATIC("webMaster");
393
394 1 gate_result_t ret = GATE_RESULT_FAILED;
395 gate_size_t root_children;
396 gate_size_t ndx_channel;
397 gate_xml_node_t const* ptr_channel;
398 gate_xml_node_t const* ptr_channel_title;
399 gate_xml_node_t const* ptr_channel_link;
400 gate_xml_node_t const* ptr_channel_descr;
401 gate_xml_node_t const* ptr_channel_date;
402 gate_xml_node_t const* ptr_channel_lang;
403 gate_xml_node_t const* ptr_channel_icon;
404 gate_xml_node_t const* ptr_channel_webmaster;
405 gate_xml_node_t const* ptr_item;
406 gate_size_t item_counter;
407 gate_size_t item_index;
408 gate_xml_node_t const* ptr_item_title;
409 gate_xml_node_t const* ptr_item_link;
410 gate_xml_node_t const* ptr_item_description;
411 gate_xml_node_t const* ptr_item_pubdate;
412 gate_datetime_t dt;
413 gate_tech_webapi_newsentry_t news_entry;
414
415 do
416 {
417 1 gate_string_clone(&response->request_url, url);
418 1 gate_string_clone(&response->uid, url);
419
420 1 root_children = gate_xml_node_children_count(root);
421
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (ndx_channel = 0; ndx_channel != root_children; ++ndx_channel)
422 {
423 1 ptr_channel = gate_xml_node_child_ptr(root, ndx_channel);
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_channel)
425 {
426 ✗ continue;
427 }
428
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!xml_node_is_tag(ptr_channel, &tag_channel))
429 {
430 /* skip non-channels */
431 ✗ continue;
432 }
433 1 ptr_channel_title = get_child_by_tag(ptr_channel, &tag_title);
434 1 ptr_channel_link = get_child_by_tag(ptr_channel, &tag_link);
435 1 ptr_channel_descr = get_child_by_tag(ptr_channel, &tag_descr);
436 1 ptr_channel_date = get_child_by_tag(ptr_channel, &tag_date);
437 1 ptr_channel_lang = get_child_by_tag(ptr_channel, &tag_language);
438 1 ptr_channel_icon = get_child_by_tag(ptr_channel, &tag_image);
439 1 ptr_channel_webmaster = get_child_by_tag(ptr_channel, &tag_webmaster);
440
441 1 extract_content(ptr_channel_title, &response->title);
442 1 extract_content(ptr_channel_link, &response->link);
443 1 extract_content(ptr_channel_descr, &response->description);
444 1 extract_content(ptr_channel_lang, &response->language);
445 1 extract_content(ptr_channel_icon, &response->image);
446 1 extract_content(ptr_channel_webmaster, &response->contact);
447
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_channel_date)
449 {
450 ✗ if (parse_time(&ptr_channel_date->content, &dt))
451 {
452 ✗ gate_date_to_time(&dt, &response->update_time);
453 }
454 }
455
456 1 item_counter = gate_xml_node_children_count(ptr_channel);
457
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1 times.
28 for (item_index = 0; item_index != item_counter; ++item_index)
458 {
459 27 ptr_item = gate_xml_node_child_ptr(ptr_channel, item_index);
460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!ptr_item)
461 {
462 ✗ continue;
463 }
464
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 20 times.
27 if (!xml_node_is_tag(ptr_item, &tag_item))
465 {
466 /* skip non-items*/
467 7 continue;
468 }
469
470 20 gate_tech_webapi_newsentry_init(&news_entry);
471
472 20 ptr_item_title = get_child_by_tag(ptr_item, &tag_title);
473 20 ptr_item_link = get_child_by_tag(ptr_item, &tag_link);
474 20 ptr_item_description = get_child_by_tag(ptr_item, &tag_descr);
475 20 ptr_item_pubdate = get_child_by_tag(ptr_item, &tag_date);
476
477 20 extract_content(ptr_item_title, &news_entry.title);
478 20 extract_content(ptr_item_link, &news_entry.link);
479 20 extract_content(ptr_item_description, &news_entry.summary);
480
481
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (ptr_item_pubdate)
482 {
483
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (parse_time(&ptr_item_pubdate->content, &dt))
484 {
485 20 gate_date_to_time(&dt, &news_entry.update_time);
486 }
487 }
488
489 20 gate_arraylist_add(response->entries, &news_entry);
490 20 gate_struct_release(&news_entry.struct_base);
491 }
492 }
493 1 ret = GATE_RESULT_OK;
494 } while (0);
495
496 1 return ret;
497 }
498
499
500 1 gate_result_t gate_tech_webapi_newsfeed(gate_tech_webapi_context_t* context,
501 gate_tech_webapi_newsfeed_request_t* request,
502 gate_tech_webapi_newsfeed_response_t* response)
503 {
504 1 gate_result_t ret = GATE_RESULT_FAILED;
505 1 gate_uri_t url = GATE_INIT_EMPTY;
506 1 gate_uint32_t http_status = 0;
507 1 gate_stringstream_t* content = NULL;
508 1 gate_xml_doc_t doc = GATE_INIT_EMPTY;
509 gate_xml_node_t const* ptr_node;
510 1 gate_string_t tag_name = GATE_STRING_INIT_EMPTY;
511 static gate_string_t const atom_root = GATE_STRING_INIT_STATIC("feed");
512 static gate_string_t const rss_root = GATE_STRING_INIT_STATIC("rss");
513
514 do
515 {
516 1 ret = gate_uri_parse(&url, &request->request_url);
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
518
519 1 content = gate_stringstream_create(0);
520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!content)
521 {
522 ✗ ret = GATE_RESULT_OUTOFMEMORY;
523 ✗ break;
524 }
525
526 1 ret = gate_tech_webapi_get(context, &url, NULL, &http_status, (gate_stream_t*)content, NULL);
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
528
529 1 ret = gate_xml_doc_load(&doc, (gate_stream_t*)content);
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
531
532 1 ret = gate_xml_doc_root_element(&doc, &ptr_node);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
534
535 1 ret = gate_xml_parse_decompose_name(&ptr_node->tag, NULL, &tag_name);
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
537
538
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_string_equals(&tag_name, &atom_root))
539 {
540 /* parse atom feed */
541 ✗ ret = parse_atom(&request->request_url, ptr_node, response);
542 }
543
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 else if (gate_string_equals(&tag_name, &rss_root))
544 {
545 /* parse RSS */
546 1 ret = parse_rss(&request->request_url, ptr_node, response);
547 }
548 else
549 {
550 ✗ ret = GATE_RESULT_INVALIDCONTENT;
551 }
552
553 } while (0);
554
555 1 gate_string_release(&tag_name);
556
557 1 gate_xml_doc_destroy(&doc);
558
559
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (content != NULL)
560 {
561 1 gate_object_release(content);
562 }
563 1 gate_uri_destroy(&url);
564
565 1 return ret;
566
567 }
568
569