Solves issue #884: single quote zenity/kdialog
This commit is contained in:
parent
a237743c8b
commit
d9125d76cb
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <FL/Fl_Native_File_Chooser.H>
|
||||
#include "Fl_String.H"
|
||||
|
||||
class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK_Driver {
|
||||
friend class Fl_Native_File_Chooser;
|
||||
@ -45,7 +46,7 @@ class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK
|
||||
int count() const FL_OVERRIDE;
|
||||
const char *filename() const FL_OVERRIDE;
|
||||
const char *filename(int i) const FL_OVERRIDE;
|
||||
virtual char *build_command();
|
||||
virtual void build_command(Fl_String& command);
|
||||
int show() FL_OVERRIDE;
|
||||
char *parse_filter(const char *f);
|
||||
const char *filter() const FL_OVERRIDE;
|
||||
@ -57,6 +58,7 @@ class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK
|
||||
const char *directory() const FL_OVERRIDE;
|
||||
void title(const char *val) FL_OVERRIDE;
|
||||
const char *title() const FL_OVERRIDE;
|
||||
void shell_quote(Fl_String& s);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* Fl_Kdialog_Native_File_Chooser_Driver : file chooser based on the "kdialog" command */
|
||||
|
||||
bool Fl_Kdialog_Native_File_Chooser_Driver::did_find_kdialog = false;
|
||||
@ -73,7 +72,7 @@ static int fnfc_dispatch(int /*event*/, Fl_Window* /*win*/) {
|
||||
}
|
||||
|
||||
|
||||
char *Fl_Kdialog_Native_File_Chooser_Driver::build_command() {
|
||||
void Fl_Kdialog_Native_File_Chooser_Driver::build_command(Fl_String& command) {
|
||||
const char *option;
|
||||
switch (_btype) {
|
||||
case Fl_Native_File_Chooser::BROWSE_DIRECTORY:
|
||||
@ -92,25 +91,30 @@ char *Fl_Kdialog_Native_File_Chooser_Driver::build_command() {
|
||||
default:
|
||||
option = "--getopenfilename";
|
||||
}
|
||||
|
||||
// Build preset
|
||||
const char *preset = ".";
|
||||
if (_preset_file) preset = _preset_file;
|
||||
if (_preset_file) preset = _preset_file;
|
||||
else if (_directory) preset = _directory;
|
||||
const int com_size = strlen(option) + strlen(preset) +
|
||||
(_title?strlen(_title)+11:0) + (_parsedfilt?strlen(_parsedfilt):0) + 50;
|
||||
char *command = new char[com_size];
|
||||
strcpy(command, "kdialog ");
|
||||
|
||||
// Build command
|
||||
command = "kdialog";
|
||||
if (_title) {
|
||||
snprintf(command+strlen(command), com_size - strlen(command),
|
||||
" --title '%s'", _title);
|
||||
Fl_String quoted_title = _title; shell_quote(quoted_title);
|
||||
command += " --title ";
|
||||
command += quoted_title;
|
||||
}
|
||||
snprintf(command+strlen(command), com_size - strlen(command),
|
||||
" %s %s ", option, preset);
|
||||
command += " ";
|
||||
command += option;
|
||||
command += " ";
|
||||
command += preset;
|
||||
if (_parsedfilt) {
|
||||
snprintf(command+strlen(command), com_size - strlen(command),
|
||||
" \"%s\" ", _parsedfilt);
|
||||
Fl_String quoted_filt = _parsedfilt; shell_quote(quoted_filt); // NOTE: orig code used double quoting -erco 1/10/24
|
||||
command += " ";
|
||||
command += quoted_filt;
|
||||
}
|
||||
strcat(command, "2> /dev/null"); // get rid of stderr output
|
||||
return command;
|
||||
command += " 2> /dev/null"; // get rid of stderr
|
||||
//printf("command = %s\n", command.c_str());
|
||||
}
|
||||
|
||||
|
||||
@ -137,9 +141,10 @@ int Fl_Kdialog_Native_File_Chooser_Driver::show() {
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *command = build_command();
|
||||
//puts(command);
|
||||
FILE *pipe = popen(command, "r");
|
||||
Fl_String command;
|
||||
build_command(command);
|
||||
fprintf(stderr, "DEBUG: POPEN: %s\n", command.c_str());
|
||||
FILE *pipe = popen(command.c_str(), "r");
|
||||
fnfc_pipe_struct data;
|
||||
data.all_files = NULL;
|
||||
if (pipe) {
|
||||
@ -175,7 +180,6 @@ int Fl_Kdialog_Native_File_Chooser_Driver::show() {
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] command;
|
||||
if (!pipe) return -1;
|
||||
return (data.all_files == NULL ? 1 : 0);
|
||||
}
|
||||
@ -298,6 +302,19 @@ const char *Fl_Kdialog_Native_File_Chooser_Driver::title() const {
|
||||
return _title;
|
||||
}
|
||||
|
||||
// Add shell quotes around string 's'.
|
||||
// Handles quoting embedded quotes.
|
||||
//
|
||||
void Fl_Kdialog_Native_File_Chooser_Driver::shell_quote(Fl_String& s) {
|
||||
Fl_String out = "'"; // leading quote
|
||||
for (int t=0; t<s.size(); t++) {
|
||||
if (s[t] == '\'') out += "'\"'\"'"; // quote any quotes
|
||||
else out += s[t];
|
||||
}
|
||||
out += "'"; // trailing quote
|
||||
s = out;
|
||||
}
|
||||
|
||||
/**
|
||||
\}
|
||||
\endcond
|
||||
|
@ -30,7 +30,8 @@ class Fl_Zenity_Native_File_Chooser_Driver : public Fl_Kdialog_Native_File_Choos
|
||||
static bool did_find_zenity;
|
||||
static bool have_looked_for_zenity;
|
||||
Fl_Zenity_Native_File_Chooser_Driver(int val);
|
||||
char *build_command() FL_OVERRIDE;
|
||||
void append_filter(Fl_String& command);
|
||||
void build_command(Fl_String& command) FL_OVERRIDE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -36,10 +36,48 @@ bool Fl_Zenity_Native_File_Chooser_Driver::have_looked_for_zenity = false;
|
||||
Fl_Zenity_Native_File_Chooser_Driver::Fl_Zenity_Native_File_Chooser_Driver(int val) : Fl_Kdialog_Native_File_Chooser_Driver(val) {
|
||||
}
|
||||
|
||||
|
||||
char *Fl_Zenity_Native_File_Chooser_Driver::build_command() {
|
||||
const char *option;
|
||||
void Fl_Zenity_Native_File_Chooser_Driver::append_filter(Fl_String& ret_command) {
|
||||
// TODO: This could probably be simplified + toughened with Fl_String -erco 1/10/24
|
||||
int l;
|
||||
int lcommand = 10000;
|
||||
char *command = new char[lcommand];
|
||||
command[0] = 0;
|
||||
char *parsed_filter_copy = strdup(_parsedfilt); // keep _parsedfilt unchanged for re-use
|
||||
char *p = strtok(parsed_filter_copy, "\n");
|
||||
while (p) {
|
||||
char *op = strchr(p, '(');
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, " --file-filter='%s|", p);
|
||||
char *cp = strchr(p, ')');
|
||||
*cp = 0;
|
||||
char *ob = strchr(op+1, '[');
|
||||
if (ob) { // process [xyz] patterns
|
||||
*ob = 0;
|
||||
char *cb = strchr(ob+1, ']');
|
||||
char aux[100];
|
||||
for (char *q = ob+1; q < cb; q++) {
|
||||
strcpy(aux, op+1);
|
||||
int la = strlen(aux);
|
||||
aux[la++] = *q;
|
||||
if (cb < cp-1) { strcpy(aux+la, cb+1); la += strlen(cb+1); }
|
||||
aux[la] = 0;
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, " %s", aux);
|
||||
}
|
||||
strcat(command, "'");
|
||||
} else {
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, "%s'", op+1);
|
||||
}
|
||||
p = strtok(NULL, "\n");
|
||||
}
|
||||
free(parsed_filter_copy);
|
||||
ret_command += command; // append to parent's Fl_String
|
||||
delete [] command;
|
||||
}
|
||||
|
||||
void Fl_Zenity_Native_File_Chooser_Driver::build_command(Fl_String& command) {
|
||||
const char *option;
|
||||
switch (_btype) {
|
||||
case Fl_Native_File_Chooser::BROWSE_DIRECTORY:
|
||||
case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY:
|
||||
@ -60,63 +98,36 @@ char *Fl_Zenity_Native_File_Chooser_Driver::build_command() {
|
||||
default:
|
||||
option = "--file-selection";
|
||||
}
|
||||
char *preset = NULL;
|
||||
|
||||
// Build preset
|
||||
Fl_String preset;
|
||||
if (_preset_file) {
|
||||
l = strlen(_preset_file) + 15;
|
||||
preset = new char[l];
|
||||
snprintf(preset, l, "--filename='%s'", _preset_file);
|
||||
}
|
||||
else if (_directory) {
|
||||
Fl_String quoted_filename = _preset_file; shell_quote(quoted_filename);
|
||||
preset = "--filename=";
|
||||
preset += quoted_filename;
|
||||
} else if (_directory) {
|
||||
// This doesn't actually seem to do anything, but supply it anyway.
|
||||
l = strlen(_directory) + 15;
|
||||
preset = new char[l];
|
||||
snprintf(preset, l, "--filename '%s'", _directory);
|
||||
Fl_String quoted_dir = _directory; shell_quote(quoted_dir);
|
||||
preset = "--filename=";
|
||||
preset += quoted_dir;
|
||||
}
|
||||
int lcommand = 10000;
|
||||
char *command = new char[lcommand];
|
||||
strcpy(command, "zenity ");
|
||||
|
||||
// Build command
|
||||
command = "zenity";
|
||||
if (_title) {
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, " --title '%s'", _title);
|
||||
Fl_String quoted_title = _title; shell_quote(quoted_title);
|
||||
command += " --title ";
|
||||
command += quoted_title;
|
||||
}
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, " %s %s ", option, preset ? preset : "");
|
||||
delete[] preset;
|
||||
if (_parsedfilt) {
|
||||
char *parsed_filter_copy = strdup(_parsedfilt); // keep _parsedfilt unchanged for re-use
|
||||
char *p = strtok(parsed_filter_copy, "\n");
|
||||
while (p) {
|
||||
char *op = strchr(p, '(');
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, " --file-filter='%s|", p);
|
||||
char *cp = strchr(p, ')');
|
||||
*cp = 0;
|
||||
char *ob = strchr(op+1, '[');
|
||||
if (ob) { // process [xyz] patterns
|
||||
*ob = 0;
|
||||
char *cb = strchr(ob+1, ']');
|
||||
char aux[100];
|
||||
for (char *q = ob+1; q < cb; q++) {
|
||||
strcpy(aux, op+1);
|
||||
int la = strlen(aux);
|
||||
aux[la++] = *q;
|
||||
if (cb < cp-1) { strcpy(aux+la, cb+1); la += strlen(cb+1); }
|
||||
aux[la] = 0;
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, " %s", aux);
|
||||
}
|
||||
strcat(command, "'");
|
||||
} else {
|
||||
l = strlen(command);
|
||||
snprintf(command+l, lcommand-l, "%s'", op+1);
|
||||
}
|
||||
p = strtok(NULL, "\n");
|
||||
}
|
||||
free(parsed_filter_copy);
|
||||
command += " ";
|
||||
command += option;
|
||||
if (preset != "") {
|
||||
command += " ";
|
||||
command += preset;
|
||||
}
|
||||
strcat(command, " 2> /dev/null"); // get rid of stderr output
|
||||
//puts(command);
|
||||
return command;
|
||||
if (_parsedfilt) append_filter(command);
|
||||
command += " 2> /dev/null"; // get rid of stderr
|
||||
//printf("command = %s\n", command.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user