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 /*.stackdump
/*.suo /*.suo
/char-server_sql /char-server_sql
/char-server
/config.log /config.log
/config.status /config.status
/core /core
/ipch /ipch
/login-server_sql /login-server_sql
/login-server
/Makefile /Makefile
/Makefile.cache /Makefile.cache
/map-server_sql /map-server_sql
/map-server
/mapcache /mapcache
/nbproject /nbproject

View File

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

View File

@ -6514,8 +6514,8 @@ character belonged to an account which had GM level 99.
input @player$; input @player$;
atcommand "@nuke "+@player$; atcommand "@nuke "+@player$;
This command has a lot of good uses, I am sure you can have some fun with this Note that for atcommands bound using 'bindatcmd', this command will execute the
one. 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 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 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. 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. This command will execute a script-bound atcommand for the attached RID. If the
The three .@atcmd_***** variables will NOT be set when invoking scripts-atcommands this way. 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. 3 - Pet friendly level (intimacy score). 1000 is full loyalty.
4 - Pet hungry level. 100 is completely full. 4 - Pet hungry level. 100 is completely full.
5 - Pet rename flag. 0 means this pet has not been named yet. 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 L_SRV=login-server
C_SRV=char-server_sql C_SRV=char-server
M_SRV=map-server_sql M_SRV=map-server
INST_PATH=/opt INST_PATH=/opt
PKG=rathena PKG=rathena
PKG_PATH=$INST_PATH/$PKG PKG_PATH=$INST_PATH/$PKG

View File

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

View File

@ -12760,11 +12760,7 @@ BUILDIN_FUNC(nude)
return 0; return 0;
} }
/*========================================== int atcommand_sub(struct script_state* st,int type){
* gmcommand [MouseJstr]
*------------------------------------------*/
BUILDIN_FUNC(atcommand)
{
TBL_PC dummy_sd; TBL_PC dummy_sd;
TBL_PC* sd; TBL_PC* sd;
int fd; 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); ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd);
script_reportsrc(st); script_reportsrc(st);
return 1; return 1;
@ -12798,6 +12794,13 @@ BUILDIN_FUNC(atcommand)
return 0; 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" ) * 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) * Get your pet info: getpetinfo(n)
* n -> 0:pet_id 1:pet_class 2:pet_name * 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) BUILDIN_FUNC(getpetinfo)
{ {
@ -12973,6 +12976,7 @@ BUILDIN_FUNC(getpetinfo)
case 3: script_pushint(st,pd->pet.intimate); break; case 3: script_pushint(st,pd->pet.intimate); break;
case 4: script_pushint(st,pd->pet.hungry); break; case 4: script_pushint(st,pd->pet.hungry); break;
case 5: script_pushint(st,pd->pet.rename_flag); break; case 5: script_pushint(st,pd->pet.rename_flag); break;
case 6: script_pushint(st,(int)pd->pet.level); break;
default: default:
script_pushint(st,0); script_pushint(st,0);
break; break;
@ -14922,35 +14926,6 @@ BUILDIN_FUNC(getd)
return 0; 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) BUILDIN_FUNC(callshop)
{ {
TBL_PC *sd = NULL; TBL_PC *sd = NULL;
@ -17400,45 +17375,8 @@ BUILDIN_FUNC(unbindatcmd) {
return 0; return 0;
} }
BUILDIN_FUNC(useatcmd) BUILDIN_FUNC(useatcmd) {
{ return atcommand_sub(st,3);
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(checkre) BUILDIN_FUNC(checkre)
@ -18336,8 +18274,6 @@ struct script_function buildin_func[] = {
// [zBuffer] List of dynamic var commands ---> // [zBuffer] List of dynamic var commands --->
BUILDIN_DEF(getd,"s"), BUILDIN_DEF(getd,"s"),
BUILDIN_DEF(setd,"sv"), BUILDIN_DEF(setd,"sv"),
// <--- [zBuffer] List of dynamic var commands
BUILDIN_DEF(petstat,"i"),
BUILDIN_DEF(callshop,"s?"), // [Skotlex] BUILDIN_DEF(callshop,"s?"), // [Skotlex]
BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] BUILDIN_DEF(npcshopitem,"sii*"), // [Lance]
BUILDIN_DEF(npcshopadditem,"sii*"), BUILDIN_DEF(npcshopadditem,"sii*"),