Mercurial > mplayer.hg
annotate libmenu/menu_filesel.c @ 10624:cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
a quote ('). The menu simply execute a "loadfile '%p'" but when the %p
is replaced by the actual value, quotes in it are not escaped !
Moreover, mp_input_parse_cmd contain some code to unescape strings but
this code was placed after the string was copied in his final buffer.
So this patch correct this issue.
By Aurlien Jacobs
author | albeu |
---|---|
date | Fri, 15 Aug 2003 18:45:35 +0000 |
parents | edfe34c5405d |
children | 261022c048cd |
rev | line source |
---|---|
8197 | 1 |
2 #include <stdlib.h> | |
3 #include <stdio.h> | |
4 #include <dirent.h> | |
5 #include <errno.h> | |
6 #include <string.h> | |
7 #include <sys/types.h> | |
8 #include <sys/stat.h> | |
9 #include <ctype.h> | |
10 #include <unistd.h> | |
8291
abe95dde3223
limits.h required to get a PATH_MAX definition (on solaris)
jkeil
parents:
8226
diff
changeset
|
11 #include <limits.h> |
8197 | 12 |
13 | |
14 #include "../config.h" | |
15 | |
16 #include "../m_struct.h" | |
17 #include "../m_option.h" | |
18 | |
19 #include "img_format.h" | |
20 #include "mp_image.h" | |
21 | |
22 #include "menu.h" | |
23 #include "menu_list.h" | |
24 #include "../input/input.h" | |
9380 | 25 #include "../osdep/keycodes.h" |
8197 | 26 |
27 struct list_entry_s { | |
28 struct list_entry p; | |
29 int d; | |
30 }; | |
31 | |
32 struct menu_priv_s { | |
33 menu_list_priv_t p; | |
34 char* dir; // current dir | |
35 /// Cfg fields | |
36 char* path; | |
37 char* title; | |
38 char* file_action; | |
39 char* dir_action; | |
40 int auto_close; | |
41 }; | |
42 | |
43 static struct menu_priv_s cfg_dflt = { | |
44 MENU_LIST_PRIV_DFLT, | |
45 NULL, | |
46 | |
47 NULL, | |
48 "Select a file: %p", | |
8226 | 49 "loadfile '%p'", |
8197 | 50 NULL, |
51 0 | |
52 }; | |
53 | |
54 #define ST_OFF(m) M_ST_OFF(struct menu_priv_s,m) | |
55 | |
56 static m_option_t cfg_fields[] = { | |
57 MENU_LIST_PRIV_FIELDS, | |
58 { "path", ST_OFF(path), CONF_TYPE_STRING, 0, 0, 0, NULL }, | |
59 { "title", ST_OFF(title), CONF_TYPE_STRING, 0, 0, 0, NULL }, | |
60 { "file-action", ST_OFF(file_action), CONF_TYPE_STRING, 0, 0, 0, NULL }, | |
61 { "dir-action", ST_OFF(dir_action), CONF_TYPE_STRING, 0, 0, 0, NULL }, | |
62 { "auto-close", ST_OFF(auto_close), CONF_TYPE_FLAG, 0, 0, 1, NULL }, | |
63 { NULL, NULL, NULL, 0,0,0,NULL } | |
64 }; | |
65 | |
66 #define mpriv (menu->priv) | |
67 | |
68 static void free_entry(list_entry_t* entry) { | |
69 free(entry->p.txt); | |
70 free(entry); | |
71 } | |
72 | |
73 static char* replace_path(char* title , char* dir) { | |
74 char *p = strstr(title,"%p"); | |
75 if(p) { | |
76 int tl = strlen(title); | |
77 int dl = strlen(dir); | |
78 int t1l = p-title; | |
79 int l = tl - 2 + dl; | |
10624
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
80 char *r, *n, *d = dir; |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
81 char term = *(p-1); |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
82 |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
83 do { |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
84 if (*d == '\\' || *d == term) |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
85 l++; |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
86 } while (*d++); |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
87 r = malloc(l + 1); |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
88 n = r + t1l; |
8197 | 89 memcpy(r,title,t1l); |
10624
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
90 do { |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
91 if (*dir == '\\' || *dir == term) |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
92 *n++ = '\\'; |
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
93 } while ((*n++ = *dir++)); |
8197 | 94 if(tl - t1l - 2 > 0) |
10624
cdfd4a43c406
I've juste found a bug which prevent to load a file whose name contain
albeu
parents:
9380
diff
changeset
|
95 strcpy(n-1,p+2); |
8197 | 96 return r; |
97 } else | |
98 return title; | |
99 } | |
100 | |
101 typedef int (*kill_warn)(const void*, const void*); | |
102 | |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
103 static int mylstat(char *dir, char *file,struct stat* st) { |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
104 int l = strlen(dir) + strlen(file); |
8613 | 105 char s[l+2]; |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
106 sprintf(s,"%s/%s",dir,file); |
9249 | 107 return stat(s,st); |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
108 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
109 |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
110 static int compare(char **a, char **b){ |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
111 if((*a)[strlen(*a) - 1] == '/') { |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
112 if((*b)[strlen(*b) - 1] == '/') |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
113 return strcmp(*b, *a) ; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
114 else |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
115 return 1; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
116 } else { |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
117 if((*b)[strlen(*b) - 1] == '/') |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
118 return -1; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
119 else |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
120 return strcmp(*b, *a); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
121 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
122 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
123 |
8197 | 124 static int open_dir(menu_t* menu,char* args) { |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
125 char **namelist, **tp; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
126 struct dirent *dp; |
8197 | 127 struct stat st; |
128 int n; | |
129 char* p = NULL; | |
130 list_entry_t* e; | |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
131 DIR* dirp; |
8197 | 132 |
133 menu_list_init(menu); | |
134 | |
135 if(mpriv->dir) | |
136 free(mpriv->dir); | |
137 mpriv->dir = strdup(args); | |
138 if(mpriv->p.title && mpriv->p.title != mpriv->title && mpriv->p.title != cfg_dflt.p.title) | |
139 free(mpriv->p.title); | |
140 p = strstr(mpriv->title,"%p"); | |
141 | |
142 mpriv->p.title = replace_path(mpriv->title,mpriv->dir); | |
143 | |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
144 if ((dirp = opendir (mpriv->dir)) == NULL){ |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
145 printf("opendir error: %s", strerror(errno)); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
146 return 0; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
147 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
148 |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
149 namelist = (char **) malloc(sizeof(char *)); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
150 |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
151 n=0; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
152 while ((dp = readdir(dirp)) != NULL) { |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
153 if(dp->d_name[0] == '.' && strcmp(dp->d_name,"..") != 0) |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
154 continue; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
155 if(n%20 == 0){ // Get some more mem |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
156 if((tp = (char **) realloc(namelist, (n+20) * sizeof (char *))) |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
157 == NULL) { |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
158 printf("realloc error: %s", strerror(errno)); |
9104
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
159 n--; |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
160 goto bailout; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
161 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
162 namelist=tp; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
163 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
164 |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
165 namelist[n] = (char *) malloc(strlen(dp->d_name) + 2); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
166 if(namelist[n] == NULL){ |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
167 printf("malloc error: %s", strerror(errno)); |
9104
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
168 n--; |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
169 goto bailout; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
170 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
171 |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
172 strcpy(namelist[n], dp->d_name); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
173 mylstat(args,namelist[n],&st); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
174 if(S_ISDIR(st.st_mode)) |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
175 strcat(namelist[n], "/"); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
176 n++; |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
177 } |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
178 |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
179 bailout: |
9104
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
180 qsort(namelist, n, sizeof(char *), (kill_warn)compare); |
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
181 |
8197 | 182 if (n < 0) { |
9104
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
183 printf("readdir error: %s\n",strerror(errno)); |
8197 | 184 return 0; |
185 } | |
186 while(n--) { | |
9104
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
187 if((e = calloc(1,sizeof(list_entry_t))) != NULL){ |
8613 | 188 e->p.next = NULL; |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
189 e->p.txt = strdup(namelist[n]); |
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
190 if(strchr(namelist[n], '/') != NULL) |
8197 | 191 e->d = 1; |
8358
ecf6a4cf3272
No scandir() an no functions defined within other functions.
arpi
parents:
8291
diff
changeset
|
192 menu_list_add_entry(menu,e); |
9104
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
193 }else{ |
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
194 printf("malloc error: %s", strerror(errno)); |
a0aacfb492a5
Also attached some cleanup to menu_filesel.c, mainly to make it more
arpi
parents:
8853
diff
changeset
|
195 } |
8197 | 196 free(namelist[n]); |
197 } | |
198 free(namelist); | |
199 | |
200 return 1; | |
201 } | |
202 | |
203 | |
204 static void read_cmd(menu_t* menu,int cmd) { | |
205 mp_cmd_t* c = NULL; | |
206 switch(cmd) { | |
207 case MENU_CMD_OK: { | |
208 // Directory | |
209 if(mpriv->p.current->d) { | |
210 if(mpriv->dir_action) { | |
211 int fname_len = strlen(mpriv->dir) + strlen(mpriv->p.current->p.txt) + 1; | |
212 char filename[fname_len]; | |
213 char* str; | |
214 sprintf(filename,"%s%s",mpriv->dir,mpriv->p.current->p.txt); | |
215 str = replace_path(mpriv->dir_action,filename); | |
216 c = mp_input_parse_cmd(str); | |
217 if(str != mpriv->dir_action) | |
218 free(str); | |
219 } else { // Default action : open this dirctory ourself | |
220 int l = strlen(mpriv->dir); | |
221 char *slash = NULL, *p = NULL; | |
222 if(strcmp(mpriv->p.current->p.txt,"../") == 0) { | |
223 if(l <= 1) break; | |
224 mpriv->dir[l-1] = '\0'; | |
225 slash = strrchr(mpriv->dir,'/'); | |
226 if(!slash) break; | |
227 slash[1] = '\0'; | |
228 p = strdup(mpriv->dir); | |
229 } else { | |
230 p = malloc(l + strlen(mpriv->p.current->p.txt) + 1); | |
231 sprintf(p,"%s%s",mpriv->dir,mpriv->p.current->p.txt); | |
232 } | |
233 menu_list_uninit(menu,free_entry); | |
234 if(!open_dir(menu,p)) { | |
235 printf("Can't open directory %s\n",p); | |
236 menu->cl = 1; | |
237 } | |
238 free(p); | |
239 } | |
240 } else { // Files | |
241 int fname_len = strlen(mpriv->dir) + strlen(mpriv->p.current->p.txt) + 1; | |
242 char filename[fname_len]; | |
243 char *str; | |
244 sprintf(filename,"%s%s",mpriv->dir,mpriv->p.current->p.txt); | |
245 str = replace_path(mpriv->file_action,filename); | |
246 c = mp_input_parse_cmd(str); | |
247 if(str != mpriv->file_action) | |
248 free(str); | |
249 } | |
250 if(c) { | |
251 mp_input_queue_cmd(c); | |
252 if(mpriv->auto_close) | |
253 menu->cl = 1; | |
254 } | |
255 } break; | |
256 default: | |
257 menu_list_read_cmd(menu,cmd); | |
258 } | |
259 } | |
260 | |
261 static void read_key(menu_t* menu,int c){ | |
262 if(c == KEY_BS) { | |
263 mpriv->p.current = mpriv->p.menu; // Hack : we consider that the first entry is ../ | |
264 read_cmd(menu,MENU_CMD_OK); | |
265 } else | |
266 menu_list_read_key(menu,c,1); | |
267 } | |
268 | |
269 static void clos(menu_t* menu) { | |
270 menu_list_uninit(menu,free_entry); | |
271 free(mpriv->dir); | |
272 } | |
273 | |
274 static int open_fs(menu_t* menu, char* args) { | |
275 char *path = mpriv->path; | |
276 int r = 0; | |
277 char wd[PATH_MAX+1]; | |
278 args = NULL; // Warning kill | |
279 | |
280 menu->draw = menu_list_draw; | |
281 menu->read_cmd = read_cmd; | |
282 menu->read_key = read_key; | |
283 menu->close = clos; | |
284 | |
285 getcwd(wd,PATH_MAX); | |
286 if(!path || path[0] == '\0') { | |
287 int l = strlen(wd) + 2; | |
288 char b[l]; | |
289 sprintf(b,"%s/",wd); | |
290 r = open_dir(menu,b); | |
291 } else if(path[0] != '/') { | |
292 int al = strlen(path); | |
293 int l = strlen(wd) + al + 3; | |
294 char b[l]; | |
295 if(b[al-1] != '/') | |
296 sprintf(b,"%s/%s/",wd,path); | |
297 else | |
298 sprintf(b,"%s/%s",wd,path); | |
299 r = open_dir(menu,b); | |
300 } else | |
301 r = open_dir(menu,path); | |
302 | |
303 return r; | |
304 } | |
305 | |
306 const menu_info_t menu_info_filesel = { | |
307 "File seletor menu", | |
308 "filesel", | |
309 "Albeu", | |
310 "", | |
311 { | |
312 "fs_cfg", | |
313 sizeof(struct menu_priv_s), | |
314 &cfg_dflt, | |
315 cfg_fields | |
316 }, | |
317 open_fs | |
318 }; |