From 38c604356d2bca55c6cf648ea8dc6321875a3eae Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Thu, 30 May 2013 18:45:26 -0400 Subject: [PATCH] catching up (again) --- cgi.d | 5 +++-- characterencodings.d | 13 +++++++++++++ database.d | 16 +++++++++++++--- oauth.d | 16 +++++++++++++--- web.d | 8 ++++++++ 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/cgi.d b/cgi.d index f6b07c8..fa258a9 100644 --- a/cgi.d +++ b/cgi.d @@ -477,7 +477,8 @@ class Cgi { //if(authorization.length == 0) // if the std is there, use it // authorization = getenv("HTTP_X_AUTHORIZATION"); - if(getenv("SERVER_PORT").length) + // the REDIRECT_HTTPS check is here because with an Apache hack, the port can become wrong + if(getenv("SERVER_PORT").length && getenv("REDIRECT_HTTPS") != "on") port = to!int(getenv("SERVER_PORT")); else port = 0; // this was probably called from the command line @@ -1360,7 +1361,7 @@ class Cgi { return format("http%s://%s%s%s", https ? "s" : "", host, - port == defaultPort ? "" : ":" ~ to!string(port), + (!port || port == defaultPort) ? "" : ":" ~ to!string(port), requestUri); } diff --git a/characterencodings.d b/characterencodings.d index a75e76d..6610320 100644 --- a/characterencodings.d +++ b/characterencodings.d @@ -43,6 +43,19 @@ import std.string; import std.array; import std.conv; +/// Like convertToUtf8, but if the encoding is unknown, it just strips all chars > 127 and calls it done instead of throwing +string convertToUtf8Lossy(immutable(ubyte)[] data, string dataCharacterEncoding) { + try { + return convertToUtf8(data, dataCharacterEncoding); + } catch(Exception e) { + string ret; + foreach(b; data) + if(b < 128) + ret ~= b; + return ret; + } +} + /// Takes data from a given character encoding and returns it as UTF-8 string convertToUtf8(immutable(ubyte)[] data, string dataCharacterEncoding) { // just to normalize the passed string... diff --git a/database.d b/database.d index 718939c..eeabe0c 100644 --- a/database.d +++ b/database.d @@ -473,7 +473,10 @@ int updateOrInsert(Database db, string table, string[string] values, string wher //cs ~= "`" ~ db.escape(column) ~ "`"; cs ~= "`" ~ column ~ "`"; // FIXME: possible insecure - vs ~= "'" ~ db.escape(value) ~ "'"; + if(value is null) + vs ~= "NULL"; + else + vs ~= "'" ~ db.escape(value) ~ "'"; } if(!outputted) @@ -499,7 +502,10 @@ int updateOrInsert(Database db, string table, string[string] values, string wher else outputted = true; - updateSql ~= "`" ~ db.escape(column) ~ "` = '" ~ db.escape(value) ~ "'"; + if(value is null) + updateSql ~= "`" ~ db.escape(column) ~ "` = NULL"; + else + updateSql ~= "`" ~ db.escape(column) ~ "` = '" ~ db.escape(value) ~ "'"; } if(!outputted) @@ -813,7 +819,11 @@ class DataObject { if(where.length) where ~= " AND "; - where ~= keyField ~ " = '"~db.escape(key in fields ? fields[key] : null)~"'" ; + auto f = key in fields ? fields[key] : null; + if(f is null) + where ~= keyField ~ " = NULL"; + else + where ~= keyField ~ " = '"~db.escape(f)~"'" ; if(keyFieldToPass.length) keyFieldToPass ~= ", "; diff --git a/oauth.d b/oauth.d index f6f6167..a5b4a20 100644 --- a/oauth.d +++ b/oauth.d @@ -288,7 +288,7 @@ import std.file; /** Redirects the user to the authorize page on the provider's website. */ -void authorizeStepOne(Cgi cgi, OAuthParams params, string oauthCallback = null) { +void authorizeStepOne(Cgi cgi, OAuthParams params, string oauthCallback = null, string additionalOptions = null, string[string] additionalTokenArgs = null) { if(oauthCallback is null) { oauthCallback = cgi.getCurrentCompleteUri(); if(oauthCallback.indexOf("?") == -1) @@ -301,7 +301,13 @@ void authorizeStepOne(Cgi cgi, OAuthParams params, string oauthCallback = null) if(oauthCallback.length) args["oauth_callback"] = oauthCallback; - auto ret = curlOAuth(params, params.baseUrl ~ params.requestTokenPath, + //foreach(k, v; additionalTokenArgs) + //args[k] = v; + + auto moreArgs = encodeVariables(additionalTokenArgs); + if(moreArgs.length) + moreArgs = "?" ~ moreArgs; + auto ret = curlOAuth(params, params.baseUrl ~ params.requestTokenPath ~ moreArgs, args, "POST", "", ""); auto vals = decodeVariables(ret); @@ -320,7 +326,11 @@ void authorizeStepOne(Cgi cgi, OAuthParams params, string oauthCallback = null) std.file.write("/tmp/oauth-token-secret-" ~ oauth_token, oauth_secret); - cgi.setResponseLocation(params.baseUrl ~ params.authorizePath ~ "?oauth_token=" ~ oauth_token); + // FIXME: make sure this doesn't break twitter etc + if("login_url" in vals) // apparently etsy does it this way... + cgi.setResponseLocation(vals["login_url"][0]); + else + cgi.setResponseLocation(params.baseUrl ~ params.authorizePath ~ "?" ~(additionalOptions.length ? (additionalOptions ~ "&") : "")~ "oauth_token=" ~ oauth_token); } /** diff --git a/web.d b/web.d index 13ab480..8fb6500 100644 --- a/web.d +++ b/web.d @@ -1,5 +1,7 @@ module arsd.web; +// it would be nice to be able to add meta info to a returned envelope + enum RequirePost; enum RequireHttps; enum NoAutomaticForm; @@ -3140,6 +3142,12 @@ class Session { return true; } + void removeKey(string key) { + data.remove(key); + _hasData = true; + changed = true; + } + /// get/set for strings @property string opDispatch(string name)(string v = null) if(name != "popFront") { if(v !is null)