mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
Made the parser anal about concatenation usage and fixed several bugs by
running /dev/urandom through carne to catch problems.
This commit is contained in:
parent
05fb5fe08b
commit
020a9262f7
3 changed files with 148 additions and 37 deletions
|
@ -27,20 +27,10 @@ domain infobot
|
|||
|
||||
global rcsid = "$Id$"
|
||||
|
||||
global facts addr_cmds cmds
|
||||
global botname = "Console"
|
||||
|
||||
// Set up some cvars if they aren't already
|
||||
ifnot $infobot_restrict {
|
||||
set infobot_restrict 0
|
||||
}
|
||||
|
||||
ifnot $(length $infobot_password) {
|
||||
set infobot_password ""
|
||||
}
|
||||
global facts addr_cmds cmds current_file
|
||||
|
||||
function infobot::makeKey {
|
||||
return $(regex::replace $args[1] \. -- \_)_
|
||||
return $(regex::replace $args[1] "\." -- "\_")_
|
||||
}
|
||||
|
||||
function infobot::hasAccess {
|
||||
|
@ -48,14 +38,46 @@ function infobot::hasAccess {
|
|||
}
|
||||
|
||||
function infobot::defineFactoid {
|
||||
if (!$infobot_restrict || $(infobot::hasAccess $args[1])) {
|
||||
if (!$infobot_restrict_factoids || $(infobot::hasAccess $args[1])) {
|
||||
key = $(infobot::makeKey $args[2])
|
||||
facts.$key = @args[3:]
|
||||
// Filter out newlines/carriage returns
|
||||
if ${facts.${key}[2]} {
|
||||
return -2
|
||||
}
|
||||
facts.${key}[0] = $(regex::replace $args[3] "[\n\r]" g "")
|
||||
facts.${key}[1] = @args[4:]
|
||||
return 0
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
function infobot::factToString {
|
||||
local out
|
||||
for i in @args[1:] {
|
||||
out = $out, $i, "\255"
|
||||
}
|
||||
return $out
|
||||
}
|
||||
|
||||
function infobot::saveFactoids {
|
||||
local output = ""
|
||||
// Build up output to write to a file
|
||||
for fact in %facts {
|
||||
output = $output, $fact, "\255", $(infobot::factToString @facts.$fact), "\n"
|
||||
}
|
||||
file::write $args[1],".fct" $output
|
||||
}
|
||||
|
||||
function infobot::loadFactoids {
|
||||
delete facts
|
||||
global facts
|
||||
for line in $(split $(file::read $args[1],".fct") "\n") {
|
||||
fact = $(split $line "\255")
|
||||
facts.${fact[0]} = @fact[1:]
|
||||
}
|
||||
current_file = $args[1]
|
||||
}
|
||||
|
||||
function infobot::chatEvent {
|
||||
// Ignore teamtalk/spectalk
|
||||
if $args[3] {
|
||||
|
@ -67,7 +89,7 @@ function infobot::chatEvent {
|
|||
local res
|
||||
|
||||
// see if we are being addressed by name
|
||||
res = $(regex::extract $mesg $botname, "[:,][[:space:]]+(.+)" i)
|
||||
res = $(regex::extract $mesg $infobot_name, "[:,][[:space:]]+(.+)" i)
|
||||
if #res {
|
||||
mesg = $res[2]
|
||||
local addr = 1
|
||||
|
@ -91,10 +113,15 @@ function infobot::chatEvent {
|
|||
}
|
||||
res = $(regex::extract $mesg "^([^[:space:]]+)[[:space:]]+(is|are)[[:space:]]+(.+)" i)
|
||||
if #res {
|
||||
if ($(infobot::defineFactoid $args[1] $res[2] $res[4] $res[3]) && $addr) {
|
||||
say $from, ": You do not have the privileges to alter factoids."
|
||||
} else if $addr {
|
||||
say $from, ": Understood."
|
||||
res = $(infobot::defineFactoid $args[1] $res[2] $res[4] $res[3])
|
||||
if $addr {
|
||||
if ($res == -1) {
|
||||
say $from, ": You do not have the privileges to alter factoids."
|
||||
} else if ($res == -2) {
|
||||
say $from, ": That factoid is locked."
|
||||
} else {
|
||||
say $from, ": Understood."
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -119,8 +146,8 @@ function infobot::cmdRegister {
|
|||
cmds.$args[1] = $args[2]
|
||||
}
|
||||
|
||||
function infobot::forget {
|
||||
ifnot (!$infobot_restrict || $(infobot::hasAccess $args[1])) {
|
||||
function infobot::forgetFactoid {
|
||||
if ($infobot_restrict_factoids && !$(infobot::hasAccess $args[1])) {
|
||||
say $args[2], ": You do not have the privileges to alter factoids."
|
||||
return
|
||||
}
|
||||
|
@ -133,10 +160,76 @@ function infobot::forget {
|
|||
}
|
||||
}
|
||||
|
||||
function infobot::lockFactoid {
|
||||
ifnot $(infobot::hasAccess $args[1]) {
|
||||
say $args[2], ": You do not have the privileges to lock factoids."
|
||||
return
|
||||
}
|
||||
fact = $(infobot::makeKey $args[3])
|
||||
ifnot #{facts.$fact} {
|
||||
say $args[2], ": No such factoid exists."
|
||||
return
|
||||
}
|
||||
facts.${fact}[2] = 1
|
||||
say $args[2], ": \"", $args[3], "\" is now locked."
|
||||
}
|
||||
|
||||
function infobot::unlockFactoid {
|
||||
ifnot $(infobot::hasAccess $args[1]) {
|
||||
say $args[2], ": You do not have the privileges to unlock factoids."
|
||||
return
|
||||
}
|
||||
fact = $(infobot::makeKey $args[3])
|
||||
ifnot #{facts.$fact} {
|
||||
say $args[2], ": No such factoid exists."
|
||||
return
|
||||
}
|
||||
facts.${fact}[2] = 0
|
||||
say $args[2], ": \"", $args[3], "\" is now unlocked."
|
||||
}
|
||||
|
||||
function infobot::stats {
|
||||
say $args[2], ": I currently reference ", $(count %facts), " factoid(s) and ", ($(count %cmds) + $(count %addr_cmds)), " command(s)."
|
||||
}
|
||||
|
||||
function infobot::syncFactoids {
|
||||
ifnot $(infobot::hasAccess $args[1]) {
|
||||
say $args[2], ": You do not have syncing privileges."
|
||||
return
|
||||
}
|
||||
if #args[3] {
|
||||
file = $args[3]
|
||||
} else {
|
||||
file = $current_file
|
||||
}
|
||||
infobot::saveFactoids $file
|
||||
say $args[2], ": Factoids successfully synced to file ", $file, ".fct."
|
||||
}
|
||||
|
||||
// These are useful to the admin
|
||||
function::export infobot::saveFactoids infobot::loadFactoids
|
||||
|
||||
event::register chat infobot::chatEvent
|
||||
infobot::cmdAddrRegister "forget" infobot::forget
|
||||
infobot::cmdAddrRegister "forget" infobot::forgetFactoid
|
||||
infobot::cmdAddrRegister "lock" infobot::lockFactoid
|
||||
infobot::cmdAddrRegister "unlock" infobot::unlockFactoid
|
||||
infobot::cmdAddrRegister "infostats" infobot::stats
|
||||
infobot::cmdAddrRegister "sync" infobot::syncFactoids
|
||||
|
||||
// Set default values
|
||||
ifnot $(length $infobot_restrict_factoids) {
|
||||
set infobot_restrict_factoids 0
|
||||
}
|
||||
|
||||
ifnot $(length $infobot_password) {
|
||||
set infobot_password "hackme"
|
||||
}
|
||||
|
||||
ifnot $(length $infobot_name) {
|
||||
set infobot_name "Console"
|
||||
}
|
||||
|
||||
// Try to load a default factoids file
|
||||
if $(contains "default.fct" $(file::find *.fct)) {
|
||||
infobot::loadFactoids "default"
|
||||
}
|
||||
|
|
|
@ -84,7 +84,9 @@ GIB_Execute_Split_Var (cbuf_t * cbuf)
|
|||
char *c, *str = cbuf->args->argv[cbuf->args->argc - 1]->str + 1;
|
||||
void *m = cbuf->args->argm[cbuf->args->argc - 1];
|
||||
|
||||
i = strlen (str) - 1;
|
||||
i = strlen (str);
|
||||
if (i)
|
||||
i--;
|
||||
if (str[-1] == '@') {
|
||||
if (str[i] == ']')
|
||||
for (; i; i--)
|
||||
|
@ -229,15 +231,15 @@ GIB_Execute (cbuf_t * cbuf)
|
|||
g->ip = g->ip->next;
|
||||
continue;
|
||||
case TREE_T_CMD:
|
||||
if (g->ip->flags & TREE_L_EMBED) {
|
||||
// Get ready for return values
|
||||
g->waitret = true;
|
||||
GIB_Buffer_Push_Sstack (cbuf);
|
||||
} else
|
||||
g->waitret = false;
|
||||
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
|
||||
return;
|
||||
else if (cbuf->args->argc) {
|
||||
if (g->ip->flags & TREE_L_EMBED) {
|
||||
// Get ready for return values
|
||||
g->waitret = true;
|
||||
GIB_Buffer_Push_Sstack (cbuf);
|
||||
} else
|
||||
g->waitret = false;
|
||||
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
|
||||
b->func ();
|
||||
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
|
||||
|
@ -254,8 +256,8 @@ GIB_Execute (cbuf_t * cbuf)
|
|||
}
|
||||
if (cbuf->state)
|
||||
return;
|
||||
g->ip = g->ip->next;
|
||||
}
|
||||
g->ip = g->ip->next;
|
||||
continue;
|
||||
default:
|
||||
GIB_Error ("QUAKEFORGE-BUG-PLEASE-REPORT", "Unknown instruction type; tastes like chicken.");
|
||||
|
|
|
@ -224,7 +224,8 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
unsigned int tstart, start;
|
||||
gib_tree_t *nodes = 0, *cur, *new, *embs = 0, *tmp;
|
||||
gib_tree_t **node = &nodes;
|
||||
qboolean cat = false;
|
||||
enum {CAT_NORMAL = 0, CAT_DISALLOW, CAT_CONCAT} cat = CAT_DISALLOW;
|
||||
const char *catestr = "Comma found before first argument, nothing to concatenate to.";
|
||||
|
||||
gib_parse_error = false;
|
||||
|
||||
|
@ -234,10 +235,15 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
(*i)++;
|
||||
// Check for concatenation, skip comma and any more whitespace
|
||||
if (program[*i] == ',') {
|
||||
cat = true;
|
||||
if (cat == CAT_DISALLOW) {
|
||||
GIB_Parse_Error(catestr, *i + pofs);
|
||||
goto ERROR;
|
||||
}
|
||||
cat = CAT_CONCAT;
|
||||
(*i)++;
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
cat = CAT_NORMAL;
|
||||
// New line/command?
|
||||
if (!program[*i] || program[*i] == '\n' || program[*i] == ';')
|
||||
break;
|
||||
|
@ -290,6 +296,12 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
str = calloc (*i - tstart + 1, sizeof (char));
|
||||
memcpy (str, program + tstart, *i - tstart);
|
||||
if (cur->delim == '{') {
|
||||
if (cat == CAT_CONCAT) {
|
||||
GIB_Parse_Error ("Program blocks may not be concatenated with other arguments.", start + pofs);
|
||||
goto ERROR;
|
||||
}
|
||||
catestr = "Program blocks may not be concatenated with other arguments.";
|
||||
cat = CAT_DISALLOW;
|
||||
// Try to parse sub-program
|
||||
if (!(new = GIB_Parse_Lines (str, tstart + pofs)))
|
||||
goto ERROR;
|
||||
|
@ -315,7 +327,13 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
}
|
||||
// Check for array splitting
|
||||
// Concatenating this onto something else is non-sensical
|
||||
if (cur->delim == ' ' && (str[0] == '@' || str[0] == '%') && !cat) {
|
||||
if (cur->delim == ' ' && (str[0] == '@' || str[0] == '%')) {
|
||||
if (cat == CAT_CONCAT) {
|
||||
GIB_Parse_Error ("Variable expansions may not be concatenated with other arguments.", start + pofs);
|
||||
goto ERROR;
|
||||
}
|
||||
catestr = "Variable expansions may not be concatenated with other arguments.";
|
||||
cat = CAT_DISALLOW;
|
||||
cur->flags |= TREE_A_EXPAND;
|
||||
}
|
||||
// We can handle escape characters now
|
||||
|
@ -323,10 +341,8 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_t
|
|||
GIB_Process_Escapes (str);
|
||||
cur->str = str;
|
||||
|
||||
if (cat) {
|
||||
if (cat == CAT_CONCAT)
|
||||
cur->flags |= TREE_A_CONCAT;
|
||||
cat = false;
|
||||
}
|
||||
// Nothing left to parse?
|
||||
if (!program[*i])
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue