summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2024-01-11 07:50:09 -0800
committerGreg Ercolano <erco@seriss.com>2024-01-11 07:50:09 -0800
commitd9125d76cb917397212f106f9b8eb8632f6ab71a (patch)
treef33ba86c0e48dabb07dc03c3e2dcd5599911d62b
parenta237743c8babfe5a24acd9b3ab7aa79dcf0159ad (diff)
Solves issue #884: single quote zenity/kdialog
-rw-r--r--src/Fl_Native_File_Chooser_Kdialog.H4
-rw-r--r--src/Fl_Native_File_Chooser_Kdialog.cxx55
-rw-r--r--src/Fl_Native_File_Chooser_Zenity.H3
-rw-r--r--src/Fl_Native_File_Chooser_Zenity.cxx117
4 files changed, 105 insertions, 74 deletions
diff --git a/src/Fl_Native_File_Chooser_Kdialog.H b/src/Fl_Native_File_Chooser_Kdialog.H
index f65445fb3..8b50b36fa 100644
--- a/src/Fl_Native_File_Chooser_Kdialog.H
+++ b/src/Fl_Native_File_Chooser_Kdialog.H
@@ -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);
};
/**
diff --git a/src/Fl_Native_File_Chooser_Kdialog.cxx b/src/Fl_Native_File_Chooser_Kdialog.cxx
index 72bb6ce18..1fa322c98 100644
--- a/src/Fl_Native_File_Chooser_Kdialog.cxx
+++ b/src/Fl_Native_File_Chooser_Kdialog.cxx
@@ -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
diff --git a/src/Fl_Native_File_Chooser_Zenity.H b/src/Fl_Native_File_Chooser_Zenity.H
index 56b12ed29..790180378 100644
--- a/src/Fl_Native_File_Chooser_Zenity.H
+++ b/src/Fl_Native_File_Chooser_Zenity.H
@@ -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;
};
/**
diff --git a/src/Fl_Native_File_Chooser_Zenity.cxx b/src/Fl_Native_File_Chooser_Zenity.cxx
index aa967bfb0..908e68cda 100644
--- a/src/Fl_Native_File_Chooser_Zenity.cxx
+++ b/src/Fl_Native_File_Chooser_Zenity.cxx
@@ -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) {
}
+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;
+}
-char *Fl_Zenity_Native_File_Chooser_Driver::build_command() {
+void Fl_Zenity_Native_File_Chooser_Driver::build_command(Fl_String& command) {
const char *option;
- int l;
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());
}
/**