From 5df79c53745fde5d6c3340a2979b1429cd5892c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 8 Oct 2011 20:30:28 +0200 Subject: Initial import of htcd system 1.0 Signed-off-by: Henrik Rydberg --- src/sh/convert.cc | 376 +++++++++++++++++++++++++++++++++++++++++++++ src/sh/dates.cc | 138 +++++++++++++++++ src/sh/file.cc | 367 ++++++++++++++++++++++++++++++++++++++++++++ src/sh/htc.cc | 92 +++++++++++ src/sh/htc.h | 77 ++++++++++ src/sh/main.cc | 129 ++++++++++++++++ src/sh/net.cc | 122 +++++++++++++++ src/sh/string.cc | 32 ++++ src/sh/sys.cc | 152 +++++++++++++++++++ src/sh/tree.cc | 304 +++++++++++++++++++++++++++++++++++++ src/sh/user.cc | 445 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/sh/user.h | 92 +++++++++++ 12 files changed, 2326 insertions(+) create mode 100644 src/sh/convert.cc create mode 100644 src/sh/dates.cc create mode 100644 src/sh/file.cc create mode 100644 src/sh/htc.cc create mode 100644 src/sh/htc.h create mode 100644 src/sh/main.cc create mode 100644 src/sh/net.cc create mode 100644 src/sh/string.cc create mode 100644 src/sh/sys.cc create mode 100644 src/sh/tree.cc create mode 100644 src/sh/user.cc create mode 100644 src/sh/user.h (limited to 'src/sh') diff --git a/src/sh/convert.cc b/src/sh/convert.cc new file mode 100644 index 0000000..8828c34 --- /dev/null +++ b/src/sh/convert.cc @@ -0,0 +1,376 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static const charset htcmask("{}\\%&*$;"); +static const charset htmlmask("<&>\""); + +static void Mask(mstream& out,const charset& mask,const sref& msg) +{ + sref q,p=msg; + while(p.nempty()) { + p=p.adv(q=p.left_first_of(mask)); + out<num) { out.put('\n'); col=0; } + else out.put(body[i]); + } +} + +TOK_IMPL(htmlize) { + sref first,rest=env[0]; + while(Splitln(first,rest)) { + Mask(out,htmlmask,first); + out<<"
\n"; + } +} + +TOK_IMPL(lf2crlf) { + LF2CRLF(out,env[0]); +} +TOK_IMPL(crlf2lf) { + CRLF2LF(out,env[0]); +} + +////////////////////////////////////////////////////////// + +TOK_IMPL(twocolumn) { + int num=atoi(env[0]); + int page=atoi(env[1]); + sref head=env[2],mid=env[3],foot=env[4],body=env[5]; + int row=0,col=0,pg=1; + out<=num) { + row=0; + col++; + if(col>=2) { col=0; pg++; } + else if(pg==page) { out<data); + decode64(sw,buffer); + } + else decode64(out,buffer); +} + +////////////////////////////////////////////////////////// + +TOK_IMPL(strip) { + sref s=env[0],a=env[1]; + for(int i=0;i=0) s.replace(p,a.size(),b); } + out<0) out.put(' '); +} +TOK_IMPL(right) { + int pad=atoi(env[1])-env[0].size(); + while(pad-->0) out.put(' '); out<0) { + p=e.adv(s); + if(n==env.req->lang) out<..\n" + "%\n" + "%Encodes a sequence of variables in\n" + "%x-www-form-urlencoded format (RFC HTTP)\n" + ); + + /////////////////////////////////////////////// + + TOK_ADD(strip,"xx",tok_t::PUBLIC, + "%Strip text from special characters\n" + "%Syntax: \\stip{text}{chars}\n" + ); + TOK_ADD(replace,"xxx",tok_t::PUBLIC, + "%Replace text\n" + "%Syntax: \\replace{text}{string}{subst}\n" + "%\n" + "%Replaces each occurence of string in text with subst.\n" + ); + + /////////////////////////////////////////////// + + TOK_ADD(left,"xx",tok_t::PUBLIC, + "%Left-adjust text\n" + "%Syntax: \\left{text}{n}\n" + "%\n" + "%Outputs n characters, padding with spaces to the right.\n" + "%\n" + "%Writes out the full text if longer than n.\n" + ); + TOK_ADD(right,"xx",tok_t::PUBLIC, + "%Right-adjust text\n" + "%Syntax: \\right{text}{n}\n" + "%\n" + "%Outputs n characters, padding with spaces to the left.\n" + "%\n" + "%Writes out the full text if longer than n.\n" + ); + + /////////////////////////////////////////////// + + TOK_ADD(sub,"xxx",tok_t::PUBLIC, + "%Substring\n" + "%Syntax: \\sub{string}{pos}{n}\n" + "%\n" + "%Gets a substring of n characters, beginning at pos, from string.\n" + "%\n" + "%Negative pos values wraps to end.\n" + "%Negative n values wraps to 1+size.\n" + ); + + /////////////////////////////////////////////// + + TOK_ADD(file2mime,"x",tok_t::PUBLIC, + "%Get MIME type\n" + "%Syntax: \\file2mime{path}\n" + "%\n" + "%Looks up the MIME type mapped to the extension of path.\n" + "%\n" + "%Defaults to application/octet-stream if not found.\n" + ); + + /////////////////////////////////////////////// + + TOK_ADD(minilang,"x",tok_t::PUBLIC, + "%Parse lang only\n" + "%Syntax: \\minilang{body}\n" + "%\n" + "%This function is used to enable lang in html files,\n" + "%which otherwise are not parsed.\n" + ); +} diff --git a/src/sh/dates.cc b/src/sh/dates.cc new file mode 100644 index 0000000..a37103b --- /dev/null +++ b/src/sh/dates.cc @@ -0,0 +1,138 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +const int ENDTIME=INT_MAX-4*SEC_PER_DAY; + +TOK_IMPL(endtime) { out<lang,atoi(env[0])); } +TOK_IMPL(month) { out<lang,atoi(env[0])); } +TOK_IMPL(sweek) { out<lang,atoi(env[0])); } +TOK_IMPL(smonth) { out<lang,atoi(env[0])); } + +//////////////////////////////////////////////////////////// + +TOK_IMPL(time2http) { out<lang,atoi(env[0])); } +TOK_IMPL(htc2time) { out<lang,env[0]); } +TOK_IMPL(cvttime) { out< +#include +#include +#include +#include + +const mstring sdot=".",sdots=".."; + +/////////////////////////////////////////////////////////////////// + +inline void stat(struct stat& fs,Env& env,const sref& path) throw(merror_t) { + if(::stat(DocPath(env,path).c_str(),&fs)<0) + THROW("htc: could not stat "<=0) file=file.past(pos,1); + pos=file.rfind('\\'); if(pos>=0) file=file.past(pos,1); + while((pos=file.find(sdots))>=0) file.erase(pos,2); + mstring acc; + for(int i=0;iuri=env[0]; +} + +TOK_IMPL(uri) { + out<uri; +} + +TOK_IMPL(pwd) { + out<uri.left_last('/'); +} + +TOK_IMPL(npwd) { + mstring s=Req(env)->uri.left_last('/'); + for(int i=0;ihtc()->docroot.nempty()) + THROW("htc: home only works in absolute file mode"); + out<data,path); + else { mstring buffer; LoadBuffer(buffer,path); out<db.Open(path,atoi(env.parg(-1))); +} + +TOK_IMPL(save) { + mstring path=DocPath(env,env[0]),var=env[1]; + int prot=atoi(env.parg(2)); if(!prot) prot=0600; + tok_t* p=env.toks->get(var); + if(!p) THROW("htc: "<is_reference()) SaveBuffer(((reference_t*)p)->data,path,prot); + else if(p->is_dbref()) ((dbref_t*)p)->db.Saveas(path,prot); + else SaveBuffer(p->body,path,prot); +} + +TOK_IMPL(dbmod) { + dbref_t* p=(dbref_t*)env.toks->get(env[0]); + if(!p&&!p->is_dbref()) THROW("htc: "<db.Lastmod(); +} + +/////////////////////////////////////////////////////////////////// + +static void Run(mstream& out,Env& env,const mstring& path) throw(merror_t) { + mstring buffer; + LoadBuffer(buffer,path); + env.parse(out,buffer); +} + +TOK_IMPL(include) { + mstring cwd=env.URI(env[0]),path=DocPath(env,cwd); + if(!env.glob_find(cwd)) { + env.toks->add(new tok_t(cwd,ms_empty,tok_t::CONSTANT|tok_t::PRIVATE),0,1); + mstream m; + Env e(env,env.mod,cwd); + Run(m,e,path); + } +} + +TOK_IMPL(parse) { + mstring cwd=env.URI(env[0]),path=DocPath(env,cwd); + Env e(env,env.mod,cwd); + Run(out,e,path); +} + +TOK_IMPL(parse_private) { + mstring cwd=env.URI(env[0]),path=DocPath(env,cwd); + Env e(env,XPRIVATE,cwd); + Run(out,e,path); +} + +TOK_IMPL(parse_public) { + mstring cwd=env.URI(env[0]),path=DocPath(env,cwd); + Env e(env,XPUBLIC,cwd); + Run(out,e,path); +} + +/////////////////////////////////////////////////////////////////// + +TOK_IMPL(dirent) { + mstring uri=env.URI(env[0]); + sref uribase=uri.leftand_last('/'),ext=uri.adv(uribase); + mstring dirpath=DocPath(env,uribase); + DIR* dir=opendir(dirpath.c_str()); + if(dir) { + dirent* p; + while((p=readdir(dir))!=0) { + sref name(p->d_name); + if(name.empty()||name==sdot||name==sdots) continue; + if(ext.empty()||name.right(-ext.size()-1)==ext) out<=0) out<{uri}\n" + ); + TOK_ADD(open,"xx?",tok_t::SYSONLY, + "%Open database to variable\n" + "%Syntax: \\load{varname}{uri}\n" + "%\n" + "%If update is true, the database is opened for reading\n" + "%and writing. NOTE that all updates are syncronous and\n" + "%instantly - saves or locks are not needed.\n" + ); + TOK_ADD(save,"xx?",tok_t::SYSONLY, + "%Save variable to file\n" + "%Syntax: \\save{uri}{varname}\n" + "%\n" + "%If the variable points to a reference object, the\n" + "%reference is saved. If it points to a database,\n" + "%the database is saved. For globals and functions,\n" + "%the body is saved.\n" + "%\n" + "%The optional prot argument is a (base 10) integer\n" + "%defining the creation mode mask (unix).\n" + ); + TOK_ADD(dbmod,"x",tok_t::PUBLIC, + "%Get modification time of open database\n" + "%Syntax: \\dbmod{var}\n" + ); + + //////////////////////////////////////////////////////// + + TOK_ADD(include,"x",tok_t::PRIVATE, + "%Include file in current running mode\n" + "%Syntax: \\include{uri}\n" + "%\n" + "%The file is loaded and evaluated, but produces no output\n" + "%Any uri can only be included once, so it is safe to use\n" + "%include as a precondition.\n" + "%\n" + "%NOTE that files parsed this way must be known to\n" + "%the super-user in order not to create a security hole -\n" + "%especially since this command is open in private mode also.\n" + ); + + TOK_ADD(parse,"x",tok_t::SYSONLY, + "%Parse file in current running mode\n" + "%Syntax: \\parse{uri}\n" + "%\n" + "%The file is loaded and evaluated to output.\n" + "%\n" + "%NOTE that files parsed this way must be known to\n" + "%the super-user in order not to create a security hole.\n" + ); + + TOK_ADD(parse_private,"x",tok_t::PRIVATE, + "%Parse file in private mode\n" + "%Syntax: \\parse.private{uri}\n" + "%\n" + "%The file is loaded and evaluated to output.\n" + "%\n" + "%System-mode commands are silently ignored.\n" + ); + + TOK_ADD(parse_public,"x",tok_t::PRIVATE, + "%Parse file in public mode\n" + "%Syntax: \\parse.public{uri}\n" + "%\n" + "%The file is loaded and evaluated to output.\n" + "%\n" + "%System/Private mode commands are silently ignored.\n" + ); + + //////////////////////////////////////////////////////// + + TOK_ADD(dirent,"x",tok_t::SYSONLY, + "%Collect directory entries\n" + "%Syntax: \\dirent{uri/match}\n" + "%\n" + "%An argument of anydir/ collects all files in anydir.\n" + "%An argument of anydir/.ext collects all files ending with .ext\n" + "%\n" + "%Note that an argument of anydir collects files in the parent\n" + "%directory of anydir which end whith anydir, which probably is\n" + "%not what you want. Trailing slashes are important.\n" + ); + TOK_ADD(dirmod,"x",tok_t::SYSONLY, + "%Return file mode of uri\n" + "%Syntax: \\dirmod{uri}\n" + "%\n" + "%dirmod uses the unix stat function.\n" + "%On failure to read, returns zero.\n" + ); + TOK_ADD(dirmtime,"x",tok_t::SYSONLY, + "%Return modification time of uri\n" + "%Syntax: \\dirmtime{uri}\n" + ); + TOK_ADD(diruid,"x",tok_t::SYSONLY, + "%Return UNIX uid of uri\n" + "%Syntax: \\diruid{uri}\n" + "%\n" + "%Note that the UNIX uid is different from the HTC one.\n" + ); + TOK_ADD(dirgid,"x",tok_t::SYSONLY, + "%Return UNIX gid of uri\n" + "%Syntax: \\dirgid{uri}\n" + "%\n" + "%Note that the UNIX gid is different from the HTC one.\n" + ); + TOK_ADD(filesize,"x",tok_t::SYSONLY, + "%Return filesize of uri\n" + "%Syntax: \\filesize{uri}\n" + ); + TOK_ADD(setperm,"xx",tok_t::SYSONLY, + "%Set file permissions of uri\n" + "%Syntax: \\setperm{uri}{mode}\n" + "%\n" + "%Mode is an integer bitmask compliant with fcntl.\n" + ); + +} diff --git a/src/sh/htc.cc b/src/sh/htc.cc new file mode 100644 index 0000000..9a87f2c --- /dev/null +++ b/src/sh/htc.cc @@ -0,0 +1,92 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +const mstring RCPATH=htchome()+sref("/htc/htc.rc"); +const mstring left="{",right="}"; +static fp_stream mout(stdout),merr(stderr); + +static int unbalanced(const sref& in) +{ + static const charset tag("{[("); + if(in.empty()) return 1; + sref s=in.right_first_of(tag); + while(s.nempty()) { + int p=-1; + switch(*s) { + case '{': p=s.skip(cset_braces); break; + case '[': p=s.skip(cset_indices); break; + case '(': p=s.skip(cset_para); break; + } + if(p<0) return 1; + s=s.adv(p).right_first_of(tag); + } + return 0; +} + +main(int argc,char* argv[]) try +{ + NODELOCK(USERMAP); + HTC htc(ms_empty); + htc_user user(htc.toks); + htc_req req(htc,user.toks); req.uri=Cwd(); + Env env(htc.ops,req,XSYSTEM); + if(argc>1) { + for(int i=2;i=0) { + Env e(env,user.toks,RCPATH); + mstream m; + e.parse(m,buffer); + } + while(!feof(stdin)) { + merr<<"htc>"; + buffer.clear(); + while(!feof(stdin)&&unbalanced(buffer)) { + getline(line,stdin); + buffer.append(line); + buffer+='\n'; + } + try { + env.parse(mout,buffer); + mout<<"\n"; + } + catch(const merror_t& e) { + merr< +#include +#include + +/////////////////////////////////////////////////// + +mstring Cwd(); + +const mstring USERMAP=htchome()+sref("/htc/users.hdb"); + +/////////////////////////////////////////////////// + +struct HTC : public Lang { + fp_stream syslog; + mstring docroot,username; + mstring host,domain,mailer; + IPnode node; + int port; + + HTC(const sref& root); + ~HTC(); + + void setHost(const sref& s); + void setDomain(const sref& s); + void setPort(int p); + void setMailer(const sref& s); +}; + +/////////////////////////////////////////////////// + +struct htc_user { + tokmap toks; + + htc_user(tokmap& p); +}; + +/////////////////////////////////////////////////// + +struct htc_req : public req_env { + mstring group; + user_t user; + + HTC* htc() { return (HTC*)glob; } + + htc_req(HTC& g,tokmap& p); +}; + +inline htc_req* Req(Env& env) { return (htc_req*)env.req; } +inline const sref& DocRoot(Env& env) { return Req(env)->htc()->docroot; } +inline mstring DocPath(Env& env,const sref& uri) { return DocRoot(env)+env.URI(uri); } + +/////////////////////////////////////////////////// + +#endif + diff --git a/src/sh/main.cc b/src/sh/main.cc new file mode 100644 index 0000000..4926b77 --- /dev/null +++ b/src/sh/main.cc @@ -0,0 +1,129 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +const mstring PREFSMAP=htchome()+sref("/htc/prefs.hdb"); +const mstring SYSLOG=htchome()+sref("/log/htc.log"); + +static fp_stream mout(stdout),merr(stderr); + +/////////////////////////////////////////////////// + +mstring Cwd() { + static char buf[1024]; + mstring cwd=getcwd(buf,1024); + cwd+='/'; + return cwd; +} + +/////////////////////////////////////////////////// + +static void OpenUSERS(dbmap& db) +{ + db.Open(USERMAP,1); + if(db.Tables()==0) for(int i=0;idb); + OpenPREFS(DBRef(toks,PREFS_tag,ms_empty,tok_t::SYSONLY)->db); +} + +/////////////////////////////////////////////////// + +htc_req::htc_req(HTC& g,tokmap& p) : req_env(g,p) +{ + user.reset(); +} + +/////////////////////////////////////////////////// + +void envAddFile(tokmap& map); +void envAddConvert(tokmap& map); +void envAddDates(tokmap& map); +void envAddUser(tokmap& map) throw(merror_t); +void envAddTree(tokmap& map); +void envAddSys(tokmap& map); +void envAddNet(tokmap& map); + +/////////////////////////////////////////////////// + +HTC::HTC(const sref& root): + syslog(fopen(SYSLOG.c_str(),"a+")) +{ + docroot=root; if(docroot.back()=='/') docroot=docroot.popb(); + username=getpwuid(getuid())->pw_name; + + envAddFile(toks); + envAddConvert(toks); + envAddDates(toks); + envAddUser(toks); + envAddTree(toks); + envAddSys(toks); + envAddNet(toks); +} + +/////////////////////////////////////////////////// + +HTC::~HTC() +{ + fclose(syslog.fp); +} + +/////////////////////////////////////////////////// + +void HTC::setHost(const sref& s) +{ + host=s; + if(!Lookup(node,host)) THROW("sys: host "< + +///////////////////////////////////////////////////////////////// + +TOK_IMPL(sethost) +{ + Req(env)->htc()->setHost(env[0]); +} +TOK_IMPL(setdomain) +{ + Req(env)->htc()->setDomain(env[0]); +} +TOK_IMPL(setport) +{ + Req(env)->htc()->setPort(atoi(env[0])); +} +TOK_IMPL(setmailer) +{ + Req(env)->htc()->setMailer(env[0]); +} + +///////////////////////////////////////////////////////////////// + +TOK_IMPL(HOST) { + out<htc()->host; +} + +TOK_IMPL(HOSTIP) { + out<htc()->node.ip; +} + +TOK_IMPL(DOMAIN) { + out<htc()->domain; +} + +TOK_IMPL(ROOT) { + out<htc()->username; + if(Req(env)->htc()->domain.size()) out<<"@"<htc()->domain; +} + +TOK_IMPL(ADMIN) { + out<htc()->username; + if(Req(env)->htc()->domain.size()) out<<"@"<htc()->domain; +} + +TOK_IMPL(port) +{ + out<htc()->port; +} + +///////////////////////////////////////////////////////////// + +void envAddNet(tokmap& T) +{ + TOK_ADD(sethost,"x",tok_t::SYSONLY, + "%Set host name\n" + "%Syntax: \\sethost{host}\n" + ); + TOK_ADD(setdomain,"x",tok_t::SYSONLY, + "%Set default domain\n" + "%Syntax: \\setdomain{domain}\n" + ); + TOK_ADD(setport,"x",tok_t::SYSONLY, + "%Set host port number\n" + "%Syntax: \\setport{port}\n" + ); + TOK_ADD(setmailer,"x",tok_t::SYSONLY, + "%Set mail program path\n" + "%Syntax: \\setmailer{path}\n" + ); + + ///////////////////////////////////////////////////////////// + + TOK_ADD(HOST,"",tok_t::PUBLIC, + "%Host name\n" + "%Syntax: \\HOST\n" + ); + + TOK_ADD(HOSTIP,"",tok_t::PUBLIC, + "%Host IP address\n" + "%Syntax: \\HOSTIP\n" + ); + + TOK_ADD(DOMAIN,"",tok_t::PUBLIC, + "%Default domain\n" + "%Syntax: \\DOMAIN\n" + ); + + TOK_ADD(ROOT,"",tok_t::PUBLIC, + "%htcroot email address\n" + "%Syntax: \\ROOT\n" + ); + + TOK_ADD(ADMIN,"",tok_t::PUBLIC, + "%admin email address\n" + "%Syntax: \\ADMIN\n" + ); + + TOK_ADD(port,"",tok_t::PUBLIC, + "%Host port number\n" + "%Syntax: \\port\n" + ); +} diff --git a/src/sh/string.cc b/src/sh/string.cc new file mode 100644 index 0000000..8075a5b --- /dev/null +++ b/src/sh/string.cc @@ -0,0 +1,32 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +static mstring empty; + +TOK_IMPL(tolower) {mstring s=env[0];s.tolower();out< +#include +#include +#include +#include +#include + +//////////////////////////////////////////// + +TOK_IMPL(sleep) { sleep(atoi(env[0])); } +TOK_IMPL(throw) { THROW(env[0]); } + +//////////////////////////////////////////// + +TOK_IMPL(sync) { dbmap::Sync(); } + +//////////////////////////////////////////// + +TOK_IMPL(gethost) { + IPnode node; if(Lookup(node,env[0])) out<\n"; + + //if(env[1].nempty()) ms<<"Reply-To: "<htc(); + if(htc->mailer.size()) { + issue_t cmd(htc->mailer+sref(" ")+env[2]); + mstream m; + cmd.run(m,ms.str()); + htc->syslog<<"["<syslog<<"["<syslog<<"-----------------------------------------\n"; + htc->syslog<syslog<<"=========================================\n"; + } + htc->syslog.flush(); +} + +//////////////////////////////////////////// + +TOK_IMPL(issue) { + HTC* htc=Req(env)->htc(); + htc->syslog<<"["<syslog.flush(); + issue_t cmd(DocPath(env,env[0])); + cmd.run(out,env[1]); + htc->syslog<<"["<syslog.flush(); +} + +////////////////////////////////////////////////////////// + +void envAddSys(tokmap& T) +{ + TOK_ADD(sleep,"x",tok_t::SYSONLY, + "%Sleep for seconds\n" + "%Syntax: \\sleep{t}\n" + "%\n" + "%This one works just like the UNIX command\n" + ); + TOK_ADD(throw,"x",tok_t::SYSONLY, + "%Throw an exception\n" + "%Syntax: \\throw{text}\n" + "%\n" + "%Throw a, for the HTC system, standard error\n" + "%expection, which also many of the built-in\n" + "%do. Enables well-behaved error handling.\n" + ); + + ///////////////////////////////////////////////////////////// + + TOK_ADD(sync,"",tok_t::SYSONLY, + "%Syncronize all open writable databases\n" + "%Syntax: \\sync\n" + "%\n" + "%Use in crontab only.\n" + ); + + ///////////////////////////////////////////////////////////// + + TOK_ADD(gethost,"x",tok_t::SYSONLY, + "%Lookup hostname on nameserver\n" + "%Syntax: \\gethost{IP address}\n" + "%\n" + "%Normally performed automatically by the server.\n" + ); + + ///////////////////////////////////////////////////////////// + + TOK_ADD(mail,"xxxxxxxx",tok_t::SYSONLY, + "%System mail\n" + "%Syntax: \\mail{from}{replyto}{to}{fromname}{date}{subject}{mime}{body}\n" + "%\n" + "%This mail command can do almost anything, so be careful!\n" + "%Usually there are several htc commands simplifying the use\n" + "%of this one.\n" + ); + + ///////////////////////////////////////////////////////////// + + TOK_ADD(issue,"xx",tok_t::SYSONLY, + "%Issue piped command\n" + "%Syntax: \\issue{uri}{stdin}\n" + "%\n" + "%Pipes stdin to cmd and output stdout.\n" + "%An extremely powerful command that may be used\n" + "%to run external programs via the web.\n" + "%\n" + "%Note that the normal uri handling is performed.\n" + ); + + ///////////////////////////////////////////////////////////// +} diff --git a/src/sh/tree.cc b/src/sh/tree.cc new file mode 100644 index 0000000..0ec8f16 --- /dev/null +++ b/src/sh/tree.cc @@ -0,0 +1,304 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +const mstring index_tag="index.htc"; +const mstring sindex_tag="/index.htc"; +const mstring htc_mime="text/x-htc"; +const mstring htx_mime="text/x-htx"; +const mstring html_mime="text/html"; + +const mstring uri_tag="stat.URI"; +const mstring refer_tag="stat.REFER"; +const mstring parent_tag="stat.PARENT"; +const mstring mime_tag="stat.MIME"; + +const mstring mod_tag="stat.MOD"; +const mstring mtime_tag="stat.LASTMOD"; +const mstring uid_tag="stat.UID"; +const mstring gid_tag="stat.GID"; +const mstring size_tag="stat.SIZE"; + +const mstring alias_tag="stat.ALIAS"; +const mstring banner_tag="stat.BANNER"; + +const mstring xclear_tag="stat.X.CLEAR"; +const mstring xcookie_tag="stat.X.COOKIE"; +const mstring domain_tag="stat.X.DOMAIN"; +const mstring user_tag="stat.X.USER"; +const mstring xcache_tag="stat.X.CACHE"; + +const mstring xmod_tag="stat.XMOD"; + +///////////////////////////////////////////////////////////////// + +TOK_IMPL(alias) { + mstring acc; + Env nenv(env,XSYSTEM,env.pwd); + acc=env.arg(0)->expr; + nenv.sloc(alias_tag,acc); +} + +TOK_IMPL(banner) { + mstring acc1; + Env nenv(env,XSYSTEM,env.pwd); + swrite sw(acc1); + nenv.parse(sw,env.arg(0)); + acc1+=' '; acc1+=env.arg(1)->expr; + nenv.sloc(banner_tag,acc1); +} + +///////////////////////////////////////////////////////////////// + +TOK_IMPL(clearance) { + mstring acc; + Env nenv(env,XSYSTEM,env.pwd); + swrite sw(acc); + nenv.parse(sw,env.arg(0)); + sref first,rest=acc; + while(Split(first,rest)) + if(first==root_tag) THROW("user: ROOT group not allowed in clearance"); + nenv.sloc(xclear_tag,acc); +} + +TOK_IMPL(clearance_cookie) { + mstring acc1,acc2; + Env nenv(env,XSYSTEM,env.pwd); + swrite sw1(acc1); + nenv.parse(sw1,env.arg(0)); + swrite sw2(acc2); + nenv.parse(sw2,env.arg(1)); + acc1+=' '; acc1+=acc2; + nenv.sloc(xcookie_tag,acc1); +} + +TOK_IMPL(clearance_domain) { + mstring acc; + Env nenv(env,XSYSTEM,env.pwd); + swrite sw(acc); + nenv.parse(sw,env.arg(0)); + nenv.sloc(domain_tag,acc); +} + +TOK_IMPL(clearance_user) { + mstring acc; + Env nenv(env,XSYSTEM,env.pwd); + swrite sw(acc); + nenv.parse(sw,env.arg(0)); + nenv.sloc(user_tag,acc); +} + +TOK_IMPL(cache) { + mstring acc; + Env nenv(env,XSYSTEM,env.pwd); + swrite sw(acc); + nenv.parse(sw,env.arg(0)); + nenv.sloc(xcache_tag,acc); +} + +///////////////////////////////////////////////////////////////// + +inline int reachable(const sref& uri) +{ + static const mstring sys_tag="/sys/"; + static const mstring bin_tag="/bin/"; + static const mstring htc_tag="/htc/"; + static const mstring sccs_tag="/SCCS/"; + static const mstring cvs_tag="/CVS/"; + if(uri.right_last(sindex_tag)==sindex_tag) return 0; + if(uri.find(sys_tag)>=0) return 0; + if(uri.find(bin_tag)>=0) return 0; + if(uri.find(htc_tag)>=0) return 0; + if(uri.find(sccs_tag)>=0) return 0; + if(uri.find(cvs_tag)>=0) return 0; + return 1; +} + +TOK_IMPL(staturi) { + struct stat fs; int ok=0; + mstring parent,refer,uri=env.URI(env[0]); + if(reachable(uri)) { + refer=uri; parent=refer.leftand_last('/'); + if(refer.back()=='/') { refer+=index_tag; parent=parent.popb().leftand_last('/'); } + int s=stat(DocPath(env,refer).c_str(),&fs); + if(s>=0) { + if(fs.st_mode&24576) { + uri+='/'; refer=uri+index_tag; + s=stat(DocPath(env,refer).c_str(),&fs); + } + if(s>=0) { + const sref* pmime=file2mime(refer); + mstring mime=pmime?*pmime:http_mime_default; + mstring index=refer.leftand_last('/')+index_tag; + + Env nenv(env); + nenv.aloc(uri_tag,uri); + nenv.aloc(refer_tag,refer); + nenv.aloc(parent_tag,parent); + nenv.aloc(mime_tag,mime); + + nenv.aloc(mod_tag,itoa(fs.st_mode)); + nenv.aloc(uid_tag,itoa(fs.st_uid)); + nenv.aloc(gid_tag,itoa(fs.st_gid)); + nenv.aloc(size_tag,itoa(fs.st_size)); + nenv.aloc(mtime_tag,itoa(fs.st_mtime)); + + nenv.aloc(alias_tag,ms_empty); + nenv.aloc(banner_tag,ms_empty); + + nenv.aloc(xclear_tag,root_tag); + nenv.aloc(xcookie_tag,ms_empty); + nenv.aloc(domain_tag,ms_empty); + nenv.aloc(user_tag,ms_empty); + nenv.aloc(xcache_tag,ms_empty); + + nenv.aloc(xmod_tag,itoa(time(0))); + + mstring buffer; + if(mime==htc_mime||mime==htx_mime||mime==html_mime) { + LoadBuffer(buffer,DocPath(nenv,refer)); + try { + Env e(nenv,XINIT,refer); + mstream m; + e.parse(m,buffer); + } + catch(const merror_t& e) { + THROW(refer<<": "<=0) { + try { + Env e(nenv,XINIT,index); + mstream m; + e.parse(m,buffer); + nenv.sloc(alias_tag,ms_empty); + nenv.sloc(banner_tag,ms_empty); + } + catch(const merror_t& e) { + THROW(index<<": "<\n" + "%\n" + "%Do body if a reference to uri is found.\n" + "%In the body environment, the record stat. is set\n" + "%with the following variables:\n" + "%\n" + "%URI the canonized URI\n" + "%REFER the file uri it refers to\n" + "%PARENT the parent uri\n" + "%MOD the file mode bits (unix)\n" + "%UID the file uid (unix)\n" + "%GID the file gid (unix)\n" + "%SIZE the file size (unix)\n" + "%LASTMOD the file modification time (unix)\n" + "%MIME the MIME type\n" + "%ALIAS alias used in tree\n" + "%X.CLEAR clerarance\n" + "%X.COOKIE cookie clearance\n" + "%X.DOMAIN domain clearance\n" + "%X.USER user clearance\n" + "%X.CACHE cache time in seconds\n" + "%\n" + "%The X. variables are inherited from index.htc\n" + "%if X.CLEAR remains equal to ROOT after init.\n" + "%\n" + "%Unreachable directories: /sys/, /bin/, /htc/, /SCCS/ and /CVS/.\n" + ); +} diff --git a/src/sh/user.cc b/src/sh/user.cc new file mode 100644 index 0000000..94285ef --- /dev/null +++ b/src/sh/user.cc @@ -0,0 +1,445 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +int allow(const sref& s,const sref& grp,time_t now,int rootok) +{ + if(grp.empty()) return 1; + int n=s.find(':'); + sref a=s.left(n); + if(rootok>=0&&a==root_tag) return rootok; + else if(grp==root_tag||a!=grp) return 0; + n=(a=s.past(n,1)).find(':'); sref b=a.past(n,1); a=a.left(n); + return (a.empty()||atoi(a)<=now)&&(b.empty()||nowget(name); + if(!env.is_clear(p)||!p->is_dbref()) THROW("htc: could not find system db "<db.remap(); + return &p->db; +} + +static int FindUser(Env& env,const sref& name) +{ + dbmap* users=GetDB(env,USERS_tag); + for(int i=0;isize();i++) { + if(users->at(i,user_alias)==name) return atoi(users->at(i,user_uid)); + sref first,rest=users->at(i,user_email); + while(Split(first,rest)) if(eqn(first,name)) return atoi(users->at(i,user_uid)); + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +TOK_IMPL(setgroup) { Req(env)->group=First(env[0]); } +TOK_IMPL(group) { out<group; } + +TOK_IMPL(getgroups) { + dbmap* users=GetDB(env,USERS_tag); + mset m; + for(int i=0;isize();i++) { + sref first,rest=users->at(i,user_access); + while(Split(first,rest)) m.insert(first.left_first(':')); + } + out<Find(env[0]); + if(row>=0) users->Get(row,Req(env)->user.list); + else Req(env)->user.reset(); +} + +TOK_IMPL(remuser) { + dbmap* users=GetDB(env,USERS_tag); + int row=users->Find(env[0]); + if(row>=0) users->Rem(row); +} + +TOK_IMPL(newuser) { + static const charset namends("*@.+"); + user_t user; + sref first,rest=env[0]; + Split(first,rest); + user.group()=first.left_first(':'); + do user.add(first); + while(Split(first,rest)); + user.pin()=Random(4); + user.email()=env[1]; + rest=env[1]; while(Split(first,rest)) if(FindUser(env,first)) { out<<0; return; } + mstring tag,alias=env[1].left_first_of(namends); + while(FindUser(env,alias+tag)) tag=itoa(atoi(tag)+1); + user.alias()=alias+tag; + user.name()=env[2]; + dbmap* users=GetDB(env,USERS_tag); + if(users->empty()) user.uid()=itoa(1); + else user.uid()=itoa(atoi(users->at(users->size()-1,user_uid))+1); + int row=users->Insert(user.list,1); + if(row<0) THROW("htc: could not add user - record not unique"); + out<user.uid(); } +TOK_IMPL(user_group) { out<user.group(); } +TOK_IMPL(user_access) { out<user.access(); } +TOK_IMPL(user_clear) { + sref first,rest=Req(env)->user.access(); int n=0; + while(Split(first,rest)) { if(n++) out.put(' '); out<user.fail(); } +TOK_IMPL(user_pin) { out<user.pin(); } +TOK_IMPL(user_alias) { out<user.alias(); } +TOK_IMPL(user_email) { out<user.email()); } +TOK_IMPL(user_emails) { out<user.email(); } +TOK_IMPL(user_name) { out<user.name(); } +TOK_IMPL(user_last) { out<user.last(); } +TOK_IMPL(user_lastin) { out<user.lastin(); } + +////////////////////////////////////////////////////////////////////////// + +TOK_IMPL(user_group_set) { Req(env)->user.group()=env[0]; } +TOK_IMPL(user_access_add) { Req(env)->user.add_list(env[0]); } +TOK_IMPL(user_access_rem) { Req(env)->user.rem_list(env[0]); } +TOK_IMPL(user_fail_set) { Req(env)->user.fail()=env[0]; } +TOK_IMPL(user_pin_set) { Req(env)->user.pin()=env[0]; } +TOK_IMPL(user_alias_set) { Req(env)->user.alias()=env[0]; } +TOK_IMPL(user_emails_set) { Req(env)->user.email()=env[0]; } +TOK_IMPL(user_name_set) { Req(env)->user.name()=env[0]; } +TOK_IMPL(user_last_set) { Req(env)->user.last()=env[0]; } +TOK_IMPL(user_lastin_set) { Req(env)->user.lastin()=env[0]; } + +////////////////////////////////////////////////////////// + +TOK_IMPL(user_update) { + htc_req* htc=Req(env); + int uid=atoi(htc->user.uid()); + int who=FindUser(env,htc->user.alias()); + if(who&&who!=uid) return; + sref first,rest=htc->user.email(); + while(Split(first,rest)) { + who=FindUser(env,first); + if(who&&who!=uid) return; + } + dbmap* users=GetDB(env,USERS_tag); + int row=users->Find(htc->user.uid()); + if(row>=0) users->Set(row,htc->user.list); +} + +////////////////////////////////////////////////////////// + +TOK_IMPL(su) { + htc_req* htc=Req(env); + user_t tmp(htc->user); + dbmap* users=GetDB(env,USERS_tag); + int row=users->Find(env[0]); + if(row>=0) { + try { + users->Get(row,htc->user.list); + env.parg(out,1); + htc->user=tmp; + } + catch(...) { + htc->user=tmp; + throw; + } + } + else env.parg(out,2); +} + +////////////////////////////////////////////////////////// + +void envAddUser(tokmap& T) throw(merror_t) +{ + TOK_ADD(setgroup,"x",tok_t::SYSONLY, + "%Set current group\n" + "%Syntax: \\setgroup{group}\n" + "%\n" + "%Nop function; only for logging and structure.\n" + ); + TOK_ADD(group,"",tok_t::PUBLIC, + "%Get current group\n" + "%Syntax: \\group\n" + "%\n" + "%Nop function; only for logging and structure.\n" + ); + + TOK_ADD(getgroups,"",tok_t::PUBLIC, + "%Get all groups\n" + "%Syntax: \\getgroups\n" + "%\n" + "%Scans users db for all groups used\n" + ); + + /////////////////////////////////////////////////// + + TOK_ADD(getuser,"x",tok_t::SYSONLY, + "%Get user ID\n" + "%Syntax: \\getuser{alias/email}\n" + "%\n" + "%Returns the uid if found, or zero if not found\n" + ); + TOK_ADD(setuser,"x",tok_t::SYSONLY, + "%Set current user\n" + "%Syntax: \\setuser{uid}\n" + ); + TOK_ADD(remuser,"x",tok_t::SYSONLY, + "%Remove user\n" + "%Syntax: \\remuser{uid}\n" + ); + TOK_ADD(newuser,"xxx",tok_t::SYSONLY, + "%Add a new user\n" + "%Syntax: \\newuser{clear}{email}{name}\n" + "%\n" + "%Returns the new uid if successful, otherwise zero.\n" + ); + + /////////////////////////////////////////////////// + + TOK_ADD(user_id,"",tok_t::PUBLIC, + "%Get uid of current user\n" + "%Syntax: \\user.id\n" + ); + TOK_ADD(user_group,"",tok_t::PUBLIC, + "%Get group of current user\n" + "%Syntax: \\user.group\n" + ); + TOK_ADD(user_access,"",tok_t::PUBLIC, + "%Get access of current user\n" + "%Syntax: \\user.access\n" + ); + TOK_ADD(user_clear,"",tok_t::PUBLIC, + "%Get clearance of current user\n" + "%Syntax: \\user.clear\n" + "%\n" + "%This is a compiled list, without the time info.\n" + ); + TOK_ADD(user_fail,"",tok_t::PUBLIC, + "%Get fail number of current user\n" + "%Syntax: \\user.fail\n" + ); + TOK_ADD(user_pin,"",tok_t::SYSONLY, + "%Get pin of current user\n" + "%Syntax: \\user.pin\n" + ); + TOK_ADD(user_alias,"",tok_t::PUBLIC, + "%Get alias of current user\n" + "%Syntax: \\user.alias\n" + ); + TOK_ADD(user_email,"",tok_t::PUBLIC, + "%Get email of current user\n" + "%Syntax: \\user.email\n" + "%\n" + "%Note that the email list may contain several addresses;\n" + "%this function returns the first in the list.\n" + ); + TOK_ADD(user_emails,"",tok_t::PUBLIC, + "%Get all email addresses of current user\n" + "%Syntax: \\user.emails\n" + ); + TOK_ADD(user_name,"",tok_t::PUBLIC, + "%Get name of current user\n" + "%Syntax: \\user.name\n" + ); + TOK_ADD(user_last,"",tok_t::PUBLIC, + "%Get last time logged in of current user\n" + "%Syntax: \\user.last\n" + ); + TOK_ADD(user_lastin,"",tok_t::PUBLIC, + "%Get last IP address of current user\n" + "%Syntax: \\user.lastin\n" + ); + + /////////////////////////////////////////////////// + + TOK_ADD(user_group_set,"x",tok_t::SYSONLY, + "%Set group of current user\n" + "%Syntax: \\user.group.set{group}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_access_add,"x",tok_t::SYSONLY, + "%Add access to current user\n" + "%Syntax: \\user.access.add{group:start:stop}\n" + "%\n" + "%The :start:stop part may be omitted, in which case\n" + "%a start value of now, and a stop value of nil is set.\n" + "%\n" + "%In case of several group strings, they are all added.\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_access_rem,"x",tok_t::SYSONLY, + "%Remove access from current user\n" + "%Syntax: \\user.access.rem{group}\n" + "%\n" + "%In case of several groups, they are all removed.\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_fail_set,"x",tok_t::SYSONLY, + "%Set fail number of current user\n" + "%Syntax: \\user.fail.set{fail}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_pin_set,"x",tok_t::SYSONLY, + "%Set pin of current user\n" + "%Syntax: \\user.pin.set{pin}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_alias_set,"x",tok_t::SYSONLY, + "%Set alias of current user\n" + "%Syntax: \\user.alias.set{alias}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_emails_set,"x",tok_t::SYSONLY, + "%Set all email addresses of current user\n" + "%Syntax: \\user.emails.set{emails}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_name_set,"x",tok_t::SYSONLY, + "%Set name of current user\n" + "%Syntax: \\user.name.set{name}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_last_set,"x",tok_t::SYSONLY, + "%Set last time logged in of current user\n" + "%Syntax: \\user.last.set{last}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + TOK_ADD(user_lastin_set,"x",tok_t::SYSONLY, + "%Set last IP address of current user\n" + "%Syntax: \\user.lastin.set{addr}\n" + "%\n" + "%Note that the changes take effect after a \\user.update\n" + ); + + /////////////////////////////////////////////////// + + TOK_ADD(user_update,"",tok_t::SYSONLY, + "%Update the current user\n" + "%Syntax: \\user.update\n" + "%\n" + "%All changes a synchronous and immediately available.\n" + ); + + /////////////////////////////////////////////////// + + TOK_ADD(su,"xr?",tok_t::SYSONLY, + "%Set user temporary\n" + "%Syntax: \\su{uid}{body}\n" + "%\n" + "%If set successfully, evaluates body, otherwise .\n" + ); + + /////////////////////////////////////////////////// + +} diff --git a/src/sh/user.h b/src/sh/user.h new file mode 100644 index 0000000..cc00e21 --- /dev/null +++ b/src/sh/user.h @@ -0,0 +1,92 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef USERH +#define USERH + +#include +#include + +///////////////////////////////////////////////////////// + +const mstring root_tag="ROOT"; +const mstring lastin_def="0.0.0.0"; + +const mstring USERS_tag="USERS"; +const mstring PREFS_tag="PREFS"; +const mstring TREE_tag="TREE"; + +const int user_tabs=10,user_uid=0,user_alias=4,user_email=5,user_access=9; +const mstring user_tab[user_tabs]={ + "UID","GROUP","FAIL","PIN","ALIAS","EMAIL","NAME","LAST","LASTIN","ACCESS" +}; + +const int prefs_tabs=8; +const mstring prefs_tab[prefs_tabs]={ + "ID","EXT","ROOM","URL","POSIT","NOTE","ABSTRACT","LASTMOD" +}; + +const int tree_tabs=17; +const mstring tree_tab[tree_tabs]={ + "URI","REFER","PARENT","MIME", + "MOD","UID","GID","SIZE","LASTMOD", + "ALIAS","BANNER", + "X.CLEAR","X.COOKIE","X.DOMAIN","X.USER","X.CACHE", + "XMOD" +}; + +int allow(const sref& s,const sref& grp,time_t now,int rootok=0); + +struct user_t { + spile list; + + user_t() : list(user_tabs) {} + user_t(const user_t& us); + + void operator=(const user_t&); + + mstring& uid() { return list[0]; } + mstring& group() { return list[1]; } + mstring& fail() { return list[2]; } + mstring& pin() { return list[3]; } + mstring& alias() { return list[4]; } + mstring& email() { return list[5]; } + mstring& name() { return list[6]; } + mstring& last() { return list[7]; } + mstring& lastin() { return list[8]; } + mstring& access() { return list[9]; } + + void reset(); + int allow(const sref& grp,time_t now,int rootok=0); + int allow_list(const sref& grps,time_t now,int rootok=0); + // rootok<0 -> ignore special root handling (new; should not interfere) + // rootok==0 -> root not allowed here + // rootok>0 -> root always allowed here + + void add(const sref& grp); + void add_list(const sref& grps); + void rem(const sref& grp); + void rem_list(const sref& grps); +}; + +///////////////////////////////////////////////////////// + +void envAddUser(tokmap& T) throw(merror_t); + +#endif -- cgit v1.2.3