Conflicts:
	database.d
This commit is contained in:
Adam D. Ruppe 2012-11-26 15:55:35 -05:00
commit f2943b90b3
8 changed files with 73 additions and 22 deletions

22
cgi.d
View File

@ -310,7 +310,8 @@ class Cgi {
else else
requestMethod = RequestMethod.CommandLine; requestMethod = RequestMethod.CommandLine;
https = getenv("HTTPS") == "on"; // FIXME: hack on REDIRECT_HTTPS; this is there because the work app uses mod_rewrite which loses the https flag! So I set it with [E=HTTPS=%HTTPS] or whatever but then it gets translated to here so i want it to still work. This is arguably wrong but meh.
https = (getenv("HTTPS") == "on" || getenv("REDIRECT_HTTPS") == "on");
// FIXME: DOCUMENT_ROOT? // FIXME: DOCUMENT_ROOT?
@ -480,6 +481,15 @@ class Cgi {
bool contentInMemory = true; // the default ought to always be true bool contentInMemory = true; // the default ought to always be true
immutable(ubyte)[] content; /// The actual content of the file, if contentInMemory == true immutable(ubyte)[] content; /// The actual content of the file, if contentInMemory == true
string contentFilename; /// the file where we dumped the content, if contentInMemory == false. Note that if you want to keep it, you MUST move the file, since otherwise it is considered garbage when cgi is disposed. string contentFilename; /// the file where we dumped the content, if contentInMemory == false. Note that if you want to keep it, you MUST move the file, since otherwise it is considered garbage when cgi is disposed.
void writeToFile(string filenameToSaveTo) {
import std.file;
if(contentInMemory)
std.file.write(filenameToSaveTo, content);
else
std.file.rename(contentFilename, filenameToSaveTo);
}
} }
// given a content type and length, decide what we're going to do with the data.. // given a content type and length, decide what we're going to do with the data..
@ -633,8 +643,9 @@ class Cgi {
// here, we should be lined up right at the boundary, which is followed by a \r\n // here, we should be lined up right at the boundary, which is followed by a \r\n
// want to keep the buffer under control in case we're under attack // want to keep the buffer under control in case we're under attack
if(pps.buffer.length + chunk.length > 70 * 1024) // they should be < 1 kb really.... //stderr.writeln("here once");
throw new Exception("wtf is up with the huge mime part headers"); //if(pps.buffer.length + chunk.length > 70 * 1024) // they should be < 1 kb really....
// throw new Exception("wtf is up with the huge mime part headers");
acceptChunk(); acceptChunk();
@ -1157,6 +1168,11 @@ class Cgi {
requestUri); requestUri);
} }
/// You can override this if your site base url isn't the same as the script name
string logicalScriptName() const {
return scriptName;
}
/// Sets the HTTP status of the response. For example, "404 File Not Found" or "500 Internal Server Error". /// Sets the HTTP status of the response. For example, "404 File Not Found" or "500 Internal Server Error".
/// It assumes "200 OK", and automatically changes to "302 Found" if you call setResponseLocation(). /// It assumes "200 OK", and automatically changes to "302 Found" if you call setResponseLocation().
/// Note setResponseStatus() must be called *before* you write() any data to the output. /// Note setResponseStatus() must be called *before* you write() any data to the output.

View File

@ -41,7 +41,7 @@ interface Database {
a = to!string(e); a = to!string(e);
} else if (arg == typeid(null)) { } else if (arg == typeid(null)) {
a = null; a = null;
} else assert(0, "invalid type " ~ arg.toString ); } else assert(0, "invalid type " ~ arg.toString() );
args ~= Variant(a); args ~= Variant(a);
} }
@ -117,7 +117,7 @@ struct Row {
} }
int opApply(int delegate(ref string, ref string) dg) { int opApply(int delegate(ref string, ref string) dg) {
foreach(a, b; toAA) foreach(a, b; toAA())
mixin(yield("a, b")); mixin(yield("a, b"));
return 0; return 0;
@ -137,10 +137,10 @@ interface ResultSet {
string[] fieldNames(); string[] fieldNames();
// this is a range that can offer other ranges to access it // this is a range that can offer other ranges to access it
bool empty(); bool empty() @property;
Row front(); Row front() @property;
void popFront(); void popFront() ;
int length(); int length() @property;
/* deprecated */ final ResultSet byAssoc() { return this; } /* deprecated */ final ResultSet byAssoc() { return this; }
} }
@ -181,7 +181,7 @@ class SelectBuilder : SqlBuilder {
return s; return s;
} }
string toString() { override string toString() {
string sql = "SELECT "; string sql = "SELECT ";
// the fields first // the fields first
@ -460,7 +460,7 @@ string fixupSqlForDataObjectUse(string sql, string[string] keyMapping = null) {
auto from = sql[start..i]; auto from = sql[start..i];
auto pieces = from.split(","); auto pieces = from.split(",");
foreach(p; pieces) { foreach(p; pieces) {
p = p.strip; p = p.strip();
start = 0; start = 0;
i = 0; i = 0;
while(i < p.length && p[i] != ' ' && p[i] != '\n' && p[i] != '\t' && p[i] != ',') while(i < p.length && p[i] != ' ' && p[i] != '\n' && p[i] != '\t' && p[i] != ',')

13
dom.d
View File

@ -3414,14 +3414,23 @@ class Document : FileResource {
pos++; pos++;
pos++; // skip the > pos++; // skip the >
break; break;
// case '%':
case '?': case '?':
char end = data[pos]; char end = data[pos];
// FIXME this is all kinda broken
more: more:
pos++; // skip the start pos++; // skip the start
while(data[pos] != end)
while(data[pos] != end) {
// FIXME: what if it is PHP?
if(data[pos] == '>')
break; // I've seen this in the wild: <?EM-dummyText>
pos++; pos++;
pos++; // skip the end }
if(data[pos] == end)
pos++; // skip the end
// FIXME: we should actually store this somewhere // FIXME: we should actually store this somewhere
// though I like having it stripped out as well tbh. // though I like having it stripped out as well tbh.

17
html.d
View File

@ -230,6 +230,21 @@ Html linkify(string text) {
return Html(div.innerHTML); return Html(div.innerHTML);
} }
Html nl2br(string text) {
auto div = Element.make("div");
bool first = true;
foreach(line; splitLines(text)) {
if(!first)
div.addChild("br");
else
first = false;
div.appendText(line);
}
return Html(div.innerHTML);
}
/// Returns true of the string appears to be html/xml - if it matches the pattern /// Returns true of the string appears to be html/xml - if it matches the pattern
/// for tags or entities. /// for tags or entities.
bool appearsToBeHtml(string src) { bool appearsToBeHtml(string src) {
@ -640,7 +655,7 @@ void translateInputTitles(Document document) {
void translateInputTitles(Element rootElement) { void translateInputTitles(Element rootElement) {
foreach(form; rootElement.getElementsByTagName("form")) { foreach(form; rootElement.getElementsByTagName("form")) {
string os; string os;
foreach(e; form.getElementsBySelector("input[type=text][title], textarea[title]")) { foreach(e; form.getElementsBySelector("input[type=text][title], input[type=email][title], textarea[title]")) {
if(e.hasClass("has-placeholder")) if(e.hasClass("has-placeholder"))
continue; continue;
e.addClass("has-placeholder"); e.addClass("has-placeholder");

10
oauth.d
View File

@ -35,7 +35,7 @@ import std.md5;
import std.file; import std.file;
Variant[string] postToFacebookWall(string[] info, string id, string message, string picture = null, string link = null) { Variant[string] postToFacebookWall(string[] info, string id, string message, string picture = null, string link = null, long when = 0) {
string url = "https://graph.facebook.com/" ~ id ~ "/feed"; string url = "https://graph.facebook.com/" ~ id ~ "/feed";
@ -46,6 +46,8 @@ Variant[string] postToFacebookWall(string[] info, string id, string message, str
data ~= "&picture=" ~ std.uri.encodeComponent(picture); data ~= "&picture=" ~ std.uri.encodeComponent(picture);
if(link !is null && link.length) if(link !is null && link.length)
data ~= "&link=" ~ std.uri.encodeComponent(link); data ~= "&link=" ~ std.uri.encodeComponent(link);
if(when)
data ~= "&scheduled_publish_time=" ~ to!string(when);
auto response = curl(url, data); auto response = curl(url, data);
@ -271,6 +273,8 @@ string tweet(OAuthParams params, string oauthToken, string tokenSecret, string m
auto ret = curlOAuth(params, "http://api.twitter.com" ~ "/1/statuses/update.json", args, "POST", data); auto ret = curlOAuth(params, "http://api.twitter.com" ~ "/1/statuses/update.json", args, "POST", data);
auto val = jsonToVariant(ret).get!(Variant[string]); auto val = jsonToVariant(ret).get!(Variant[string]);
if("id_str" !in val)
throw new Exception("bad result from twitter: " ~ ret);
return val["id_str"].get!string; return val["id_str"].get!string;
} }
@ -317,7 +321,7 @@ void authorizeStepOne(Cgi cgi, OAuthParams params, string oauthCallback = null)
Gets the final token, given the stuff from step one. This should be called Gets the final token, given the stuff from step one. This should be called
from the callback in step one. from the callback in step one.
Returns [token, secret] Returns [token, secret, raw original data (for extended processing - twitter also sends the screen_name and user_id there)]
*/ */
string[] authorizeStepTwo(const(Cgi) cgi, OAuthParams params) { string[] authorizeStepTwo(const(Cgi) cgi, OAuthParams params) {
if("oauth_problem" in cgi.get) if("oauth_problem" in cgi.get)
@ -339,7 +343,7 @@ string[] authorizeStepTwo(const(Cgi) cgi, OAuthParams params) {
auto vars = decodeVariables(ret); auto vars = decodeVariables(ret);
return [vars["oauth_token"][0], vars["oauth_token_secret"][0]]; return [vars["oauth_token"][0], vars["oauth_token_secret"][0], ret];
} }

View File

@ -84,7 +84,7 @@ class PostgresResult : ResultSet {
void popFront() { void popFront() {
position++; position++;
if(position < numRows) if(position < numRows)
fetchNext; fetchNext();
} }
int length() { int length() {

11
rtud.d
View File

@ -297,9 +297,11 @@ Message[] parseMessages(string wegot, string eventTypeFilter = null) {
switch(name) { switch(name) {
default: break; // do nothing default: break; // do nothing
case "timestamp": case "timestamp":
if(data.length)
m.timestamp = to!long(data); m.timestamp = to!long(data);
break; break;
case "ttl": case "ttl":
if(data.length)
m.ttl = to!long(data); m.ttl = to!long(data);
break; break;
case "operation": case "operation":
@ -448,7 +450,7 @@ class NotificationConnection : RtudConnection {
auto bm = sort!"a.timestamp < b.timestamp"(backMessages); auto bm = sort!"a.timestamp < b.timestamp"(backMessages);
backMessages = array(find!("a.timestamp > b")(bm, to!long(message["minimum-time"][$-1]))); backMessages = array(find!("a.timestamp >= b")(bm, to!long(message["minimum-time"][$-1])));
} }
if("close-time" in message) if("close-time" in message)
@ -474,8 +476,11 @@ class DataConnection : RtudConnection {
override void handleMessage(string[][string] message) { override void handleMessage(string[][string] message) {
string getStr(string key, string def) { string getStr(string key, string def) {
if(key in message) if(key in message) {
return message[key][$ - 1]; auto s = message[key][$ - 1];
if(s.length)
return s;
}
return def; return def;
} }

View File

@ -403,8 +403,10 @@ class LocalWebDotDApiProvider extends WebDotDApiProvider {
// The full session ID tells it what to use, and the file hash proves // The full session ID tells it what to use, and the file hash proves
// to D that we already have access to it. // to D that we already have access to it.
$magic = $this->session->sessionId . ";" . $this->session->fileHash; $magic = $this->session->sessionId . ";" . $this->session->fileHash;
$headers = array("X-Arsd-Local: yes");
if(strlen($magic) > 0) if(strlen($magic) > 0)
curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-Arsd-Session-Override: $magic")); $headers[] = "X-Arsd-Session-Override: $magic";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
} }
} }