tracker-0.16.2/src/libtracker-sparql/tracker-uri.c

No issues found

  1 /*
  2  * Copyright (C) 2008-2010, Nokia <ivan.frade@nokia.com>
  3  * Copyright (C) 2010, Codeminded BVBA <abustany@gnome.org>
  4  *
  5  * This library is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU Lesser General Public
  7  * License as published by the Free Software Foundation; either
  8  * version 2.1 of the License, or (at your option) any later version.
  9  *
 10  * This library is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * Lesser General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU Lesser General Public
 16  * License along with this library; if not, write to the
 17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 18  * Boston, MA  02110-1301, USA.
 19  */
 20 
 21 #include "config.h"
 22 
 23 #include <string.h>
 24 
 25 #include <glib.h>
 26 
 27 gchar *
 28 tracker_sparql_escape_uri_vprintf (const gchar *format,
 29                                    va_list      args);
 30 gchar *
 31 tracker_sparql_escape_uri_printf  (const gchar* format,
 32                                    ...);
 33 
 34 static const char *
 35 find_conversion (const char  *format,
 36                  const char **after)
 37 {
 38 	const char *start = format;
 39 	const char *cp;
 40 
 41 	while (*start != '\0' && *start != '%')
 42 		start++;
 43 
 44 	if (*start == '\0') {
 45 		*after = start;
 46 		return NULL;
 47 	}
 48 
 49 	cp = start + 1;
 50 
 51 	if (*cp == '\0') {
 52 		*after = cp;
 53 		return NULL;
 54 	}
 55 
 56 	/* Test for positional argument.  */
 57 	if (*cp >= '0' && *cp <= '9') {
 58 		const char *np;
 59 
 60 		for (np = cp; *np >= '0' && *np <= '9'; np++)
 61 			;
 62 		if (*np == '$')
 63 			cp = np + 1;
 64 	}
 65 
 66 	/* Skip the flags.  */
 67 	for (;;) {
 68 		if (*cp == '\'' ||
 69 		    *cp == '-' ||
 70 		    *cp == '+' ||
 71 		    *cp == ' ' ||
 72 		    *cp == '#' ||
 73 		    *cp == '0')
 74 			cp++;
 75 		else
 76 			break;
 77 	}
 78 
 79 	/* Skip the field width.  */
 80 	if (*cp == '*') {
 81 		cp++;
 82 
 83 		/* Test for positional argument.  */
 84 		if (*cp >= '0' && *cp <= '9') {
 85 			const char *np;
 86 
 87 			for (np = cp; *np >= '0' && *np <= '9'; np++)
 88 				;
 89 			if (*np == '$')
 90 				cp = np + 1;
 91 		}
 92 	} else {
 93 		for (; *cp >= '0' && *cp <= '9'; cp++)
 94 			;
 95 	}
 96 
 97 	/* Skip the precision.  */
 98 	if (*cp == '.') {
 99 		cp++;
100 		if (*cp == '*') {
101 			/* Test for positional argument.  */
102 			if (*cp >= '0' && *cp <= '9') {
103 				const char *np;
104 
105 				for (np = cp; *np >= '0' && *np <= '9'; np++)
106 					;
107 				if (*np == '$')
108 					cp = np + 1;
109 			}
110 		} else {
111 			for (; *cp >= '0' && *cp <= '9'; cp++)
112 				;
113 		}
114 	}
115 
116 	/* Skip argument type/size specifiers.  */
117 	while (*cp == 'h' ||
118 	       *cp == 'L' ||
119 	       *cp == 'l' ||
120 	       *cp == 'j' ||
121 	       *cp == 'z' ||
122 	       *cp == 'Z' ||
123 	       *cp == 't')
124 		cp++;
125 
126 	/* Skip the conversion character.  */
127 	cp++;
128 
129 	*after = cp;
130 	return start;
131 }
132 
133 /**
134  * tracker_sparql_escape_uri_vprintf:
135  * @format: a standard printf() format string, but notice
136  *     <link linkend="string-precision">string precision pitfalls</link> documented in g_strdup_printf()
137  * @args: the list of parameters to insert into the format string
138  *
139  * Similar to the standard C vsprintf() function but safer, since it
140  * calculates the maximum space required and allocates memory to hold
141  * the result.
142  *
143  * The result is escaped using g_uri_escape_string().
144  *
145  * Returns: a newly-allocated string holding the result. The returned string
146  * should be freed with g_free() when no longer needed.
147  *
148  * Since: 0.10
149  */
150 gchar *
151 tracker_sparql_escape_uri_vprintf (const gchar *format,
152                                    va_list      args)
153 {
154 	GString *format1;
155 	GString *format2;
156 	GString *result = NULL;
157 	gchar *output1 = NULL;
158 	gchar *output2 = NULL;
159 	const char *p;
160 	gchar *op1, *op2;
161 	va_list args2;
162 
163 	format1 = g_string_new (NULL);
164 	format2 = g_string_new (NULL);
165 	p = format;
166 	while (TRUE) {
167 		const char *after;
168 		const char *conv = find_conversion (p, &after);
169 		if (!conv)
170 			break;
171 
172 		g_string_append_len (format1, conv, after - conv);
173 		g_string_append_c (format1, 'X');
174 		g_string_append_len (format2, conv, after - conv);
175 		g_string_append_c (format2, 'Y');
176 
177 		p = after;
178 	}
179 
180 	/* Use them to format the arguments
181 	 */
182 	G_VA_COPY (args2, args);
183 
184 	output1 = g_strdup_vprintf (format1->str, args);
185 	va_end (args);
186 	if (!output1) {
187 		va_end (args2);
188 		goto cleanup;
189 	}
190 
191 	output2 = g_strdup_vprintf (format2->str, args2);
192 	va_end (args2);
193 	if (!output2)
194 		goto cleanup;
195 
196 	result = g_string_new (NULL);
197 
198 	op1 = output1;
199 	op2 = output2;
200 	p = format;
201 	while (TRUE) {
202 		const char *after;
203 		const char *output_start;
204 		const char *conv = find_conversion (p, &after);
205 		char *escaped;
206 
207 		if (!conv) {
208 			g_string_append_len (result, p, after - p);
209 			break;
210 		}
211 
212 		g_string_append_len (result, p, conv - p);
213 		output_start = op1;
214 		while (*op1 == *op2) {
215 			op1++;
216 			op2++;
217 		}
218 
219 		*op1 = '\0';
220 		escaped = g_uri_escape_string (output_start, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, FALSE);
221 		g_string_append (result, escaped);
222 		g_free (escaped);
223 
224 		p = after;
225 		op1++;
226 		op2++;
227 	}
228 
229 cleanup:
230 	g_string_free (format1, TRUE);
231 	g_string_free (format2, TRUE);
232 	g_free (output1);
233 	g_free (output2);
234 
235 	if (result)
236 		return g_string_free (result, FALSE);
237 	else
238 		return NULL;
239 }
240 
241 /**
242  * tracker_sparql_escape_uri_printf:
243  * @format: a standard printf() format string, but notice
244  *     <link linkend="string-precision">string precision pitfalls</link> documented in g_strdup_printf()
245  * @...: the parameters to insert into the format string
246  *
247  * Calls tracker_sparql_escape_uri_vprintf() with the @... supplied.
248  *
249  * Returns: a newly-allocated string holding the result.The returned string
250  * should be freed with g_free() when no longer needed.
251  *
252  * Since: 0.10
253  */
254 gchar *
255 tracker_sparql_escape_uri_printf (const gchar *format, ...)
256 {
257 	gchar *result;
258 	va_list args;
259 
260 	va_start (args, format);
261 	result = tracker_sparql_escape_uri_vprintf (format, args);
262 	va_end (args);
263 
264 	return result;
265 }