1 /* librepo - A library providing (libcURL like) API to downloading repository
2 * Copyright (C) 2012 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 <glib.h>
22 #include <assert.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include "url_substitution.h"
27 #include "util.h"
28
29 static LrVar *
lr_var_new(const char * var,const char * val)30 lr_var_new(const char *var, const char *val)
31 {
32 LrVar *var_val = lr_malloc0(sizeof(LrVar));
33 var_val->var = g_strdup(var);
34 var_val->val = g_strdup(val);
35 return var_val;
36 }
37
38 static void
lr_var_free(LrVar * var)39 lr_var_free(LrVar *var)
40 {
41 lr_free(var->var);
42 lr_free(var->val);
43 lr_free(var);
44 }
45
46 LrUrlVars *
lr_urlvars_set(LrUrlVars * list,const char * var,const char * value)47 lr_urlvars_set(LrUrlVars *list, const char *var, const char *value)
48 {
49 LrUrlVars *ret = list;
50
51 assert(var);
52
53 if (!value) {
54 // Remove var from the list
55 for (LrUrlVars *elem = list; elem; elem = g_slist_next(elem)) {
56 LrVar *var_val = elem->data;
57 if (!strcmp(var, var_val->var)) {
58 ret = g_slist_remove(list, var_val);
59 lr_var_free(var_val);
60 return ret;
61 }
62 }
63 } else {
64 // Replace var
65 for (LrUrlVars *elem = list; elem; elem = g_slist_next(elem)) {
66 LrVar *var_val = elem->data;
67 if (!strcmp(var, var_val->var)) {
68 lr_free(var_val->val);
69 var_val->val = g_strdup(value);
70 return ret;
71 }
72 }
73
74 // Add var
75 LrVar *var_val = lr_var_new(var, value);
76 ret = g_slist_prepend(list, var_val);
77 }
78
79 return ret;
80 }
81
82 void
lr_urlvars_free(LrUrlVars * list)83 lr_urlvars_free(LrUrlVars *list)
84 {
85 if (!list)
86 return;
87 for (LrUrlVars *elem = list; elem; elem = g_slist_next(elem))
88 lr_var_free(elem->data);
89 g_slist_free(list);
90 }
91
92 char *
lr_url_substitute(const char * url,LrUrlVars * list)93 lr_url_substitute(const char *url, LrUrlVars *list)
94 {
95 const char *cur = url;
96 const char *p = url;
97
98 if (!url)
99 return NULL;
100
101 if (!list)
102 return g_strdup(url);
103
104 char *res = g_strdup("");
105
106 while (*cur != '\0') {
107 if (*cur == '$') {
108 // Adds unprocessed text before the variable to the "res".
109 if (cur-p) {
110 char *tmp = g_strndup(p, cur-p);
111 char *tmp_res = g_strconcat(res, tmp, NULL);
112 g_free(tmp);
113 g_free(res);
114 res = tmp_res;
115 p = cur;
116 }
117
118 // Tries to substitute the variable and store result to the "res".
119 gboolean bracket;
120 if (*++cur == '{') {
121 bracket = TRUE;
122 ++cur;
123 } else {
124 bracket = FALSE;
125 }
126 const char *varname = cur;
127 for (; isalnum(*cur) || (*cur == '_' && isalnum(*(cur + 1))); ++cur);
128 if (cur != varname && (!bracket || *cur == '}')) {
129 for (LrUrlVars *elem = list; elem; elem = g_slist_next(elem)) {
130 LrVar *var_val = elem->data;
131 size_t var_len = strlen(var_val->var);
132 if (var_len == cur - varname && strncmp(var_val->var, varname, var_len) == 0) {
133 if (bracket)
134 ++cur;
135 p = cur;
136 char *tmp_res = g_strconcat(res, var_val->val, NULL);
137 g_free(res);
138 res = tmp_res;
139 break;
140 }
141 }
142 }
143 } else {
144 ++cur;
145 }
146 }
147
148 // Adds remaining text to the "res".
149 if (*p != '\0') {
150 char *tmp_res = g_strconcat(res, p, NULL);
151 g_free(res);
152 res = tmp_res;
153 }
154
155 return res;
156 }
157