Upload mirror
This commit is contained in:
1 parent
d0038e50d7
commit
3636ecd7cd
10 files changed
+1700
No files matched your search
@@ -0,0 +1,385 @@
|
||||
|
||||
/* File System Parsers */
|
||||
|
||||
// Strip filename from path.
|
||||
void StripPathFilename(char[] path)
|
||||
{
|
||||
strcopy(path, FindCharInString(path, '/', true) + 1, path);
|
||||
}
|
||||
|
||||
// Return the filename and extension from a given path.
|
||||
void GetPathBasename(char[] path, char[] buffer, int maxlength)
|
||||
{
|
||||
int check = -1;
|
||||
if ((check = FindCharInString(path, '/', true)) != -1 ||
|
||||
(check = FindCharInString(path, '\\', true)) != -1)
|
||||
{
|
||||
strcopy(buffer, maxlength, path[check+1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcopy(buffer, maxlength, path);
|
||||
}
|
||||
}
|
||||
|
||||
// Add http protocol to url if it's missing.
|
||||
void PrefixURL(char[] buffer, int maxlength, const char[] url)
|
||||
{
|
||||
if (strncmp(url, "http://", 7) != 0 && strncmp(url, "https://", 8) != 0)
|
||||
{
|
||||
Format(buffer, maxlength, "http://%s", url);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcopy(buffer, maxlength, url);
|
||||
}
|
||||
}
|
||||
|
||||
// Split URL into hostname, location, and filename. No trailing slashes.
|
||||
void ParseURL(const char[] url, char[] host, int maxHost, char[] location, int maxLoc, char[] filename, int maxName)
|
||||
{
|
||||
// Strip url prefix.
|
||||
int idx = StrContains(url, "://");
|
||||
idx = (idx != -1) ? idx + 3 : 0;
|
||||
|
||||
char dirs[16][64];
|
||||
int total = ExplodeString(url[idx], "/", dirs, sizeof(dirs), sizeof(dirs[]));
|
||||
|
||||
// host
|
||||
Format(host, maxHost, "%s", dirs[0]);
|
||||
|
||||
// location
|
||||
location[0] = '\0';
|
||||
for (int i = 1; i < total - 1; i++)
|
||||
{
|
||||
Format(location, maxLoc, "%s/%s", location, dirs[i]);
|
||||
}
|
||||
|
||||
// filename
|
||||
Format(filename, maxName, "%s", dirs[total-1]);
|
||||
}
|
||||
|
||||
// Converts Updater SMC file paths into paths relative to the game folder.
|
||||
void ParseSMCPathForLocal(const char[] path, char[] buffer, int maxlength)
|
||||
{
|
||||
char dirs[16][64];
|
||||
int total = ExplodeString(path, "/", dirs, sizeof(dirs), sizeof(dirs[]));
|
||||
|
||||
if (StrEqual(dirs[0], "Path_SM"))
|
||||
{
|
||||
BuildPath(Path_SM, buffer, maxlength, "");
|
||||
}
|
||||
else // Path_Mod
|
||||
{
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
// Construct the path and create directories if needed.
|
||||
for (int i = 1; i < total - 1; i++)
|
||||
{
|
||||
Format(buffer, maxlength, "%s%s/", buffer, dirs[i]);
|
||||
|
||||
if(!DirExists(buffer))
|
||||
{
|
||||
CreateDirectory(buffer, 511);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the filename to the end of the path.
|
||||
Format(buffer, maxlength, "%s%s", buffer, dirs[total-1]);
|
||||
}
|
||||
|
||||
// Converts Updater SMC file paths into paths relative to the plugin's update URL.
|
||||
void ParseSMCPathForDownload(const char[] path, char[] buffer, int maxlength)
|
||||
{
|
||||
char dirs[16][64];
|
||||
int total = ExplodeString(path, "/", dirs, sizeof(dirs), sizeof(dirs[]));
|
||||
|
||||
// Construct the path.
|
||||
buffer[0] = '\0';
|
||||
for (int i = 1; i < total; i++)
|
||||
{
|
||||
Format(buffer, maxlength, "%s/%s", buffer, dirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a plugin's update file.
|
||||
// Logs update notes and begins download if required.
|
||||
// Returns true if an update was available.
|
||||
static Handle SMC_Sections;
|
||||
static Handle SMC_DataTrie;
|
||||
static Handle SMC_DataPack;
|
||||
static int SMC_LineNum;
|
||||
|
||||
bool ParseUpdateFile(int index, const char[] path)
|
||||
{
|
||||
/* Return true if an update was available. */
|
||||
SMC_Sections = CreateArray(64);
|
||||
SMC_DataTrie = CreateTrie();
|
||||
SMC_DataPack = CreateDataPack();
|
||||
SMC_LineNum = 0;
|
||||
|
||||
Handle smc = SMC_CreateParser();
|
||||
|
||||
SMC_SetRawLine(smc, Updater_RawLine);
|
||||
SMC_SetReaders(smc, Updater_NewSection, Updater_KeyValue, Updater_EndSection);
|
||||
|
||||
char sBuffer[MAX_URL_LENGTH];
|
||||
Handle hPack;
|
||||
bool bUpdate = false;
|
||||
SMCError err = SMC_ParseFile(smc, path);
|
||||
|
||||
if (err == SMCError_Okay)
|
||||
{
|
||||
// Initialize data
|
||||
Handle hPlugin = IndexToPlugin(index);
|
||||
Handle hFiles = Updater_GetFiles(index);
|
||||
ClearArray(hFiles);
|
||||
|
||||
// current version.
|
||||
char sCurrentVersion[16];
|
||||
|
||||
if (!GetPluginInfo(hPlugin, PlInfo_Version, sCurrentVersion, sizeof(sCurrentVersion)))
|
||||
{
|
||||
strcopy(sCurrentVersion, sizeof(sCurrentVersion), "Null");
|
||||
}
|
||||
|
||||
// latest version.
|
||||
char smcLatestVersion[16];
|
||||
|
||||
if (GetTrieValue(SMC_DataTrie, "version->latest", hPack))
|
||||
{
|
||||
ResetPack(hPack);
|
||||
ReadPackString(hPack, smcLatestVersion, sizeof(smcLatestVersion));
|
||||
}
|
||||
|
||||
// Check if we have the latest version.
|
||||
if (!StrEqual(sCurrentVersion, smcLatestVersion))
|
||||
{
|
||||
char sFilename[64];
|
||||
char sName[64];
|
||||
GetPluginFilename(hPlugin, sFilename, sizeof(sFilename));
|
||||
|
||||
if (GetPluginInfo(hPlugin, PlInfo_Name, sName, sizeof(sName)))
|
||||
{
|
||||
Updater_Log("Update available for \"%s\" (%s). Current: %s - Latest: %s", sName, sFilename, sCurrentVersion, smcLatestVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
Updater_Log("Update available for \"%s\". Current: %s - Latest: %s", sFilename, sCurrentVersion, smcLatestVersion);
|
||||
}
|
||||
|
||||
if (GetTrieValue(SMC_DataTrie, "information->notes", hPack))
|
||||
{
|
||||
ResetPack(hPack);
|
||||
|
||||
int iCount = 0;
|
||||
while (IsPackReadable(hPack, 1))
|
||||
{
|
||||
ReadPackString(hPack, sBuffer, sizeof(sBuffer));
|
||||
Updater_Log(" [%i] %s", iCount++, sBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Log update notes, save file list, and begin downloading.
|
||||
if (g_bGetDownload && Fwd_OnPluginDownloading(hPlugin) == Plugin_Continue)
|
||||
{
|
||||
// Get previous version.
|
||||
char smcPrevVersion[16];
|
||||
if (GetTrieValue(SMC_DataTrie, "version->previous", hPack))
|
||||
{
|
||||
ResetPack(hPack);
|
||||
ReadPackString(hPack, smcPrevVersion, sizeof(smcPrevVersion));
|
||||
}
|
||||
|
||||
// Check if we only need the patch files.
|
||||
if (StrEqual(sCurrentVersion, smcPrevVersion) && GetTrieValue(SMC_DataTrie, "patch->plugin", hPack))
|
||||
{
|
||||
ParseSMCFilePack(index, hPack, hFiles);
|
||||
|
||||
if (g_bGetSource && GetTrieValue(SMC_DataTrie, "patch->source", hPack))
|
||||
{
|
||||
ParseSMCFilePack(index, hPack, hFiles);
|
||||
}
|
||||
}
|
||||
else if (GetTrieValue(SMC_DataTrie, "files->plugin", hPack))
|
||||
{
|
||||
ParseSMCFilePack(index, hPack, hFiles);
|
||||
|
||||
if (g_bGetSource && GetTrieValue(SMC_DataTrie, "files->source", hPack))
|
||||
{
|
||||
ParseSMCFilePack(index, hPack, hFiles);
|
||||
}
|
||||
}
|
||||
|
||||
Updater_SetStatus(index, Status_Downloading);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't want to spam the logs with the same update notification.
|
||||
Updater_SetStatus(index, Status_Updated);
|
||||
}
|
||||
|
||||
bUpdate = true;
|
||||
}
|
||||
|
||||
#if defined DEBUG
|
||||
iCount = 0;
|
||||
|
||||
Updater_DebugLog(" ");
|
||||
Updater_DebugLog("SMC DEBUG");
|
||||
ResetPack(SMC_DataPack);
|
||||
|
||||
while (IsPackReadable(SMC_DataPack, 1))
|
||||
{
|
||||
ReadPackString(SMC_DataPack, sBuffer, sizeof(sBuffer));
|
||||
Updater_DebugLog("%s", sBuffer);
|
||||
|
||||
if (GetTrieValue(SMC_DataTrie, sBuffer, hPack))
|
||||
{
|
||||
iCount = 0;
|
||||
ResetPack(hPack);
|
||||
|
||||
while (IsPackReadable(hPack, 1))
|
||||
{
|
||||
ReadPackString(hPack, sBuffer, sizeof(sBuffer));
|
||||
Updater_DebugLog(" [%i] %s", iCount++, sBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Updater_DebugLog("END SMC DEBUG");
|
||||
Updater_DebugLog(" ");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Updater_Log("SMC parsing error on line %d", SMC_LineNum);
|
||||
|
||||
Updater_GetURL(index, sBuffer, sizeof(sBuffer));
|
||||
Updater_Log(" [0] URL: %s", sBuffer);
|
||||
|
||||
if (SMC_GetErrorString(err, sBuffer, sizeof(sBuffer)))
|
||||
{
|
||||
Updater_Log(" [1] ERROR: %s", sBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up SMC data.
|
||||
ResetPack(SMC_DataPack);
|
||||
|
||||
while (IsPackReadable(SMC_DataPack, 1))
|
||||
{
|
||||
ReadPackString(SMC_DataPack, sBuffer, sizeof(sBuffer));
|
||||
|
||||
if (GetTrieValue(SMC_DataTrie, sBuffer, hPack))
|
||||
{
|
||||
CloseHandle(hPack);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(SMC_Sections);
|
||||
CloseHandle(SMC_DataTrie);
|
||||
CloseHandle(SMC_DataPack);
|
||||
CloseHandle(smc);
|
||||
|
||||
return bUpdate;
|
||||
}
|
||||
|
||||
void ParseSMCFilePack(int index, Handle hPack, Handle hFiles)
|
||||
{
|
||||
// Prepare URL
|
||||
char urlprefix[MAX_URL_LENGTH];
|
||||
char url[MAX_URL_LENGTH];
|
||||
char dest[PLATFORM_MAX_PATH];
|
||||
char sBuffer[MAX_URL_LENGTH];
|
||||
Updater_GetURL(index, urlprefix, sizeof(urlprefix));
|
||||
StripPathFilename(urlprefix);
|
||||
|
||||
ResetPack(hPack);
|
||||
|
||||
while (IsPackReadable(hPack, 1))
|
||||
{
|
||||
ReadPackString(hPack, sBuffer, sizeof(sBuffer));
|
||||
|
||||
// Merge url.
|
||||
ParseSMCPathForDownload(sBuffer, url, sizeof(url));
|
||||
Format(url, sizeof(url), "%s%s", urlprefix, url);
|
||||
|
||||
// Make sure the current plugin path matches the update.
|
||||
ParseSMCPathForLocal(sBuffer, dest, sizeof(dest));
|
||||
|
||||
char sLocalBase[64];
|
||||
char sPluginBase[64];
|
||||
char sFilename[64];
|
||||
GetPathBasename(dest, sLocalBase, sizeof(sLocalBase));
|
||||
GetPathBasename(sFilename, sPluginBase, sizeof(sPluginBase));
|
||||
|
||||
if (StrEqual(sLocalBase, sPluginBase))
|
||||
{
|
||||
StripPathFilename(dest);
|
||||
Format(dest, sizeof(dest), "%s/%s", dest, sFilename);
|
||||
}
|
||||
|
||||
// Save the file location for later.
|
||||
PushArrayString(hFiles, dest);
|
||||
|
||||
// Add temporary file extension.
|
||||
Format(dest, sizeof(dest), "%s.%s", dest, TEMP_FILE_EXT);
|
||||
|
||||
// Begin downloading file.
|
||||
AddToDownloadQueue(index, url, dest);
|
||||
}
|
||||
}
|
||||
|
||||
public SMCResult Updater_RawLine(Handle smc, const char[] line, int lineno)
|
||||
{
|
||||
SMC_LineNum = lineno;
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
public SMCResult Updater_NewSection(Handle smc, const char[] name, bool opt_quotes)
|
||||
{
|
||||
PushArrayString(SMC_Sections, name);
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
public SMCResult Updater_KeyValue(Handle smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes)
|
||||
{
|
||||
char sCurSection[MAX_URL_LENGTH];
|
||||
char sKey[MAX_URL_LENGTH];
|
||||
Handle hPack;
|
||||
|
||||
GetArrayString(SMC_Sections, GetArraySize(SMC_Sections)-1, sCurSection, sizeof(sCurSection));
|
||||
FormatEx(sKey, sizeof(sKey), "%s->%s", sCurSection, key);
|
||||
StringToLower(sKey);
|
||||
|
||||
if (!GetTrieValue(SMC_DataTrie, sKey, hPack))
|
||||
{
|
||||
hPack = CreateDataPack();
|
||||
SetTrieValue(SMC_DataTrie, sKey, hPack);
|
||||
WritePackString(SMC_DataPack, sKey);
|
||||
}
|
||||
|
||||
WritePackString(hPack, value);
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
public SMCResult Updater_EndSection(Handle smc)
|
||||
{
|
||||
if (GetArraySize(SMC_Sections))
|
||||
{
|
||||
RemoveFromArray(SMC_Sections, GetArraySize(SMC_Sections)-1);
|
||||
}
|
||||
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
stock void StringToLower(char[] input)
|
||||
{
|
||||
int length = strlen(input);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
input[i] = CharToLower(input[i]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user