]>
Commit | Line | Data |
---|---|---|
5b80d150 AM |
1 | From 8e8e146c9763635d510c8a065c2c143068dc58d6 Mon Sep 17 00:00:00 2001 |
2 | From: "Alexander V. Lukyanov" <lavv17f@gmail.com> | |
3 | Date: Wed, 21 Jan 2015 19:28:52 +0300 | |
4 | Subject: [PATCH] (ArgV::CombineShellQuoted) new method; use it for FishDirList | |
5 | ||
6 | This fixes a problem with ls (fish protocol) when called with an | |
7 | argument containing spaces and other special symbols. | |
8 | --- | |
9 | src/ArgV.cc | 19 +++++++++++++++++++ | |
10 | src/ArgV.h | 4 ++++ | |
11 | src/Fish.h | 2 +- | |
12 | src/misc.cc | 41 ++++++++++++++++++++++------------------- | |
13 | src/misc.h | 1 + | |
14 | 5 files changed, 47 insertions(+), 20 deletions(-) | |
15 | ||
16 | diff --git a/src/ArgV.cc b/src/ArgV.cc | |
17 | index fdf9379..785966d 100644 | |
18 | --- a/src/ArgV.cc | |
19 | +++ b/src/ArgV.cc | |
20 | @@ -72,6 +72,25 @@ char *ArgV::Combine(int start,int end) const | |
21 | } | |
22 | } | |
23 | ||
24 | +char *ArgV::CombineShellQuoted(int start) const | |
25 | +{ | |
26 | + xstring res(""); | |
27 | + if(start>=Count()) | |
28 | + return res.borrow(); | |
29 | + for(;;) | |
30 | + { | |
31 | + for(const char *arg=String(start++); *arg; arg++) | |
32 | + { | |
33 | + if (is_shell_special(*arg)) | |
34 | + res.append('\\'); | |
35 | + res.append(*arg); | |
36 | + } | |
37 | + if(start>=Count()) | |
38 | + return(res.borrow()); | |
39 | + res.append(' '); | |
40 | + } | |
41 | +} | |
42 | + | |
43 | int ArgV::getopt_long(const char *opts,const struct option *lopts,int *lind) | |
44 | { | |
45 | optind=ind; | |
46 | diff --git a/src/ArgV.h b/src/ArgV.h | |
47 | index 442d6a3..c911733 100644 | |
48 | --- a/src/ArgV.h | |
49 | +++ b/src/ArgV.h | |
50 | @@ -42,6 +42,10 @@ class ArgV : public StringSet | |
51 | void Add(const char *a) { Append(a); } // alias | |
52 | ||
53 | char *Combine(int start_index=0,int end_index=0) const; | |
54 | + | |
55 | + // for the UNIX shell | |
56 | + char *CombineShellQuoted(int start) const; | |
57 | + // for lftp's CmdExec | |
58 | char *CombineQuoted(int start_index=0) const; | |
59 | char *CombineCmd(int i=0) const; | |
60 | ||
61 | diff --git a/src/Fish.h b/src/Fish.h | |
62 | index dd9112d..5493e59 100644 | |
63 | --- a/src/Fish.h | |
64 | +++ b/src/Fish.h | |
65 | @@ -150,7 +150,7 @@ class FishDirList : public DirList | |
66 | ||
67 | public: | |
68 | FishDirList(Fish *s,ArgV *a) | |
69 | - : DirList(s,a), pattern(args->Combine(1)) {} | |
70 | + : DirList(s,a), pattern(args->CombineShellQuoted(1)) {} | |
71 | const char *Status(); | |
72 | int Do(); | |
73 | ||
74 | diff --git a/src/misc.cc b/src/misc.cc | |
75 | index 9e253ef..b31e523 100644 | |
76 | --- a/src/misc.cc | |
77 | +++ b/src/misc.cc | |
78 | @@ -882,6 +882,26 @@ const char *memrchr(const char *buf,char c,size_t len) | |
79 | return 0; | |
80 | } | |
81 | ||
82 | +bool is_shell_special(char c) | |
83 | +{ | |
84 | + switch (c) | |
85 | + { | |
86 | + case '\'': | |
87 | + case '(': case ')': | |
88 | + case '!': case '{': case '}': /* reserved words */ | |
89 | + case '^': | |
90 | + case '$': case '`': /* expansion chars */ | |
91 | + case '*': case '[': case '?': case ']': /* globbing chars */ | |
92 | + case ' ': case '\t': case '\n': /* IFS white space */ | |
93 | + case '"': case '\\': /* quoting chars */ | |
94 | + case '|': case '&': case ';': /* shell metacharacters */ | |
95 | + case '<': case '>': | |
96 | + case '#': /* comment char */ | |
97 | + return true; | |
98 | + } | |
99 | + return false; | |
100 | +} | |
101 | + | |
102 | const xstring& shell_encode(const char *string) | |
103 | { | |
104 | if(!string) | |
105 | @@ -901,26 +921,9 @@ const xstring& shell_encode(const char *string) | |
106 | int c; | |
107 | for (const char *s = string; s && (c = *s); s++) | |
108 | { | |
109 | - switch (c) | |
110 | - { | |
111 | - case '\'': | |
112 | - case '(': case ')': | |
113 | - case '!': case '{': case '}': /* reserved words */ | |
114 | - case '^': | |
115 | - case '$': case '`': /* expansion chars */ | |
116 | - case '*': case '[': case '?': case ']': /* globbing chars */ | |
117 | - case ' ': case '\t': case '\n': /* IFS white space */ | |
118 | - case '"': case '\\': /* quoting chars */ | |
119 | - case '|': case '&': case ';': /* shell metacharacters */ | |
120 | - case '<': case '>': | |
121 | - case '#': /* comment char */ | |
122 | + if (is_shell_special(c)) | |
123 | *r++ = '\\'; | |
124 | - *r++ = c; | |
125 | - break; | |
126 | - default: | |
127 | - *r++ = c; | |
128 | - break; | |
129 | - } | |
130 | + *r++ = c; | |
131 | } | |
132 | result.set_length(r-result); | |
133 | return (result); | |
134 | diff --git a/src/misc.h b/src/misc.h | |
135 | index 4cda301..f93d25e 100644 | |
136 | --- a/src/misc.h | |
137 | +++ b/src/misc.h | |
138 | @@ -123,6 +123,7 @@ static inline char *memrchr(char *buf,char c,size_t len) { | |
139 | return const_cast<char*>(memrchr(const_cast<const char*>(buf),c,len)); | |
140 | } | |
141 | ||
142 | +bool is_shell_special(char c); | |
143 | const xstring& shell_encode(const char *); | |
144 | void remove_tags(char *buf); | |
145 | void rtrim(char *s); |