safeDialogs detects and prevents players sending falsified dialog responses that includes wrong dialog ID, invalid list-item or fake input-text (list-item string). Faking list-item or item string can lead to many risks of player breaking server security. It can also lead to crashes where listitem used as array index goes out of bounds. However, this include ensures that everything's safe and filtered. This include triggers a callback on player sending spoofed dialog response.How's this different from others?
I've never seen any anti-cheat or dialog include that provides protection over list items and over sending fake inputtext data for list type dialogs. This topic is what that has inspired me to create such an include to provide complete protection over dialog responses.Callbacks and Functions
Exploit Protection Spoofed dialog ids Yes Spoofed dialog list-items Yes Spoofed dialog list-item inputtext Yes Filtering user's inputtext Yes
CallbackImportant NotesFunctions - These functions can only be used under OnDialogResponse and OnDialogSpoof. Once any of these callbacks are over, they'll return their default values only.Parameters:pawn Code:public OnDialogSpoof(playerid, spooftype) {
return 0; //Return 0 to block spoofed data!
}
playerid - The player who sent spoofed data.
spooftype - Spoof type.
Spoof types:
DIALOG_SPOOFTYPE_DIALOG_ID - If dialog ID is spoofed.
DIALOG_SPOOFTYPE_LIST_ITEM - If dialog listitem is spoofed.
DIALOG_SPOOFTYPE_INPUT_TEXT - If dialog inputtext (for lists) is spoofed.
Enumerator
pawn Code:enum {
DIALOG_SPOOFTYPE_DIALOG_ID,
DIALOG_SPOOFTYPE_LIST_ITEM,
DIALOG_SPOOFTYPE_INPUT_TEXT
}
pawn Code:native GetPlayerDialog(playerid); //Returns the current dialog ID of player.
native GetPlayerDialogStyle(playerid); //Returns the current dialog style of player. (255 if invalid)
native GetPlayerDialogInfo(playerid, dest[], size = sizeof(dest)); //Stores the dialog info to "dest" array.
native GetPlayerDialogItem(playerid, listitem, dest[], bool:filter = false, size = sizeof(dest)); //Stores the dialog's list-item string to "dest" array. View change-logs (v1.0.3) below to know more.
• This include must be included on every scripts that uses dialog features.Usage
• This include must be included after a_samp to ensure any other includes using dialog features are also protected. If you're having "fixes.inc" - include this after fixes.inc to avoid the user errors by fixes.inc.
• If you're using easyDialogs, yes, this can be integrated along with it. But include safeDialogs before easyDialogs.
• If your script is having a list-item of length greater than 256, edit MAX_DIALOG_LISTITEM_LEN. Or simply do this:
pawn Code://These defines are optional. If you haven't defined, script will use it's default values.
//Before including safeDialogs
#define MAX_DIALOG_LISTITEM_LEN 300
//You can also define MAX_DIALOG_STRING (not greater than 2048 since that's a limitation on SA-MP)
#define MAX_DIALOG_STRING 2000
#include <a_samp>
#include <safeDialogs>
Using this include is very easy! A small example is given below.Changelogs
pawn Code:#include <a_samp>
#include <safeDialogs>
public OnDialogSpoof(playerid, spooftype) {
//Player is spoofing dialog!
Kick(playerid); //Kick the player.
return 0; //Block the spoofed data by returning 0. Returning other values will accept spoofed data which isn't recommended.
}
- Added a static-global array to handle huge strings, thereby freeing more heap space. If you were facing any heap space related warning after including safeDialogs earlier, it should be fixed now.safeDialogs - v1.0.2:
- Improved list-item filtering. There used to be a confusion for non-hex codes between curly braces in list-item string, no more now though!
- Added new function : GetPlayerDialogItem - It stores the list-item string/data into destination. Using this function, you don't have to rely on inputtext for list-type dialogs to get their string data. In cases of DIALOG_STYLE_TABLIST or DIALOG_STYLE_TABLIST_HEADERS - it stores the complete list-item data.
To know more about this function and how it outputs - http://forum.sa-mp.com/showpost.php?...0&postcount=17pawn Code:GetPlayerDialogItem(playerid, listitem, dest[], bool:filter = false, size = sizeof(dest));
playerid - The player to obtain data from.
listitem - The listitem of which data/string has to be obtained.
dest[] - Array to store string/data.
filter = false - Whether to filter the contents in a list-item. If filter is set to true,
it will automatically remove color embedding and make it look like
how it's shown to clients / players.
If filter is set to false (by default it's false), it will show the raw data
which may or may not include color embedding, depending on how the
code is.
size = sizeof(dest) - The size of destination array.
- Fixed functions : Functions from safeDialogs can now be used under OnDialogResponse and OnDialogSpoof.
- Include initialization won't call OnPlayerConnect completely anymore, instead it only resets necessary variables. This also means that "_ALS_" hook errors upon including certain libraries along with safeDialogs, are fixed.
- Fixed false triggers for dialogs using color embedding. Thanks to GoldenLion for reporting!safeDialogs - v1.0.1:
- Include is now completely stand-alone. It no longer requires script_compatibility include since it had a problem with users using YSI.
- Fixed false triggers for DIALOG_STYLE_TABLIST and DIALOG_STYLE_TABLIST_HEADERS. Thanks to GoldenLion for reporting!safeDialogs - v1.0:
- Initial release.Download
Seems to be nice, but when I tried it a few minutes ago OnDialogSpoof got called for no reason when I used DIALOG_STYLE_TABLIST_HEADERS.
|
The code doesn't matter, but the spoof type was DIALOG_SPOOFTYPE_INPUT_TEXT. The problem must be that the inputtext at OnDialogResponse for DIALOG_STYLE_TABLIST_HEADERS and DIALOG_STYLE_TABLIST_HEADERS is the text before the first '\t' as far as I know so for example let's say there is "Item1\tItem2\n" in the dialog, but the inputtext at OnPlayerDialogResponse is just "Item1" (or "Item1\t"), not "Item1\tItem2\n" so the include thinks the inputtext is spoofed.
|
Exacly what I need, I have been struggling months ago to find something similar, good job mate!
|
Thanks for reporting, it has been fixed! I suggest everyone to re-download the latest commit.
|
Ah, one of my half-way finished projects. Great to see one released as I never got around finishing mine.
Here's a suggestion for you, thats a huge array sitting somewhere unused until they use dialogs, so use PVars instead. |
Another amazing release! Good job over there Lordz
![]() I'll be looking at the code and tell you if find some bug :P |
The bug is still there. I think it's not possible to fix it as it's impossible to get the whole inputtext.
|
//testing safeDialogs
#define FILTERSCRIPT
#include <a_samp>
#include <safeDialogs>
#include <zcmd>
static const dialogSpoofReasons[][] = {
{"spoofing dialog ID"},
{"spoofing list-item"},
{"spoofing input-text"}
};
public OnDialogSpoof(playerid, spooftype) {
new
tempString[144],
tempName[MAX_PLAYER_NAME + 1]
;
GetPlayerName(playerid, tempName, sizeof(tempName));
format(tempString, sizeof(tempString), "%s (ID:%d) has been caught for %s",
tempName, playerid, dialogSpoofReasons[spooftype]);
SendClientMessageToAll(-1, tempString);
print("\a"); //Beep sound.
print(tempString);
return 0;
}
CMD:showdialog(playerid, params[]) {
if(isnull(params))
return SendClientMessage(playerid, 0xFF0000FF, "USAGE : /showdialog [type]");
if(!strcmp(params, "list", true)) {
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_LIST, "DIALOG_STYLE_LIST",
"Item1\nItem2\nItem3\nItem4", "Select", "Close");
}
else if(!strcmp(params, "msgbox", true)) {
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_MSGBOX, "DIALOG_STYLE_MSGBOX",
"Item1\nItem2\nItem3\nItem4", "Select", "Close");
}
else if(!strcmp(params, "header", true)) {
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_TABLIST_HEADERS,
"DIALOG_STYLE_TABLIST_HEADERS",
"Item\tIndex\n\
Item\t1\n\
Stuff\t2\n\
Other\t3", "Select", "Close");
/*ShowPlayerDialog(playerid, 1, DIALOG_STYLE_TABLIST_HEADERS,
"DIALOG_STYLE_TABLIST_HEADERS",
"Item\tIndex\n", "Select", "Close");*/
}
else if(!strcmp(params, "tablist", true)) {
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_TABLIST,
"DIALOG_STYLE_TABLIST",
"Item\t1\n\
Stuff\t2\n\
Other\t3", "Select", "Close");
}
else if(!strcmp(params, "input", true)) {
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_INPUT, "DIALOG_STYLE_INPUT",
"Input some stuff", "Select", "Close");
}
return 1;
}
inputtext: Mask tempDListString: {FFFFFF}Mask 1 0.10 lbs
I printed out the stuff to show you what's up.
This is what the dialog looks like in-game: https://gyazo.com/8f43f40824ac5c85f6e216325d005fcb This is what it printed when I clicked on the mask: Code:
inputtext: Mask tempDListString: {FFFFFF}Mask 1 0.10 lbs |
- Fixes false calls on dialog lists having color embedding.
- Include is completely stand-alone now. It requires no script_compatibility include since it was a problem for users using YSI.
Please re-download the latest commit of this include. If you find any more issues, please post on this topic as it'd really be helpful.
It's really a shame that we can't use the whole inputtext line in tablists.
|
#include <a_samp>
#include <safeDialogs>
GetPlayerDialogItem(playerid, listitem, dest[], size = sizeof(dest)) {
new
initPoint,
endPoint,
tempCounts,
dStr[MAX_DIALOG_STRING],
dLen
;
tempCounts = (GetPlayerDialogStyle(playerid) == DIALOG_STYLE_TABLIST_HEADERS) ? -2 : -1;
GetPlayerDialogInfo(playerid, dStr, sizeof(dStr));
dLen = strlen(dStr);
for(endPoint = 0; endPoint < dLen; endPoint++) {
if(dStr[endPoint] == '\n') {
if(++tempCounts == listitem)
break;
initPoint = endPoint;
}
}
if(initPoint != 0)
initPoint++;
strmid(dest, dStr, initPoint, endPoint, size));
return 1;
}
public OnDialogResponse(...) {
if(dialogid == sometablistID) {
new
listStr[256];
GetPlayerDialogItem(playerid, listitem, listStr);
//listStr now contains the item's string regardless of player's input.
//It's the raw data which even includes color embedding.
GetPlayerDialogItem(playerid, listitem, dest[], bool:filter = false, size = sizeof(dest));
playerid - The player to obtain data from.
listitem - The listitem of which data/string has to be obtained.
dest[] - Array to store string/data.
filter = false - Whether to filter the contents in a list-item. If filter is set to true,
it will automatically remove color embedding and make it look like
how it's shown to clients / players.
If filter is set to false (by default it's false), it will show the raw data
which may or may not include color embedding, depending on how the
code is.
size = sizeof(dest) - The size of destination array.
ShowPlayerDialog(playerid, 1, DIALOG_STYLE_TABLIST,
"DIALOG_STYLE_TABLIST",
"Item\t1\n\
{FF0000}Stuff\t2\n\
{FFFaf9}Other\t3", "Select", "Close");
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) {
if(dialogid == 1) {
new
tmpString[256];
GetPlayerDialogItem(playerid, listitem, tmpString, false, sizeof(tmpString));
//filter is false - This output can include color embedding if the script has done so.
printf("%s", tmpString);
tmpString[0] = EOS;
GetPlayerDialogItem(playerid, listitem, tmpString, true, sizeof(tmpString));
//filter is true - It will print the text exactly like how clients view in game.
printf("%s", tmpString);
return 1;
}
return 0;
}
Item 1 Item 1 {FF0000}Stuff 2 Stuff 2 {FFFaf9}Other 3 Other 3
dialogid: 52 g_LSafeDialogs_Player[playerid][e_L_SD_pDIALOG_ID]: -1
OnDialogSpoof got called for no reason again and the spoof type was dialog ID. This is what my dialog looked like: https://gyazo.com/ed8c0f8b1d392086fd890bb8d15579f7
Responding to it showed this dialog: https://gyazo.com/f88309606a29a632457e6f7e1966fc22 and after I responded to the second dialog OnDialogSpoof got called. I printed the dialog IDs: Code:
dialogid: 52 g_LSafeDialogs_Player[playerid][e_L_SD_pDIALOG_ID]: -1 |
Are you using multiple filterscripts that uses dialog features? If so, please wait because I'll have to change the data structure to use PVars. I'm currently on a tour and will be updating as soon as I get back.
If what I said is your problem, for now return 1 under your OnDialogResponse. If this isn't the problem, try compiling with v1.0.2 (can be taken from commit history) and see if it's working well or not. Edit : One more thing I'd like to add - Are you calling OnDialogResponse callback explicitly anywhere on your code? Also let me know if you're using easyDialogs or not. |
I don't have any filterscripts nor easyDialogs include and I don't call OnDialogResponse anywhere. Also I return 1 there already, I never return 0. :P I'll try 1.0.2.
|