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 SSL won't work on windows (but I laid some
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:
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(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_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.5.4.3

Reply via email to