GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/webapis_newsfeed.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 151 225 67.1%
Functions: 10 14 71.4%
Branches: 49 112 43.8%

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 462 static gate_bool_t xml_node_is_tag(gate_xml_node_t const* node, gate_string_t const* tagname)
133 {
134 462 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 434 times.
✓ Branch 1 taken 23 times.
457 for (ndx = 0; ndx != children; ++ndx)
143 {
144 434 ptr_child = gate_xml_node_child_ptr(node, ndx);
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 434 times.
434 if (!ptr_child)
146 {
147 continue;
148 }
149
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 370 times.
434 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_node_attribute(gate_xml_node_t const* node, gate_string_t const* tagname, gate_string_t const* attr, gate_string_t* target)
280 {
281 gate_string_t const* ptr_attrvalue;
282 gate_xml_node_t const* child = get_child_by_tag(node, tagname);
283 if (child)
284 {
285 ptr_attrvalue = gate_xml_node_attribute_ptr_by_name(node, attr);
286 if (ptr_attrvalue)
287 {
288 gate_string_clone(target, ptr_attrvalue);
289 return true;
290 }
291 }
292 return false;
293 }
294
295
296 static gate_bool_t extract_time(gate_xml_node_t const* node, gate_time_t* timestamp)
297 {
298 gate_datetime_t dt;
299 if (node)
300 {
301 if (gate_date_parse_string(node->content.str, node->content.length, &dt, NULL) > 0)
302 {
303 gate_date_to_time(&dt, timestamp);
304 return true;
305 }
306 }
307 return false;
308 }
309
310 static gate_result_t parse_atom(gate_string_t const* url, gate_xml_doc_t const* doc, gate_xml_node_t const* root, gate_tech_webapi_newsfeed_response_t* response)
311 {
312 static gate_string_t const tag_title = GATE_STRING_INIT_STATIC("title");
313 static gate_string_t const tag_subtitle = GATE_STRING_INIT_STATIC("subtitle");
314 static gate_string_t const tag_link = GATE_STRING_INIT_STATIC("link");
315 static gate_string_t const tag_id = GATE_STRING_INIT_STATIC("id");
316 static gate_string_t const tag_updated = GATE_STRING_INIT_STATIC("updated");
317 static gate_string_t const attr_href = GATE_STRING_INIT_STATIC("href");
318
319 static gate_string_t const tag_entry = GATE_STRING_INIT_STATIC("entry");
320 /*static gate_string_t const tag_published = GATE_STRING_INIT_STATIC("published");*/
321 static gate_string_t const tag_summary = GATE_STRING_INIT_STATIC("summary");
322 static gate_string_t const tag_content = GATE_STRING_INIT_STATIC("content");
323 static gate_string_t const tag_author = GATE_STRING_INIT_STATIC("author");
324 static gate_string_t const tag_name = GATE_STRING_INIT_STATIC("name");
325 static gate_string_t const tag_email = GATE_STRING_INIT_STATIC("email");
326
327 gate_result_t ret = GATE_RESULT_FAILED;
328 gate_size_t root_children, ndx;
329 gate_xml_node_t const* entry;
330 gate_xml_node_t const* subentry;
331 gate_tech_webapi_newsentry_t news_entry;
332
333 GATE_UNUSED_ARG(doc);
334
335 do
336 {
337 gate_string_clone(&response->request_url, url);
338 extract_content(get_child_by_tag(root, &tag_title), &response->title);
339 extract_content(get_child_by_tag(root, &tag_subtitle), &response->description);
340 extract_attribute(get_child_by_tag(root, &tag_link), &attr_href, &response->link);
341 extract_content(get_child_by_tag(root, &tag_id), &response->uid);
342 extract_time(get_child_by_tag(root, &tag_updated), &response->update_time);
343 subentry = get_child_by_tag(root, &tag_author);
344 if (subentry)
345 {
346 extract_content(get_child_by_tag(subentry, &tag_email), &response->contact);
347 extract_content(get_child_by_tag(subentry, &tag_name), &response->publisher);
348 }
349
350 root_children = gate_xml_node_children_count(root);
351 for (ndx = 0; ndx != root_children; ++ndx)
352 {
353 entry = gate_xml_node_child_ptr(root, ndx);
354 if (!entry)
355 {
356 continue;
357 }
358 if (!xml_node_is_tag(entry, &tag_entry))
359 {
360 /* skip non-channels */
361 continue;
362 }
363
364 gate_tech_webapi_newsentry_init(&news_entry);
365
366 extract_content(get_child_by_tag(entry, &tag_title), &news_entry.title);
367 extract_attribute(get_child_by_tag(entry, &tag_link), &attr_href, &news_entry.link);
368 extract_content(get_child_by_tag(entry, &tag_id), &news_entry.uid);
369 extract_content(get_child_by_tag(entry, &tag_summary), &news_entry.summary);
370 extract_content(get_child_by_tag(entry, &tag_content), &news_entry.content);
371 extract_time(get_child_by_tag(entry, &tag_updated), &news_entry.update_time);
372 subentry = get_child_by_tag(entry, &tag_author);
373 if (subentry)
374 {
375 if (!extract_content(get_child_by_tag(subentry, &tag_name), &news_entry.author))
376 {
377 gate_string_clone(&news_entry.author, &response->publisher);
378 }
379 }
380 else
381 {
382 gate_string_clone(&news_entry.author, &response->publisher);
383 }
384
385 gate_arraylist_add(response->entries, &news_entry);
386 gate_struct_release(&news_entry.struct_base);
387 }
388
389 ret = GATE_RESULT_OK;
390 } while (0);
391
392
393 return ret;
394 }
395
396
397 1 static gate_result_t parse_rss(gate_string_t const* url, gate_xml_doc_t const* doc, gate_xml_node_t const* root, gate_tech_webapi_newsfeed_response_t* response)
398 {
399 static gate_string_t const tag_channel = GATE_STRING_INIT_STATIC("channel");
400 /*static gate_string_t const tag_category = GATE_STRING_INIT_STATIC("category");*/
401 static gate_string_t const tag_title = GATE_STRING_INIT_STATIC("title");
402 static gate_string_t const tag_link = GATE_STRING_INIT_STATIC("link");
403 static gate_string_t const tag_descr = GATE_STRING_INIT_STATIC("description");
404 static gate_string_t const tag_date = GATE_STRING_INIT_STATIC("pubDate");
405 static gate_string_t const tag_item = GATE_STRING_INIT_STATIC("item");
406 /*static gate_string_t const tag_author = GATE_STRING_INIT_STATIC("author");*/
407 /*static gate_string_t const tag_guid = GATE_STRING_INIT_STATIC("guid");*/
408 /*static gate_string_t const tag_content = GATE_STRING_INIT_STATIC("content");*/
409 static gate_string_t const tag_language = GATE_STRING_INIT_STATIC("language");
410 static gate_string_t const tag_image = GATE_STRING_INIT_STATIC("image");
411 static gate_string_t const tag_webmaster = GATE_STRING_INIT_STATIC("webMaster");
412
413 1 gate_result_t ret = GATE_RESULT_FAILED;
414 gate_size_t root_children;
415 gate_size_t ndx_channel;
416 gate_xml_node_t const* ptr_channel;
417 gate_xml_node_t const* ptr_channel_title;
418 gate_xml_node_t const* ptr_channel_link;
419 gate_xml_node_t const* ptr_channel_descr;
420 gate_xml_node_t const* ptr_channel_date;
421 gate_xml_node_t const* ptr_channel_lang;
422 gate_xml_node_t const* ptr_channel_icon;
423 gate_xml_node_t const* ptr_channel_webmaster;
424 gate_xml_node_t const* ptr_item;
425 gate_size_t item_counter;
426 gate_size_t item_index;
427 gate_xml_node_t const* ptr_item_title;
428 gate_xml_node_t const* ptr_item_link;
429 gate_xml_node_t const* ptr_item_description;
430 gate_xml_node_t const* ptr_item_pubdate;
431 gate_datetime_t dt;
432 gate_tech_webapi_newsentry_t news_entry;
433
434 do
435 {
436 1 gate_string_clone(&response->request_url, url);
437 1 gate_string_clone(&response->uid, url);
438
439 1 root_children = gate_xml_node_children_count(root);
440
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (ndx_channel = 0; ndx_channel != root_children; ++ndx_channel)
441 {
442 1 ptr_channel = gate_xml_node_child_ptr(root, ndx_channel);
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_channel)
444 {
445 continue;
446 }
447
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!xml_node_is_tag(ptr_channel, &tag_channel))
448 {
449 /* skip non-channels */
450 continue;
451 }
452 1 ptr_channel_title = get_child_by_tag(ptr_channel, &tag_title);
453 1 ptr_channel_link = get_child_by_tag(ptr_channel, &tag_link);
454 1 ptr_channel_descr = get_child_by_tag(ptr_channel, &tag_descr);
455 1 ptr_channel_date = get_child_by_tag(ptr_channel, &tag_date);
456 1 ptr_channel_lang = get_child_by_tag(ptr_channel, &tag_language);
457 1 ptr_channel_icon = get_child_by_tag(ptr_channel, &tag_image);
458 1 ptr_channel_webmaster = get_child_by_tag(ptr_channel, &tag_webmaster);
459
460 1 extract_content(ptr_channel_title, &response->title);
461 1 extract_content(ptr_channel_link, &response->link);
462 1 extract_content(ptr_channel_descr, &response->description);
463 1 extract_content(ptr_channel_lang, &response->language);
464 1 extract_content(ptr_channel_icon, &response->image);
465 1 extract_content(ptr_channel_webmaster, &response->contact);
466
467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_channel_date)
468 {
469 if (parse_time(&ptr_channel_date->content, &dt))
470 {
471 gate_date_to_time(&dt, &response->update_time);
472 }
473 }
474
475 1 item_counter = gate_xml_node_children_count(ptr_channel);
476
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1 times.
28 for (item_index = 0; item_index != item_counter; ++item_index)
477 {
478 27 ptr_item = gate_xml_node_child_ptr(ptr_channel, item_index);
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!ptr_item)
480 {
481 continue;
482 }
483
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 20 times.
27 if (!xml_node_is_tag(ptr_item, &tag_item))
484 {
485 /* skip non-items*/
486 7 continue;
487 }
488
489 20 gate_tech_webapi_newsentry_init(&news_entry);
490
491 20 ptr_item_title = get_child_by_tag(ptr_item, &tag_title);
492 20 ptr_item_link = get_child_by_tag(ptr_item, &tag_link);
493 20 ptr_item_description = get_child_by_tag(ptr_item, &tag_descr);
494 20 ptr_item_pubdate = get_child_by_tag(ptr_item, &tag_date);
495
496 20 extract_content(ptr_item_title, &news_entry.title);
497 20 extract_content(ptr_item_link, &news_entry.link);
498 20 extract_content(ptr_item_description, &news_entry.summary);
499
500
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (ptr_item_pubdate)
501 {
502
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if (parse_time(&ptr_item_pubdate->content, &dt))
503 {
504 20 gate_date_to_time(&dt, &news_entry.update_time);
505 }
506 }
507
508 20 gate_arraylist_add(response->entries, &news_entry);
509 20 gate_struct_release(&news_entry.struct_base);
510 }
511 }
512 1 ret = GATE_RESULT_OK;
513 } while (0);
514
515 1 return ret;
516 }
517
518
519 1 gate_result_t gate_tech_webapi_newsfeed(gate_tech_webapi_context_t* context,
520 gate_tech_webapi_newsfeed_request_t* request,
521 gate_tech_webapi_newsfeed_response_t* response)
522 {
523 1 gate_result_t ret = GATE_RESULT_FAILED;
524 1 gate_uri_t url = GATE_INIT_EMPTY;
525 1 gate_uint32_t http_status = 0;
526 1 gate_stringstream_t* content = NULL;
527 1 gate_xml_doc_t doc = GATE_INIT_EMPTY;
528 gate_xml_node_t const* ptr_node;
529 1 gate_string_t tag_name = GATE_STRING_INIT_EMPTY;
530 static gate_string_t const atom_root = GATE_STRING_INIT_STATIC("feed");
531 static gate_string_t const rss_root = GATE_STRING_INIT_STATIC("rss");
532
533 do
534 {
535 1 ret = gate_uri_parse(&url, &request->request_url);
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
537
538 1 content = gate_stringstream_create(0);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!content)
540 {
541 ret = GATE_RESULT_OUTOFMEMORY;
542 break;
543 }
544
545 1 ret = gate_tech_webapi_get(context, &url, NULL, &http_status, (gate_stream_t*)content, NULL);
546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
547
548 1 ret = gate_xml_doc_load(&doc, (gate_stream_t*)content);
549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
550
551 1 ret = gate_xml_doc_root_element(&doc, &ptr_node);
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
553
554 1 ret = gate_xml_parse_decompose_name(&ptr_node->tag, NULL, &tag_name);
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
556
557
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_string_equals(&tag_name, &atom_root))
558 {
559 /* parse atom feed */
560 ret = parse_atom(&request->request_url, &doc, ptr_node, response);
561 }
562
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 else if (gate_string_equals(&tag_name, &rss_root))
563 {
564 /* parse RSS */
565 1 ret = parse_rss(&request->request_url, &doc, ptr_node, response);
566 }
567 else
568 {
569 ret = GATE_RESULT_INVALIDCONTENT;
570 }
571
572 } while (0);
573
574 1 gate_string_release(&tag_name);
575
576 1 gate_xml_doc_destroy(&doc);
577
578
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (content != NULL)
579 {
580 1 gate_object_release(content);
581 }
582 1 gate_uri_destroy(&url);
583
584 1 return ret;
585
586 }
587
588