Skip to content

Commit eda0d81

Browse files
committed
Implement ACL request fingerprinting and change detection in CResource
1 parent 0d930ac commit eda0d81

File tree

4 files changed

+75
-3
lines changed

4 files changed

+75
-3
lines changed

Server/mods/deathmatch/logic/CResource.AclRequest.cpp

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ bool CResource::HasAutoPermissions(CXMLNode* pNodeAclRequest)
123123
///////////////////////////////////////////////////////////////
124124
void CResource::RefreshAutoPermissions(CXMLNode* pNodeAclRequest)
125125
{
126-
// Check if permissions already active
127-
if (HasAutoPermissions(pNodeAclRequest))
128-
return;
129126

130127
// Ensure group and acl exist
131128
CAccessControlListGroup* pAutoGroup = g_pGame->GetACLManager()->AddGroup(GetAutoGroupName());
@@ -372,3 +369,53 @@ bool CResource::FindAclRequest(SAclRequest& result)
372369

373370
return pAclRight->GetAttributeValue("pending") != "";
374371
}
372+
373+
std::string CResource::CalculateACLRequestFingerprint()
374+
{
375+
std::string strPath;
376+
if (!GetFilePath("meta.xml", strPath))
377+
return "";
378+
379+
CXMLFile* pMetaFile = g_pServerInterface->GetXML()->CreateXML(strPath.c_str());
380+
if (!pMetaFile || !pMetaFile->Parse())
381+
{
382+
delete pMetaFile;
383+
return "";
384+
}
385+
386+
CXMLNode* pRoot = pMetaFile->GetRootNode();
387+
if (!pRoot)
388+
{
389+
delete pMetaFile;
390+
return "";
391+
}
392+
393+
std::string strFingerprint;
394+
CXMLNode* pNodeAclRequest = pRoot->FindSubNode("aclrequest", 0);
395+
396+
if (pNodeAclRequest)
397+
{
398+
for (uint uiIndex = 0; true; uiIndex++)
399+
{
400+
CXMLNode* pNodeRight = pNodeAclRequest->FindSubNode("right", uiIndex);
401+
if (!pNodeRight)
402+
break;
403+
404+
std::string strName = pNodeRight->GetAttributeValue("name");
405+
std::string strAccess = pNodeRight->GetAttributeValue("access");
406+
407+
if (!strFingerprint.empty())
408+
strFingerprint += ";";
409+
strFingerprint += strName + ":" + strAccess;
410+
}
411+
}
412+
413+
delete pMetaFile;
414+
return strFingerprint;
415+
}
416+
417+
bool CResource::HasACLRequestsChanged()
418+
{
419+
std::string strCurrentFingerprint = CalculateACLRequestFingerprint();
420+
return strCurrentFingerprint != m_strACLRequestFingerprint;
421+
}

Server/mods/deathmatch/logic/CResource.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ bool CResource::Load()
196196
else
197197
RemoveAutoPermissions();
198198

199+
m_strACLRequestFingerprint = CalculateACLRequestFingerprint();
200+
199201
// Find any map sync option
200202
m_bSyncMapElementData = true;
201203
m_bSyncMapElementDataDefined = false;
@@ -351,6 +353,7 @@ bool CResource::Unload()
351353
m_strResourceZip = "";
352354
m_strResourceCachePath = "";
353355
m_strResourceDirectoryPath = "";
356+
m_strACLRequestFingerprint.clear();
354357
m_eState = EResourceState::None;
355358

356359
return true;
@@ -402,6 +405,8 @@ CResource::~CResource()
402405

403406
void CResource::TidyUp()
404407
{
408+
RemoveAutoPermissions();
409+
405410
// Close the zipfile stuff
406411
if (m_zipfile)
407412
unzClose(m_zipfile);
@@ -678,6 +683,11 @@ bool CResource::HasResourceChanged()
678683
return true;
679684
}
680685

686+
if (HasACLRequestsChanged())
687+
{
688+
return true;
689+
}
690+
681691
return false;
682692
}
683693

@@ -1195,6 +1205,9 @@ bool CResource::Stop(bool bManualStop)
11951205
// Clear the list of players where this resource is running
11961206
std::exchange(m_isRunningForPlayer, {});
11971207

1208+
// Remove ACL permissions when stopping
1209+
RemoveAutoPermissions();
1210+
11981211
OnResourceStateChange("loaded");
11991212
m_eState = EResourceState::Loaded;
12001213
return true;

Server/mods/deathmatch/logic/CResource.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ class CResource : public EHS
349349
void CommitAclRequest(const SAclRequest& request);
350350
bool FindAclRequest(SAclRequest& request);
351351

352+
std::string CalculateACLRequestFingerprint();
353+
bool HasACLRequestsChanged();
354+
352355
private:
353356
bool CheckState(); // if the resource has no Dependents, stop it, if it has, start it. returns true if the resource is started.
354357
bool ReadIncludedResources(CXMLNode* pRoot);
@@ -450,6 +453,7 @@ class CResource : public EHS
450453
SString m_strMinServerReason;
451454

452455
CChecksum m_metaChecksum; // Checksum of meta.xml last time this was loaded, generated in GenerateChecksums()
456+
std::string m_strACLRequestFingerprint;
453457

454458
uint m_uiFunctionRightCacheRevision = 0;
455459
CFastHashMap<lua_CFunction, bool> m_FunctionRightCacheMap;

Server/mods/deathmatch/logic/CResourceManager.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ bool CResourceManager::Refresh(bool bRefreshAll, const SString strJustThisResour
184184
// Add the resource
185185
Load(!info.bIsDir, info.strAbsPath, info.strName);
186186
}
187+
else if (pResource && pResource->HasResourceChanged())
188+
{
189+
if (g_pServerInterface->IsRequestingExit())
190+
return false;
191+
192+
// Resource exists but has changed, reload it
193+
Load(!info.bIsDir, info.strAbsPath, info.strName);
194+
}
187195
}
188196
}
189197

0 commit comments

Comments
 (0)