Problem with ^A in Filename
Commit Message
Udo Richter wrote:
> Klaus Schmidinger wrote:
>
>> Patrick Fischer wrote:
>>
>>> @Ripley's unglaubliche Welt
>>> will be saved as (only shown if I pipe "ll . > out.txt" and look at
>>> the file or by using xterm)
>>> @Ripley^As_unglaubliche_Welt
>>
>>
>> The single quote character is mapped to 0x01 so that in shell script
>> it is guaranteed that no recording name contains such a character, and
>> you can always be sure that enclosing a recording name in single quotes
>> will work.
>
>
> This is only true in classic mode. In VFAT-mode, unsafe characters like
> this are mapped to literal ascii codes, in this case '#27'.
>
> Using ASCII control chars (0x01 alias SOH for ', 0x02 alias STX for /)
> in file names doesn't sound like a good idea to me anyway. Wouldn't it
> be better to use '#27' and '#2F' (and consequently '#23' for #) in
> non-VFAT mode too?
>
> Cheers,
>
> Udo
I've now made it so that in "normal" mode (non-VFAT) the single quote
is not mapped any more (IIRC I thought that this might be necessary
for external commands, but with strescape() and "..." this works just
fine). The '/' and '~' are swapped between internal and external
representation, so that no more "control" characters are used.
For backwards compatibility 0x01, 0x02 and 0x03 are still recognized.
Please give the attached patch a try.
Klaus
@@ -386,92 +386,75 @@
#define RESUME_NOT_INITIALIZED (-2)
-struct tCharExchange { char a; char b; };
-tCharExchange CharExchange[] = {
- { '~', '/' },
- { ' ', '_' },
- { '\'', '\x01' },
- { '/', '\x02' },
- { 0, 0 }
- };
-
char *ExchangeChars(char *s, bool ToFileSystem)
{
char *p = s;
while (*p) {
- if (VfatFileSystem) {
- // The VFAT file system can't handle all characters, so we
- // have to take extra efforts to encode/decode them:
- if (ToFileSystem) {
- switch (*p) {
- // characters that can be used "as is":
- case '!':
- case '@':
- case '$':
- case '%':
- case '&':
- case '(':
- case ')':
- case '+':
- case ',':
- case '-':
- case ';':
- case '=':
- case '0' ... '9':
- case 'a' ... 'z':
- case 'A' ... 'Z':
- case 'ä': case 'Ä':
- case 'ö': case 'Ö':
- case 'ü': case 'Ü':
- case 'ß':
- break;
- // characters that can be mapped to other characters:
- case ' ': *p = '_'; break;
- case '~': *p = '/'; break;
- // characters that have to be encoded:
- default:
- if (*p != '.' || !*(p + 1) || *(p + 1) == '~') { // Windows can't handle '.' at the end of directory names
- int l = p - s;
- s = (char *)realloc(s, strlen(s) + 10);
- p = s + l;
- char buf[4];
- sprintf(buf, "#%02X", (unsigned char)*p);
- memmove(p + 2, p, strlen(p) + 1);
- strncpy(p, buf, 3);
- p += 2;
- }
- }
- }
- else {
- switch (*p) {
- // mapped characters:
- case '_': *p = ' '; break;
- case '/': *p = '~'; break;
- // encodes characters:
- case '#': {
- if (strlen(p) > 2) {
- char buf[3];
- sprintf(buf, "%c%c", *(p + 1), *(p + 2));
- unsigned char c = strtol(buf, NULL, 16);
- *p = c;
- memmove(p + 1, p + 3, strlen(p) - 2);
- }
- }
- break;
- // backwards compatibility:
- case '\x01': *p = '\''; break;
- case '\x02': *p = '/'; break;
- case '\x03': *p = ':'; break;
- }
- }
+ if (ToFileSystem) {
+ switch (*p) {
+ // characters that can be used "as is":
+ case '!':
+ case '@':
+ case '$':
+ case '%':
+ case '&':
+ case '(':
+ case ')':
+ case '+':
+ case ',':
+ case '-':
+ case ';':
+ case '=':
+ case '0' ... '9':
+ case 'a' ... 'z':
+ case 'A' ... 'Z':
+ case 'ä': case 'Ä':
+ case 'ö': case 'Ö':
+ case 'ü': case 'Ü':
+ case 'ß':
+ break;
+ // characters that can be mapped to other characters:
+ case ' ': *p = '_'; break;
+ case '~': *p = '/'; break;
+ case '/': *p = '~'; break;
+ // characters that have to be encoded:
+ default:
+ // The VFAT file system can't handle all characters, so we
+ // have to take extra efforts to encode them.
+ if (VfatFileSystem && (*p != '.' || !*(p + 1) || *(p + 1) == '~')) { // Windows can't handle '.' at the end of directory names
+ int l = p - s;
+ s = (char *)realloc(s, strlen(s) + 10);
+ p = s + l;
+ char buf[4];
+ sprintf(buf, "#%02X", (unsigned char)*p);
+ memmove(p + 2, p, strlen(p) + 1);
+ strncpy(p, buf, 3);
+ p += 2;
+ }
+ }
}
else {
- for (struct tCharExchange *ce = CharExchange; ce->a && ce->b; ce++) {
- if (*p == (ToFileSystem ? ce->a : ce->b)) {
- *p = ToFileSystem ? ce->b : ce->a;
- break;
+ switch (*p) {
+ // mapped characters:
+ case '_': *p = ' '; break;
+ case '/': *p = '~'; break;
+ case '~': *p = '/'; break;
+ // encoded characters:
+ case '#': {
+ if (VfatFileSystem && strlen(p) > 2) {
+ char buf[3];
+ sprintf(buf, "%c%c", *(p + 1), *(p + 2));
+ unsigned char c = strtol(buf, NULL, 16);
+ *p = c;
+ memmove(p + 1, p + 3, strlen(p) - 2);
+ }
}
- }
+ break;
+ // backwards compatibility:
+ case '\x01': *p = '\''; break;
+ case '\x02': *p = '/'; break;
+ case '\x03': *p = ':'; break;
+ }
}
p++;
}
@@ -2036,7 +2036,7 @@
cRecording *recording = GetRecording(ri);
if (recording) {
char *parameter = NULL;
- asprintf(¶meter, "'%s'", recording->FileName());
+ asprintf(¶meter, "\"%s\"", *strescape(recording->FileName(), "\"$"));
cMenuCommands *menu;
eOSState state = AddSubMenu(menu = new cMenuCommands(tr("Recording commands"), &RecordingCommands, parameter));
free(parameter);