1 /* librepo - A library providing (libcURL like) API to downloading repository
2 * Copyright (C) 2013 Tomas Mlcoch
3 *
4 * Licensed under the GNU Lesser General Public License Version 2.1
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "util.h"
26 #include "lrmirrorlist.h"
27
28 LrProtocol
lr_detect_protocol(const char * url)29 lr_detect_protocol(const char *url)
30 {
31 assert(url);
32
33 if (g_str_has_prefix(url, "http://") || g_str_has_prefix(url, "https://"))
34 return LR_PROTOCOL_HTTP;
35
36 if (g_str_has_prefix(url, "ftp://"))
37 return LR_PROTOCOL_FTP;
38
39 if (g_str_has_prefix(url, "file:/"))
40 return LR_PROTOCOL_FILE;
41
42 if (g_str_has_prefix(url, "rsync://"))
43 return LR_PROTOCOL_RSYNC;
44
45 return LR_PROTOCOL_OTHER;
46 }
47
48 static LrInternalMirror *
lr_lrmirror_new(const char * url,LrUrlVars * urlvars)49 lr_lrmirror_new(const char *url, LrUrlVars *urlvars)
50 {
51 LrInternalMirror *mirror;
52
53 mirror = lr_malloc0(sizeof(*mirror));
54 mirror->url = lr_url_substitute(url, urlvars);
55 return mirror;
56 }
57
58 static void
lr_lrmirror_free(void * data)59 lr_lrmirror_free(void *data)
60 {
61 LrInternalMirror *mirror = data;
62 lr_free(mirror->url);
63 lr_free(mirror);
64 }
65
66 void
lr_lrmirrorlist_free(LrInternalMirrorlist * list)67 lr_lrmirrorlist_free(LrInternalMirrorlist *list)
68 {
69 if (!list)
70 return;
71
72 g_slist_free_full(list, lr_lrmirror_free);
73 }
74
75 LrInternalMirrorlist *
lr_lrmirrorlist_append_url(LrInternalMirrorlist * list,const char * url,LrUrlVars * urlvars)76 lr_lrmirrorlist_append_url(LrInternalMirrorlist *list,
77 const char *url,
78 LrUrlVars *urlvars)
79 {
80 if (!url || !strlen(url))
81 return list;
82
83 LrInternalMirror *mirror = lr_lrmirror_new(url, urlvars);
84 mirror->preference = 100;
85 mirror->protocol = lr_detect_protocol(mirror->url);
86
87 //g_debug("%s: Appending URL: %s", __func__, mirror->url);
88
89 return g_slist_append(list, mirror);
90 }
91
92 LrInternalMirrorlist *
lr_lrmirrorlist_append_mirrorlist(LrInternalMirrorlist * list,LrMirrorlist * mirrorlist,LrUrlVars * urlvars)93 lr_lrmirrorlist_append_mirrorlist(LrInternalMirrorlist *list,
94 LrMirrorlist *mirrorlist,
95 LrUrlVars *urlvars)
96 {
97 if (!mirrorlist || !mirrorlist->urls)
98 return list;
99
100 for (GSList *elem = mirrorlist->urls; elem; elem = g_slist_next(elem)) {
101 char *url = elem->data;
102
103 if (!url || !strlen(url))
104 continue;
105
106 LrInternalMirror *mirror = lr_lrmirror_new(url, urlvars);
107 mirror->preference = 100;
108 mirror->protocol = lr_detect_protocol(mirror->url);
109 list = g_slist_append(list, mirror);
110
111 //g_debug("%s: Appending URL: %s", __func__, mirror->url);
112 }
113
114 return list;
115 }
116
117 LrInternalMirrorlist *
lr_lrmirrorlist_append_metalink(LrInternalMirrorlist * list,LrMetalink * metalink,const char * suffix,LrUrlVars * urlvars)118 lr_lrmirrorlist_append_metalink(LrInternalMirrorlist *list,
119 LrMetalink *metalink,
120 const char *suffix,
121 LrUrlVars *urlvars)
122 {
123 size_t suffix_len = 0;
124
125 if (!metalink || !metalink->urls)
126 return list;
127
128 if (suffix)
129 suffix_len = strlen(suffix);
130
131 for (GSList *elem = metalink->urls; elem; elem = g_slist_next(elem)) {
132 LrMetalinkUrl *metalinkurl = elem->data;
133 assert(metalinkurl);
134 char *url = metalinkurl->url;
135
136 if (!url)
137 continue; // No url present
138
139 size_t url_len = strlen(url);
140
141 if (!url_len)
142 continue; // No url present
143
144 char *url_copy = NULL;
145
146 if (suffix_len) {
147 /* Remove suffix if necessary */
148 if (url_len >= suffix_len
149 && !strcmp(url+(url_len-suffix_len), suffix))
150 url_copy = g_strndup(url, url_len-suffix_len);
151 }
152
153 if (!url_copy)
154 url_copy = g_strdup(url);
155
156 LrInternalMirror *mirror = lr_lrmirror_new(url_copy, urlvars);
157 mirror->preference = metalinkurl->preference;
158 mirror->protocol = lr_detect_protocol(mirror->url);
159 lr_free(url_copy);
160 list = g_slist_append(list, mirror);
161
162 //g_debug("%s: Appending URL: %s", __func__, mirror->url);
163 }
164
165 return list;
166 }
167
168 LrInternalMirrorlist *
lr_lrmirrorlist_append_lrmirrorlist(LrInternalMirrorlist * list,LrInternalMirrorlist * other)169 lr_lrmirrorlist_append_lrmirrorlist(LrInternalMirrorlist *list,
170 LrInternalMirrorlist *other)
171 {
172 if (!other)
173 return list;
174
175 for (LrInternalMirrorlist *elem = other; elem; elem = g_slist_next(elem)) {
176 LrInternalMirror *oth = elem->data;
177 if (!oth->url || !strlen(oth->url))
178 continue;
179 LrInternalMirror *mirror = lr_lrmirror_new(oth->url, NULL);
180 mirror->preference = oth->preference;
181 mirror->protocol = oth->protocol;
182 list = g_slist_append(list, mirror);
183 //g_debug("%s: Appending URL: %s", __func__, mirror->url);
184 }
185
186 return list;
187 }
188
189 LrInternalMirror *
lr_lrmirrorlist_nth(LrInternalMirrorlist * list,unsigned int nth)190 lr_lrmirrorlist_nth(LrInternalMirrorlist *list,
191 unsigned int nth)
192 {
193 return g_slist_nth_data(list, nth);
194 }
195
196 char *
lr_lrmirrorlist_nth_url(LrInternalMirrorlist * list,unsigned int nth)197 lr_lrmirrorlist_nth_url(LrInternalMirrorlist *list,
198 unsigned int nth)
199 {
200 LrInternalMirror *mirror = g_slist_nth_data(list, nth);
201 return (mirror) ? mirror->url : NULL;
202 }
203