Commit fc9cce2b authored by Stefano Pettini's avatar Stefano Pettini
Browse files

VFAT-safe file and directory names cannot end with dot

This adds special handling of trailing dots to vfatPath(),
that are replaced with '_'. This doesn't affect '.' and '..'.

  ../Music/R.E.M./Monster -> ../Music/R.E.M_/Monster

Unit tests updated, minor bugs when vfatPath() is invoked
with a PathSeparatorBehaviour not matching the system
detected by improving unit tests and fixed.

BUG: 388465
parent 49c6c316
......@@ -335,8 +335,7 @@ namespace Amarok
{
QString s = path;
if( behaviour == AutoBehaviour )
behaviour = ( QDir::separator() == '/' ) ? UnixBehaviour : WindowsBehaviour;
QChar separator = ( behaviour == AutoBehaviour ) ? QDir::separator() : ( behaviour == UnixBehaviour ) ? '/' : '\\';
if( behaviour == UnixBehaviour ) // we are on *nix, \ is a valid character in file or directory names, NOT the dir separator
s.replace( '\\', '_' );
......@@ -390,22 +389,35 @@ namespace Amarok
/* max path length of Windows API */
s = s.left(255);
/* whitespace at the end of folder/file names or extensions are bad */
/* whitespace or dot at the end of folder/file names or extensions are bad */
len = s.length();
if( s[len-1] == ' ' )
s[len-1] = '_';
int extensionIndex = s.lastIndexOf( '.' ); // correct trailing spaces in file name itself
if( ( s.length() > 1 ) && ( extensionIndex > 0 ) )
if( s.at( extensionIndex - 1 ) == ' ' )
s[extensionIndex - 1] = '_';
if( s.at(len - 1) == ' ' || s.at(len - 1) == '.' )
s[len - 1] = '_';
for( int i = 1; i < s.length(); i++ ) // correct trailing whitespace in folder names
{
if( ( s.at( i ) == QDir::separator() ) && ( s.at( i - 1 ) == ' ' ) )
if( s.at(i) == separator && s.at(i - 1) == ' ' )
s[i - 1] = '_';
}
for( int i = 1; i < s.length(); i++ ) // correct trailing dot in folder names, excluding . and ..
{
if( s.at(i) == separator
&& s.at(i - 1) == '.'
&& !( i == 1 // ./any
|| ( i == 2 && s.at(i - 2) == '.' ) // ../any
|| ( i >= 2 && s.at(i - 2) == separator ) // any/./any
|| ( i >= 3 && s.at(i - 3) == separator && s.at(i - 2) == '.' ) // any/../any
) )
s[i - 1] = '_';
}
/* correct trailing spaces in file name itself, not needed for dots */
int extensionIndex = s.lastIndexOf( '.' );
if( ( s.length() > 1 ) && ( extensionIndex > 0 ) )
if( s.at(extensionIndex - 1) == ' ' )
s[extensionIndex - 1] = '_';
return s;
}
......
......@@ -26,6 +26,7 @@
#include <QtCore/QDateTime>
#include <qtest_kde.h>
#include <iostream>
QTEST_KDEMAIN_CORE( TestAmarok )
......@@ -243,17 +244,48 @@ void TestAmarok::testVfatPath()
QCOMPARE( Amarok::vfatPath( "test .ext " ), QString( "test _.ext _" ) );
QCOMPARE( Amarok::vfatPath( " test .ext " ), QString( " test _.ext _" ) ); // yes, really!
#ifdef Q_WS_WIN // interpret / as part of the name, not directory separator
QCOMPARE( Amarok::vfatPath( "\\some\\folder \\" ), QString( "\\some\\folder _\\" ) );
QCOMPARE( Amarok::vfatPath( "\\some \\folder \\" ), QString( "\\some _\\folder _\\" ) );
QCOMPARE( Amarok::vfatPath( "\\...some \\ev il \\folders...\\" ), QString( "\\...some _\\ev il _\\folders...\\" ) );
QCOMPARE( Amarok::vfatPath( "\\some\\fol/der \\" ), QString( "\\some\\fol_der _\\" ) );
#else // interpret \ as part of the name, not directory separator
QCOMPARE( Amarok::vfatPath( "/some/folder /" ), QString( "/some/folder _/" ) );
QCOMPARE( Amarok::vfatPath( "/some /folder /" ), QString( "/some _/folder _/" ) );
QCOMPARE( Amarok::vfatPath( "/...some /ev il /folders.../" ), QString( "/...some _/ev il _/folders.../" ) );
QCOMPARE( Amarok::vfatPath( "/some/fol\\der /" ), QString( "/some/fol_der _/" ) );
#endif
/* trailing dot in directory and file names are unsupported are being ignored (!) */
QCOMPARE( Amarok::vfatPath( "test..." ), QString( "test.._" ) );
QCOMPARE( Amarok::vfatPath( "...test..." ), QString( "...test.._" ) );
QCOMPARE( Amarok::vfatPath( "test.ext..." ), QString( "test.ext.._" ) );
QCOMPARE( Amarok::vfatPath( "test....ext..." ), QString( "test....ext.._" ) );
QCOMPARE( Amarok::vfatPath( "...test....ext..." ), QString( "...test....ext.._" ) );
/* more tests of trailing spaces and dot in directory names for Windows */
QCOMPARE( Amarok::vfatPath( "\\some\\folder \\", Amarok::WindowsBehaviour ), QString( "\\some\\folder _\\" ) );
QCOMPARE( Amarok::vfatPath( "\\some \\folder \\", Amarok::WindowsBehaviour ), QString( "\\some _\\folder _\\" ) );
QCOMPARE( Amarok::vfatPath( "\\...some \\ev il \\folders...\\", Amarok::WindowsBehaviour ), QString( "\\...some _\\ev il _\\folders.._\\" ) );
QCOMPARE( Amarok::vfatPath( "\\some\\fol/der \\", Amarok::WindowsBehaviour ), QString( "\\some\\fol_der _\\" ) );
QCOMPARE( Amarok::vfatPath( "\\some...\\folder...\\", Amarok::WindowsBehaviour ), QString( "\\some.._\\folder.._\\" ) );
QCOMPARE( Amarok::vfatPath( "\\some\\fol/der...\\", Amarok::WindowsBehaviour ), QString( "\\some\\fol_der.._\\" ) );
QCOMPARE( Amarok::vfatPath( "\\so..me.\\folder .\\", Amarok::WindowsBehaviour ), QString( "\\so..me_\\folder _\\" ) );
QCOMPARE( Amarok::vfatPath( ".\\any", Amarok::WindowsBehaviour ), QString( ".\\any" ) );
QCOMPARE( Amarok::vfatPath( "..\\any", Amarok::WindowsBehaviour ), QString( "..\\any" ) );
QCOMPARE( Amarok::vfatPath( "...\\any", Amarok::WindowsBehaviour ), QString( ".._\\any" ) );
QCOMPARE( Amarok::vfatPath( "a..\\any", Amarok::WindowsBehaviour ), QString( "a._\\any" ) );
QCOMPARE( Amarok::vfatPath( "any\\.\\any.", Amarok::WindowsBehaviour ), QString( "any\\.\\any_" ) );
QCOMPARE( Amarok::vfatPath( "any\\..\\any ", Amarok::WindowsBehaviour ), QString( "any\\..\\any_" ) );
QCOMPARE( Amarok::vfatPath( "any.\\...\\any", Amarok::WindowsBehaviour ), QString( "any_\\.._\\any" ) );
QCOMPARE( Amarok::vfatPath( "any \\a..\\any", Amarok::WindowsBehaviour ), QString( "any_\\a._\\any" ) );
QCOMPARE( Amarok::vfatPath( "Music\\R.E.M.\\Automatic for the people", Amarok::WindowsBehaviour ), QString( "Music\\R.E.M_\\Automatic for the people" ) );
/* more tests of trailing spaces and dot in directory names for Unix */
QCOMPARE( Amarok::vfatPath( "/some/folder /", Amarok::UnixBehaviour ), QString( "/some/folder _/" ) );
QCOMPARE( Amarok::vfatPath( "/some /folder /", Amarok::UnixBehaviour ), QString( "/some _/folder _/" ) );
QCOMPARE( Amarok::vfatPath( "/...some /ev il /folders.../", Amarok::UnixBehaviour ), QString( "/...some _/ev il _/folders.._/" ) );
QCOMPARE( Amarok::vfatPath( "/some/fol\\der /", Amarok::UnixBehaviour ), QString( "/some/fol_der _/" ) );
QCOMPARE( Amarok::vfatPath( "/some.../folder.../", Amarok::UnixBehaviour ), QString( "/some.._/folder.._/" ) );
QCOMPARE( Amarok::vfatPath( "/some/fol\\der.../", Amarok::UnixBehaviour ), QString( "/some/fol_der.._/" ) );
QCOMPARE( Amarok::vfatPath( "/so..me./folder ./", Amarok::UnixBehaviour ), QString( "/so..me_/folder _/" ) );
QCOMPARE( Amarok::vfatPath( "./any", Amarok::UnixBehaviour ), QString( "./any" ) );
QCOMPARE( Amarok::vfatPath( "../any", Amarok::UnixBehaviour ), QString( "../any" ) );
QCOMPARE( Amarok::vfatPath( ".../any", Amarok::UnixBehaviour ), QString( ".._/any" ) );
QCOMPARE( Amarok::vfatPath( "a../any", Amarok::UnixBehaviour ), QString( "a._/any" ) );
QCOMPARE( Amarok::vfatPath( "any/./any.", Amarok::UnixBehaviour ), QString( "any/./any_" ) );
QCOMPARE( Amarok::vfatPath( "any/../any ", Amarok::UnixBehaviour ), QString( "any/../any_" ) );
QCOMPARE( Amarok::vfatPath( "any./.../any", Amarok::UnixBehaviour ), QString( "any_/.._/any" ) );
QCOMPARE( Amarok::vfatPath( "any /a../any", Amarok::UnixBehaviour ), QString( "any_/a._/any" ) );
QCOMPARE( Amarok::vfatPath( "Music/R.E.M./Automatic for the people", Amarok::UnixBehaviour ), QString( "Music/R.E.M_/Automatic for the people" ) );
/* Stepping deeper into M$ hell: reserved device names
* See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment