summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2007-11-14 22:02:41 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2007-11-14 22:02:41 +0000
commit31f76116f1b3188eb15a1b2caaa445d1770efb30 (patch)
tree50d0ddd6190f6cd96f033981ddb0fba301432b22
parent7ddefe2a5d6ef10463cc26262d37f54a490b1afb (diff)
downloadrockbox-31f76116f1b3188eb15a1b2caaa445d1770efb30.tar.gz
rockbox-31f76116f1b3188eb15a1b2caaa445d1770efb30.zip
Make the WPS parser stricter with invalid parameter lists. It will now reject them instead of ignoring them (this includes the second parameter to %m|x|, which is invalid and now causes a failure). Also change the debugging code in order to allow more precise error messages, including the faulty token's index and description. Finally, add a few missing token description and fine-tune the #ifdefs.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15624 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/gui/gwps.h4
-rw-r--r--apps/gui/wps_debug.c714
-rw-r--r--apps/gui/wps_parser.c129
3 files changed, 483 insertions, 364 deletions
diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h
index 31f58ee408..56c8a6da6d 100644
--- a/apps/gui/gwps.h
+++ b/apps/gui/gwps.h
@@ -180,9 +180,11 @@ enum wps_token_type {
180 WPS_TOKEN_CONDITIONAL_END, 180 WPS_TOKEN_CONDITIONAL_END,
181 181
182 /* Database */ 182 /* Database */
183#ifdef HAVE_TAGCACHE
183 WPS_TOKEN_DATABASE_PLAYCOUNT, 184 WPS_TOKEN_DATABASE_PLAYCOUNT,
184 WPS_TOKEN_DATABASE_RATING, 185 WPS_TOKEN_DATABASE_RATING,
185 WPS_TOKEN_DATABASE_AUTOSCORE, 186 WPS_TOKEN_DATABASE_AUTOSCORE,
187#endif
186 188
187 /* File */ 189 /* File */
188 WPS_TOKEN_FILE_BITRATE, 190 WPS_TOKEN_FILE_BITRATE,
@@ -237,7 +239,9 @@ enum wps_token_type {
237 239
238 /* Progressbar */ 240 /* Progressbar */
239 WPS_TOKEN_PROGRESSBAR, 241 WPS_TOKEN_PROGRESSBAR,
242#ifdef HAVE_LCD_CHARCELLS
240 WPS_TOKEN_PLAYER_PROGRESSBAR, 243 WPS_TOKEN_PLAYER_PROGRESSBAR,
244#endif
241 245
242#ifdef HAVE_LCD_BITMAP 246#ifdef HAVE_LCD_BITMAP
243 /* Peakmeter */ 247 /* Peakmeter */
diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_debug.c
index 6b7b988321..9443f23730 100644
--- a/apps/gui/wps_debug.c
+++ b/apps/gui/wps_debug.c
@@ -28,9 +28,10 @@
28#include "debug.h" 28#include "debug.h"
29#endif 29#endif
30 30
31#define PARSE_FAIL_UNCLOSED_COND 1 31#define PARSE_FAIL_UNCLOSED_COND 1
32#define PARSE_FAIL_INVALID_CHAR 2 32#define PARSE_FAIL_INVALID_CHAR 2
33#define PARSE_FAIL_COND_SYNTAX_ERROR 3 33#define PARSE_FAIL_COND_SYNTAX_ERROR 3
34#define PARSE_FAIL_COND_INVALID_PARAM 4
34 35
35#if defined(SIMULATOR) || defined(__PCTOOL__) 36#if defined(SIMULATOR) || defined(__PCTOOL__)
36extern bool debug_wps; 37extern bool debug_wps;
@@ -41,368 +42,431 @@ static char *next_str(bool next) {
41 return next ? "next " : ""; 42 return next ? "next " : "";
42} 43}
43 44
44static void dump_wps_tokens(struct wps_data *data) 45static char *get_token_desc(struct wps_token *token, struct wps_data *data,
46 char *buf, int bufsize)
45{ 47{
46 struct wps_token *token; 48 bool next = token->next;
47 int i, j;
48 int indent = 0;
49 char buf[64];
50 bool next;
51 int num_string_tokens = 0;
52
53 /* Dump parsed WPS */
54 for (i = 0, token = data->tokens; i < data->num_tokens; i++, token++) {
55 next = token->next;
56
57 switch(token->type) {
58 case WPS_TOKEN_UNKNOWN:
59 snprintf(buf, sizeof(buf), "Unknown token");
60 break;
61 case WPS_TOKEN_CHARACTER:
62 snprintf(buf, sizeof(buf), "Character '%c'",
63 token->value.c);
64 break;
65 49
66 case WPS_TOKEN_STRING: 50 switch(token->type)
67 snprintf(buf, sizeof(buf), "String '%s'", 51 {
68 data->strings[token->value.i]); 52 case WPS_NO_TOKEN:
69 num_string_tokens++; 53 snprintf(buf, bufsize, "No token");
70 break; 54 break;
71 55
72#ifdef HAVE_LCD_BITMAP 56 case WPS_TOKEN_UNKNOWN:
73 case WPS_TOKEN_ALIGN_LEFT: 57 snprintf(buf, bufsize, "Unknown token");
74 snprintf(buf, sizeof(buf), "align left"); 58 break;
75 break;
76 59
77 case WPS_TOKEN_ALIGN_CENTER: 60 case WPS_TOKEN_CHARACTER:
78 snprintf(buf, sizeof(buf), "align center"); 61 snprintf(buf, bufsize, "Character '%c'",
79 break; 62 token->value.c);
63 break;
80 64
81 case WPS_TOKEN_ALIGN_RIGHT: 65 case WPS_TOKEN_STRING:
82 snprintf(buf, sizeof(buf), "align right"); 66 snprintf(buf, bufsize, "String '%s'",
83 break; 67 data->strings[token->value.i]);
68 break;
84 69
85 case WPS_TOKEN_LEFTMARGIN: 70#ifdef HAVE_LCD_BITMAP
86 snprintf(buf, sizeof(buf), "left margin, value: %d", 71 case WPS_TOKEN_ALIGN_LEFT:
87 token->value.i); 72 snprintf(buf, bufsize, "align left");
88 break; 73 break;
74
75 case WPS_TOKEN_ALIGN_CENTER:
76 snprintf(buf, bufsize, "align center");
77 break;
78
79 case WPS_TOKEN_ALIGN_RIGHT:
80 snprintf(buf, bufsize, "align right");
81 break;
82
83 case WPS_TOKEN_LEFTMARGIN:
84 snprintf(buf, bufsize, "left margin, value: %d",
85 token->value.i);
86 break;
89#endif 87#endif
90 88
91 case WPS_TOKEN_SUBLINE_TIMEOUT: 89 case WPS_TOKEN_SUBLINE_TIMEOUT:
92 snprintf(buf, sizeof(buf), "subline timeout value: %d", 90 snprintf(buf, bufsize, "subline timeout value: %d",
93 token->value.i); 91 token->value.i);
94 break; 92 break;
95 93
96 case WPS_TOKEN_CONDITIONAL: 94 case WPS_TOKEN_CONDITIONAL:
97 snprintf(buf, sizeof(buf), "conditional, %d options", 95 snprintf(buf, bufsize, "conditional, %d options",
98 token->value.i); 96 token->value.i);
99 break; 97 break;
100 98
101 case WPS_TOKEN_CONDITIONAL_START: 99 case WPS_TOKEN_CONDITIONAL_START:
102 snprintf(buf, sizeof(buf), "conditional start, next cond: %d", 100 snprintf(buf, bufsize, "conditional start, next cond: %d",
103 token->value.i); 101 token->value.i);
104 indent++; 102 break;
105 break;
106 103
107 case WPS_TOKEN_CONDITIONAL_OPTION: 104 case WPS_TOKEN_CONDITIONAL_OPTION:
108 snprintf(buf, sizeof(buf), "conditional option, next cond: %d", 105 snprintf(buf, bufsize, "conditional option, next cond: %d",
109 token->value.i); 106 token->value.i);
110 break; 107 break;
111 108
112 case WPS_TOKEN_CONDITIONAL_END: 109 case WPS_TOKEN_CONDITIONAL_END:
113 snprintf(buf, sizeof(buf), "conditional end"); 110 snprintf(buf, bufsize, "conditional end");
114 indent--; 111 break;
115 break;
116 112
117#ifdef HAVE_LCD_BITMAP 113#ifdef HAVE_LCD_BITMAP
118 case WPS_TOKEN_IMAGE_PRELOAD: 114 case WPS_TOKEN_IMAGE_PRELOAD:
119 snprintf(buf, sizeof(buf), "preload image"); 115 snprintf(buf, bufsize, "preload image");
120 break; 116 break;
121 117
122 case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: 118 case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY:
123 snprintf(buf, sizeof(buf), "display preloaded image %d", 119 snprintf(buf, bufsize, "display preloaded image %d",
124 token->value.i); 120 token->value.i);
125 break; 121 break;
126 122
127 case WPS_TOKEN_IMAGE_DISPLAY: 123 case WPS_TOKEN_IMAGE_DISPLAY:
128 snprintf(buf, sizeof(buf), "display image"); 124 snprintf(buf, bufsize, "display image");
129 break; 125 break;
130#endif 126#endif
131 127
132#ifdef HAS_BUTTON_HOLD 128#ifdef HAS_BUTTON_HOLD
133 case WPS_TOKEN_MAIN_HOLD: 129 case WPS_TOKEN_MAIN_HOLD:
134 snprintf(buf, sizeof(buf), "mode hold"); 130 snprintf(buf, bufsize, "mode hold");
135 break; 131 break;
136#endif 132#endif
137 133
138#ifdef HAS_REMOTE_BUTTON_HOLD 134#ifdef HAS_REMOTE_BUTTON_HOLD
139 case WPS_TOKEN_REMOTE_HOLD: 135 case WPS_TOKEN_REMOTE_HOLD:
140 snprintf(buf, sizeof(buf), "mode remote hold"); 136 snprintf(buf, bufsize, "mode remote hold");
141 break; 137 break;
142#endif 138#endif
143 139
144 case WPS_TOKEN_REPEAT_MODE: 140 case WPS_TOKEN_REPEAT_MODE:
145 snprintf(buf, sizeof(buf), "mode repeat"); 141 snprintf(buf, bufsize, "mode repeat");
146 break; 142 break;
147 143
148 case WPS_TOKEN_PLAYBACK_STATUS: 144 case WPS_TOKEN_PLAYBACK_STATUS:
149 snprintf(buf, sizeof(buf), "mode playback"); 145 snprintf(buf, bufsize, "mode playback");
150 break; 146 break;
151 147
152 case WPS_TOKEN_RTC_DAY_OF_MONTH: 148 case WPS_TOKEN_RTC_DAY_OF_MONTH:
153 snprintf(buf, sizeof(buf), "rtc: day of month (01..31)"); 149 snprintf(buf, bufsize, "rtc: day of month (01..31)");
154 break; 150 break;
155 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED: 151 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
156 snprintf(buf, sizeof(buf), 152 snprintf(buf, bufsize,
157 "rtc: day of month, blank padded ( 1..31)"); 153 "rtc: day of month, blank padded ( 1..31)");
158 break; 154 break;
159 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED: 155 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
160 snprintf(buf, sizeof(buf), "rtc: hour (00..23)"); 156 snprintf(buf, bufsize, "rtc: hour (00..23)");
161 break; 157 break;
162 case WPS_TOKEN_RTC_HOUR_24: 158 case WPS_TOKEN_RTC_HOUR_24:
163 snprintf(buf, sizeof(buf), "rtc: hour ( 0..23)"); 159 snprintf(buf, bufsize, "rtc: hour ( 0..23)");
164 break; 160 break;
165 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED: 161 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
166 snprintf(buf, sizeof(buf), "rtc: hour (01..12)"); 162 snprintf(buf, bufsize, "rtc: hour (01..12)");
167 break; 163 break;
168 case WPS_TOKEN_RTC_HOUR_12: 164 case WPS_TOKEN_RTC_HOUR_12:
169 snprintf(buf, sizeof(buf), "rtc: hour ( 1..12)"); 165 snprintf(buf, bufsize, "rtc: hour ( 1..12)");
170 break; 166 break;
171 case WPS_TOKEN_RTC_MONTH: 167 case WPS_TOKEN_RTC_MONTH:
172 snprintf(buf, sizeof(buf), "rtc: month (01..12)"); 168 snprintf(buf, bufsize, "rtc: month (01..12)");
173 break; 169 break;
174 case WPS_TOKEN_RTC_MINUTE: 170 case WPS_TOKEN_RTC_MINUTE:
175 snprintf(buf, sizeof(buf), "rtc: minute (00..59)"); 171 snprintf(buf, bufsize, "rtc: minute (00..59)");
176 break; 172 break;
177 case WPS_TOKEN_RTC_SECOND: 173 case WPS_TOKEN_RTC_SECOND:
178 snprintf(buf, sizeof(buf), "rtc: second (00..59)"); 174 snprintf(buf, bufsize, "rtc: second (00..59)");
179 break; 175 break;
180 case WPS_TOKEN_RTC_YEAR_2_DIGITS: 176 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
181 snprintf(buf, sizeof(buf), 177 snprintf(buf, bufsize,
182 "rtc: last two digits of year (00..99)"); 178 "rtc: last two digits of year (00..99)");
183 break; 179 break;
184 case WPS_TOKEN_RTC_YEAR_4_DIGITS: 180 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
185 snprintf(buf, sizeof(buf), "rtc: year (1970...)"); 181 snprintf(buf, bufsize, "rtc: year (1970...)");
186 break; 182 break;
187 case WPS_TOKEN_RTC_AM_PM_UPPER: 183 case WPS_TOKEN_RTC_AM_PM_UPPER:
188 snprintf(buf, sizeof(buf), 184 snprintf(buf, bufsize,
189 "rtc: upper case AM or PM indicator"); 185 "rtc: upper case AM or PM indicator");
190 break; 186 break;
191 case WPS_TOKEN_RTC_AM_PM_LOWER: 187 case WPS_TOKEN_RTC_AM_PM_LOWER:
192 snprintf(buf, sizeof(buf), 188 snprintf(buf, bufsize,
193 "rtc: lower case am or pm indicator"); 189 "rtc: lower case am or pm indicator");
194 break; 190 break;
195 case WPS_TOKEN_RTC_WEEKDAY_NAME: 191 case WPS_TOKEN_RTC_WEEKDAY_NAME:
196 snprintf(buf, sizeof(buf), 192 snprintf(buf, bufsize,
197 "rtc: abbreviated weekday name (Sun..Sat)"); 193 "rtc: abbreviated weekday name (Sun..Sat)");
198 break; 194 break;
199 case WPS_TOKEN_RTC_MONTH_NAME: 195 case WPS_TOKEN_RTC_MONTH_NAME:
200 snprintf(buf, sizeof(buf), 196 snprintf(buf, bufsize,
201 "rtc: abbreviated month name (Jan..Dec)"); 197 "rtc: abbreviated month name (Jan..Dec)");
202 break; 198 break;
203 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON: 199 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
204 snprintf(buf, sizeof(buf), 200 snprintf(buf, bufsize,
205 "rtc: day of week (1..7); 1 is Monday"); 201 "rtc: day of week (1..7); 1 is Monday");
206 break; 202 break;
207 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN: 203 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
208 snprintf(buf, sizeof(buf), 204 snprintf(buf, bufsize,
209 "rtc: day of week (0..6); 0 is Sunday"); 205 "rtc: day of week (0..6); 0 is Sunday");
210 break; 206 break;
211 207
212#if (CONFIG_CODEC == SWCODEC) 208#if (CONFIG_CODEC == SWCODEC)
213 case WPS_TOKEN_CROSSFADE: 209 case WPS_TOKEN_CROSSFADE:
214 snprintf(buf, sizeof(buf), "crossfade"); 210 snprintf(buf, bufsize, "crossfade");
215 break; 211 break;
216 212
217 case WPS_TOKEN_REPLAYGAIN: 213 case WPS_TOKEN_REPLAYGAIN:
218 snprintf(buf, sizeof(buf), "replaygain"); 214 snprintf(buf, bufsize, "replaygain");
219 break; 215 break;
220#endif 216#endif
221 217
222#ifdef HAVE_ALBUMART 218#ifdef HAVE_ALBUMART
223 case WPS_TOKEN_ALBUMART_DISPLAY: 219 case WPS_TOKEN_ALBUMART_DISPLAY:
224 snprintf(buf, sizeof(buf), "album art display at x=%d, y=%d, " 220 snprintf(buf, bufsize, "album art display");
225 "maxwidth=%d, maxheight=%d", data->albumart_x, 221 break;
226 data->albumart_y, data->albumart_max_width, 222
227 data->albumart_max_height); 223 case WPS_TOKEN_ALBUMART_FOUND:
228 break; 224 snprintf(buf, bufsize, "%strack album art conditional",
225 next_str(next));
226 break;
229#endif 227#endif
230 228
231#ifdef HAVE_LCD_BITMAP 229#ifdef HAVE_LCD_BITMAP
232 case WPS_TOKEN_IMAGE_BACKDROP: 230 case WPS_TOKEN_IMAGE_BACKDROP:
233 snprintf(buf, sizeof(buf), "backdrop image"); 231 snprintf(buf, bufsize, "backdrop image");
234 break; 232 break;
235 233
236 case WPS_TOKEN_IMAGE_PROGRESS_BAR: 234 case WPS_TOKEN_IMAGE_PROGRESS_BAR:
237 snprintf(buf, sizeof(buf), "progressbar bitmap"); 235 snprintf(buf, bufsize, "progressbar bitmap");
238 break; 236 break;
239 237
240 case WPS_TOKEN_PEAKMETER: 238 case WPS_TOKEN_PEAKMETER:
241 snprintf(buf, sizeof(buf), "peakmeter"); 239 snprintf(buf, bufsize, "peakmeter");
242 break; 240 break;
243#endif 241#endif
244 242
245 case WPS_TOKEN_PROGRESSBAR: 243 case WPS_TOKEN_PROGRESSBAR:
246 snprintf(buf, sizeof(buf), "progressbar"); 244 snprintf(buf, bufsize, "progressbar");
247 break; 245 break;
248 246
249#ifdef HAVE_LCD_CHARCELLS 247#ifdef HAVE_LCD_CHARCELLS
250 case WPS_TOKEN_PLAYER_PROGRESSBAR: 248 case WPS_TOKEN_PLAYER_PROGRESSBAR:
251 snprintf(buf, sizeof(buf), "full line progressbar"); 249 snprintf(buf, bufsize, "full line progressbar");
252 break; 250 break;
253#endif 251#endif
254 252
255 case WPS_TOKEN_TRACK_TIME_ELAPSED: 253 case WPS_TOKEN_TRACK_TIME_ELAPSED:
256 snprintf(buf, sizeof(buf), "time elapsed in track"); 254 snprintf(buf, bufsize, "time elapsed in track");
257 break; 255 break;
258 256
259 case WPS_TOKEN_TRACK_ELAPSED_PERCENT: 257 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
260 snprintf(buf, sizeof(buf), "played percentage of track"); 258 snprintf(buf, bufsize, "played percentage of track");
261 break; 259 break;
262 260
263 case WPS_TOKEN_PLAYLIST_ENTRIES: 261 case WPS_TOKEN_PLAYLIST_ENTRIES:
264 snprintf(buf, sizeof(buf), "number of entries in playlist"); 262 snprintf(buf, bufsize, "number of entries in playlist");
265 break; 263 break;
266 264
267 case WPS_TOKEN_PLAYLIST_NAME: 265 case WPS_TOKEN_PLAYLIST_NAME:
268 snprintf(buf, sizeof(buf), "playlist name"); 266 snprintf(buf, bufsize, "playlist name");
269 break; 267 break;
270 268
271 case WPS_TOKEN_PLAYLIST_POSITION: 269 case WPS_TOKEN_PLAYLIST_POSITION:
272 snprintf(buf, sizeof(buf), "position in playlist"); 270 snprintf(buf, bufsize, "position in playlist");
273 break; 271 break;
274 272
275 case WPS_TOKEN_TRACK_TIME_REMAINING: 273 case WPS_TOKEN_TRACK_TIME_REMAINING:
276 snprintf(buf, sizeof(buf), "time remaining in track"); 274 snprintf(buf, bufsize, "time remaining in track");
277 break; 275 break;
278 276
279 case WPS_TOKEN_PLAYLIST_SHUFFLE: 277 case WPS_TOKEN_PLAYLIST_SHUFFLE:
280 snprintf(buf, sizeof(buf), "playlist shuffle mode"); 278 snprintf(buf, bufsize, "playlist shuffle mode");
281 break; 279 break;
282 280
283 case WPS_TOKEN_TRACK_LENGTH: 281 case WPS_TOKEN_TRACK_LENGTH:
284 snprintf(buf, sizeof(buf), "track length"); 282 snprintf(buf, bufsize, "track length");
285 break; 283 break;
286 284
287 case WPS_TOKEN_VOLUME: 285 case WPS_TOKEN_VOLUME:
288 snprintf(buf, sizeof(buf), "volume"); 286 snprintf(buf, bufsize, "volume");
289 break; 287 break;
290 288
291 case WPS_TOKEN_METADATA_ARTIST: 289 case WPS_TOKEN_METADATA_ARTIST:
292 snprintf(buf, sizeof(buf), "%strack artist", 290 snprintf(buf, bufsize, "%strack artist",
293 next_str(next)); 291 next_str(next));
294 break; 292 break;
295 293
296 case WPS_TOKEN_METADATA_COMPOSER: 294 case WPS_TOKEN_METADATA_COMPOSER:
297 snprintf(buf, sizeof(buf), "%strack composer", 295 snprintf(buf, bufsize, "%strack composer",
298 next_str(next)); 296 next_str(next));
299 break; 297 break;
300 298
301 case WPS_TOKEN_METADATA_ALBUM: 299 case WPS_TOKEN_METADATA_ALBUM:
302 snprintf(buf, sizeof(buf), "%strack album", 300 snprintf(buf, bufsize, "%strack album",
303 next_str(next)); 301 next_str(next));
304 break; 302 break;
305 303
306 case WPS_TOKEN_METADATA_GROUPING: 304 case WPS_TOKEN_METADATA_GROUPING:
307 snprintf(buf, sizeof(buf), "%strack grouping", 305 snprintf(buf, bufsize, "%strack grouping",
308 next_str(next)); 306 next_str(next));
309 break; 307 break;
310 308
311 case WPS_TOKEN_METADATA_GENRE: 309 case WPS_TOKEN_METADATA_GENRE:
312 snprintf(buf, sizeof(buf), "%strack genre", 310 snprintf(buf, bufsize, "%strack genre",
313 next_str(next)); 311 next_str(next));
314 break; 312 break;
315 313
316 case WPS_TOKEN_METADATA_DISC_NUMBER: 314 case WPS_TOKEN_METADATA_DISC_NUMBER:
317 snprintf(buf, sizeof(buf), "%strack disc", next_str(next)); 315 snprintf(buf, bufsize, "%strack disc", next_str(next));
318 break; 316 break;
319 317
320 case WPS_TOKEN_METADATA_TRACK_NUMBER: 318 case WPS_TOKEN_METADATA_TRACK_NUMBER:
321 snprintf(buf, sizeof(buf), "%strack number", 319 snprintf(buf, bufsize, "%strack number",
322 next_str(next)); 320 next_str(next));
323 break; 321 break;
324 322
325 case WPS_TOKEN_METADATA_TRACK_TITLE: 323 case WPS_TOKEN_METADATA_TRACK_TITLE:
326 snprintf(buf, sizeof(buf), "%strack title", 324 snprintf(buf, bufsize, "%strack title",
327 next_str(next)); 325 next_str(next));
328 break; 326 break;
329 327
330 case WPS_TOKEN_METADATA_VERSION: 328 case WPS_TOKEN_METADATA_VERSION:
331 snprintf(buf, sizeof(buf), "%strack ID3 version", 329 snprintf(buf, bufsize, "%strack ID3 version",
332 next_str(next)); 330 next_str(next));
333 break; 331 break;
334 332
335 case WPS_TOKEN_METADATA_YEAR: 333 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
336 snprintf(buf, sizeof(buf), "%strack year", next_str(next)); 334 snprintf(buf, bufsize, "%strack album artist",
337 break; 335 next_str(next));
338 336 break;
339 case WPS_TOKEN_BATTERY_PERCENT: 337
340 snprintf(buf, sizeof(buf), "battery percentage"); 338 case WPS_TOKEN_METADATA_COMMENT:
341 break; 339 snprintf(buf, bufsize, "%strack comment",
342 340 next_str(next));
343 case WPS_TOKEN_BATTERY_VOLTS: 341 break;
344 snprintf(buf, sizeof(buf), "battery voltage"); 342
345 break; 343 case WPS_TOKEN_METADATA_YEAR:
346 344 snprintf(buf, bufsize, "%strack year", next_str(next));
347 case WPS_TOKEN_BATTERY_TIME: 345 break;
348 snprintf(buf, sizeof(buf), "battery time left"); 346
349 break; 347#ifdef HAVE_TAGCACHE
350 348 case WPS_TOKEN_DATABASE_PLAYCOUNT:
351 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED: 349 snprintf(buf, bufsize, "track playcount (database)");
352 snprintf(buf, sizeof(buf), "battery charger connected"); 350 break;
353 break; 351
354 352 case WPS_TOKEN_DATABASE_RATING:
355 case WPS_TOKEN_BATTERY_CHARGING: 353 snprintf(buf, bufsize, "track rating (database)");
356 snprintf(buf, sizeof(buf), "battery charging"); 354 break;
357 break; 355
358 356 case WPS_TOKEN_DATABASE_AUTOSCORE:
359 case WPS_TOKEN_FILE_BITRATE: 357 snprintf(buf, bufsize, "track autoscore (database)");
360 snprintf(buf, sizeof(buf), "%sfile bitrate", next_str(next)); 358 break;
361 break; 359#endif
362
363 case WPS_TOKEN_FILE_CODEC:
364 snprintf(buf, sizeof(buf), "%sfile codec", next_str(next));
365 break;
366
367 case WPS_TOKEN_FILE_FREQUENCY:
368 snprintf(buf, sizeof(buf), "%sfile audio frequency in Hz",
369 next_str(next));
370 break;
371 360
372 case WPS_TOKEN_FILE_FREQUENCY_KHZ: 361 case WPS_TOKEN_BATTERY_PERCENT:
373 snprintf(buf, sizeof(buf), "%sfile audio frequency in KHz", 362 snprintf(buf, bufsize, "battery percentage");
374 next_str(next)); 363 break;
375 break; 364
365 case WPS_TOKEN_BATTERY_VOLTS:
366 snprintf(buf, bufsize, "battery voltage");
367 break;
368
369 case WPS_TOKEN_BATTERY_TIME:
370 snprintf(buf, bufsize, "battery time left");
371 break;
372
373 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
374 snprintf(buf, bufsize, "battery charger connected");
375 break;
376
377 case WPS_TOKEN_BATTERY_CHARGING:
378 snprintf(buf, bufsize, "battery charging");
379 break;
380
381 case WPS_TOKEN_BATTERY_SLEEPTIME:
382 snprintf(buf, bufsize, "sleep timer");
383 break;
384
385 case WPS_TOKEN_FILE_BITRATE:
386 snprintf(buf, bufsize, "%sfile bitrate", next_str(next));
387 break;
388
389 case WPS_TOKEN_FILE_CODEC:
390 snprintf(buf, bufsize, "%sfile codec", next_str(next));
391 break;
392
393 case WPS_TOKEN_FILE_FREQUENCY:
394 snprintf(buf, bufsize, "%sfile audio frequency in Hz",
395 next_str(next));
396 break;
397
398 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
399 snprintf(buf, bufsize, "%sfile audio frequency in KHz",
400 next_str(next));
401 break;
402
403 case WPS_TOKEN_FILE_NAME:
404 snprintf(buf, bufsize, "%sfile name", next_str(next));
405 break;
406
407 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
408 snprintf(buf, bufsize, "%sfile name with extension",
409 next_str(next));
410 break;
411
412 case WPS_TOKEN_FILE_PATH:
413 snprintf(buf, bufsize, "%sfile path", next_str(next));
414 break;
415
416 case WPS_TOKEN_FILE_SIZE:
417 snprintf(buf, bufsize, "%sfile size", next_str(next));
418 break;
419
420 case WPS_TOKEN_FILE_VBR:
421 snprintf(buf, bufsize, "%sfile is vbr", next_str(next));
422 break;
423
424 case WPS_TOKEN_FILE_DIRECTORY:
425 snprintf(buf, bufsize, "%sfile directory, level: %d",
426 next_str(next), token->value.i);
427 break;
428
429 case WPS_TOKEN_SOUND_PITCH:
430 snprintf(buf, bufsize, "pitch value");
431 break;
432
433 default:
434 snprintf(buf, bufsize, "FIXME (code: %d)",
435 token->type);
436 break;
437 }
376 438
377 case WPS_TOKEN_FILE_NAME: 439 return buf;
378 snprintf(buf, sizeof(buf), "%sfile name", next_str(next)); 440}
379 break;
380 441
381 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION: 442static void dump_wps_tokens(struct wps_data *data)
382 snprintf(buf, sizeof(buf), "%sfile name with extension", 443{
383 next_str(next)); 444 struct wps_token *token;
384 break; 445 int i, j;
446 int indent = 0;
447 char buf[64];
448 int num_string_tokens = 0;
385 449
386 case WPS_TOKEN_FILE_PATH: 450 /* Dump parsed WPS */
387 snprintf(buf, sizeof(buf), "%sfile path", next_str(next)); 451 for (i = 0, token = data->tokens; i < data->num_tokens; i++, token++)
388 break; 452 {
453 get_token_desc(token, data, buf, sizeof(buf));
389 454
390 case WPS_TOKEN_FILE_SIZE: 455 switch(token->type)
391 snprintf(buf, sizeof(buf), "%sfile size", next_str(next)); 456 {
457 case WPS_TOKEN_STRING:
458 num_string_tokens++;
392 break; 459 break;
393 460
394 case WPS_TOKEN_FILE_VBR: 461 case WPS_TOKEN_CONDITIONAL_START:
395 snprintf(buf, sizeof(buf), "%sfile is vbr", next_str(next)); 462 indent++;
396 break; 463 break;
397 464
398 case WPS_TOKEN_FILE_DIRECTORY: 465 case WPS_TOKEN_CONDITIONAL_END:
399 snprintf(buf, sizeof(buf), "%sfile directory, level: %d", 466 indent--;
400 next_str(next), token->value.i);
401 break; 467 break;
402 468
403 default: 469 default:
404 snprintf(buf, sizeof(buf), "FIXME (code: %d)",
405 token->type);
406 break; 470 break;
407 } 471 }
408 472
@@ -528,6 +592,8 @@ void print_debug_info(struct wps_data *data, int fail, int line)
528 592
529 if (fail) 593 if (fail)
530 { 594 {
595 char buf[64];
596
531 DEBUGF("Failed parsing on line %d : ", line); 597 DEBUGF("Failed parsing on line %d : ", line);
532 switch (fail) 598 switch (fail)
533 { 599 {
@@ -536,11 +602,27 @@ void print_debug_info(struct wps_data *data, int fail, int line)
536 break; 602 break;
537 603
538 case PARSE_FAIL_INVALID_CHAR: 604 case PARSE_FAIL_INVALID_CHAR:
539 DEBUGF("Invalid conditional char (not in an open conditional)"); 605 DEBUGF("unexpected conditional char after token %d: \"%s\"",
606 data->num_tokens-1,
607 get_token_desc(&data->tokens[data->num_tokens-1], data,
608 buf, sizeof(buf))
609 );
540 break; 610 break;
541 611
542 case PARSE_FAIL_COND_SYNTAX_ERROR: 612 case PARSE_FAIL_COND_SYNTAX_ERROR:
543 DEBUGF("Conditional syntax error"); 613 DEBUGF("Conditional syntax error after token %d: \"%s\"",
614 data->num_tokens-1,
615 get_token_desc(&data->tokens[data->num_tokens-1], data,
616 buf, sizeof(buf))
617 );
618 break;
619
620 case PARSE_FAIL_COND_INVALID_PARAM:
621 DEBUGF("Invalid parameter list for token %d: \"%s\"",
622 data->num_tokens,
623 get_token_desc(&data->tokens[data->num_tokens], data,
624 buf, sizeof(buf))
625 );
544 break; 626 break;
545 } 627 }
546 DEBUGF("\n"); 628 DEBUGF("\n");
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c
index 907a8a3278..07805f20c7 100644
--- a/apps/gui/wps_parser.c
+++ b/apps/gui/wps_parser.c
@@ -42,9 +42,12 @@
42#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps" 42#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
43#define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps" 43#define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps"
44 44
45#define PARSE_FAIL_UNCLOSED_COND 1 45#define WPS_ERROR_INVALID_PARAM -1
46#define PARSE_FAIL_INVALID_CHAR 2 46
47#define PARSE_FAIL_COND_SYNTAX_ERROR 3 47#define PARSE_FAIL_UNCLOSED_COND 1
48#define PARSE_FAIL_INVALID_CHAR 2
49#define PARSE_FAIL_COND_SYNTAX_ERROR 3
50#define PARSE_FAIL_COND_INVALID_PARAM 4
48 51
49/* level of current conditional. 52/* level of current conditional.
50 -1 means we're not in a conditional. */ 53 -1 means we're not in a conditional. */
@@ -115,7 +118,7 @@ static int parse_dir_level(const char *wps_bufptr,
115 struct wps_token *token, struct wps_data *wps_data); 118 struct wps_token *token, struct wps_data *wps_data);
116 119
117#ifdef HAVE_LCD_BITMAP 120#ifdef HAVE_LCD_BITMAP
118static int parse_scrollmargin(const char *wps_bufptr, 121static int parse_leftmargin(const char *wps_bufptr,
119 struct wps_token *token, struct wps_data *wps_data); 122 struct wps_token *token, struct wps_data *wps_data);
120static int parse_image_special(const char *wps_bufptr, 123static int parse_image_special(const char *wps_bufptr,
121 struct wps_token *token, struct wps_data *wps_data); 124 struct wps_token *token, struct wps_data *wps_data);
@@ -253,7 +256,7 @@ static const struct wps_tag all_tags[] = {
253 { WPS_TOKEN_PLAYBACK_STATUS, "mp", WPS_REFRESH_DYNAMIC, NULL }, 256 { WPS_TOKEN_PLAYBACK_STATUS, "mp", WPS_REFRESH_DYNAMIC, NULL },
254 257
255#ifdef HAVE_LCD_BITMAP 258#ifdef HAVE_LCD_BITMAP
256 { WPS_TOKEN_LEFTMARGIN, "m", 0, parse_scrollmargin }, 259 { WPS_TOKEN_LEFTMARGIN, "m", 0, parse_leftmargin },
257#endif 260#endif
258 261
259#ifdef HAVE_LCD_BITMAP 262#ifdef HAVE_LCD_BITMAP
@@ -277,9 +280,12 @@ static const struct wps_tag all_tags[] = {
277 { WPS_TOKEN_PLAYLIST_NAME, "pn", WPS_REFRESH_STATIC, NULL }, 280 { WPS_TOKEN_PLAYLIST_NAME, "pn", WPS_REFRESH_STATIC, NULL },
278 { WPS_TOKEN_PLAYLIST_SHUFFLE, "ps", WPS_REFRESH_DYNAMIC, NULL }, 281 { WPS_TOKEN_PLAYLIST_SHUFFLE, "ps", WPS_REFRESH_DYNAMIC, NULL },
279 282
283#ifdef HAVE_TAGCACHE
280 { WPS_TOKEN_DATABASE_PLAYCOUNT, "rp", WPS_REFRESH_DYNAMIC, NULL }, 284 { WPS_TOKEN_DATABASE_PLAYCOUNT, "rp", WPS_REFRESH_DYNAMIC, NULL },
281 { WPS_TOKEN_DATABASE_RATING, "rr", WPS_REFRESH_DYNAMIC, NULL }, 285 { WPS_TOKEN_DATABASE_RATING, "rr", WPS_REFRESH_DYNAMIC, NULL },
282 { WPS_TOKEN_DATABASE_AUTOSCORE, "ra", WPS_REFRESH_DYNAMIC, NULL }, 286 { WPS_TOKEN_DATABASE_AUTOSCORE, "ra", WPS_REFRESH_DYNAMIC, NULL },
287#endif
288
283#if CONFIG_CODEC == SWCODEC 289#if CONFIG_CODEC == SWCODEC
284 { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL }, 290 { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL },
285 { WPS_TOKEN_CROSSFADE, "xf", WPS_REFRESH_DYNAMIC, NULL }, 291 { WPS_TOKEN_CROSSFADE, "xf", WPS_REFRESH_DYNAMIC, NULL },
@@ -425,8 +431,7 @@ static int parse_image_display(const char *wps_bufptr,
425 if (n == -1) 431 if (n == -1)
426 { 432 {
427 /* invalid picture display tag */ 433 /* invalid picture display tag */
428 token->type = WPS_TOKEN_UNKNOWN; 434 return WPS_ERROR_INVALID_PARAM;
429 return 0;
430 } 435 }
431 436
432 token->value.i = n; 437 token->value.i = n;
@@ -444,15 +449,17 @@ static int parse_image_load(const char *wps_bufptr,
444{ 449{
445 int n; 450 int n;
446 const char *ptr = wps_bufptr; 451 const char *ptr = wps_bufptr;
447 char *pos = NULL; 452 const char *pos = NULL;
453 const char *newline;
448 454
449 /* format: %x|n|filename.bmp|x|y| 455 /* format: %x|n|filename.bmp|x|y|
450 or %xl|n|filename.bmp|x|y| */ 456 or %xl|n|filename.bmp|x|y| */
451 457
452 ptr = strchr(ptr, '|') + 1; 458 ptr = strchr(ptr, '|') + 1;
453 pos = strchr(ptr, '|'); 459 pos = strchr(ptr, '|');
460 newline = strchr(ptr, '\n');
454 461
455 if (!pos) 462 if (!pos || pos > newline)
456 return 0; 463 return 0;
457 464
458 /* get the image ID */ 465 /* get the image ID */
@@ -461,8 +468,8 @@ static int parse_image_load(const char *wps_bufptr,
461 /* check the image number and load state */ 468 /* check the image number and load state */
462 if(n < 0 || n >= MAX_IMAGES || wps_data->img[n].loaded) 469 if(n < 0 || n >= MAX_IMAGES || wps_data->img[n].loaded)
463 { 470 {
464 /* Skip the rest of the line */ 471 /* Invalid image ID */
465 return 0; 472 return WPS_ERROR_INVALID_PARAM;
466 } 473 }
467 474
468 ptr = pos + 1; 475 ptr = pos + 1;
@@ -475,23 +482,23 @@ static int parse_image_load(const char *wps_bufptr,
475 482
476 /* get x-position */ 483 /* get x-position */
477 pos = strchr(ptr, '|'); 484 pos = strchr(ptr, '|');
478 if (pos) 485 if (pos && pos < newline)
479 wps_data->img[n].x = atoi(ptr); 486 wps_data->img[n].x = atoi(ptr);
480 else 487 else
481 { 488 {
482 /* weird syntax, bail out */ 489 /* weird syntax, bail out */
483 return 0; 490 return WPS_ERROR_INVALID_PARAM;
484 } 491 }
485 492
486 /* get y-position */ 493 /* get y-position */
487 ptr = pos + 1; 494 ptr = pos + 1;
488 pos = strchr(ptr, '|'); 495 pos = strchr(ptr, '|');
489 if (pos) 496 if (pos && pos < newline)
490 wps_data->img[n].y = atoi(ptr); 497 wps_data->img[n].y = atoi(ptr);
491 else 498 else
492 { 499 {
493 /* weird syntax, bail out */ 500 /* weird syntax, bail out */
494 return 0; 501 return WPS_ERROR_INVALID_PARAM;
495 } 502 }
496 503
497 if (token->type == WPS_TOKEN_IMAGE_DISPLAY) 504 if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
@@ -505,6 +512,16 @@ static int parse_image_special(const char *wps_bufptr,
505 struct wps_token *token, 512 struct wps_token *token,
506 struct wps_data *wps_data) 513 struct wps_data *wps_data)
507{ 514{
515 (void)wps_data; /* kill warning */
516 const char *pos = NULL;
517 const char *newline;
518
519 pos = strchr(wps_bufptr + 1, '|');
520 newline = strchr(wps_bufptr, '\n');
521
522 if (pos > newline)
523 return WPS_ERROR_INVALID_PARAM;
524
508 if (token->type == WPS_TOKEN_IMAGE_PROGRESS_BAR) 525 if (token->type == WPS_TOKEN_IMAGE_PROGRESS_BAR)
509 { 526 {
510 /* format: %P|filename.bmp| */ 527 /* format: %P|filename.bmp| */
@@ -518,8 +535,6 @@ static int parse_image_special(const char *wps_bufptr,
518 } 535 }
519#endif 536#endif
520 537
521 (void)wps_data; /* to avoid a warning */
522
523 /* Skip the rest of the line */ 538 /* Skip the rest of the line */
524 return skip_end_of_line(wps_bufptr); 539 return skip_end_of_line(wps_bufptr);
525} 540}
@@ -632,7 +647,7 @@ static int parse_albumart_load(const char *wps_bufptr,
632 struct wps_token *token, 647 struct wps_token *token,
633 struct wps_data *wps_data) 648 struct wps_data *wps_data)
634{ 649{
635 const char* _pos; 650 const char *_pos, *newline;
636 bool parsing; 651 bool parsing;
637 const short xalign_mask = WPS_ALBUMART_ALIGN_LEFT | 652 const short xalign_mask = WPS_ALBUMART_ALIGN_LEFT |
638 WPS_ALBUMART_ALIGN_CENTER | 653 WPS_ALBUMART_ALIGN_CENTER |
@@ -652,25 +667,27 @@ static int parse_albumart_load(const char *wps_bufptr,
652 667
653 /* format: %Cl|x|y|[[l|c|r][d|i|s]mwidth]|[[t|c|b][d|i|s]mheight]| */ 668 /* format: %Cl|x|y|[[l|c|r][d|i|s]mwidth]|[[t|c|b][d|i|s]mheight]| */
654 669
670 newline = strchr(wps_bufptr, '\n');
671
655 /* initial validation and parsing of x and y components */ 672 /* initial validation and parsing of x and y components */
656 if (*wps_bufptr != '|') 673 if (*wps_bufptr != '|')
657 return 0; /* malformed token: e.g. %Cl7 */ 674 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
658 675
659 _pos = wps_bufptr + 1; 676 _pos = wps_bufptr + 1;
660 if (!isdigit(*_pos)) 677 if (!isdigit(*_pos))
661 return 0; /* malformed token: e.g. %Cl|@ */ 678 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl|@ */
662 wps_data->albumart_x = atoi(_pos); 679 wps_data->albumart_x = atoi(_pos);
663 680
664 _pos = strchr(_pos, '|'); 681 _pos = strchr(_pos, '|');
665 if (!_pos || !isdigit(*(++_pos))) 682 if (!_pos || _pos > newline || !isdigit(*(++_pos)))
666 return 0; /* malformed token: e.g. %Cl|7\n or %Cl|7|@ */ 683 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl|7\n or %Cl|7|@ */
667 684
668 wps_data->albumart_y = atoi(_pos); 685 wps_data->albumart_y = atoi(_pos);
669 686
670 _pos = strchr(_pos, '|'); 687 _pos = strchr(_pos, '|');
671 if (!_pos) 688 if (!_pos || _pos > newline)
672 return 0; /* malformed token: no | after y coordinate 689 return WPS_ERROR_INVALID_PARAM; /* malformed token: no | after y coordinate
673 e.g. %Cl|7|59\n */ 690 e.g. %Cl|7|59\n */
674 691
675 /* parsing width field */ 692 /* parsing width field */
676 parsing = true; 693 parsing = true;
@@ -721,13 +738,15 @@ static int parse_albumart_load(const char *wps_bufptr,
721 /* extract max width data */ 738 /* extract max width data */
722 if (*_pos != '|') 739 if (*_pos != '|')
723 { 740 {
724 if (!isdigit(*_pos)) 741 if (!isdigit(*_pos)) /* malformed token: e.g. %Cl|7|59|# */
725 return 0; /* malformed token: e.g. %Cl|7|59|# */ 742 return WPS_ERROR_INVALID_PARAM;
743
726 wps_data->albumart_max_width = atoi(_pos); 744 wps_data->albumart_max_width = atoi(_pos);
745
727 _pos = strchr(_pos, '|'); 746 _pos = strchr(_pos, '|');
728 if (!_pos) 747 if (!_pos || _pos > newline)
729 return 0; /* malformed token: no | after width field 748 return WPS_ERROR_INVALID_PARAM; /* malformed token: no | after width field
730 e.g. %Cl|7|59|200\n */ 749 e.g. %Cl|7|59|200\n */
731 } 750 }
732 751
733 /* parsing height field */ 752 /* parsing height field */
@@ -780,12 +799,14 @@ static int parse_albumart_load(const char *wps_bufptr,
780 if (*_pos != '|') 799 if (*_pos != '|')
781 { 800 {
782 if (!isdigit(*_pos)) 801 if (!isdigit(*_pos))
783 return 0; /* malformed token e.g. %Cl|7|59|200|@ */ 802 return WPS_ERROR_INVALID_PARAM; /* malformed token e.g. %Cl|7|59|200|@ */
803
784 wps_data->albumart_max_height = atoi(_pos); 804 wps_data->albumart_max_height = atoi(_pos);
805
785 _pos = strchr(_pos, '|'); 806 _pos = strchr(_pos, '|');
786 if (!_pos) 807 if (!_pos || _pos > newline)
787 return 0; /* malformed token: no closing | 808 return WPS_ERROR_INVALID_PARAM; /* malformed token: no closing |
788 e.g. %Cl|7|59|200|200\n */ 809 e.g. %Cl|7|59|200|200\n */
789 } 810 }
790 811
791 /* if we got here, we parsed everything ok .. ! */ 812 /* if we got here, we parsed everything ok .. ! */
@@ -841,29 +862,29 @@ static int parse_albumart_conditional(const char *wps_bufptr,
841#endif /* HAVE_ALBUMART */ 862#endif /* HAVE_ALBUMART */
842 863
843#ifdef HAVE_LCD_BITMAP 864#ifdef HAVE_LCD_BITMAP
844static int parse_scrollmargin(const char *wps_bufptr, struct wps_token *token, 865static int parse_leftmargin(const char *wps_bufptr, struct wps_token *token,
845 struct wps_data *wps_data) 866 struct wps_data *wps_data)
846{ 867{
847 const char* p; 868 const char* p;
848 const char* pend; 869 const char* pend;
870 const char *newline;
849 871
850 (void)wps_data; /* Kill the warning */ 872 (void)wps_data; /* Kill the warning */
851 873
852 /* valid tag looks like %m or %m|12| */ 874 /* valid tag looks like %m|12| */
853 if(*wps_bufptr == '|') 875 if(*wps_bufptr == '|')
854 { 876 {
855 p = wps_bufptr + 1; 877 p = wps_bufptr + 1;
856 878 newline = strchr(wps_bufptr, '\n');
857 if(isdigit(*p) && (pend = strchr(p, '|'))) 879 if(isdigit(*p) && (pend = strchr(p, '|')) && pend < newline)
858 { 880 {
859 token->value.i = atoi(p); 881 token->value.i = atoi(p);
860 return(pend - wps_bufptr + 1); 882 return pend - wps_bufptr + 1;
861 } 883 }
862 } else {
863 token->value.i = 0;
864 } 884 }
865 885
866 return(0); 886 /* invalid tag syntax */
887 return WPS_ERROR_INVALID_PARAM;
867} 888}
868#endif 889#endif
869 890
@@ -871,7 +892,7 @@ static int parse_scrollmargin(const char *wps_bufptr, struct wps_token *token,
871/* Parse a generic token from the given string. Return the length read */ 892/* Parse a generic token from the given string. Return the length read */
872static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) 893static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
873{ 894{
874 int skip = 0, taglen = 0; 895 int skip = 0, taglen = 0, ret;
875 struct wps_token *token = wps_data->tokens + wps_data->num_tokens; 896 struct wps_token *token = wps_data->tokens + wps_data->num_tokens;
876 const struct wps_tag *tag; 897 const struct wps_tag *tag;
877 898
@@ -898,7 +919,9 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
898 condindex[level] = wps_data->num_tokens; 919 condindex[level] = wps_data->num_tokens;
899 numoptions[level] = 1; 920 numoptions[level] = 1;
900 wps_data->num_tokens++; 921 wps_data->num_tokens++;
901 taglen = 1 + parse_token(wps_bufptr + 1, wps_data); 922 ret = parse_token(wps_bufptr + 1, wps_data);
923 if (ret < 0) return ret;
924 taglen = 1 + ret;
902 break; 925 break;
903 926
904 default: 927 default:
@@ -914,7 +937,11 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
914 937
915 /* if the tag has a special parsing function, we call it */ 938 /* if the tag has a special parsing function, we call it */
916 if (tag->parse_func) 939 if (tag->parse_func)
917 skip += tag->parse_func(wps_bufptr + taglen, token, wps_data); 940 {
941 ret = tag->parse_func(wps_bufptr + taglen, token, wps_data);
942 if (ret < 0) return ret;
943 skip += ret;
944 }
918 945
919 /* Some tags we don't want to save as tokens */ 946 /* Some tags we don't want to save as tokens */
920 if (tag->type == WPS_NO_TOKEN) 947 if (tag->type == WPS_NO_TOKEN)
@@ -945,6 +972,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
945 char *stringbuf = data->string_buffer; 972 char *stringbuf = data->string_buffer;
946 int stringbuf_used = 0; 973 int stringbuf_used = 0;
947 int fail = 0; 974 int fail = 0;
975 int ret;
948 line = 1; 976 line = 1;
949 level = -1; 977 level = -1;
950 978
@@ -956,7 +984,12 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
956 984
957 /* Regular tag */ 985 /* Regular tag */
958 case '%': 986 case '%':
959 wps_bufptr += parse_token(wps_bufptr, data); 987 if ((ret = parse_token(wps_bufptr, data)) < 0)
988 {
989 fail = PARSE_FAIL_COND_INVALID_PARAM;
990 break;
991 }
992 wps_bufptr += ret;
960 break; 993 break;
961 994
962 /* Alternating sublines separator */ 995 /* Alternating sublines separator */