1 /*
2  * Copyright (c) 2013 Tim Ruehsen
3  * Copyright (c) 2015-2021 Free Software Foundation, Inc.
4  *
5  * This file is part of libwget.
6  *
7  * Libwget is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Libwget is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with libwget.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  *
21  * Extracting URLs from Atom feeds (RFC 4287)
22  *
23  * Changelog
24  * 15.12.2013  Tim Ruehsen  created
25  */
26 
27 #include <config.h>
28 
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <c-ctype.h>
33 
34 #include <wget.h>
35 #include "private.h"
36 
37 /**
38  * \file
39  * \brief URL extraction from Atom feed XML data
40  * \defgroup libwget-parse_atom Atom URL extraction routines
41  * @{
42  *
43  * Routines for URL extraction from Atom feeds.
44  */
45 
46 struct atom_context {
47 	wget_vector
48 		*urls;
49 };
50 
atom_get_url(void * context,int flags,const char * dir,const char * attr,const char * val,size_t len,size_t pos WGET_GCC_UNUSED)51 static void atom_get_url(void *context, int flags, const char *dir, const char *attr, const char *val, size_t len, size_t pos WGET_GCC_UNUSED)
52 {
53 	struct atom_context *ctx = context;
54 	wget_string *url;
55 
56 	if (!val || !len)
57 		return;
58 
59 	if ((flags & XML_FLG_ATTRIBUTE)) {
60 		if (!wget_strcasecmp_ascii(attr, "href") || !wget_strcasecmp_ascii(attr, "uri")
61 			|| !wget_strcasecmp_ascii(attr, "src") || !wget_strcasecmp_ascii(attr, "scheme")
62 			|| !wget_strcasecmp_ascii(attr, "xmlns") || !wget_strncasecmp_ascii(attr, "xmlns:", 6))
63 		{
64 			for (;len && c_isspace(*val); val++, len--); // skip leading spaces
65 			for (;len && c_isspace(val[len - 1]); len--);  // skip trailing spaces
66 
67 			if (!(url = wget_malloc(sizeof(wget_string))))
68 				return;
69 
70 			url->p = val;
71 			url->len = len;
72 
73 			if (!ctx->urls)
74 				ctx->urls = wget_vector_create(32, NULL);
75 
76 			wget_vector_add(ctx->urls, url);
77 		}
78 	}
79 	else if ((flags & XML_FLG_CONTENT)) {
80 		const char *elem = strrchr(dir, '/');
81 
82 		if (elem) {
83 			elem++;
84 
85 			if (!wget_strcasecmp_ascii(elem, "icon") || !wget_strcasecmp_ascii(elem, "id")
86 				 || !wget_strcasecmp_ascii(elem, "logo"))
87 			{
88 				for (;len && c_isspace(*val); val++, len--); // skip leading spaces
89 				for (;len && c_isspace(val[len - 1]); len--);  // skip trailing spaces
90 
91 				// debug_printf("#2 %02X %s %s '%.*s' %zd\n", flags, dir, attr, (int) len, val, len);
92 
93 				if (!(url = wget_malloc(sizeof(wget_string))))
94 					return;
95 
96 				url->p = val;
97 				url->len = len;
98 
99 				if (!ctx->urls)
100 					ctx->urls = wget_vector_create(32, NULL);
101 
102 				wget_vector_add(ctx->urls, url);
103 			}
104 		}
105 	}
106 }
107 
108 /**
109  * \param[in] atom Atom XML data
110  * \param[in,out] urls Pointer to return vector of URLs
111  *
112  * Finds all URLs within the Atom XML data \p atom and returns them
113  * as vector in \p urls.
114  *
115  */
wget_atom_get_urls_inline(const char * atom,wget_vector ** urls)116 void wget_atom_get_urls_inline(const char *atom, wget_vector **urls)
117 {
118 	struct atom_context context = { .urls = NULL };
119 
120 	wget_xml_parse_buffer(atom, atom_get_url, &context, XML_HINT_REMOVE_EMPTY_CONTENT);
121 
122 	*urls = context.urls;
123 }
124 
125 /**@}*/
126