@@ -0,0 +1,210 @@ | |||
using System; | |||
using System.Text; | |||
using System.Runtime.InteropServices; | |||
using System.Web; | |||
namespace CppCMS.Session { | |||
internal class API { | |||
public const int SESSION_FIXED=0; | |||
public const int SESSION_RENEW=1; | |||
public const int SESSION_BROWSER=2; | |||
public const int ERROR_OK=0; | |||
public const int ERROR_GENERAL=1; | |||
public const int ERROR_RUNTIME=2; | |||
public const int ERROR_INVALID_ARGUMENT=4; | |||
public const int ERROR_LOGIC=5; | |||
public const int ERROR_ALLOC=6; | |||
public const string library = "cppcms"; | |||
[DllImport(library,EntryPoint="cppcms_capi_error")] | |||
public static extern int error(IntPtr obj); | |||
[DllImport(library,EntryPoint="cppcms_capi_error_message")] | |||
public static extern IntPtr error_message(IntPtr obj); | |||
[DllImport(library,EntryPoint="cppcms_capi_error_clear")] | |||
public static extern IntPtr error_clear(IntPtr obj); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_pool_new")] | |||
public static extern IntPtr session_pool_new(); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_pool_delete")] | |||
public static extern void session_pool_delete(IntPtr pool); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_pool_init")] | |||
public static extern int session_pool_init(IntPtr pool,byte[] config_file); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_pool_init_from_json")] | |||
public static extern int session_pool_init_from_json(IntPtr pool,byte[] json); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_new")] | |||
public static extern IntPtr session_new(); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_delete")] | |||
public static extern void session_delete(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_init")] | |||
public static extern int session_init(IntPtr session,IntPtr pool); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_clear")] | |||
public static extern int session_clear(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_is_set")] | |||
public static extern int session_is_set(IntPtr session,byte[] key); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_erase")] | |||
public static extern int session_erase(IntPtr session,byte[] key); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_exposed")] | |||
public static extern int session_get_exposed(IntPtr session,byte[] key); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_exposed")] | |||
public static extern int session_set_exposed(IntPtr session,byte[] key,int is_exposed); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_first_key")] | |||
public static extern IntPtr session_get_first_key(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_next_key")] | |||
public static extern IntPtr session_get_next_key(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_csrf_token")] | |||
public static extern IntPtr session_get_csrf_token(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set")] | |||
public static extern int session_set(IntPtr session,byte[] key,byte[] val); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get")] | |||
public static extern IntPtr session_get(IntPtr session,byte[] key); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_binary_as_hex")] | |||
public static extern int session_set_binary_as_hex(IntPtr session,byte[] key,byte[] val); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_binary_as_hex")] | |||
public static extern IntPtr session_get_binary_as_hex(IntPtr session,byte[] key); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_binary")] | |||
public static extern int session_set_binary(IntPtr session,byte[] key,byte[] val,int length); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_binary")] | |||
public static extern int session_get_binary(IntPtr session,byte[] key,byte[] buf,int buffer_size); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_binary_len")] | |||
public static extern int session_get_binary_len(IntPtr session,byte[] key); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_reset_session")] | |||
public static extern int session_reset_session(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_default_age")] | |||
public static extern int session_set_default_age(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_age")] | |||
public static extern int session_set_age(IntPtr session,int t); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_age")] | |||
public static extern int session_get_age(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_default_expiration")] | |||
public static extern int session_set_default_expiration(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_expiration")] | |||
public static extern int session_set_expiration(IntPtr session,int t); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_expiration")] | |||
public static extern int session_get_expiration(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_set_on_server")] | |||
public static extern int session_set_on_server(IntPtr session,int is_on_server); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_on_server")] | |||
public static extern int session_get_on_server(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_get_session_cookie_name")] | |||
public static extern IntPtr session_get_session_cookie_name(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_load")] | |||
public static extern int session_load(IntPtr session,byte[] session_cookie_value); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_save")] | |||
public static extern int session_save(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_cookie_first")] | |||
public static extern IntPtr session_cookie_first(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_session_cookie_next")] | |||
public static extern IntPtr session_cookie_next(IntPtr session); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_delete")] | |||
public static extern void cookie_delete(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_header")] | |||
public static extern IntPtr cookie_header(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_header_content")] | |||
public static extern IntPtr cookie_header_content(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_name")] | |||
public static extern IntPtr cookie_name(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_value")] | |||
public static extern IntPtr cookie_value(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_path")] | |||
public static extern IntPtr cookie_path(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_domain")] | |||
public static extern IntPtr cookie_domain(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_max_age_defined")] | |||
public static extern int cookie_max_age_defined(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_max_age")] | |||
public static extern uint cookie_max_age(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_expires_defined")] | |||
public static extern int cookie_expires_defined(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_expires")] | |||
public static extern long cookie_expires(IntPtr cookie); | |||
[DllImport(library,EntryPoint="cppcms_capi_cookie_is_secure")] | |||
public static extern int cookie_is_secure(IntPtr cookie); | |||
public static void Main(string[] args) | |||
{ | |||
using(SessionPool pool = SessionPool.FromConfig(args[0])) { | |||
string state = ""; | |||
using(Session session = pool.Session()) { | |||
session.Load(state); | |||
session["x"]="y"; | |||
session["y"]="124"; | |||
session.SetExposed("y",true); | |||
foreach(string k in session.Keys) { | |||
Console.WriteLine("Got Key " + k); | |||
} | |||
session.Save(); | |||
foreach(Cookie c in session.Cookies) { | |||
if(c.Name == session.SessionCookieName) | |||
state = c.Value; | |||
Console.WriteLine("Got Cookie " + c); | |||
} | |||
} | |||
using(Session session = pool.Session()) { | |||
session.Load(state); | |||
session.SetExposed("y",false); | |||
session.Save(); | |||
foreach(Cookie c in session.Cookies) { | |||
if(c.Name == session.SessionCookieName) | |||
state = c.Value; | |||
Console.WriteLine("Got Cookie " + c); | |||
} | |||
foreach(HttpCookie c in session.HttpCookies) { | |||
Console.WriteLine("Got HttpCookie " + c.Name + " expires at " + c.Expires ); | |||
} | |||
} | |||
} | |||
Console.WriteLine("Ok"); | |||
} | |||
} // class | |||
} // namespace |
@@ -0,0 +1,43 @@ | |||
using System; | |||
using System.Runtime.InteropServices; | |||
namespace CppCMS.Session { | |||
public class Cookie { | |||
public readonly string Header; | |||
public readonly string Name; | |||
public readonly string Value; | |||
public readonly string Domain; | |||
public readonly string Path; | |||
public readonly string HeaderContent; | |||
public readonly bool MaxAgeDefined; | |||
public readonly bool ExpiresDefined; | |||
public readonly bool Secure; | |||
public readonly uint MaxAge; | |||
public readonly long Expires; | |||
private static String ts(IntPtr p) | |||
{ | |||
return SessionBase.ts(p); | |||
} | |||
internal Cookie(IntPtr d) | |||
{ | |||
Header = ts(API.cookie_header(d)); | |||
Name = ts(API.cookie_name(d)); | |||
Value = ts(API.cookie_value(d)); | |||
Domain = ts(API.cookie_domain(d)); | |||
Path = ts(API.cookie_path(d)); | |||
HeaderContent = ts(API.cookie_header_content(d)); | |||
MaxAgeDefined = API.cookie_max_age_defined(d)!=0; | |||
ExpiresDefined = API.cookie_expires_defined(d)!=0; | |||
Secure = API.cookie_is_secure(d)!=0; | |||
MaxAge = API.cookie_max_age(d); | |||
Expires = API.cookie_expires(d); | |||
} | |||
public override string ToString() | |||
{ | |||
return this.Header; | |||
} | |||
} // class | |||
} // namespcae | |||
@@ -0,0 +1,162 @@ | |||
using System; | |||
using System.Collections; | |||
using System.Runtime.InteropServices; | |||
using System.Web; | |||
namespace CppCMS.Session { | |||
public class Session : SessionBase { | |||
public const int SESSION_FIXED=0; | |||
public const int SESSION_RENEW=1; | |||
public const int SESSION_BROWSER=2; | |||
internal Session(SessionPool pool) | |||
{ | |||
d=API.session_new(); | |||
API.session_init(d,pool.d); | |||
try { | |||
check(); | |||
} | |||
catch(Exception) { | |||
Close(); | |||
throw; | |||
} | |||
} | |||
override public void Close() | |||
{ | |||
if(d!=IntPtr.Zero) { | |||
API.session_delete(d); | |||
d=IntPtr.Zero; | |||
} | |||
} | |||
public void Clear() { API.session_clear(d); check(); } | |||
public bool IsSet(string key) { bool r = API.session_is_set(d,tb(key))!=0; check(); return r; } | |||
public void Erase(string key) { API.session_erase(d,tb(key)); check(); } | |||
public bool GetExposed(string key) { bool r = API.session_get_exposed(d,tb(key))!=0; check(); return r; } | |||
public void SetExposed(string key,bool v) { API.session_set_exposed(d,tb(key),v?1:0); check(); } | |||
public string[] Keys { | |||
get { | |||
ArrayList a=new ArrayList(); | |||
string s=ts(API.session_get_first_key(d)); | |||
while(s!=null) { | |||
a.Add(s); | |||
s=ts(API.session_get_next_key(d)); | |||
} | |||
check(); | |||
return (string[])a.ToArray(typeof(string)); | |||
} | |||
} | |||
public string CSRFToken { get { string r=ts(API.session_get_csrf_token(d)); check(); return r; } } | |||
public void Set(string key,string val) { API.session_set(d,tb(key),tb(val)); check(); } | |||
public string Get(string key) { string r = ts(API.session_get(d,tb(key))); check(); return r; } | |||
public string this[string key] { | |||
get { return Get(key); } | |||
set { Set(key,value); } | |||
} | |||
public void SetBinary(string key,byte[] val) { API.session_set_binary(d,tb(key),val,val.Length); check(); } | |||
public byte[] GetBinary(string key) { | |||
byte[] bkey = tb(key); | |||
int len = API.session_get_binary_len(d,bkey); | |||
check(); | |||
byte[] res = new byte[len]; | |||
API.session_get_binary(d,bkey,res,len); | |||
check(); | |||
return res; | |||
} | |||
public void ResetSession() { API.session_reset_session(d); check(); } | |||
public void SetDefaultAge() { API.session_set_default_age(d); check(); } | |||
public int Age { | |||
set { API.session_set_age(d,value); check(); } | |||
get { int r = API.session_get_age(d); check(); return r; } | |||
} | |||
public void SetDefaultExpiration() { API.session_set_default_expiration(d); check(); } | |||
public int Expiration { | |||
set { API.session_set_expiration(d,value); check(); } | |||
get { int r = API.session_get_expiration(d); check(); return r; } | |||
} | |||
public bool OnServer { | |||
set { API.session_set_on_server(d,value ? 1 : 0); check(); } | |||
get { bool r = API.session_get_on_server(d)!=0; check(); return r; } | |||
} | |||
public string SessionCookieName { | |||
get { string r=ts(API.session_get_session_cookie_name(d)); check(); return r; } | |||
} | |||
public void Load(String cookie) { API.session_load(d,tb(cookie)); check(); } | |||
public void Load(HttpRequest r) | |||
{ | |||
HttpCookie c=r.Cookies[SessionCookieName]; | |||
if(c==null) | |||
Load(""); | |||
else | |||
Load(c.Value); | |||
} | |||
public void Save() { API.session_save(d); check(); } | |||
public Cookie[] Cookies { | |||
get { | |||
ArrayList a=new ArrayList(); | |||
IntPtr cookie = API.session_cookie_first(d); | |||
while(cookie!=IntPtr.Zero) { | |||
a.Add(new Cookie(cookie)); | |||
API.cookie_delete(cookie); | |||
cookie = API.session_cookie_next(d); | |||
} | |||
check(); | |||
return (Cookie[])a.ToArray(typeof(Cookie)); | |||
} | |||
} | |||
public HttpCookie[] HttpCookies { | |||
get { | |||
Cookie[] ccs = Cookies; | |||
HttpCookie[] hcs = new HttpCookie[ccs.Length]; | |||
for(int i=0;i<ccs.Length;i++) { | |||
Cookie cc =ccs[i]; | |||
HttpCookie hc = new HttpCookie(cc.Name,cc.Value); | |||
if(cc.Path!="") | |||
hc.Path = cc.Path; | |||
if(cc.Domain!="") | |||
hc.Domain = cc.Domain; | |||
hc.Secure = cc.Secure; | |||
if(cc.MaxAgeDefined || cc.ExpiresDefined) { | |||
DateTime dt; | |||
if(cc.ExpiresDefined) { | |||
dt = new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc); | |||
dt = dt.AddSeconds(cc.Expires); | |||
} | |||
else { | |||
if(cc.MaxAge == 0) | |||
dt = new DateTime(1970,1,1,0,0,1,DateTimeKind.Utc); | |||
else | |||
dt = DateTime.UtcNow.AddSeconds(cc.MaxAge); | |||
} | |||
hc.Expires = dt; | |||
} | |||
hcs[i]=hc; | |||
} | |||
return hcs; | |||
} | |||
} | |||
public void Save(HttpResponse r) | |||
{ | |||
Save(); | |||
IntPtr cookie = IntPtr.Zero; | |||
try { | |||
cookie = API.session_cookie_first(d); | |||
while(cookie!=IntPtr.Zero) { | |||
string val = ts(API.cookie_header_content(cookie)); | |||
API.cookie_delete(cookie); | |||
cookie=IntPtr.Zero; | |||
r.AppendHeader("Set-Cookie",val); | |||
cookie = API.session_cookie_next(d); | |||
} | |||
check(); | |||
} | |||
finally { | |||
if(cookie != IntPtr.Zero) | |||
API.cookie_delete(cookie); | |||
} | |||
} | |||
} // class | |||
} // namespace |
@@ -0,0 +1,57 @@ | |||
using System; | |||
using System.Text; | |||
using System.Runtime.InteropServices; | |||
namespace CppCMS.Session { | |||
abstract public class SessionBase : IDisposable { | |||
internal IntPtr d = IntPtr.Zero; | |||
abstract public void Close(); | |||
public void Dispose() | |||
{ | |||
Close(); | |||
} | |||
~SessionBase() | |||
{ | |||
Close(); | |||
} | |||
internal static byte[] tb(string s) | |||
{ | |||
if(s==null) | |||
return null; | |||
return Encoding.UTF8.GetBytes(s + "\0"); | |||
} | |||
internal static string ts(IntPtr p) | |||
{ | |||
if(p==IntPtr.Zero) | |||
return null; | |||
int len = 0; | |||
while(Marshal.ReadByte(p,len)!=0) | |||
len++; | |||
byte[] tmp = new byte[len]; | |||
Marshal.Copy(p,tmp,0,len); | |||
return Encoding.UTF8.GetString(tmp); | |||
} | |||
protected void check() | |||
{ | |||
int code = API.error(d); | |||
if(code == 0) | |||
return; | |||
string msg = ts(API.error_clear(d)); | |||
switch(code) { | |||
case API.ERROR_ALLOC: | |||
throw new OutOfMemoryException(msg); | |||
case API.ERROR_INVALID_ARGUMENT: | |||
throw new ArgumentException(msg); | |||
case API.ERROR_LOGIC: | |||
throw new InvalidOperationException(msg); | |||
default: | |||
throw new SystemException(msg); | |||
} | |||
} | |||
} // class | |||
} // namespace |
@@ -0,0 +1,35 @@ | |||
using System; | |||
namespace CppCMS.Session { | |||
public class SessionPool : SessionBase { | |||
private SessionPool() | |||
{ | |||
d=API.session_pool_new(); | |||
} | |||
override public void Close() | |||
{ | |||
if(d!=IntPtr.Zero) { | |||
API.session_pool_delete(d); | |||
d=IntPtr.Zero; | |||
} | |||
} | |||
public static SessionPool FromConfig(string path) | |||
{ | |||
SessionPool p = new SessionPool(); | |||
API.session_pool_init(p.d,tb(path)); | |||
p.check(); | |||
return p; | |||
} | |||
public static SessionPool FromJSON(string json) | |||
{ | |||
SessionPool p = new SessionPool(); | |||
API.session_pool_init_from_json(p.d,tb(json)); | |||
p.check(); | |||
return p; | |||
} | |||
public Session Session() | |||
{ | |||
return new Session(this); | |||
} | |||
} | |||
} // namespace | |||
@@ -0,0 +1,7 @@ | |||
<%@ Page Language="C#" Inherits="Example" CodeFile="example.aspx.cs" %> | |||
<html> | |||
<body> | |||
<p>Session Counter = <%=counter%></p> | |||
</body> | |||
</html> |
@@ -0,0 +1,23 @@ | |||
using System; | |||
using System.Web.UI; | |||
using CppCMS.Session; | |||
public partial class Example : Page { | |||
static SessionPool pool; | |||
static Example() { | |||
pool = SessionPool.FromConfig("cppcms-config.js"); | |||
} | |||
protected string counter = null; | |||
protected void Page_Load(object sender,EventArgs e) | |||
{ | |||
using(Session s = pool.Session()) { | |||
s.Load(Request); | |||
string v="0"; | |||
if(s.IsSet("x")) | |||
v=s["x"]; | |||
v = (int.Parse(v) + 1).ToString(); | |||
s["x"]=v; | |||
s.Save(Response); | |||
counter = v; | |||
} | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
#!/bin/bash | |||
parsed() | |||
{ | |||
grep -E '(CPPCMS_API|define.*[0-9])' "$1" | \ | |||
sed 's/char const \*\([a-z_]*\)\([,\)]\)/string \1\2/g' | \ | |||
sed 's/char const \*cppcms/IntPtr cppcms/g' | \ | |||
sed 's/const//' | \ | |||
sed 's/void *\*\([a-z_]*\)\([,\)]\)/byte[] \1\2/g' | \ | |||
sed 's/int *\([a-z_]*\)\([,)]\)/int \1\2/g' | \ | |||
sed 's/cppcms_capi[a-z_]* *\*\([a-z_]*\)\([,\)]\)/pointer \1\2/g' | \ | |||
sed 's/cppcms_capi[a-z_]* *\*cppcms_capi/pointer cppcms_capi/g' | \ | |||
sed 's/cppcms_capi_object *\([a-zA-Z_]*\)/pointer \1/g' | \ | |||
sed 's/CPPCMS_API //' | \ | |||
sed 's/long long/llong/g' | \ | |||
sed 's/\t/ /g' | \ | |||
sed 's/ / /g' | |||
} | |||
FILE=$1 | |||
if [ "$FILE" == "" ] | |||
then | |||
FILE=../../../../cppcms/capi/session.h | |||
fi | |||
parsed $FILE \ | |||
| sed 's/pointer/IntPtr/g' \ | |||
| sed 's/string/byte[] /g' \ | |||
| sed 's/llong/long/g' \ | |||
| sed 's/int/int/g' \ | |||
| sed 's/\([^_]\)value/\1val/g' \ | |||
| sed 's/unsigned/uint/g' \ | |||
| sed 's/#define *CPPCMS_CAPI_\([a-zA-Z0-9_]*\) *\([0-9\-]*\)/\ public const int \1=\2;/' \ | |||
| sed 's/\([a-zA-Z_][a-zA-Z_]*\) *cppcms_capi_\([a-z_][a-z_]*\)(\(.*\));/ [DllImport(library,EntryPoint="cppcms_capi_\2")]\n public static extern \1 \2(\3);\n/' >API.cs |