Qt: Import zips with illegal names

If a profile import contains illegal path names inside the zip
container, the illegal names are being filtered out and replaced with an
underscore

Change-Id: I4e1bc495156b8c1cd3f4dfca69604e880647f74e
Reviewed-on: https://code.wireshark.org/review/34220
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
Roland Knall 2019-08-09 14:39:55 +02:00
parent 9ac61952ec
commit 2a32808e50
4 changed files with 80 additions and 25 deletions

View File

@ -1095,6 +1095,14 @@ bool ProfileModel::acceptFile(QString fileName, int fileSize)
return true;
}
QString ProfileModel::cleanName(QString fileName)
{
QStringList parts = fileName.split(QDir::separator());
QString temp = parts[parts.count() - 1].replace( QRegExp( "[" + QRegExp::escape( illegalCharacters() ) + "]" ), QString( "_" ) );
temp = parts.join(QDir::separator());
return temp;
}
int ProfileModel::importProfilesFromZip(QString filename, int * skippedCnt, QStringList *result)
{
QTemporaryDir dir;
@ -1106,7 +1114,7 @@ int ProfileModel::importProfilesFromZip(QString filename, int * skippedCnt, QStr
int cnt = 0;
if ( dir.isValid() )
{
WireSharkZipHelper::unzip(filename, dir.path(), &ProfileModel::acceptFile);
WireSharkZipHelper::unzip(filename, dir.path(), &ProfileModel::acceptFile, &ProfileModel::cleanName);
cnt = importProfilesFromDir(dir.path(), skippedCnt, true, result);
}
@ -1225,18 +1233,24 @@ bool ProfileModel::clearImported(QString *msg)
return result;
}
QString ProfileModel::illegalCharacters()
{
#ifdef _WIN32
/* According to https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions */
return QString("<>:\"/\\|?*");
#else
return QDir::separator();
#endif
}
bool ProfileModel::checkNameValidity(QString name, QString *msg)
{
QString message;
bool invalid = false;
QString msgChars;
#ifdef _WIN32
/* According to https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions */
QString invalid_dir_chars = "<>:\"/\\|?*";
#else
QString invalid_dir_chars = QDir::separator();
#endif
QString invalid_dir_chars = illegalCharacters();
for ( int cnt = 0; cnt < invalid_dir_chars.length() && ! invalid; cnt++ )
{

View File

@ -119,6 +119,9 @@ public:
Q_SIGNALS:
void itemChanged(const QModelIndex &idx);
protected:
static QString illegalCharacters();
private:
QList<profile_def *> profiles_;
QStringList profile_files_;
@ -138,6 +141,7 @@ private:
#ifdef HAVE_MINIZIP
static bool acceptFile(QString fileName, int fileSize);
static QString cleanName(QString fileName);
#endif
QVariant dataDisplay(const QModelIndex & idx) const;

View File

@ -29,8 +29,9 @@
#include <QFile>
#include <QFileInfo>
#include <QDateTime>
#include <QMap>
bool WireSharkZipHelper::unzip(QString zipFile, QString directory, bool (*fileCheck)(QString, int))
bool WireSharkZipHelper::unzip(QString zipFile, QString directory, bool (*fileCheck)(QString, int), QString (*cleanName)(QString))
{
unzFile uf = Q_NULLPTR;
QFileInfo fi(zipFile);
@ -49,6 +50,8 @@ bool WireSharkZipHelper::unzip(QString zipFile, QString directory, bool (*fileCh
if (nmbr <= 0)
return false;
QMap<QString, QString> cleanPaths;
for ( unsigned int cnt = 0; cnt < nmbr; cnt++ )
{
char filename_inzip[256];
@ -59,10 +62,42 @@ bool WireSharkZipHelper::unzip(QString zipFile, QString directory, bool (*fileCh
{
QString fileInZip(filename_inzip);
int fileSize = static_cast<int>(file_info.uncompressed_size);
/* Sanity check for the filenames as well as the file size (max 512kb) */
if ( fileCheck && fileCheck(fileInZip, fileSize) && di.exists() )
/* Sanity check for the filen */
if ( fileInZip.length() == 0 || ( fileCheck && ! fileCheck(fileInZip, fileSize) ) )
continue;
if ( di.exists() )
{
QFileInfo fi(di.path() + QDir::separator() + fileInZip);
QString fullPath = di.path() + QDir::separator() + fileInZip;
QFileInfo fi(fullPath);
QString dirPath = fi.absolutePath();
/* clean up name from import. e.g. illegal characters in name */
if ( cleanName )
{
if ( ! cleanPaths.keys().contains(dirPath) )
{
QString tempPath = cleanName(dirPath);
int cnt = 1;
while ( QFile::exists(tempPath) )
{
tempPath = cleanName(dirPath) + QString::number(cnt);
cnt++;
}
cleanPaths.insert(dirPath, tempPath);
}
dirPath = cleanPaths[dirPath];
if ( dirPath.length() == 0 )
continue;
fi = QFileInfo(dirPath + QDir::separator() + fi.fileName());
fullPath = fi.absoluteFilePath();
}
if ( fullPath.length() == 0 )
continue;
QDir tP(fi.absolutePath());
if ( ! tP.exists() )
di.mkpath(fi.absolutePath());
@ -70,23 +105,25 @@ bool WireSharkZipHelper::unzip(QString zipFile, QString directory, bool (*fileCh
if ( fileInZip.contains("/") )
{
QString filePath = fi.absoluteFilePath();
err = unzOpenCurrentFile(uf);
if ( err == UNZ_OK )
QFile file(filePath);
if ( ! file.exists() )
{
char * buf = static_cast<char *>(malloc(IO_BUF_SIZE));
QFile file(filePath);
if ( file.open(QIODevice::WriteOnly) )
err = unzOpenCurrentFile(uf);
if ( err == UNZ_OK )
{
while ( ( err = unzReadCurrentFile(uf, buf, IO_BUF_SIZE) ) != UNZ_EOF )
file.write(buf, err);
char * buf = static_cast<char *>(malloc(IO_BUF_SIZE));
if ( file.open(QIODevice::WriteOnly) )
{
while ( ( err = unzReadCurrentFile(uf, buf, IO_BUF_SIZE) ) != UNZ_EOF )
file.write(buf, err);
file.close();
file.close();
}
unzCloseCurrentFile(uf);
free(buf);
files++;
}
unzCloseCurrentFile(uf);
free(buf);
files++;
}
}
}

View File

@ -24,7 +24,7 @@ class WireSharkZipHelper
{
public:
static bool zip(QString zipFile, QStringList files, QString relativeTo = QString());
static bool unzip(QString zipFile, QString directory, bool (*fileCheck)(QString fileName, int fileSize) );
static bool unzip(QString zipFile, QString directory, bool (*fileCheck)(QString fileName, int fileSize) = Q_NULLPTR, QString (*cleanName)(QString name) = Q_NULLPTR );
protected:
static void addFileToZip(zipFile zf, QString filepath, QString fileInZip);