Merge.
Merge.
1.1 --- a/configs/core.cfg Wed Feb 18 02:19:22 2009 -0600
1.2 +++ b/configs/core.cfg Wed Feb 18 02:30:21 2009 -0600
1.3 @@ -5,14 +5,6 @@
1.4 "Core"
1.5 {
1.6 /**
1.7 - * Relative path to SourceMod's base directory. This is relative to the game/mod directory.
1.8 - * Only change this if you have installed SourceMod in a non-default location.
1.9 - *
1.10 - * The default value is "addons/sourcemod"
1.11 - */
1.12 - "BasePath" "addons/sourcemod"
1.13 -
1.14 - /**
1.15 * This option determines if SourceMod logging is enabled.
1.16 *
1.17 * "on" - Logging is enabled (default)
1.18 @@ -105,6 +97,12 @@
1.19 "ForceRestartAfterUpdate" "no"
1.20
1.21 /**
1.22 + * URL to use for retrieving update information.
1.23 + * SSL is not yet supported.
1.24 + */
1.25 + "AutoUpdateURL" "http://www.sourcemod.net/update/"
1.26 +
1.27 + /**
1.28 * Whether to show debug spew.
1.29 * Currently this will log details about the gamedata updating process.
1.30 */
2.1 --- a/core/CoreConfig.cpp Wed Feb 18 02:19:22 2009 -0600
2.2 +++ b/core/CoreConfig.cpp Wed Feb 18 02:30:21 2009 -0600
2.3 @@ -79,9 +79,7 @@
2.4
2.5 const char *arg = cmd.Arg(1);
2.6
2.7 - if (!g_bServerExecd
2.8 - && arg != NULL
2.9 - && strcmp(arg, g_ServerCfgFile->GetString()) == 0)
2.10 + if (!g_bServerExecd && arg != NULL && strcmp(arg, g_ServerCfgFile->GetString()) == 0)
2.11 {
2.12 g_bGotTrigger = true;
2.13 }
2.14 @@ -103,8 +101,7 @@
2.15
2.16 void CheckAndFinalizeConfigs()
2.17 {
2.18 - if ((g_bServerExecd || g_ServerCfgFile == NULL)
2.19 - && g_bGotServerStart)
2.20 + if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
2.21 {
2.22 #if SOURCE_ENGINE >= SE_ORANGEBOX
2.23 g_PendingInternalPush = true;
2.24 @@ -122,6 +119,14 @@
2.25 g_pOnAutoConfigsBuffered = g_Forwards.CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
2.26 }
2.27
2.28 +CoreConfig::CoreConfig() : m_Strings(512)
2.29 +{
2.30 +}
2.31 +
2.32 +CoreConfig::~CoreConfig()
2.33 +{
2.34 +}
2.35 +
2.36 void CoreConfig::OnSourceModShutdown()
2.37 {
2.38 g_RootMenu.RemoveRootConsoleCommand("config", this);
2.39 @@ -218,6 +223,10 @@
2.40 /* Format path to config file */
2.41 g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
2.42
2.43 + /* Reset cached key values */
2.44 + m_KeyValues.clear();
2.45 + m_Strings.Reset();
2.46 +
2.47 /* Parse config file */
2.48 if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
2.49 {
2.50 @@ -256,9 +265,21 @@
2.51 pBase = pBase->m_pGlobalClassNext;
2.52 }
2.53
2.54 + m_KeyValues.replace(option, m_Strings.AddString(value));
2.55 +
2.56 return ConfigResult_Ignore;
2.57 }
2.58
2.59 +const char *CoreConfig::GetCoreConfigValue(const char *key)
2.60 +{
2.61 + int *pKey = m_KeyValues.retrieve(key);
2.62 + if (pKey == NULL)
2.63 + {
2.64 + return NULL;
2.65 + }
2.66 + return m_Strings.GetString(*pKey);
2.67 +}
2.68 +
2.69 bool SM_AreConfigsExecuted()
2.70 {
2.71 return g_bConfigsExecd;
3.1 --- a/core/CoreConfig.h Wed Feb 18 02:19:22 2009 -0600
3.2 +++ b/core/CoreConfig.h Wed Feb 18 02:30:21 2009 -0600
3.3 @@ -35,6 +35,8 @@
3.4 #include "sm_globals.h"
3.5 #include <ITextParsers.h>
3.6 #include <IRootConsoleMenu.h>
3.7 +#include <sm_trie_tpl.h>
3.8 +#include "sm_memtable.h"
3.9
3.10 using namespace SourceMod;
3.11
3.12 @@ -43,6 +45,9 @@
3.13 public ITextListener_SMC,
3.14 public IRootConsoleCommand
3.15 {
3.16 +public:
3.17 + CoreConfig();
3.18 + ~CoreConfig();
3.19 public: // SMGlobalClass
3.20 void OnSourceModAllInitialized();
3.21 void OnSourceModShutdown();
3.22 @@ -56,11 +61,15 @@
3.23 * Initializes CoreConfig by reading from core.cfg file
3.24 */
3.25 void Initialize();
3.26 + const char *GetCoreConfigValue(const char *key);
3.27 private:
3.28 /**
3.29 * Sets configuration option by notifying SourceMod components that rely on core.cfg
3.30 */
3.31 ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
3.32 +private:
3.33 + BaseStringTable m_Strings;
3.34 + KTrie<int> m_KeyValues;
3.35 };
3.36
3.37 extern bool SM_AreConfigsExecuted();
4.1 --- a/core/GameConfigs.cpp Wed Feb 18 02:19:22 2009 -0600
4.2 +++ b/core/GameConfigs.cpp Wed Feb 18 02:30:21 2009 -0600
4.3 @@ -749,6 +749,44 @@
4.4 }
4.5 }
4.6
4.7 + /* Parse the contents of the 'custom' directory */
4.8 + g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/custom", m_File);
4.9 + IDirectory *customDir = g_LibSys.OpenDirectory(path);
4.10 +
4.11 + if (!customDir)
4.12 + {
4.13 + return true;
4.14 + }
4.15 +
4.16 + while (customDir->MoreFiles())
4.17 + {
4.18 + if (!customDir->IsEntryFile())
4.19 + {
4.20 + customDir->NextEntry();
4.21 + continue;
4.22 + }
4.23 +
4.24 + const char *curFile = customDir->GetEntryName();
4.25 +
4.26 + /* Only allow .txt files */
4.27 + int len = strlen(curFile);
4.28 + if (len > 4 && strcmp(&curFile[len-4], ".txt") != 0)
4.29 + {
4.30 + customDir->NextEntry();
4.31 + continue;
4.32 + }
4.33 +
4.34 + UTIL_Format(path, sizeof(path), "%s/custom/%s", m_File, curFile);
4.35 + if (!EnterFile(path, error, maxlength))
4.36 + {
4.37 + g_LibSys.CloseDirectory(customDir);
4.38 + return false;
4.39 + }
4.40 +
4.41 + customDir->NextEntry();
4.42 + }
4.43 +
4.44 + g_LibSys.CloseDirectory(customDir);
4.45 return true;
4.46 }
4.47
4.48 @@ -764,15 +802,11 @@
4.49 bShouldBeReadingDefault = true;
4.50 m_ParseState = PSTATE_NONE;
4.51
4.52 - g_GameConfigs.AcquireLock();
4.53 -
4.54 if ((err=textparsers->ParseSMCFile(m_CurFile, this, &state, error, maxlength))
4.55 != SMCError_Okay)
4.56 {
4.57 const char *msg;
4.58
4.59 - g_GameConfigs.ReleaseLock();
4.60 -
4.61 msg = textparsers->GetSMCErrorString(err);
4.62
4.63 g_Logger.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
4.64 @@ -793,8 +827,6 @@
4.65 return false;
4.66 }
4.67
4.68 - g_GameConfigs.ReleaseLock();
4.69 -
4.70 return true;
4.71 }
4.72
4.73 @@ -862,8 +894,6 @@
4.74
4.75 void GameConfigManager::OnSourceModStartup(bool late)
4.76 {
4.77 - m_FileLock = g_pThreader->MakeMutex();
4.78 -
4.79 LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
4.80
4.81 strncopy(g_Game, g_SourceMod.GetGameFolderName(), sizeof(g_Game));
4.82 @@ -898,7 +928,6 @@
4.83 void GameConfigManager::OnSourceModAllShutdown()
4.84 {
4.85 CloseGameConfigFile(g_pGameConf);
4.86 - m_FileLock->DestroyThis();
4.87 }
4.88
4.89 bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength)
4.90 @@ -993,10 +1022,8 @@
4.91
4.92 void GameConfigManager::AcquireLock()
4.93 {
4.94 - m_FileLock->Lock();
4.95 }
4.96
4.97 void GameConfigManager::ReleaseLock()
4.98 {
4.99 - m_FileLock->Unlock();
4.100 }
5.1 --- a/core/GameConfigs.h Wed Feb 18 02:19:22 2009 -0600
5.2 +++ b/core/GameConfigs.h Wed Feb 18 02:30:21 2009 -0600
5.3 @@ -120,7 +120,6 @@
5.4 private:
5.5 List<CGameConfig *> m_cfgs;
5.6 Trie *m_pLookup;
5.7 - IMutex *m_FileLock;
5.8 public:
5.9 KTrie<ITextListener_SMC *> m_customHandlers;
5.10 };
6.1 --- a/core/UserMessages.cpp Wed Feb 18 02:19:22 2009 -0600
6.2 +++ b/core/UserMessages.cpp Wed Feb 18 02:30:21 2009 -0600
6.3 @@ -348,6 +348,8 @@
6.4 MsgIter iter;
6.5 ListenerInfo *pInfo;
6.6
6.7 + m_InHook = false;
6.8 +
6.9 pList = &m_msgIntercepts[m_CurId];
6.10 for (iter=pList->begin(); iter!=pList->end(); )
6.11 {
6.12 @@ -367,8 +369,6 @@
6.13 iter++;
6.14 }
6.15
6.16 - m_InHook = false;
6.17 -
6.18 pList = &m_msgHooks[m_CurId];
6.19 for (iter=pList->begin(); iter!=pList->end(); )
6.20 {
7.1 --- a/core/sourcemod.cpp Wed Feb 18 02:19:22 2009 -0600
7.2 +++ b/core/sourcemod.cpp Wed Feb 18 02:30:21 2009 -0600
7.3 @@ -70,6 +70,12 @@
7.4 typedef ISourcePawnEngine2 *(*GET_SP_V2)();
7.5 typedef void (*NOTIFYSHUTDOWN)();
7.6
7.7 +#ifdef PLATFORM_WINDOWS
7.8 +ConVar sm_basepath("sm_basepath", "addons\\sourcemod", 0, "SourceMod base path (set via command line)");
7.9 +#elif defined PLATFORM_LINUX || defined PLATFORM_APPLE
7.10 +ConVar sm_basepath("sm_basepath", "addons/sourcemod", 0, "SourceMod base path (set via command line)");
7.11 +#endif
7.12 +
7.13 void ShutdownJIT()
7.14 {
7.15 NOTIFYSHUTDOWN notify = (NOTIFYSHUTDOWN)g_pJIT->GetSymbolAddress("NotifyShutdown");
7.16 @@ -145,16 +151,26 @@
7.17 }
7.18 }
7.19
7.20 - /* Initialize CoreConfig so we can get SourceMod base path properly - this basically parses core.cfg */
7.21 + const char *basepath = icvar->GetCommandLineValue("sm_basepath");
7.22 + /* Set a custom base path if there is one. */
7.23 + if (basepath != NULL && basepath[0] != '\0')
7.24 + {
7.25 + m_GotBasePath = true;
7.26 + }
7.27 + /* Otherwise, use a default and keep the m_GotBasePath unlocked. */
7.28 + else
7.29 + {
7.30 + basepath = sm_basepath.GetDefault();
7.31 + }
7.32 +
7.33 + g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/%s", g_BaseDir.c_str(), basepath);
7.34 + g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "%s", basepath);
7.35 +
7.36 + /* Initialize CoreConfig to get the SourceMod base path properly - this parses core.cfg */
7.37 g_CoreConfig.Initialize();
7.38
7.39 - /* This shouldn't happen, but can't hurt to be safe */
7.40 - if (!g_LibSys.PathExists(m_SMBaseDir) || !m_GotBasePath)
7.41 - {
7.42 - g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str());
7.43 - g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "addons/sourcemod");
7.44 - m_GotBasePath = true;
7.45 - }
7.46 + /* There will always be a path by this point, since it was force-set above. */
7.47 + m_GotBasePath = true;
7.48
7.49 /* Attempt to load the JIT! */
7.50 char file[PLATFORM_MAX_PATH];
7.51 @@ -696,6 +712,11 @@
7.52 ::AddFrameAction(FrameAction(fn, data));
7.53 }
7.54
7.55 +const char *SourceModBase::GetCoreConfigValue(const char *key)
7.56 +{
7.57 + return g_CoreConfig.GetCoreConfigValue(key);
7.58 +}
7.59 +
7.60 SMGlobalClass *SMGlobalClass::head = NULL;
7.61
7.62 SMGlobalClass::SMGlobalClass()
8.1 --- a/core/sourcemod.h Wed Feb 18 02:19:22 2009 -0600
8.2 +++ b/core/sourcemod.h Wed Feb 18 02:30:21 2009 -0600
8.3 @@ -132,6 +132,7 @@
8.4 size_t Format(char *buffer, size_t maxlength, const char *fmt, ...);
8.5 size_t FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap);
8.6 void AddFrameAction(FRAMEACTION fn, void *data);
8.7 + const char *GetCoreConfigValue(const char *key);
8.8 private:
8.9 CStack<CDataPack *> m_freepacks;
8.10 char m_SMBaseDir[PLATFORM_MAX_PATH];
9.1 --- a/extensions/updater/Updater.cpp Wed Feb 18 02:19:22 2009 -0600
9.2 +++ b/extensions/updater/Updater.cpp Wed Feb 18 02:30:21 2009 -0600
9.3 @@ -34,8 +34,6 @@
9.4 #include "Updater.h"
9.5 #include "md5.h"
9.6
9.7 -#define UPDATE_URL "http://www.sourcemod.net/update/"
9.8 -
9.9 #define USTATE_NONE 0
9.10 #define USTATE_FOLDERS 1
9.11 #define USTATE_CHANGED 2
9.12 @@ -43,7 +41,7 @@
9.13
9.14 using namespace SourceMod;
9.15
9.16 -UpdateReader::UpdateReader()
9.17 +UpdateReader::UpdateReader() : partFirst(NULL), partLast(NULL)
9.18 {
9.19 }
9.20
9.21 @@ -125,7 +123,7 @@
9.22 }
9.23 else if (strcmp(key, "location") == 0)
9.24 {
9.25 - url.assign(UPDATE_URL);
9.26 + url.assign(update_url);
9.27 url.append(value);
9.28 }
9.29 break;
9.30 @@ -174,6 +172,21 @@
9.31 return SMCResult_Continue;
9.32 }
9.33
9.34 +void UpdateReader::LinkPart(UpdatePart *part)
9.35 +{
9.36 + part->next = NULL;
9.37 + if (partFirst == NULL)
9.38 + {
9.39 + partFirst = part;
9.40 + partLast = part;
9.41 + }
9.42 + else
9.43 + {
9.44 + partLast->next = part;
9.45 + partLast = part;
9.46 + }
9.47 +}
9.48 +
9.49 void UpdateReader::HandleFile()
9.50 {
9.51 MD5 md5;
9.52 @@ -192,6 +205,12 @@
9.53 md5.finalize();
9.54 md5.hex_digest(real_checksum);
9.55
9.56 + if (mdl.GetSize() == 0)
9.57 + {
9.58 + AddUpdateError("Zero-length file returned for \"%s\"", curfile.c_str());
9.59 + return;
9.60 + }
9.61 +
9.62 if (strcasecmp(checksum, real_checksum) != 0)
9.63 {
9.64 AddUpdateError("Checksums for file \"%s\" do not match:", curfile.c_str());
9.65 @@ -199,45 +218,20 @@
9.66 return;
9.67 }
9.68
9.69 - char path[PLATFORM_MAX_PATH];
9.70 - smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", curfile.c_str());
9.71 -
9.72 - gameconfs->AcquireLock();
9.73 -
9.74 - FILE *fp = fopen(path, "wt");
9.75 - if (fp == NULL)
9.76 - {
9.77 - gameconfs->ReleaseLock();
9.78 - AddUpdateError("Could not open %s for writing", path);
9.79 - return;
9.80 - }
9.81 -
9.82 - fwrite(mdl.GetBuffer(), 1, mdl.GetSize(), fp);
9.83 - fclose(fp);
9.84 -
9.85 - gameconfs->ReleaseLock();
9.86 -
9.87 - AddUpdateMessage("Successfully updated gamedata file \"%s\"", curfile.c_str());
9.88 + UpdatePart *part = new UpdatePart;
9.89 + part->data = (char*)malloc(mdl.GetSize());
9.90 + part->file = strdup(curfile.c_str());
9.91 + part->length = mdl.GetSize();
9.92 + LinkPart(part);
9.93 }
9.94
9.95 void UpdateReader::HandleFolder(const char *folder)
9.96 {
9.97 - char path[PLATFORM_MAX_PATH];
9.98 -
9.99 - smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", folder);
9.100 - if (libsys->IsPathDirectory(path))
9.101 - {
9.102 - return;
9.103 - }
9.104 -
9.105 - if (!libsys->CreateFolder(path))
9.106 - {
9.107 - AddUpdateError("Could not create folder: %s", path);
9.108 - }
9.109 - else
9.110 - {
9.111 - AddUpdateMessage("Created folder \"%s\" from updater", folder);
9.112 - }
9.113 + UpdatePart *part = new UpdatePart;
9.114 + part->data = NULL;
9.115 + part->length = 0;
9.116 + part->file = strdup(folder);
9.117 + LinkPart(part);
9.118 }
9.119
9.120 static bool md5_file(const char *file, char checksum[33])
9.121 @@ -334,18 +328,18 @@
9.122 libsys->CloseDirectory(dir);
9.123 }
9.124
9.125 -void UpdateReader::PerformUpdate()
9.126 +void UpdateReader::PerformUpdate(const char *url)
9.127 {
9.128 IWebForm *form;
9.129 MemoryDownloader master;
9.130 SMCStates states = {0, 0};
9.131
9.132 + update_url = url;
9.133 +
9.134 form = webternet->CreateForm();
9.135 xfer = webternet->CreateSession();
9.136 xfer->SetFailOnHTTPError(true);
9.137
9.138 - const char *root_url = UPDATE_URL "gamedata.php";
9.139 -
9.140 form->AddString("version", SVN_FULL_VERSION);
9.141 form->AddString("build", SM_BUILD_UNIQUEID);
9.142
9.143 @@ -356,9 +350,9 @@
9.144 smutils->Format(temp, sizeof(temp), "%d", num_files);
9.145 form->AddString("files", temp);
9.146
9.147 - if (!xfer->PostAndDownload(root_url, form, &master, NULL))
9.148 + if (!xfer->PostAndDownload(url, form, &master, NULL))
9.149 {
9.150 - AddUpdateError("Could not download \"%s\"", root_url);
9.151 + AddUpdateError("Could not download \"%s\"", url);
9.152 AddUpdateError("Error: %s", xfer->LastErrorMessage());
9.153 goto cleanup;
9.154 }
9.155 @@ -381,3 +375,14 @@
9.156 delete xfer;
9.157 delete form;
9.158 }
9.159 +
9.160 +UpdatePart *UpdateReader::DetachParts()
9.161 +{
9.162 + UpdatePart *first;
9.163 +
9.164 + first = partFirst;
9.165 + partFirst = NULL;
9.166 + partLast = NULL;
9.167 +
9.168 + return first;
9.169 +}
10.1 --- a/extensions/updater/Updater.h Wed Feb 18 02:19:22 2009 -0600
10.2 +++ b/extensions/updater/Updater.h Wed Feb 18 02:30:21 2009 -0600
10.3 @@ -37,6 +37,14 @@
10.4 #include <sh_string.h>
10.5 #include "MemoryDownloader.h"
10.6
10.7 +struct UpdatePart
10.8 +{
10.9 + UpdatePart* next;
10.10 + char *file;
10.11 + char *data;
10.12 + size_t length;
10.13 +};
10.14 +
10.15 namespace SourceMod
10.16 {
10.17 class UpdateReader :
10.18 @@ -51,10 +59,12 @@
10.19 SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
10.20 SMCResult ReadSMC_LeavingSection(const SMCStates *states);
10.21 public:
10.22 - void PerformUpdate();
10.23 + void PerformUpdate(const char *url);
10.24 + UpdatePart *DetachParts();
10.25 private:
10.26 void HandleFile();
10.27 void HandleFolder(const char *folder);
10.28 + void LinkPart(UpdatePart *part);
10.29 private:
10.30 IWebTransfer *xfer;
10.31 MemoryDownloader mdl;
10.32 @@ -63,6 +73,9 @@
10.33 SourceHook::String curfile;
10.34 SourceHook::String url;
10.35 char checksum[33];
10.36 + UpdatePart *partFirst;
10.37 + UpdatePart *partLast;
10.38 + const char *update_url;
10.39 };
10.40 }
10.41
11.1 --- a/extensions/updater/extension.cpp Wed Feb 18 02:19:22 2009 -0600
11.2 +++ b/extensions/updater/extension.cpp Wed Feb 18 02:30:21 2009 -0600
11.3 @@ -38,6 +38,8 @@
11.4 #include <sh_list.h>
11.5 #include <sh_string.h>
11.6
11.7 +#define DEFAULT_UPDATE_URL "http://www.sourcemod.net/update/"
11.8 +
11.9 using namespace SourceHook;
11.10
11.11 SmUpdater g_Updater; /**< Global singleton for extension's main interface */
11.12 @@ -45,8 +47,8 @@
11.13
11.14 IWebternet *webternet;
11.15 static List<String *> update_errors;
11.16 -static List<String *> update_messages;
11.17 static IThreadHandle *update_thread;
11.18 +static String update_url;
11.19
11.20 bool SmUpdater::SDK_OnLoad(char *error, size_t maxlength, bool late)
11.21 {
11.22 @@ -65,6 +67,13 @@
11.23 return false;
11.24 }
11.25
11.26 + const char *url = smutils->GetCoreConfigValue("AutoUpdateURL");
11.27 + if (url == NULL)
11.28 + {
11.29 + url = DEFAULT_UPDATE_URL;
11.30 + }
11.31 + update_url.assign(url);
11.32 +
11.33 return true;
11.34 }
11.35
11.36 @@ -85,10 +94,6 @@
11.37 {
11.38 iter = update_errors.erase(iter);
11.39 }
11.40 - while (iter != update_messages.end())
11.41 - {
11.42 - iter = update_messages.erase(iter);
11.43 - }
11.44 }
11.45
11.46 bool SmUpdater::QueryInterfaceDrop(SourceMod::SMInterface *pInterface)
11.47 @@ -112,11 +117,61 @@
11.48 }
11.49 }
11.50
11.51 -static void LogAllMessages(void *data)
11.52 +static void PumpUpdate(void *data)
11.53 {
11.54 String *str;
11.55 List<String *>::iterator iter;
11.56
11.57 + char path[PLATFORM_MAX_PATH];
11.58 + UpdatePart *temp;
11.59 + UpdatePart *part = (UpdatePart*)data;
11.60 + while (part != NULL)
11.61 + {
11.62 + if (strstr(part->file, "..") != NULL)
11.63 + {
11.64 + /* Naughty naughty */
11.65 + AddUpdateError("Detected invalid path escape (..): %s", part->file);
11.66 + goto skip_create;
11.67 + }
11.68 + if (part->data == NULL)
11.69 + {
11.70 + smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", part->file);
11.71 + if (libsys->IsPathDirectory(path))
11.72 + {
11.73 + continue;
11.74 + }
11.75 + if (!libsys->CreateFolder(path))
11.76 + {
11.77 + AddUpdateError("Could not create folder: %s", path);
11.78 + }
11.79 + else
11.80 + {
11.81 + smutils->LogMessage(myself, "Created folder \"%s\" from updater", path);
11.82 + }
11.83 + }
11.84 + else
11.85 + {
11.86 + smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", part->file);
11.87 + FILE *fp = fopen(path, "wt");
11.88 + if (fp == NULL)
11.89 + {
11.90 + AddUpdateError("Could not open %s for writing", path);
11.91 + return;
11.92 + }
11.93 + fwrite(part->data, 1, part->length, fp);
11.94 + fclose(fp);
11.95 + smutils->LogMessage(myself,
11.96 + "Successfully updated gamedata file \"%s\"",
11.97 + part->file);
11.98 + }
11.99 +skip_create:
11.100 + temp = part->next;
11.101 + free(part->data);
11.102 + free(part->file);
11.103 + delete part;
11.104 + part = temp;
11.105 + }
11.106 +
11.107 if (update_errors.size())
11.108 {
11.109 smutils->LogError(myself, "--- BEGIN ERRORS FROM AUTOMATIC UPDATER ---");
11.110 @@ -131,44 +186,21 @@
11.111
11.112 smutils->LogError(myself, "--- END ERRORS FROM AUTOMATIC UPDATER ---");
11.113 }
11.114 -
11.115 - for (iter = update_messages.begin();
11.116 - iter != update_messages.end();
11.117 - iter++)
11.118 - {
11.119 - str = (*iter);
11.120 - smutils->LogMessage(myself, "%s", str->c_str());
11.121 - }
11.122 }
11.123
11.124 void SmUpdater::RunThread(IThreadHandle *pHandle)
11.125 {
11.126 UpdateReader ur;
11.127
11.128 - ur.PerformUpdate();
11.129 + ur.PerformUpdate(update_url.c_str());
11.130
11.131 - if (update_errors.size() || update_messages.size())
11.132 - {
11.133 - smutils->AddFrameAction(LogAllMessages, NULL);
11.134 - }
11.135 + smutils->AddFrameAction(PumpUpdate, ur.DetachParts());
11.136 }
11.137
11.138 void SmUpdater::OnTerminate(IThreadHandle *pHandle, bool cancel)
11.139 {
11.140 }
11.141
11.142 -void AddUpdateMessage(const char *fmt, ...)
11.143 -{
11.144 - va_list ap;
11.145 - char buffer[2048];
11.146 -
11.147 - va_start(ap, fmt);
11.148 - smutils->FormatArgs(buffer, sizeof(buffer), fmt, ap);
11.149 - va_end(ap);
11.150 -
11.151 - update_messages.push_back(new String(buffer));
11.152 -}
11.153 -
11.154 void AddUpdateError(const char *fmt, ...)
11.155 {
11.156 va_list ap;
12.1 --- a/gamedata/sm-tf2.games.txt Wed Feb 18 02:19:22 2009 -0600
12.2 +++ b/gamedata/sm-tf2.games.txt Wed Feb 18 02:30:21 2009 -0600
12.3 @@ -38,7 +38,7 @@
12.4 {
12.5 "library" "server"
12.6 "linux" "@_ZN8CTFKnife26CalcIsAttackCriticalHelperEv"
12.7 - "windows" "\x33\xC0\x83\xB9\x08\x13\x00\x00\x01\x0F\x94\xC0\xC3"
12.8 + "windows" "\x33\xC0\x83\xB9\x30\x13\x00\x00\x01\x0F\x94\xC0\xC3"
12.9 }
12.10
12.11 }
13.1 --- a/public/IGameConfigs.h Wed Feb 18 02:19:22 2009 -0600
13.2 +++ b/public/IGameConfigs.h Wed Feb 18 02:30:21 2009 -0600
13.3 @@ -163,12 +163,12 @@
13.4 virtual void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener) =0;
13.5
13.6 /**
13.7 - * @brief Acquires a file reading lock on the gamedata system.
13.8 + * @brief Does nothing.
13.9 */
13.10 virtual void AcquireLock() = 0;
13.11
13.12 /**
13.13 - * @brief Releases the file reading lock.
13.14 + * @brief Does nothing.
13.15 */
13.16 virtual void ReleaseLock() = 0;
13.17 };
14.1 --- a/public/ISourceMod.h Wed Feb 18 02:19:22 2009 -0600
14.2 +++ b/public/ISourceMod.h Wed Feb 18 02:30:21 2009 -0600
14.3 @@ -43,7 +43,7 @@
14.4 #include <time.h>
14.5
14.6 #define SMINTERFACE_SOURCEMOD_NAME "ISourceMod"
14.7 -#define SMINTERFACE_SOURCEMOD_VERSION 9
14.8 +#define SMINTERFACE_SOURCEMOD_VERSION 10
14.9
14.10 /**
14.11 * @brief Forward declaration of the KeyValues class.
14.12 @@ -287,6 +287,15 @@
14.13 * @param data Data to pass to function.
14.14 */
14.15 virtual void AddFrameAction(FRAMEACTION fn, void *data) = 0;
14.16 +
14.17 + /**
14.18 + * @brief Retrieves a core.cfg configuration value.
14.19 + *
14.20 + * @param key Core.cfg key phrase.
14.21 + * @return Value string, or NULL on failure.
14.22 + * The string will be destroyed on core.cfg reparses.
14.23 + */
14.24 + virtual const char *GetCoreConfigValue(const char *key) = 0;
14.25 };
14.26 }
14.27