mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-21 01:04:06 +00:00
Fix the replay menu for people with non-latin characters in their username.
Use OsPath instead of CStr and CStrW where possible,
wstring_from_utf8(OsPath.string8()) to pass printable strings to the
JSAPI,
OsString when opening a filestream and
off_t instead of int for filesizes.
Fixes #4320
Differential Revision: https://code.wildfiregames.com/D518
Reviewed By: Imarok
Tested By: Imarok on Windows, wraitii on OSX
Special thanks to Philip for advice and the lib/path.h fix in
47cc447322.
This was SVN commit r19824.
This commit is contained in:
+31
-33
@@ -49,7 +49,7 @@ OsPath VisualReplay::GetDirectoryName()
|
||||
return OsPath(paths.UserData() / "replays" / engine_version);
|
||||
}
|
||||
|
||||
void VisualReplay::StartVisualReplay(const CStrW& directory)
|
||||
void VisualReplay::StartVisualReplay(const OsPath& directory)
|
||||
{
|
||||
ENSURE(!g_NetServer);
|
||||
ENSURE(!g_NetClient);
|
||||
@@ -61,7 +61,7 @@ void VisualReplay::StartVisualReplay(const CStrW& directory)
|
||||
return;
|
||||
|
||||
g_Game = new CGame(false, false);
|
||||
g_Game->StartVisualReplay(replayFile.string8());
|
||||
g_Game->StartVisualReplay(replayFile);
|
||||
}
|
||||
|
||||
bool VisualReplay::ReadCacheFile(ScriptInterface& scriptInterface, JS::MutableHandleObject cachedReplaysObject)
|
||||
@@ -72,7 +72,7 @@ bool VisualReplay::ReadCacheFile(ScriptInterface& scriptInterface, JS::MutableHa
|
||||
if (!FileExists(cacheFileName))
|
||||
return false;
|
||||
|
||||
std::ifstream cacheStream(cacheFileName.string8().c_str());
|
||||
std::ifstream cacheStream(OsString(cacheFileName).c_str());
|
||||
CStr cacheStr((std::istreambuf_iterator<char>(cacheStream)), std::istreambuf_iterator<char>());
|
||||
cacheStream.close();
|
||||
|
||||
@@ -95,7 +95,7 @@ void VisualReplay::StoreCacheFile(ScriptInterface& scriptInterface, JS::HandleOb
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedValue replaysRooted(cx, JS::ObjectValue(*replays));
|
||||
std::ofstream cacheStream(tempCacheFileName.string8().c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
std::ofstream cacheStream(OsString(tempCacheFileName).c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
cacheStream << scriptInterface.StringifyJSON(&replaysRooted);
|
||||
cacheStream.close();
|
||||
|
||||
@@ -111,7 +111,7 @@ JS::HandleObject VisualReplay::ReloadReplayCache(ScriptInterface& scriptInterfac
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
// Maps the filename onto the index and size
|
||||
typedef std::map<CStr, std::pair<u32, off_t>> replayCacheMap;
|
||||
typedef std::map<OsPath, std::pair<u32, off_t>> replayCacheMap;
|
||||
|
||||
replayCacheMap fileList;
|
||||
|
||||
@@ -127,7 +127,7 @@ JS::HandleObject VisualReplay::ReloadReplayCache(ScriptInterface& scriptInterfac
|
||||
JS_GetElement(cx, cachedReplaysObject, j, &replay);
|
||||
|
||||
JS::RootedValue file(cx);
|
||||
CStr fileName;
|
||||
OsPath fileName;
|
||||
double fileSize;
|
||||
scriptInterface.GetProperty(replay, "directory", fileName);
|
||||
scriptInterface.GetProperty(replay, "fileSize", fileSize);
|
||||
@@ -158,7 +158,7 @@ JS::HandleObject VisualReplay::ReloadReplayCache(ScriptInterface& scriptInterfac
|
||||
continue;
|
||||
|
||||
bool isNew = true;
|
||||
replayCacheMap::iterator it = fileList.find(directory.string8());
|
||||
replayCacheMap::iterator it = fileList.find(directory);
|
||||
if (it != fileList.end())
|
||||
{
|
||||
if (compareFiles)
|
||||
@@ -180,7 +180,7 @@ JS::HandleObject VisualReplay::ReloadReplayCache(ScriptInterface& scriptInterfac
|
||||
CFileInfo fileInfo;
|
||||
GetFileInfo(replayFile, &fileInfo);
|
||||
scriptInterface.Eval("({})", &replayData);
|
||||
scriptInterface.SetProperty(replayData, "directory", directory);
|
||||
scriptInterface.SetProperty(replayData, "directory", directory.string());
|
||||
scriptInterface.SetProperty(replayData, "fileSize", (double)fileInfo.Size());
|
||||
}
|
||||
JS_SetElement(cx, replays, i++, replayData);
|
||||
@@ -241,7 +241,7 @@ JS::Value VisualReplay::GetReplays(ScriptInterface& scriptInterface, bool compar
|
||||
*
|
||||
* @return The current cursor position or -1 on error.
|
||||
*/
|
||||
inline int goBackToLineBeginning(std::istream* replayStream, const CStr& fileName, const u64& fileSize)
|
||||
inline off_t goBackToLineBeginning(std::istream* replayStream, const OsPath& fileName, off_t fileSize)
|
||||
{
|
||||
int currentPos;
|
||||
char character;
|
||||
@@ -255,7 +255,7 @@ inline int goBackToLineBeginning(std::istream* replayStream, const CStr& fileNam
|
||||
|
||||
if (!replayStream->good())
|
||||
{
|
||||
LOGERROR("Unknown error when returning to the last line (%i of %lu) of %s", currentPos, fileSize, fileName.c_str());
|
||||
LOGERROR("Unknown error when returning to the last line (%i of %lu) of %s", currentPos, fileSize, fileName.string8().c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ inline int goBackToLineBeginning(std::istream* replayStream, const CStr& fileNam
|
||||
replayStream->seekg(-2, std::ios_base::cur);
|
||||
}
|
||||
|
||||
LOGERROR("Infinite loop when going back to a line beginning in %s", fileName.c_str());
|
||||
LOGERROR("Infinite loop when going back to a line beginning in %s", fileName.string8().c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ inline int goBackToLineBeginning(std::istream* replayStream, const CStr& fileNam
|
||||
*
|
||||
* @return seconds or -1 on error
|
||||
*/
|
||||
inline int getReplayDuration(std::istream* replayStream, const CStr& fileName, const u64& fileSize)
|
||||
inline int getReplayDuration(std::istream* replayStream, const OsPath& fileName, off_t fileSize)
|
||||
{
|
||||
CStr type;
|
||||
|
||||
@@ -290,7 +290,7 @@ inline int getReplayDuration(std::istream* replayStream, const CStr& fileName, c
|
||||
// There should be about 5 lines to read until a turn is found.
|
||||
for (int linesRead = 1; linesRead < 1000; ++linesRead)
|
||||
{
|
||||
int currentPosition = goBackToLineBeginning(replayStream, fileName, fileSize);
|
||||
off_t currentPosition = goBackToLineBeginning(replayStream, fileName, fileSize);
|
||||
|
||||
// Read error or reached file beginning. No turns exist.
|
||||
if (currentPosition < 1)
|
||||
@@ -298,12 +298,12 @@ inline int getReplayDuration(std::istream* replayStream, const CStr& fileName, c
|
||||
|
||||
if (!replayStream->good())
|
||||
{
|
||||
LOGERROR("Read error when determining replay duration at %i of %llu in %s", currentPosition - 2, fileSize, fileName.c_str());
|
||||
LOGERROR("Read error when determining replay duration at %i of %llu in %s", currentPosition - 2, fileSize, fileName.string8().c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Found last turn, compute duration.
|
||||
if ((u64) currentPosition + 4 < fileSize && (*replayStream >> type).good() && type == "turn")
|
||||
if (currentPosition + 4 < fileSize && (*replayStream >> type).good() && type == "turn")
|
||||
{
|
||||
u32 turn = 0, turnLength = 0;
|
||||
*replayStream >> turn >> turnLength;
|
||||
@@ -314,7 +314,7 @@ inline int getReplayDuration(std::istream* replayStream, const CStr& fileName, c
|
||||
replayStream->seekg(currentPosition - 2, std::ios_base::beg);
|
||||
}
|
||||
|
||||
LOGERROR("Infinite loop when determining replay duration for %s", fileName.c_str());
|
||||
LOGERROR("Infinite loop when determining replay duration for %s", fileName.string8().c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -329,26 +329,24 @@ JS::Value VisualReplay::LoadReplayData(ScriptInterface& scriptInterface, const O
|
||||
// Get file size and modification date
|
||||
CFileInfo fileInfo;
|
||||
GetFileInfo(replayFile, &fileInfo);
|
||||
const u64 fileSize = (u64)fileInfo.Size();
|
||||
const off_t fileSize = fileInfo.Size();
|
||||
|
||||
if (fileSize == 0)
|
||||
return JSVAL_NULL;
|
||||
|
||||
// Open file
|
||||
const CStr fileName = replayFile.string8();
|
||||
std::ifstream* replayStream = new std::ifstream(fileName.c_str());
|
||||
std::ifstream* replayStream = new std::ifstream(OsString(replayFile).c_str());
|
||||
|
||||
// File must begin with "start"
|
||||
CStr type;
|
||||
if (!(*replayStream >> type).good())
|
||||
{
|
||||
LOGERROR("Couldn't open %s. Non-latin characters are not supported yet.", fileName.c_str());
|
||||
LOGERROR("Couldn't open %s.", replayFile.string8().c_str());
|
||||
SAFE_DELETE(replayStream);
|
||||
return JSVAL_NULL;
|
||||
}
|
||||
|
||||
if (type != "start")
|
||||
{
|
||||
LOGWARNING("The replay %s is broken!", fileName.c_str());
|
||||
LOGWARNING("The replay %s doesn't begin with 'start'!", replayFile.string8().c_str());
|
||||
SAFE_DELETE(replayStream);
|
||||
return JSVAL_NULL;
|
||||
}
|
||||
@@ -361,7 +359,7 @@ JS::Value VisualReplay::LoadReplayData(ScriptInterface& scriptInterface, const O
|
||||
JS::RootedValue attribs(cx);
|
||||
if (!scriptInterface.ParseJSON(header, &attribs))
|
||||
{
|
||||
LOGERROR("Couldn't parse replay header of %s", fileName.c_str());
|
||||
LOGERROR("Couldn't parse replay header of %s", replayFile.string8().c_str());
|
||||
SAFE_DELETE(replayStream);
|
||||
return JSVAL_NULL;
|
||||
}
|
||||
@@ -382,7 +380,7 @@ JS::Value VisualReplay::LoadReplayData(ScriptInterface& scriptInterface, const O
|
||||
return JSVAL_NULL;
|
||||
}
|
||||
|
||||
int duration = getReplayDuration(replayStream, fileName, fileSize);
|
||||
int duration = getReplayDuration(replayStream, replayFile, fileSize);
|
||||
|
||||
SAFE_DELETE(replayStream);
|
||||
|
||||
@@ -393,14 +391,14 @@ JS::Value VisualReplay::LoadReplayData(ScriptInterface& scriptInterface, const O
|
||||
// Return the actual data
|
||||
JS::RootedValue replayData(cx);
|
||||
scriptInterface.Eval("({})", &replayData);
|
||||
scriptInterface.SetProperty(replayData, "directory", directory);
|
||||
scriptInterface.SetProperty(replayData, "directory", directory.string());
|
||||
scriptInterface.SetProperty(replayData, "fileSize", (double)fileSize);
|
||||
scriptInterface.SetProperty(replayData, "attribs", attribs);
|
||||
scriptInterface.SetProperty(replayData, "duration", duration);
|
||||
return replayData;
|
||||
}
|
||||
|
||||
bool VisualReplay::DeleteReplay(const CStrW& replayDirectory)
|
||||
bool VisualReplay::DeleteReplay(const OsPath& replayDirectory)
|
||||
{
|
||||
if (replayDirectory.empty())
|
||||
return false;
|
||||
@@ -409,7 +407,7 @@ bool VisualReplay::DeleteReplay(const CStrW& replayDirectory)
|
||||
return DirectoryExists(directory) && DeleteDirectory(directory) == INFO::OK;
|
||||
}
|
||||
|
||||
JS::Value VisualReplay::GetReplayAttributes(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& directoryName)
|
||||
JS::Value VisualReplay::GetReplayAttributes(ScriptInterface::CxPrivate* pCxPrivate, const OsPath& directoryName)
|
||||
{
|
||||
// Create empty JS object
|
||||
JSContext* cx = pCxPrivate->pScriptInterface->GetContext();
|
||||
@@ -423,7 +421,7 @@ JS::Value VisualReplay::GetReplayAttributes(ScriptInterface::CxPrivate* pCxPriva
|
||||
return attribs;
|
||||
|
||||
// Open file
|
||||
std::istream* replayStream = new std::ifstream(replayFile.string8().c_str());
|
||||
std::istream* replayStream = new std::ifstream(OsString(replayFile).c_str());
|
||||
CStr type, line;
|
||||
ENSURE((*replayStream >> type).good() && type == "start");
|
||||
|
||||
@@ -473,13 +471,13 @@ void VisualReplay::SaveReplayMetadata(ScriptInterface* scriptInterface)
|
||||
const OsPath fileName = g_Game->GetReplayLogger().GetDirectory() / L"metadata.json";
|
||||
CreateDirectories(fileName.Parent(), 0700);
|
||||
|
||||
std::ofstream stream (fileName.string8().c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
std::ofstream stream (OsString(fileName).c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||
stream << scriptInterface->StringifyJSON(&metadata, false);
|
||||
stream.close();
|
||||
debug_printf("Saved replay metadata to %s\n", fileName.string8().c_str());
|
||||
}
|
||||
|
||||
bool VisualReplay::HasReplayMetadata(const CStrW& directoryName)
|
||||
bool VisualReplay::HasReplayMetadata(const OsPath& directoryName)
|
||||
{
|
||||
const OsPath filePath(GetDirectoryName() / directoryName / L"metadata.json");
|
||||
|
||||
@@ -492,7 +490,7 @@ bool VisualReplay::HasReplayMetadata(const CStrW& directoryName)
|
||||
return fileInfo.Size() > 0;
|
||||
}
|
||||
|
||||
JS::Value VisualReplay::GetReplayMetadata(ScriptInterface::CxPrivate* pCxPrivate, const CStrW& directoryName)
|
||||
JS::Value VisualReplay::GetReplayMetadata(ScriptInterface::CxPrivate* pCxPrivate, const OsPath& directoryName)
|
||||
{
|
||||
if (!HasReplayMetadata(directoryName))
|
||||
return JSVAL_NULL;
|
||||
@@ -501,7 +499,7 @@ JS::Value VisualReplay::GetReplayMetadata(ScriptInterface::CxPrivate* pCxPrivate
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue metadata(cx);
|
||||
|
||||
std::ifstream* stream = new std::ifstream(OsPath(GetDirectoryName() / directoryName / L"metadata.json").string8());
|
||||
std::ifstream* stream = new std::ifstream(OsString(GetDirectoryName() / directoryName / L"metadata.json").c_str());
|
||||
ENSURE(stream->good());
|
||||
CStr line;
|
||||
std::getline(*stream, line);
|
||||
|
||||
Reference in New Issue
Block a user