Safecheck atcommand

-Add restriction for atcommand to prevent possible mapcrash from script
or console usage while waiting full portability.
-Upd athena-start for new default binname.
-Remove petstat as it was similar to getpetinfo and copy only missing
attribute level atribute into getpetinfo.
-Merge useatcmd and atcommand as they shared quite the same code, also
properly differenciate useatcmd from normal player call.
--Upd script-documentation about it thx Euphy.
This commit is contained in:
lighta 2013-08-28 20:07:45 -04:00
parent ef4fd59996
commit 55e776076b
7 changed files with 86 additions and 136 deletions

3
.gitignore vendored
View File

@ -17,14 +17,17 @@
/*.stackdump
/*.suo
/char-server_sql
/char-server
/config.log
/config.status
/core
/ipch
/login-server_sql
/login-server
/Makefile
/Makefile.cache
/map-server_sql
/map-server
/mapcache
/nbproject

View File

@ -1399,11 +1399,13 @@ e_yut5 85
e_yut6 86
e_yut7 87
PET_ID 0
PET_CLASS 1
PET_NAME 2
PET_LEVEL 3
PET_INTIMATE 3
PET_HUNGRY 4
PET_INTIMATE 5
PET_RENAMED 5
PET_LEVEL 6
MOB_NAME 0
MOB_LV 1

View File

@ -6514,8 +6514,8 @@ character belonged to an account which had GM level 99.
input @player$;
atcommand "@nuke "+@player$;
This command has a lot of good uses, I am sure you can have some fun with this
one.
Note that for atcommands bound using 'bindatcmd', this command will execute the
original atcommand, not the script-bound atcommand.
---------------------------------------
@ -6532,7 +6532,7 @@ The commands can also run without an attached rid.
---------------------------------------
*bindatcmd "command","<NPC object name>::<event label>"{,<atcommand level>,<charcommand level>};
*bindatcmd "<command>","<NPC object name>::<event label>"{,<atcommand level>,<charcommand level>};
This command will bind a NPC event label to an atcommand. Upon execution of the
atcommand, the user will invoke the NPC event label. Each atcommand is only allowed
@ -6558,16 +6558,20 @@ OnAtcommand:
---------------------------------------
*unbindatcmd "command";
*unbindatcmd "<command>";
This command will unbind a NPC event label from an atcommand.
---------------------------------------
*useatcmd "command";
*useatcmd "<command>";
This command will execute an atcommand binding on the attached RID from a script.
The three .@atcmd_***** variables will NOT be set when invoking scripts-atcommands this way.
This command will execute a script-bound atcommand for the attached RID. If the
supplied command is not bound to any script, this command will act like 'atcommand'
and attempt to execute a source-defined command.
The three .@atcmd_***** variables will NOT be set when invoking script-bound atcommands
in this way.
---------------------------------------
\\
@ -7604,23 +7608,8 @@ currently has active. Valid types are:
3 - Pet friendly level (intimacy score). 1000 is full loyalty.
4 - Pet hungry level. 100 is completely full.
5 - Pet rename flag. 0 means this pet has not been named yet.
6 - Pet level
---------------------------------------
*petstat(<flag>)
Returns current pet status, all are integers except name.
Returns 0 or "" if the player doesn't have pets.
Flags usable:
- PET_CLASS
- PET_NAME
- PET_LEVEL
- PET_HUNGRY
- PET_INTIMATE
Example:
set @i, petstat(PET_CLASS);
---------------------------------------

View File

@ -1,6 +1,6 @@
L_SRV=login-server_sql
C_SRV=char-server_sql
M_SRV=map-server_sql
L_SRV=login-server
C_SRV=char-server
M_SRV=map-server
INST_PATH=/opt
PKG=rathena
PKG_PATH=$INST_PATH/$PKG

View File

@ -65,6 +65,7 @@ struct AtCommandInfo {
AtCommandFunc func;
char* at_groups;/* quick @commands "can-use" lookup */
char* char_groups;/* quick @charcommands "can-use" lookup */
int restriction; //prevent : 1 console, 2 script...
};
struct AliasInfo {
@ -9042,14 +9043,18 @@ ACMD_FUNC(langtype)
/**
* Fills the reference of available commands in atcommand DBMap
**/
#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL }
#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL }
#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL, 0 }
#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL, 0 }
//define with restriction
#define ACMD_DEFR(x, r) { #x, atcommand_ ## x, NULL, NULL, r }
#define ACMD_DEF2R(x2, x, r) { x2, atcommand_ ## x, NULL, NULL, r }
void atcommand_basecommands(void) {
/**
* Command reference list, place the base of your commands here
* TODO : all restricted command are crashing case, please look into it
**/
AtCommandInfo atcommand_base[] = {
ACMD_DEF2("warp", mapmove),
ACMD_DEF2R("warp", mapmove, 1),
ACMD_DEF(where),
ACMD_DEF(jumpto),
ACMD_DEF(jump),
@ -9067,7 +9072,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(guildstorage),
ACMD_DEF(option),
ACMD_DEF(hide), // + /hide
ACMD_DEF(jobchange),
ACMD_DEFR(jobchange, 1),
ACMD_DEF(kill),
ACMD_DEF(alive),
ACMD_DEF(kami),
@ -9083,7 +9088,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(clearstorage),
ACMD_DEF(cleargstorage),
ACMD_DEF(clearcart),
ACMD_DEF2("blvl", baselevelup),
ACMD_DEF2R("blvl", baselevelup, 1),
ACMD_DEF2("jlvl", joblevelup),
ACMD_DEF(help),
ACMD_DEF(pvpoff),
@ -9091,7 +9096,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(gvgoff),
ACMD_DEF(gvgon),
ACMD_DEF(model),
ACMD_DEF(go),
ACMD_DEFR(go, 1),
ACMD_DEF(monster),
ACMD_DEF2("monstersmall", monster),
ACMD_DEF2("monsterbig", monster),
@ -9140,11 +9145,11 @@ void atcommand_basecommands(void) {
ACMD_DEF(broadcast), // + /b and /nb
ACMD_DEF(localbroadcast), // + /lb and /nlb
ACMD_DEF(recallall),
ACMD_DEF(reload),
ACMD_DEFR(reload,2),
ACMD_DEF2("reloaditemdb", reload),
ACMD_DEF2("reloadmobdb", reload),
ACMD_DEF2("reloadskilldb", reload),
ACMD_DEF2("reloadscript", reload),
ACMD_DEF2R("reloadscript", reload,2),
ACMD_DEF2("reloadatcommand", reload),
ACMD_DEF2("reloadbattleconf", reload),
ACMD_DEF2("reloadstatusdb", reload),
@ -9323,6 +9328,7 @@ void atcommand_basecommands(void) {
CREATE(atcommand, AtCommandInfo, 1);
safestrncpy(atcommand->command, atcommand_base[i].command, sizeof(atcommand->command));
atcommand->func = atcommand_base[i].func;
atcommand->restriction = atcommand_base[i].restriction;
strdb_put(atcommand_db, atcommand->command, atcommand);
}
return;
@ -9423,7 +9429,14 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n
dbi_destroy(alias_iter);
}
/// Executes an at-command.
/*
* Executes an at-command
* \param type :
* 0 : script call (atcommand)
* 1 : normal player @atcommand
* 2 : console
* 3 : script call (useatcmd)
*/
bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type)
{
char charname[NAME_LENGTH], params[100];
@ -9455,9 +9468,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
if ( *message != atcommand_symbol && *message != charcommand_symbol )
return false;
// type value 0 = server invoked: bypass restrictions
// 1 = player invoked
if ( type == 1) {
// type value 0|2 = script|console invoked: bypass restrictions
if ( type == 1 || type == 3) {
//Commands are disabled on maps flagged as 'nocommand'
if ( map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand ) {
clif_displaymessage(fd, msg_txt(sd,143));
@ -9524,7 +9536,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
params[0] = '\0';
// @commands (script based)
if(type == 1 && atcmd_binding_count > 0) {
if((type == 1 || type == 3) && atcmd_binding_count > 0) {
struct atcmd_binding_data * binding;
// Check if the command initiated is a character command
@ -9562,6 +9574,14 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
return false;
}
//check restriction
if(info->restriction){
if(info->restriction&1 && type == 2) //console prevent
return true;
if(info->restriction&2 && (type == 0 || type == 3) ) //scripts prevent
return true;
}
// type == 1 : player invoked
if (type == 1) {
if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) ||

View File

@ -3302,7 +3302,7 @@ int parse_console(const char* buf){
sd.bl.y = y;
ShowNotice("Now at: '%s' Coords: %d %d\n", map, x, y);
}
else if( !is_atcommand(sd.fd, &sd, command, 0) )
else if( !is_atcommand(sd.fd, &sd, command, 2) )
ShowInfo("Console: Invalid atcommand.\n");
}
else if( n == 2 && strcmpi("server", type) == 0 ){

View File

@ -12760,11 +12760,7 @@ BUILDIN_FUNC(nude)
return 0;
}
/*==========================================
* gmcommand [MouseJstr]
*------------------------------------------*/
BUILDIN_FUNC(atcommand)
{
int atcommand_sub(struct script_state* st,int type){
TBL_PC dummy_sd;
TBL_PC* sd;
int fd;
@ -12789,7 +12785,7 @@ BUILDIN_FUNC(atcommand)
}
}
if (!is_atcommand(fd, sd, cmd, 0)) {
if (!is_atcommand(fd, sd, cmd, type)) {
ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd);
script_reportsrc(st);
return 1;
@ -12798,6 +12794,13 @@ BUILDIN_FUNC(atcommand)
return 0;
}
/*==========================================
* gmcommand [MouseJstr]
*------------------------------------------*/
BUILDIN_FUNC(atcommand) {
return atcommand_sub(st,0);
}
/*==========================================
* Displays a message for the player only (like system messages like "you got an apple" )
*------------------------------------------*/
@ -12950,7 +12953,7 @@ BUILDIN_FUNC(recovery)
/*==========================================
* Get your pet info: getpetinfo(n)
* n -> 0:pet_id 1:pet_class 2:pet_name
* 3:friendly 4:hungry, 5: rename flag.
* 3:friendly 4:hungry, 5: rename flag.6:level
*------------------------------------------*/
BUILDIN_FUNC(getpetinfo)
{
@ -12973,6 +12976,7 @@ BUILDIN_FUNC(getpetinfo)
case 3: script_pushint(st,pd->pet.intimate); break;
case 4: script_pushint(st,pd->pet.hungry); break;
case 5: script_pushint(st,pd->pet.rename_flag); break;
case 6: script_pushint(st,(int)pd->pet.level); break;
default:
script_pushint(st,0);
break;
@ -14922,35 +14926,6 @@ BUILDIN_FUNC(getd)
return 0;
}
// <--- [zBuffer] List of dynamic var commands
// Pet stat [Lance]
BUILDIN_FUNC(petstat)
{
TBL_PC *sd = NULL;
struct pet_data *pd;
int flag = script_getnum(st,2);
sd = script_rid2sd(st);
if(!sd || !sd->status.pet_id || !sd->pd){
if(flag == 2)
script_pushconststr(st, "");
else
script_pushint(st,0);
return 0;
}
pd = sd->pd;
switch(flag){
case 1: script_pushint(st,(int)pd->pet.class_); break;
case 2: script_pushstrcopy(st, pd->pet.name); break;
case 3: script_pushint(st,(int)pd->pet.level); break;
case 4: script_pushint(st,(int)pd->pet.hungry); break;
case 5: script_pushint(st,(int)pd->pet.intimate); break;
default:
script_pushint(st,0);
break;
}
return 0;
}
BUILDIN_FUNC(callshop)
{
TBL_PC *sd = NULL;
@ -17400,45 +17375,8 @@ BUILDIN_FUNC(unbindatcmd) {
return 0;
}
BUILDIN_FUNC(useatcmd)
{
TBL_PC dummy_sd;
TBL_PC* sd;
int fd;
const char* cmd;
cmd = script_getstr(st,2);
if( st->rid )
{
sd = script_rid2sd(st);
fd = sd->fd;
}
else
{ // Use a dummy character.
sd = &dummy_sd;
fd = 0;
memset(&dummy_sd, 0, sizeof(TBL_PC));
if( st->oid )
{
struct block_list* bl = map_id2bl(st->oid);
memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
if( bl->type == BL_NPC )
safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
}
}
// compatibility with previous implementation (deprecated!)
if( cmd[0] != atcommand_symbol )
{
cmd += strlen(sd->status.name);
while( *cmd != atcommand_symbol && *cmd != 0 )
cmd++;
}
is_atcommand(fd, sd, cmd, 1);
return 0;
BUILDIN_FUNC(useatcmd) {
return atcommand_sub(st,3);
}
BUILDIN_FUNC(checkre)
@ -18336,8 +18274,6 @@ struct script_function buildin_func[] = {
// [zBuffer] List of dynamic var commands --->
BUILDIN_DEF(getd,"s"),
BUILDIN_DEF(setd,"sv"),
// <--- [zBuffer] List of dynamic var commands
BUILDIN_DEF(petstat,"i"),
BUILDIN_DEF(callshop,"s?"), // [Skotlex]
BUILDIN_DEF(npcshopitem,"sii*"), // [Lance]
BUILDIN_DEF(npcshopadditem,"sii*"),