1717#include < Server/Components/Vehicles/vehicles.hpp>
1818#include < Server/Components/LegacyConfig/legacyconfig.hpp>
1919#include < Server/Components/CustomModels/custommodels.hpp>
20+ #include < cstdlib>
2021#include < cstdarg>
2122#include < cxxopts.hpp>
2223#include < events.hpp>
@@ -317,6 +318,71 @@ class Config final : public IEarlyConfig
317318
318319 std::map<String, ConfigStorage> defaults;
319320
321+ String expandEnvironmentVariables (const String& value) const
322+ {
323+ String result;
324+ result.reserve (value.length ());
325+
326+ size_t i = 0 ;
327+ while (i < value.length ())
328+ {
329+ const char ch = value[i];
330+
331+ if (ch != ' $' )
332+ {
333+ result.push_back (ch);
334+ ++i;
335+ continue ;
336+ }
337+
338+ if (i + 1 < value.length () && value[i + 1 ] == ' $' )
339+ {
340+ result.push_back (' $' );
341+ i += 2 ;
342+ continue ;
343+ }
344+
345+ if (i + 1 >= value.length () || value[i + 1 ] != ' {' )
346+ {
347+ result.push_back (ch);
348+ ++i;
349+ continue ;
350+ }
351+
352+ const size_t varStart = i + 2 ;
353+ const size_t end = value.find (' }' , varStart);
354+
355+ if (end == String::npos)
356+ {
357+ result.append (value.substr (i));
358+ break ;
359+ }
360+
361+ const String fullVar = value.substr (varStart, end - varStart);
362+ const size_t defaultPos = fullVar.find (" :-" );
363+
364+ const String varName = (defaultPos != String::npos) ? fullVar.substr (0 , defaultPos) : fullVar;
365+ const char * envValue = std::getenv (varName.c_str ());
366+
367+ if (envValue)
368+ {
369+ result.append (envValue);
370+ }
371+ else if (defaultPos != String::npos)
372+ {
373+ result.append (fullVar.substr (defaultPos + 2 ));
374+ }
375+ else
376+ {
377+ result.append (value.substr (i, end - i + 1 ));
378+ }
379+
380+ i = end + 1 ;
381+ }
382+
383+ return result;
384+ }
385+
320386 void processNode (const nlohmann::json::object_t & node, String ns = " " )
321387 {
322388 for (const auto & kv : node)
@@ -337,7 +403,8 @@ class Config final : public IEarlyConfig
337403 }
338404 else if (v.is_string ())
339405 {
340- processed[key].emplace <String>(v.get <String>());
406+ String strValue = v.get <String>();
407+ processed[key].emplace <String>(expandEnvironmentVariables (strValue));
341408 }
342409 else if (v.is_array ())
343410 {
@@ -347,7 +414,8 @@ class Config final : public IEarlyConfig
347414 {
348415 if (arrVal.is_string ())
349416 {
350- vec.emplace_back (arrVal.get <String>());
417+ String strValue = arrVal.get <String>();
418+ vec.emplace_back (expandEnvironmentVariables (strValue));
351419 }
352420 }
353421 }
@@ -2205,4 +2273,4 @@ class Core final : public ICore, public PlayerConnectEventHandler, public Consol
22052273 HTTPAsyncIO* httpIO = new HTTPAsyncIO (handler, type, url, data, true , config.getString (" network.bind" ));
22062274 httpFutures.emplace (httpIO);
22072275 }
2208- };
2276+ };
0 commit comments