OSDN Git Service

dbtcpserver function.
authorvisor <visor@users.sourceforge.jp>
Sat, 12 Jun 2010 11:55:08 +0000 (20:55 +0900)
committervisor <visor@users.sourceforge.jp>
Sat, 12 Jun 2010 11:55:08 +0000 (20:55 +0900)
16 files changed:
Makefile.conf
ext/ml-sqlite3.cc
ext/ml-sqlite3.h
ext/ml-tcpserver.cc [new file with mode: 0644]
ext/ml-tcpserver.h [new file with mode: 0644]
lib/bdbmacro.h
lib/ml.h
lib/util_check.cc
lib/util_check.h
modules/ml-cookielogin.cc
modules/ml-cookielogin.h
modules/ml-db.cc
modules/ml-db.h
modules/ml-http.cc
modules/ml-http.h
modules/ml-variable.cc

index 59337eb..b95b006 100644 (file)
@@ -2,6 +2,7 @@ UTF8JP = 1
 BSD = 1
 #Linux = 1
 
+MSRCS += ml-tcpserver.cc
 MSRCS += ml-http.cc
 MSRCS += diff.cc
 MSRCS += ml-config.cc
index fc98d30..41cb7b7 100644 (file)
@@ -47,7 +47,7 @@ void  MLSqlite3::finalize () {
     }
 }
 
-int  MLSqlite3::prepare (ustring& sql, MlEnv* mlenv) {
+int  MLSqlite3::prepare (ustring& sql) {
     int  rc;
 
 #ifdef DEBUG
@@ -59,7 +59,7 @@ int  MLSqlite3::prepare (ustring& sql, MlEnv* mlenv) {
     return rc;
 }
 
-void  MLSqlite3::bind (namearray& name, namearray& value, MlEnv* mlenv) {
+void  MLSqlite3::bind (namearray& name, namearray& value) {
     namearray::iterator  i1, i2;
     int  n;
 
@@ -97,7 +97,7 @@ void  MLSqlite3::bind (namearray& name, namearray& value, MlEnv* mlenv) {
     }
 }
 
-void  MLSqlite3::bind (namearray& value, MlEnv* mlenv) {
+void  MLSqlite3::bind (namearray& value) {
     namearray::iterator  i2;
     int  n;
 
@@ -119,7 +119,7 @@ void  MLSqlite3::bind (namearray& value, MlEnv* mlenv) {
     }
 }
 
-void  MLSqlite3::exec (MlEnv* mlenv) {
+void  MLSqlite3::exec () {
     int  rc;
 
     rc = sqlite3_step (dbst);
@@ -140,7 +140,7 @@ void  MLSqlite3::exec (MlEnv* mlenv) {
     }
 }
 
-void  MLSqlite3::step (MlEnv* mlenv) {
+void  MLSqlite3::step () {
     int  rc;
 
     rc = sqlite3_step (dbst);
@@ -158,7 +158,7 @@ void  MLSqlite3::step (MlEnv* mlenv) {
     }
 }
 
-void  MLSqlite3::answer (namearray& vars, MlEnv* mlenv) {
+void  MLSqlite3::answer (namearray& vars) {
     int  i;
     int  n = vars.size ();
     MNodePtr  h;
@@ -180,7 +180,7 @@ void  MLSqlite3::answer (namearray& vars, MlEnv* mlenv) {
     }
 }
 
-void  MLSqlite3::answer (namearray& vars, int idx, MlEnv* mlenv) {
+void  MLSqlite3::answer (namearray& vars, int idx) {
     int  i;
     int  n = vars.size ();
     MNodePtr  h;
@@ -202,22 +202,22 @@ void  MLSqlite3::answer (namearray& vars, int idx, MlEnv* mlenv) {
     }
 }
 
-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;
 
@@ -234,7 +234,7 @@ MNode*  MLSqlite3::answer_list (MlEnv* mlenv) {
     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;
@@ -255,7 +255,7 @@ MNode*  MLSqlite3::answer_list_ary (MlEnv* mlenv) {
        }
        if (n >= limit && limit > 0)
            break;
-       step (mlenv);
+       step ();
     }
 
     for (i = 0; i < ncols; i ++) {
@@ -277,7 +277,7 @@ sqlite3_int64  MLSqlite3::rowid () {
 //#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;
@@ -460,18 +460,18 @@ static MNode*  ml_sqlite3_sql_main (MNode* cell, MlEnv* mlenv, MLSqlite3::fsqlPa
     }
 #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);
@@ -479,7 +479,7 @@ static MNode*  ml_sqlite3_sql_main (MNode* cell, MlEnv* mlenv, MLSqlite3::fsqlPa
                }
            } 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 ++) {
@@ -490,9 +490,9 @@ static MNode*  ml_sqlite3_sql_main (MNode* cell, MlEnv* mlenv, MLSqlite3::fsqlPa
        } 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 ();
                }
            }
        }
index b091274..990cd19 100644 (file)
@@ -35,7 +35,6 @@ class  ustringptr_vector: public std::vector<ustring*> {
 
 class  MLSqlite3: public MLFunc {
  public:
-//    typedef boost::ptr_vector<ustring>  namearray;
     typedef ustringptr_vector  namearray;
     class  fsqlParam {
     public:
@@ -58,7 +57,7 @@ class  MLSqlite3: public MLFunc {
     int  ncols;
     bool  fcreate;
 
-    MLSqlite3 (): MLFunc (cMLSqlite3ID) {
+    MLSqlite3 (MlEnv* _mlenv): MLFunc (cMLSqlite3ID, _mlenv) {
        dbh = NULL;
        limit = kARRAYMAX;
        dbst = NULL;
@@ -71,19 +70,19 @@ class  MLSqlite3: public MLFunc {
     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 ();
 };
 
diff --git a/ext/ml-tcpserver.cc b/ext/ml-tcpserver.cc
new file mode 100644 (file)
index 0000000..033e7d9
--- /dev/null
@@ -0,0 +1,508 @@
+#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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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;
+}
+
diff --git a/ext/ml-tcpserver.h b/ext/ml-tcpserver.h
new file mode 100644 (file)
index 0000000..a90d867
--- /dev/null
@@ -0,0 +1,43 @@
+#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 */
index 92d6193..15afc45 100644 (file)
@@ -8,6 +8,7 @@
 #include <db.h>
 #endif
 #include <fcntl.h>
+#include <exception>
 
 class  BDB {
  public:
@@ -164,6 +165,8 @@ class  BDBHash: public BDB {
        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.")));
     };
 };
 
@@ -171,6 +174,8 @@ class  BDBHashRDOnly: public BDB {
  public:
     void  open (const char* path) {
        db = dbopen (path, O_RDONLY, 0666, DB_HASH, NULL);
+       if (! db)
+           throw (ustring (CharConst ("can't open database.")));
     };
 };
 
@@ -178,9 +183,13 @@ class  BDBBtree: public BDB {
  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.")));
     };
 };
 
index d45e78d..25c6949 100644 (file)
--- a/lib/ml.h
+++ b/lib/ml.h
@@ -394,8 +394,9 @@ class  MotorSexp {
 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) {
index 94ecccd..3d94d45 100644 (file)
@@ -5,7 +5,7 @@
 #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)) {
@@ -15,7 +15,7 @@ static bool  checkname (const ustring& name, uregex& 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)) {
@@ -28,91 +28,97 @@ static bool  checkname (uiterator& b, uiterator& e, uregex& 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) {
index eb698cb..901c22b 100644 (file)
 #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);
index 88e5f6e..208e589 100644 (file)
@@ -131,7 +131,7 @@ SESSIONKEY, SESSIONKEY+"N"
 //#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;
 
index 7d1aa7b..ef478a1 100644 (file)
@@ -15,12 +15,11 @@ class  MLCookieLogin: public MLFunc {
     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 ();
 };
index bbe5907..eb3dbc4 100644 (file)
@@ -16,7 +16,7 @@
 
 */
 
-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);
@@ -26,20 +26,20 @@ void  MLDb::dbPath (const ustring& name, bool fxserial, ustring& dbpath, ustring
     }
 }
 
-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 ());
 }
@@ -56,7 +56,7 @@ typedef enum {
 
 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;
@@ -85,10 +85,10 @@ static MNode*  ml_db_sub (MNode* cell, MlEnv* mlenv, DBFUNC fn) {
 
     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);
@@ -520,7 +520,7 @@ static ustring  TempRWDB (CharConst ("temprwdb"));
 //#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;
 
@@ -534,7 +534,7 @@ MNode*  ml_temp_read (MNode* cell, MlEnv* mlenv) {
     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 ();
@@ -564,7 +564,7 @@ MNode*  ml_temp_read (MNode* cell, MlEnv* mlenv) {
 //#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;
@@ -585,7 +585,7 @@ MNode*  ml_temp_write (MNode* cell, MlEnv* mlenv) {
     if (mlenv->env->storedir.empty ())
        throw (uErrorNoStore);
 
-    obj.openRW (TempRWDB, true, mlenv);
+    obj.openRW (TempRWDB, true);
 
     v.reserve (size);
     if (values.size () > 0) {
index cfdbfea..537a3e6 100644 (file)
@@ -17,15 +17,15 @@ class  MLDb: public MLFunc {
 //    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 ();
 };
 
index c5f79fe..e6e1698 100644 (file)
@@ -273,7 +273,7 @@ MNode*  ml_location_html (MNode* cell, MlEnv* mlenv) {
 //#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;
index 91b81aa..4cc443a 100644 (file)
@@ -12,12 +12,10 @@ class  MlEnv;
 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 () {
index f1042c6..eb6158f 100644 (file)
@@ -123,7 +123,6 @@ MNode*  ml_let (MNode* cell, MlEnv* mlenv) {
     varlist = arg->car ();
     nextNode (arg);
 
-//    mlenv->beginLocal ();
     {
        AutoLocalVariable  autoLocal (mlenv);
 
@@ -162,7 +161,6 @@ MNode*  ml_let (MNode* cell, MlEnv* mlenv) {
            mlenv->setBreaksym (NULL);
        }
     }
-//    mlenv->endLocal ();
 
     return ans.release ();
 }
@@ -327,7 +325,7 @@ MNode*  ml_unshift (MNode* cell, MlEnv* mlenv) {
 
 /*DOC:
 ===array===
- (array ARRAY)
+ (array ARRAY) -> LIST
 
 */
 //#AFUNC       array   ml_array
@@ -335,8 +333,6 @@ MNode*  ml_unshift (MNode* cell, MlEnv* mlenv) {
 MNode*  ml_array (MNode* cell, MlEnv* mlenv) {
     MNode*  arg = cell->cdr ();
     ustring  var;
-//    MNode  ans;
-//    MNode*  y = &ans;
     MNodeList  ans;
     int  i, n;
 
@@ -352,15 +348,9 @@ MNode*  ml_array (MNode* cell, MlEnv* mlenv) {
     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 ();
 }