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