Skip to content

Commit

Permalink
Proper symlink handling for layers and projects
Browse files Browse the repository at this point in the history
- Prevent QGIS from silently resolving symlinks in qgspathresolver.cpp
- Respect symlink for “%_attachments.zip” companion file in .qgs project
- Add new tests to verify good behaviours in common symlink scenarios
- Fix formatting

Fixes #60135
  • Loading branch information
vsydorov committed Jan 20, 2025
1 parent b601cc7 commit 758d093
Show file tree
Hide file tree
Showing 3 changed files with 389 additions and 7 deletions.
17 changes: 13 additions & 4 deletions src/core/qgsarchive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,18 @@ bool QgsArchive::zip( const QString &filename )
return false;
}

QString target {filename};

// remove existing zip file
if ( QFile::exists( filename ) )
QFile::remove( filename );
if ( QFile::exists( target ) )
{
// If symlink -> we want to write to its target instead
const QFileInfo targetFileInfo( target );
target = targetFileInfo.canonicalFilePath();
// If target still exists, remove (might not exist if was a dangling symlink)
if ( QFile::exists( target ) )
QFile::remove( target );
}

#ifdef Q_OS_WIN
// Clear temporary flag (see GH #32118)
Expand All @@ -94,9 +103,9 @@ bool QgsArchive::zip( const QString &filename )
#endif // Q_OS_WIN

// save zip archive
if ( ! tmpFile.rename( filename ) )
if ( ! tmpFile.rename( target ) )
{
const QString err = QObject::tr( "Unable to save zip file '%1'" ).arg( filename );
const QString err = QObject::tr( "Unable to save zip file '%1'" ).arg( target );
QgsMessageLog::logMessage( err, QStringLiteral( "QgsArchive" ) );
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/qgspathresolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ QString QgsPathResolver::readPath( const QString &f ) const
}
else
{
return vsiPrefix + fi.canonicalFilePath();
return vsiPrefix + QDir::cleanPath( fi.absoluteFilePath() );
}
}

Expand Down Expand Up @@ -291,7 +291,8 @@ QString QgsPathResolver::writePath( const QString &s ) const

const QFileInfo srcFileInfo( srcPath );
if ( srcFileInfo.exists() )
srcPath = srcFileInfo.canonicalFilePath();
// Do NOT resolve symlinks, but do remove '..' and '.'
srcPath = QDir::cleanPath( srcFileInfo.absoluteFilePath() );

// if this is a VSIFILE, remove the VSI prefix and append to final result
const QString vsiPrefix = QgsGdalUtils::vsiPrefixForPath( src );
Expand Down
Loading

0 comments on commit 758d093

Please sign in to comment.