diff --git a/libeay32.dll b/libeay32.dll new file mode 100644 index 0000000..cea737b Binary files /dev/null and b/libeay32.dll differ diff --git a/libssh2.d b/libssh2.d new file mode 100644 index 0000000..38c271f --- /dev/null +++ b/libssh2.d @@ -0,0 +1,176 @@ +// Small wrapper for libssh2 +// just link with it on Linux +// it'll need a couple dlls and a lib on windows. + +version(libssh_example) +void main() { + import std.socket; + + if(libssh2_init(0)) + throw new Exception("libssh2_init"); + scope(exit) + libssh2_exit(); + + auto socket = new Socket(AddressFamily.INET, SocketType.STREAM); + socket.connect(new InternetAddress("localhost", 22)); + scope(exit) socket.close(); + + auto session = libssh2_session_init_ex(null, null, null, null); + if(session is null) throw new Exception("init session"); + scope(exit) + libssh2_session_disconnect_ex(session, 0, "normal", "EN"); + + if(libssh2_session_handshake(session, socket.handle)) + throw new Exception("handshake"); + + auto fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); + + /* + import core.stdc.stdio; + for(int i = 0; i < 20; i++) + printf("%02X ", fingerprint[i]); + */ + + /* + auto got = libssh2_userauth_list(session, "me", 2); + if(got is null) throw new Exception("list"); + import core.stdc.stdio; + printf("%s\n", got); + */ + + if(auto err = libssh2_userauth_publickey_fromfile_ex(session, "me".ptr, "me".length, "/home/me/.ssh/id_rsa.pub", "/home/me/.ssh/id_rsa", null)) + throw new Exception("auth"); + + + auto channel = libssh2_channel_open_ex(session, "session".ptr, "session".length, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, null, 0); + + if(channel is null) + throw new Exception("channel open"); + + scope(exit) + libssh2_channel_free(channel); + + libssh2_channel_setenv_ex(channel, "ELVISBG".dup.ptr, "ELVISBG".length, "dark".ptr, "dark".length); + + if(libssh2_channel_request_pty_ex(channel, "xterm", "xterm".length, null, 0, 80, 24, 0, 0)) + throw new Exception("pty"); + + if(libssh2_channel_process_startup(channel, "shell".ptr, "shell".length, null, 0)) + throw new Exception("process_startup"); + + libssh2_keepalive_config(session, 0, 60); + libssh2_session_set_blocking(session, 0); + + + char[1024] buffer; + again: + auto got = libssh2_channel_read_ex(channel, 0, buffer.ptr, buffer.length); + if(got == LIBSSH2_ERROR_EAGAIN) { + import core.thread; + Thread.sleep(msecs(500)); + goto again; + } + + import std.stdio; + writeln(buffer[0 .. got]); +} + + + + +alias socket_t = int; + +version(Windows) { + pragma(lib, "libssh2"); +} else { + pragma(lib, "ssh2"); +} + +version(X86) + alias ssize_t = int; +else version(X86_64) + alias ssize_t = long; + +extern(C) { + struct LIBSSH2_SESSION {} + LIBSSH2_SESSION* libssh2_session_init_ex(void* myalloc, void* myfree, void* myrealloc, void* abstract_); + + int libssh2_session_handshake(LIBSSH2_SESSION* session, socket_t socket); + + enum int LIBSSH2_HOSTKEY_HASH_MD5 = 1; + enum int LIBSSH2_HOSTKEY_HASH_SHA1 = 2; + const(char)* libssh2_hostkey_hash(LIBSSH2_SESSION*, int hash_type); + + int libssh2_userauth_publickey_fromfile_ex( + LIBSSH2_SESSION* session, + const char *username, + uint ousername_len, + const char *publickey, + const char *privatekey, + const char *passphrase); + + struct LIBSSH2_CHANNEL {} + LIBSSH2_CHANNEL* libssh2_channel_open_ex( + LIBSSH2_SESSION *session, + const char *channel_type, + uint channel_type_len, + uint window_size, + uint packet_size, + const char *message, + uint message_len); + // channel_open_session calls the above + + int libssh2_channel_setenv_ex( + LIBSSH2_CHANNEL* channel, + char* varname, + uint varname_len, + const char *value, + uint value_len); + + enum LIBSSH2_CHANNEL_WINDOW_DEFAULT = (256*1024); + enum LIBSSH2_CHANNEL_PACKET_DEFAULT = 32768; + + int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term, uint term_len, const char *modes, uint modes_len, int width, int height, int width_px, int height_px); + + int libssh2_channel_process_startup( + LIBSSH2_CHANNEL* channel, + const char *request, + uint request_len, + const char *message, + uint message_len); + + + int libssh2_channel_free(LIBSSH2_CHANNEL *channel); + int libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason, const char *description, const char *lang); + int libssh2_session_free(LIBSSH2_SESSION *session); + + int libssh2_init(int flags); + void libssh2_exit(); + + // stream_id 0 == normal, 1 == error. + ssize_t libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf, size_t buflen); + + ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, + int stream_id, char *buf, + size_t buflen); + + void libssh2_session_set_blocking(LIBSSH2_SESSION* session, int blocking); + + void libssh2_keepalive_config(LIBSSH2_SESSION *session, + int want_reply, + uint interval); + + int libssh2_keepalive_send(LIBSSH2_SESSION *session, + int *seconds_to_next); + + int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, + int width, int height, + int width_px, + int height_px); + + char * + libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, + uint username_len); + + enum LIBSSH2_ERROR_EAGAIN = -37; +} diff --git a/libssh2.dll b/libssh2.dll new file mode 100644 index 0000000..5a15362 Binary files /dev/null and b/libssh2.dll differ diff --git a/libssh2.lib b/libssh2.lib new file mode 100644 index 0000000..36af1d1 Binary files /dev/null and b/libssh2.lib differ diff --git a/simpledisplay.d b/simpledisplay.d index 1c7ffff..2d079f2 100644 --- a/simpledisplay.d +++ b/simpledisplay.d @@ -1,5 +1,7 @@ module simpledisplay; +// FIXME: icons on Windows don't look quite right, I think the transparency mask is off. + // http://wiki.dlang.org/Simpledisplay.d // FIXME: SIGINT handler is necessary to clean up shared memory handles upon ctrl+c @@ -2086,6 +2088,8 @@ version(Windows) { HBRUSH originalBrush; HBRUSH currentBrush; @property void fillColor(Color c) { + // FIXME: we probably don't need to call all this if the brush + // is already good HBRUSH brush; if(c.a == 0) { brush = GetStockObject(HOLLOW_BRUSH); @@ -2795,6 +2799,8 @@ version(X11) { } @property void outlineColor(Color c) { + if(_pen.color == c) + return; // don't double call for performance _pen.color = c; pen = _pen; } @@ -2815,6 +2821,8 @@ version(X11) { @property void fillColor(Color c) { + if(_fillColor == c) + return; // already good, no need to waste time calling it _fillColor = c; if(c.a == 0) { backgroundIsNotTransparent = false;