Example #1
0
muf_re *
muf_re_get(struct shared_string *pattern, int flags, int *err)
{
    int idx =
        (hash(DoNullInd(pattern), MUF_RE_CACHE_ITEMS) +
         flags) % MUF_RE_CACHE_ITEMS;
    muf_re *re = &muf_re_cache[idx];

    if (re->pattern) {
        if ((flags != re->flags)
            || strcmp(DoNullInd(pattern), DoNullInd(re->pattern))) {
            regfree(&re->re);

            if (re->pattern && (--re->pattern->links == 0))
                free((void *) re->pattern);
        } else
            return re;
    }

    if ((*err =
         regcomp(&re->re, DoNullInd(pattern), flags | REG_EXTENDED)) != 0) {
        re->pattern = NULL;
        return NULL;
    }

    re->pattern = pattern;
    re->pattern->links++;

    re->flags = flags;

    return re;
}
Example #2
0
muf_re* muf_re_get(struct shared_string* pattern, int flags, const char** errmsg)
{
	int		idx	= (hash(DoNullInd(pattern), MUF_RE_CACHE_ITEMS) + flags) % MUF_RE_CACHE_ITEMS;
	muf_re*	re	= &muf_re_cache[idx];
	int     erroff;

	if (re->pattern)
	{
		if ((flags != re->flags) || strcmp(DoNullInd(pattern), DoNullInd(re->pattern)))
		{
			pcre_free(re->re);

			if (re->pattern && (--re->pattern->links == 0))
    			free((void *)re->pattern);
		}
		else
			return re;
	}

	re->re = pcre_compile(DoNullInd(pattern), flags, errmsg, &erroff, NULL);
	if (re->re == NULL)
	{
		re->pattern = NULL;
		return NULL;
	}

	re->pattern	= pattern;
	re->pattern->links++;

	re->flags	= flags;

	return re;
}
Example #3
0
void
prim_regmatch(PRIM_PROTOTYPE)
{
    muf_re*     re;
    char*       text;
    int         flags;
    int         matchcnt = 0;
    const char* errstr = NULL;
    int         result = 0;

    CHECKOP(3);
    oper3 = POP(); /* int:Flags */
    oper2 = POP(); /* str:Pattern */
    oper1 = POP(); /* str:Text */

    if (oper1->type != PROG_STRING)
        abort_interp("Non-string argument (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_INTEGER)
        abort_interp("Non-integer argument (3)");

    /* This primitive is for matching, not capturing. Using user-supplied
     * parenthesis for anything other than grouping purposes is therefore a
     * waste of resources, but most casual regex users won't know about the
     * non-capturing parenthesis alternatives available when PCRE_EXTENDED is
     * set. Since this is the case, we'll enable PCRE_NO_AUTO_CAPTURE as a
     * default option to optimize the majority of lazy user input.
     * -brevantes */

    flags = PCRE_NO_AUTO_CAPTURE;

    if (oper3->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper3->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    re = regmatch_re_get(oper2->data.string, flags, &errstr);
    if (errstr)
        abort_interp(errstr)

    text    = (char *)DoNullInd(oper1->data.string);

    if ((matchcnt = regmatch_exec(re, text)) < 0) {
        if (matchcnt != PCRE_ERROR_NOMATCH)
        {
            abort_interp(muf_re_error(matchcnt));
        }
    }
    else
        /* Returning matchcnt isn't useful in match-only mode. */
        result = 1;
    
    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushInt(result);
}
Example #4
0
void 
prim_abort(PRIM_PROTOTYPE)
{
    CHECKOP(1);
    oper1 = POP();
    if (oper1->type != PROG_STRING)
	abort_interp("Invalid argument");
    strcpy(buf, DoNullInd(oper1->data.string));
    abort_interp(buf);
}
Example #5
0
void
prim_force(PRIM_PROTOTYPE)
{
	struct inst *oper1 = NULL; /* prevents re-entrancy issues! */
	struct inst *oper2 = NULL; /* prevents re-entrancy issues! */

	int i;

	/* d s -- */
	CHECKOP(2);
	oper1 = POP();				/* string to @force */
	oper2 = POP();				/* player dbref */
	if (mlev < 4)
		abort_interp("Wizbit only primitive.");
	if (fr->level > 8)
		abort_interp("Interp call loops not allowed.");
	if (oper1->type != PROG_STRING)
		abort_interp("Non-string argument (2).");
	if (oper2->type != PROG_OBJECT)
		abort_interp("Non-object argument (1).");
	ref = oper2->data.objref;
	if (ref < 0 || ref >= db_top)
		abort_interp("Invalid object to force. (1)");
	if (Typeof(ref) != TYPE_PLAYER && Typeof(ref) != TYPE_THING)
		abort_interp("Object to force not a thing or player. (1)");
	if (0 == strcmp(DoNullInd(oper1->data.string), ""))
		abort_interp("Empty command argument (2).");
	if (index(oper1->data.string->data, '\r'))
		abort_interp("Carriage returns not allowed in command string. (2).");
#ifdef GOD_PRIV
	if (God(oper2->data.objref) && !God(OWNER(program)))
		abort_interp("Cannot force god (1).");
#endif
	force_prog = program;
	force_level++;
	process_command(dbref_first_descr(oper2->data.objref), oper2->data.objref,
					oper1->data.string->data);
	force_level--;
	force_prog = NOTHING;

	for (i = 1; i <= fr->caller.top; i++) {
		if (Typeof(fr->caller.st[i]) != TYPE_PROGRAM) {
#ifdef DEBUG
			char str[BUFFER_LEN];
			snprintf(str,BUFFER_LEN,"[debug] prim_force: fr->caller.st[%d] isn't a program.",i);
			notify_nolisten(player,str,1);
#endif /* DEBUG */
			do_abort_silent();
		}
	}

	CLEAR(oper1);
	CLEAR(oper2);
}
Example #6
0
void
prim_timer_start(PRIM_PROTOTYPE)
{
	CHECKOP(2);
	oper2 = POP();				/* string: timer id */
	oper1 = POP();				/* int: delay length in seconds */

	if (fr->timercount > tp_process_timer_limit)
		abort_interp("Too many timers!");
	if (oper1->type != PROG_INTEGER)
		abort_interp("Expected an integer delay time. (1)");
	if (oper2->type != PROG_STRING)
		abort_interp("Expected a string timer id. (2)");

    dequeue_timers(fr->pid, DoNullInd(oper2->data.string));
	add_muf_timer_event(fr->descr, player, program, fr, oper1->data.number, DoNullInd(oper2->data.string));

	CLEAR(oper1);
	CLEAR(oper2);
}
Example #7
0
muf_re* muf_re_get(struct shared_string* pattern, int flags, const char** errmsg)
{
    int     idx = (hash(DoNullInd(pattern), MUF_RE_CACHE_ITEMS) + flags) % MUF_RE_CACHE_ITEMS;
    muf_re* re  = &muf_re_cache[idx];
    int     erroff;
    const char* errstr;

    if (re->pattern)
    {
        if ((flags != re->flags) || strcmp(DoNullInd(pattern), DoNullInd(re->pattern)))
        {
            pcre_free(re->re);
            free(re->extra);

            if (re->pattern && (--re->pattern->links == 0))
                free((void *)re->pattern);
        } else {
            if (++(re->hits) == 3 && !re->extra) {
                re->extra = pcre_study(re->re, 0, &errstr);
                // can't abort_interp here...
            }
            return re;
        }
    }

    re->re = pcre_compile(DoNullInd(pattern), flags, errmsg, &erroff, NULL);
    if (re->re == NULL)
    {
        re->pattern = NULL;
        return NULL;
    }

    re->pattern = pattern;
    re->pattern->links++;

    re->flags   = flags;
    re->hits    = 1;
    re->extra   = NULL;

    return re;
}
Example #8
0
void
prim_event_send(PRIM_PROTOTYPE)
{
    struct frame *destfr;
    stk_array *arr;
    struct inst temp1;

    CHECKOP(3);
    oper3 = POP();		/* any: data to pass */
    oper2 = POP();		/* string: event id */
    oper1 = POP();		/* int: process id to send to */

    if (mlev < 3)
	abort_interp("Requires Mucker level 3 or better.");
    if (oper1->type != PROG_INTEGER)
	abort_interp("Expected an integer process id. (1)");
    if (oper2->type != PROG_STRING)
	abort_interp("Expected a string event id. (2)");

    if (oper1->data.number == fr->pid)
	destfr = fr;
    else
	destfr = timequeue_pid_frame(oper1->data.number);

    if (destfr) {
        stk_array_active_list = &destfr->array_active_list;
        struct inst data_copy;
        deep_copyinst(oper3, &data_copy, destfr->pinning);
	arr = new_array_dictionary(destfr->pinning);
	array_set_strkey(&arr, "data", &data_copy);
	array_set_strkey_intval(&arr, "caller_pid", fr->pid);
	array_set_strkey_intval(&arr, "descr", fr->descr);
	array_set_strkey_refval(&arr, "caller_prog", program);
	array_set_strkey_refval(&arr, "trigger", fr->trig);
	array_set_strkey_refval(&arr, "prog_uid", ProgUID);
	array_set_strkey_refval(&arr, "player", player);

	temp1.type = PROG_ARRAY;
	temp1.data.array = arr;

	snprintf(buf, sizeof(buf), "USER.%.32s", DoNullInd(oper2->data.string));
	muf_event_add(destfr, buf, &temp1, 0);

        stk_array_active_list = &fr->array_active_list;

	CLEAR(&temp1);
        CLEAR(&data_copy);
    }

    CLEAR(oper1);
    CLEAR(oper2);
    CLEAR(oper3);
}
Example #9
0
void
prim_interp(PRIM_PROTOTYPE)
{
    struct inst *oper1 = NULL;	/* prevents re-entrancy issues! */
    struct inst *oper2 = NULL;	/* prevents re-entrancy issues! */
    struct inst *oper3 = NULL;	/* prevents re-entrancy issues! */

    struct inst *rv = NULL;
    char buf[BUFFER_LEN];
    struct frame *tmpfr;

    CHECKOP(3);
    oper3 = POP();		/* string -- top stack argument */
    oper2 = POP();		/* dbref  --  trigger */
    oper1 = POP();		/* dbref  --  Program to run */

    if (!valid_object(oper1) || Typeof(oper1->data.objref) != TYPE_PROGRAM)
	abort_interp("Bad program reference. (1)");
    if (!valid_object(oper2))
	abort_interp("Bad object. (2)");
    if (oper3->type != PROG_STRING)
	abort_interp("Expected a string. (3)");
    if ((mlev < 3) && !permissions(ProgUID, oper2->data.objref))
	abort_interp("Permission denied.");
    if (fr->level > 8)
	abort_interp("Interp call loops not allowed.");
    CHECKREMOTE(oper2->data.objref);

    strcpyn(buf, sizeof(buf), match_args);
    strcpyn(match_args, sizeof(match_args), DoNullInd(oper3->data.string));
    tmpfr = interp(fr->descr, player, LOCATION(player), oper1->data.objref,
		   oper2->data.objref, PREEMPT, STD_HARDUID, 0);
    if (tmpfr) {
	rv = interp_loop(player, oper1->data.objref, tmpfr, 1);
    }
    strcpyn(match_args, sizeof(match_args), buf);

    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    if (rv) {
	if (rv->type < PROG_STRING) {
	    push(arg, top, rv->type, MIPSCAST(&rv->data.number));
	} else {
	    push(arg, top, rv->type, MIPSCAST(rv->data.string));
	}
    } else {
	PushNullStr;
    }

}
Example #10
0
void
prim_nextprop(PRIM_PROTOTYPE)
{
	/* dbref pname -- pname */
	char *pname;
	char exbuf[BUFFER_LEN];

	CHECKOP(2);
	oper2 = POP();				/* pname */
	oper1 = POP();				/* dbref */
	if (mlev < 3)
		abort_interp("Permission denied.");
	if (oper2->type != PROG_STRING)
		abort_interp("String required. (2)");
	if (oper1->type != PROG_OBJECT)
		abort_interp("Dbref required. (1)");
	if (!valid_object(oper1))
		abort_interp("Invalid dbref. (1)");

	ref = oper1->data.objref;
	(void) strcpyn(buf, sizeof(buf), DoNullInd(oper2->data.string));

	CLEAR(oper1);
	CLEAR(oper2);

	{
		char *tmpname;

		pname = next_prop_name(ref, exbuf, sizeof(exbuf), buf);

#ifdef LOG_PROPS
		log2file("props.log", "#%d (%d) NEXTPROP: o=%d n=\"%s\" on=\"%s\"",
				 program, pc->line, ref, pname, buf);
#endif

		while (pname && !prop_read_perms(ProgUID, ref, pname, mlev)) {
			tmpname = next_prop_name(ref, exbuf, sizeof(exbuf), pname);

#ifdef LOG_PROPS
			log2file("props.log", "#%d (%d) NEXTPROP: o=%d n=\"%s\" on=\"%s\"",
					 program, pc->line, ref, tmpname, pname);
#endif

			pname = tmpname;
		}
	}
	if (pname) {
		PushString(pname);
	} else {
		PushNullStr;
	}
}
Example #11
0
void
prim_timer_stop(PRIM_PROTOTYPE)
{
	CHECKOP(1);
	oper1 = POP();				/* string: timer id */

	if (oper1->type != PROG_STRING)
		abort_interp("Expected a string timer id. (2)");

    dequeue_timers(fr->pid, DoNullInd(oper1->data.string));

	CLEAR(oper1);
}
Example #12
0
void
prim_sysparm_array(PRIM_PROTOTYPE)
{
    stk_array *nu;
    int security = TUNE_MLEV(player);

    CHECKOP(1);
    oper1 = POP();		/* string: match pattern */

    if (oper1->type != PROG_STRING)
	abort_interp("Expected a string smatch pattern.");
    nu = tune_parms_array(DoNullInd(oper1->data.string), security, fr->pinning);

    CLEAR(oper1);
    PushArrayRaw(nu);
}
Example #13
0
void
prim_sysparm_array(PRIM_PROTOTYPE)
{
    stk_array *nu;

    /* string */
    CHECKOP(1);
    oper1 = POP();

    if (oper1->type != PROG_STRING)
        abort_interp("Expected a string smatch pattern. (1)");

    nu = tune_parms_array(DoNullInd(oper1->data.string), mlev);

    CLEAR(oper1);
    PushArrayRaw(nu);
}
Example #14
0
void
prim_remove_prop(PRIM_PROTOTYPE)
{
	CHECKOP(2);
	oper1 = POP();
	oper2 = POP();
	if (oper1->type != PROG_STRING)
		abort_interp("Non-string argument (2)");
	if (!valid_object(oper2))
		abort_interp("Non-object argument (1)");

	CHECKREMOTE(oper2->data.objref);

	strncpy(buf, DoNullInd(oper1->data.string), BUFFER_LEN);
	buf[BUFFER_LEN - 1] = '\0';

	{
		int	len = strlen(buf);
		char*	ptr = buf + len;

		while((--len >= 0) && (*--ptr == PROPDIR_DELIMITER))
			*ptr = '\0';
	}

	if (!*buf)
		abort_interp("Can't remove root propdir (2)");

	if (!prop_write_perms(ProgUID, oper2->data.objref, buf, mlev))
		abort_interp("Permission denied.");

	remove_property(oper2->data.objref, buf);

#ifdef LOG_PROPS
	log2file("props.log", "#%d (%d) REMOVEPROP: o=%d n=\"%s\"",
		program, pc->line, oper2->data.objref, buf);
#endif

	ts_modifyobject(oper2->data.objref);

	CLEAR(oper1);
	CLEAR(oper2);
}
Example #15
0
void 
prim_queue(PRIM_PROTOTYPE)
{
    dbref temproom;

    /* int dbref string -- */
    CHECKOP(3);
    oper1 = POP();
    oper2 = POP();
    oper3 = POP();
    if (mlev < LM3)
	abort_interp("M3 prim");
    if (oper3->type != PROG_INTEGER)
	abort_interp("Non-integer argument (1)");
    if (oper2->type != PROG_OBJECT)
	abort_interp("Argument must be a dbref (2)");
    if (!valid_object(oper2))
	abort_interp("Invalid dbref (2)");
    if (Typeof(oper2->data.objref) != TYPE_PROGRAM)
	abort_interp("Object must be a program (2)");
    if (oper1->type != PROG_STRING)
	abort_interp("Non-string argument (3)");

    if ((oper4 = fr->variables + 1)->type != PROG_OBJECT)
	temproom = DBFETCH(player)->location;
    else
	temproom = oper4->data.objref;

    result = add_muf_delayq_event(oper3->data.number, fr->descr, player, temproom,
		    NOTHING, oper2->data.objref, DoNullInd(oper1->data.string),
		     "Queued Event.", 0);

    CLEAR(oper1);
    CLEAR(oper2);
    CLEAR(oper3);
    PushInt(result);
}
Example #16
0
void
prim_event_send(PRIM_PROTOTYPE)
{
      struct frame *destfr;
      stk_array *arr;
      struct inst temp1;

	CHECKOP(3);
	oper3 = POP();				/* any: data to pass */
	oper2 = POP();				/* string: event id */
	oper1 = POP();				/* int: process id to send to */

	if (mlev < 3)
		abort_interp("Requires Mucker level 3 or better.");
	if (oper1->type != PROG_INTEGER)
		abort_interp("Expected an integer process id. (1)");
	if (oper2->type != PROG_STRING)
		abort_interp("Expected a string event id. (2)");

      destfr = (struct frame*) timequeue_pid_frame(oper1->data.number);
	if (destfr) {
		arr = new_array_dictionary();
		array_set_strkey(&arr, "data", oper3);
		array_set_strkey_intval(&arr, "caller_pid", fr->pid);
		array_set_strkey_refval(&arr, "caller_prog", program);

		temp1.type = PROG_ARRAY;
		temp1.data.array = arr; 

		sprintf(buf, "USER.%.32s", DoNullInd(oper2->data.string));
		muf_event_add(destfr, buf, oper3);
	}

      CLEAR(oper1);
	CLEAR(oper2);
	CLEAR(oper3);
}
Example #17
0
void
show_re_cache(dbref player) {
    muf_re* re;
    size_t tmp;
    int idx = 0;
    int patterns = 0;
    int studies = 0;
    size_t size_re = 0;
    size_t size_extra = 0;

    if (!Boy(OWNER(player))) {
        anotify_fmt(player, CFAIL "%s", tp_noperm_mesg);
        return;
    }

    anotify(player, SYSYELLOW "idx hits flags studied? pattern"); 
    while (idx <= MUF_RE_CACHE_ITEMS) {
        re = &muf_re_cache[idx];

        if (re->re) {
            patterns++;
            notify_fmt(player, "%3i %4i %5i        %i \"%s\"",
                       idx, re->hits, re->flags,
                         (re->extra != NULL), DoNullInd(re->pattern));
            pcre_fullinfo(re->re, NULL, PCRE_INFO_SIZE, &tmp);
            size_re = size_re + tmp;
            if (re->extra) {
                studies++;
                pcre_fullinfo(re->re, re->extra, PCRE_INFO_STUDYSIZE, &tmp);
                size_extra = size_extra + tmp;
            }
        }
        idx++;
    }
    anotify_fmt(player, SYSPURPLE "\n%i compiled patterns are using %zd bytes of RAM.", patterns, size_re);
    anotify_fmt(player, SYSGREEN "%i study instances are using are using %zd bytes of RAM.", studies, size_extra);
}
Example #18
0
void
prim_array_regmatchval(PRIM_PROTOTYPE)
{
    struct inst *in;
    stk_array *arr;
    stk_array *nw;
    muf_re* re;
    char* text;
    int flags;
    int matchcnt = 0;
    const char* errstr = NULL;

    CHECKOP(3);
    oper3 = POP();              /* int  pcreflags */
    oper2 = POP();              /* str  pattern */
    oper1 = POP();              /* arr  Array */
    if (oper1->type != PROG_ARRAY)
        abort_interp("Argument not an array. (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Argument not a string pattern. (2)");
    if (oper3->type != PROG_INTEGER)
        abort_interp("Non-integer argument (3)");

    flags = PCRE_NO_AUTO_CAPTURE;

    if (oper3->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper3->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    re = regmatch_re_get(oper2->data.string, flags, &errstr);
    if (errstr)
        abort_interp(errstr)

    nw = new_array_dictionary();
    arr = oper1->data.array;

    if (re && !re->extra && array_count(arr) > 2) {
        /* This pattern is getting used 3 or more times, let's study it. A null
         * return is okay, that just means there's nothing to optimize. */
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    if (array_first(arr, &temp1)) {
        do {
            in = array_getitem(arr, &temp1);
            if (in->type == PROG_STRING) {
                text    = (char *)DoNullInd(in->data.string);
                if ((matchcnt = regmatch_exec(re, text)) < 0) {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    array_setitem(&nw, &temp1, in);
                }
            } else if (in->type == PROG_OBJECT) {
                text    = (char *) NAME(in->data.objref);
                if ((matchcnt = regmatch_exec(re, text)) < 0) {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    array_setitem(&nw, &temp1, in);
                }
            }
        } while (array_next(arr, &temp1));
    }


    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushArrayRaw(nw);
}
Example #19
0
void
prim_array_filter_prop(PRIM_PROTOTYPE)
{
	char pattern[BUFFER_LEN];
	char tname[BUFFER_LEN];
	struct inst *in;
	struct inst temp1;
	stk_array *arr;
	stk_array *nu;
	char* prop;
	int len;

	CHECKOP(3);
	oper3 = POP();				/* str     pattern */
	oper2 = POP();				/* str     propname */
	oper1 = POP();				/* refarr  Array */
	if (oper1->type != PROG_ARRAY)
		abort_interp("Argument not an array. (1)");
	if (!array_is_homogenous(oper1->data.array, PROG_OBJECT))
		abort_interp("Argument not an array of dbrefs. (1)");
	if (oper2->type != PROG_STRING || !oper2->data.string)
		abort_interp("Argument not a non-null string. (2)");
	if (oper3->type != PROG_STRING)
		abort_interp("Argument not a string pattern. (3)");

	len = oper2->data.string ? oper2->data.string->length : 0;
	strcpyn(tname, sizeof(tname), DoNullInd(oper2->data.string));
	while (len-- > 0 && tname[len] == PROPDIR_DELIMITER) {
		tname[len] = '\0';
	}

	nu = new_array_packed(0);
	arr = oper1->data.array;
	prop = tname;
	strcpyn(pattern, sizeof(pattern), DoNullInd(oper3->data.string));
	if (array_first(arr, &temp1)) {
		do {
			in = array_getitem(arr, &temp1);
			if (valid_object(in)) {
				ref = in->data.objref;
				CHECKREMOTE(ref);
				if (prop_read_perms(ProgUID, ref, prop, mlev)) {
					PropPtr pptr = get_property(ref, prop);

					if (pptr)
					{
						switch(PropType(pptr))
						{
							case PROP_STRTYP:
								strncpy(buf, PropDataStr(pptr), BUFFER_LEN);
							break;

							case PROP_LOKTYP:
								if (PropFlags(pptr) & PROP_ISUNLOADED) {
									strncpy(buf, "*UNLOCKED*", BUFFER_LEN);
								} else {
									strncpy(buf, unparse_boolexp(ProgUID, PropDataLok(pptr), 0), BUFFER_LEN);
								}
							break;

							case PROP_REFTYP:
								snprintf(buf, BUFFER_LEN, "#%i", PropDataRef(pptr));
							break;

							case PROP_INTTYP:
								snprintf(buf, BUFFER_LEN, "%i", PropDataVal(pptr));
							break;

							case PROP_FLTTYP:
								snprintf(buf, BUFFER_LEN, "%g", PropDataFVal(pptr));
							break;

							default:
								strncpy(buf, "", BUFFER_LEN);
							break;
						}
					}
					else
						strncpy(buf, "", BUFFER_LEN);

					if (equalstr(pattern, buf)) {
						array_appenditem(&nu, in);
					}
				}
			}
		} while (array_next(arr, &temp1));
	}

	CLEAR(oper3);
	CLEAR(oper2);
	CLEAR(oper1);

	PushArrayRaw(nu);
}
Example #20
0
void
prim_array_regsub(PRIM_PROTOTYPE)
{
    struct inst *in;
    stk_array *arr;
    stk_array *nw;
    int         matches[MATCH_ARR_SIZE];
    int         flags       = 0;
    char*       write_ptr   = buf;
    int         write_left  = BUFFER_LEN - 1;
    muf_re*     re;
    char*       text;
    char*       textstart;
    const char* errstr;
    int         matchcnt, len;

    CHECKOP(4);

    oper4 = POP(); /* int:Flags */
    oper3 = POP(); /* str:Replace */
    oper2 = POP(); /* str:Pattern */
    oper1 = POP(); /* str:Text */

    if (oper1->type != PROG_ARRAY)
        abort_interp("Argument not an array of strings. (1)");
    if (!array_is_homogenous(oper1->data.array, PROG_STRING))
        abort_interp("Argument not an array of strings. (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_STRING)
        abort_interp("Non-string argument (3)");
    if (oper4->type != PROG_INTEGER)
        abort_interp("Non-integer argument (4)");
    if (!oper2->data.string)
        abort_interp("Empty string argument (2)");

    if (oper4->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper4->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL)
        abort_interp(errstr);



    nw = new_array_dictionary();
    arr = oper1->data.array;

    if (!re->extra
        && ((oper4->data.number & MUF_RE_ALL ) || array_count(arr) > 2)) {
        /* Study the pattern if the user requested recursive substitution, or
         * if the input array contains at least three items. */
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    if (array_first(arr, &temp1)) {
        do {
            write_ptr = buf;
            write_left = BUFFER_LEN - 1;

            in = array_getitem(arr, &temp1);
            textstart = text = (char *)DoNullInd(in->data.string);
            len = strlen(textstart);

            while((*text != '\0') && (write_left > 0))
            {
                if ((matchcnt = pcre_exec(re->re, re->extra, textstart, len,
                                          text-textstart, 0, matches,
                                          MATCH_ARR_SIZE)) < 0)
                {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                    {
                        abort_interp(muf_re_error(matchcnt));
                    }

                    while((write_left > 0) && (*text != '\0'))
                    {
                        *write_ptr++ = *text++;
                        write_left--;
                    }

                    break;
                }
                else
                {
                    int         allstart    = matches[0];
                    int         allend      = matches[1];
                    int         substart    = -1;
                    int         subend      = -1;
                    char*       read_ptr    = (char *)DoNullInd(oper3->data.string);
                    int         count;

                    for(count = allstart-(text-textstart);
                                (write_left > 0) && (*text != '\0') && (count > 0);
                                count--)
                    {
                        *write_ptr++ = *text++;
                        write_left--;
                    }

                    while((write_left > 0) && (*read_ptr != '\0'))
                    {
                        if (*read_ptr == '\\')
                        {
                            if (!isdigit(*(++read_ptr)))
                            {
                                *write_ptr++ = *read_ptr++;
                                write_left--;
                            }
                            else
                            {
                                int idx = (*read_ptr++) - '0';

                                if ((idx < 0) || (idx >= matchcnt))
                                {
                                    abort_interp("Invalid \\subexp in substitution string. (3)");
                                }

                                substart = matches[idx*2];
                                subend = matches[idx*2+1];

                                if ((substart >= 0) && (subend >= 0) && (substart < len))
                                {
                                    char* ptr = &textstart[substart];

                                    count = subend - substart;

                                    if (count > write_left)
                                    {
                                        abort_interp("Operation would result in overflow");
                                    }

                                    for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--)
                                    {
                                        *write_ptr++ = *ptr++;
                                        write_left--;
                                    }
                                }
                            }
                        }
                        else
                        {
                            *write_ptr++ = *read_ptr++;
                            write_left--;
                        }
                    }

                    for(count = allend - allstart; (*text != '\0') && (count > 0); count--)
                        text++;

                    if (allstart == allend && *text) {
                        *write_ptr++ = *text++;
                        write_left--;
                    }
                }

                if ((oper4->data.number & MUF_RE_ALL) == 0)
                {
                    while((write_left > 0) && (*text != '\0'))
                    {
                        *write_ptr++ = *text++;
                        write_left--;
                    }

                    break;
                }
            }

            if (*text != '\0')
                abort_interp("Operation would result in overflow");

            *write_ptr = '\0';

            temp2.type = PROG_STRING;
            temp2.data.string = alloc_prog_string(buf);

            array_setitem(&nw, &temp1, &temp2);
            CLEAR(&temp2);
        } while (array_next(arr, &temp1));
    }

    CLEAR(oper4);
    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushArrayRaw(nw);
}
Example #21
0
void
prim_regsub(PRIM_PROTOTYPE)
{
    int         matches[MATCH_ARR_SIZE];
    int         flags       = 0;
    char*       write_ptr   = buf;
    int         write_left  = BUFFER_LEN - 1;
    muf_re*     re;
    char*       text;
    char*       textstart;
    const char* errstr;
    int         matchcnt, len;

    CHECKOP(4);

    oper4 = POP(); /* int:Flags */
    oper3 = POP(); /* str:Replace */
    oper2 = POP(); /* str:Pattern */
    oper1 = POP(); /* str:Text */

    if (oper1->type != PROG_STRING)
        abort_interp("Non-string argument (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_STRING)
        abort_interp("Non-string argument (3)");
    if (oper4->type != PROG_INTEGER)
        abort_interp("Non-integer argument (4)");
    if (!oper2->data.string)
        abort_interp("Empty string argument (2)");

    if (oper4->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper4->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL)
        abort_interp(errstr);

    if (!re->extra && (oper4->data.number & MUF_RE_ALL)) {
        /* User requested a recursive pattern search. This generally means
         * pcre_exec will be called at least twice unless the pattern doesn't
         * exist in the string at all. Presence of this option suggests that
         * the user anticipates the pattern occurring at least once, so it's
         * safest to go ahead and study the pattern. -brevantes */
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }


    textstart = text = (char *)DoNullInd(oper1->data.string);

    len = strlen(textstart);
    while((*text != '\0') && (write_left > 0))
    {
        if ((matchcnt = pcre_exec(re->re, re->extra, textstart, len, text-textstart, 0, matches, MATCH_ARR_SIZE)) < 0)
        {
            if (matchcnt != PCRE_ERROR_NOMATCH)
            {
                abort_interp(muf_re_error(matchcnt));
            }

            while((write_left > 0) && (*text != '\0'))
            {
                *write_ptr++ = *text++;
                write_left--;
            }

            break;
        }
        else
        {
            int         allstart    = matches[0];
            int         allend      = matches[1];
            int         substart    = -1;
            int         subend      = -1;
            char*       read_ptr    = (char *)DoNullInd(oper3->data.string);
            int         count;

            for(count = allstart-(text-textstart); (write_left > 0) && (*text != '\0') && (count > 0); count--)
            {
                *write_ptr++ = *text++;
                write_left--;
            }

            while((write_left > 0) && (*read_ptr != '\0'))
            {
                if (*read_ptr == '\\')
                {
                    if (!isdigit(*(++read_ptr)))
                    {
                        *write_ptr++ = *read_ptr++;
                        write_left--;
                    }
                    else
                    {
                        int idx = (*read_ptr++) - '0';

                        if ((idx < 0) || (idx >= matchcnt))
                        {
                            abort_interp("Invalid \\subexp in substitution string. (3)");
                        }

                        substart = matches[idx*2];
                        subend = matches[idx*2+1];

                        if ((substart >= 0) && (subend >= 0) && (substart < len))
                        {
                            char* ptr = &textstart[substart];

                            count = subend - substart;

                            if (count > write_left)
                            {
                                abort_interp("Operation would result in overflow");
                            }

                            for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--)
                            {
                                *write_ptr++ = *ptr++;
                                write_left--;
                            }
                        }
                    }
                }
                else
                {
                    *write_ptr++ = *read_ptr++;
                    write_left--;
                }
            }

            for(count = allend - allstart; (*text != '\0') && (count > 0); count--)
                text++;

            if (allstart == allend && *text) {
                *write_ptr++ = *text++;
                write_left--;
            }
        }

        if ((oper4->data.number & MUF_RE_ALL) == 0)
        {
            while((write_left > 0) && (*text != '\0'))
            {
                *write_ptr++ = *text++;
                write_left--;
            }

            break;
        }
    }

    if (*text != '\0')
        abort_interp("Operation would result in overflow");

    *write_ptr = '\0';

    CLEAR(oper4);
    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushString(buf);
}
Example #22
0
void
prim_regexp(PRIM_PROTOTYPE)
{
    stk_array*  nu_val  = 0;
    stk_array*  nu_idx  = 0;
    int         matches[MATCH_ARR_SIZE];
    muf_re*     re;
    char*       text;
    int         flags   = 0;
    int         len, i;
    int         matchcnt = 0;
    const char* errstr;

    CHECKOP(3);

    oper3 = POP(); /* int:Flags */
    oper2 = POP(); /* str:Pattern */
    oper1 = POP(); /* str:Text */

    if (oper1->type != PROG_STRING)
        abort_interp("Non-string argument (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_INTEGER)
        abort_interp("Non-integer argument (3)");
    if (!oper2->data.string)
        abort_interp("Empty string argument (2)");

    if (oper3->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper3->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL)
        abort_interp(errstr);

    text    = (char *)DoNullInd(oper1->data.string);
    len     = strlen(text);

    if ((matchcnt = pcre_exec(re->re, re->extra, text, len, 0, 0, matches, MATCH_ARR_SIZE)) < 0)
    {
        if (matchcnt != PCRE_ERROR_NOMATCH)
        {
            abort_interp(muf_re_error(matchcnt));
        }

        if (((nu_val = new_array_packed(0)) == NULL) ||
            ((nu_idx = new_array_packed(0)) == NULL))
        {
            if (nu_val != NULL)
                array_free(nu_val);

            if (nu_idx != NULL)
                array_free(nu_idx);

            abort_interp("Out of memory");
        }
    }
    else
    {
        if (((nu_val = new_array_packed(matchcnt)) == NULL) ||
            ((nu_idx = new_array_packed(matchcnt)) == NULL))
        {
            if (nu_val != NULL)
                array_free(nu_val);

            if (nu_idx != NULL)
                array_free(nu_idx);

            abort_interp("Out of memory");
        }

        for(i = 0; i < matchcnt; i++)
        {
            int substart = matches[i*2];
            int subend = matches[i*2+1];
            struct inst idx, val;
            stk_array*  nu;

            if ((substart >= 0) && (subend >= 0) && (substart < len))
                snprintf(buf, BUFFER_LEN, "%.*s", (int)(subend - substart), &text[substart]);
            else
                buf[0] = '\0';

            idx.type        = PROG_INTEGER;
            idx.data.number = i;
            val.type        = PROG_STRING;
            val.data.string = alloc_prog_string(buf);

            array_setitem(&nu_val, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);

            if ((nu = new_array_packed(2)) == NULL)
            {
                array_free(nu_val);
                array_free(nu_idx);

                abort_interp("Out of memory");
            }

            idx.type        = PROG_INTEGER;
            idx.data.number = 0;
            val.type        = PROG_INTEGER;
            val.data.number = substart + 1;

            array_setitem(&nu, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);

            idx.type        = PROG_INTEGER;
            idx.data.number = 1;
            val.type        = PROG_INTEGER;
            val.data.number = subend - substart;

            array_setitem(&nu, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);

            idx.type        = PROG_INTEGER;
            idx.data.number = i;
            val.type        = PROG_ARRAY;
            val.data.array  = nu;

            array_setitem(&nu_idx, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);
        }
    }

    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushArrayRaw(nu_val);
    PushArrayRaw(nu_idx);
}
Example #23
0
void
prim_regfindnext(PRIM_PROTOTYPE)
{
    struct flgchkdat check;
    dbref who, item, ref, i;
    const char *name;
    muf_re* re;
    char* text;
    int flags;
    int matchcnt = 0;
    const char* errstr = NULL;

    CHECKOP(5);
    oper5 = POP();              /* int:pcreflags */
    oper4 = POP();              /* str:objflags */
    oper3 = POP();              /* str:namepattern */
    oper2 = POP();              /* ref:owner */
    oper1 = POP();              /* ref:currobj */

    if (oper5->type != PROG_INTEGER)
        abort_interp("Non-integer argument (5)");
    if (oper4->type != PROG_STRING)
        abort_interp("Expected string argument. (4)");
    if (oper3->type != PROG_STRING)
        abort_interp("Expected string argument. (3)");
    if (oper2->type != PROG_OBJECT)
        abort_interp("Expected dbref argument. (2)");
    if (oper2->data.objref < NOTHING || oper2->data.objref >= db_top)
        abort_interp("Bad object. (2)");
    if (oper1->type != PROG_OBJECT)
        abort_interp("Expected dbref argument. (1)");
    if (oper1->data.objref < NOTHING || oper1->data.objref >= db_top)
        abort_interp("Bad object. (1)");
    if (oper2->data.objref != NOTHING &&
        Typeof(oper2->data.objref) == TYPE_GARBAGE)
        abort_interp("Owner dbref is garbage. (2)");

    item = oper1->data.objref;
    who = oper2->data.objref;
    name = DoNullInd(oper3->data.string);

    if (mlev < 2)
        abort_interp("Permission denied.  Requires at least Mucker Level 2.");

    if (mlev < 3) {
        if (who == NOTHING) {
            abort_interp
                ("Permission denied.  Owner inspecific searches require Mucker Level 3.");
        } else if (who != ProgUID) {
            abort_interp
                ("Permission denied.  Searching for other people's stuff requires Mucker Level 3.");
        }
    }

    flags = PCRE_NO_AUTO_CAPTURE;

    if (oper5->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper5->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    re = regmatch_re_get(oper3->data.string, flags, &errstr);
    if (errstr)
        abort_interp(errstr)

    /* We're scanning a chunk of the DB, so studying should pay off.
     * A null return is fine, it just means we can't optimize further. */
    if (re && !re->extra) {
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    if (item == NOTHING) {
        item = 0;
    } else {
        item++;
    }

    ref = NOTHING;
    init_checkflags(PSafe, DoNullInd(oper4->data.string), &check);
    for (i = item; i < db_top; i++) {
        if ((who == NOTHING || OWNER(i) == who) &&
            checkflags(i, check) && NAME(i)) {
            if (!*name) {
                ref = i;
                break;
            } else {
                text = (char *) NAME(i);
                if ((matchcnt = regmatch_exec(re, text)) < 0) {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    ref = i;
                    break;
                }
            }
        }
    }


    CLEAR(oper1);
    CLEAR(oper2);
    CLEAR(oper3);
    CLEAR(oper4);
    CLEAR(oper5);

    PushObject(ref);
}
Example #24
0
void
prim_regexp(PRIM_PROTOTYPE)
{
    stk_array *nu_val = 0;
    stk_array *nu_idx = 0;
    regmatch_t *matches = 0;
    muf_re *re;
    char *text;
    int flags = 0;
    int nosubs, err, len, i;

    CHECKOP(3);

    oper3 = POP();              /* int:Flags */
    oper2 = POP();              /* str:Pattern */
    oper1 = POP();              /* str:Text */

    if (oper1->type != PROG_STRING)
        abort_interp("Non-string argument (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_INTEGER)
        abort_interp("Non-integer argument (3)");
    if (!oper2->data.string)
        abort_interp("Empty string argument (2)");

    if (oper3->data.number & MUF_RE_ICASE)
        flags |= REG_ICASE;

    if ((re = muf_re_get(oper2->data.string, flags, &err)) == NULL)
        abort_interp(muf_re_error(err));

    text = DoNullInd(oper1->data.string);
    len = strlen(text);
    nosubs = re->re.re_nsub + 1;

    if ((matches = (regmatch_t *) malloc(sizeof(regmatch_t) * nosubs)) == NULL)
        abort_interp("Out of memory");

    if ((err = regexec(&re->re, text, nosubs, matches, 0)) != 0) {
        if (err != REG_NOMATCH) {
            free(matches);
            abort_interp(muf_re_error(err));
        }

        if (((nu_val = new_array_packed(0)) == NULL) ||
            ((nu_idx = new_array_packed(0)) == NULL)) {
            free(matches);

            if (nu_val != NULL)
                array_free(nu_val);

            if (nu_idx != NULL)
                array_free(nu_idx);

            abort_interp("Out of memory");
        }
    } else {
        if (((nu_val = new_array_packed(nosubs)) == NULL) ||
            ((nu_idx = new_array_packed(nosubs)) == NULL)) {
            free(matches);

            if (nu_val != NULL)
                array_free(nu_val);

            if (nu_idx != NULL)
                array_free(nu_idx);

            abort_interp("Out of memory");
        }

        for (i = 0; i < nosubs; i++) {
            regmatch_t *cm = &matches[i];
            struct inst idx, val;
            stk_array *nu;

            if ((cm->rm_so >= 0) && (cm->rm_eo >= 0) && (cm->rm_so < len))
                snprintf(buf, BUFFER_LEN, "%.*s", cm->rm_eo - cm->rm_so,
                         &text[cm->rm_so]);
            else
                buf[0] = '\0';

            idx.type = PROG_INTEGER;
            idx.data.number = i;
            val.type = PROG_STRING;
            val.data.string = alloc_prog_string(buf);

            array_setitem(&nu_val, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);

            if ((nu = new_array_packed(2)) == NULL) {
                free(matches);

                array_free(nu_val);
                array_free(nu_idx);

                abort_interp("Out of memory");
            }

            idx.type = PROG_INTEGER;
            idx.data.number = 0;
            val.type = PROG_INTEGER;
            val.data.number = cm->rm_so + 1;

            array_setitem(&nu, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);

            idx.type = PROG_INTEGER;
            idx.data.number = 1;
            val.type = PROG_INTEGER;
            val.data.number = cm->rm_eo - cm->rm_so;

            array_setitem(&nu, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);

            idx.type = PROG_INTEGER;
            idx.data.number = i;
            val.type = PROG_ARRAY;
            val.data.array = nu;

            array_setitem(&nu_idx, &idx, &val);

            CLEAR(&idx);
            CLEAR(&val);
        }
    }

    free(matches);

    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushArrayRaw(nu_val);
    PushArrayRaw(nu_idx);
}
Example #25
0
void
prim_regsub(PRIM_PROTOTYPE)
{
    regmatch_t *matches = 0;
    int flags = 0;
    char *write_ptr = buf;
    int write_left = BUFFER_LEN - 1;
    muf_re *re;
    char *text;
    int nosubs, err, len, i;

    CHECKOP(4);

    oper4 = POP();              /* int:Flags */
    oper3 = POP();              /* str:Replace */
    oper2 = POP();              /* str:Pattern */
    oper1 = POP();              /* str:Text */

    if (oper1->type != PROG_STRING)
        abort_interp("Non-string argument (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_STRING)
        abort_interp("Non-string argument (3)");
    if (oper4->type != PROG_INTEGER)
        abort_interp("Non-integer argument (4)");
    if (!oper2->data.string)
        abort_interp("Empty string argument (2)");

    if (oper4->data.number & MUF_RE_ICASE)
        flags |= REG_ICASE;

    if ((re = muf_re_get(oper2->data.string, flags, &err)) == NULL)
        abort_interp(muf_re_error(err));

    text = DoNullInd(oper1->data.string);
    nosubs = re->re.re_nsub + 1;

    if ((matches = (regmatch_t *) malloc(sizeof(regmatch_t) * nosubs)) == NULL)
        abort_interp("Out of memory");

    while ((*text != '\0') && (write_left > 0)) {
        len = strlen(text);

        if ((err = regexec(&re->re, text, nosubs, matches, 0)) != 0) {
            if (err != REG_NOMATCH) {
                free(matches);
                abort_interp(muf_re_error(err));
            }

            while ((write_left > 0) && (*text != '\0')) {
                *write_ptr++ = *text++;
                write_left--;
            }

            break;
        } else {
            regmatch_t *cm = &matches[0];
            char *read_ptr = DoNullInd(oper3->data.string);
            int soff = cm->rm_so;
            int count;

            for (count = cm->rm_so;
                 (write_left > 0) && (*text != '\0') && (count > 0); count--) {
                *write_ptr++ = *text++;
                write_left--;
            }

            while ((write_left > 0) && (*read_ptr != '\0')) {
                if (*read_ptr == '\\') {
                    if (!isdigit(*(++read_ptr))) {
                        *write_ptr++ = *read_ptr++;
                        write_left--;
                    } else {
                        int idx = (*read_ptr++) - '0';

                        if ((idx < 0) || (idx >= nosubs)) {
                            free(matches);
                            abort_interp("Invalid \\subexp (3)");
                        }

                        cm = &matches[idx];

                        if ((cm->rm_so >= 0) && (cm->rm_eo >= 0)
                            && (cm->rm_so < len)) {
                            char *ptr = &text[cm->rm_so - soff];

                            count = cm->rm_eo - cm->rm_so;

                            if (count > write_left) {
                                free(matches);
                                abort_interp
                                    ("Operation would result in overflow");
                            }

                            for (; (write_left > 0) && (count > 0)
                                 && (*ptr != '\0'); count--) {
                                *write_ptr++ = *ptr++;
                                write_left--;
                            }
                        }
                    }
                } else {
                    *write_ptr++ = *read_ptr++;
                    write_left--;
                }
            }

            cm = &matches[0];

            for (count = cm->rm_eo - cm->rm_so; (*text != '\0') && (count > 0);
                 count--)
                text++;
        }

        if ((oper4->data.number & MUF_RE_ALL) == 0) {
            while ((write_left > 0) && (*text != '\0')) {
                *write_ptr++ = *text++;
                write_left--;
            }

            break;
        }
    }

    free(matches);

    if (*text != '\0')
        abort_interp("Operation would result in overflow");

    *write_ptr = '\0';

    CLEAR(oper4);
    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushString(buf);
}
Example #26
0
void
prim_regsub(PRIM_PROTOTYPE)
{
	int			matches[MATCH_ARR_SIZE];
	int			flags		= 0;
	char*		write_ptr	= buf;
	int			write_left	= BUFFER_LEN - 1;
	muf_re*		re;
	char*		text;
	char*		textstart;
	const char*	errstr;
	int			matchcnt, len;

	CHECKOP(4);

	oper4 = POP(); /* int:Flags */
	oper3 = POP(); /* str:Replace */
	oper2 = POP(); /* str:Pattern */
	oper1 = POP(); /* str:Text */

	if (oper1->type != PROG_STRING)
		abort_interp("Non-string argument (1)");
	if (oper2->type != PROG_STRING)
		abort_interp("Non-string argument (2)");
	if (oper3->type != PROG_STRING)
		abort_interp("Non-string argument (3)");
	if (oper4->type != PROG_INTEGER)
		abort_interp("Non-integer argument (4)");
	if (!oper2->data.string)
		abort_interp("Empty string argument (2)");

	if (oper4->data.number & MUF_RE_ICASE)
		flags |= PCRE_CASELESS;
	if (oper4->data.number & MUF_RE_EXTENDED)
		flags |= PCRE_EXTENDED;

	if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL)
		abort_interp(errstr);

	textstart = text = DoNullInd(oper1->data.string);

	len = strlen(textstart);
	while((*text != '\0') && (write_left > 0))
	{
		if ((matchcnt = pcre_exec(re->re, NULL, textstart, len, text-textstart, 0, matches, MATCH_ARR_SIZE)) < 0)
		{
			if (matchcnt != PCRE_ERROR_NOMATCH)
			{
				abort_interp(muf_re_error(matchcnt));
			}

			while((write_left > 0) && (*text != '\0'))
			{
				*write_ptr++ = *text++;
				write_left--;
			}

			break;
		}
		else
		{
			int			allstart	= matches[0];
			int			allend		= matches[1];
			int			substart	= -1;
			int			subend		= -1;
			char*		read_ptr	= DoNullInd(oper3->data.string);
			int			count;

			for(count = allstart-(text-textstart); (write_left > 0) && (*text != '\0') && (count > 0); count--)
			{
				*write_ptr++ = *text++;
				write_left--;
			}

			while((write_left > 0) && (*read_ptr != '\0'))
			{
				if (*read_ptr == '\\')
				{
					if (!isdigit(*(++read_ptr)))
					{
						*write_ptr++ = *read_ptr++;
						write_left--;
					}
					else
					{
						int idx = (*read_ptr++) - '0';

						if ((idx < 0) || (idx >= matchcnt))
						{
							abort_interp("Invalid \\subexp in substitution string. (3)");
						}

						substart = matches[idx*2];
						subend = matches[idx*2+1];

						if ((substart >= 0) && (subend >= 0) && (substart < len))
						{
							char* ptr = &textstart[substart];

							count = subend - substart;

							if (count > write_left)
							{
								abort_interp("Operation would result in overflow");
							}

							for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--)
							{
								*write_ptr++ = *ptr++;
								write_left--;
							}
						}
					}
				}
				else
				{
					*write_ptr++ = *read_ptr++;
					write_left--;
				}
			}

			for(count = allend - allstart; (*text != '\0') && (count > 0); count--)
				text++;

			if (allstart == allend && *text) {
				*write_ptr++ = *text++;
				write_left--;
			}
		}

		if ((oper4->data.number & MUF_RE_ALL) == 0)
		{
			while((write_left > 0) && (*text != '\0'))
			{
				*write_ptr++ = *text++;
				write_left--;
			}

			break;
		}
	}

	if (*text != '\0')
		abort_interp("Operation would result in overflow");

	*write_ptr = '\0';

	CLEAR(oper4);
	CLEAR(oper3);
	CLEAR(oper2);
	CLEAR(oper1);

	PushString(buf);
}
Example #27
0
void
prim_setsysparm(PRIM_PROTOTYPE)
{
    const char *parmname, *newvalue;
    char *oldvalue;
    int security = TUNE_MLEV(player);

    CHECKOP(2);
    oper1 = POP();		/* string: new parameter value */
    oper2 = POP();		/* string: parameter to tune */

    if (mlev < 4)
	abort_interp("Wizbit only primitive.");
    if (force_level)
	abort_interp("Cannot be forced.");
    if (oper2->type != PROG_STRING)
	abort_interp("Invalid argument. (1)");
    if (!oper2->data.string)
	abort_interp("Null string argument. (1)");
    if (oper1->type != PROG_STRING)
	abort_interp("Invalid argument. (2)");

    parmname = oper2->data.string->data;
    /* Duplicate the string, otherwise the oldvalue pointer will be overridden to the new value
       when tune_setparm() is called. */
    oldvalue = strdup(tune_get_parmstring(oper2->data.string->data, security));
    newvalue = DoNullInd(oper1->data.string);

    result = tune_setparm(player, parmname, newvalue, security);

    /* Note: free(oldvalue) BEFORE calling abort_interp, or it will leak. */
    switch (result) {
    case TUNESET_SUCCESS:
	log_status("TUNED (MUF): %s(%d) tuned %s from '%s' to '%s'",
		   NAME(player), player, parmname, oldvalue, newvalue);
	if (oldvalue)
	    free(oldvalue);
	break;
    case TUNESET_SUCCESS_DEFAULT:
	/* No need to show the flag in output */
	TP_CLEAR_FLAG_DEFAULT(parmname);
	log_status("TUNED (MUF): %s(%d) tuned %s from '%s' to default",
		   NAME(player), player, parmname, oldvalue);
	if (oldvalue)
	    free(oldvalue);
	break;
    case TUNESET_UNKNOWN:
	if (oldvalue)
	    free(oldvalue);
	abort_interp("Unknown parameter. (1)");
    case TUNESET_SYNTAX:
	if (oldvalue)
	    free(oldvalue);
	abort_interp("Bad parameter syntax. (2)");
    case TUNESET_BADVAL:
	if (oldvalue)
	    free(oldvalue);
	abort_interp("Bad parameter value. (2)");
    case TUNESET_DENIED:
	if (oldvalue)
	    free(oldvalue);
	abort_interp("Permission denied. (1)");
    default:
	if (oldvalue)
	    free(oldvalue);
	break;
    }
    CLEAR(oper1);
    CLEAR(oper2);
}
Example #28
0
void
prim_array_regfilter_prop(PRIM_PROTOTYPE)
{
    char buf[BUFFER_LEN];
    struct inst *in;
    stk_array *arr;
    stk_array *nu;
    char* prop;
    const char* ptr;
    muf_re* re;
    int flags;
    int matchcnt = 0;
    const char* errstr = NULL;

    CHECKOP(4);
    oper4 = POP();    /* int     pcreflags */
    oper3 = POP();    /* str     pattern */
    oper2 = POP();    /* str     propname */
    oper1 = POP();    /* refarr  Array */

    if (oper1->type != PROG_ARRAY)
        abort_interp("Argument not an array. (1)");
    if (!array_is_homogenous(oper1->data.array, PROG_OBJECT))
        abort_interp("Argument not an array of dbrefs. (1)");
    if (oper2->type != PROG_STRING || !oper2->data.string)
        abort_interp("Argument not a non-null string. (2)");
    if (oper3->type != PROG_STRING)
        abort_interp("Argument not a string pattern. (3)");
    if (oper4->type != PROG_INTEGER)
        abort_interp("Non-integer argument (4)");


    ptr = oper2->data.string->data;
    while ((ptr = index(ptr, PROPDIR_DELIMITER)))
        if (!(*(++ptr)))
            abort_interp("Cannot access a propdir directly.");
    nu = new_array_packed(0);
    arr = oper1->data.array;

    flags = PCRE_NO_AUTO_CAPTURE;

    if (oper4->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper4->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    re = regmatch_re_get(oper3->data.string, flags, &errstr);
    if (errstr)
        abort_interp(errstr)

    if (re && !re->extra && array_count(arr) > 2) {
        /* This pattern is getting used 3 or more times, let's study it. A null
         * return is okay, that just means there's nothing to optimize. */
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    prop = (char *) DoNullInd(oper2->data.string);
    if (array_first(arr, &temp1)) {
        do {
            in = array_getitem(arr, &temp1);
            if (valid_object(in)) {
                ref = in->data.objref;
                CHECKREMOTE(ref);
                if (prop_read_perms(ProgUID, ref, prop, mlev)) {
                    ptr = get_property_class(ref, prop);
                    if (ptr)
                        strcpy(buf, ptr);
                    else
                        strcpy(buf, "");
                    if ((matchcnt = regmatch_exec(re, buf)) < 0) {
                        if (matchcnt != PCRE_ERROR_NOMATCH)
                            abort_interp(muf_re_error(matchcnt));
                    } else {
                        array_appenditem(&nu, in);
                    }
                }
            }
        } while (array_next(arr, &temp1));
    }


    CLEAR(oper4);
    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);
    PushArrayRaw(nu);
}
Example #29
0
void
prim_regfind_array(PRIM_PROTOTYPE)
{
    struct flgchkdat check;
    dbref ref, who;
    const char *name;
    stk_array *nw;
    muf_re* re;
    char* text = NULL;
    int flags;
    int matchcnt = 0;
    const char* errstr = NULL;

    CHECKOP(4);
    oper4 = POP();              /* int:pcreflags */
    oper3 = POP();              /* str:objflags */
    oper2 = POP();              /* str:namepattern */
    oper1 = POP();              /* ref:owner */

    if (mlev < LMAGE)
        abort_interp("MAGE prim.");
    if (oper4->type != PROG_INTEGER)
        abort_interp("Non-integer argument (4)");
    if (oper3->type != PROG_STRING)
        abort_interp("Expected string argument. (3)");
    if (oper2->type != PROG_STRING)
        abort_interp("Expected string argument. (2)");
    if (oper1->type != PROG_OBJECT)
        abort_interp("Expected dbref argument. (1)");
    if (oper1->data.objref < NOTHING || oper1->data.objref >= db_top)
        abort_interp("Bad object. (1)");


    flags = PCRE_NO_AUTO_CAPTURE;

    if (oper4->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper4->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    re = regmatch_re_get(oper2->data.string, flags, &errstr);
    if (errstr)
        abort_interp(errstr)

    /* We're scanning a chunk of the DB, so studying should pay off.
     * A null return is fine, it just means we can't optimize further. */
    if (re && !re->extra) {
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    who = oper1->data.objref;
    name = DoNullInd(oper2->data.string);

    init_checkflags(PSafe, DoNullInd(oper3->data.string), &check);
    nw = new_array_packed(0);

    /* The "result = array_appendref" stuff was copied from find_array. I'm
     * making sure these alterations work as-is before attempting to remove it.
     * -brevantes */
    for (ref = (dbref) 0; ref < db_top; ref++) {
        if (((who == NOTHING) ? 1 : (OWNER(ref) == who)) &&
            checkflags(ref, check) && NAME(ref)) {
            if (!*name)
                result = array_appendref(&nw, ref);
            else
                text = (char *)NAME(ref);
                if ((matchcnt = regmatch_exec(re, text)) < 0)
                {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    result = array_appendref(&nw, ref);
                }
        }
    }


    CLEAR(oper1);
    CLEAR(oper2);
    CLEAR(oper3);
    CLEAR(oper4);
    PushArrayRaw(nw);
}
Example #30
0
void
prim_parsepropex(PRIM_PROTOTYPE)
{
	struct inst*	oper1 = NULL; /* prevents reentrancy issues! */
	struct inst*	oper2 = NULL; /* prevents reentrancy issues! */
	struct inst*	oper3 = NULL; /* prevents reentrancy issues! */
	struct inst*	oper4 = NULL; /* prevents reentrancy issues! */
	stk_array*		vars;
	const char*		mpi;
	char*			str = 0;
	array_iter		idx;
	extern int		varc; /* from msgparse.c */
	int				mvarcnt = 0;
	char*			buffers = NULL;
	int				novars;
	int				hashow = 0;
	int				i;
	int             len;
	char			tname[BUFFER_LEN];
	char			buf[BUFFER_LEN];

	CHECKOP(4);

	oper4 = POP(); /* int:Private */
	oper3 = POP(); /* dict:Vars */
	oper2 = POP(); /* str:Prop */
	oper1 = POP(); /* ref:Object */

	if (mlev < 3)
		abort_interp("Mucker level 3 or greater required.");

	if (oper1->type != PROG_OBJECT)
		abort_interp("Non-object argument. (1)");
	if (oper2->type != PROG_STRING)
		abort_interp("Non-string argument. (2)");
	if (oper3->type != PROG_ARRAY)
		abort_interp("Non-array argument. (3)");
	if (oper3->data.array && (oper3->data.array->type != ARRAY_DICTIONARY))
		abort_interp("Dictionary array expected. (3)");
	if (oper4->type != PROG_INTEGER)
		abort_interp("Non-integer argument. (4)");

	if (!valid_object(oper1))
		abort_interp("Invalid object. (1)");
	if (!oper2->data.string)
		abort_interp("Empty string argument. (2)");
	if ((oper4->data.number != 0) && (oper4->data.number != 1))
		abort_interp("Integer of 0 or 1 expected. (4)");

	CHECKREMOTE(oper1->data.objref);

	if (!prop_read_perms(ProgUID, oper1->data.objref, oper2->data.string->data, mlev))
		abort_interp("Permission denied.");

	len = oper2->data.string->length;
	strcpyn(tname, sizeof(tname), oper2->data.string->data);
	while (len-- > 0 && tname[len] == PROPDIR_DELIMITER) {
		tname[len] = '\0';
	}

	mpi		= get_property_class(oper1->data.objref, tname);
	vars	= oper3->data.array;
	novars	= array_count(vars);

	if (check_mvar_overflow(novars))
		abort_interp("Out of MPI variables. (3)");

	if (array_first(vars, &idx))
	{
		do
		{
			array_data*	val = array_getitem(vars, &idx);

			if (idx.type != PROG_STRING)
			{
				CLEAR(&idx);
				abort_interp("Only string keys supported. (3)");
			}

			if (idx.data.string == NULL)
			{
				CLEAR(&idx);
				abort_interp("Empty string keys not supported. (3)");
			}

			if (strlen(idx.data.string->data) > MAX_MFUN_NAME_LEN)
			{
				CLEAR(&idx);
				abort_interp("Key too long to be an MPI variable. (3)");
			}

			switch(val->type)
			{
				case PROG_INTEGER:
				case PROG_FLOAT:
				case PROG_OBJECT:
				case PROG_STRING:
				case PROG_LOCK:
				break;

				default:
					CLEAR(&idx);
					abort_interp("Only integer, float, dbref, string and lock values supported. (3)");
				break;
			}

			if (string_compare(idx.data.string->data, "how") == 0)
				hashow = 1;
		}
		while(array_next(vars, &idx));
	}

	if (mpi && *mpi)
	{
		if (novars > 0)
		{
			mvarcnt = varc;

			if ((buffers = (char*)malloc(novars * BUFFER_LEN)) == NULL)
				abort_interp("Out of memory.");

			if (array_first(vars, &idx))
			{
				i = 0;

				do
				{
					char*		var_buf = buffers + (i++ * BUFFER_LEN);
					array_data*	val;

					val = array_getitem(vars, &idx);

					switch(val->type)
					{
						case PROG_INTEGER:
							snprintf(var_buf, BUFFER_LEN, "%i", val->data.number);
						break;

						case PROG_FLOAT:
							snprintf(var_buf, BUFFER_LEN, "%g", val->data.fnumber);
						break;

						case PROG_OBJECT:
							snprintf(var_buf, BUFFER_LEN, "#%i", val->data.objref);
						break;

						case PROG_STRING:
							strncpy(var_buf, DoNullInd(val->data.string), BUFFER_LEN);
						break;

						case PROG_LOCK:
							strncpy(var_buf, unparse_boolexp(ProgUID, val->data.lock, 1), BUFFER_LEN);
						break;

						default:
							var_buf[0] = '\0';
						break;
					}

					var_buf[BUFFER_LEN - 1] = '\0';

					new_mvar(idx.data.string->data, var_buf);
				}
				while(array_next(vars, &idx));
			}
		}

		result = 0;

		if (oper4->data.number)
			result |= MPI_ISPRIVATE;

		if (Prop_Blessed(oper1->data.objref, oper2->data.string->data))
			result |= MPI_ISBLESSED;

		if (hashow)
			result |= MPI_NOHOW;

		str = do_parse_mesg(fr->descr, player, oper1->data.objref, mpi, "(parsepropex)", buf, sizeof(buf), result);

		if (novars > 0)
		{
			if (array_first(vars, &idx))
			{
				i = 0;

				do
				{
					char*		var_buf = buffers + (i++ * BUFFER_LEN);
					struct inst	temp;

					temp.type			= PROG_STRING;
					temp.data.string	= alloc_prog_string(var_buf);

					array_setitem(&vars, &idx, &temp);

					CLEAR(&temp);
				}
				while(array_next(vars, &idx));
			}

			free(buffers);

			varc = mvarcnt;
		}
	}

	oper3->data.array = NULL;

	CLEAR(oper1);
	CLEAR(oper2);
	CLEAR(oper3);
	CLEAR(oper4);

	PushArrayRaw(vars);
	PushString(str);
}