GCC Code Coverage Report


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