mirror of https://github.com/adamdruppe/arsd.git
so much amazing stuff
This commit is contained in:
parent
4953cba8fa
commit
03315adfa6
42
cgi.d
42
cgi.d
|
@ -2746,9 +2746,28 @@ struct Uri {
|
|||
}
|
||||
}
|
||||
|
||||
n.removeDots();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void removeDots() {
|
||||
auto parts = this.path.split("/");
|
||||
string[] toKeep;
|
||||
foreach(part; parts) {
|
||||
if(part == ".") {
|
||||
continue;
|
||||
} else if(part == "..") {
|
||||
toKeep = toKeep[0 .. $-1];
|
||||
continue;
|
||||
} else {
|
||||
toKeep ~= part;
|
||||
}
|
||||
}
|
||||
|
||||
this.path = toKeep.join("/");
|
||||
}
|
||||
|
||||
unittest {
|
||||
auto uri = Uri("test.html");
|
||||
assert(uri.path == "test.html");
|
||||
|
@ -2810,6 +2829,10 @@ struct Uri {
|
|||
assert(url.basedOn(Uri("http://test.com/what/test.html?a=b&c=d#what")) == "http://test.com/what/test.html?query=answer");
|
||||
assert(url.basedOn(Uri("http://test.com")) == "http://test.com?query=answer");
|
||||
|
||||
url = Uri("/test/bar");
|
||||
assert(Uri("./").basedOn(url) == "/test/", Uri("./").basedOn(url));
|
||||
assert(Uri("../").basedOn(url) == "/");
|
||||
|
||||
//auto uriBefore = url;
|
||||
url = Uri("#anchor"); // everything should remain the same except the anchor
|
||||
//uriBefore.anchor = "anchor");
|
||||
|
@ -6458,16 +6481,22 @@ auto callFromCgi(alias method, T)(T dg, Cgi cgi) {
|
|||
auto ident = idents[idx];
|
||||
if(cgi.requestMethod == Cgi.RequestMethod.GET) {
|
||||
if(ident !in cgi.get) {
|
||||
static if(is(defaults[idx] == void))
|
||||
throw new MissingArgumentException(__traits(identifier, method), ident, param.stringof);
|
||||
static if(is(defaults[idx] == void)) {
|
||||
static if(is(param == bool))
|
||||
params[idx] = false;
|
||||
else
|
||||
throw new MissingArgumentException(__traits(identifier, method), ident, param.stringof);
|
||||
} else
|
||||
params[idx] = defaults[idx];
|
||||
}
|
||||
} else {
|
||||
if(ident !in cgi.post) {
|
||||
static if(is(defaults[idx] == void))
|
||||
throw new MissingArgumentException(__traits(identifier, method), ident, param.stringof);
|
||||
static if(is(defaults[idx] == void)) {
|
||||
static if(is(param == bool))
|
||||
params[idx] = false;
|
||||
else
|
||||
throw new MissingArgumentException(__traits(identifier, method), ident, param.stringof);
|
||||
} else
|
||||
params[idx] = defaults[idx];
|
||||
}
|
||||
}
|
||||
|
@ -6510,6 +6539,9 @@ auto callFromCgi(alias method, T)(T dg, Cgi cgi) {
|
|||
} else static if(isSomeString!T || isIntegral!T || isFloatingPoint!T) {
|
||||
*what = to!T(value);
|
||||
return true;
|
||||
} else static if(is(T == bool)) {
|
||||
*what = value == "1" || value == "yes" || value == "t" || value == "true" || value == "on";
|
||||
return true;
|
||||
} else static if(is(T == K[], K)) {
|
||||
K tmp;
|
||||
if(name == paramName) {
|
||||
|
@ -6552,6 +6584,8 @@ auto callFromCgi(alias method, T)(T dg, Cgi cgi) {
|
|||
|
||||
auto k = to!K(insideBrackets);
|
||||
V v;
|
||||
if(auto ptr = k in *what)
|
||||
v = *ptr;
|
||||
|
||||
name = name[0 .. paramName.length];
|
||||
//writeln(name, afterName, " ", paramName);
|
||||
|
|
13
database.d
13
database.d
|
@ -3,6 +3,7 @@ module arsd.database;
|
|||
|
||||
public import std.variant;
|
||||
import std.string;
|
||||
public import std.datetime;
|
||||
|
||||
/*
|
||||
Database 2.0 plan, WIP:
|
||||
|
@ -48,6 +49,9 @@ interface Database {
|
|||
return queryImpl(sql, args);
|
||||
}
|
||||
|
||||
/// turns a systime into a value understandable by the target database as a timestamp to be concated into a query. so it should be quoted and escaped etc as necessary
|
||||
string sysTimeToValue(SysTime);
|
||||
|
||||
/// Prepared statement api
|
||||
/*
|
||||
PreparedStatement prepareStatement(string sql, int numberOfArguments);
|
||||
|
@ -355,9 +359,14 @@ class SelectBuilder : SqlBuilder {
|
|||
// used in the internal placeholder thing
|
||||
string toSql(Database db, Variant a) {
|
||||
auto v = a.peek!(void*);
|
||||
if(v && (*v is null))
|
||||
if(v && (*v is null)) {
|
||||
return "NULL";
|
||||
else {
|
||||
} else if(auto t = a.peek!(SysTime)) {
|
||||
return db.sysTimeToValue(*t);
|
||||
} else if(auto t = a.peek!(DateTime)) {
|
||||
// FIXME: this might be broken cuz of timezones!
|
||||
return db.sysTimeToValue(cast(SysTime) *t);
|
||||
} else {
|
||||
string str = to!string(a);
|
||||
return '\'' ~ db.escape(str) ~ '\'';
|
||||
}
|
||||
|
|
|
@ -48,10 +48,29 @@ struct Nullable(T) {
|
|||
isNull = false;
|
||||
value = v;
|
||||
}
|
||||
|
||||
T toArsdJsvar() { return value; }
|
||||
}
|
||||
|
||||
struct Timestamp {
|
||||
string value;
|
||||
string toArsdJsvar() { return value; }
|
||||
|
||||
// FIXME: timezone
|
||||
static Timestamp fromStrings(string date, string time) {
|
||||
if(time.length < 6)
|
||||
time ~= ":00";
|
||||
import std.datetime;
|
||||
return Timestamp(SysTime.fromISOExtString(date ~ "T" ~ time).toISOExtString());
|
||||
}
|
||||
}
|
||||
|
||||
SysTime parseDbTimestamp(string s) {
|
||||
if(s.length == 0) return SysTime.init;
|
||||
auto date = s[0 .. 10];
|
||||
auto time = s[11 .. 20];
|
||||
auto tz = s[20 .. $];
|
||||
return SysTime.fromISOExtString(date ~ "T" ~ time ~ tz);
|
||||
}
|
||||
|
||||
struct Constraint(string sql) {}
|
||||
|
@ -61,6 +80,9 @@ struct UniqueIndex(Fields...) {}
|
|||
|
||||
struct Serial {
|
||||
int value;
|
||||
int toArsdJsvar() { return value; }
|
||||
int getValue() { return value; }
|
||||
alias getValue this;
|
||||
}
|
||||
|
||||
|
||||
|
@ -148,6 +170,7 @@ string generateCreateTableFor(alias O)() {
|
|||
|
||||
static foreach(attr; __traits(getAttributes, member)) {
|
||||
static if(is(typeof(attr) == Default)) {
|
||||
// FIXME: postgresism there, try current_timestamp in sqlite
|
||||
sql ~= " DEFAULT " ~ attr.sql;
|
||||
} else static if(is(attr == Unique)) {
|
||||
sql ~= " UNIQUE";
|
||||
|
@ -282,9 +305,11 @@ void insert(O)(ref O t, Database db) {
|
|||
builder.addVariable(memberName, __traits(getMember, t, memberName));
|
||||
else static if(is(T == bool))
|
||||
builder.addVariable(memberName, __traits(getMember, t, memberName));
|
||||
else static if(is(T == Timestamp))
|
||||
{} // skipping... for now at least
|
||||
else static if(is(T == enum))
|
||||
else static if(is(T == Timestamp)) {
|
||||
auto v = __traits(getMember, t, memberName).value;
|
||||
if(v.length)
|
||||
builder.addVariable(memberName, v);
|
||||
} else static if(is(T == enum))
|
||||
builder.addVariable(memberName, cast(int) __traits(getMember, t, memberName));
|
||||
}
|
||||
}}
|
||||
|
|
20
http2.d
20
http2.d
|
@ -514,8 +514,28 @@ struct Uri {
|
|||
}
|
||||
}
|
||||
|
||||
n.removeDots();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void removeDots() {
|
||||
auto parts = this.path.split("/");
|
||||
string[] toKeep;
|
||||
foreach(part; parts) {
|
||||
if(part == ".") {
|
||||
continue;
|
||||
} else if(part == "..") {
|
||||
toKeep = toKeep[0 .. $-1];
|
||||
continue;
|
||||
} else {
|
||||
toKeep ~= part;
|
||||
}
|
||||
}
|
||||
|
||||
this.path = toKeep.join("/");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
5
mssql.d
5
mssql.d
|
@ -49,6 +49,11 @@ class MsSql : Database {
|
|||
query("START TRANSACTION");
|
||||
}
|
||||
|
||||
// possible fixme, idk if this is right
|
||||
override string sysTimeToValue(SysTime s) {
|
||||
return "'" ~ escape(s.toISOExtString()) ~ "'";
|
||||
}
|
||||
|
||||
ResultSet queryImpl(string sql, Variant[] args...) {
|
||||
sql = escapedVariants(this, sql, args);
|
||||
|
||||
|
|
3
mysql.d
3
mysql.d
|
@ -74,6 +74,9 @@ class MySqlResult : ResultSet {
|
|||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
string sysTimeToValue(SysTime s) {
|
||||
return "cast('" ~ escape(s.toISOExtString()) ~ "' as datetime)";
|
||||
}
|
||||
|
||||
MYSQL_FIELD[] fields() {
|
||||
int numFields = mysql_num_fields(result);
|
||||
|
|
|
@ -41,6 +41,10 @@ class PostgreSql : Database {
|
|||
PQfinish(conn);
|
||||
}
|
||||
|
||||
string sysTimeToValue(SysTime s) {
|
||||
return "'" ~ escape(s.toISOExtString()) ~ "'::timestamptz";
|
||||
}
|
||||
|
||||
/**
|
||||
Prepared statement support
|
||||
|
||||
|
|
4
sqlite.d
4
sqlite.d
|
@ -91,6 +91,10 @@ class Sqlite : Database {
|
|||
throw new DatabaseException(error());
|
||||
}
|
||||
|
||||
string sysTimeToValue(SysTime s) {
|
||||
return "datetime('" ~ escape(s.toISOExtString()) ~ "')";
|
||||
}
|
||||
|
||||
// my extension for easier editing
|
||||
version(sqlite_extended_metadata_available) {
|
||||
ResultByDataObject queryDataObject(T...)(string sql, T t) {
|
||||
|
|
|
@ -39,6 +39,30 @@ Document renderTemplate(string templateName, var context = var.emptyObject, var
|
|||
return encodeComponent(f.get!string);
|
||||
};
|
||||
|
||||
context.formatDate = function string(string s) {
|
||||
if(s.length < 10)
|
||||
return s;
|
||||
auto year = s[0 .. 4];
|
||||
auto month = s[5 .. 7];
|
||||
auto day = s[8 .. 10];
|
||||
|
||||
return month ~ "/" ~ day ~ "/" ~ year;
|
||||
};
|
||||
|
||||
context.formatTime = function string(string s) {
|
||||
if(s.length < 20)
|
||||
return s;
|
||||
auto hour = s[11 .. 13].to!int;
|
||||
auto minutes = s[14 .. 16].to!int;
|
||||
auto seconds = s[17 .. 19].to!int;
|
||||
|
||||
auto am = (hour >= 12) ? "PM" : "AM";
|
||||
if(hour > 12)
|
||||
hour -= 12;
|
||||
|
||||
return hour.to!string ~ (minutes < 10 ? ":0" : ":") ~ minutes.to!string ~ " " ~ am;
|
||||
};
|
||||
|
||||
auto skeleton = new Document(readText("templates/skeleton.html"), true, true);
|
||||
auto document = new Document();
|
||||
document.parseSawAspCode = (string) => true; // enable adding <% %> to the dom
|
||||
|
|
Loading…
Reference in New Issue