diff options
| -rw-r--r-- | LICENSE.md (renamed from LICENSE) | 0 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | nameblocker.sp | 264 |
3 files changed, 108 insertions, 160 deletions
| @@ -6,3 +6,7 @@ TF2 Name Blocker is a simple sourcemod plugin that prevents users with certain n | |||
| 6 | 6 | ||
| 7 | ## Features | 7 | ## Features |
| 8 | 8 | ||
| 9 | - Add, remove, and replace regular expression patterns to a filter-list | ||
| 10 | - Kick, ban, or do nothing to users with offending names | ||
| 11 | - Target admins based off of immunity flags | ||
| 12 | - Change the compilation flags used to create the regular expression | ||
diff --git a/nameblocker.sp b/nameblocker.sp index 8e6ab33..9611efa 100644 --- a/nameblocker.sp +++ b/nameblocker.sp | |||
| @@ -52,6 +52,8 @@ public Plugin myinfo = { | |||
| 52 | // This exists because you can't sizeof() a Handle, but it IS specified to be a 32bit integer. This should also equal the size of | 52 | // This exists because you can't sizeof() a Handle, but it IS specified to be a 32bit integer. This should also equal the size of |
| 53 | // any other methodmap or descendant of Handle (like Regex) | 53 | // any other methodmap or descendant of Handle (like Regex) |
| 54 | 54 | ||
| 55 | #define STEAMID64LENGTH 17 | ||
| 56 | |||
| 55 | #define PATTERN_MAX_LEN (512 + 1) /* 512 chars + null terminator */ | 57 | #define PATTERN_MAX_LEN (512 + 1) /* 512 chars + null terminator */ |
| 56 | #define DATABASE_FAIL_MSG "Could not populate regex & pattern lists from database" | 58 | #define DATABASE_FAIL_MSG "Could not populate regex & pattern lists from database" |
| 57 | 59 | ||
| @@ -65,11 +67,18 @@ enum OperatingMode { | |||
| 65 | ArrayList regexlist; | 67 | ArrayList regexlist; |
| 66 | ArrayList patternlist; | 68 | ArrayList patternlist; |
| 67 | 69 | ||
| 68 | Database db; static const char DBTABLENAME[] = "163687013_SMNameBlocker"; | 70 | #define DBTABLENAME "163687013_SMNameBlocker" |
| 69 | DBStatement dbInsert; static const char DBINSERTSTATEMENT[] = "INSERT OR IGNORE INTO ? (regexstr, steamid64) VALUES (?, ?);"; | 71 | #define DBCREATETABLE "CREATE TABLE IF NOT EXISTS " ... DBTABLENAME ... " (id INTEGER NOT NULL, regexstr TEXT NOT NULL ON CONFLICT IGNORE, steamid64 TEXT NOT NULL ON CONFLICT IGNORE, dateof TEXT DEFAULT CURRENT_DATE, timeof TEXT DEFAULT CURRENT_TIME, PRIMARY KEY (id), UNIQUE (regexstr));" |
| 70 | DBStatement dbDelete; static const char DBDELETESTATEMENT[] = "DELETE FROM ? WHERE regexstr=?;"; | 72 | #define DBINSERTSTATEMENT "INSERT OR IGNORE INTO " ... DBTABLENAME ... " (regexstr, steamid64) VALUES (?, ?);" |
| 71 | DBStatement dbReplace; static const char DBREPLACESTATEMENT[] = "UPDATE OR IGNORE ? SET regexstr=?, steamid64=? WHERE regexstr=?;"; | 73 | #define DBDELETESTATEMENT "DELETE FROM " ... DBTABLENAME ... " WHERE regexstr=?;" |
| 72 | DBStatement dbPopulate; static const char DBPOPULATESTATEMENT[] = "SELECT regexstr FROM ?"; | 74 | #define DBREPLACESTATEMENT "UPDATE OR IGNORE " ... DBTABLENAME ... " SET regexstr=?, steamid64=? WHERE regexstr=?;" |
| 75 | #define DBPOPULATESTATEMENT "SELECT regexstr FROM " ... DBTABLENAME | ||
| 76 | |||
| 77 | Database db; | ||
| 78 | DBStatement dbInsert; | ||
| 79 | DBStatement dbDelete; | ||
| 80 | DBStatement dbReplace; | ||
| 81 | DBStatement dbPopulate; | ||
| 73 | 82 | ||
| 74 | 83 | ||
| 75 | ConVar gcvarOperMode; static const char OPERMODENAME[] = "nameblock_OperatingMode"; const OperatingMode DEFAULTOPERMODE = OP_KICK; | 84 | ConVar gcvarOperMode; static const char OPERMODENAME[] = "nameblock_OperatingMode"; const OperatingMode DEFAULTOPERMODE = OP_KICK; |
| @@ -125,85 +134,66 @@ void xRegisterIntConVar(ConVar& cv, int defaultVal, const char[] name, const cha | |||
| 125 | 134 | ||
| 126 | int initPrepStatements() { | 135 | int initPrepStatements() { |
| 127 | char sqlerr[256 + 1]; | 136 | char sqlerr[256 + 1]; |
| 128 | 137 | int err = 0; | |
| 138 | |||
| 129 | SQL_LockDatabase(db); | 139 | SQL_LockDatabase(db); |
| 130 | if((dbInsert = SQL_PrepareQuery(db, DBINSERTSTATEMENT, sqlerr, sizeof(sqlerr))) == null) { | 140 | if((dbInsert = SQL_PrepareQuery(db, DBINSERTSTATEMENT, sqlerr, sizeof(sqlerr))) == null && !err) |
| 131 | SQL_UnlockDatabase(db); | 141 | err = 1; |
| 132 | logAndFail("Could not prepare insert statement: %s", sqlerr); | ||
| 133 | } | ||
| 134 | if((dbDelete = SQL_PrepareQuery(db, DBDELETESTATEMENT, sqlerr, sizeof(sqlerr))) == null) { | ||
| 135 | SQL_UnlockDatabase(db); | ||
| 136 | logAndFail("Could not prepare delete statement: %s", sqlerr); | ||
| 137 | } | ||
| 138 | if((dbReplace = SQL_PrepareQuery(db, DBREPLACESTATEMENT, sqlerr, sizeof(sqlerr))) == null) { | ||
| 139 | SQL_UnlockDatabase(db); | ||
| 140 | logAndFail("Could not prepare replace statement: %s", sqlerr); | ||
| 141 | } | ||
| 142 | if((dbPopulate = SQL_PrepareQuery(db, DBPOPULATESTATEMENT, sqlerr, sizeof(sqlerr))) == null) { | ||
| 143 | SQL_UnlockDatabase(db); | ||
| 144 | logAndFail("Could not prepare populate statement: %s", sqlerr); | ||
| 145 | } | ||
| 146 | 142 | ||
| 147 | // This might not work / I might have to use Format() instead of binding. We will see | 143 | if((dbDelete = SQL_PrepareQuery(db, DBDELETESTATEMENT, sqlerr, sizeof(sqlerr))) == null && !err) |
| 148 | if(SQL_BindParamString(dbInsert, 0, DBTABLENAME, true)) { | 144 | err = 2; |
| 149 | SQL_GetError(dbInsert, sqlerr, sizeof(sqlerr)); | ||
| 150 | SQL_UnlockDatabase(db); | ||
| 151 | logAndFail("Could not bind tablename to insert statement: %s", sqlerr); | ||
| 152 | } | ||
| 153 | if(SQL_BindParamString(dbDelete, 0, DBTABLENAME, true)) { | ||
| 154 | SQL_GetError(dbDelete, sqlerr, sizeof(sqlerr)); | ||
| 155 | SQL_UnlockDatabase(db); | ||
| 156 | logAndFail("Could not bind tablename to delete statement: %s", sqlerr); | ||
| 157 | } | ||
| 158 | if( SQL_BindParamString(dbReplace, 0, DBTABLENAME, true)) { | ||
| 159 | SQL_GetError(dbReplace, sqlerr, sizeof(sqlerr)); | ||
| 160 | SQL_UnlockDatabase(db); | ||
| 161 | logAndFail("Could not bind tablename to replace statement: %s", sqlerr); | ||
| 162 | } | ||
| 163 | if(SQL_BindParamString(dbPopulate, 0, DBTABLENAME, true)) { | ||
| 164 | SQL_GetError(dbPopulate, sqlerr, sizeof(sqlerr)); | ||
| 165 | SQL_UnlockDatabase(db); | ||
| 166 | logAndFail("Could not bind tablename to populate statement: %s", sqlerr); | ||
| 167 | } | ||
| 168 | 145 | ||
| 169 | // If I knew how to do macros this would be much nicer | 146 | if((dbReplace = SQL_PrepareQuery(db, DBREPLACESTATEMENT, sqlerr, sizeof(sqlerr))) == null && !err) |
| 147 | err = 3; | ||
| 148 | |||
| 149 | if((dbPopulate = SQL_PrepareQuery(db, DBPOPULATESTATEMENT, sqlerr, sizeof(sqlerr))) == null && !err) | ||
| 150 | err = 4; | ||
| 170 | 151 | ||
| 171 | SQL_UnlockDatabase(db); | 152 | SQL_UnlockDatabase(db); |
| 153 | switch(err) { | ||
| 154 | case 1: {logAndFail("Could not prepare insert statement: %s", sqlerr);} | ||
| 155 | case 2: {logAndFail("Could not prepare delete statement: %s", sqlerr);} | ||
| 156 | case 3: {logAndFail("Could not prepare replace statement: %s", sqlerr);} | ||
| 157 | case 4: {logAndFail("Could not prepare populate statement: %s", sqlerr);} | ||
| 158 | } | ||
| 159 | |||
| 172 | return 0; | 160 | return 0; |
| 173 | } | 161 | } |
| 174 | 162 | ||
| 175 | int loadFromDatabase() { | 163 | int loadFromDatabase() { |
| 176 | // Initialize and populate datatypes | 164 | // Initialize and populate datatypes |
| 177 | regexlist = new ArrayList(ByteCountToCells(HANDLE_SIZE)); | 165 | regexlist = new ArrayList(ByteCountToCells(HANDLE_SIZE)); |
| 178 | if(regexlist == null) logAndFail("Could not initialize regexlist ArrayList"); | 166 | if(regexlist == null) logAndFail("Could not initialize regexlist ArrayList"); |
| 179 | 167 | ||
| 180 | patternlist = new ArrayList(ByteCountToCells(PATTERN_MAX_LEN)); | 168 | patternlist = new ArrayList(ByteCountToCells(PATTERN_MAX_LEN)); |
| 181 | if(patternlist == null) logAndFail("Could not initialize patternlist ArrayList"); | 169 | if(patternlist == null) logAndFail("Could not initialize patternlist ArrayList"); |
| 182 | 170 | ||
| 171 | |||
| 183 | // Get database handle | 172 | // Get database handle |
| 184 | char sqlerr[256 + 1]; | 173 | char sqlerr[256 + 1]; |
| 185 | db = SQLite_UseDatabase("sourcemod-local", sqlerr, sizeof(sqlerr)); | 174 | db = SQLite_UseDatabase("sourcemod-local", sqlerr, sizeof(sqlerr)); |
| 186 | if(db == null) logAndFail("Could not connect to sql database: %s", sqlerr); | 175 | if(db == null) logAndFail("Could not connect to sql database: %s", sqlerr); |
| 187 | 176 | ||
| 188 | // Initialize table if it doesn't exist | 177 | // Initialize table if it doesn't exist |
| 189 | // I could make this a prepared statement, but I don't believe it's entirely necessary | 178 | int err = 0; |
| 190 | char sqlcbuf[256 + 1]; | ||
| 191 | Format(sqlcbuf, sizeof(sqlcbuf), "CREATE TABLE IF NOT EXISTS \"%s\" (id INTEGER NOT NULL, regexstr TEXT NOT NULL ON CONFLICT IGNORE, steamid64 TEXT NOT NULL ON CONFLICT IGNORE, dateof TEXT DEFAULT CURRENT_DATE, timeof TEXT DEFAULT CURRENT_TIME, PRIMARY KEY (id), UNIQUE (regexstr));", DBTABLENAME); | ||
| 192 | |||
| 193 | SQL_LockDatabase(db); | 179 | SQL_LockDatabase(db); |
| 194 | if(!SQL_FastQuery(db, sqlcbuf)) { | 180 | if(!SQL_FastQuery(db, DBCREATETABLE)) { |
| 195 | SQL_GetError(db, sqlerr, sizeof(sqlerr)); | 181 | SQL_GetError(db, sqlerr, sizeof(sqlerr)); |
| 196 | SQL_UnlockDatabase(db); | 182 | err = 1; |
| 197 | logAndFail("Could not initialize nameblocker table: %s", sqlerr); | ||
| 198 | } | 183 | } |
| 199 | 184 | ||
| 200 | // select patterns from nameblock table/database | 185 | // select patterns from nameblock table/database |
| 201 | if(SQL_Execute(dbPopulate)) { | 186 | if(SQL_Execute(dbPopulate) && !err) { |
| 202 | SQL_GetError(dbPopulate, sqlerr, sizeof(sqlerr)); | 187 | SQL_GetError(dbPopulate, sqlerr, sizeof(sqlerr)); |
| 203 | SQL_UnlockDatabase(db); | 188 | err = 2; |
| 204 | logAndFail("Population query failed"); | ||
| 205 | } | 189 | } |
| 190 | |||
| 206 | SQL_UnlockDatabase(db); | 191 | SQL_UnlockDatabase(db); |
| 192 | switch(err) { | ||
| 193 | case 1: {logAndFail("Could not initialize nameblocker table: %s", sqlerr);} | ||
| 194 | case 2: {logAndFail("Population query failed: %s", sqlerr);} | ||
| 195 | } | ||
| 196 | |||
| 207 | 197 | ||
| 208 | // compile each pattern & insert | 198 | // compile each pattern & insert |
| 209 | Regex cur; char reerr[256]; RegexError reenum; | 199 | Regex cur; char reerr[256]; RegexError reenum; |
| @@ -231,10 +221,10 @@ public void OnAllPluginsLoaded() { | |||
| 231 | loadFromDatabase(); | 221 | loadFromDatabase(); |
| 232 | 222 | ||
| 233 | // Register convars | 223 | // Register convars |
| 234 | xRegisterIntConVar(gcvarOperMode, view_as<int>(DEFAULTOPERMODE), OPERMODENAME, "Operating mode (disabled, kick, ban, etc.)"); | 224 | xRegisterIntConVar(gcvarOperMode, DEFAULTOPERMODE, OPERMODENAME, "Operating mode (disabled, kick, ban, etc.)"); |
| 235 | xRegisterIntConVar(gcvarAdmCmdFlag, DEFAULTADMCMDFLAG, ADMCMDFLAGNAME, "Admin flag to modify pattern list"); | 225 | xRegisterIntConVar(gcvarAdmCmdFlag, DEFAULTADMCMDFLAG, ADMCMDFLAGNAME, "Admin flag to modify pattern list"); |
| 236 | xRegisterIntConVar(gcvarRegexCompFlags, DEFAULTREGEXCOMPFLAGS, REGEXCOMPFLAGSNAME, "Regular expression compilation flags"); | 226 | xRegisterIntConVar(gcvarRegexCompFlags, DEFAULTREGEXCOMPFLAGS, REGEXCOMPFLAGSNAME, "Regular expression compilation flags"); |
| 237 | xRegisterIntConVar(gcvarAmdImmFlag, DEFAULTADMIMMFLAG, ADMINIMMUNITYFLAGNAME, "Admin immunity flag"); | 227 | xRegisterIntConVar(gcvarAmdImmFlag, DEFAULTADMIMMFLAG, ADMINIMMUNITYFLAGNAME, "Admin immunity flag"); |
| 238 | 228 | ||
| 239 | AutoExecConfig(true, "nameblocker_cvars"); | 229 | AutoExecConfig(true, "nameblocker_cvars"); |
| 240 | 230 | ||
| @@ -341,49 +331,74 @@ enum MOD_MODE { | |||
| 341 | MM_TOOBIG | 331 | MM_TOOBIG |
| 342 | }; | 332 | }; |
| 343 | 333 | ||
| 344 | int modPattern(MOD_MODE mode, int index, char[] pattern="", int patternlen=0) { | 334 | int __modPattern__insert(int index, char[] pattern, int patternlen, int client) { |
| 345 | if(index < 0 || index > regexlist.Length) return -1; | 335 | if(IsNullString(pattern) || patternlen < 0 || patternlen > PATTERN_MAX_LEN || client < 0) {return -1;} |
| 346 | 336 | ||
| 347 | switch(mode) { | 337 | char steamid64[STEAMID64LENGTH + 1]; |
| 348 | case MM_INSERT: { | 338 | if(GetClientAuthId(client, AuthId_SteamID64, steamid64, sizeof(steamid64))) {} // TODO: Error handling |
| 349 | if(IsNullString(pattern) || patternlen < 0 || patternlen > PATTERN_MAX_LEN) {return -1;} | ||
| 350 | 339 | ||
| 351 | // Add pattern to database | 340 | SQL_LockDatabase(db); |
| 352 | SQL_LockDatabase(db); | 341 | SQL_BindParamString(dbInsert, 0, pattern, false); |
| 353 | SQL_UnlockDatabase(db); | 342 | SQL_BindParamString(dbInsert, 1, steamid64, false); |
| 343 | if(!SQL_Execute(dbInsert)) {} // TODO: Error handling | ||
| 344 | SQL_UnlockDatabase(db); | ||
| 354 | 345 | ||
| 355 | aModPattern(mode, index, pattern); | 346 | if(aModPattern(MM_INSERT, index, pattern)) {} // TODO: Error handling |
| 356 | } | ||
| 357 | 347 | ||
| 358 | case MM_DELETE: { | 348 | return 0; |
| 359 | // Detele from database | 349 | } |
| 360 | SQL_LockDatabase(db); | 350 | int __modPattern__delete(int index) { |
| 361 | SQL_UnlockDatabase(db); | 351 | char pattern[PATTERN_MAX_LEN]; |
| 352 | patternlist.GetString(index, pattern, sizeof(pattern), ByteCountToCells(PATTERN_MAX_LEN)); | ||
| 362 | 353 | ||
| 363 | aModPattern(mode, index); | 354 | SQL_LockDatabase(db); |
| 364 | } | 355 | SQL_BindParamString(dbDelete, 0, pattern, false); |
| 356 | if(SQL_Execute(dbDelete)) {} // TODO: Error handling | ||
| 357 | SQL_UnlockDatabase(db); | ||
| 365 | 358 | ||
| 366 | case MM_REPLACE: { | 359 | if(aModPattern(MM_DELETE, index)) {} // TODO: Error handling |
| 367 | LogError("Replace mode not implemented yet"); | 360 | |
| 368 | return -1; | 361 | return 0; |
| 362 | } | ||
| 363 | int __modPattern__replace(int index, char[] pattern, int patternlen, int client) { | ||
| 364 | if(IsNullString(pattern) || patternlen < 0 || patternlen > PATTERN_MAX_LEN || client < 0) {return -1;} | ||
| 369 | 365 | ||
| 370 | // Replace in database | 366 | char oldpattern[PATTERN_MAX_LEN]; |
| 371 | // SQL_LockDatabase(db); | 367 | patternlist.GetString(index, oldpattern, sizeof(oldpattern), ByteCountToCells(PATTERN_MAX_LEN)); |
| 372 | // SQL_UnlockDatabase(db); | ||
| 373 | 368 | ||
| 374 | // aModPattern(mode, index, pattern); | 369 | char steamid64[STEAMID64LENGTH]; |
| 375 | } | 370 | if(GetClientAuthId(client, AuthId_SteamID64, steamid64, sizeof(steamid64))) {} // TODO: Error handling |
| 371 | |||
| 372 | SQL_LockDatabase(db); | ||
| 373 | SQL_BindParamString(dbReplace, 0, pattern, false); | ||
| 374 | SQL_BindParamString(dbReplace, 1, steamid64, false); | ||
| 375 | SQL_BindParamString(dbReplace, 2, oldpattern, false); | ||
| 376 | |||
| 377 | if(SQL_Execute(dbReplace)) {} // TODO: Error handling | ||
| 378 | SQL_UnlockDatabase(db); | ||
| 379 | |||
| 380 | if(aModPattern(MM_REPLACE, index, pattern)) {} // TODO: Error handling | ||
| 381 | |||
| 382 | return 0; | ||
| 383 | } | ||
| 384 | |||
| 385 | int modPattern(MOD_MODE mode, int index, char[] pattern="", int patternlen=-1, int client=-1) { | ||
| 386 | if(index < 0 || index > regexlist.Length) return -1; | ||
| 376 | 387 | ||
| 388 | switch(mode) { | ||
| 389 | case MM_INSERT: {return __modPattern__insert(index, pattern, patternlen, client);} | ||
| 390 | case MM_DELETE: {return __modPattern__delete(index);} | ||
| 391 | case MM_REPLACE: {return __modPattern__replace(index, pattern, patternlen, client);} | ||
| 377 | default: { | 392 | default: { |
| 378 | LogError("Given invalid DBMOD_MODE"); | 393 | LogError("Given invalid DBMOD_MODE"); |
| 379 | return -1; | 394 | return -1; |
| 380 | } | 395 | } |
| 381 | } | 396 | } |
| 382 | |||
| 383 | return 0; | ||
| 384 | } | 397 | } |
| 385 | 398 | ||
| 386 | int aModPattern(MOD_MODE mode, int index, char[] pattern="", int patternlen=0) { | 399 | int aModPattern(MOD_MODE mode, int index, char[] pattern="", int patternlen=0) { |
| 400 | LogError("aModPattern not implemented"); return -1; | ||
| 401 | |||
| 387 | if(mode <= MM_UNDEF || mode >= MM_TOOBIG || index < 0 || index > patternlist.Length) return -1; | 402 | if(mode <= MM_UNDEF || mode >= MM_TOOBIG || index < 0 || index > patternlist.Length) return -1; |
| 388 | 403 | ||
| 389 | if(mode > MM_DELETE) { | 404 | if(mode > MM_DELETE) { |
| @@ -448,7 +463,7 @@ int checkName(int client) { | |||
| 448 | m = MatchRegex(regexlist.Get(i), name, reerr); | 463 | m = MatchRegex(regexlist.Get(i), name, reerr); |
| 449 | 464 | ||
| 450 | if(m < 0) { | 465 | if(m < 0) { |
| 451 | handleFailedRegex(client, reerr); | 466 | handleFailedRegex(client); |
| 452 | return -1; | 467 | return -1; |
| 453 | } | 468 | } |
| 454 | if(m == 0) continue; | 469 | if(m == 0) continue; |
| @@ -481,87 +496,16 @@ int handleNameHit(int client) { | |||
| 481 | // BanClient() | 496 | // BanClient() |
| 482 | // TODO: Interop with other ban systems | 497 | // TODO: Interop with other ban systems |
| 483 | // Log ban | 498 | // Log ban |
| 499 | return 0; | ||
| 484 | } | 500 | } |
| 485 | default: { | 501 | default: { |
| 486 | LogError("%L failed a name check, but the operating mode in an invalid state", client); | 502 | LogError("%L failed a name check, but the operating mode in an invalid state", client); |
| 487 | return -1; | 503 | return -1; |
| 488 | } | 504 | } |
| 489 | } | 505 | } |
| 490 | |||
| 491 | LogError("Broke out of switch statement that shouldn't have happened"); | ||
| 492 | return -1; // Shouldn't get to this point | ||
| 493 | } | 506 | } |
| 494 | 507 | ||
| 495 | int handleFailedRegex(int client, RegexError reerr) { | 508 | int handleFailedRegex(int client) { |
| 496 | char regstr[128]; | 509 | LogError("Ran into regex error when trying to check user %L's name", client); |
| 497 | RegexStrError(reerr, regstr, sizeof(regstr)); | ||
| 498 | |||
| 499 | LogError("Ran into regex error when trying to check user %L's name. Reported regex error: %s", client, regstr); | ||
| 500 | return 0; | 510 | return 0; |
| 501 | } | ||
| 502 | |||
| 503 | |||
| 504 | |||
| 505 | // Note: May or may not be particularly descriptive for any given error | ||
| 506 | int RegexStrError(RegexError err, char[] buf, int buflen) { | ||
| 507 | if(IsNullString(buf)) return -1; | ||
| 508 | |||
| 509 | char tmp[64]; | ||
| 510 | switch(err) { | ||
| 511 | case REGEX_ERROR_NONE: {tmp = "No error";} | ||
| 512 | |||
| 513 | case REGEX_ERROR_ASSERT: {tmp = "Internal error";} | ||
| 514 | case REGEX_ERROR_BADBR: {tmp = "Invalid repeat counts in {}";} | ||
| 515 | case REGEX_ERROR_BADPAT: {tmp = "Pattern error";} | ||
| 516 | case REGEX_ERROR_BADRPT: {tmp = "? * + invalid";} | ||
| 517 | case REGEX_ERROR_EBRACE: {tmp = "Unbalanced {}";} | ||
| 518 | case REGEX_ERROR_EBRACK: {tmp = "Unbalanced []";} | ||
| 519 | case REGEX_ERROR_ECOLLATE: {tmp = "Collation error - not relevant";} | ||
| 520 | case REGEX_ERROR_ECTYPE: {tmp = "Bad class";} | ||
| 521 | case REGEX_ERROR_EESCAPE: {tmp = "Bad escape sequence";} | ||
| 522 | case REGEX_ERROR_EMPTY: {tmp = "Empty expression";} | ||
| 523 | case REGEX_ERROR_EPAREN: {tmp = "Unbalanced ()";} | ||
| 524 | case REGEX_ERROR_ERANGE: {tmp = "Bad range inside []";} | ||
| 525 | case REGEX_ERROR_ESIZE: {tmp = "Expression too big";} | ||
| 526 | case REGEX_ERROR_ESPACE: {tmp = "Failed to get memory";} | ||
| 527 | case REGEX_ERROR_ESUBREG: {tmp = "Bad back reference";} | ||
| 528 | case REGEX_ERROR_INVARG: {tmp = "Bad argument";} | ||
| 529 | |||
| 530 | case REGEX_ERROR_NOMATCH: {tmp = "No match was found";} | ||
| 531 | case REGEX_ERROR_NULL: {tmp = "Null";} | ||
| 532 | case REGEX_ERROR_BADOPTION: {tmp = "Bad Option";} | ||
| 533 | case REGEX_ERROR_BADMAGIC: {tmp = "Bad Magic";} | ||
| 534 | case REGEX_ERROR_UNKNOWN_OPCODE: {tmp = "Unknown OpCode";} | ||
| 535 | case REGEX_ERROR_NOMEMORY: {tmp = "No Memory";} | ||
| 536 | case REGEX_ERROR_NOSUBSTRING: {tmp = "No substring";} | ||
| 537 | case REGEX_ERROR_MATCHLIMIT: {tmp = "Match limit";} | ||
| 538 | case REGEX_ERROR_CALLOUT: {tmp = "Callout";} // Never used by PCRE itself | ||
| 539 | case REGEX_ERROR_BADUTF8: {tmp = "Bad UTF8";} | ||
| 540 | case REGEX_ERROR_BADUTF8_OFFSET: {tmp = "Bad UTF8 offset";} | ||
| 541 | case REGEX_ERROR_PARTIAL: {tmp = "Partial";} | ||
| 542 | case REGEX_ERROR_BADPARTIAL: {tmp = "Bad Partial";} | ||
| 543 | case REGEX_ERROR_INTERNAL: {tmp = "Internal error";} | ||
| 544 | case REGEX_ERROR_BADCOUNT: {tmp = "Bad count";} | ||
| 545 | case REGEX_ERROR_DFA_UITEM: {tmp = "DFA UItem";} | ||
| 546 | case REGEX_ERROR_DFA_UCOND: {tmp = "DFA UCOND";} | ||
| 547 | case REGEX_ERROR_DFA_UMLIMIT: {tmp = "DFA UMLIMIT";} | ||
| 548 | case REGEX_ERROR_DFA_WSSIZE: {tmp = "DFA WSSIZE";} | ||
| 549 | case REGEX_ERROR_DFA_RECURSE: {tmp = "DFA recurse";} | ||
| 550 | case REGEX_ERROR_RECURSIONLIMIT: {tmp = "Recursion Limit";} | ||
| 551 | case REGEX_ERROR_NULLWSLIMIT: {tmp = "NULL WSLIMIT";} /* No longer actually used */ | ||
| 552 | case REGEX_ERROR_BADNEWLINE: {tmp = "Bad newline";} | ||
| 553 | case REGEX_ERROR_BADOFFSET: {tmp = "Bad offset";} | ||
| 554 | case REGEX_ERROR_SHORTUTF8: {tmp = "Short UFT8";} | ||
| 555 | case REGEX_ERROR_RECURSELOOP: {tmp = "Recurse loop";} | ||
| 556 | case REGEX_ERROR_JIT_STACKLIMIT: {tmp = "JIT Stacklimit";} | ||
| 557 | case REGEX_ERROR_BADMODE: {tmp = "Bad mode";} | ||
| 558 | case REGEX_ERROR_BADENDIANNESS: {tmp = "Bad endianness";} | ||
| 559 | case REGEX_ERROR_DFA_BADRESTART: {tmp = "DFA Bad Restart";} | ||
| 560 | case REGEX_ERROR_JIT_BADOPTION: {tmp = "JIT bad option";} | ||
| 561 | case REGEX_ERROR_BADLENGTH: {tmp = "Bad length";} | ||
| 562 | |||
| 563 | default: {tmp = "Unknown Error";} | ||
| 564 | } | ||
| 565 | |||
| 566 | return strcopy(buf, buflen, tmp); | ||
| 567 | } \ No newline at end of file | 511 | } \ No newline at end of file |
