selector bugs

This commit is contained in:
Adam D. Ruppe 2016-02-27 13:20:02 -05:00
parent 0e2017e83a
commit c713cd6b63
30 changed files with 284 additions and 89 deletions

1
bmp.d
View File

@ -1,3 +1,4 @@
/// bmp impl for MemoryImage
module arsd.bmp;
import arsd.color;

46
cgi.d
View File

@ -27,16 +27,22 @@
mixin GenericMain!hello;
---
Compile_and_run:
For CGI, `dmd yourfile.d cgi.d` then put the executable in your cgi-bin directory.
For FastCGI: `dmd yourfile.d cgi.d -version=fastcgi` and run it. spawn-fcgi helps on nginx. You can put the file in the directory for Apache. On IIS, run it with a port on the command line.
For SCGI: `dmd yourfile.d cgi.d -version=scgi` and run the executable, providing a port number on the command line.
For an embedded HTTP server, run `dmd yourfile.d cgi.d -version=embedded_httpd` and run the generated program. It listens on port 8085 by default. You can change this on the command line with the --port option when running your program.
You can also simulate a request by passing parameters on the command line, like:
```console
./yourprogram GET / name=adr
```
And it will print the result to stdout.
@ -103,32 +109,43 @@
---
Concepts:
Input: get, post, request(), files, cookies, pathInfo, requestMethod, and HTTP headers (headers, userAgent, referrer, accept, authorization, lastEventId
Output: cgi.write(), cgi.header(), cgi.setResponseStatus, cgi.setResponseContentType, gzipResponse
Cookies: setCookie, clearCookie, cookie, cookies
Caching: cgi.setResponseExpires, cgi.updateResponseExpires, cgi.setCache
Redirections: cgi.setResponseLocation
Other Information: remoteAddress, https, port, scriptName, requestUri, getCurrentCompleteUri, onRequestBodyDataReceived
Overriding behavior: handleIncomingDataChunk, prepareForIncomingDataChunks, cleanUpPostDataState
Input: [Cgi.get], [Cgi.post], [Cgi.request], [Cgi.files], [Cgi.cookies], [Cgi.pathInfo], [Cgi.requestMethod],
and HTTP headers ([Cgi.headers], [Cgi.userAgent], [Cgi.referrer], [Cgi.accept], [Cgi.authorization], [Cgi.lastEventId]
Output: [Cgi.write], [Cgi.header], [Cgi.setResponseStatus], [Cgi.setResponseContentType], [Cgi.gzipResponse]
Cookies: [Cgi.setCookie], [Cgi.clearCookie], [Cgi.cookie], [Cgi.cookies]
Caching: [Cgi.setResponseExpires], [Cgi.updateResponseExpires], [Cgi.setCache]
Redirections: [Cgi.setResponseLocation]
Other Information: [Cgi.remoteAddress], [Cgi.https], [Cgi.port], [Cgi.scriptName], [Cgi.requestUri], [Cgi.getCurrentCompleteUri], [Cgi.onRequestBodyDataReceived]
Overriding behavior: [Cgi.handleIncomingDataChunk], [Cgi.prepareForIncomingDataChunks], [Cgi.cleanUpPostDataState]
Installing: Apache, IIS, CGI, FastCGI, SCGI, embedded HTTPD (not recommended for production use)
Guide_for_PHP_users:
If you are coming from PHP, here's a quick guide to help you get started:
```
$_GET["var"] == cgi.get["var"]
$_POST["var"] == cgi.post["var"]
$_COOKIE["var"] == cgi.cookies["var"]
```
In PHP, you can give a form element a name like "something[]", and then
$_POST["something"] gives an array. In D, you can use whatever name
you want, and access an array of values with the cgi.getArray["name"] and
cgi.postArray["name"] members.
In PHP, you can give a form element a name like `"something[]"`, and then
`$_POST["something"]` gives an array. In D, you can use whatever name
you want, and access an array of values with the `cgi.getArray["name"]` and
`cgi.postArray["name"]` members.
```
echo("hello"); == cgi.write("hello");
$_SERVER["REMOTE_ADDR"] == cgi.remoteAddress
$_SERVER["HTTP_HOST"] == cgi.host
```
See_Also:
@ -140,9 +157,9 @@
Copyright:
cgi.d copyright 2008-2015, Adam D. Ruppe. Provided under the Boost Software License.
cgi.d copyright 2008-2016, Adam D. Ruppe. Provided under the Boost Software License.
Yes, this file is seven years old, and yes, it is still actively maintained and used.
Yes, this file is almost eight years old, and yes, it is still actively maintained and used.
+/
module arsd.cgi;
@ -3107,6 +3124,7 @@ import std.socket;
// it is a class primarily for reference semantics
// I might change this interface
///
class BufferedInputRange {
version(Posix)
this(int source, ubyte[] buffer = null) {
@ -3644,6 +3662,7 @@ version(cgi_with_websocket) {
WEBSOCKET SUPPORT:
Full example:
---
import arsd.cgi;
void websocketEcho(Cgi cgi) {
@ -3671,6 +3690,7 @@ version(cgi_with_websocket) {
}
mixin GenericMain!websocketEcho;
---
*/
class WebSocket {

6
cidr.d
View File

@ -1,3 +1,7 @@
///
module cidr;
///
uint addressToUint(string address) {
import std.algorithm.iteration, std.conv;
@ -12,6 +16,7 @@ uint addressToUint(string address) {
return result;
}
///
string uintToAddress(uint addr) {
import std.conv;
string res;
@ -26,6 +31,7 @@ string uintToAddress(uint addr) {
return res;
}
///
struct IPv4Block {
this(string cidr) {
import std.algorithm.searching, std.conv;

33
color.d
View File

@ -1,3 +1,4 @@
///
module arsd.color;
@safe:
@ -114,7 +115,7 @@ private {
/// Represents an RGBA color
struct Color {
union {
ubyte[4] components;
ubyte[4] components; ///
struct {
ubyte r; /// red
@ -123,7 +124,7 @@ struct Color {
ubyte a; /// alpha. 255 == opaque
}
uint asUint;
uint asUint; ///
}
// this makes sure they are in range before casting
@ -518,25 +519,28 @@ Color setLightness(Color c, real lightness) {
}
///
Color rotateHue(Color c, real degrees) {
auto hsl = toHsl(c);
hsl[0] += degrees;
return fromHsl(hsl);
}
///
Color setHue(Color c, real hue) {
auto hsl = toHsl(c);
hsl[0] = hue;
return fromHsl(hsl);
}
///
Color desaturate(Color c, real percentage) {
auto hsl = toHsl(c);
hsl[1] *= (1 - percentage);
return fromHsl(hsl);
}
///
Color saturate(Color c, real percentage) {
auto hsl = toHsl(c);
hsl[1] *= (1 + percentage);
@ -545,6 +549,7 @@ Color saturate(Color c, real percentage) {
return fromHsl(hsl);
}
///
Color setSaturation(Color c, real saturation) {
auto hsl = toHsl(c);
hsl[1] = saturation;
@ -592,6 +597,7 @@ So, given the background color and the resultant color, what was
composited on to it?
*/
///
ubyte unalpha(ubyte colorYouHave, float alpha, ubyte backgroundColor) {
// resultingColor = (1-alpha) * backgroundColor + alpha * answer
auto resultingColorf = cast(float) colorYouHave;
@ -605,6 +611,7 @@ ubyte unalpha(ubyte colorYouHave, float alpha, ubyte backgroundColor) {
return cast(ubyte) answer;
}
///
ubyte makeAlpha(ubyte colorYouHave, ubyte backgroundColor/*, ubyte foreground = 0x00*/) {
//auto foregroundf = cast(float) foreground;
auto foregroundf = 0.00f;
@ -644,6 +651,7 @@ int fromHex(string s) {
return result;
}
///
Color colorFromString(string s) {
if(s.length == 0)
return Color(0,0,0,255);
@ -1118,19 +1126,22 @@ void floydSteinbergDither(IndexedImage img, in TrueColorImage original) {
// these are just really useful in a lot of places where the color/image functions are used,
// so I want them available with Color
///
struct Point {
int x;
int y;
int x; ///
int y; ///
}
///
struct Size {
int width;
int height;
int width; ///
int height; ///
}
///
struct Rectangle {
int left;
int top;
int right;
int bottom;
int left; ///
int top; ///
int right; ///
int bottom; ///
}

2
csv.d
View File

@ -1,8 +1,10 @@
///
module arsd.csv;
import std.string;
import std.array;
///
string[][] readCsv(string data) {
data = data.replace("\r", "");

1
curl.d
View File

@ -1,3 +1,4 @@
/// curl wrapper, it sux
module arsd.curl;
// see this for info on making a curl.lib on windows:

View File

@ -1,3 +1,4 @@
///
module arsd.database;
public import std.variant;
@ -21,6 +22,7 @@ import std.string;
so they are always done once per program...
*/
///
interface Database {
/// Actually implements the query for the database. The query() method
/// below might be easier to use.

46
dom.d
View File

@ -5051,11 +5051,9 @@ int intFromHex(string hex) {
return false;
}
foreach(a; notSelectors) {
auto sels = parseSelectorString(a);
foreach(sel; sels)
foreach(part; sel.parts)
if(part.matchElement(e))
return false;
auto sel = Selector(a);
if(sel.matchesElement(e))
return false;
}
return true;
@ -5092,23 +5090,9 @@ int intFromHex(string hex) {
}
break;
case 2: // next-sibling
auto tmp = start.parentNode;
if(tmp !is null) {
sizediff_t pos = -1;
auto children = tmp.childElements;
foreach(i, child; children) {
if(child is start) {
pos = i;
break;
}
}
assert(pos != -1);
if(pos + 1 < children.length) {
auto e = children[pos+1];
if(part.matchElement(e))
ret ~= getElementsBySelectorParts(e, parts[1..$]);
}
}
auto e = start.nextSibling("*");
if(part.matchElement(e))
ret ~= getElementsBySelectorParts(e, parts[1..$]);
break;
case 3: // younger sibling
auto tmp = start.parentNode;
@ -5204,6 +5188,16 @@ int intFromHex(string hex) {
return removeDuplicates(ret);
}
/++
Like [getMatchingElements], but returns a lazy range. Be careful
about mutating the dom as you iterate through this.
+/
auto getMatchingElementsLazy(Element start, Element relativeTo = null) {
import std.algorithm.iteration;
return start.tree.filter!(a => this.matchesElement(a, relativeTo));
}
/// Returns the string this was built from
string toString() {
return original;
@ -5254,7 +5248,7 @@ int intFromHex(string hex) {
int lastSeparation = -1;
foreach(part; retro(parts)) {
writeln("matching ", where, " with ", part, " via ", lastSeparation);
// writeln("matching ", where, " with ", part, " via ", lastSeparation);
if(lastSeparation == -1) {
if(!part.matchElement(where))
@ -5280,12 +5274,12 @@ int intFromHex(string hex) {
if(!part.matchElement(where))
return false;
} else if(lastSeparation == 2) { // the + operator
where = where.previousSibling;
where = where.previousSibling("*");
if(!part.matchElement(where))
return false;
} else if(lastSeparation == 3) { // the ~ operator
where = where.previousSibling;
where = where.previousSibling("*");
while(where !is null) {
if(part.matchElement(where))
break;
@ -5293,7 +5287,7 @@ int intFromHex(string hex) {
if(where is relativeTo)
return false;
where = where.previousSibling;
where = where.previousSibling("*");
}
if(where is null)

View File

@ -1,3 +1,4 @@
///
module arsd.email;
import std.net.curl;

View File

@ -1,3 +1,4 @@
///
module arsd.english;
string plural(int count, string word, string pluralWord = null) {

View File

@ -1,3 +1,4 @@
/// crappy event loop for linux
module arsd.eventloop;
/* **** */
@ -251,6 +252,7 @@ public struct FileEventDispatcher {
return;
addListener(&lowLevelReadHandler);
addListener(&lowLevelHupHandler);
addListener(&lowLevelWriteHandler);
addListener(&lowLevelErrorHandler);
handlersActive = true;
@ -261,6 +263,7 @@ public struct FileEventDispatcher {
return;
removeListener(&lowLevelErrorHandler);
removeListener(&lowLevelHupHandler);
removeListener(&lowLevelWriteHandler);
removeListener(&lowLevelReadHandler);
handlersActive = false;
@ -302,6 +305,9 @@ public struct FileEventDispatcher {
private void lowLevelErrorHandler(FileError ev) {
doHandler(ev.fd, 2);
}
private void lowLevelHupHandler(FileHup ev) {
doHandler(ev.fd, 2);
}
/// You can add a file to listen to here. Files can be OS handles or Phobos types. The handlers can be null, meaning use the default
/// (see: setDefaultHandler), or callables with zero or one argument. If they take an argument, it will be the file being handled at this time.
@ -330,11 +336,11 @@ public struct FileEventDispatcher {
events |= FileEvents.read;
}
if(writeEventHandler !is null) {
handlerSet[0] = wrap(writeEventHandler);
handlerSet[1] = wrap(writeEventHandler);
events |= FileEvents.write;
}
if(errorEventHandler !is null)
handlerSet[0] = wrap(errorEventHandler);
handlerSet[2] = wrap(errorEventHandler);
listeners[handle] = handlerSet;
@ -344,6 +350,7 @@ public struct FileEventDispatcher {
public void removeFile(OsFileHandle handle) {
listeners.remove(handle);
removeFileFromLoopImplementation(handle);
}
/// What should this default handler work on?
@ -492,6 +499,12 @@ version(linux) {
epoll_ctl(epoll, EPOLL_CTL_ADD, fd, &ev);
}
private void removeFileFromLoopImplementation(int fd) {
epoll_event ev = void;
ev.data.fd = fd;
epoll_ctl(epoll, EPOLL_CTL_DEL, fd, &ev);
}
private void loopImplementation() {
insideLoop = true;
@ -561,7 +574,10 @@ version(linux) {
if((flags & EPOLLERR)) {
//import core.stdc.stdio; printf("ERROR on fd from epoll %d\n", fd);
sendSync(FileError(fd));
break outer_loop;
// I automatically remove them because otherwise the error flag
// may never actually be cleared and this thing will infinite loop.
removeFileEventListeners(fd);
}
if((flags & EPOLLHUP)) {
//import core.stdc.stdio; printf("HUP on fd from epoll %d\n", fd);

View File

@ -1,3 +1,5 @@
/// A draft of a better way to do exceptions
module arsd.exception;
/*
Exceptions 2.0
*/

1
hmac.d
View File

@ -1,3 +1,4 @@
///
module arsd.hmac;
// FIXME: the blocksize is correct for MD5, SHA1, and SHA256 but not generally

127
html.d
View File

@ -1,5 +1,5 @@
/**
This module includes functions to work with HTML.
This module includes functions to work with HTML and CSS.
It publically imports the DOM module to get started.
Then it adds a number of functions to enhance html
@ -1235,6 +1235,7 @@ string translateJavascriptSourceWithDToStandardScript(string src)() {
+/
abstract class CssPart {
string comment;
override string toString() const;
CssPart clone() const;
}
@ -1245,6 +1246,7 @@ class CssAtRule : CssPart {
assert(css.length);
assert(css[0] == '@');
auto cssl = css.length;
int braceCount = 0;
int startOfInnerSlice = -1;
@ -1277,6 +1279,12 @@ class CssAtRule : CssPart {
}
}
}
if(cssl == css.length) {
throw new Exception("Bad CSS: unclosed @ rule. " ~ to!string(braceCount) ~ " brace(s) uncloced");
}
innerParts = lexCss(inner, false);
}
string content;
@ -1284,17 +1292,35 @@ class CssAtRule : CssPart {
string opener;
string inner;
CssPart[] innerParts;
override CssAtRule clone() const {
auto n = new CssAtRule();
n.content = content;
n.opener = opener;
n.inner = inner;
foreach(part; innerParts)
n.innerParts ~= part.clone();
return n;
}
override string toString() const { return content; }
}
override string toString() const {
string c;
if(comment.length)
c ~= "/* " ~ comment ~ "*/\n";
c ~= opener.strip();
if(innerParts.length) {
string i;
foreach(part; innerParts)
i ~= part.toString() ~ "\n";
import std.stdio;
c ~= " {\n";
foreach(line; i.splitLines)
c ~= "\t" ~ line ~ "\n";
c ~= "}";
}
return c;
}
}
class CssRuleSet : CssPart {
this() {}
@ -1326,7 +1352,7 @@ class CssRuleSet : CssPart {
f++;
css = css[f .. $];
contents = lexCss(content);
contents = lexCss(content, false);
}
string[] selectors;
@ -1418,6 +1444,10 @@ class CssRuleSet : CssPart {
override string toString() const {
string ret;
if(comment.length)
ret ~= "/* " ~ comment ~ "*/\n";
bool outputtedSelector = false;
foreach(selector; selectors) {
if(outputtedSelector)
@ -1456,6 +1486,21 @@ class CssRule : CssPart {
// note: does not include the ending semicolon
string content;
string key() const {
auto idx = content.indexOf(":");
if(idx == -1)
throw new Exception("Bad css, missing colon in " ~ content);
return content[0 .. idx].strip.toLower;
}
string value() const {
auto idx = content.indexOf(":");
if(idx == -1)
throw new Exception("Bad css, missing colon in " ~ content);
return content[idx + 1 .. $].strip;
}
override CssRule clone() const {
auto n = new CssRule();
n.content = content;
@ -1463,20 +1508,32 @@ class CssRule : CssPart {
}
override string toString() const {
string ret;
if(strip(content).length == 0)
return "";
return content ~ ";";
ret = "";
else
ret = key ~ ": " ~ value ~ ";";
if(comment.length)
ret ~= " /* " ~ comment ~ " */";
return ret;
}
}
CssPart[] lexCss(string css) {
import std.regex;
// strips comments
css = std.regex.replace(css, regex(r"\/\*[^*]*\*+([^/*][^*]*\*+)*\/", "g"), "");
// Never call stripComments = false unless you have already stripped them.
// this thing can't actually handle comments intelligently.
CssPart[] lexCss(string css, bool stripComments = true) {
if(stripComments) {
import std.regex;
css = std.regex.replace(css, regex(r"\/\*[^*]*\*+([^/*][^*]*\*+)*\/", "g"), "");
}
CssPart[] ret;
css = css.stripLeft();
int cnt;
while(css.length > 1) {
CssPart p;
@ -1486,7 +1543,7 @@ CssPart[] lexCss(string css) {
// non-at rules can be either rules or sets.
// The question is: which comes first, the ';' or the '{' ?
auto endOfStatement = css.indexOf(";");
auto endOfStatement = css.indexOfCssSmart(';');
if(endOfStatement == -1)
endOfStatement = css.indexOf("}");
if(endOfStatement == -1)
@ -1508,6 +1565,46 @@ CssPart[] lexCss(string css) {
return ret;
}
// This needs to skip characters inside parens or quotes, so it
// doesn't trip up on stuff like data uris when looking for a terminating
// character.
ptrdiff_t indexOfCssSmart(string i, char find) {
int parenCount;
char quote;
bool escaping;
foreach(idx, ch; i) {
if(escaping) {
escaping = false;
continue;
}
if(quote != char.init) {
if(ch == quote)
quote = char.init;
continue;
}
if(ch == '\'' || ch == '"') {
quote = ch;
continue;
}
if(ch == '(')
parenCount++;
if(parenCount) {
if(ch == ')')
parenCount--;
continue;
}
// at this point, we are not in parenthesis nor are we in
// a quote, so we can actually search for the relevant character
if(ch == find)
return idx;
}
return -1;
}
string cssToString(in CssPart[] css) {
string ret;
foreach(c; css) {
@ -1543,7 +1640,7 @@ const(CssPart)[] denestCss(CssPart[] css) {
auto newCss = at.opener ~ "{\n";
// the whitespace manipulations are just a crude indentation thing
newCss ~= "\t" ~ (cssToString(denestCss(lexCss(at.inner))).replace("\n", "\n\t").replace("\n\t\n\t", "\n\n\t"));
newCss ~= "\t" ~ (cssToString(denestCss(lexCss(at.inner, false))).replace("\n", "\n\t").replace("\n\t\n\t", "\n\n\t"));
newCss ~= "\n}";
@ -2161,11 +2258,11 @@ Color readCssColor(string cssColor) {
}
/*
Copyright: Adam D. Ruppe, 2010 - 2012
Copyright: Adam D. Ruppe, 2010 - 2015
License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
Authors: Adam D. Ruppe, with contributions by Nick Sabalausky and Trass3r
Copyright Adam D. Ruppe 2010-2012.
Copyright Adam D. Ruppe 2010-2015.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)

View File

@ -1,3 +1,4 @@
///
module arsd.htmltotext;
import arsd.dom;

View File

@ -1,3 +1,4 @@
/// HTTP client lib
// Copyright 2013, Adam D. Ruppe.
module arsd.http2;

3
jpg.d
View File

@ -1,3 +1,4 @@
///
module arsd.jpg;
import std.typecons;
@ -88,6 +89,7 @@ Tuple!(int, int) getSizeFromFile(string filename) {
}
version(with_libjpeg) {
/+
import arsd.color;
TrueColorImage read_JPEG_file(string filename) {
@ -213,4 +215,5 @@ version(with_libjpeg) {
/* And we're done! */
return 1;
}
+/
}

View File

@ -1,6 +1,6 @@
// Small wrapper for libssh2
// just link with it on Linux
// it'll need a couple dlls and a lib on windows.
/// Small wrapper for libssh2
/// just link with it on Linux
/// it'll need a couple dlls and a lib on windows.
module arsd.libssh2;
@ -181,4 +181,9 @@ extern(C) {
int libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel);
enum LIBSSH2_ERROR_EAGAIN = -37;
int libssh2_session_flag(LIBSSH2_SESSION*, int, int);
enum LIBSSH2_FLAG_SIGPIPE = 1;
enum LIBSSH2_FLAG_COMPRESS = 2;
}

View File

@ -1,3 +1,4 @@
/// a D mangler
module mangle;
import std.conv;

View File

@ -1,6 +1,6 @@
// NOTE: I haven't even tried to use this for a test yet!
// It's probably godawful, if it works at all.
///
module arsd.mssql;
version(Windows):

View File

@ -1,3 +1,4 @@
///
module arsd.oauth;
import arsd.curl;

1
png.d
View File

@ -1,3 +1,4 @@
/// PNG file handling for color.d's Image interfaces
module arsd.png;
/// Easily reads a png file into a MemoryImage

View File

@ -1,3 +1,4 @@
/// minimal libpq wrapper
module arsd.postgres;
pragma(lib, "pq");

1
sha.d
View File

@ -1,3 +1,4 @@
/// homemade sha 1 and sha2 impls. beware of bugs.
module arsd.sha;
/*

View File

@ -52,7 +52,7 @@
compiler are all opt-in.
simpledisplay.d's home base is on my arsd repo on Github. The file is:
$(L https://github.com/adamdruppe/arsd/blob/master/simpledisplay.d)
https://github.com/adamdruppe/arsd/blob/master/simpledisplay.d
simpledisplay is basically stable. I plan to refactor the internals,
and may add new features and fix bugs, but It do not expect to
@ -4416,8 +4416,8 @@ version(X11) {
version(with_eventloop) {
import arsd.eventloop;
static void eventListener(OsFileHandle fd) {
this.mtLock();
scope(exit) this.mtUnlock();
//this.mtLock();
//scope(exit) this.mtUnlock();
while(XPending(display))
doXNextEvent(display);
}

View File

@ -1,4 +1,4 @@
/*
/**
Compile with version=sqlite_extended_metadata_available
if your sqlite is compiled with the
SQLITE_ENABLE_COLUMN_METADATA C-preprocessor symbol.
@ -8,7 +8,6 @@
use DataObjects, but you'll have to set up the mappings
manually without the extended metadata.)
*/
module arsd.sqlite;
pragma(lib, "sqlite3");
version(linux)

View File

@ -1,4 +1,4 @@
/*
/**
This is CLIENT only at this point. Don't try to
bind/accept with these.
@ -47,9 +47,18 @@ version(use_openssl) {
void SSL_free(SSL*);
void SSL_CTX_free(SSL_CTX*);
void SSL_set_verify(SSL*, int, void*);
enum SSL_VERIFY_NONE = 0;
SSL_METHOD* SSLv3_client_method();
SSL_METHOD* TLS_client_method();
SSL_METHOD* SSLv23_client_method();
void ERR_print_errors_fp(FILE*);
}
import core.stdc.stdio;
shared static this() {
SSL_library_init();
OpenSSL_add_all_ciphers();
@ -63,19 +72,26 @@ version(use_openssl) {
class OpenSslSocket : Socket {
private SSL* ssl;
private SSL_CTX* ctx;
private void initSsl() {
ctx = SSL_CTX_new(SSLv3_client_method());
private void initSsl(bool verifyPeer) {
ctx = SSL_CTX_new(SSLv23_client_method());
assert(ctx !is null);
ssl = SSL_new(ctx);
if(!verifyPeer)
SSL_set_verify(ssl, SSL_VERIFY_NONE, null);
SSL_set_fd(ssl, this.handle);
}
@trusted
override void connect(Address to) {
super.connect(to);
if(SSL_connect(ssl) == -1)
if(SSL_connect(ssl) == -1) {
ERR_print_errors_fp(stderr);
int i;
printf("wtf\n");
scanf("%d\n", i);
throw new Exception("ssl connect");
}
}
@trusted
@ -93,14 +109,14 @@ version(use_openssl) {
return receive(buf, SocketFlags.NONE);
}
this(AddressFamily af, SocketType type = SocketType.STREAM) {
this(AddressFamily af, SocketType type = SocketType.STREAM, bool verifyPeer = true) {
super(af, type);
initSsl();
initSsl(verifyPeer);
}
this(socket_t sock, AddressFamily af) {
super(sock, af);
initSsl();
initSsl(true);
}
~this() {

View File

@ -1,11 +1,12 @@
// stb_truetype.h - v0.6c - public domain
// authored from 2009-2012 by Sean Barrett / RAD Game Tools
/// stb_truetype.h - v0.6c - public domain
/// authored from 2009-2012 by Sean Barrett / RAD Game Tools
//
// http://nothings.org/stb/stb_truetype.h
//
// port to D by adam d. ruppe. see the link above for more info about the lib and real author.
// here's some D convenience functions
module stb_truetype;
struct TtfFont {
stbtt_fontinfo font;

View File

@ -1516,13 +1516,15 @@ struct RealTimeConsoleInput {
FD_ZERO(&fs);
FD_SET(fdIn, &fs);
select(fdIn + 1, &fs, null, null, &tv);
if(select(fdIn + 1, &fs, null, null, &tv) == -1) {
return false;
}
return FD_ISSET(fdIn, &fs);
}
}
private bool anyInput_internal() {
/* private */ bool anyInput_internal() {
if(inputQueue.length || timedCheckForInput(0))
return true;
version(Posix)
@ -3351,6 +3353,9 @@ version(Windows) {
struct ScrollbackBuffer {
bool demandsAttention;
this(string name) {
this.name = name;
}
@ -3640,6 +3645,8 @@ struct ScrollbackBuffer {
case InputEvent.Type.KeyboardEvent:
auto ev = e.keyboardEvent;
demandsAttention = false;
switch(ev.which) {
case KeyboardEvent.Key.UpArrow:
scrollUp();
@ -3660,6 +3667,7 @@ struct ScrollbackBuffer {
case InputEvent.Type.MouseEvent:
auto ev = e.mouseEvent;
if(ev.x >= x && ev.x < x + width && ev.y >= y && ev.y < y + height) {
demandsAttention = false;
// it is inside our box, so do something with it
auto mx = ev.x - x;
auto my = ev.y - y;

3
web.d
View File

@ -1,3 +1,4 @@
/// magic web wrapper
module arsd.web;
// it would be nice to be able to add meta info to a returned envelope
@ -3594,7 +3595,7 @@ struct TemplateFilters {
switch(word[$ - 1]) {
case 's':
case 'a', 'e', 'i', 'o', 'u':
case 'a', 'i', 'o', 'u':
return word ~ "es";
case 'f':
return word[0 .. $-1] ~ "ves";