core/concmd_cleaner.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Sat Sep 10 12:08:38 2011 -0400 (2011-09-10)
changeset 3389 68d3e56f4bb7
parent 2806 686c283b08fc
child 3819 d17aed3d46bf
permissions -rw-r--r--
Added CheckAccess native to check cmd/override access of AdminId (bug 5083, r=fyren).
dvander@1582
     1
/**
dvander@1582
     2
 * vim: set ts=4 :
dvander@1582
     3
 * =============================================================================
dvander@1582
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@1582
     6
 * =============================================================================
dvander@1582
     7
 *
dvander@1582
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@1582
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@1582
    10
 * Free Software Foundation.
dvander@1582
    11
 * 
dvander@1582
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@1582
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@1582
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@1582
    15
 * details.
dvander@1582
    16
 *
dvander@1582
    17
 * You should have received a copy of the GNU General Public License along with
dvander@1582
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1582
    19
 *
dvander@1582
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@1582
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@1582
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@1582
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@1582
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@1582
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@1582
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@1582
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@1582
    28
 *
dvander@1582
    29
 * Version: $Id$
dvander@1582
    30
 */
dvander@1582
    31
dvander@1582
    32
#include "sm_globals.h"
dvander@1582
    33
#include <sh_list.h>
dvander@1582
    34
#include <convar.h>
dvander@1582
    35
#include "concmd_cleaner.h"
dvander@1582
    36
#include "sm_stringutil.h"
dvander@1582
    37
#include "sourcemm_api.h"
ds@2400
    38
#include "compat_wrappers.h"
dvander@1582
    39
ds@2400
    40
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1582
    41
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
dvander@2806
    42
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
dvander@2806
    43
#else
dvander@2806
    44
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
dvander@1582
    45
#endif
dvander@1582
    46
dvander@1582
    47
using namespace SourceHook;
dvander@1582
    48
dvander@1582
    49
struct ConCommandInfo
dvander@1582
    50
{
dvander@1582
    51
	ConCommandBase *pBase;
dvander@1582
    52
	IConCommandTracker *cls;
dvander@1582
    53
	char name[64];
dvander@1582
    54
};
dvander@1582
    55
dvander@1582
    56
List<ConCommandInfo *> tracked_bases;
dvander@2806
    57
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
dvander@1582
    58
dvander@1582
    59
ConCommandBase *FindConCommandBase(const char *name);
dvander@1582
    60
dvander@1582
    61
class ConCommandCleaner : public SMGlobalClass
dvander@1582
    62
{
dvander@1582
    63
public:
dvander@1582
    64
	void OnSourceModAllInitialized()
dvander@1582
    65
	{
dvander@2806
    66
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1585
    67
		SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
dvander@2806
    68
		SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
dvander@2806
    69
#else
dvander@2806
    70
		SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
dvander@2806
    71
#endif
dvander@1582
    72
	}
dvander@1582
    73
dvander@1582
    74
	void OnSourceModShutdown()
dvander@1582
    75
	{
dvander@2806
    76
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1585
    77
		SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
dvander@2806
    78
		SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
dvander@2806
    79
#else
dvander@2806
    80
		SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
dvander@2806
    81
#endif
dvander@1582
    82
	}
dvander@2806
    83
dvander@2806
    84
	void LinkConCommandBase(ConCommandBase *pBase)
dvander@2806
    85
	{
dvander@2806
    86
		IConCommandLinkListener *listener = IConCommandLinkListener::head;
dvander@2806
    87
		while (listener)
dvander@2806
    88
		{
dvander@2806
    89
			listener->OnLinkConCommand(pBase);
dvander@2806
    90
			listener = listener->next;
dvander@2806
    91
		}
dvander@2806
    92
	}
dvander@1582
    93
dvander@1582
    94
	void UnlinkConCommandBase(ConCommandBase *pBase)
dvander@1582
    95
	{
dvander@1582
    96
		ConCommandInfo *pInfo;
dvander@1582
    97
		List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
dvander@1582
    98
dvander@2806
    99
		IConCommandLinkListener *listener = IConCommandLinkListener::head;
dvander@2806
   100
		while (listener)
dvander@2806
   101
		{
dvander@2806
   102
			listener->OnUnlinkConCommand(pBase);
dvander@2806
   103
			listener = listener->next;
dvander@2806
   104
		}
dvander@2806
   105
dvander@1582
   106
		if (pBase)
dvander@1582
   107
		{
dvander@1582
   108
			while (iter != tracked_bases.end())
dvander@1582
   109
			{
dvander@1582
   110
				if ((*iter)->pBase == pBase)
dvander@1582
   111
				{
dvander@1582
   112
					pInfo = (*iter);
dvander@1582
   113
					iter = tracked_bases.erase(iter);
dvander@1582
   114
					pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
dvander@1582
   115
					delete pInfo;
dvander@1582
   116
				}
dvander@1582
   117
				else
dvander@1582
   118
				{
dvander@1582
   119
					iter++;
dvander@1582
   120
				}
dvander@1582
   121
			}
dvander@1582
   122
		}
dvander@1582
   123
		else
dvander@1582
   124
		{
dvander@1582
   125
			while (iter != tracked_bases.end())
dvander@1582
   126
			{
dvander@1582
   127
				/* This is just god-awful! */
ds@2400
   128
				if (FindCommandBase((*iter)->name) != (*iter)->pBase)
dvander@1582
   129
				{
dvander@1582
   130
					pInfo = (*iter);
dvander@1582
   131
					iter = tracked_bases.erase(iter);
dvander@1584
   132
					pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
dvander@1582
   133
					delete pInfo;
dvander@1582
   134
				}
dvander@1582
   135
				else
dvander@1582
   136
				{
dvander@1582
   137
					iter++;
dvander@1582
   138
				}
dvander@1582
   139
			}
dvander@1582
   140
		}
dvander@1582
   141
	}
dvander@1582
   142
dvander@1582
   143
	void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
dvander@1582
   144
	{
dvander@1582
   145
		ConCommandInfo *info = new ConCommandInfo;
dvander@1582
   146
dvander@1582
   147
		info->pBase = pBase;
dvander@1582
   148
		info->cls = cls;
dvander@1582
   149
		strncopy(info->name, pBase->GetName(), sizeof(info->name));
dvander@1582
   150
dvander@1582
   151
		tracked_bases.push_back(info);
dvander@1582
   152
	}
dvander@1582
   153
dvander@1582
   154
	void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls)
dvander@1582
   155
	{
dvander@1582
   156
		List<ConCommandInfo *>::iterator iter;
dvander@1582
   157
		ConCommandInfo *pInfo;
dvander@1582
   158
dvander@1582
   159
		iter = tracked_bases.begin();
dvander@1582
   160
		while (iter != tracked_bases.end())
dvander@1582
   161
		{
dvander@1582
   162
			pInfo = (*iter);
dvander@1582
   163
			if (pInfo->pBase == pBase && pInfo->cls == cls)
dvander@1582
   164
			{
dvander@1582
   165
				delete pInfo;
dvander@1582
   166
				iter = tracked_bases.erase(iter);
dvander@1582
   167
			}
dvander@1582
   168
			else
dvander@1582
   169
			{
dvander@1582
   170
				iter++;
dvander@1582
   171
			}
dvander@1582
   172
		}
dvander@1582
   173
	}
dvander@1582
   174
} s_ConCmdTracker;
dvander@1582
   175
dvander@1582
   176
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
dvander@1582
   177
{
dvander@1582
   178
	s_ConCmdTracker.AddTarget(pBase, me);
dvander@1582
   179
}
dvander@1582
   180
dvander@1582
   181
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
dvander@1582
   182
{
dvander@1582
   183
	s_ConCmdTracker.RemoveTarget(pBase, me);
dvander@1582
   184
}
dvander@1582
   185
dvander@1582
   186
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase)
dvander@1582
   187
{
dvander@1582
   188
	s_ConCmdTracker.UnlinkConCommandBase(pBase);
dvander@1582
   189
}