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.39 GB of 70.42 GB (33.22%)
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/ courier-0.66.1/ courier/ - drwxrwxrwx

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

#include    "config.h"
#include    "cgi/cgi.h"
#include    "rfc822/rfc822.h"
#include    "rfc822/rfc2047.h"
#include    "numlib/numlib.h"
#include    "unicode/unicode.h"
#include    "datadir.h"

#include    <stdio.h>
#include    <errno.h>
#include    <stdlib.h>
#if    HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    <string.h>
#include    <signal.h>

#include    <sys/types.h>
#include    <sys/stat.h>
#include        <sys/socket.h>
#include        <sys/un.h>
#if    HAVE_LOCALE_H
#if    HAVE_SETLOCALE
#include    <locale.h>
#endif
#endif

#include    <list>
#include    <vector>
#include    <string>
#include    <algorithm>
#include    <iostream>
#include    <fstream>
#include    <sstream>
#include    <map>

#include    "cmlm.h"
#include    "cmlmcmdmisc.h"
#include    "webmlmd.H"
#include    "webmlmdcmlm.H"
#include    "webmlmddirs.H"
#include    "webmlmdhandlers.H"

#define TEMPLATEDIR DATADIR "/couriermlm"

extern "C" {

    void fake_exit(int rc)
    {
        exit(rc);
    }

    void rfc2045_enomem(const char *errmsg)
    {
        cginocache();
        std::cout << "Content-Type: text/plain" << std::endl
              << std::endl
              << errmsg
              << std::endl << std::flush;
        fake_exit(1);
    }

    void error(const char *errmsg)
    {
        cginocache();
        printf("Content-Type: text/html; charset=utf-8\n\n"
                       "<html><head><title>%s</title></head><body><h1>%s</h1></body></html>\n",
                       errmsg, errmsg);
        fake_exit(1);
    }
}

webmlmd::dirs mlm_dirs;

std::string toutf8str(std::wstring w)
{
    std::vector<unicode_char> u;

    u.reserve(w.size()+1);

    u.insert(u.end(), w.begin(), w.end());

    u.push_back(0);

    return mail::iconvert::convert(u, "utf-8");
}

// First component of PATH_INFO is the mailing list name

std::string webmlmd::list_name()
{
    const char *pi=getenv("PATH_INFO");

    if (!pi)
        return "";

    if (*pi == '/')
        ++pi;

    std::string list_name(pi);

    std::string::iterator b=list_name.begin(),
        p=std::find(b, list_name.end(), '/');

    return std::string(b, p);
}

// The remaining component in PATH_INFO is the list command

static std::string list_cmd()
{
    const char *pi=cgiextrapath();

    if (*pi == '/')
        ++pi;

    std::string list_name(pi);

    std::string::iterator b=list_name.begin(), e=list_name.end(),
        p=std::find(b, e, '/');

    if (p != e)
        ++p;

    return std::string(p, e);
}

static void main2(void *);

static void init_dirs(void *dummy)
{
    const char *dirs=getenv("LISTS");

    if (!mlm_dirs.initialize(dirs ? dirs:""))
    {
        exit(1);
    }
}

int main(int argc, char **argv)
{
    const char *cmd=NULL;
    const char *port_s=getenv("PORT");
    const char *prefork_s=getenv("PREFORK");

    if (argc > 1)
        cmd=argv[1];

#if HAVE_SETLOCALE
    setlocale(LC_ALL, "C");
#endif

    /*
    ** For convenience's sake, we need to start webmlmd by a helper script.
    ** Rather than confusing folks with webmlmd.rc, automatically invoke
    ** the helper script, when needed.
    */

    if (cmd && strcmp(cmd, "check"))
    {
        std::vector<char> shscript_v;

        {
            std::string shscript=argv[0];

            shscript += ".rc";

            shscript_v.reserve(shscript.size()+1);

            shscript_v.insert(shscript_v.end(),
                      shscript.begin(),
                      shscript.end());
            shscript_v.push_back(0);
        }

        std::vector<char *> new_argv;

        new_argv.push_back(&shscript_v[0]);

        new_argv.insert(new_argv.end(), argv, argv+argc);
        new_argv.push_back(0);

        execvp(new_argv[0], &new_argv[0]);
        perror(new_argv[0]);
        exit(1);
    }

    if (!port_s || !*port_s)
    {
        std::cerr << "PORT not set in the configuration file"
              << std::endl;
        exit(1);
    }

    if (argc > 1 && strcmp(argv[1], "check") == 0)
    {
        if (access(port_s, 0) == 0)
        {
            if (access(port_s, W_OK) < 0)
            {
                perror(port_s);
                exit(1);
            }
        }
        else
        {
            int fd=socket(PF_UNIX, SOCK_STREAM, 0);

            if (fd >= 0)
            {
                struct sockaddr_un skun;

                memset(&skun, 0, sizeof(skun));

                if (strlen(port_s) >= sizeof(skun.sun_path))
                {
                    fprintf(stderr, "%s: pathname too long\n",
                        port_s);
                    exit(1);
                }

                skun.sun_family=AF_UNIX;

                strcpy(skun.sun_path, port_s);

                if (bind(fd, (const struct sockaddr *)&skun,
                     sizeof(skun)) ||
                    listen(fd, 5) < 0)
                {
                    close(fd);
                    fd= -1;
                }
            }

            if (fd < 0)
            {
                perror(port_s);
                exit(1);
            }
            close(fd);
        }
    }

    if (cmd)
    {
        init_dirs(NULL);
        exit(0); /* The "check" command */
    }

    cgi_daemon(atoi(prefork_s), port_s, init_dirs, main2, NULL);

    return (0);
}

std::string getoption(std::string listdir,
              std::string option)
{
    std::string n=listdir + "/options";

    std::ifstream i(n.c_str());

    std::string s;

    if (!i.is_open())
        return s;

    while (std::getline(i, s).good())
    {
        std::string::iterator b=s.begin(), e=s.end(),
            p=std::find(b, e, '=');

        if (std::string(b, p) == option)
        {
            if (p != e)
                ++p;

            return std::string(p, e);
        }
    }
    return "";
}

std::string getoption(std::string option)
{
    return getoption(".", option);
}

std::wstring getwoption(std::string dir, std::string option)
{
    std::string s=getoption(dir, option);

    std::vector<unicode_char> u;

    mail::iconvert::convert(s, "utf-8", u);

    std::wstring w(u.begin(), u.end());
    return w;
}

std::wstring getwoption(std::string option)
{
    return getwoption(".", option);
}

std::string getlistname(std::string dir, std::string dirbasename)
{
    std::wstring listname=getwoption(dir, "LISTNAME");

    if (listname.size() == 0)
    {
        listname.insert(listname.end(),
                dirbasename.begin(),
                dirbasename.end());
    }

    return toutf8str(webmlmd::html_escape(listname));
}

std::string getlistname(std::string dirbasename)
{
    return getlistname(".", dirbasename);
}

HANDLER("LISTS", emit_lists)
{
    std::vector<std::string>::iterator b=mlm_dirs.begin(),
        e=mlm_dirs.end();

    std::cout << "<ul>";

    while (b != e)
    {
        std::string n=webmlmd::basename(*b);

        std::cout << "<li><a href=\"" << cgirelscriptptr() << "/"
              << webmlmd::html_escape(n) << "\">"
              << getlistname(*b, n)
              << "</a></li>";
        ++b;
    }
    std::cout << "</ul>";
}

HANDLER("LISTNAME", emit_list_name)
{
    std::cout << getlistname(list_name());
}

HANDLER("LISTDESCR", emit_list_descr)
{
    std::cout << getoption("LISTDESCR");
}

HANDLER("LISTURL", emit_list_url)
{
    std::cout << cgirelscriptptr() << "/" << list_name();
}

HANDLER("REPEATURL", emit_repeat_url)
{
    std::cout << cgirelscriptptr() << cgiextrapath();
}

static void emit_select(const char *name,
            const char *values,
            const std::list<std::string> &options,
            std::string default_option,
            size_t list_size=0,
            bool allow_multiple=false)
{
    std::string options_str;

    std::list<std::string>::const_iterator b=options.begin();

    while (b != options.end())
    {
        options_str += *b++;
        options_str += "\n";
    }

    char *buf=cgi_select(name, values, options_str.c_str(),
                 getoption("POST").c_str(), 0, 0);

    if (buf)
    {
        std::cout << buf;
        free(buf);
    }
}


static void emit_checkbox(const char *name, const char *value,
              const char *opts)
{
    char *buf=cgi_checkbox(name, value, opts);

    if (buf)
    {
        std::cout << buf;
        free(buf);
    }
}

static void emit_textarea(const char *name, std::string value,
              const char *wrap,
              int rows, int cols, const char *opts)
{
    std::vector<unicode_char> u;

    u.reserve(value.size()+1);

    u.insert(u.end(), value.begin(), value.end());
    u.push_back(0);

    char *buf=cgi_textarea(name, rows, cols, &u[0], wrap, opts);

    u.clear();

    if (buf)
    {
        std::cout << buf;
        free(buf);
    }
}

static void emit_input(const char *name, std::wstring value,
               int size, int maxlength,
               const char *opts)
{
    std::vector<unicode_char> unicode_buf;

    unicode_buf.reserve(value.size()+1);

    unicode_buf.insert(unicode_buf.end(), value.begin(), value.end());
    unicode_buf.push_back(0);

    char *buf=cgi_input(name, &unicode_buf[0], size, maxlength, "");
    unicode_buf.clear();

    if (buf)
    {
        std::cout << buf;
        free(buf);
    }
}

HANDLER("ADMINUPDATE", do_admin_update)
{
    if (!*cgi("update"))
        return;

    std::list<std::string> new_cmds;

    static const char * const booleans[]={
        "!simpleconfirm",
        "casesensitive",
        "nobozos",
        "nodsn",
    };

    size_t i;

    for (i=0; i<sizeof(booleans)/sizeof(booleans[0]); i++)
    {
        const char *p=booleans[i];

        const char *yes, *no;

        if (*p =='!')
        {
            ++p;

            yes="0";
            no="1";
        }
        else
        {
            yes="1";
            no="0";
        }

        std::string setting=p;

        std::transform(setting.begin(), setting.end(),
                   setting.begin(), std::ptr_fun(toupper));

        std::string varname("opt");

        varname += p;

        new_cmds.push_back(setting + "=" +
                   (*cgi(varname.c_str()) ? yes:no));
    }

    new_cmds.push_back(*cgi("optsubscribe") ?
               "SUBSCRIBE=mod":"subscribe=all");

    static const char * const plains[]={
        "post",
        "postarchive",
        "reportaddr",
        "digest",
        "listname",
        "keyword"
    };

    for (i=0; i<sizeof(plains)/sizeof(plains[0]); i++)
    {

        std::string setting=plains[i];

        std::transform(setting.begin(), setting.end(),
                   setting.begin(), std::ptr_fun(toupper));

        std::string varname("opt");

        varname += plains[i];

        new_cmds.push_back(setting + "=" + cgi(varname.c_str()));
    }

    static const struct {
        const char *name;
        unsigned minvalue;
        unsigned maxvalue;
    } numerical[]={
        {"startprobe", 3, 30},
        {"maxbounces", 10, 50},
        {"purgebounce", 5, 30},
        {"maxmodnotices", 5, 99},
        {"remoderate", 12, 48},
        {"maxfetchsize", 100, 9999},
        {"purgearchive", 2, 9999},
        {"purgecmd", 6, 720},
    };

    for (i=0; i<sizeof(numerical)/sizeof(numerical[0]); i++)
    {

        std::string setting=numerical[i].name;

        std::transform(setting.begin(), setting.end(),
                   setting.begin(), std::ptr_fun(toupper));

        std::string varname("opt");

        varname += numerical[i].name;

        std::ostringstream o;

        o << setting << "=";

        int nn=atoi(cgi(varname.c_str()));

        if (nn > 0)
        {
            if ((unsigned)nn < numerical[i].minvalue)
                nn=(int)numerical[i].minvalue;
            if ((unsigned)nn > numerical[i].maxvalue)
                nn=(int)numerical[i].maxvalue;

            o << nn;
        }

        new_cmds.push_back(o.str());
    }

    char *p=rfc2047_encode_str(cgi("optname"), "utf-8",
                   rfc2047_qp_allow_word);

    new_cmds.push_back(std::string("NAME=") + (p ? p:""));

    if (p)
        free(p);

    std::vector<std::string> args_array;

    args_array.reserve(new_cmds.size());
    args_array.insert(args_array.end(), new_cmds.begin(),
              new_cmds.end());

    cmdset(args_array, false);

    {
        std::string key=cgi("optheaderadd");

        key += "\n";

        std::istringstream i(key);

        std::ofstream ofs(HEADERADD ".new");

        std::string s;

        while (std::getline(i, s).good())
            if (s.size() > 0)
            {
                ofs << s << "\n";
            }

        ofs.close();
        rename(HEADERADD ".new", HEADERADD);
    }

    {
        std::string key=cgi("optheaderdel");
        key += "\n";

        std::istringstream i(key);

        std::ofstream ofs(HEADERDEL ".new");

        std::string s;

        while (std::getline(i, s).good())
            if (s.size() > 0)
            {
                ofs << s << "\n";
            }

        ofs.close();
        rename(HEADERDEL ".new", HEADERDEL);
    }

}

HANDLER("OPTPOST", emit_optpost_setting)
{
    if (args.size() != 3)
        return;

    emit_select("optpost",
            "all\n"
            "subscribers\n"
            "mod\n", args, getoption("POST"));
}

HANDLER("OPTSUBSCRIBE", emit_optsubscribe)
{
    emit_checkbox("optsubscribe", "X",
              getoption("SUBSCRIBE") == "mod" ? "*":"");
}

HANDLER("OPTSIMPLECONFIRM", emit_simpleconfirm)
{
    emit_checkbox("optsimpleconfirm", "X",
              getoption("SIMPLECONFIRM") != "1" ? "*":"");
}

HANDLER("OPTPURGECMD", emit_purgecmd)
{
    emit_input("optpurgecmd", getwoption("PURGECMD"), 8, 8, "");
}

HANDLER("OPTKEYWORD", emit_keyword)
{
    emit_input("optkeyword", getwoption("KEYWORD"), 32, 255, "");
}

HANDLER("OPTNAME", emit_name)
{
    std::string n=getoption("NAME");

    char *p=rfc822_display_hdrvalue_tobuf("subject",
                          n.c_str(),
                          "utf-8",
                          NULL,
                          NULL);
    if (p)
    {
        std::vector<unicode_char> u;

        mail::iconvert::convert(p, "utf-8", u);

        emit_input("optname", std::wstring(u.begin(), u.end()), 32, 255,
               "");
        free(p);
    }
}

HANDLER("OPTLISTNAME", emit_listname)
{
    emit_input("optlistname", getwoption("LISTNAME"), 32, 255, "");
}

HANDLER("OPTPOSTARCHIVE", emit_postarchive)
{
    if (args.size() != 2)
        return;

    emit_select("optpostarchive",
            "all\n"
            "subscribers\n", args, getoption("POSTARCHIVE"));
}

HANDLER("OPTCASESENSITIVE", emit_casesensitive)
{
    emit_checkbox("optcasesensitive", "X",
              getoption("CASESENSITIVE") == "1" ? "*":"");
}

HANDLER("OPTREPORTADDR", emit_reportaddr)
{
    emit_input("optreportaddr", getwoption("REPORTADDR"), 32, 255, "");
}

HANDLER("OPTNOBOZOS", emit_nobozos)
{
    emit_checkbox("optnobozos", "X",
              getoption("NOBOZOS") != "0" ? "*":"");
}

HANDLER("OPTDIGEST", emit_digest)
{
    emit_input("optdigest", getwoption("DIGEST"), 32, 255, "");
}

HANDLER("OPTMAXFETCHSIZE", emit_maxfetchsize)
{
    emit_input("optmaxfetchsize", getwoption("MAXFETCHSIZE"), 8, 8, "");
}

HANDLER("OPTNODSN", emit_nodsn)
{
    emit_checkbox("optnodsn", "X",
              getoption("NODSN") == "1" ? "*":"");
}

HANDLER("OPTSTARTPROBE", emit_startprobe)
{
    emit_input("optstartprobe", getwoption("STARTPROBE"), 8, 8, "");
}

HANDLER("OPTMAXBOUNCES", emit_maxbounces)
{
    emit_input("optmaxbounces", getwoption("MAXBOUNCES"), 8, 8, "");
}

HANDLER("OPTPURGEBOUNCE", emit_purgebounce)
{
    emit_input("optpurgebounce", getwoption("PURGEBOUNCE"), 8, 8, "");
}

HANDLER("OPTMAXMODNOTICES", emit_maxmodnotices)
{
    emit_input("optmaxmodnotices", getwoption("MAXMODNOTICES"), 8, 8, "");
}

HANDLER("OPTREMODERATE", emit_remoderate)
{
    emit_input("optremoderate", getwoption("REMODERATE"), 8, 8, "");
}

HANDLER("OPTPURGEARCHIVE", emit_purgearchive)
{
    emit_input("optpurgearchive", getwoption("PURGEARCHIVE"), 8, 8, "");
}

HANDLER("OPTHEADERADD", emit_headeradd)
{
    std::ostringstream o;

    std::ifstream ifs(HEADERADD);

    if (ifs.is_open())
    {
        std::string line;

        while (std::getline(ifs, line).good())
            if (line.size())
                o << line << std::endl;
    }

    emit_textarea("optheaderadd", o.str(), "off", 4, 40, "");
}

HANDLER("OPTHEADERDEL", emit_headerdel)
{
    std::ostringstream o;

    std::ifstream ifs(HEADERDEL);

    if (ifs.is_open())
    {
        std::string line;

        while (std::getline(ifs, line).good())
            if (line.size())
                o << line << std::endl;
    }

    emit_textarea("optheaderdel", o.str(), "off", 4, 40, "");
}



static void showform(const char *filename,
             const std::map<std::string, std::string> &parms)
{
    webmlmd::handler_list handlers;

    std::ifstream i(filename);

    if (!i.is_open())
    {
        std::cout << filename << ": cannot open"
              << std::endl;
        return;
    }

    std::string line;

    while (std::getline(i, line).good())
    {
        std::string::iterator b=line.begin(), e=line.end();

        while (b != e)
        {
            static const char mac_open[]="[@";
            static const char mac_close[]="@]";

            std::string::iterator p=
                std::search(b, e, mac_open, mac_open+2);

            std::cout << std::string(b, p);

            b=p;

            if (b == e)
                break;

            b += 2;

            p=std::search(b, e, mac_close, mac_close+2);

            std::list<std::string> args;

            std::replace(b, p, '_', ' ');
            while (b != p)
            {
                std::string::iterator word_start=b;

                b=std::find(b, p, ':');

                args.push_back(std::string(word_start, b));

                if (b != p)
                    ++b;
            }

            if (b != e)
                b += 2;

            std::string handler_name;

            if (!args.empty())
            {
                handler_name=args.front();
                args.pop_front();
            }

            webmlmd::handler_list::iterator
                h=handlers.find(handler_name);

            if (h != handlers.end())
                (*h->second)(args);

            std::map<std::string, std::string>::const_iterator
                vb=parms.find(handler_name);

            if (vb != parms.end())
            {
                std::string txt=vb->second;

                if (vb->first.substr(0, 1) != ".")
                    txt= webmlmd::html_escape(txt);
                std::cout << txt;
            }
        }
        std::cout << std::endl;
    }
}

void webmlmd::showhtmlform(const char *formname,
               std::map<std::string, std::string> &parms)
{
    cginocache();
    std::cout << "Content-Type: text/html; charset=utf-8"
          << std::endl
          << std::endl;

    showform(formname, parms);
}

void webmlmd::showhtmlform(const char *formname)
{
    std::map<std::string, std::string> dummy;

    webmlmd::showhtmlform(formname, dummy);
}

static void showerrorform(const char *formname,
              std::string errmsg)
{
    std::map<std::string, std::string> parms;

    parms["ERRMSG"]=errmsg;

    webmlmd::showhtmlform(formname, parms);
}

static void sendsubunsub(std::string ext)
{
    std::string address(cgi("address"));

    std::string::iterator b=address.begin(),
        e=address.end(),
        p=std::find(b, e, '@');

    if (p == e || std::find(p+1, e, '@') != e ||
        std::find(p, e, '/') != e)
    {
        showerrorform("webmlmerror.tmpl.html",
                  "Invalid E-mail address: " + address);
        return;
    }

    webmlmd::cmlm ctlmsg;

    if (ctlmsg.start(ext, address, "ctlmsg"))
    {
        FILE *stdinptr=ctlmsg.stdinptr();

        ctlmsg.mk_received_header();
        fprintf(stdinptr, "From: %s\n", address.c_str());
        fprintf(stdinptr, "Subject: %s\n", ext.c_str());
        fprintf(stdinptr, "\nSubscription request received.\n");

        if (ctlmsg.wait())
        {
            webmlmd::showhtmlform("webmlmrequestreceived.tmpl.html");
            return;
        }
    }

    showerrorform("webmlmerror.tmpl.html",
              "An error occured processing this request.\n"
              "Please try again later.\n");
}

/*
** /admin request, password is good
*/

static void adminrequest(std::string admin_path)
{
    if (admin_path == "gosublist")
    {
        std::map<std::string, std::string> parms;

        parms["REFRESHURL"]=std::string(cgirelscriptptr())
            + "/" + webmlmd::list_name() + "/admin/sublist";
        webmlmd::showhtmlform("webmlmpleasewait.tmpl.html", parms);
        return;
    }

    if (admin_path == "sublist")
    {
        webmlmd::showhtmlform("webmlmsublist.tmpl.html");
        return;
    }

    if (admin_path == "subinfo")
    {
        webmlmd::showhtmlform("webmlmsubinfo.tmpl.html");
        return;
    }

    if (admin_path == "mod")
    {
        std::string filename;

        std::map<std::string, std::string> parms;

        if (*cgi("domoderate"))
        {
            filename=cgi("msgname");

            if (filename.find('/') != filename.npos)
                filename="";
        }

        if (filename != "" && strcmp(cgi("modaction"), "accept") == 0)
        {
            parms[".ERRMSG"]=webmlmd::do_mod_accept(filename);

            if (parms[".ERRMSG"] != "")
                filename="";
        }
        else if (filename != "" && strcmp(cgi("modaction"), "reject")
             == 0)
        {
            parms[".ERRMSG"]=
                webmlmd::do_mod_reject(filename,
                               *cgi("returntosender")
                               != 0,
                               cgi("rejectmsg"));

            if (parms[".ERRMSG"] != "")
                filename="";
        }

        if (filename != "")
        {
            size_t dummy;

            filename=webmlmd::get_next_mod_filename(filename,
                                dummy);

            if (filename == "")
            {
                std::string url=std::string(cgirelscriptptr())
                    + "/" + webmlmd::list_name()
                    + "/admin";

                cgiredirect(url.c_str());

                fflush(stdout);
                std::cout << "\nRedirect to " << url << "\n";
                return;
            }

            cgi_put("msgname", filename.c_str());
                
        }

        webmlmd::showhtmlform("webmlmlistadminmod.tmpl.html", parms);
        return;
    }

    webmlmd::showhtmlform("webmlmlistadmin.tmpl.html");
}

/*
** Some list request
*/

static void listrequest2(std::string list_name, std::string path_info)
{
    if (path_info == "sendsub")
    {
        sendsubunsub("subscribe");
        return;
    }

    if (path_info == "sendunsub")
    {
        sendsubunsub("unsubscribe");
        return;
    }

    if (path_info == "doconfirm")
    {
        std::string method(cgi("method"));
        std::string token(cgi("token"));

        std::string errmsg="Confirmation failed.  No further information is available.";

        if (std::find_if(method.begin(), method.end(),
                 std::not1(std::ptr_fun(::isalpha))) ==
            method.end() &&
            std::find_if(token.begin(), token.end(),
                 std::not1(std::ptr_fun(::isalpha))) ==
            token.end())
        {
            webmlmd::cmlm confirm;

            if (confirm.start(method + "-" + token, "",
                      "ctlmsg"))
            {
                FILE *stdinptr=confirm.stdinptr();

                confirm.mk_received_header();
                fprintf(stdinptr,
                    "Subject: yes -- confirmed by WebMLM\n"
                    "\n"
                    "Confirmed\n");

                if (confirm.wait())
                {
                    webmlmd::showhtmlform("webmlmprocessed.html");
                    return;
                }

                char buf[1024];
                bool isfirst=true;

                FILE *stdoutptr=confirm.stdoutptr();

                while (fgets(buf, sizeof(buf), stdoutptr))
                {
                    if (isfirst)
                    {
                        isfirst=false;
                        errmsg="";
                    }
                    errmsg += buf;
                }
            }
        }

        std::map<std::string, std::string> args;

        args["ERROR"]=webmlmd::html_escape(errmsg);
        webmlmd::showhtmlform("webmlmnotprocessed.html", args);
        return;
    }


    std::string::iterator b=path_info.begin(), e=path_info.end();

    std::string::iterator p=std::find(b, e, '/');

    std::string w(b, p);

    if (p != e) ++p;

    if (w == "subconfirm" || w == "unsubconfirm")
    {
        std::map<std::string, std::string> args;

        args["METHOD"]=w;
        args["TOKEN"]=std::string(p, e);
        webmlmd::showhtmlform("webmlmconfirm.html", args);
        return;
    }

    if (w == "style.css")
    {
        std::map<std::string, std::string> args;

        std::cout << "Content-Type: text/css"
              << std::endl << std::endl;
        showform("style.css.tmpl", args);
        return;
    }

    if (w == "admin")
    {
        char *password_cookie=cgi_get_cookie("password");
        const char *password;

        if (password_cookie)
        {
            if (getoption("LISTPW") == password_cookie)
            {
                free(password_cookie);
                adminrequest(std::string(p, e));
                return;
            }

            free(password_cookie);
        }

        password=cgi("password");

        if (*password && getoption("LISTPW") == password)
        {
            struct cgi_set_cookie_info cookie_info;

            cgi_set_cookie_info_init(&cookie_info);

            cgi_set_cookie_session(&cookie_info, "password",
                           password);

            std::string cookie_path;

            cookie_path=cgirelscriptptr();

            cookie_path += "/";
            cookie_path += list_name;

            cgi_set_cookie_url(&cookie_info, cookie_path.c_str());

            cgi_set_cookies(&cookie_info, 1);
            cgi_set_cookie_info_free(&cookie_info);
            adminrequest(std::string(p, e));
            return;
        }
        webmlmd::showhtmlform("webmlmlistadminpw.tmpl.html");
        return;
    }

    // Clear the password cookie when returning to the list screen

    {
        struct cgi_set_cookie_info cookie_info;

        cgi_set_cookie_info_init(&cookie_info);

        cgi_set_cookie_expired(&cookie_info, "password");

        std::string cookie_path;

        cookie_path=cgirelscriptptr();

        cookie_path += "/";
        cookie_path += list_name;

        cgi_set_cookie_url(&cookie_info, cookie_path.c_str());

        cgi_set_cookies(&cookie_info, 1);
        cgi_set_cookie_info_free(&cookie_info);
    }

    webmlmd::showhtmlform("webmlmlistindex.tmpl.html");
}

static void listrequest(std::string list_name,
            std::string path_info)
{
    std::vector<std::string>::iterator lb=mlm_dirs.begin(),
        le=mlm_dirs.end();

    while (lb != le)
    {
        std::string d=*lb++;

        if (webmlmd::basename(d) == list_name)
        {
            if (chdir(d.c_str()) < 0)
            {
                cginocache();
                std::cout << "Content-Type: text/plain"
                      << std::endl
                      << std::endl;
                perror(d.c_str());
                return;
            }
            listrequest2(list_name, path_info);
            return;
        }
    }

    cginocache();
    std::cout << "Content-Type: text/plain"
          << std::endl
          << std::endl
          << "List " << list_name << " not found."
          << std::endl;
    return;
}

static void main2(void *dummy)
{
    cgi_setup();

    std::string n=webmlmd::list_name();

    if (n.size() == 0)
    {
        webmlmd::showhtmlform(TEMPLATEDIR "/webmlmidx.html");
    }
    else
    {
        listrequest(n, list_cmd());
    }

    std::cout.flush();
}
Command:
Quick Commands:
Upload:
[OK] Max size: 100MB
PHP Filesystem: <@ Ú
Search File:
regexp
Create File:
Overwrite [OK]
View File:
Mass Defacement:
[+] Main Directory: [+] Defacement Url:
LmfaoX Shell - Private Build [BETA] - v0.1 -; Generated: 0.2673 seconds