mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Ensure filenames are valid UTF-8 on Unix
On Unix, the encoding of filenames is unspecified, although UTF-8 is likely used in most cases. Detecting and converting from several possible encodings to UTF-8 would be too much effort, considering that most systems already use UTF-8 per default. Therefore, any filenames which are not valid UTF-8 will be ignored when listing directories with `fs_listdir(_fileinfo)`, `fs_storage_path` will fail if the storage location is not valid UTF-8 and `fs_getcwd` will fail if the current working directory is not valid UTF-8. Paths specified in `storage.cfg` must also be valid UTF-8. On Windows, we already ensure that all filenames are converted to UTF-8.
This commit is contained in:
parent
55098cd313
commit
5c7bb58457
|
@ -2111,7 +2111,6 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
|||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
/* add all the entries */
|
||||
do
|
||||
{
|
||||
const std::string current_entry = windows_wide_to_utf8(finddata.cFileName);
|
||||
|
@ -2121,26 +2120,29 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
|||
|
||||
FindClose(handle);
|
||||
#else
|
||||
struct dirent *entry;
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
int length;
|
||||
DIR *d = opendir(dir);
|
||||
|
||||
if(!d)
|
||||
DIR *dir_handle = opendir(dir);
|
||||
if(dir_handle == nullptr)
|
||||
return;
|
||||
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
||||
while((entry = readdir(d)) != NULL)
|
||||
size_t length = str_length(buffer);
|
||||
while(true)
|
||||
{
|
||||
str_copy(buffer + length, entry->d_name, (int)sizeof(buffer) - length);
|
||||
struct dirent *entry = readdir(dir_handle);
|
||||
if(entry == nullptr)
|
||||
break;
|
||||
if(!str_utf8_check(entry->d_name))
|
||||
{
|
||||
log_error("filesystem", "ERROR: file/folder name containing invalid UTF-8 found in folder '%s'", dir);
|
||||
continue;
|
||||
}
|
||||
str_copy(buffer + length, entry->d_name, sizeof(buffer) - length);
|
||||
if(cb(entry->d_name, fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
}
|
||||
|
||||
/* close the directory and return */
|
||||
closedir(d);
|
||||
closedir(dir_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2156,7 +2158,6 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
|||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
/* add all the entries */
|
||||
do
|
||||
{
|
||||
const std::string current_entry = windows_wide_to_utf8(finddata.cFileName);
|
||||
|
@ -2172,25 +2173,29 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
|||
|
||||
FindClose(handle);
|
||||
#else
|
||||
struct dirent *entry;
|
||||
time_t created = -1, modified = -1;
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
int length;
|
||||
DIR *d = opendir(dir);
|
||||
|
||||
if(!d)
|
||||
DIR *dir_handle = opendir(dir);
|
||||
if(dir_handle == nullptr)
|
||||
return;
|
||||
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
size_t length = str_length(buffer);
|
||||
|
||||
while((entry = readdir(d)) != NULL)
|
||||
while(true)
|
||||
{
|
||||
CFsFileInfo info;
|
||||
|
||||
str_copy(buffer + length, entry->d_name, (int)sizeof(buffer) - length);
|
||||
struct dirent *entry = readdir(dir_handle);
|
||||
if(entry == nullptr)
|
||||
break;
|
||||
if(!str_utf8_check(entry->d_name))
|
||||
{
|
||||
log_error("filesystem", "ERROR: file/folder name containing invalid UTF-8 found in folder '%s'", dir);
|
||||
continue;
|
||||
}
|
||||
str_copy(buffer + length, entry->d_name, sizeof(buffer) - length);
|
||||
time_t created = -1, modified = -1;
|
||||
fs_file_time(buffer, &created, &modified);
|
||||
|
||||
CFsFileInfo info;
|
||||
info.m_pName = entry->d_name;
|
||||
info.m_TimeCreated = created;
|
||||
info.m_TimeModified = modified;
|
||||
|
@ -2199,8 +2204,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
|||
break;
|
||||
}
|
||||
|
||||
/* close the directory and return */
|
||||
closedir(d);
|
||||
closedir(dir_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2209,17 +2213,27 @@ int fs_storage_path(const char *appname, char *path, int max)
|
|||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
WCHAR *wide_home = _wgetenv(L"APPDATA");
|
||||
if(!wide_home)
|
||||
{
|
||||
path[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
const std::string home = windows_wide_to_utf8(wide_home);
|
||||
str_format(path, max, "%s/%s", home.c_str(), appname);
|
||||
return 0;
|
||||
#elif defined(CONF_PLATFORM_ANDROID)
|
||||
// just use the data directory
|
||||
return -1;
|
||||
#else
|
||||
char *home = getenv("HOME");
|
||||
if(!home)
|
||||
{
|
||||
path[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!str_utf8_check(home))
|
||||
{
|
||||
log_error("filesystem", "ERROR: the HOME environment variable contains invalid UTF-8");
|
||||
path[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(CONF_PLATFORM_HAIKU)
|
||||
str_format(path, max, "%s/config/settings/%s", home, appname);
|
||||
|
@ -2235,7 +2249,15 @@ int fs_storage_path(const char *appname, char *path, int max)
|
|||
{
|
||||
char *data_home = getenv("XDG_DATA_HOME");
|
||||
if(data_home)
|
||||
{
|
||||
if(!str_utf8_check(data_home))
|
||||
{
|
||||
log_error("filesystem", "ERROR: the XDG_DATA_HOME environment variable contains invalid UTF-8");
|
||||
path[0] = '\0';
|
||||
return -1;
|
||||
}
|
||||
str_format(path, max, "%s/%s", data_home, appname);
|
||||
}
|
||||
else
|
||||
str_format(path, max, "%s/.local/share/%s", home, appname);
|
||||
}
|
||||
|
@ -2366,13 +2388,20 @@ char *fs_getcwd(char *buffer, int buffer_size)
|
|||
const DWORD LastError = GetLastError();
|
||||
const std::string ErrorMsg = windows_format_system_message(LastError);
|
||||
dbg_msg("filesystem", "GetCurrentDirectoryW failed: %ld %s", LastError, ErrorMsg.c_str());
|
||||
buffer[0] = '\0';
|
||||
return nullptr;
|
||||
}
|
||||
const std::string current_dir = windows_wide_to_utf8(wide_current_dir.c_str());
|
||||
str_copy(buffer, current_dir.c_str(), buffer_size);
|
||||
return buffer;
|
||||
#else
|
||||
return getcwd(buffer, buffer_size);
|
||||
char *result = getcwd(buffer, buffer_size);
|
||||
if(result == nullptr || !str_utf8_check(result))
|
||||
{
|
||||
buffer[0] = '\0';
|
||||
return nullptr;
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include <base/hash_ctxt.h>
|
||||
#include <base/log.h>
|
||||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
|
||||
|
@ -30,21 +31,31 @@ public:
|
|||
{
|
||||
mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths));
|
||||
m_NumPaths = 0;
|
||||
m_aDatadir[0] = 0;
|
||||
m_aUserdir[0] = 0;
|
||||
m_aDatadir[0] = '\0';
|
||||
m_aUserdir[0] = '\0';
|
||||
m_aCurrentdir[0] = '\0';
|
||||
m_aBinarydir[0] = '\0';
|
||||
}
|
||||
|
||||
int Init(int StorageType, int NumArgs, const char **ppArguments)
|
||||
{
|
||||
// get userdir
|
||||
#if !defined(CONF_PLATFORM_ANDROID)
|
||||
// get userdir, just use data directory on android
|
||||
char aFallbackUserdir[IO_MAX_PATH_LENGTH];
|
||||
fs_storage_path("DDNet", m_aUserdir, sizeof(m_aUserdir));
|
||||
fs_storage_path("Teeworlds", aFallbackUserdir, sizeof(aFallbackUserdir));
|
||||
if(fs_storage_path("DDNet", m_aUserdir, sizeof(m_aUserdir)))
|
||||
{
|
||||
log_error("storage", "could not determine user directory");
|
||||
}
|
||||
if(fs_storage_path("Teeworlds", aFallbackUserdir, sizeof(aFallbackUserdir)))
|
||||
{
|
||||
log_error("storage", "could not determine fallback user directory");
|
||||
}
|
||||
|
||||
if(!fs_is_dir(m_aUserdir) && fs_is_dir(aFallbackUserdir))
|
||||
if((m_aUserdir[0] == '\0' || !fs_is_dir(m_aUserdir)) && aFallbackUserdir[0] != '\0' && fs_is_dir(aFallbackUserdir))
|
||||
{
|
||||
str_copy(m_aUserdir, aFallbackUserdir);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get datadir
|
||||
FindDatadir(ppArguments[0]);
|
||||
|
@ -54,7 +65,9 @@ public:
|
|||
|
||||
// get currentdir
|
||||
if(!fs_getcwd(m_aCurrentdir, sizeof(m_aCurrentdir)))
|
||||
m_aCurrentdir[0] = 0;
|
||||
{
|
||||
log_error("storage", "could not determine current directory");
|
||||
}
|
||||
|
||||
// load paths from storage.cfg
|
||||
LoadPaths(ppArguments[0]);
|
||||
|
@ -161,12 +174,12 @@ public:
|
|||
{
|
||||
if(!pPath[0])
|
||||
{
|
||||
dbg_msg("storage", "cannot add empty path");
|
||||
log_error("storage", "cannot add empty path");
|
||||
return;
|
||||
}
|
||||
if(m_NumPaths >= MAX_PATHS)
|
||||
{
|
||||
dbg_msg("storage", "cannot add path '%s', the maximum number of paths is %d", pPath, MAX_PATHS);
|
||||
log_error("storage", "cannot add path '%s', the maximum number of paths is %d", pPath, MAX_PATHS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -177,6 +190,10 @@ public:
|
|||
str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserdir);
|
||||
dbg_msg("storage", "added path '$USERDIR' ('%s')", m_aUserdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("storage", "cannot add path '$USERDIR' because it could not be determined");
|
||||
}
|
||||
}
|
||||
else if(!str_comp(pPath, "$DATADIR"))
|
||||
{
|
||||
|
@ -185,13 +202,17 @@ public:
|
|||
str_copy(m_aaStoragePaths[m_NumPaths++], m_aDatadir);
|
||||
dbg_msg("storage", "added path '$DATADIR' ('%s')", m_aDatadir);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("storage", "cannot add path '$DATADIR' because it could not be determined");
|
||||
}
|
||||
}
|
||||
else if(!str_comp(pPath, "$CURRENTDIR"))
|
||||
{
|
||||
m_aaStoragePaths[m_NumPaths++][0] = 0;
|
||||
m_aaStoragePaths[m_NumPaths++][0] = '\0';
|
||||
dbg_msg("storage", "added path '$CURRENTDIR' ('%s')", m_aCurrentdir);
|
||||
}
|
||||
else
|
||||
else if(str_utf8_check(pPath))
|
||||
{
|
||||
if(fs_is_dir(pPath))
|
||||
{
|
||||
|
@ -200,9 +221,13 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
dbg_msg("storage", "cannot add path '%s', which is not a directory", pPath);
|
||||
log_error("storage", "cannot add path '%s', which is not a directory", pPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("storage", "cannot add path containing invalid UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
void FindDatadir(const char *pArgv0)
|
||||
|
@ -817,8 +842,6 @@ public:
|
|||
str_append(pBuffer, "/", BufferSize);
|
||||
str_append(pBuffer, aBinaryPath, BufferSize);
|
||||
}
|
||||
else
|
||||
pBuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
str_copy(pBuffer, aBinaryPath, BufferSize);
|
||||
|
|
Loading…
Reference in a new issue