# # # patch "NEWS" # from [fedab0b6110210fd90efd17b7d63621b6449f7e5] # to [30dd3def02920d7ba446b2775e0f52616fa112b1] # # patch "res/forms/preferences.ui" # from [69162c4976189a8f3930ae77d23968e764934990] # to [ab0701e37aee557c3ea5b9ba8ba7f4979b70efa4] # # patch "src/util/Platform.cpp" # from [000c883c348069c523b39d3682aa2ac102978ce6] # to [ebe032e1b8f3f8971dfe9db035e31d5684b2d331] # # patch "src/util/Platform.h" # from [f24cbb3d1b1ff9947c7f564b57627f79d875b6dc] # to [7f8f1005a264dc6ab04856b6ff944d59897486eb] # # patch "src/view/WorkspaceWindow.cpp" # from [a23cfb2e04ee1dfa0b4a9198bd9ffb124d893ad1] # to [708547edc9a4d6db85f44c8ca6c96f677f19e141] # # patch "src/view/dialogs/Preferences.cpp" # from [9cc4653180d5ad4f5491c4ac5a43119d3d9c61d1] # to [9dd17b862ff966238899f496d8df42c90baca5f9] # # patch "src/view/dialogs/RevisionManifest.cpp" # from [2d81703aa99b208169d84eb9573bc262c8019ae0] # to [6316625d53d8349258ae940ddc1f5c8d5dc641ec] # # patch "src/vocab.h" # from [b4b58ec186846eedc156ee5bf76f3b6d757a58d0] # to [948198e53da18526486a8ce2b1b2e25ec0096999] # ============================================================ --- NEWS fedab0b6110210fd90efd17b7d63621b6449f7e5 +++ NEWS 30dd3def02920d7ba446b2775e0f52616fa112b1 @@ -11,6 +11,11 @@ - new: a panel to view and edit database variables (open it via View > Panels > Database Variables) - new: possibility to skip a new program version in the native dialog + - new: guitone now checks if a file is executable and if its extension is + included in a list of known precarious file formats before it greenly tries + to open it. If it find such a file, it prompts the user to verify his decision. + This check and the list of extensions can be configured in the Preferences + dialog. (closes FS#10) - improved: startup dialog slightly changed - now contains the possibility to edit the preferences, open recent databases and workspaces. Removed this functionality from the initialization phase of the application which was ============================================================ --- res/forms/preferences.ui 69162c4976189a8f3930ae77d23968e764934990 +++ res/forms/preferences.ui ab0701e37aee557c3ea5b9ba8ba7f4979b70efa4 @@ -5,8 +5,8 @@ 0 0 - 439 - 370 + 399 + 445 @@ -218,23 +218,8 @@ Miscellaneous - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - + + check for updates on application launch @@ -244,7 +229,7 @@ - + read workspace incrementally (faster for big directory trees) @@ -254,6 +239,36 @@ + + + + ask before opening executable files and files with the +following extensions (comma-separated list): + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + @@ -327,8 +342,8 @@ accept() - 278 - 253 + 494 + 563 96 @@ -343,8 +358,8 @@ reject() - 369 - 253 + 429 + 563 179 @@ -352,5 +367,21 @@ + + askFileOpen + toggled(bool) + askFileOpenExtensions + setEnabled(bool) + + + 93 + 469 + + + 126 + 496 + + + ============================================================ --- src/util/Platform.cpp 000c883c348069c523b39d3682aa2ac102978ce6 +++ src/util/Platform.cpp ebe032e1b8f3f8971dfe9db035e31d5684b2d331 @@ -16,10 +16,13 @@ * along with this program. If not, see . * ***************************************************************************/ +#include "vocab.h" #include "Platform.h" -#include "vocab.h" +#include "Settings.h" #include +#include +#include #ifdef Q_WS_X11 #include @@ -45,8 +48,66 @@ using namespace std; // It opens a file with the associated program on the specific platform // Original author: Chris Thompson // -bool Platform::openFile(const QString &filename) +bool Platform::openFile(const QString & filename, bool isSymlink /* = false */) { + // if this looks like a file, and not like an URL or something else + if (filename.indexOf(QRegExp("^\\w+:\\/\\/")) == -1) + { + QFileInfo fileInfo(filename); + if (!fileInfo.exists()) + { + QMessageBox::critical( + NULL, + QObject::tr("Error"), + QObject::tr("The file you're trying to open does not exist."), + QMessageBox::Ok, 0, 0 + ); + return false; + } + + if (fileInfo.isSymLink()) + { + if (isSymlink) + { + QMessageBox::critical( + NULL, + QObject::tr("Error"), + QObject::tr("No support for nested symlinks - " + "abort opening of %1").arg(filename), + QMessageBox::Ok, 0, 0 + ); + return false; + } + return openFile(fileInfo.symLinkTarget(), true); + } + + if (Settings::getBool("AskFileOpen", true)) + { + QString suffix = fileInfo.completeSuffix(); + QStringList harmfulSuffixes = + Settings::getString("AskFileOpenExt", ASK_OPEN_FILE_EXT) + .split(",", QString::SkipEmptyParts); + + if (fileInfo.isExecutable() || harmfulSuffixes.contains(suffix)) + { + QMessageBox::StandardButton btn = QMessageBox::question( + NULL, + QObject::tr("Attention"), + QObject::tr("The file '%1' you're trying to open is either " + "executable or included in the list of " + "precarious file formats - do you really " + "want to continue?").arg(filename), + QMessageBox::Yes | QMessageBox::No + ); + + if (btn == QMessageBox::No) + { + return false; + } + } + } + } + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool retval = false; @@ -111,7 +172,20 @@ bool Platform::openFile(const QString &f #endif QApplication::restoreOverrideCursor(); - return retval; + + if (!retval) + { + QMessageBox::critical( + NULL, + QObject::tr("Error"), + QObject::tr("Unable to open files on your platform - please " + "contact the author about this problem."), + QMessageBox::Ok, 0, 0 + ); + return false; + } + + return true; } // ============================================================ --- src/util/Platform.h f24cbb3d1b1ff9947c7f564b57627f79d875b6dc +++ src/util/Platform.h 7f8f1005a264dc6ab04856b6ff944d59897486eb @@ -27,11 +27,8 @@ public: /** * Opens a file or URL with the default registered handler * The URL is assumed to be valid. No security checks are performed. - * @arg QWidget *widget The parent to the browser. This is - * not used on some platforms. - * @arg const string &filename The URL to open. */ - static bool openFile(const QString & filename); + static bool openFile(const QString & filename, bool isSymlink = false); /** * Returns the name of the currently logged in user of the system */ ============================================================ --- src/view/WorkspaceWindow.cpp a23cfb2e04ee1dfa0b4a9198bd9ffb124d893ad1 +++ src/view/WorkspaceWindow.cpp 708547edc9a4d6db85f44c8ca6c96f677f19e141 @@ -279,28 +279,7 @@ void WorkspaceWindow::openFile(const QSt void WorkspaceWindow::openFile(const QString & filePath) { - QFileInfo file(workspacePath + "/" + filePath); - if (!file.exists()) - { - QMessageBox::critical( - this, - tr("Error"), - tr("The file you're trying to open does not exist."), - QMessageBox::Ok, 0, 0 - ); - return; - } - - if (!Platform::openFile(file.absoluteFilePath())) - { - QMessageBox::critical( - this, - tr("Error"), - tr("Unable to open files on your platform - please contact the " - "author about this problem."), - QMessageBox::Ok, 0, 0 - ); - } + Platform::openFile(workspacePath + "/" + filePath); } //! FIXME the dialog should query the data itself or retrieve from some global cache: ============================================================ --- src/view/dialogs/Preferences.cpp 9cc4653180d5ad4f5491c4ac5a43119d3d9c61d1 +++ src/view/dialogs/Preferences.cpp 9dd17b862ff966238899f496d8df42c90baca5f9 @@ -59,6 +59,15 @@ Preferences::Preferences(QWidget * paren Qt::Checked : Qt::Unchecked ); + askFileOpen->setCheckState( + Settings::getBool("AskFileOpen", true) ? + Qt::Checked : Qt::Unchecked + ); + + askFileOpenExtensions->setText( + Settings::getString("AskFileOpenExt", ASK_OPEN_FILE_EXT) + ); + readWorkspaceIncrementally->setCheckState( Settings::getBool("ReadWorkspaceIncrementally", false) ? Qt::Checked : Qt::Unchecked @@ -119,6 +128,8 @@ void Preferences::accept() DebugLog::setLogLevel(level); Settings::setBool("CheckForUpdates", checkForUpdates->isChecked()); + Settings::setBool("AskFileOpen", askFileOpen->isChecked()); + Settings::setString("AskFileOpenExt", askFileOpenExtensions->text()); if (Settings::getBool("ReadWorkspaceIncrementally", false) != readWorkspaceIncrementally->isChecked()) ============================================================ --- src/view/dialogs/RevisionManifest.cpp 2d81703aa99b208169d84eb9573bc262c8019ae0 +++ src/view/dialogs/RevisionManifest.cpp 6316625d53d8349258ae940ddc1f5c8d5dc641ec @@ -120,25 +120,17 @@ void RevisionManifest::openFile(const QM file.write(out.getOutput()); file.close(); - if (!Platform::openFile(tempPath)) + // if the action was successful, block execution (i.e. deleting of the + // temporary file) until the user tells us to continue + if (Platform::openFile(tempPath)) { - QMessageBox::critical( + QMessageBox::information( this, - tr("Error"), - tr("Unable to open files on your platform - please contact the " - "author about this problem.") + tr("Information"), + tr("Please close this message to remove the temporary file.") ); - - file.remove(); - return; } - QMessageBox::information( - this, - tr("Information"), - tr("Please close this message to remove the temporary file.") - ); - file.remove(); } ============================================================ --- src/vocab.h b4b58ec186846eedc156ee5bf76f3b6d757a58d0 +++ src/vocab.h 948198e53da18526486a8ce2b1b2e25ec0096999 @@ -100,5 +100,13 @@ typedef QString DatabaseFile; typedef QString WorkspacePath; typedef QString DatabaseFile; +// +// global constants +// +const QString ASK_OPEN_FILE_EXT = + "exe,com,bat,pif,hta,js,jse,inf,lnk,scr,wsc,wsf,wsh,vb,vbe,vbs,vbscript," // Windows + "sh,bsh,zsh,csh,ksh,py,pl,php,php3,php4,rb,ruby,awk,cgi,jar," // Unix/Linux/Mac + "app,pkg,dmg,scpt"; // Mac OS X + #endif