Merge.
This commit is contained in:
@@ -34,8 +34,6 @@
|
||||
#include "Updater.h"
|
||||
#include "md5.h"
|
||||
|
||||
#define UPDATE_URL "http://www.sourcemod.net/update/"
|
||||
|
||||
#define USTATE_NONE 0
|
||||
#define USTATE_FOLDERS 1
|
||||
#define USTATE_CHANGED 2
|
||||
@@ -43,7 +41,7 @@
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
UpdateReader::UpdateReader()
|
||||
UpdateReader::UpdateReader() : partFirst(NULL), partLast(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -125,7 +123,7 @@ SMCResult UpdateReader::ReadSMC_KeyValue(const SMCStates *states,
|
||||
}
|
||||
else if (strcmp(key, "location") == 0)
|
||||
{
|
||||
url.assign(UPDATE_URL);
|
||||
url.assign(update_url);
|
||||
url.append(value);
|
||||
}
|
||||
break;
|
||||
@@ -174,6 +172,21 @@ SMCResult UpdateReader::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
void UpdateReader::LinkPart(UpdatePart *part)
|
||||
{
|
||||
part->next = NULL;
|
||||
if (partFirst == NULL)
|
||||
{
|
||||
partFirst = part;
|
||||
partLast = part;
|
||||
}
|
||||
else
|
||||
{
|
||||
partLast->next = part;
|
||||
partLast = part;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateReader::HandleFile()
|
||||
{
|
||||
MD5 md5;
|
||||
@@ -192,6 +205,12 @@ void UpdateReader::HandleFile()
|
||||
md5.finalize();
|
||||
md5.hex_digest(real_checksum);
|
||||
|
||||
if (mdl.GetSize() == 0)
|
||||
{
|
||||
AddUpdateError("Zero-length file returned for \"%s\"", curfile.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(checksum, real_checksum) != 0)
|
||||
{
|
||||
AddUpdateError("Checksums for file \"%s\" do not match:", curfile.c_str());
|
||||
@@ -199,45 +218,20 @@ void UpdateReader::HandleFile()
|
||||
return;
|
||||
}
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", curfile.c_str());
|
||||
|
||||
gameconfs->AcquireLock();
|
||||
|
||||
FILE *fp = fopen(path, "wt");
|
||||
if (fp == NULL)
|
||||
{
|
||||
gameconfs->ReleaseLock();
|
||||
AddUpdateError("Could not open %s for writing", path);
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(mdl.GetBuffer(), 1, mdl.GetSize(), fp);
|
||||
fclose(fp);
|
||||
|
||||
gameconfs->ReleaseLock();
|
||||
|
||||
AddUpdateMessage("Successfully updated gamedata file \"%s\"", curfile.c_str());
|
||||
UpdatePart *part = new UpdatePart;
|
||||
part->data = (char*)malloc(mdl.GetSize());
|
||||
part->file = strdup(curfile.c_str());
|
||||
part->length = mdl.GetSize();
|
||||
LinkPart(part);
|
||||
}
|
||||
|
||||
void UpdateReader::HandleFolder(const char *folder)
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", folder);
|
||||
if (libsys->IsPathDirectory(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!libsys->CreateFolder(path))
|
||||
{
|
||||
AddUpdateError("Could not create folder: %s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddUpdateMessage("Created folder \"%s\" from updater", folder);
|
||||
}
|
||||
UpdatePart *part = new UpdatePart;
|
||||
part->data = NULL;
|
||||
part->length = 0;
|
||||
part->file = strdup(folder);
|
||||
LinkPart(part);
|
||||
}
|
||||
|
||||
static bool md5_file(const char *file, char checksum[33])
|
||||
@@ -334,18 +328,18 @@ static void add_folders(IWebForm *form, const char *root, unsigned int &num_file
|
||||
libsys->CloseDirectory(dir);
|
||||
}
|
||||
|
||||
void UpdateReader::PerformUpdate()
|
||||
void UpdateReader::PerformUpdate(const char *url)
|
||||
{
|
||||
IWebForm *form;
|
||||
MemoryDownloader master;
|
||||
SMCStates states = {0, 0};
|
||||
|
||||
update_url = url;
|
||||
|
||||
form = webternet->CreateForm();
|
||||
xfer = webternet->CreateSession();
|
||||
xfer->SetFailOnHTTPError(true);
|
||||
|
||||
const char *root_url = UPDATE_URL "gamedata.php";
|
||||
|
||||
form->AddString("version", SVN_FULL_VERSION);
|
||||
form->AddString("build", SM_BUILD_UNIQUEID);
|
||||
|
||||
@@ -356,9 +350,9 @@ void UpdateReader::PerformUpdate()
|
||||
smutils->Format(temp, sizeof(temp), "%d", num_files);
|
||||
form->AddString("files", temp);
|
||||
|
||||
if (!xfer->PostAndDownload(root_url, form, &master, NULL))
|
||||
if (!xfer->PostAndDownload(url, form, &master, NULL))
|
||||
{
|
||||
AddUpdateError("Could not download \"%s\"", root_url);
|
||||
AddUpdateError("Could not download \"%s\"", url);
|
||||
AddUpdateError("Error: %s", xfer->LastErrorMessage());
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -381,3 +375,14 @@ cleanup:
|
||||
delete xfer;
|
||||
delete form;
|
||||
}
|
||||
|
||||
UpdatePart *UpdateReader::DetachParts()
|
||||
{
|
||||
UpdatePart *first;
|
||||
|
||||
first = partFirst;
|
||||
partFirst = NULL;
|
||||
partLast = NULL;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,14 @@
|
||||
#include <sh_string.h>
|
||||
#include "MemoryDownloader.h"
|
||||
|
||||
struct UpdatePart
|
||||
{
|
||||
UpdatePart* next;
|
||||
char *file;
|
||||
char *data;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
class UpdateReader :
|
||||
@@ -51,10 +59,12 @@ namespace SourceMod
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||
public:
|
||||
void PerformUpdate();
|
||||
void PerformUpdate(const char *url);
|
||||
UpdatePart *DetachParts();
|
||||
private:
|
||||
void HandleFile();
|
||||
void HandleFolder(const char *folder);
|
||||
void LinkPart(UpdatePart *part);
|
||||
private:
|
||||
IWebTransfer *xfer;
|
||||
MemoryDownloader mdl;
|
||||
@@ -63,6 +73,9 @@ namespace SourceMod
|
||||
SourceHook::String curfile;
|
||||
SourceHook::String url;
|
||||
char checksum[33];
|
||||
UpdatePart *partFirst;
|
||||
UpdatePart *partLast;
|
||||
const char *update_url;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
|
||||
#define DEFAULT_UPDATE_URL "http://www.sourcemod.net/update/"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
SmUpdater g_Updater; /**< Global singleton for extension's main interface */
|
||||
@@ -45,8 +47,8 @@ SMEXT_LINK(&g_Updater);
|
||||
|
||||
IWebternet *webternet;
|
||||
static List<String *> update_errors;
|
||||
static List<String *> update_messages;
|
||||
static IThreadHandle *update_thread;
|
||||
static String update_url;
|
||||
|
||||
bool SmUpdater::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
@@ -65,6 +67,13 @@ bool SmUpdater::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *url = smutils->GetCoreConfigValue("AutoUpdateURL");
|
||||
if (url == NULL)
|
||||
{
|
||||
url = DEFAULT_UPDATE_URL;
|
||||
}
|
||||
update_url.assign(url);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,10 +94,6 @@ void SmUpdater::SDK_OnUnload()
|
||||
{
|
||||
iter = update_errors.erase(iter);
|
||||
}
|
||||
while (iter != update_messages.end())
|
||||
{
|
||||
iter = update_messages.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
bool SmUpdater::QueryInterfaceDrop(SourceMod::SMInterface *pInterface)
|
||||
@@ -112,11 +117,61 @@ void SmUpdater::NotifyInterfaceDrop(SMInterface *pInterface)
|
||||
}
|
||||
}
|
||||
|
||||
static void LogAllMessages(void *data)
|
||||
static void PumpUpdate(void *data)
|
||||
{
|
||||
String *str;
|
||||
List<String *>::iterator iter;
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
UpdatePart *temp;
|
||||
UpdatePart *part = (UpdatePart*)data;
|
||||
while (part != NULL)
|
||||
{
|
||||
if (strstr(part->file, "..") != NULL)
|
||||
{
|
||||
/* Naughty naughty */
|
||||
AddUpdateError("Detected invalid path escape (..): %s", part->file);
|
||||
goto skip_create;
|
||||
}
|
||||
if (part->data == NULL)
|
||||
{
|
||||
smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", part->file);
|
||||
if (libsys->IsPathDirectory(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!libsys->CreateFolder(path))
|
||||
{
|
||||
AddUpdateError("Could not create folder: %s", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
smutils->LogMessage(myself, "Created folder \"%s\" from updater", path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", part->file);
|
||||
FILE *fp = fopen(path, "wt");
|
||||
if (fp == NULL)
|
||||
{
|
||||
AddUpdateError("Could not open %s for writing", path);
|
||||
return;
|
||||
}
|
||||
fwrite(part->data, 1, part->length, fp);
|
||||
fclose(fp);
|
||||
smutils->LogMessage(myself,
|
||||
"Successfully updated gamedata file \"%s\"",
|
||||
part->file);
|
||||
}
|
||||
skip_create:
|
||||
temp = part->next;
|
||||
free(part->data);
|
||||
free(part->file);
|
||||
delete part;
|
||||
part = temp;
|
||||
}
|
||||
|
||||
if (update_errors.size())
|
||||
{
|
||||
smutils->LogError(myself, "--- BEGIN ERRORS FROM AUTOMATIC UPDATER ---");
|
||||
@@ -131,44 +186,21 @@ static void LogAllMessages(void *data)
|
||||
|
||||
smutils->LogError(myself, "--- END ERRORS FROM AUTOMATIC UPDATER ---");
|
||||
}
|
||||
|
||||
for (iter = update_messages.begin();
|
||||
iter != update_messages.end();
|
||||
iter++)
|
||||
{
|
||||
str = (*iter);
|
||||
smutils->LogMessage(myself, "%s", str->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SmUpdater::RunThread(IThreadHandle *pHandle)
|
||||
{
|
||||
UpdateReader ur;
|
||||
|
||||
ur.PerformUpdate();
|
||||
ur.PerformUpdate(update_url.c_str());
|
||||
|
||||
if (update_errors.size() || update_messages.size())
|
||||
{
|
||||
smutils->AddFrameAction(LogAllMessages, NULL);
|
||||
}
|
||||
smutils->AddFrameAction(PumpUpdate, ur.DetachParts());
|
||||
}
|
||||
|
||||
void SmUpdater::OnTerminate(IThreadHandle *pHandle, bool cancel)
|
||||
{
|
||||
}
|
||||
|
||||
void AddUpdateMessage(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[2048];
|
||||
|
||||
va_start(ap, fmt);
|
||||
smutils->FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
update_messages.push_back(new String(buffer));
|
||||
}
|
||||
|
||||
void AddUpdateError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
Reference in New Issue
Block a user