I'm using PYQt 5 on a Linux based system; Currently I'm in need to let the user insert a USB pen drive and save some file into it, or open some file from it (i.e., a software upgrade or a configuration). Showing a file dialog in which I can save or select a file seems a simple task to do.
But additionally I want the user to browse only into the USB pen drive (i.e. /mnt/myUSB/..) forward and back, but not to go back to the system directory and perform some potentially harmful operation.
Has anyone ever done this?
Doing this opens the dialog in /mnt, but don't prevent the user to browse back to /usr/local/bin or similar ' dangerous' path.
dialog = QtWidgets.QFileDialog(self)
dialog.setDirectory('/mnt')
dialog.setFileMode(QtWidgets.QFileDialog.AnyFile)
dialog.exec_()
It is possible by using some known features of QFileDialog and a few undocumented aspects.
There are two main requirements for this:
The first requirement is done by using
setProxyModel()with a QSortFilterProxyModel subclass that implementsfilterAcceptsRow():This will ensure that only paths that are inside the "base" directory will be shown.
The
self.base.startswith(path)part also ensures that all parent directories will be available to the view, which is required in order to access the base path itself: if any of the parent is filtered out, the base path will never be reached.This is how it can be used:
Now, this doesn't completely prevent the user to go up in the directory structure. In your specific case this may not be a big of an issue, since the parent directory of
/tmpis the root, which doesn't provide write access to standard users.But, in case the target directory is a child of another, writable directory, that may be an issue.
In order to limit that access, we can check whenever the current directory changes, and prevent the user to ever navigate the parent. To do so we:
accept()function so that it doesn't inadvertently accept entered paths manually typed in the file name field;The widgets are safely retrieved because their object names are hardcoded in the QFileDialog ui sources and are consistent along different Qt versions.