ShellBanner
System:Linux MiraNet 3.0.0-14-generic-pae #23-Ubuntu SMP Mon Nov 21 22:07:10 UTC 2011 i686
Software:Apache. PHP/5.3.6-13ubuntu3.10
ID:uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
Safe Mode:OFF
Open_Basedir:OFF
Freespace:23.7 GB of 70.42 GB (33.65%)
MySQL: ON MSSQL: OFF Oracle: OFF PostgreSQL: OFF Curl: OFF Sockets: ON Fetch: OFF Wget: ON Perl: ON
Disabled Functions: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

/ usr/ src/ maildrop-2.2.0/ maildrop/ - drwxr-xr-x

Directory:
Viewing file:     recipenode.C (29.35 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 1998 - 2009 Double Precision, Inc.
** See COPYING for distribution information.
*/

#include    "recipenode.h"
#include    "recipe.h"
#include    "varlist.h"
#include    "message.h"
#include    "funcs.h"
#include    "mio.h"
#include    "search.h"
#include    "dotlock.h"
#include    "maildrop.h"
#include    "log.h"
#include    "config.h"
#include    "xconfig.h"
#include    "lexer.h"
#include    "filelock.h"
#include    "rfc822.h"
#include    "mytime.h"
#include    <ctype.h>
#include    <stdlib.h>
#include    <string.h>
#include    <sysexits.h>

static const char rcsid[]="$Id: recipenode.C,v 1.27 2009/06/27 16:32:38 mrsam Exp $";

extern int xfilter(const char *, int);

static void parse_backslash(const Buffer &, Buffer &);

//////////////////////////////////////////////////////////////////////////
//
// Utility class to save and restore the status of the embedded_mode flag.
//
// Embedded mode can be temporarily disabled by including something from
// ETCDIR/maildroprcs.
//

class MaildropSaveEM {
    int save_mode;
public:
    MaildropSaveEM() { save_mode=maildrop.embedded_mode; }
    ~MaildropSaveEM() { maildrop.embedded_mode=save_mode; }
} ;

//////////////////////////////////////////////////////////////////////////

RecipeNode::RecipeNode(RecipeNodeType t) : prevNode(0), nextNode(0),
    parentNode(0), prevSibling(0), nextSibling(0),
    firstChild(0), lastChild(0), linenum(0), nodeType(t)
{
}

void    RecipeNode::AppendSibling(RecipeNode *chld)
{
    chld->parentNode=this;
    chld->nextSibling=0;
    if ( (chld->prevSibling=lastChild) != 0)
        lastChild->nextSibling=chld;
    else
        firstChild=chld;
    lastChild=chld;
}

void    RecipeNode::Evaluate(Recipe &r, Buffer &b)
{
RecipeNode    *c;

    b.reset();
    switch (nodeType)    {
    case statementlist:

        for (c=firstChild; c; c=c->nextSibling)
        {
            b.reset();
            c->Evaluate(r, b);
        }
        break;
    case assignment:
        if (!firstChild || !firstChild->nextSibling ||
            firstChild->nodeType != qstring)
                throw "Internal error in assignment.";
        firstChild->nextSibling->Evaluate(r, b);
        if (VerboseLevel() > 3)
        {
        Buffer    s;

            s=firstChild->str;
            s += "=\"";
            s += b;
            s += "\"";
            s += '\0';
            r.errmsg(*this, s);
        }
        SetVar(firstChild->str, b);
        break;
    case regexpr:
        EvaluateRegExp(r, b, (Buffer *)NULL);
        break;
    case qstring:
    case sqstring:
    case btstring:
        EvaluateString(r, b);
        break;
    case add:
    case subtract:
    case multiply:
    case divide:
    case lessthan:
    case lessthanoreq:
    case greaterthan:
    case greaterthanoreq:
    case equal:
    case notequal:
    case bitwiseor:
    case bitwiseand:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in evaluate binary.";
        {
        double a1, a2;
        Buffer ba1, ba2;
        Buffer debug;

            firstChild->Evaluate(r, ba1);
            firstChild->nextSibling->Evaluate(r, ba2);

            if (VerboseLevel() > 5)
            {
                debug="Operation on: ";
                debug += ba1;
                debug += " and ";
                debug += ba2;
            }

            ba1 += '\0';
            ba2 += '\0';
            maildrop.sigfpe=0;
            a1=atof( (const char *)ba1 );
            a2=atof( (const char *)ba2 );
            switch (nodeType)    {
            case add:
                a1 += a2;
                if (VerboseLevel() > 5)
                    debug += " - add";
                break;
            case subtract:
                a1 -= a2;
                if (VerboseLevel() > 5)
                    debug += " - subtract";
                break;
            case multiply:
                if (VerboseLevel() > 5)
                    debug += " - multiply";
                a1 *= a2;
                break;
            case divide:
                if (VerboseLevel() > 5)
                    debug += " - divide";
                a1 /= a2;
                break;
            case lessthan:
                a1=a1 < a2;
                if (VerboseLevel() > 5)
                    debug += " - less than";
                break;
            case lessthanoreq:
                a1=a1 <= a2;
                if (VerboseLevel() > 5)
                    debug += " - less than or equal";
                break;
            case greaterthan:
                a1=a1 > a2;
                if (VerboseLevel() > 5)
                    debug += " - greater than";
                break;
            case greaterthanoreq:
                a1=a1 >= a2;
                if (VerboseLevel() > 5)
                    debug += " - greater than or equal";
                break;
            case equal:
                a1= a1 == a2;
                if (VerboseLevel() > 5)
                    debug += " - equal";
                break;
            case notequal:
                a1= a1 != a2;
                if (VerboseLevel() > 5)
                    debug += " - not equal";
                break;
            case bitwiseor:
                a1= (unsigned long)a1 | (unsigned long)a2;
                if (VerboseLevel() > 5)
                    debug += " - bitwise or";
                break;
            case bitwiseand:
                a1= (unsigned long)a1 & (unsigned long)a2;
                if (VerboseLevel() > 5)
                    debug += " - bitwise and";
                break;
            default:
                break;
            }
            if (maildrop.sigfpe)
            {
                r.errmsg(*this, "Numerical exception.\n");
                a1=0;
            }
            b.append(a1);
            if (VerboseLevel() > 5)
            {
                debug += ", result is ";
                debug += b;
                debug += '\0';
                r.errmsg(*this, debug);
            }
        }
        break;
    case strlessthan:
    case strlessthanoreq:
    case strgreaterthan:
    case strgreaterthanoreq:
    case strequal:
    case strnotequal:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in evaluate binary.";
        {
        Buffer ba1, ba2;
        Buffer debug;

            firstChild->Evaluate(r, ba1);
            firstChild->nextSibling->Evaluate(r, ba2);

            if (VerboseLevel() > 5)
            {
                debug="Operation on: ";
                debug += ba1;
                debug += " and ";
                debug += ba2;
            }

            ba1 += '\0';
            ba2 += '\0';

        int    n=strcmp( (const char *)ba1, (const char *)ba2);

            switch (nodeType)    {
            case strlessthan:
                n= n < 0;
                if (VerboseLevel() > 5)
                    debug += " - string less than";
                break;
            case strlessthanoreq:
                n= n <= 0;
                if (VerboseLevel() > 5)
                    debug += " - string less than or equal";
                break;
            case strgreaterthan:
                n= n > 0;
                if (VerboseLevel() > 5)
                    debug += " - string greater than";
                break;
            case strgreaterthanoreq:
                n= n >= 0;
                if (VerboseLevel() > 5)
                    debug += " - string grater than or equal";
                break;
            case strequal:
                n= n == 0;
                if (VerboseLevel() > 5)
                    debug += " - string equal";
                break;
            case strnotequal:
                n= n != 0;
                if (VerboseLevel() > 5)
                    debug += " - string not equal";
                break;
            default:
                break;
            }
            b.append((unsigned long)n);
            if (VerboseLevel() > 5)
            {
                debug += ", result is ";
                debug += b;
                debug += '\0';
                r.errmsg(*this, debug);
            }
            break;
        }
    case logicalnot:
        if (!firstChild)
            throw "Internal error in evaluate unary.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation on: ";
            debug += b;
            debug += " - logical not.";
            debug += '\0';
            r.errmsg(*this, debug);
        }
        {
        int n= !boolean(b);

            b.reset();
            b.append( (unsigned long)n );
        }
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation: logical not=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        break;
    case bitwisenot:
        if (!firstChild)
            throw "Internal error in evaluate unary.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation on: ";
            debug += b;
            debug += " - bitwise not.";
            debug += '\0';
            r.errmsg(*this, debug);
        }
        maildrop.sigfpe=0;
        {
            b += '\0';

        long n=atol( (const char *) b);

            n= ~n;
            b.reset();
            if (n < 0)
            {
                b += '-';
                n= -n;
            }
            b.append( (unsigned long)n );
        }
        if (maildrop.sigfpe)
        {
            r.errmsg(*this, "Numerical exception.\n");
        }
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation: bitwise not=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        break;
    case logicalor:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in evaluate binary.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation: logical or, left hand side=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        if (!boolean(b))
        {
            if (VerboseLevel() > 5)
            {
            Buffer    debug;

                debug="Operation: logical or, evaluating right hand size.";
                debug += '\0';
                r.errmsg(*this, debug);
            }
            firstChild->nextSibling->Evaluate(r, b);
        }
        if (VerboseLevel() > 5)
        {
        Buffer debug;

            debug="Operation: logical or, result=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        break;
    case logicaland:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in evaluate binary.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation: logical and, left hand side=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        if (boolean(b))
        {
            if (VerboseLevel() > 5)
            {
            Buffer    debug;

                debug="Operation: logical and, evaluating right hand size.";
                debug += '\0';
                r.errmsg(*this, debug);
            }
            firstChild->nextSibling->Evaluate(r, b);
        }
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation: logical and, result=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        break;
    case concat:
        {
        Buffer    bb;

            for (c=firstChild; c; c=c->nextSibling)
            {
                c->Evaluate(r, bb);
                b += bb;
            }
        }
        break;
    case strlength:
        if (!firstChild)
            throw "Internal error in evaluate unary.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation on: ";
            debug += b;
            debug += " - strlength.";
            debug += '\0';
            r.errmsg(*this, debug);
        }
        {
        unsigned long    n=b.Length();

            b.reset();
            b.append(n);
        }
        if (VerboseLevel() > 5)
        {
        Buffer    debug;

            debug="Operation: strlength=";
            debug += b;
            debug += '\0';
            r.errmsg(*this, debug);
        }
        break;
    case    strsubstr:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in evaluate unary.";
        {
        Buffer    bb, cc;

            firstChild->Evaluate(r, bb);
            firstChild->nextSibling->Evaluate(r, cc);
            cc += '\0';

        long n=atol( (const char *) cc);

            if (VerboseLevel() > 5)
            {
            Buffer    debug;

                debug="Operation on: ";
                debug += bb;
                debug += " - strsubstr ";
                debug.append( (unsigned long) n);
                debug += '\0';
                r.errmsg(*this, debug);
            }
    
        long l=bb.Length();

            if (n < 0 || n > l)    n=l;
            b.append( (const char *)bb + n, l-n);
            if (firstChild->nextSibling->nextSibling)
            {
                firstChild->nextSibling->nextSibling->
                            Evaluate(r, cc);
                cc += '\0';
                n=atol( (const char *)cc);
                if (n < b.Length())
                    b.Length(n);

                if (VerboseLevel() > 5)
                {
                Buffer    debug;

                    debug="Operation on: ";
                    debug += bb;
                    debug += " - strsubstr chop ";
                    debug.append( (unsigned long)n);
                    debug += '\0';
                    r.errmsg(*this, debug);
                }
            }
            if (VerboseLevel() > 5)
            {
            Buffer    debug;

                debug="Operation: ";
                debug += " strsubstr=";
                debug.append(b);
                debug += '\0';
                r.errmsg(*this, debug);
            }
        }
        break;
    case strregexp:
        EvaluateStrRegExp(r, b, (Buffer *)NULL);
        break;
    case whileloop:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in while loop.";

        for (;;)
        {
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="Evaluating WHILE condition.";
                r.errmsg(*this, buf);
            }
            firstChild->Evaluate(r,b);
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="While condition evaluated, result=";
                buf += b;
                buf += '\0';
                r.errmsg(*this, buf);
            }
            if (! boolean(b))    break;

            firstChild->nextSibling->Evaluate(r, b);
        }
        break;
    case ifelse:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in while loop.";
        if (VerboseLevel() > 3)
        {
        Buffer    buf;

            buf="Evaluating IF condition.";
            buf += '\0';
            r.errmsg(*this, buf);
        }
        firstChild->Evaluate(r,b);

        if (VerboseLevel() > 3)
        {
        Buffer    buf;

            buf="IF evaluated, result=";
            buf += b;
            buf += '\0';
            r.errmsg(*this, buf);
        }
        if (boolean(b))
            firstChild->nextSibling->Evaluate(r, b);
        else if (firstChild->nextSibling->nextSibling)
            firstChild->nextSibling->nextSibling->Evaluate(r, b);
        break;
    case deliver:
        if (!firstChild)
            throw "Internal error in delivery statement.";
        firstChild->Evaluate(r,b);
        b += '\0';
        if (delivery(b) < 0)
            throw "Unable to deliver to mailbox.";
        b="EXITCODE";
        throw ( GetVar(b)->Int("0") );
    case delivercc:
        if (!firstChild)
            throw "Internal error in delivery statement.";
        firstChild->Evaluate(r,b);
        b += '\0';
        if (delivery(b) < 0)
            throw "Unable to deliver to mailbox.";
        b = "0";
        break;
    case xfilter:
        if (!firstChild)
            throw "Internal error in xfilter statement.";
        firstChild->Evaluate(r,b);
        b += '\0';
        if (VerboseLevel() > 0)
            merr << "maildrop: Filtering through xfilter " <<
                (const char *)b << "\n";
        if (filter(b) < 0)
            throw "Unable to filter message.";
        b = "0";
        break;
    case exception:
        if (!firstChild)
            throw "Internal error in delivery statement.";
        try
        {
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="Trapping exceptions.";
                buf += '\0';
                r.errmsg(*this, buf);
            }
            firstChild->Evaluate(r, b);
            b="";
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="Exception trapping removed.";
                buf += '\0';
                r.errmsg(*this, buf);
            }
        }
        catch (const char *p)
        {
            b=p;
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="Trapped exception.";
                buf += '\0';
                r.errmsg(*this, buf);
            }
        }
#if NEED_NONCONST_EXCEPTIONS
        catch (char *p)
        {
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="Trapped exceptions.";
                buf += '\0';
                r.errmsg(*this, buf);
            }
            b=p;
        }
#endif
        catch (int rc)
        {
            if (rc == 0)
                throw rc;
            rc=0;
            b="";
            if (VerboseLevel() > 3)
            {
            Buffer    buf;

                buf="Trapped exception.";
                buf += '\0';
                r.errmsg(*this, buf);
            }
        }
        break;
    case echo:
        if (!firstChild)
            throw "Internal error in echo statement.";
        firstChild->Evaluate(r, b);
        {
        Buffer    s;

            parse_backslash(b, s);
            mout << s;
        }
        break;
    case dotlock:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in dotlock statement.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 3)
        {
        Buffer    s;

            s="Creating dotlock ";
            s += b;
            s += '\0';
            r.errmsg(*this, s);
        }
        b += '\0';
        {
        DotLock    d;

            d.Lock(b);
            firstChild->nextSibling->Evaluate(r, b);
            d.Unlock();
        }
        break;
    case flock:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in flock statement.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 3)
        {
        Buffer    s;

            s="Creating flock ";
            s += b;
            s += '\0';
            r.errmsg(*this, s);
        }
        b += '\0';
        {
        FileLock    filelock;

            filelock.Lock(b);
            firstChild->nextSibling->Evaluate(r, b);
        }
        break;
    case logfile:
        if (!firstChild)
            throw "Internal error in logfile statement.";
        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 3)
        {
        Buffer    s;

            s="Opening logfile ";
            s += b;
            s += '\0';
            r.errmsg(*this, s);
        }
        b += '\0';
        maildrop.logfile.Close();
        if (maildrop.logfile.Open(b, O_CREAT | O_WRONLY | O_APPEND,
            0600) < 0)
            throw "Unable to create log file.";
        break;
    case log:
        if (!firstChild)
            throw "Internal error in logfile statement.";
        firstChild->Evaluate(r, b);
        {
        Buffer    s;

            parse_backslash(b, s);
            log_line(s);
        }
        break;
    case importtoken:
        if (!firstChild)
            throw "Internal error in import statement.";
        firstChild->Evaluate(r, b);
        {
        Buffer    s;

            if (VerboseLevel() > 3)
            {
                s="import ";
                s += " \"";
                s += b;
                s += "\"";
                s += '\0';
                r.errmsg(*this, s);
            }

            s=b;

            s += '\0';

        const char *name=s;
        const char *val=getenv(name);

            if (!val)    val="";
            s=val;

            SetVar(b, s);
        }
        break;
    case include:
        if (!firstChild)
            throw "Internal error in logfile statement.";
        if (maildrop.includelevel >= 20)
        {
            r.errmsg(*this, "Too many included files.");
            throw EX_TEMPFAIL;
        }

        firstChild->Evaluate(r, b);
        if (VerboseLevel() > 3)
        {
        Buffer    s;

            s="Opening include file ";
            s += b;
            s += '\0';
            r.errmsg(*this, s);
        }
        b += '\0';
        {
        Recipe    r;
        Lexer    in;
        MaildropSaveEM save_embedded_mode;
        static const char embedded_mode_directory[]=ETCDIR "/maildroprcs/";

            if (strncmp( (const char *)b, embedded_mode_directory,
                sizeof(embedded_mode_directory)-1) == 0 &&
                strchr( (const char *)b, '.') == 0)
            {
                maildrop.embedded_mode=0;
                maildrop.reset_vars();
            }
            if (in.Open( (const char *)b ) < 0)
                throw "Unable to open include file.";
            if (r.ParseRecipe(in) < 0)
                throw EX_TEMPFAIL;

            try
            {
                ++maildrop.includelevel;
                r.ExecuteRecipe();
                --maildrop.includelevel;
            }
            catch (...)
            {
                --maildrop.includelevel;
                throw;
            }
        }
        break;
    case exit:
        b="EXITCODE";
        ::exit ( GetVar(b)->Int("0") );
    case foreach:
        if (!firstChild || !firstChild->nextSibling ||
            ( firstChild->nodeType != regexpr &&
                firstChild->nodeType != strregexp))
            throw "Internal error in foreach statement.";
        {
        Buffer    foreachbuf;
        Buffer    varname;
        Buffer    varvalue;

            if (firstChild->nodeType == regexpr)
                firstChild->EvaluateRegExp(r, b, &foreachbuf);
            else
                firstChild->EvaluateStrRegExp(r,b,&foreachbuf);

        const char *p=foreachbuf;
        int l=foreachbuf.Length();

            while (l)
            {
                varvalue.reset();

            int    i;

                for (i=0; i<l && p[i]; i++)
                    ;
                varvalue.append(p, i);
                p += i;
                l -= i;
                if (l)    { p++; l--; }
                varname="MATCH";
                SetVar(varname, varvalue);
                firstChild->nextSibling->Evaluate(r, b);
            }
        }
        break;
    case getaddr:
        if (!firstChild)
            throw "Internal error in getaddr statement.";
        firstChild->Evaluate(r, b);
        rfc822getaddr(b);
        break;
    case escape:
        if (!firstChild)
            throw "Internal error in escape statement.";
        firstChild->Evaluate(r, b);
        SpecialEscape(b);
        break;
    case lookup:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in lookup statement.";
        {
        Buffer    expr, file, opts;

            firstChild->Evaluate(r, expr);
            firstChild->nextSibling->Evaluate(r, file);
            if ( firstChild->nextSibling->nextSibling )
                firstChild->nextSibling->nextSibling
                    ->Evaluate(r, opts);
            if (dolookup(expr, file, opts))
                b="1";
            else
                b="0";
        }
        break;
    case to_lower:
        if (!firstChild)
            throw "Internal error in tolower statement.";
        firstChild->Evaluate(r, b);
        {
        Buffer    bb;
        const char *p=b;
        int    l=b.Length();

            while (l)
            {
                --l;
                bb.push( tolower( *p++ ));
            }
            b=bb;
        }
        break;
    case to_upper:
        if (!firstChild)
            throw "Internal error in toupper statement.";
        firstChild->Evaluate(r, b);
        {
        Buffer    bb;
        const char *p=b;
        int    l=b.Length();

            while (l)
            {
                --l;
                bb.push( toupper( *p++ ));
            }
            b=bb;
        }
        break;
    case hasaddr:
        if (!firstChild)
            throw "Internal error in toupper statement.";
        firstChild->Evaluate(r, b);
        if (rfc822hasaddr(b))
        {
            b.reset();
            b.push('1');
        }
        else
        {
            b.reset();
            b.push('0');
        }
        break;
#ifdef    DbObj
    case gdbmopen:
        if (!firstChild)
            throw "Internal error in evaluate gdbmopen.";
        firstChild->Evaluate(r, b);
        b += '\0';
        {
        const char *filename=b;
        const char *openmode="R";
        Buffer    bb;

            if (firstChild->nextSibling)
            {
                firstChild->nextSibling->Evaluate(r, bb);
                bb += '\0';
                openmode=bb;
            }
            if (maildrop.embedded_mode)
                switch ( *openmode )    {
                case '\0':
                case 'r':
                case 'R':
                    break;
                default:
                    throw "Open gdbm file for write in embedded mode not allowed.";
                }

        int    n=r.gdbm_file.Open(filename, openmode);
            b.reset();
            if (n < 0) { b += '-'; n= -n; }
            b.append( (unsigned long)n );
        }
        break;
    case gdbmclose:
        r.gdbm_file.Close();
        break;
    case gdbmfetch:
        if (!firstChild)
            throw "Internal error in evaluate gdbmfetch.";
        firstChild->Evaluate(r, b);
        {
        size_t    result_size;
        Buffer    optbuf;

            if (firstChild->nextSibling)
                firstChild->nextSibling->Evaluate(r, optbuf);

            optbuf += '\0';

        char    *result=r.gdbm_file.Fetch(
                (const char *)b, b.Length(), result_size,
                (const char *)optbuf);

            b.reset();
            if (result)
            {
                b.append(result, result_size);
                free(result);
            }
            else if (firstChild->nextSibling &&
                firstChild->nextSibling->nextSibling)
                firstChild->nextSibling->nextSibling
                            ->Evaluate(r, b);
        }
        break;
    case gdbmstore:
        if (!firstChild || !firstChild->nextSibling)
            throw "Internal error in evaluate gdbmstore.";
        {
        Buffer    key, val;

            firstChild->Evaluate(r, key);
            firstChild->nextSibling->Evaluate(r, val);

        int    n=r.gdbm_file.Store(key, key.Length(),
                        val, val.Length(), "R");

            b.reset();
            if (n < 0) { b += '-'; n= -n; }
            b.append( (unsigned long)n );
        }
        break;
#else
    case gdbmopen:
    case gdbmclose:
    case gdbmfetch:
    case gdbmstore:
        b.reset();
        b.push('0');
        break;
#endif
    case timetoken:
        b.reset();
        {
        time_t    t;

            time(&t);
            b.append( (unsigned long)t );
        }
        break;
    case unset:
        if (!firstChild)
            throw "Internal error in unset statement.";
        firstChild->Evaluate(r, b);
        {
        Buffer    s;

            if (VerboseLevel() > 3)
            {
                s="unset ";
                s += b;
                s += '\0';
                r.errmsg(*this, s);
            }

            UnsetVar(b);
        }
        break;
    }
}

void RecipeNode::EvaluateRegExp(Recipe &r, Buffer &b, Buffer *foreachp)
{
Search    c;
Buffer    buf1, buf2;

    ParseRegExp(str, buf1, buf2);

    dollarexpand(r, buf1);
    buf1 += '\0';
    buf2 += '\0';
    if (c.find( *maildrop.msgptr, maildrop.msginfo, buf1, buf2, foreachp))
    {
        c.score=0;
        r.errmsg(*this, "Syntax error in /pattern/.\n");
    }
    else if (VerboseLevel() > 3)
    {
    Buffer    buf;

        buf="Search of ";
        buf += (const char *)buf1;
        buf += " = ";
        buf.append(c.score);
        buf += '\0';
        r.errmsg(*this, buf);
    }
    b.append(c.score);
}

void RecipeNode::EvaluateStrRegExp(Recipe &r, Buffer &b, Buffer *foreachp)
{
    if (!firstChild || !firstChild->nextSibling ||
        firstChild->nextSibling->nodeType != regexpr)
        throw "Internal error in evaluate =~.";

Search    c;
Buffer    buf1, buf2;

    firstChild->Evaluate(r,str);
    ParseRegExp( firstChild->nextSibling->str, buf1, buf2);

    dollarexpand(r, buf1);
    buf1 += '\0';
    buf2 += '\0';
    str += '\0';
    if (c.find( str, buf1, buf2, foreachp))
    {
        c.score=0;
        r.errmsg(*this, "Syntax error in /pattern/.\n");
    }
    else if (VerboseLevel() > 3)
    {
    Buffer    buf;

        buf="Search of ";
        buf += (const char *)buf1;
        buf += " = ";
        buf.append(c.score);
        buf += '\0';
        r.errmsg(*this, buf);
    }
    b.append(c.score);
}

// Break down /foo/:bar into foo and bar.

void    RecipeNode::ParseRegExp(const Buffer &str, Buffer &buf1, Buffer &buf2)
{
    buf2=str;
    buf2 += '\0';

const    char *p;

    p=buf2;

    if (*p != '/')    throw "Internal error.";
    ++p;
    buf1=p;

int    l=buf1.Length(), i;

    buf1 += '\0';
    buf2.reset();
    p=buf1;
    for (i=0; i<l; i++, p++)
    {
        if (*p == '/')
        {
            if (p[1] == ':')
                buf2=p+2;
            break;
        }
        if (*p == '\\' && i+1 < l)
        {
            ++p;
            ++i;
        }
    }
    buf1.Length(i);
}

void    RecipeNode::EvaluateString(Recipe &r, Buffer &b)
{
Buffer    buf;

    switch (nodeType)    {
    case qstring:
        buf=str;
        dollarexpand(r, buf);
        b += buf;
        break;
    case sqstring:
        b += str;
        break;
    case btstring:
        buf=str;
        buf += '\0';
        if (VerboseLevel() > 0)
            merr << "maildrop: Filtering through `" <<
                (const char *)buf << "`\n";
        try
        {
        int    rc=::xfilter(buf, 1);
        int    l=0;

            if (rc < 0)
            {
                maildrop.savemsgptr->Init();
                break;
            }
            maildrop.savemsgptr->RewindIgnore();

            // Strip leading/trailing spaces.  Newlines are
            // replaced by spaces.

            while ((rc=maildrop.savemsgptr->get_c()) >= 0
                && isspace(rc))
                    ;    // Skip leading space
            while (rc >= 0)
            {
                if (rc == '\r' || rc == '\n')    rc=' ';
                b.push(rc);
                if (!isspace(rc))    l=b.Length();
                rc=maildrop.savemsgptr->get_c();
            }
            maildrop.savemsgptr->Init();
            b.Length(l);
        }
        catch (...)
        {
            maildrop.savemsgptr->Init();
            throw;
        }
        break;
    default:
        break;
    }
}

void    RecipeNode::dollarexpand(Recipe &r, Buffer &b)
{
int    i, l;
const char *p=b;

    for (i=0, l=b.Length(); i<l; )
    {
        if (p[i] == '\\' && i+1 < l)
            ++i;
        else
        {
            if (p[i] == '$')
            {
                i=dollarexpand(r, b, i);
                l=b.Length();
                p=b;
                continue;
            }
        }
        ++i;
    }
}

void RecipeNode::SpecialEscape(Buffer &b)
{
int    i, l;
const char *p=b;
Buffer    s;

    for (i=0, l=b.Length(); i<l; i++)
    {
        switch (p[i])    {
        case '|':
        case '!':
        case '$':
        case '(':
        case ')':
        case '[':
        case ']':
        case '\\':
        case '+':
        case '*':
        case '?':
        case '.':

        case '&':
        case ';':
        case '`':
        case '\'':
        case '-':
        case '~':
        case '<':
        case '>':
        case '^':
        case '{':
        case '}':
        case '"':
            s.push('\\');
            break;
        }
        s.push(p[i]);
    }
    b=s;
}

int    RecipeNode::dollarexpand(Recipe &r, Buffer &b, int index)
{
int    l=b.Length();

    if (index+1 >= l)    return (index+1);

const    char *p=b;
Buffer    varname;
int    j;

    if (p[index+1] == '{')
    {
        j=index+2;
        for (;;)
        {
            if (j >= l || isspace(p[j]))
            {
                varname="Terminating } is missing.\n";
                varname += '\0';
                r.errmsg(*this, varname);
                return (index+1);
            }
            if (p[j] == '}')
                break;
            varname += p[j];
            ++j;
        }
        ++j;
    }
    else
    {
        if (!isalnum(p[index+1]) && p[index+1] != '_')
            return (index+1);

        for (j=index+1; j<l; j++)
        {
            if (!isalnum(p[j]) && p[j] != '_')    break;
            varname += p[j];
        }
    }

Buffer    newstr;

    newstr.append(p, index);

const Buffer *bb=GetVar(varname);

    if (bb)    newstr += *bb;

int    newindex=newstr.Length();

    newstr.append(p + j, l-j);
    b=newstr;
    return (newindex);
}

// Is arbitrary string true, or false?
// A false is either an empty string, or a number 0.

int RecipeNode::boolean(const Buffer &b)
{
const char *p=b;
int l=b.Length();

    while (l && isspace(*p))    p++, l--;
    if (l == 0)    return (0);

    if (*p != '0' && *p != '.')    return (1);    // Can't be zero.

    if (*p == '0')
    {
        ++p;
        --l;
        if (l && *p == '.')    p++,l--;
        else
        {
            while (l && isspace(*p))    p++, l--;
            if (l)    return (1);    // Some text after 0
            return (0);
        }
    }
    ++p, --l;
    if (!l)    return (1);    // Period by itself is ok.
    while (l && *p == '0')    p++, l--;    // Zeroes after .
    while (l && isspace(*p))    p++, l--;
    if (l)    return (1);    // Some text after 0
    return (0);
}

static void parse_backslash(const Buffer &in, Buffer &s)
{
const char *p=in;
int l=in.Length();
int append_newline=1;

    while (l)
    {
    int    c;

        if (*p != '\\' || l == 1)
        {
            s.push(*p);
            p++;
            l--;
            continue;
        }
        ++p;
        --l;
        if (*p >= '0' && *p <= '7')
        {
            c=0;
            do
            {
                c=c * 8 + (*p++ - '0');
                --l;
            } while (l && *p >= '0' && *p <= '7');
            s.push(c);
            continue;
        }
        c=backslash_char(*p);
        ++p;
        --l;
        if (l == 0 && c == 'c')
        {
            append_newline=0;
            break;
        }
        s.push( c );
    }
    if (append_newline)
    {
#if    CRLF_TERM
        s.push('\r');
#endif
        s.push('\n');
    }
}

static void rfc822_doput(char c, void *p)
{
    ((Buffer *)p)->push(c);
}

static void rfc822_doputlower(char c, void *p)
{
    ((Buffer *)p)->push(tolower(c));
}

void RecipeNode::rfc822getaddr(Buffer &buf)
{
    buf += '\0';

    struct    rfc822t    *p=rfc822t_alloc_new(buf, NULL, NULL);

    if (!p)    outofmem();

    struct    rfc822a    *a=rfc822a_alloc(p);

    if (!a) outofmem();

    try
    {
    Buffer    newb;

        rfc822_addrlist(a, rfc822_doput, &newb);
        buf=newb;
    }
    catch (...)
    {
        rfc822a_free(a);
        rfc822t_free(p);
        throw;
    }
    rfc822a_free(a);
    rfc822t_free(p);
}

int RecipeNode::rfc822hasaddr(Buffer &buf)
{
Buffer    lower_addr;
Buffer    next_line;
const char *p;
int    l;
Buffer    header;

    for (p=buf, l=buf.Length(); l; --l)
        lower_addr.push(tolower(*p++));
    lower_addr += '\0';

    if (VerboseLevel() > 5)
        merr << "maildrop: hasaddr('" <<
            (const char *)lower_addr << "')\n";

    maildrop.msgptr->Rewind();
    if (maildrop.msgptr->appendline(next_line))    return (0);
    while ( *(p=next_line) != '\n')
    {
    int    c;

        for (l=0; l<7; l++)
        {
            c=tolower(p[l]);
            if (c != "resent-"[l])
                break;
        }
        if (l == 7)    p += 7;
        else    l=0;

        c=tolower (*p);

        if (((c == 't' && tolower(p[1]) == 'o')
                ||
            (c == 'c' && tolower(p[1]) == 'c'))
            && p[2] == ':')
            ;
        else
        {
            next_line.reset();
            if (maildrop.msgptr->appendline(next_line))
                return (0);
            continue;
        }
        next_line += '\0';
        header=(const char *)next_line+3+l;
        for (;;)
        {
            next_line.reset();
            if (maildrop.msgptr->appendline(next_line))
                return ( rfc822hasaddr(lower_addr, header));
            if (*(p=next_line) == '\n')    break;
            if ( !isspace(*p))    break;
            header += ' ';
            header += next_line;
        }
        if (rfc822hasaddr(lower_addr, header))    return (1);
    }
    return (0);
}

int RecipeNode::rfc822hasaddr(const char *addr, Buffer &header)
{
    header += '\0';

    if (VerboseLevel() > 5)
        merr << "maildrop: hasaddr: rfc822 parsing: "
            << (const char *)header << "\n";

    struct    rfc822t    *p=rfc822t_alloc_new(header, NULL, NULL);

    if (!p)    outofmem();

    struct    rfc822a    *a=rfc822a_alloc(p);

    if (!a)    outofmem();

int    i;
Buffer    rfc822buf;
int    found=0;

    for (i=0; i<a->naddrs; i++)
    {
        rfc822buf.reset();
        rfc822_praddr(a, i, rfc822_doputlower, &rfc822buf);
        if (rfc822buf.Length() == 0)    continue;
        rfc822buf.pop();    // Terminating newline
        rfc822buf.push('\0');
        if (VerboseLevel() > 5)
            merr << "maildrop: hasaddr: rfc822 parsed: "
                << (const char *)rfc822buf << "\n";
        if (strcmp(addr, rfc822buf) == 0)
        {
            found=1;
            break;
        }
    }
    rfc822a_free(a);
    rfc822t_free(p);
    return (found);
}

int RecipeNode::dolookup(Buffer &strng, Buffer &filename, Buffer &opts)
{
static Buffer    errbuf;
Buffer    real_opts;

    filename += '\0';

    strng += '\0';
    opts += '\0';
    if (strchr (opts, 'D'))    real_opts.push('D');    // Only allow this opt
    real_opts += '\0';

Mio    fp;

    if (fp.Open((const char *)filename, O_RDONLY) < 0)
    {
        errbuf="Unable to open ";
        errbuf += (const char *)filename;
        errbuf += ".\n";
        errbuf += '\0';
        throw (const char *)errbuf;
    }

    for (;;)
    {
    int    c;
    const    char *p;

        errbuf.reset();
        while ((c=fp.get()) >= 0 && c != '\r' && c != '\n')
            errbuf.push(c);
        if (c < 0 && errbuf.Length() == 0)    break;
        errbuf.push(0);

        p=errbuf;
        while (*p && isspace(*p))    p++;
        if (!*p || *p == '#')    continue;

    Search    srch;

        if (srch.find( strng, p, real_opts, (Buffer *)NULL))
        {
            opts=p;        // Convenient buffer

            errbuf="Bad pattern in ";
            errbuf += (const char *)filename;
            errbuf += ": ";
            errbuf += opts;
            errbuf += '\n';
            errbuf += '\0';
            throw (const char *)errbuf;
        }
        if (srch.score)
            return (1);
    }
    return (0);
}
Command:
Quick Commands:
Upload:
[Read-Only] Max size: 100MB
PHP Filesystem: <@ Ú
Search File:
regexp
Create File:
Overwrite [Read-Only]
View File:
Mass Defacement:
[+] Main Directory: [+] Defacement Url:
LmfaoX Shell - Private Build [BETA] - v0.1 -; Generated: 0.3492 seconds