(resending patch without line breaks)

This patch adds support for image downloads from ports other than port 80 and 
allows the download method to handle http over SSL (https://). This has only 
been tested using Linux/curl. I couldn't
 figure out the windows http code, so it won't work on windows (but I added the 
groundwork, and I'd love to see how!). I also didn't test on OS X.

With this patch you can do the following:
image 'http://localhost:3000/images/rails.png'

The following has also been tested with Linux/curl:
image 'https://mail.google.com/mail/help/images/logo.gif'

---
 shoes/http.h             |    1 +
 shoes/http/curl.c        |    2 +-
 shoes/http/nsurl.m       |    2 +-
 shoes/http/windownload.c |    6 +++++-
 shoes/http/winhttp.c     |    2 +-
 shoes/http/winhttp.h     |    2 +-
 shoes/image.c            |    8 +++++---
 shoes/ruby.c             |    4 ++++
 shoes/ruby.h             |    2 +-
 9 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/shoes/http.h b/shoes/http.h
index 9bba849..5b5a710 100644
--- a/shoes/http.h
+++ b/shoes/http.h
@@ -9,6 +9,7 @@
 #include "shoes/http/common.h"
 
 typedef struct {
+  char *scheme;
   char *host;
   int port;
   char *path;
diff --git a/shoes/http/curl.c b/shoes/http/curl.c
index b171f23..ccdf659 100644
--- a/shoes/http/curl.c
+++ b/shoes/http/curl.c
@@ -117,7 +117,7 @@ shoes_download(shoes_download_request *req)
   if (curl == NULL) return;
 
   if (req->path[0] == '/') slash[0] = '\0';
-  sprintf(url, "http://%s:%d%s%s";, req->host, req->port, slash, req->path);
+  sprintf(url, "%s://%s:%d%s%s", req->scheme, req->host, req->port, slash, 
req->path);
   sprintf(uagent, "Shoes/0.r%d (%s) %s/%d", SHOES_REVISION, SHOES_PLATFORM,
     SHOES_RELEASE_NAME, SHOES_BUILD_DATE);
 
diff --git a/shoes/http/nsurl.m b/shoes/http/nsurl.m
index 645262f..350c2c0 100644
--- a/shoes/http/nsurl.m
+++ b/shoes/http/nsurl.m
@@ -51,7 +51,7 @@
 {
   char slash[2] = "/";
   if (req->path[0] == '/') slash[0] = '\0';
-  NSString *url = [NSString stringWithFormat: @"http://%s:%d%s%s";, req->host, 
req->port, slash, req->path];
+  NSString *url = [NSString stringWithFormat: @"%s://%s:%d%s%s", req->scheme, 
req->host, req->port, slash, req->path];
   NSString *uagent = [NSString stringWithFormat: @"Shoes/0.r%d (%s) %s/%d", 
     SHOES_REVISION, SHOES_PLATFORM, SHOES_RELEASE_NAME, SHOES_BUILD_DATE];
   NSMutableURLRequest *nsreq = [NSMutableURLRequest requestWithURL: 
diff --git a/shoes/http/windownload.c b/shoes/http/windownload.c
index c36e658..67b39a7 100644
--- a/shoes/http/windownload.c
+++ b/shoes/http/windownload.c
@@ -20,9 +20,11 @@ shoes_download(shoes_download_request *req)
   HANDLE file = INVALID_HANDLE_VALUE;
   INTERNET_PORT _port = req->port;
   LPWSTR _method = NULL, _body = NULL;
+  LPWSTR _scheme = SHOE_ALLOC_N(WCHAR, MAX_PATH);
   LPWSTR _host = SHOE_ALLOC_N(WCHAR, MAX_PATH);
   LPWSTR _path = SHOE_ALLOC_N(WCHAR, MAX_PATH);
   DWORD _size;
+  MultiByteToWideChar(CP_UTF8, 0, req->scheme, -1, _scheme, MAX_PATH);
   MultiByteToWideChar(CP_UTF8, 0, req->host, -1, _host, MAX_PATH);
   MultiByteToWideChar(CP_UTF8, 0, req->path, -1, _path, MAX_PATH);
   if (req->method != NULL)
@@ -34,9 +36,10 @@ shoes_download(shoes_download_request *req)
   if (req->mem == NULL && req->filepath != NULL)
     file = CreateFile(req->filepath, GENERIC_READ | GENERIC_WRITE,
       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 
FILE_ATTRIBUTE_NORMAL, NULL);
-  shoes_winhttp(_host, _port, _path, _method, req->headers, (LPVOID)req->body, 
req->bodylen,
+  shoes_winhttp(_scheme, _host, _port, _path, _method, req->headers, 
(LPVOID)req->body, req->bodylen,
                &req->mem, req->memlen, file, &_size, req->flags, req->handler, 
req->data);
   req->size = _size;
+  SHOE_FREE(_scheme);
   SHOE_FREE(_host);
   SHOE_FREE(_path);
   if (_method != NULL) SHOE_FREE(_method);
@@ -47,6 +50,7 @@ shoes_download2(LPVOID data)
 {
   shoes_download_request *req = (shoes_download_request *)data;
   shoes_download(req);
+  if (req->scheme != NULL) free(req->scheme);
   if (req->method != NULL) free(req->method);
   if (req->body != NULL) free(req->body);
   if (req->headers != NULL) free(req->headers);
diff --git a/shoes/http/winhttp.c b/shoes/http/winhttp.c
index 5248509..95f265e 100644
--- a/shoes/http/winhttp.c
+++ b/shoes/http/winhttp.c
@@ -52,7 +52,7 @@ shoes_winhttp_headers(HINTERNET req, shoes_download_handler 
handler, void *data)
 }
 
 void
-shoes_winhttp(LPCWSTR host, INTERNET_PORT port, LPCWSTR path, LPCWSTR method,
+shoes_winhttp(LPCWSTR scheme, LPCWSTR host, INTERNET_PORT port, LPCWSTR path, 
LPCWSTR method,
   LPCWSTR headers, LPVOID body, DWORD bodylen, TCHAR **mem, ULONG memlen, 
HANDLE file,
   LPDWORD size, UCHAR flags, shoes_download_handler handler, void *data)
 {
diff --git a/shoes/http/winhttp.h b/shoes/http/winhttp.h
index 795738e..48d2386 100644
--- a/shoes/http/winhttp.h
+++ b/shoes/http/winhttp.h
@@ -14,6 +14,6 @@
 
 #define HTTP_HANDLER(x) reinterpret_cast<shoes_download_handler>(x)
 
-void shoes_winhttp(LPCWSTR, INTERNET_PORT, LPCWSTR, LPCWSTR, LPCWSTR, LPVOID, 
DWORD, TCHAR **, ULONG, HANDLE, LPDWORD, UCHAR, shoes_download_handler, void *);
+void shoes_winhttp(LPCWSTR, LPCWSTR, INTERNET_PORT, LPCWSTR, LPCWSTR, LPCWSTR, 
LPVOID, DWORD, TCHAR **, ULONG, HANDLE, LPDWORD, UCHAR, shoes_download_handler, 
void *);
 
 #endif
diff --git a/shoes/image.c b/shoes/image.c
index 7e5fb9c..a164f2f 100644
--- a/shoes/image.c
+++ b/shoes/image.c
@@ -878,12 +878,13 @@ shoes_load_image(VALUE slot, VALUE imgpath)
   if (shoes_cache_lookup(RSTRING_PTR(imgpath), &cached))
     goto done;
 
-  if (strlen(fname) > 7 && strncmp(fname, "http://";, 7) == 0)
+  if (strlen(fname) > 7 && (strncmp(fname, "http://";, 7) == 0 || 
strncmp(fname, "https://";, 8) == 0))
   {
     struct timeval tv;
-    VALUE cache, uext, hdrs, tmppath, uri, host, port, requ, path, cachepath = 
Qnil, hash = Qnil;
+    VALUE cache, uext, hdrs, tmppath, uri, scheme, host, port, requ, path, 
cachepath = Qnil, hash = Qnil;
     rb_require("shoes/data");
     uri = rb_funcall(cShoes, rb_intern("uri"), 1, imgpath);
+    scheme = rb_funcall(uri, s_scheme, 0);
     host = rb_funcall(uri, s_host, 0);
     port = rb_funcall(uri, s_port, 0);
     requ = rb_funcall(uri, s_request_uri, 0);
@@ -921,8 +922,9 @@ shoes_load_image(VALUE slot, VALUE imgpath)
     SHOE_MEMZERO(req, shoes_download_request, 1);
     shoes_image_download_event *idat = SHOE_ALLOC(shoes_image_download_event);
     SHOE_MEMZERO(idat, shoes_image_download_event, 1);
+    req->scheme = RSTRING_PTR(scheme);
     req->host = RSTRING_PTR(host);
-    req->port = 80;
+    req->port = NUM2INT(port);
     req->path = RSTRING_PTR(requ);
     req->handler = shoes_download_image_handler;
     req->filepath = strdup(RSTRING_PTR(tmppath));
diff --git a/shoes/ruby.c b/shoes/ruby.c
index a3af54d..957cd84 100644
--- a/shoes/ruby.c
+++ b/shoes/ruby.c
@@ -4084,11 +4084,13 @@ VALUE
 shoes_download_non_threaded(VALUE self, VALUE url)
 {
   if (!rb_respond_to(url, s_host)) url = rb_funcall(rb_mKernel, s_URI, 1, url);
+  VALUE scheme = rb_funcall(url, s_scheme, 0);
   VALUE host = rb_funcall(url, s_host, 0);
   VALUE port = rb_funcall(url, s_port, 0);
   VALUE path = rb_funcall(url, s_request_uri, 0);
   shoes_download_request req;
   SHOE_MEMZERO(&req, shoes_download_request, 1);
+  req.scheme = RSTRING_PTR(scheme);
   req.host = RSTRING_PTR(host);
   req.port = NUM2INT(port);
   req.path = RSTRING_PTR(path);
@@ -4169,12 +4171,14 @@ shoes_download_threaded(VALUE self, VALUE url, VALUE 
attr)
   GET_STRUCT(canvas, self_t);
 
   if (!rb_respond_to(url, s_host)) url = rb_funcall(rb_mKernel, s_URI, 1, url);
+  VALUE scheme = rb_funcall(url, s_scheme, 0);
   VALUE host = rb_funcall(url, s_host, 0);
   VALUE port = rb_funcall(url, s_port, 0);
   VALUE path = rb_funcall(url, s_request_uri, 0);
 
   shoes_download_request *req = SHOE_ALLOC(shoes_download_request);
   SHOE_MEMZERO(req, shoes_download_request, 1);
+  req->scheme = RSTRING_PTR(scheme);
   req->host = RSTRING_PTR(host);
   req->port = NUM2INT(port);
   req->path = RSTRING_PTR(path);
diff --git a/shoes/ruby.h b/shoes/ruby.h
index 91cca31..19ae907 100644
--- a/shoes/ruby.h
+++ b/shoes/ruby.h
@@ -188,7 +188,7 @@ void shoes_ele_remove_all(VALUE);
 void shoes_cairo_rect(cairo_t *, double, double, double, double, double);
 void shoes_cairo_arc(cairo_t *, double, double, double, double, double, 
double);
 
-#define SYMBOL_DEFS(f) f(bind); f(gsub); f(keys); f(update); f(merge); f(new); 
f(URI); f(now); f(debug); f(info); f(warn); f(error); f(run); f(to_a); 
f(to_ary); f(to_f); f(to_i); f(to_int); f(to_s); f(to_str); f(to_pattern); 
f(angle); f(angle1); f(angle2); f(arrow); f(autoplay); f(begin); f(body); 
f(cancel); f(call); f(center); f(change); f(checked); f(choose); f(click); 
f(corner); f(curve); f(distance); f(displace_left); f(displace_top); 
f(downcase); f(draw); f(end); f(fill); f(finish); f(font); f(group); f(hand); 
f(headers); f(hidden); f(host); f(hover); f(href); f(insert); f(inner); 
f(items); f(keypress); f(match); f(method); f(motion); f(link); f(leading); 
f(leave); f(ok); f(outer); f(path); f(points); f(port); f(progress); 
f(redirect); f(release); f(request_uri); f(save); f(state); f(wheel); 
f(scroll); f(stroke); f(start); f(attach); f(text); f(title); f(top); f(right); 
f(bottom); f(left); f(up); f(down); f(height); f(remove); f(resizable); 
f(strokewidth); f(cap); f(wid
th); f(margin); f(margin_left); f(margin_right); f(margin_top); 
f(margin_bottom); f(radius); f(secret); f(blur); f(glow); f(shadow); f(arc); 
f(rect); f(oval); f(line); f(shape); f(star); f(project); f(round); f(square);
+#define SYMBOL_DEFS(f) f(bind); f(gsub); f(keys); f(update); f(merge); f(new); 
f(URI); f(now); f(debug); f(info); f(warn); f(error); f(run); f(to_a); 
f(to_ary); f(to_f); f(to_i); f(to_int); f(to_s); f(to_str); f(to_pattern); 
f(angle); f(angle1); f(angle2); f(arrow); f(autoplay); f(begin); f(body); 
f(cancel); f(call); f(center); f(change); f(checked); f(choose); f(click); 
f(corner); f(curve); f(distance); f(displace_left); f(displace_top); 
f(downcase); f(draw); f(end); f(fill); f(finish); f(font); f(group); f(hand); 
f(headers); f(hidden); f(host); f(hover); f(href); f(insert); f(inner); 
f(items); f(keypress); f(match); f(method); f(motion); f(link); f(leading); 
f(leave); f(ok); f(outer); f(path); f(points); f(port); f(progress); 
f(redirect); f(release); f(request_uri); f(scheme); f(save); f(state); 
f(wheel); f(scroll); f(stroke); f(start); f(attach); f(text); f(title); f(top); 
f(right); f(bottom); f(left); f(up); f(down); f(height); f(remove); 
f(resizable); f(strokewidth); f(
cap); f(width); f(margin); f(margin_left); f(margin_right); f(margin_top); 
f(margin_bottom); f(radius); f(secret); f(blur); f(glow); f(shadow); f(arc); 
f(rect); f(oval); f(line); f(shape); f(star); f(project); f(round); f(square);
 #define SYMBOL_INTERN(name) s_##name = rb_intern("" # name)
 #define SYMBOL_ID(name) ID s_##name 
 #define SYMBOL_EXTERN(name) extern ID s_##name
-- 
1.6.0.5

Reply via email to