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
