Skip to content

Expose FileUtils.listDir to QML plugins#7442

Open
Ipickedausername wants to merge 7 commits into
opengisch:masterfrom
Ipickedausername:feature/plugin-import-project-from-url
Open

Expose FileUtils.listDir to QML plugins#7442
Ipickedausername wants to merge 7 commits into
opengisch:masterfrom
Ipickedausername:feature/plugin-import-project-from-url

Conversation

@Ipickedausername

@Ipickedausername Ipickedausername commented May 17, 2026

Copy link
Copy Markdown

Edit:
QField plugins run in a sandboxed QML/JS engine and only have access to APIs explicitly exposed by QField. I would like to add a way to display project archives in Imported Projects/

Changes
FileUtils — adds listDir(path, filter):

  • Lists directory entries matching an optional wildcard filter (e.g. "oktos_*")
  • Returns entry names only (not full paths)
  • Restricted to paths within applicationDirectory() — calls outside this boundary return an empty list with a warning

Tests — adds a ListDir section to test_fileutils.cpp verifying correct filtering, empty results for non-existent directories, and rejection of paths outside applicationDirectory()

PlatformUtilities::removeDir initially included in this PR has been dropped following feedback.

PR made with the help of LLM's

@qfield-fairy

qfield-fairy commented May 17, 2026

Copy link
Copy Markdown
Collaborator

🍎 MacOS DMG universal builds

Download a MacOS DMG universal build of this PR for testing.
(Built from commit 751e27d)

🪟 Windows builds

Download a Windows build of this PR for testing and for arm64.

(Built from commit 6291819)

📱 Android builds

Download an Android arm64 build of this PR for testing.
(Built from commit 6291819)

Other Android architectures

@Ipickedausername

Copy link
Copy Markdown
Author

This is an experiment, I was hoping to get an APK for tests on Android.

@nirvn

nirvn commented May 17, 2026

Copy link
Copy Markdown
Member

@Ipickedausername , I've restarted the Android CI, there was an unrelated issue getting a cmake package. If your code compiles you should get APKs.

FYI, I would be a big -1 on unrestrained access to listing and deleting folders on people's devices and computers. I would suggest that you find a way to script your plugin around the current storage access limitations we have in place.

That said, a file/directory listing function within these confines would be most welcome :)

@Ipickedausername

Copy link
Copy Markdown
Author

FYI, I would be a big -1 on unrestrained access to listing and deleting folders on people's devices and computers. I would suggest that you find a way to script your plugin around the current storage access limitations we have in place.

Yes, I was expecting that answer 🙂
In my workflow, I currently delete a folder containing files shared across several projects when updating them. But I understand the concern, and I’ll see how I can adapt the plugin to work directly on the files instead of relying on broader folder deletion access.

@Ipickedausername Ipickedausername changed the title Expose FileUtils.listDir and PlatformUtilities.removeDir to QML plugins Expose FileUtils.listDir to QML plugins May 17, 2026
@Ipickedausername

Copy link
Copy Markdown
Author

Hi !
I sent you @nirvn an e-mail regarding te implementations I would need to pull in order to work on my side.
I hope you will have a moment to check and tell me if I can work on it or if you and other devs might oppose to it.
Thank you !

@nirvn nirvn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ipickedausername , sorry for the delay, added some hints on how to move forward here.

Comment on lines +1015 to +1023
const QString appDir = QDir::cleanPath( PlatformUtilities::instance()->applicationDirectory() );
const QString appDirParent = QDir::cleanPath( appDir + "/.." );
const QString cleanPath = QDir::cleanPath( path );

if ( !cleanPath.startsWith( appDirParent ) )
{
qWarning() << QStringLiteral( "Security: listDir called outside allowed directories: %1" ).arg( path );
return QStringList();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not quite do it. I think what we'd want to do here is to create a isWithinApplicationDirectories function that mimics isWithinProjectDirectory.

Also, it should check for all application directories.

Comment on lines +1025 to +1026
if ( !dir.exists() )
return QStringList();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Styling wise, we try our best not to introduce conditional blocks without { }, even if it's a single line.

Comment thread test/test_fileutils.cpp
Comment on lines +419 to +433
SECTION( "ListDir" )
{
// listDir is restricted to applicationDirectory() — path outside returns empty list
QStringList outside = FileUtils::listDir( QDir::tempPath() );
REQUIRE( outside.isEmpty() );

// Within applicationDirectory() — returns entries
QString appDir = PlatformUtilities::instance()->applicationDirectory();
QDir dir( appDir );
if ( dir.exists() )
{
QStringList all = FileUtils::listDir( appDir );
REQUIRE( all.size() >= 0 ); // valid directory
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section fails to compile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants