|  | 
| 23 | 23 | #include "CStaticFunctionDefinitions.h" | 
| 24 | 24 | #include "CLanBroadcast.h" | 
| 25 | 25 | 
 | 
| 26 |  | -#define MTA_SERVER_CONF_TEMPLATE "mtaserver.conf.template" | 
|  | 26 | +#define SETTINGS_TEMPLATE_PATH "mtaserver.conf.template" | 
| 27 | 27 | 
 | 
| 28 | 28 | extern CGame* g_pGame; | 
| 29 | 29 | 
 | 
| @@ -865,91 +865,90 @@ bool CMainConfig::AddMissingSettings() | 
| 865 | 865 |  if (!g_pGame->IsUsingMtaServerConf()) | 
| 866 | 866 |  return false; | 
| 867 | 867 | 
 | 
| 868 |  | - const SString templateFileName = PathJoin(g_pServerInterface->GetServerModPath(), "mtaserver.conf.template"); | 
| 869 |  | - | 
|  | 868 | + const std::string templateFileName = PathJoin(g_pServerInterface->GetServerModPath(), SETTINGS_TEMPLATE_PATH); | 
| 870 | 869 |  if (!FileExists(templateFileName)) | 
| 871 | 870 |  return false; | 
| 872 | 871 | 
 | 
| 873 |  | - CXMLFile* templateFile = g_pServerInterface->GetXML()->CreateXML(templateFileName); | 
| 874 |  | - CXMLNode* templateRootNode = templateFile && templateFile->Parse() ? templateFile->GetRootNode() : nullptr; | 
|  | 872 | + std::unique_ptr<CXMLFile> templateFile(g_pServerInterface->GetXML()->CreateXML(templateFileName.c_str())); | 
|  | 873 | + if (!templateFile || !templateFile->Parse()) | 
|  | 874 | + { | 
|  | 875 | + CLogger::ErrorPrintf("Failed to parse template file: '%s'\n", templateFileName.c_str()); | 
|  | 876 | + return false; | 
|  | 877 | + } | 
|  | 878 | + | 
|  | 879 | + CXMLNode* templateRootNode = templateFile->GetRootNode(); | 
| 875 | 880 |  if (!templateRootNode) | 
| 876 | 881 |  { | 
| 877 |  | - CLogger::ErrorPrintf("Can't parse '%s'\n", *templateFileName); | 
|  | 882 | + CLogger::ErrorPrintf("Template file '%s' has no root node\n", templateFileName.c_str()); | 
| 878 | 883 |  return false; | 
| 879 | 884 |  } | 
| 880 | 885 | 
 | 
| 881 | 886 |  // Check that each item in the template also exists in the server config | 
| 882 |  | - bool  hasConfigChanged = false; | 
|  | 887 | + bool configChanged = false; | 
| 883 | 888 |  CXMLNode* previousNode = nullptr; | 
|  | 889 | + | 
| 884 | 890 |  for (auto it = templateRootNode->ChildrenBegin(); it != templateRootNode->ChildrenEnd(); ++it) | 
| 885 | 891 |  { | 
| 886 | 892 |  CXMLNode* templateNode = *it; | 
| 887 |  | - SString templateNodeTagName = templateNode->GetTagName(); | 
|  | 893 | + const std::string& templateNodeName = templateNode->GetTagName(); | 
| 888 | 894 | 
 | 
|  | 895 | + // Skip certain optional nodes | 
|  | 896 | + if (templateNodeName == "resource" || templateNodeName == "module") | 
|  | 897 | + continue; | 
|  | 898 | + | 
| 889 | 899 |  // Find node with exact same attributes | 
| 890 | 900 |  CXMLAttributes& templateAttributes = templateNode->GetAttributes(); | 
| 891 | 901 |  CXMLNode* foundNode = nullptr; | 
| 892 | 902 |  for (auto it2 = m_pRootNode->ChildrenBegin(); it2 != m_pRootNode->ChildrenEnd(); ++it2) | 
| 893 | 903 |  { | 
| 894 | 904 |  CXMLNode* tempNode = *it2; | 
| 895 |  | - if (tempNode->GetTagName() != templateNodeTagName) | 
| 896 |  | - { | 
|  | 905 | + if (tempNode->GetTagName() != templateNodeName) | 
| 897 | 906 |  continue; | 
| 898 |  | - } | 
|  | 907 | + | 
| 899 | 908 |  CXMLAttributes& attributes = tempNode->GetAttributes(); | 
| 900 |  | - bool attributesMatch = true; | 
| 901 |  | - | 
|  | 909 | + bool attributesMatch = true; | 
|  | 910 | + | 
| 902 | 911 |  for (auto it3 = templateAttributes.ListBegin(); it3 != templateAttributes.ListEnd(); ++it3) | 
| 903 | 912 |  { | 
| 904 | 913 |  CXMLAttribute* templateAttribute = *it3; | 
| 905 |  | - const SString& strKey = templateAttribute->GetName(); | 
| 906 |  | - const SString& strValue = templateAttribute->GetValue(); | 
| 907 |  | - | 
| 908 |  | - CXMLAttribute* foundAttribute = attributes.Find(strKey); | 
| 909 |  | - if (!foundAttribute || foundAttribute->GetValue() != strValue) | 
|  | 914 | + const SString& attrName = templateAttribute->GetName(); | 
|  | 915 | + | 
|  | 916 | + // Don't check value attribute which is intended to be different | 
|  | 917 | + if (attrName == "value") | 
|  | 918 | + continue; | 
|  | 919 | + | 
|  | 920 | + const SString& attrValue = templateAttribute->GetValue(); | 
|  | 921 | + | 
|  | 922 | + CXMLAttribute* foundAttribute = attributes.Find(attrName); | 
|  | 923 | + if (!foundAttribute || foundAttribute->GetValue() != attrValue) | 
| 910 | 924 |  { | 
| 911 | 925 |  attributesMatch = false; | 
| 912 | 926 |  break; | 
| 913 | 927 |  } | 
| 914 | 928 |  } | 
| 915 |  | - | 
|  | 929 | + | 
| 916 | 930 |  if (attributesMatch) | 
| 917 | 931 |  { | 
| 918 | 932 |  foundNode = tempNode; | 
| 919 | 933 |  break; | 
| 920 | 934 |  } | 
| 921 | 935 |  } | 
| 922 |  | - // Create missing node if not found | 
|  | 936 | + | 
| 923 | 937 |  if (!foundNode) | 
| 924 | 938 |  { | 
| 925 |  | - CLogger::LogPrintf("Adding missing '%s' to mtaserver.conf\n", *templateNodeTagName); | 
| 926 |  | - SString value = templateNode->GetTagContent(); | 
| 927 |  | - SString commentText = templateNode->GetCommentText(); | 
| 928 |  | - foundNode = m_pRootNode->CreateSubNode(templateNodeTagName, previousNode); | 
| 929 |  | - foundNode->SetTagContent(value); | 
| 930 |  | - foundNode->SetCommentText(commentText, true); | 
| 931 |  | - | 
| 932 |  | - // Copy attributes from template node | 
| 933 |  | - CXMLAttributes& templateAttributes = templateNode->GetAttributes(); | 
| 934 |  | - for (auto it = templateAttributes.ListBegin(); it != templateAttributes.ListEnd(); ++it) | 
| 935 |  | - { | 
| 936 |  | - CXMLAttribute* templateAttribute = *it; | 
| 937 |  | - const SString& attributeName = templateAttribute->GetName(); | 
| 938 |  | - const SString& attributeValue = templateAttribute->GetValue(); | 
|  | 939 | + const std::string templateNodeValue = templateNode->GetTagContent(); | 
|  | 940 | + const SString templateNodeComment = templateNode->GetCommentText(); | 
| 939 | 941 | 
 | 
| 940 |  | - CXMLAttribute* newAttribute = foundNode->GetAttributes().Create(attributeName); | 
| 941 |  | - if (newAttribute) | 
| 942 |  | - newAttribute->SetValue(attributeValue); | 
| 943 |  | - } | 
| 944 |  | - hasConfigChanged = true; | 
|  | 942 | + foundNode = m_pRootNode->CreateSubNode(templateNodeName.c_str(), previousNode); | 
|  | 943 | + foundNode->SetTagContent(templateNodeValue.c_str()); | 
|  | 944 | + foundNode->SetCommentText(templateNodeComment.c_str(), true); | 
|  | 945 | + | 
|  | 946 | + CLogger::LogPrintf("Added missing '%s' setting to mtaserver.conf\n", templateNodeName.c_str()); | 
|  | 947 | + configChanged = true; | 
| 945 | 948 |  } | 
| 946 | 949 |  previousNode = foundNode; | 
| 947 | 950 |  } | 
| 948 |  | - | 
| 949 |  | - // Clean up | 
| 950 |  | - g_pServerInterface->GetXML()->DeleteXML(templateFile); | 
| 951 |  | - FileDelete(templateFileName); | 
| 952 |  | - return hasConfigChanged; | 
|  | 951 | + return configChanged; | 
| 953 | 952 | } | 
| 954 | 953 | 
 | 
| 955 | 954 | bool CMainConfig::IsValidPassword(const char* szPassword) | 
|  | 
0 commit comments