Browse Source

Initial commit

Current filter setup only handles unprintable characters and newlines.
nosoop 7 years ago
parent
commit
5ab91c9403
1 changed files with 159 additions and 0 deletions
  1. 159 0
      scripting/csrd_name_filter.sp

+ 159 - 0
scripting/csrd_name_filter.sp

@@ -0,0 +1,159 @@
+/**
+ * [CSRD] Name Filter
+ * 
+ * An in-house plugin that tidies up names.
+ * Made in response to a few script kiddies that are (ab)using newlines and other non-printing
+ * characters in their name.
+ * 
+ */
+#pragma semicolon 1
+#include <sourcemod>
+
+#include <sdktools_functions>
+
+#pragma newdecls required
+
+#define PLUGIN_VERSION "1.0.0"
+public Plugin myinfo = {
+	name = "[CSRD] Name Filter",
+	author = "nosoop",
+	description = "Filters out rather unscrupulous characters from names and locks the name if "
+			... "they are using a completely non-printable name.",
+	version = PLUGIN_VERSION,
+	url = "https://pika.nom-nom-nom.us/git/"
+}
+
+#define UNPRINTABLE_NAME_USER_FORMAT "unprintable (%d)"
+
+bool g_bNameLockSupported;
+
+int g_FilteredWhitespace[] = {
+	0xe2a080, // braille pattern blank U+2800
+	0x0a, // linefeed
+	0x0d, // carriage return
+	0
+};
+
+public void OnPluginStart() {
+	for (int i = 1; i <= MaxClients; i++) {
+		if (IsClientConnected(i)) {
+			OnNameUpdated(i);
+		}
+	}
+	
+	g_bNameLockSupported = CommandExists("namelockid");
+}
+
+public void OnClientConnected(int client) {
+	OnNameUpdated(client);
+}
+
+public void OnClientSettingsChanged(int client) {
+	OnNameUpdated(client);
+}
+
+void OnNameUpdated(int client) {
+	char currentName[MAX_NAME_LENGTH], newNameBuffer[MAX_NAME_LENGTH];
+	
+	GetClientName(client, currentName, sizeof(currentName));
+	
+	bool bNameChanged;
+	
+	/**
+	 * Copies valid characters into another buffer (while also dealing with Unicode).
+	 * The buffer is used if any characters are filtered.
+	 */
+	for (int i = 0; i < strlen(currentName); /* ... */) {
+		int fullChar, nCharBytes;
+		fullChar = GetMultiByteCharacterAt(currentName, i, nCharBytes);
+		
+		bool bCharFiltered;
+		
+		// Filter out whitespace
+		int c;
+		do {
+			bCharFiltered |= (fullChar == g_FilteredWhitespace[c]);
+		} while (g_FilteredWhitespace[++c] != 0 && !bCharFiltered);
+		
+		if (!bCharFiltered) {
+			// it's a character that we don't really care about 
+			StrCatMultiByteChar(newNameBuffer, sizeof(newNameBuffer), fullChar, nCharBytes);
+		} else {
+			StrCat(newNameBuffer, sizeof(newNameBuffer), " ");
+		}
+		
+		bNameChanged |= bCharFiltered;
+		
+		i += nCharBytes;
+	}
+	
+	if (bNameChanged) {
+		// Remove surrounding whitespace
+		TrimString(newNameBuffer);
+		
+		// If there's no printable characters in the buffer, the player is a total dongbus.
+		if (strlen(newNameBuffer) == 0) {
+			Format(newNameBuffer, sizeof(newNameBuffer), UNPRINTABLE_NAME_USER_FORMAT,
+					GetClientUserId(client));
+			
+			SetClientNameLock(client);
+		}
+		SetClientName(client, newNameBuffer);
+	}
+	// TODO else not name changed, but check if we can do other non-filter stuff? (trim)
+}
+
+/**
+ * Attempts to lock the specified client's name.
+ */
+stock void SetClientNameLock(int client, bool locked = true) {
+	if (g_bNameLockSupported) {
+		ServerCommand("namelockid %d %d", GetClientUserId(client), locked ? 0 : 1);
+	}
+}
+
+/**
+ * Gets a possibly multi-byte character at the specified position in a string as an integer.
+ * 
+ * If the character is an ASCII character, the integer representation of the character will be
+ * returned, and the number of characters read will be 1.
+ * 
+ * This stock is made specifically for the purpose of handling strings with multi-byte
+ * characters.
+ */
+stock int GetMultiByteCharacterAt(const char[] text, int pos, int &read = 0) {
+	int nCharBytes, charOutput;
+	
+	nCharBytes = GetCharBytes(text[pos]);
+	
+	for (int b = 0; b < nCharBytes; b++) {
+		charOutput = charOutput << 8;
+		
+		// read in the current byte
+		charOutput |= text[pos + b] & 0xFF;
+		
+		read++;
+	}
+	
+	return charOutput;
+}
+
+/**
+ * Appends a multi-byte character to a string.
+ */
+stock void StrCatMultiByteChar(char[] buffer, int maxlen, int character, int size) {
+	char[] appended = new char[size];
+	
+	MultiByteCharacterToCharArray(appended, size, character);
+	
+	StrCat(buffer, maxlen, appended);
+}
+
+/**
+ * Converts a multi-byte character to a char array.
+ */
+stock void MultiByteCharacterToCharArray(char[] buffer, int charsize, int character) {
+	for (int i = 0; i < charsize; i++) {
+		buffer[i] = (character >> ((charsize - i - 1) * 8 )) & 0xFF;
+	}
+}