BSD = 1
#Linux = 1
+MSRCS += ml-tcpserver.cc
MSRCS += ml-http.cc
MSRCS += diff.cc
MSRCS += ml-config.cc
}
}
-int MLSqlite3::prepare (ustring& sql, MlEnv* mlenv) {
+int MLSqlite3::prepare (ustring& sql) {
int rc;
#ifdef DEBUG
return rc;
}
-void MLSqlite3::bind (namearray& name, namearray& value, MlEnv* mlenv) {
+void MLSqlite3::bind (namearray& name, namearray& value) {
namearray::iterator i1, i2;
int n;
}
}
-void MLSqlite3::bind (namearray& value, MlEnv* mlenv) {
+void MLSqlite3::bind (namearray& value) {
namearray::iterator i2;
int n;
}
}
-void MLSqlite3::exec (MlEnv* mlenv) {
+void MLSqlite3::exec () {
int rc;
rc = sqlite3_step (dbst);
}
}
-void MLSqlite3::step (MlEnv* mlenv) {
+void MLSqlite3::step () {
int rc;
rc = sqlite3_step (dbst);
}
}
-void MLSqlite3::answer (namearray& vars, MlEnv* mlenv) {
+void MLSqlite3::answer (namearray& vars) {
int i;
int n = vars.size ();
MNodePtr h;
}
}
-void MLSqlite3::answer (namearray& vars, int idx, MlEnv* mlenv) {
+void MLSqlite3::answer (namearray& vars, int idx) {
int i;
int n = vars.size ();
MNodePtr h;
}
}
-void MLSqlite3::answer_ary (MlEnv* mlenv, MLSqlite3::fsqlParam& par) {
+void MLSqlite3::answer_ary (MLSqlite3::fsqlParam& par) {
int n = 0;
while (isReady ()) {
n ++;
- answer (par.answer, n, mlenv);
+ answer (par.answer, n);
if (n >= limit && limit > 0)
break;
- step (mlenv);
+ step ();
}
for (int i = 0; i < par.answer.size (); i ++) {
mlenv->setArySize (*par.answer[i], n);
}
}
-MNode* MLSqlite3::answer_list (MlEnv* mlenv) {
+MNode* MLSqlite3::answer_list () {
MNodeList ans;
int i;
return ans.release ();
}
-MNode* MLSqlite3::answer_list_ary (MlEnv* mlenv) {
+MNode* MLSqlite3::answer_list_ary () {
boost::ptr_vector<MNodeList> list;
MNodeList ans;
int i, n;
}
if (n >= limit && limit > 0)
break;
- step (mlenv);
+ step ();
}
for (i = 0; i < ncols; i ++) {
//#MFUNC $sqlite3 ml_sqlite3 cMLSqlite3ID
MNode* ml_sqlite3 (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
- MLSqlite3 obj;
+ MLSqlite3 obj (mlenv);
ustring db;
ustring dbfile;
MNodePtr ans;
}
#endif /* DEBUG */
- rc = obj->prepare (par.sql, mlenv);
+ rc = obj->prepare (par.sql);
if (rc == SQLITE_OK) {
if (mode == 2) {
- obj->bind (par.bindValue, mlenv);
+ obj->bind (par.bindValue);
} else {
- obj->bind (par.bindName, par.bindValue, mlenv);
+ obj->bind (par.bindName, par.bindValue);
}
- obj->exec (mlenv);
+ obj->exec ();
if (par.answer.size () > 0) {
if (par.answerisary) {
if (obj->isReady ()) {
- obj->answer_ary (mlenv, par);
+ obj->answer_ary (par);
} else {
for (int i = 0; i < par.answer.size (); i ++) {
mlenv->setArySize (*par.answer[i], 0);
}
} else {
if (obj->isReady ()) {
- obj->answer (par.answer, mlenv);
+ obj->answer (par.answer);
obj->finalize ();
} else {
for (int i = 0; i < par.answer.size (); i ++) {
} else {
if (obj->isReady ()) {
if (par.answerisary) {
- ans = obj->answer_list_ary (mlenv);
+ ans = obj->answer_list_ary ();
} else {
- ans = obj->answer_list (mlenv);
+ ans = obj->answer_list ();
}
}
}
class MLSqlite3: public MLFunc {
public:
-// typedef boost::ptr_vector<ustring> namearray;
typedef ustringptr_vector namearray;
class fsqlParam {
public:
int ncols;
bool fcreate;
- MLSqlite3 (): MLFunc (cMLSqlite3ID) {
+ MLSqlite3 (MlEnv* _mlenv): MLFunc (cMLSqlite3ID, _mlenv) {
dbh = NULL;
limit = kARRAYMAX;
dbst = NULL;
virtual int open (ustring& name);
virtual void close ();
virtual void finalize ();
- virtual int prepare (ustring& sql, MlEnv* mlenv);
- virtual void bind (namearray& name, namearray& value, MlEnv* mlenv);
- virtual void bind (namearray& value, MlEnv* mlenv);
- virtual void exec (MlEnv* mlenv);
- virtual void step (MlEnv* mlenv);
+ virtual int prepare (ustring& sql);
+ virtual void bind (namearray& name, namearray& value);
+ virtual void bind (namearray& value);
+ virtual void exec ();
+ virtual void step ();
virtual bool isReady () {
return (dbst != NULL);
};
- virtual void answer (namearray& vars, MlEnv* mlenv);
- virtual void answer (namearray& vars, int idx, MlEnv* mlenv);
- virtual void answer_ary (MlEnv* mlenv, fsqlParam& par);
- virtual MNode* answer_list (MlEnv* mlenv);
- virtual MNode* answer_list_ary (MlEnv* mlenv);
+ virtual void answer (namearray& vars);
+ virtual void answer (namearray& vars, int idx);
+ virtual void answer_ary (fsqlParam& par);
+ virtual MNode* answer_list ();
+ virtual MNode* answer_list_ary ();
virtual sqlite3_int64 rowid ();
};
--- /dev/null
+#include "ml-tcpserver.h"
+#include "motorconst.h"
+#include "ml.h"
+#include "mlenv.h"
+#include "motorenv.h"
+#include "ustring.h"
+#include "expr.h"
+#include "util_const.h"
+#include "util_check.h"
+#include "util_string.h"
+#include "bdbmacro.h"
+#include "sigsafe.h"
+#include <sys/file.h>
+#include <string.h>
+#include <time.h>
+#include <exception>
+
+/*DOC:
+==dbtcpserver module==
+
+*/
+static uregex re_iprange ("^[0-9]{1,3}\\.([0-9]{1,3}\\.([0-9]{1,3}\\.([0-9]{1,3})?)?)?$");
+static uregex re_domainrange ("^\\.?[a-zA-Z0-9][a-zA-Z0-9\\-]*(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]*)*$");
+
+void MLDbTcpserver::setPath (const ustring& name) {
+ dbpath = mlenv->env->path_to_auth (name);
+ dbpath.append (CharConst (kEXT_HASH));
+}
+
+void MLDbTcpserver::opendb () {
+ db.open (dbpath.c_str ());
+ flock (db.db->fd (db.db), LOCK_EX);
+}
+
+void MLDbTcpserver::closedb () {
+ if (db.db) {
+ flock (db.db->fd (db.db), LOCK_UN);
+ db.close ();
+ }
+}
+
+void MLDbTcpserver::addAllow (const ustring& key, time_t span, MNode* rest, MlEnv* mlenv) {
+ ustring val;
+ ustring estr;
+
+ if (span < 0)
+ span = 1; // timeout
+ if (span > 0) {
+ span += time (NULL);
+ val.append (CharConst ("\xff\xff\xff\xff")).append ((const char*)(&span), sizeof (time_t));
+ }
+ if (rest) {
+ while (rest) {
+ estr = eval_str (rest->car (), mlenv);
+ nextNode (rest);
+ if (! checkASCII (estr) || estr.length () > 1024)
+ throw (estr + uErrorBadValue);
+ val.append (CharConst ("+")).append (estr).append (1, 0);
+ }
+ }
+ db.put (key, val);
+}
+
+void MLDbTcpserver::addDeny (const ustring& key) {
+ ustring val;
+
+ val.assign (CharConst ("D\x00"));
+ db.put (key, val);
+}
+
+void MLDbTcpserver::del (const ustring& key) {
+ db.del (key);
+}
+
+bool MLDbTcpserver::splitRec (const ustring& rec, bool& allow, time_t& limit, MNodeList& estr) {
+ uiterator b, e, m;
+
+ b = rec.begin ();
+ e = rec.end ();
+ allow = true;
+ limit = 0;
+ if (b == e) {
+ return true;
+ } else if (matchHead (b, e, CharConst ("D\x00"))) {
+ allow = false;
+ limit = 0;
+ return true;
+ } else if (matchSkip (b, e, CharConst ("\xff\xff\xff\xff"))) {
+ if (e - b >= sizeof (time_t)) {
+ allow = true;
+ memcpy ((void*)&limit, &*b, sizeof (time_t));
+ b += sizeof (time_t);
+ } else {
+ return false;
+ }
+ }
+ while (b <= e) {
+ if (b == e) {
+ return true;
+ } else {
+ if (*b == '+') {
+ b ++;
+ if (splitChar (b, e, '\x00', m)) {
+ estr.append (newMNode_str (new ustring (b, m)));
+ b = m + 1;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool MLDbTcpserver::splitRec (const ustring& rec, bool& allow, time_t& limit) {
+ uiterator b, e, m;
+
+ b = rec.begin ();
+ e = rec.end ();
+ allow = true;
+ limit = 0;
+ if (b == e) {
+ return true;
+ } else if (matchHead (b, e, CharConst ("D\x00"))) {
+ allow = false;
+ limit = 0;
+ return true;
+ } else if (matchSkip (b, e, CharConst ("\xff\xff\xff\xff"))) {
+ if (e - b >= sizeof (time_t)) {
+ allow = true;
+ memcpy ((void*)&limit, &*b, sizeof (time_t));
+ b += sizeof (time_t);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+/*DOC:
+===$dbtcpserver===
+ ($dbtcpserver NAME [SUBFUNCTION...])
+DJBのucspi-tcp拡張版のBerkeleyDBアクセス制御データベースのハンドリング。
+
+*/
+//#MFUNC $dbtcpserver ml_dbtcpserver cMLDbTcpserverID
+MNode* ml_dbtcpserver (MNode* cell, MlEnv* mlenv) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver obj (mlenv);
+ ustring name;
+ MNodePtr ans;
+
+ if (! arg)
+ throw (uErrorWrongNumber);
+
+ name = eval_str (arg->car (), mlenv);
+ nextNode (arg);
+
+ if (name.size () == 0)
+ throw (uErrorFilenameEmpty);
+ if (! checkName (name))
+ throw (name + uErrorBadName);
+ if (mlenv->env) {
+ SigSafe sig;
+ obj.setPath (name);
+
+ mlenv->setMStack (&obj);
+ obj.opendb ();
+ ans = progn (arg, mlenv);
+ if (mlenv->breaksym ()
+ && (mlenv->breaksym ()->isNil () || eq (mlenv->breaksym (), cell->car ()))) {
+ mlenv->setBreaksym (NULL);
+ }
+ obj.closedb ();
+ }
+
+ return ans.release ();
+}
+
+/*DOC:
+===subfunctions of $dbtcpserver===
+
+*/
+/*DOC:
+====add-allow-ip====
+ (add-allow-ip IP SPAN ENV...) -> NIL
+IPアドレス,アドレスレンジをキーにしたallow行を追加する。
+ドットで終わる4オクテット未満のアドレスを指定すると,アドレスレンジ指定となる。
+SPANが0以上の時,登録時からSPAN病後までの間,レコードが有効になる。
+環境変数指定を「名前=値」の形式で指定する。環境変数指定は複数指定できる。
+
+====add-allow-host====
+ (add-allow-host DOMAIN SPAN ENV...) -> NIL
+ホスト名,ドメイン名をキーにしたallow行を追加する。
+ドットで始まるドメイン名を指定すると,ドメイン全体の指定となる。
+SPANが0以上の時,登録時からSPAN病後までの間,レコードが有効になる。
+環境変数指定を「名前=値」の形式で指定する。環境変数指定は複数指定できる。
+
+====add-deny-ip====
+ (add-deny-ip IP) -> NIL
+IPアドレス,アドレスレンジをキーにしたdeny行を追加する。
+ドットで終わる4オクテット未満のアドレスを指定すると,アドレスレンジ指定となる。
+
+====add-deny-host====
+ (add-deny-host DOMAIN) -> NIL
+ホスト名,ドメイン名をキーにしたdeny行を追加する。
+ドットで始まるドメイン名を指定すると,ドメイン全体の指定となる。
+
+====delete-ip====
+ (delete-ip IP) -> NIL
+IPアドレスをキーとして登録したレコードを削除する。
+
+====delete-host====
+ (delete-host DOMAIN)
+ドメイン名をキーとして登録したレコードを削除する。
+
+====read-ip====
+ (read-ip IP) -> (["allow" | "deny"] TIME ENV_LIST)
+IPアドレスをキーとしてレコードを読み取る。
+レコードの期限が指定されているものは,期限の時刻のUNIX timeが返される。
+環境変数指定はリストで返される。
+
+====read-host====
+ (read-host DOMAIN) -> (["allow" | "deny"] TIME ENV_LIST)
+ドメイン名をキーとしてレコードを読み取る。
+レコードの期限が指定されているものは,期限の時刻のUNIX timeが返される。
+環境変数指定はリストで返される。
+
+====dump-ip====
+ (dump-ip) -> (IP PERM_LIST TIME_LIST ENV_LIST)
+IPアドレスをキーとした全レコードをリストで返す。
+空文字列のキーのレコードは,dump-ip関数の戻り値に含まれる。
+
+====dump-host====
+ (dump-host) -> (DOMAIN PERM_LIST TIME_LIST ENV_LIST)
+ドメイン名をキーとしたレコードをリストで返す。
+
+====cleanup====
+ (cleanup) -> NIL
+有効期限指定のあるレコードで,期限を杉田レコードを削除する。
+
+*/
+
+//#SFUNC add-allow-ip ml_dbtcpserver_add_allow_ip $dbtcpserver
+MNode* ml_dbtcpserver_add_allow_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ MNode* rest;
+ ustring ip;
+ time_t span;
+
+ setParams (arg, 2, ¶ms, NULL, NULL, &rest);
+ ip = eval_str (params[0], mlenv);
+ span = eval_int (params[1], mlenv);
+ if (ip.length () > 0 && ! checkRe (ip, re_iprange))
+ throw (ip + uErrorBadValue);
+
+ obj->addAllow (ip, span, rest, mlenv);
+
+ return NULL;
+}
+
+//#SFUNC add-allow-host ml_dbtcpserver_add_allow_host $dbtcpserver
+MNode* ml_dbtcpserver_add_allow_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ MNode* rest;
+ ustring host;
+ time_t span;
+
+ setParams (arg, 2, ¶ms, NULL, NULL, &rest);
+ host = eval_str (params[0], mlenv);
+ span = eval_int (params[1], mlenv);
+ if (host.length () > 0 && ! checkRe (host, re_domainrange))
+ throw (host + uErrorBadValue);
+
+ if (host.length () > 0)
+ host = ustring (CharConst ("=")).append (host);
+ obj->addAllow (host, span, rest, mlenv);
+
+ return NULL;
+}
+
+//#SFUNC add-deny-ip ml_dbtcpserver_add_deny_ip $dbtcpserver
+MNode* ml_dbtcpserver_add_deny_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ ustring ip;
+
+ setParams (arg, 1, ¶ms, NULL, NULL, NULL);
+ ip = eval_str (params[0], mlenv);
+ if (ip.length () > 0 && ! checkRe (ip, re_iprange))
+ throw (ip + uErrorBadValue);
+
+ obj->addDeny (ip);
+
+ return NULL;
+}
+
+//#SFUNC add-deny-host ml_dbtcpserver_add_deny_host $dbtcpserver
+MNode* ml_dbtcpserver_add_deny_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ ustring host;
+
+ setParams (arg, 1, ¶ms, NULL, NULL, NULL);
+ host = eval_str (params[0], mlenv);
+ if (host.length () > 0 && ! checkRe (host, re_domainrange))
+ throw (host + uErrorBadValue);
+
+ if (host.length () > 0)
+ host = ustring (CharConst ("=")).append (host);
+ obj->addDeny (host);
+
+ return NULL;
+}
+
+//#SFUNC delete-ip ml_dbtcpserver_delete_ip $dbtcpserver
+MNode* ml_dbtcpserver_delete_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ ustring ip;
+
+ setParams (arg, 1, ¶ms, NULL, NULL, NULL);
+ ip = eval_str (params[0], mlenv);
+ if (ip.length () > 0 && ! checkRe (ip, re_iprange))
+ throw (ip + uErrorBadValue);
+
+ obj->del (ip);
+
+ return NULL;
+}
+
+//#SFUNC delete-host ml_dbtcpserver_delete_host $dbtcpserver
+MNode* ml_dbtcpserver_delete_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ ustring host;
+
+ setParams (arg, 1, ¶ms, NULL, NULL, NULL);
+ host = eval_str (params[0], mlenv);
+ if (host.length () > 0 && ! checkRe (host, re_domainrange))
+ throw (host + uErrorBadValue);
+
+ if (host.length () > 0)
+ host = ustring (CharConst ("=")).append (host);
+ obj->del (host);
+
+ return NULL;
+}
+
+static MNode* accessRec (MLDbTcpserver* obj, const ustring& key) {
+ ustring val;
+ bool allow;
+ time_t limit;
+ MNodeList estr;
+
+ if (obj->db.get (key, val)) {
+ if (obj->splitRec (val, allow, limit, estr)) {
+ MNodeList ans;
+ if (allow) {
+ ans.append (newMNode_str (new ustring (CharConst ("allow"))));
+ } else {
+ ans.append (newMNode_str (new ustring (CharConst ("deny"))));
+ }
+ ans.append (newMNode_num (limit));
+ ans.append (estr.release ());
+ return ans.release ();
+ }
+ }
+ return NULL;
+}
+
+static void accessRec (MLDbTcpserver* obj, const ustring& key, const ustring& val, MNodeList& lkey, MNodeList& lallow, MNodeList& llimit, MNodeList& lestr) {
+ bool allow;
+ time_t limit;
+ MNodeList estr;
+
+ if (obj->splitRec (val, allow, limit, estr)) {
+ lkey.append (newMNode_str (new ustring (key)));
+ if (allow) {
+ lallow.append (newMNode_str (new ustring (CharConst ("allow"))));
+ } else {
+ lallow.append (newMNode_str (new ustring (CharConst ("deny"))));
+ }
+ llimit.append (newMNode_num (limit));
+ lestr.append (estr.release ());
+ }
+}
+
+//#SFUNC read-ip ml_dbtcpserver_read_ip $dbtcpserver
+MNode* ml_dbtcpserver_read_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ ustring ip;
+
+ setParams (arg, 1, ¶ms, NULL, NULL, NULL);
+ ip = eval_str (params[0], mlenv);
+ if (ip.length () > 0 && ! checkRe (ip, re_iprange))
+ throw (ip + uErrorBadValue);
+
+ return accessRec (obj, ip);
+}
+
+//#SFUNC read-host ml_dbtcpserver_read_host $dbtcpserver
+MNode* ml_dbtcpserver_read_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ std::vector<MNode*> params;
+ ustring host;
+
+ setParams (arg, 1, ¶ms, NULL, NULL, NULL);
+ host = eval_str (params[0], mlenv);
+ if (host.length () > 0 && ! checkRe (host, re_domainrange))
+ throw (host + uErrorBadValue);
+
+ if (host.length () > 0)
+ host = ustring (CharConst ("=")).append (host);
+ return accessRec (obj, host);
+}
+
+//#SFUNC dump-ip ml_dbtcpserver_dump_ip $dbtcpserver
+MNode* ml_dbtcpserver_dump_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ MNodeList ans, lkey, lallow, llimit, lestr;
+ ustring key, val;
+
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ obj->db.initeach ();
+ while (obj->db.each (key, val)) {
+ if (key.length () > 0 && key[0] == '=') {
+ } else {
+ accessRec (obj, key, val, lkey, lallow, llimit, lestr);
+ }
+ }
+ ans.append (lkey.release ());
+ ans.append (lallow.release ());
+ ans.append (llimit.release ());
+ ans.append (lestr.release ());
+ return ans.release ();
+}
+
+//#SFUNC dump-host ml_dbtcpserver_dump_host $dbtcpserver
+MNode* ml_dbtcpserver_dump_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ MNodeList ans, lkey, lallow, llimit, lestr;
+ ustring key, val;
+
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ obj->db.initeach ();
+ while (obj->db.each (key, val)) {
+ if (key.length () > 0 && key[0] == '=') {
+ key.assign (key.begin () + 1, key.end ());
+ accessRec (obj, key, val, lkey, lallow, llimit, lestr);
+ } else {
+ }
+ }
+ ans.append (lkey.release ());
+ ans.append (lallow.release ());
+ ans.append (llimit.release ());
+ ans.append (lestr.release ());
+ return ans.release ();
+}
+
+//#SFUNC cleanup ml_dbtcpserver_cleanup $dbtcpserver
+MNode* ml_dbtcpserver_cleanup (MNode* cell, MlEnv* mlenv, MLFunc* mobj) {
+ MNode* arg = cell->cdr ();
+ MLDbTcpserver* obj = MObjRef<MLDbTcpserver> (mobj, cMLDbTcpserverID);
+ ustring key, val;
+ std::vector<ustring> ary;
+ time_t now = time (NULL);
+ bool allow;
+ time_t limit;
+ std::vector<ustring>::iterator b, e;
+
+ if (arg)
+ throw (uErrorWrongNumber);
+
+ obj->db.initeach ();
+ while (obj->db.each (key, val)) {
+ if (obj->splitRec (val, allow, limit)) {
+ if (allow && limit > 0 && limit < now) {
+ ary.push_back (key);
+ }
+ } else {
+ ary.push_back (key);
+ }
+ }
+ b = ary.begin ();
+ e = ary.end ();
+ for (; b < e; b ++) {
+ obj->db.del (*b);
+ }
+
+ return NULL;
+}
+
--- /dev/null
+#ifndef ML_TCPSERVER_H
+#define ML_TCPSERVER_H
+
+#include "ml.h"
+#include "ml-id.h"
+#include "ustring.h"
+#include "bdbmacro.h"
+
+class MlEnv;
+
+class MLDbTcpserver: public MLFunc {
+ public:
+ BDBHash db;
+ ustring dbpath;
+
+ MLDbTcpserver (MlEnv* _mlenv): MLFunc (cMLDbTcpserverID, _mlenv) {};
+ virtual ~MLDbTcpserver () {
+ closedb ();
+ };
+ virtual void setPath (const ustring& name);
+ virtual void opendb ();
+ virtual void closedb ();
+ virtual void addAllow (const ustring& key, time_t span, MNode* rest, MlEnv* mlenv);
+ virtual void addDeny (const ustring& key);
+ virtual void del (const ustring& key);
+ virtual bool splitRec (const ustring& rec, bool& allow, time_t& limit, MNodeList& estr);
+ virtual bool splitRec (const ustring& rec, bool& allow, time_t& limit);
+};
+
+MNode* ml_dbtcpserver (MNode* cell, MlEnv* mlenv);
+MNode* ml_dbtcpserver_add_allow_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_add_allow_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_add_deny_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_add_deny_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_delete_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_delete_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_read_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_read_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_dump_ip (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_dump_host (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+MNode* ml_dbtcpserver_cleanup (MNode* cell, MlEnv* mlenv, MLFunc* mobj);
+
+#endif /* ML_TCPSERVER_H */
#include <db.h>
#endif
#include <fcntl.h>
+#include <exception>
class BDB {
public:
db = dbopen (path, O_RDWR | O_CREAT, 0666, DB_HASH, &info);
#endif
db = dbopen (path, O_RDWR | O_CREAT, 0666, DB_HASH, NULL);
+ if (! db)
+ throw (ustring (CharConst ("can't open database.")));
};
};
public:
void open (const char* path) {
db = dbopen (path, O_RDONLY, 0666, DB_HASH, NULL);
+ if (! db)
+ throw (ustring (CharConst ("can't open database.")));
};
};
public:
void openRead (const char* path) {
db = dbopen (path, O_RDONLY, 0666, DB_BTREE, NULL);
+ if (! db)
+ throw (ustring (CharConst ("can't open database.")));
};
void openRW (const char* path) {
db = dbopen (path, O_RDWR | O_CREAT, 0666, DB_BTREE, NULL);
+ if (! db)
+ throw (ustring (CharConst ("can't open database.")));
};
};
class MLFunc {
public:
int id;
+ MlEnv* mlenv;
- MLFunc (int v): id (v) {};
+ MLFunc (int v, MlEnv* _mlenv): id (v), mlenv (_mlenv) {};
virtual ~MLFunc () {};
};
template <class T> inline T* MObjRef (MLFunc* mobj, int id) {
#include "motorconst.h"
#include "ustring.h"
-static bool checkname (const ustring& name, uregex& re) {
+bool checkRe (const ustring& name, uregex& re) {
umatch m;
if (usearch (name, m, re)) {
}
}
-static bool checkname (uiterator& b, uiterator& e, uregex& re) {
+bool checkRe (uiterator& b, uiterator& e, uregex& re) {
umatch m;
if (usearch (b, e, m, re)) {
bool checkName (const ustring& name) {
static uregex re ("^" kWNAME "{0,31}$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkFilename (const ustring& name) {
static uregex re ("^" kWNAME "{1,127}(\\." kWORD "{1,16})?$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkResourceName (const ustring& name) {
static uregex re ("^(" kWNAME "{0,127}/)*" kWNAME "{0,127}(\\." kWORD "{1,16})?$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkAbsoluteResourceName (const ustring& name) {
// static uregex re ("^/(" kWNAME "{0,127}/)*" kWNAME "{0,127}(\\." kWORD "{1,16})?$");
static uregex re ("^/(" kFName "/)*" kFName "$");
- return (checkname (name, re));
+ return (checkRe (name, re));
+}
+
+bool checkASCII (const ustring& name) {
+ static uregex re ("^[ -\\x7e]*$");
+
+ return (checkRe (name, re));
}
bool checkIP (const ustring& name) {
static uregex re ("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkDomain_dot (const ustring& name) {
static uregex re ("^\\.?([a-zA-Z0-9-]+\\.)*([a-zA-Z0-9-]+)$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkHostname (const ustring& name) {
static uregex re ("^[a-zA-Z0-9][a-zA-Z0-9\\-]*(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]*)*$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkMimeType (const ustring& name) {
static uregex re ("^[a-z_0-9-]+/[a-z_0-9.+-]+$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkMailAddr (const ustring& name) {
static uregex re ("^[^\\x00- @\\x7f-\\xff]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$");
- return (checkname (name, re));
+ return (checkRe (name, re));
}
bool checkNum (const ustring& text) {
- return (checkname (text, re_num));
+ return (checkRe (text, re_num));
}
bool checkNum (uiterator& b, uiterator& e) {
- return (checkname (b, e, re_num));
+ return (checkRe (b, e, re_num));
}
static uregex re_width ("^[0-9]+(%|px|pt|in|mm|cm|em|ex)?$");
bool checkWidth (uiterator& b, uiterator& e) {
- return (checkname (b, e, re_width));
+ return (checkRe (b, e, re_width));
}
bool checkWidth (const ustring& text) {
- return (checkname (text, re_width));
+ return (checkRe (text, re_width));
}
static uregex re_color ("^#([0-9a-fA-F]{3}){1,2}$");
bool checkColor (uiterator& b, uiterator& e) {
- return (checkname (b, e, re_color));
+ return (checkRe (b, e, re_color));
}
bool checkColor (const ustring& text) {
- return (checkname (text, re_color));
+ return (checkRe (text, re_color));
}
static uregex re_wikiid ("^" rWikiID "$");
bool checkWikiID (uiterator& b, uiterator& e) {
- return (checkname (b, e, re_wikiid));
+ return (checkRe (b, e, re_wikiid));
}
bool checkWikiID (const ustring& text) {
- return (checkname (text, re_wikiid));
+ return (checkRe (text, re_wikiid));
}
bool checkAry (const ustring& name) {
#define UA_Opera 0x00000800
#define UA_NetFront 0x00001000
+bool checkRe (const ustring& name, uregex& re);
+bool checkRe (uiterator& b, uiterator& e, uregex& re);
bool checkName (const ustring& name);
bool checkFilename (const ustring& name);
bool checkResourceName (const ustring& name);
bool checkAbsoluteResourceName (const ustring& name);
+bool checkASCII (const ustring& name);
bool checkIP (const ustring& name);
bool checkDomain_dot (const ustring& name);
bool checkHostname (const ustring& name);
//#MFUNC $login-cookie ml_cookielogin cMLCookieLoginID
MNode* ml_cookielogin (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
- MLCookieLogin obj;
+ MLCookieLogin obj (mlenv);
ustring name;
MNodePtr ans;
ustring dbpath;
ustring sessionkey;
- MLCookieLogin (): MLFunc (cMLCookieLoginID) {};
+ MLCookieLogin (MlEnv* _mlenv): MLFunc (cMLCookieLoginID, _mlenv) {};
virtual ~MLCookieLogin () {
closedb ();
};
-// virtual void opendb (ustring& path);
virtual void opendb ();
virtual void closedb ();
};
*/
-void MLDb::dbPath (const ustring& name, bool fxserial, ustring& dbpath, ustring& lockpath, MlEnv* mlenv) {
+void MLDb::dbPath (const ustring& name, bool fxserial, ustring& dbpath, ustring& lockpath) {
if (fxserial) {
dbpath = mlenv->env->path_store_file (name, kEXT_BTREE);
lockpath = mlenv->env->path_store_file (name, kEXT_LOCK);
}
}
-void MLDb::openRead (const ustring& name, bool fxserial, MlEnv* mlenv) {
+void MLDb::openRead (const ustring& name, bool fxserial) {
ustring dbpath;
ustring lockpath;
- dbPath (name, fxserial, dbpath, lockpath, mlenv);
+ dbPath (name, fxserial, dbpath, lockpath);
lock.openReadLock (lockpath.c_str ());
db.openRead (dbpath.c_str ());
}
-void MLDb::openRW (const ustring& name, bool fxserial, MlEnv* mlenv) {
+void MLDb::openRW (const ustring& name, bool fxserial) {
ustring dbpath;
ustring lockpath;
- dbPath (name, fxserial, dbpath, lockpath, mlenv);
+ dbPath (name, fxserial, dbpath, lockpath);
lock.openAppendLock (lockpath.c_str ());
db.openRW (dbpath.c_str ());
}
static MNode* ml_db_sub (MNode* cell, MlEnv* mlenv, DBFUNC fn) {
MNode* arg = cell->cdr ();
- MLDb obj;
+ MLDb obj (mlenv);
MNodePtr ans;
ustring name;
bool fxserial = false;
switch (fn) {
case FN_READ:
- obj.openRead (name, fxserial, mlenv);
+ obj.openRead (name, fxserial);
break;
case FN_RW:
- obj.openRW (name, fxserial, mlenv);
+ obj.openRW (name, fxserial);
break;
default:
assert (0);
//#AFUNC temp-read ml_temp_read
MNode* ml_temp_read (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
- MLDb obj;
+ MLDb obj (mlenv);
ustring key;
ustring val;
if (mlenv->env->storedir.empty ())
throw (uErrorNoStore);
- obj.openRead (TempRWDB, true, mlenv);
+ obj.openRead (TempRWDB, true);
if (obj.db.get (key, val)) {
uiterator b = val.begin ();
//#AFUNC temp-write ml_temp_write
MNode* ml_temp_write (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
- MLDb obj;
+ MLDb obj (mlenv);
ustring key;
std::vector<ustring> values;
ustring v;
if (mlenv->env->storedir.empty ())
throw (uErrorNoStore);
- obj.openRW (TempRWDB, true, mlenv);
+ obj.openRW (TempRWDB, true);
v.reserve (size);
if (values.size () > 0) {
// ustring dbpath;
int limit;
- MLDb (): MLFunc (cMLDbID) {
+ MLDb (MlEnv* _mlenv): MLFunc (cMLDbID, _mlenv) {
limit = 10000;
};
virtual ~MLDb () {
closedb ();
};
- virtual void dbPath (const ustring& name, bool fxserial, ustring& dbpath, ustring& lockpath, MlEnv* mlenv);
- virtual void openRead (const ustring& name, bool fxserial, MlEnv* mlenv);
- virtual void openRW (const ustring& name, bool fxserial, MlEnv* mlenv);
+ virtual void dbPath (const ustring& name, bool fxserial, ustring& dbpath, ustring& lockpath);
+ virtual void openRead (const ustring& name, bool fxserial);
+ virtual void openRW (const ustring& name, bool fxserial);
virtual void closedb ();
};
//#MFUNC $http-get ml_http_get cMLHttpGetID
MNode* ml_http_get (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
- MLHttpGet obj;
+ MLHttpGet obj (mlenv);
ustring url;
MNodePtr query;
MNodePtr cookie;
class MLHttpGet: public MLFunc {
public:
HTTPSend http;
-// TcpClient client;
TcpClient* client;
TcpBuf buf;
- MLHttpGet (): MLFunc (cMLHttpGetID) {
-// client = new BasicTcpClient;
+ MLHttpGet (MlEnv* _mlenv): MLFunc (cMLHttpGetID, _mlenv) {
client = NULL;
};
virtual ~MLHttpGet () {
varlist = arg->car ();
nextNode (arg);
-// mlenv->beginLocal ();
{
AutoLocalVariable autoLocal (mlenv);
mlenv->setBreaksym (NULL);
}
}
-// mlenv->endLocal ();
return ans.release ();
}
/*DOC:
===array===
- (array ARRAY)
+ (array ARRAY) -> LIST
*/
//#AFUNC array ml_array
MNode* ml_array (MNode* cell, MlEnv* mlenv) {
MNode* arg = cell->cdr ();
ustring var;
-// MNode ans;
-// MNode* y = &ans;
MNodeList ans;
int i, n;
n = mlenv->getArySize (var);
if (n > 0) {
for (i = 1; i <= n; i ++) {
-// newMNodeCdr (y);
-// y->set_car (mlenv->getAry (var, i));
ans.append (mlenv->getAry (var, i));
}
}
-// if (ans.isCons ())
-// return ans.release_cdr ();
-// else
-// return NULL;
return ans.release ();
}