mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge pull request #7481 from Robyt3/Storage-UTF8-Check
Ensure filenames are valid UTF-8 on Unix
This commit is contained in:
commit
46679deddc
|
@ -2111,7 +2111,6 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
||||||
if(handle == INVALID_HANDLE_VALUE)
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* add all the entries */
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
const std::string current_entry = windows_wide_to_utf8(finddata.cFileName);
|
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);
|
FindClose(handle);
|
||||||
#else
|
#else
|
||||||
struct dirent *entry;
|
DIR *dir_handle = opendir(dir);
|
||||||
char buffer[IO_MAX_PATH_LENGTH];
|
if(dir_handle == nullptr)
|
||||||
int length;
|
|
||||||
DIR *d = opendir(dir);
|
|
||||||
|
|
||||||
if(!d)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
char buffer[IO_MAX_PATH_LENGTH];
|
||||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||||
length = str_length(buffer);
|
size_t length = str_length(buffer);
|
||||||
|
while(true)
|
||||||
while((entry = readdir(d)) != NULL)
|
|
||||||
{
|
{
|
||||||
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))
|
if(cb(entry->d_name, fs_is_dir(buffer), type, user))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close the directory and return */
|
closedir(dir_handle);
|
||||||
closedir(d);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2156,7 +2158,6 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
||||||
if(handle == INVALID_HANDLE_VALUE)
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* add all the entries */
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
const std::string current_entry = windows_wide_to_utf8(finddata.cFileName);
|
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);
|
FindClose(handle);
|
||||||
#else
|
#else
|
||||||
struct dirent *entry;
|
DIR *dir_handle = opendir(dir);
|
||||||
time_t created = -1, modified = -1;
|
if(dir_handle == nullptr)
|
||||||
char buffer[IO_MAX_PATH_LENGTH];
|
|
||||||
int length;
|
|
||||||
DIR *d = opendir(dir);
|
|
||||||
|
|
||||||
if(!d)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
char buffer[IO_MAX_PATH_LENGTH];
|
||||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
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;
|
struct dirent *entry = readdir(dir_handle);
|
||||||
|
if(entry == nullptr)
|
||||||
str_copy(buffer + length, entry->d_name, (int)sizeof(buffer) - length);
|
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);
|
fs_file_time(buffer, &created, &modified);
|
||||||
|
|
||||||
|
CFsFileInfo info;
|
||||||
info.m_pName = entry->d_name;
|
info.m_pName = entry->d_name;
|
||||||
info.m_TimeCreated = created;
|
info.m_TimeCreated = created;
|
||||||
info.m_TimeModified = modified;
|
info.m_TimeModified = modified;
|
||||||
|
@ -2199,8 +2204,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close the directory and return */
|
closedir(dir_handle);
|
||||||
closedir(d);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2209,17 +2213,27 @@ int fs_storage_path(const char *appname, char *path, int max)
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR *wide_home = _wgetenv(L"APPDATA");
|
WCHAR *wide_home = _wgetenv(L"APPDATA");
|
||||||
if(!wide_home)
|
if(!wide_home)
|
||||||
|
{
|
||||||
|
path[0] = '\0';
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
const std::string home = windows_wide_to_utf8(wide_home);
|
const std::string home = windows_wide_to_utf8(wide_home);
|
||||||
str_format(path, max, "%s/%s", home.c_str(), appname);
|
str_format(path, max, "%s/%s", home.c_str(), appname);
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(CONF_PLATFORM_ANDROID)
|
|
||||||
// just use the data directory
|
|
||||||
return -1;
|
|
||||||
#else
|
#else
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if(!home)
|
if(!home)
|
||||||
|
{
|
||||||
|
path[0] = '\0';
|
||||||
return -1;
|
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)
|
#if defined(CONF_PLATFORM_HAIKU)
|
||||||
str_format(path, max, "%s/config/settings/%s", home, appname);
|
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");
|
char *data_home = getenv("XDG_DATA_HOME");
|
||||||
if(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);
|
str_format(path, max, "%s/%s", data_home, appname);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
str_format(path, max, "%s/.local/share/%s", home, appname);
|
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 DWORD LastError = GetLastError();
|
||||||
const std::string ErrorMsg = windows_format_system_message(LastError);
|
const std::string ErrorMsg = windows_format_system_message(LastError);
|
||||||
dbg_msg("filesystem", "GetCurrentDirectoryW failed: %ld %s", LastError, ErrorMsg.c_str());
|
dbg_msg("filesystem", "GetCurrentDirectoryW failed: %ld %s", LastError, ErrorMsg.c_str());
|
||||||
|
buffer[0] = '\0';
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const std::string current_dir = windows_wide_to_utf8(wide_current_dir.c_str());
|
const std::string current_dir = windows_wide_to_utf8(wide_current_dir.c_str());
|
||||||
str_copy(buffer, current_dir.c_str(), buffer_size);
|
str_copy(buffer, current_dir.c_str(), buffer_size);
|
||||||
return buffer;
|
return buffer;
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
/* (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. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#include <base/hash_ctxt.h>
|
#include <base/hash_ctxt.h>
|
||||||
|
#include <base/log.h>
|
||||||
#include <base/math.h>
|
#include <base/math.h>
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
|
@ -30,21 +31,31 @@ public:
|
||||||
{
|
{
|
||||||
mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths));
|
mem_zero(m_aaStoragePaths, sizeof(m_aaStoragePaths));
|
||||||
m_NumPaths = 0;
|
m_NumPaths = 0;
|
||||||
m_aDatadir[0] = 0;
|
m_aDatadir[0] = '\0';
|
||||||
m_aUserdir[0] = 0;
|
m_aUserdir[0] = '\0';
|
||||||
|
m_aCurrentdir[0] = '\0';
|
||||||
|
m_aBinarydir[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int Init(int StorageType, int NumArgs, const char **ppArguments)
|
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];
|
char aFallbackUserdir[IO_MAX_PATH_LENGTH];
|
||||||
fs_storage_path("DDNet", m_aUserdir, sizeof(m_aUserdir));
|
if(fs_storage_path("DDNet", m_aUserdir, sizeof(m_aUserdir)))
|
||||||
fs_storage_path("Teeworlds", aFallbackUserdir, sizeof(aFallbackUserdir));
|
{
|
||||||
|
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);
|
str_copy(m_aUserdir, aFallbackUserdir);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// get datadir
|
// get datadir
|
||||||
FindDatadir(ppArguments[0]);
|
FindDatadir(ppArguments[0]);
|
||||||
|
@ -54,7 +65,9 @@ public:
|
||||||
|
|
||||||
// get currentdir
|
// get currentdir
|
||||||
if(!fs_getcwd(m_aCurrentdir, sizeof(m_aCurrentdir)))
|
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
|
// load paths from storage.cfg
|
||||||
LoadPaths(ppArguments[0]);
|
LoadPaths(ppArguments[0]);
|
||||||
|
@ -161,12 +174,12 @@ public:
|
||||||
{
|
{
|
||||||
if(!pPath[0])
|
if(!pPath[0])
|
||||||
{
|
{
|
||||||
dbg_msg("storage", "cannot add empty path");
|
log_error("storage", "cannot add empty path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(m_NumPaths >= MAX_PATHS)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +190,10 @@ public:
|
||||||
str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserdir);
|
str_copy(m_aaStoragePaths[m_NumPaths++], m_aUserdir);
|
||||||
dbg_msg("storage", "added path '$USERDIR' ('%s')", 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"))
|
else if(!str_comp(pPath, "$DATADIR"))
|
||||||
{
|
{
|
||||||
|
@ -185,13 +202,17 @@ public:
|
||||||
str_copy(m_aaStoragePaths[m_NumPaths++], m_aDatadir);
|
str_copy(m_aaStoragePaths[m_NumPaths++], m_aDatadir);
|
||||||
dbg_msg("storage", "added path '$DATADIR' ('%s')", 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"))
|
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);
|
dbg_msg("storage", "added path '$CURRENTDIR' ('%s')", m_aCurrentdir);
|
||||||
}
|
}
|
||||||
else
|
else if(str_utf8_check(pPath))
|
||||||
{
|
{
|
||||||
if(fs_is_dir(pPath))
|
if(fs_is_dir(pPath))
|
||||||
{
|
{
|
||||||
|
@ -200,9 +221,13 @@ public:
|
||||||
}
|
}
|
||||||
else
|
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)
|
void FindDatadir(const char *pArgv0)
|
||||||
|
@ -817,8 +842,6 @@ public:
|
||||||
str_append(pBuffer, "/", BufferSize);
|
str_append(pBuffer, "/", BufferSize);
|
||||||
str_append(pBuffer, aBinaryPath, BufferSize);
|
str_append(pBuffer, aBinaryPath, BufferSize);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
pBuffer[0] = '\0';
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
str_copy(pBuffer, aBinaryPath, BufferSize);
|
str_copy(pBuffer, aBinaryPath, BufferSize);
|
||||||
|
|
Loading…
Reference in a new issue