shoes 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +12 -0
- data/CHANGELOG +29 -0
- data/COPYING +30 -0
- data/README.md +76 -0
- data/README.old +117 -0
- data/Rakefile +130 -0
- data/Rakefile.bk +651 -0
- data/app.yaml +7 -0
- data/bin/main.skel +104 -0
- data/bugs/issue-012e9468ddc7b0cb7e1503413a8a11c4f8707b67.yaml +21 -0
- data/bugs/issue-0711ff8b67baa63586f11d0096fee9dd4436bf58.yaml +23 -0
- data/bugs/issue-07f87998d93eb401e22395c11085676389b935c4.yaml +22 -0
- data/bugs/issue-0bff2d80008803cbc7efbcdacdc60ef2163664d2.yaml +22 -0
- data/bugs/issue-0c66f223d19efbca7b692f3b91961f407ad7abec.yaml +24 -0
- data/bugs/issue-183bc3c7a8f575aff2b24e0bf22aa0dfcc8e4fc2.yaml +29 -0
- data/bugs/issue-1bad1e60a04cb3adb6a8f3ded128af2e16b56ffe.yaml +18 -0
- data/bugs/issue-1f1d43f76bf4de79d7f94adbae6dd506a9d81633.yaml +41 -0
- data/bugs/issue-320924117cadb045cc91f2a6fca922b4d81d4bb5.yaml +20 -0
- data/bugs/issue-33e5c8355fbf65252ea9e939714651df8bd8cb3b.yaml +25 -0
- data/bugs/issue-36f7c8262a72bcd5e28cfa4ed29328b8237ea79b.yaml +20 -0
- data/bugs/issue-39bf04ee50c3bef67b89b8e9beb28657805587ce.yaml +18 -0
- data/bugs/issue-3e28ba7754f73d02ef416eef989af707a8c00f01.yaml +23 -0
- data/bugs/issue-3f638cc03f41f9c3fdf217355321f1563f8fee45.yaml +22 -0
- data/bugs/issue-41e48e14f1ef4f6deb69be68165d7dd3ffd99156.yaml +22 -0
- data/bugs/issue-4c9408166a2aa5dd333bbb05520deebf4ded08e0.yaml +22 -0
- data/bugs/issue-55c687e108ecd5aeb8e0d0aeb4294984f84acd3e.yaml +18 -0
- data/bugs/issue-5811d34692cc292717a58ec1df1f8948cf30d826.yaml +28 -0
- data/bugs/issue-5a7c1f59a0526f9cea7fb366867cf1e6ed8ef69d.yaml +22 -0
- data/bugs/issue-688a2c2566bef6a03efa57a4ae1f7cfa8fc74444.yaml +21 -0
- data/bugs/issue-78b16c7988ade2ef96e716fa8cb9a004bd4ced65.yaml +33 -0
- data/bugs/issue-804ee49f9800154eddf0650690c7a9bb5626253f.yaml +27 -0
- data/bugs/issue-807dd1c610b2e941a5d454e26b2eac27e89a0ab4.yaml +22 -0
- data/bugs/issue-822ee33ec11ebd25f90ea86e8438de7891e63aee.yaml +18 -0
- data/bugs/issue-82ff7152cebb8a1cb065b864cb4fe22de2328146.yaml +29 -0
- data/bugs/issue-856afbdcdd4970ad54b8ce4a6c017fbaab45f49d.yaml +31 -0
- data/bugs/issue-8d49e32fb21522651c67490adb4d80076dbb14e1.yaml +24 -0
- data/bugs/issue-91583359653a9d530c1e32be72d874d847a306e7.yaml +21 -0
- data/bugs/issue-af41a5229613172764e7d3c98431172db337053d.yaml +20 -0
- data/bugs/issue-bd9856b3788dd429c998a5af1b2aae8221cb80b7.yaml +28 -0
- data/bugs/issue-be22aef5c564fb7b5e9938343136a9cd6a2edb7b.yaml +22 -0
- data/bugs/issue-bf8697523c77c326e7e35fc82cf3dd739ae92310.yaml +27 -0
- data/bugs/issue-cdd4b4795f34d6ff46e56ece10f8216a4a5456b2.yaml +25 -0
- data/bugs/issue-d9bfb5581d745ef9deb3b9b2e08ef74d1cd43082.yaml +20 -0
- data/bugs/issue-e0ce2f687cc096f35715d28b0af88589f4ab6cc6.yaml +18 -0
- data/bugs/issue-e4b0aca4a10a574b333aeaecaaf221dbc5ed22c6.yaml +38 -0
- data/bugs/issue-f263746594b95ba778455730478ee8df60ee639d.yaml +22 -0
- data/bugs/project.yaml +72 -0
- data/builddeps.sh +102 -0
- data/fonts/Coolvetica.ttf +0 -0
- data/fonts/Lacuna.ttf +0 -0
- data/gemlib/shoes.rb +1 -0
- data/lib/shoes.rb +548 -0
- data/lib/shoes/cache.rb +54 -0
- data/lib/shoes/chipmunk.rb +35 -0
- data/lib/shoes/data.rb +39 -0
- data/lib/shoes/help.rb +468 -0
- data/lib/shoes/image.rb +25 -0
- data/lib/shoes/inspect.rb +128 -0
- data/lib/shoes/log.rb +48 -0
- data/lib/shoes/minitar.rb +986 -0
- data/lib/shoes/override.rb +38 -0
- data/lib/shoes/pack.rb +543 -0
- data/lib/shoes/search.rb +46 -0
- data/lib/shoes/setup.rb +329 -0
- data/lib/shoes/shy.rb +131 -0
- data/lib/shoes/shybuilder.rb +44 -0
- data/lib/shoes/version.rb +3 -0
- data/make/darwin/deps.vlc +12 -0
- data/make/darwin/dylibs.shoes +22 -0
- data/make/darwin/dylibs.video +11 -0
- data/make/darwin/env.rb +81 -0
- data/make/darwin/tasks.rb +105 -0
- data/make/linux/env.rb +65 -0
- data/make/linux/tasks.rb +61 -0
- data/make/make.rb +85 -0
- data/make/mingw/dlls +19 -0
- data/make/mingw/env.rb +69 -0
- data/make/mingw/tasks.rb +70 -0
- data/make/rakefile_common.rb +8 -0
- data/manual-snapshots/class-book.png +0 -0
- data/manual-snapshots/expert-definr.png +0 -0
- data/manual-snapshots/expert-funnies.png +0 -0
- data/manual-snapshots/expert-irb.png +0 -0
- data/manual-snapshots/expert-minesweeper.png +0 -0
- data/manual-snapshots/expert-othello.png +0 -0
- data/manual-snapshots/expert-pong.png +0 -0
- data/manual-snapshots/expert-tankspank.png +0 -0
- data/manual-snapshots/good-arc.png +0 -0
- data/manual-snapshots/good-clock.png +0 -0
- data/manual-snapshots/good-follow.png +0 -0
- data/manual-snapshots/good-reminder.png +0 -0
- data/manual-snapshots/good-vjot.png +0 -0
- data/manual-snapshots/simple-accordion.png +0 -0
- data/manual-snapshots/simple-anim-shapes.png +0 -0
- data/manual-snapshots/simple-anim-text.png +0 -0
- data/manual-snapshots/simple-arc.png +0 -0
- data/manual-snapshots/simple-bounce.png +0 -0
- data/manual-snapshots/simple-calc.png +0 -0
- data/manual-snapshots/simple-chipmunk.png +0 -0
- data/manual-snapshots/simple-control-sizes.png +0 -0
- data/manual-snapshots/simple-curve.png +0 -0
- data/manual-snapshots/simple-dialogs.png +0 -0
- data/manual-snapshots/simple-downloader.png +0 -0
- data/manual-snapshots/simple-draw.png +0 -0
- data/manual-snapshots/simple-editor.png +0 -0
- data/manual-snapshots/simple-form.png +0 -0
- data/manual-snapshots/simple-mask.png +0 -0
- data/manual-snapshots/simple-menu.png +0 -0
- data/manual-snapshots/simple-menu1.png +0 -0
- data/manual-snapshots/simple-rubygems.png +0 -0
- data/manual-snapshots/simple-slide.png +0 -0
- data/manual-snapshots/simple-sphere.png +0 -0
- data/manual-snapshots/simple-sqlite3.png +0 -0
- data/manual-snapshots/simple-timer.png +0 -0
- data/manual-snapshots/simple-video.png +0 -0
- data/platform/mac/Info.plist +55 -0
- data/platform/mac/build-deps.sh +658 -0
- data/platform/mac/command-manual.rb +1 -0
- data/platform/mac/deps-osx.patch +159 -0
- data/platform/mac/dmg_ds_store +0 -0
- data/platform/mac/pangorc +2 -0
- data/platform/mac/pkg-dmg +1447 -0
- data/platform/mac/shoes +31 -0
- data/platform/mac/shoes-launch +7 -0
- data/platform/mac/stub.m +178 -0
- data/platform/mac/version.plist +14 -0
- data/platform/msw/base.nsi +644 -0
- data/platform/msw/installer-1.bmp +0 -0
- data/platform/msw/installer-2.bmp +0 -0
- data/platform/msw/shoes.exe.manifest +17 -0
- data/platform/msw/shoes.ico +0 -0
- data/platform/msw/stub-inject.c +59 -0
- data/platform/msw/stub.c +271 -0
- data/platform/msw/stub32.h +14 -0
- data/platform/msw/stub32.rc +16 -0
- data/platform/nix/INSTALL +56 -0
- data/platform/nix/Makefile +144 -0
- data/platform/nix/shoes.launch +20 -0
- data/platform/skel.rb +27 -0
- data/rakefile_darwin.rb +7 -0
- data/rakefile_linux.rb +3 -0
- data/rakefile_mingw.rb +7 -0
- data/samples/class-book.rb +43 -0
- data/samples/class-book.yaml +387 -0
- data/samples/expert-definr.rb +23 -0
- data/samples/expert-funnies.rb +51 -0
- data/samples/expert-irb.rb +112 -0
- data/samples/expert-minesweeper.rb +267 -0
- data/samples/expert-othello.rb +319 -0
- data/samples/expert-pong.rb +62 -0
- data/samples/expert-tankspank.rb +385 -0
- data/samples/good-arc.rb +37 -0
- data/samples/good-clock.rb +51 -0
- data/samples/good-follow.rb +26 -0
- data/samples/good-reminder.rb +174 -0
- data/samples/good-vjot.rb +56 -0
- data/samples/simple-accordion.rb +75 -0
- data/samples/simple-anim-shapes.rb +17 -0
- data/samples/simple-anim-text.rb +13 -0
- data/samples/simple-arc.rb +23 -0
- data/samples/simple-bounce.rb +24 -0
- data/samples/simple-calc.rb +70 -0
- data/samples/simple-chipmunk.rb +26 -0
- data/samples/simple-control-sizes.rb +24 -0
- data/samples/simple-curve.rb +26 -0
- data/samples/simple-dialogs.rb +29 -0
- data/samples/simple-downloader.rb +27 -0
- data/samples/simple-draw.rb +13 -0
- data/samples/simple-editor.rb +28 -0
- data/samples/simple-form.rb +28 -0
- data/samples/simple-form.shy +0 -0
- data/samples/simple-mask.rb +21 -0
- data/samples/simple-menu.rb +31 -0
- data/samples/simple-menu1.rb +35 -0
- data/samples/simple-rubygems.rb +29 -0
- data/samples/simple-slide.rb +45 -0
- data/samples/simple-sphere.rb +28 -0
- data/samples/simple-sqlite3.rb +13 -0
- data/samples/simple-timer.rb +13 -0
- data/samples/simple-video.rb +13 -0
- data/shoes.gemspec +21 -0
- data/shoes/app.c +591 -0
- data/shoes/app.h +110 -0
- data/shoes/appwin32.h +13 -0
- data/shoes/appwin32.rc +28 -0
- data/shoes/canvas.c +2202 -0
- data/shoes/canvas.h +682 -0
- data/shoes/code.h +14 -0
- data/shoes/config.h +232 -0
- data/shoes/effects.c +243 -0
- data/shoes/effects.h +7 -0
- data/shoes/http.h +44 -0
- data/shoes/http/common.h +86 -0
- data/shoes/http/curl.c +259 -0
- data/shoes/http/nsurl.m +274 -0
- data/shoes/http/windownload.c +114 -0
- data/shoes/http/winhttp.c +216 -0
- data/shoes/http/winhttp.h +19 -0
- data/shoes/image.c +1020 -0
- data/shoes/internal.c +46 -0
- data/shoes/internal.h +63 -0
- data/shoes/native.h +110 -0
- data/shoes/native/cocoa.h +105 -0
- data/shoes/native/cocoa.m +1557 -0
- data/shoes/native/gtk.c +1257 -0
- data/shoes/native/windows.c +2392 -0
- data/shoes/ruby.c +5221 -0
- data/shoes/ruby.h +299 -0
- data/shoes/world.c +243 -0
- data/shoes/world.h +63 -0
- data/static/Shoes.icns +0 -0
- data/static/avatar.png +0 -0
- data/static/code_highlighter.js +188 -0
- data/static/code_highlighter_ruby.js +26 -0
- data/static/icon-debug.png +0 -0
- data/static/icon-error.png +0 -0
- data/static/icon-info.png +0 -0
- data/static/icon-warn.png +0 -0
- data/static/listbox_button1.png +0 -0
- data/static/listbox_button2.png +0 -0
- data/static/man-app.png +0 -0
- data/static/man-builds.png +0 -0
- data/static/man-builds1.png +0 -0
- data/static/man-editor-notepad.png +0 -0
- data/static/man-editor-osx.png +0 -0
- data/static/man-ele-background.png +0 -0
- data/static/man-ele-border.png +0 -0
- data/static/man-ele-button.png +0 -0
- data/static/man-ele-check.png +0 -0
- data/static/man-ele-editbox.png +0 -0
- data/static/man-ele-editline.png +0 -0
- data/static/man-ele-image.png +0 -0
- data/static/man-ele-listbox.png +0 -0
- data/static/man-ele-progress.png +0 -0
- data/static/man-ele-radio.png +0 -0
- data/static/man-ele-shape.png +0 -0
- data/static/man-ele-textblock.png +0 -0
- data/static/man-ele-video.png +0 -0
- data/static/man-intro-dmg.png +0 -0
- data/static/man-intro-exe.png +0 -0
- data/static/man-look-tiger.png +0 -0
- data/static/man-look-ubuntu.png +0 -0
- data/static/man-look-vista.png +0 -0
- data/static/man-run-osx.png +0 -0
- data/static/man-run-vista.png +0 -0
- data/static/man-run-xp.png +0 -0
- data/static/man-shot1.png +0 -0
- data/static/manual-en.txt +3531 -0
- data/static/manual-ja.txt +2825 -0
- data/static/manual.css +167 -0
- data/static/menu-corner1.png +0 -0
- data/static/menu-corner2.png +0 -0
- data/static/menu-gray.png +0 -0
- data/static/menu-left.png +0 -0
- data/static/menu-right.png +0 -0
- data/static/menu-top.png +0 -0
- data/static/shoes-dmg.jpg +0 -0
- data/static/shoes-icon-blue.png +0 -0
- data/static/shoes-icon.png +0 -0
- data/static/shoes-manual-apps.gif +0 -0
- data/static/shoes_main_window.png +0 -0
- data/static/stripe.png +0 -0
- data/static/stubs/blank.exe +0 -0
- data/static/stubs/blank.hfz +0 -0
- data/static/stubs/blank.run +375 -0
- data/static/stubs/cocoa-install +0 -0
- data/static/stubs/sh-install +49 -0
- data/static/stubs/shoes-stub-inject.exe +0 -0
- data/static/stubs/shoes-stub.exe +0 -0
- data/static/tutor-back.png +0 -0
- data/test/shoes_test.rb +8 -0
- data/test/test_helper.rb +25 -0
- data/use-deps +12 -0
- data/use-tmp-dep +8 -0
- metadata +509 -0
data/shoes/effects.h
ADDED
data/shoes/http.h
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
//
|
2
|
+
// shoes/http.h
|
3
|
+
// the shoes downloader, which uses platform code and threads
|
4
|
+
// to achieve much faster and brain-dead http access.
|
5
|
+
//
|
6
|
+
#ifndef SHOES_HTTP_H
|
7
|
+
#define SHOES_HTTP_H
|
8
|
+
|
9
|
+
#include "shoes/http/common.h"
|
10
|
+
|
11
|
+
typedef struct {
|
12
|
+
char *url;
|
13
|
+
char *scheme;
|
14
|
+
char *host;
|
15
|
+
int port;
|
16
|
+
char *path;
|
17
|
+
|
18
|
+
char *method, *body;
|
19
|
+
unsigned long bodylen;
|
20
|
+
SHOES_DOWNLOAD_HEADERS headers;
|
21
|
+
|
22
|
+
char *mem;
|
23
|
+
unsigned long memlen;
|
24
|
+
char *filepath;
|
25
|
+
unsigned LONG_LONG size;
|
26
|
+
shoes_http_handler handler;
|
27
|
+
void *data;
|
28
|
+
unsigned char flags;
|
29
|
+
} shoes_http_request;
|
30
|
+
|
31
|
+
void shoes_download(shoes_http_request *req);
|
32
|
+
void shoes_queue_download(shoes_http_request *req);
|
33
|
+
VALUE shoes_http_err(SHOES_DOWNLOAD_ERROR error);
|
34
|
+
SHOES_DOWNLOAD_HEADERS shoes_http_headers(VALUE hsh);
|
35
|
+
void shoes_http_request_free(shoes_http_request *);
|
36
|
+
void shoes_http_headers_free(SHOES_DOWNLOAD_HEADERS);
|
37
|
+
|
38
|
+
#ifdef SHOES_WIN32
|
39
|
+
#include "shoes/http/winhttp.h"
|
40
|
+
#else
|
41
|
+
#define HTTP_HANDLER(x)
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#endif
|
data/shoes/http/common.h
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
//
|
2
|
+
// shoes/http/common.h
|
3
|
+
// cross-platform structures common to Shoes and its stubs
|
4
|
+
//
|
5
|
+
#ifndef SHOES_HTTP_COMMON_H
|
6
|
+
#define SHOES_HTTP_COMMON_H
|
7
|
+
|
8
|
+
#define SHOES_CHUNKSIZE 16384
|
9
|
+
|
10
|
+
#define SHOES_DL_REDIRECTS 1
|
11
|
+
#define SHOES_DL_DEFAULTS (SHOES_DL_REDIRECTS)
|
12
|
+
|
13
|
+
#define SHOES_DOWNLOAD_CONTINUE 0
|
14
|
+
#define SHOES_DOWNLOAD_HALT 1
|
15
|
+
|
16
|
+
#define SHOES_HTTP_STATUS 3
|
17
|
+
#define SHOES_HTTP_HEADER 4
|
18
|
+
#define SHOES_HTTP_CONNECTED 5
|
19
|
+
#define SHOES_HTTP_TRANSFER 10
|
20
|
+
#define SHOES_HTTP_COMPLETED 15
|
21
|
+
#define SHOES_HTTP_ERROR 20
|
22
|
+
|
23
|
+
#define HTTP_HEADER(ptr, realsize, handler, data) \
|
24
|
+
{ \
|
25
|
+
char *colon, *val, *end; \
|
26
|
+
for (colon = ptr; colon < ptr + realsize; colon++) \
|
27
|
+
if (colon[0] == ':') \
|
28
|
+
break; \
|
29
|
+
for (val = colon + 1; val < ptr + realsize; val++) \
|
30
|
+
if (val[0] != ' ') \
|
31
|
+
break; \
|
32
|
+
for (end = (ptr + realsize) - 1; end > ptr; end--) \
|
33
|
+
if (end[0] != '\r' && end[0] != '\n' && end[0] != ' ') \
|
34
|
+
break; \
|
35
|
+
if (colon < ptr + realsize) \
|
36
|
+
{ \
|
37
|
+
shoes_http_event *event = SHOE_ALLOC(shoes_http_event); \
|
38
|
+
event->stage = SHOES_HTTP_HEADER; \
|
39
|
+
event->hkey = ptr; \
|
40
|
+
event->hkeylen = colon - ptr; \
|
41
|
+
event->hval = val; \
|
42
|
+
event->hvallen = (end - val) + 1; \
|
43
|
+
if (handler != NULL) handler(event, data); \
|
44
|
+
SHOE_FREE(event); \
|
45
|
+
} \
|
46
|
+
}
|
47
|
+
|
48
|
+
#define HTTP_EVENT(handler, s, last, perc, trans, tot, dat, bd, abort) \
|
49
|
+
{ SHOES_TIME ts; \
|
50
|
+
shoes_get_time(&ts); \
|
51
|
+
unsigned long elapsed = shoes_diff_time(&(last), &ts); \
|
52
|
+
if (s != SHOES_HTTP_TRANSFER || elapsed > 600 ) { \
|
53
|
+
shoes_http_event *event = SHOE_ALLOC(shoes_http_event); \
|
54
|
+
event->stage = s; \
|
55
|
+
if (s == SHOES_HTTP_COMPLETED) event->stage = SHOES_HTTP_TRANSFER; \
|
56
|
+
event->percent = perc; \
|
57
|
+
event->transferred = trans;\
|
58
|
+
event->total = tot; \
|
59
|
+
last = ts; \
|
60
|
+
if (handler != NULL && (handler(event, dat) & SHOES_DOWNLOAD_HALT)) \
|
61
|
+
{ SHOE_FREE(event); event = NULL; abort; } \
|
62
|
+
if (event != NULL && s == SHOES_HTTP_COMPLETED) { event->stage = s; \
|
63
|
+
event->body = bd; \
|
64
|
+
if (handler != NULL && (handler(event, dat) & SHOES_DOWNLOAD_HALT)) \
|
65
|
+
{ SHOE_FREE(event); event = NULL; abort; } \
|
66
|
+
} \
|
67
|
+
if (event != NULL) SHOE_FREE(event); \
|
68
|
+
} }
|
69
|
+
|
70
|
+
typedef struct {
|
71
|
+
unsigned char stage;
|
72
|
+
unsigned long status;
|
73
|
+
char *hkey, *hval, *body;
|
74
|
+
unsigned long hkeylen, hvallen, bodylen;
|
75
|
+
unsigned LONG_LONG total;
|
76
|
+
unsigned LONG_LONG transferred;
|
77
|
+
unsigned long percent;
|
78
|
+
SHOES_DOWNLOAD_ERROR error;
|
79
|
+
} shoes_http_event;
|
80
|
+
|
81
|
+
typedef int (*shoes_http_handler)(shoes_http_event *, void *);
|
82
|
+
|
83
|
+
void shoes_get_time(SHOES_TIME *);
|
84
|
+
unsigned long shoes_diff_time(SHOES_TIME *, SHOES_TIME *);
|
85
|
+
|
86
|
+
#endif
|
data/shoes/http/curl.c
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
//
|
2
|
+
// shoes/http/curl.c
|
3
|
+
// the downloader routines using libcurl.
|
4
|
+
//
|
5
|
+
#include "shoes/app.h"
|
6
|
+
#include "shoes/ruby.h"
|
7
|
+
#include "shoes/config.h"
|
8
|
+
#include "shoes/http.h"
|
9
|
+
#include "shoes/version.h"
|
10
|
+
#include "shoes/internal.h"
|
11
|
+
#include <stdio.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <string.h>
|
14
|
+
#include <pthread.h>
|
15
|
+
|
16
|
+
typedef struct {
|
17
|
+
char *mem;
|
18
|
+
unsigned long memlen;
|
19
|
+
FILE *fp;
|
20
|
+
char *body;
|
21
|
+
size_t size, total, readpos, bodylen;
|
22
|
+
unsigned long status;
|
23
|
+
shoes_http_handler handler;
|
24
|
+
SHOES_TIME last;
|
25
|
+
CURL *curl;
|
26
|
+
void *data;
|
27
|
+
} shoes_curl_data;
|
28
|
+
|
29
|
+
const char *content_len_str = "Content-Length: ";
|
30
|
+
|
31
|
+
size_t
|
32
|
+
shoes_curl_header_funk(char *ptr, size_t size, size_t nmemb, void *user)
|
33
|
+
{
|
34
|
+
shoes_curl_data *data = (shoes_curl_data *)user;
|
35
|
+
size_t realsize = size * nmemb;
|
36
|
+
if (data->status == 0 && data->handler != NULL)
|
37
|
+
{
|
38
|
+
curl_easy_getinfo(data->curl, CURLINFO_RESPONSE_CODE, (long *)&data->status);
|
39
|
+
if (data->handler != NULL)
|
40
|
+
{
|
41
|
+
shoes_http_event *event = SHOE_ALLOC(shoes_http_event);
|
42
|
+
SHOE_MEMZERO(event, shoes_http_event, 1);
|
43
|
+
event->stage = SHOES_HTTP_STATUS;
|
44
|
+
event->status = data->status;
|
45
|
+
data->handler(event, data->data);
|
46
|
+
SHOE_FREE(event);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
HTTP_HEADER(ptr, realsize, data->handler, data->data);
|
51
|
+
if ((data->mem != NULL || data->fp != NULL) &&
|
52
|
+
strncmp(ptr, content_len_str, strlen(content_len_str)) == 0)
|
53
|
+
{
|
54
|
+
data->total = strtoull(ptr + strlen(content_len_str), NULL, 10);
|
55
|
+
if (data->mem != NULL && data->total > data->memlen)
|
56
|
+
{
|
57
|
+
data->memlen = data->total;
|
58
|
+
SHOE_REALLOC_N(data->mem, char, data->memlen);
|
59
|
+
if (data->mem == NULL) return -1;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
return realsize;
|
63
|
+
}
|
64
|
+
|
65
|
+
size_t
|
66
|
+
shoes_curl_read_funk(void *ptr, size_t size, size_t nmemb, void *user)
|
67
|
+
{
|
68
|
+
shoes_curl_data *data = (shoes_curl_data *)user;
|
69
|
+
size_t realsize = size * nmemb;
|
70
|
+
if (realsize > data->bodylen - data->readpos)
|
71
|
+
realsize = data->bodylen - data->readpos;
|
72
|
+
SHOE_MEMCPY(ptr, &(data->body[data->readpos]), char, realsize);
|
73
|
+
data->readpos += realsize;
|
74
|
+
return realsize;
|
75
|
+
}
|
76
|
+
|
77
|
+
size_t
|
78
|
+
shoes_curl_write_funk(void *ptr, size_t size, size_t nmemb, void *user)
|
79
|
+
{
|
80
|
+
shoes_curl_data *data = (shoes_curl_data *)user;
|
81
|
+
size_t realsize = size * nmemb;
|
82
|
+
if (data->size == 0)
|
83
|
+
{
|
84
|
+
HTTP_EVENT(data->handler, SHOES_HTTP_CONNECTED, data->last, 0, 0, data->total, data->data, NULL, return -1);
|
85
|
+
}
|
86
|
+
if (data->mem != NULL)
|
87
|
+
{
|
88
|
+
if (data->size + realsize > data->memlen)
|
89
|
+
{
|
90
|
+
while (data->size + realsize > data->memlen)
|
91
|
+
data->memlen += SHOES_BUFSIZE;
|
92
|
+
SHOE_REALLOC_N(data->mem, char, data->memlen);
|
93
|
+
if (data->mem == NULL) return -1;
|
94
|
+
}
|
95
|
+
SHOE_MEMCPY(&(data->mem[data->size]), ptr, char, realsize);
|
96
|
+
}
|
97
|
+
if (data->fp != NULL)
|
98
|
+
realsize = fwrite(ptr, size, nmemb, data->fp) * size;
|
99
|
+
if (realsize > 0)
|
100
|
+
data->size += realsize;
|
101
|
+
return realsize;
|
102
|
+
}
|
103
|
+
|
104
|
+
int
|
105
|
+
shoes_curl_progress_funk(void *user, double dltotal, double dlnow, double ultotal, double ulnow)
|
106
|
+
{
|
107
|
+
shoes_curl_data *data = (shoes_curl_data *)user;
|
108
|
+
if (dltotal > 0.)
|
109
|
+
{
|
110
|
+
HTTP_EVENT(data->handler, SHOES_HTTP_TRANSFER, data->last, dlnow * 100.0 / dltotal, dlnow,
|
111
|
+
dltotal, data->data, NULL, return 1);
|
112
|
+
}
|
113
|
+
return 0;
|
114
|
+
}
|
115
|
+
|
116
|
+
void
|
117
|
+
shoes_download(shoes_http_request *req)
|
118
|
+
{
|
119
|
+
char uagent[SHOES_BUFSIZE];
|
120
|
+
CURL *curl = curl_easy_init();
|
121
|
+
CURLcode res;
|
122
|
+
shoes_curl_data *cdata = SHOE_ALLOC(shoes_curl_data);
|
123
|
+
if (curl == NULL) return;
|
124
|
+
|
125
|
+
sprintf(uagent, "Shoes/0.r%d (%s) %s/%d", SHOES_REVISION, SHOES_PLATFORM,
|
126
|
+
SHOES_RELEASE_NAME, SHOES_BUILD_DATE);
|
127
|
+
|
128
|
+
cdata->mem = req->mem;
|
129
|
+
cdata->memlen = req->memlen;
|
130
|
+
cdata->fp = NULL;
|
131
|
+
cdata->size = cdata->readpos = req->size = 0;
|
132
|
+
cdata->total = 0;
|
133
|
+
cdata->handler = req->handler;
|
134
|
+
cdata->data = req->data;
|
135
|
+
cdata->last.tv_sec = 0;
|
136
|
+
cdata->last.tv_nsec = 0;
|
137
|
+
cdata->status = 0;
|
138
|
+
cdata->curl = curl;
|
139
|
+
cdata->body = NULL;
|
140
|
+
|
141
|
+
if (req->mem == NULL && req->filepath != NULL)
|
142
|
+
{
|
143
|
+
cdata->fp = fopen(req->filepath, "wb");
|
144
|
+
if (cdata->fp == NULL) goto done;
|
145
|
+
}
|
146
|
+
|
147
|
+
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
|
148
|
+
curl_easy_setopt(curl, CURLOPT_URL, req->url);
|
149
|
+
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, shoes_curl_header_funk);
|
150
|
+
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, cdata);
|
151
|
+
if (cdata->mem != NULL || cdata->fp != NULL)
|
152
|
+
{
|
153
|
+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, shoes_curl_write_funk);
|
154
|
+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, cdata);
|
155
|
+
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
156
|
+
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, shoes_curl_progress_funk);
|
157
|
+
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, cdata);
|
158
|
+
}
|
159
|
+
else
|
160
|
+
{
|
161
|
+
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
162
|
+
}
|
163
|
+
curl_easy_setopt(curl, CURLOPT_USERAGENT, uagent);
|
164
|
+
if (req->flags & SHOES_DL_REDIRECTS)
|
165
|
+
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
166
|
+
if (req->method)
|
167
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, req->method);
|
168
|
+
if (req->headers)
|
169
|
+
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, req->headers);
|
170
|
+
if (req->body)
|
171
|
+
{
|
172
|
+
cdata->body = req->body;
|
173
|
+
cdata->bodylen = req->bodylen;
|
174
|
+
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
175
|
+
curl_easy_setopt(curl, CURLOPT_INFILE, cdata);
|
176
|
+
curl_easy_setopt(curl, CURLOPT_INFILESIZE, cdata->bodylen);
|
177
|
+
curl_easy_setopt(curl, CURLOPT_READFUNCTION, shoes_curl_read_funk);
|
178
|
+
}
|
179
|
+
|
180
|
+
res = curl_easy_perform(curl);
|
181
|
+
req->size = cdata->size;
|
182
|
+
req->mem = cdata->mem;
|
183
|
+
|
184
|
+
if (res != CURLE_OK)
|
185
|
+
{
|
186
|
+
if (req->handler != NULL)
|
187
|
+
{
|
188
|
+
shoes_http_event *event = SHOE_ALLOC(shoes_http_event);
|
189
|
+
SHOE_MEMZERO(event, shoes_http_event, 1);
|
190
|
+
event->stage = SHOES_HTTP_ERROR;
|
191
|
+
event->error = res;
|
192
|
+
req->handler(event, req->data);
|
193
|
+
SHOE_FREE(event);
|
194
|
+
}
|
195
|
+
goto done;
|
196
|
+
}
|
197
|
+
|
198
|
+
if (cdata->fp != NULL)
|
199
|
+
{
|
200
|
+
fclose(cdata->fp);
|
201
|
+
cdata->fp = NULL;
|
202
|
+
}
|
203
|
+
|
204
|
+
HTTP_EVENT(cdata->handler, SHOES_HTTP_COMPLETED, cdata->last, 100, req->size, req->size, cdata->data, req->mem, goto done);
|
205
|
+
|
206
|
+
done:
|
207
|
+
if (cdata->fp != NULL)
|
208
|
+
fclose(cdata->fp);
|
209
|
+
if (cdata != NULL)
|
210
|
+
SHOE_FREE(cdata);
|
211
|
+
|
212
|
+
curl_easy_cleanup(curl);
|
213
|
+
}
|
214
|
+
|
215
|
+
void *
|
216
|
+
shoes_download2(void *data)
|
217
|
+
{
|
218
|
+
shoes_http_request *req = (shoes_http_request *)data;
|
219
|
+
shoes_download(req);
|
220
|
+
shoes_http_request_free(req);
|
221
|
+
free(req);
|
222
|
+
return NULL;
|
223
|
+
}
|
224
|
+
|
225
|
+
void
|
226
|
+
shoes_queue_download(shoes_http_request *req)
|
227
|
+
{
|
228
|
+
pthread_t tid;
|
229
|
+
pthread_create(&tid, NULL, shoes_download2, req);
|
230
|
+
}
|
231
|
+
|
232
|
+
VALUE
|
233
|
+
shoes_http_err(SHOES_DOWNLOAD_ERROR code)
|
234
|
+
{
|
235
|
+
return rb_str_new2(curl_easy_strerror(code));
|
236
|
+
}
|
237
|
+
|
238
|
+
SHOES_DOWNLOAD_HEADERS
|
239
|
+
shoes_http_headers(VALUE hsh)
|
240
|
+
{
|
241
|
+
long i;
|
242
|
+
struct curl_slist *slist = NULL;
|
243
|
+
VALUE keys = rb_funcall(hsh, s_keys, 0);
|
244
|
+
for (i = 0; i < RARRAY_LEN(keys); i++ )
|
245
|
+
{
|
246
|
+
VALUE key = rb_ary_entry(keys, i);
|
247
|
+
VALUE header = rb_str_dup(key);
|
248
|
+
rb_str_cat2(header, ": ");
|
249
|
+
rb_str_append(header, rb_hash_aref(hsh, key));
|
250
|
+
slist = curl_slist_append(slist, RSTRING_PTR(header));
|
251
|
+
}
|
252
|
+
return slist;
|
253
|
+
}
|
254
|
+
|
255
|
+
void
|
256
|
+
shoes_http_headers_free(struct curl_slist *slist)
|
257
|
+
{
|
258
|
+
curl_slist_free_all(slist);
|
259
|
+
}
|
data/shoes/http/nsurl.m
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
//
|
2
|
+
// shoes/http/nsurl.m
|
3
|
+
// the downloader routines using nsurl classes.
|
4
|
+
//
|
5
|
+
#include "shoes/app.h"
|
6
|
+
#include "shoes/ruby.h"
|
7
|
+
#include "shoes/internal.h"
|
8
|
+
#include "shoes/config.h"
|
9
|
+
#include "shoes/http.h"
|
10
|
+
#include "shoes/version.h"
|
11
|
+
#include "shoes/world.h"
|
12
|
+
#include "shoes/native.h"
|
13
|
+
|
14
|
+
#import <Cocoa/Cocoa.h>
|
15
|
+
|
16
|
+
@interface ShoesHttp : NSObject
|
17
|
+
{
|
18
|
+
char *dest;
|
19
|
+
unsigned long destlen;
|
20
|
+
NSURLConnection *conn;
|
21
|
+
NSURLDownload *down;
|
22
|
+
NSURLResponse *resp;
|
23
|
+
NSFileManager *fm;
|
24
|
+
long long size;
|
25
|
+
long long total;
|
26
|
+
unsigned char flags;
|
27
|
+
shoes_http_handler handler;
|
28
|
+
SHOES_TIME last;
|
29
|
+
NSMutableData *bytes;
|
30
|
+
void *data;
|
31
|
+
}
|
32
|
+
@end
|
33
|
+
|
34
|
+
@implementation ShoesHttp
|
35
|
+
- (id)init
|
36
|
+
{
|
37
|
+
if ((self = [super init]))
|
38
|
+
{
|
39
|
+
bytes = [[NSMutableData data] retain];
|
40
|
+
fm = [NSFileManager defaultManager];
|
41
|
+
destlen = 0;
|
42
|
+
}
|
43
|
+
return self;
|
44
|
+
}
|
45
|
+
- (void)releaseData
|
46
|
+
{
|
47
|
+
if (dest != NULL) free(dest);
|
48
|
+
if (data != NULL) free(data);
|
49
|
+
}
|
50
|
+
- (void)download: (shoes_http_request *)req
|
51
|
+
{
|
52
|
+
NSString *url = [NSString stringWithFormat: @"%s", req->url];
|
53
|
+
NSString *uagent = [NSString stringWithFormat: @"Shoes/0.r%d (%s) %s/%d",
|
54
|
+
SHOES_REVISION, SHOES_PLATFORM, SHOES_RELEASE_NAME, SHOES_BUILD_DATE];
|
55
|
+
NSMutableURLRequest *nsreq = [NSMutableURLRequest requestWithURL:
|
56
|
+
[NSURL URLWithString: url]
|
57
|
+
cachePolicy: NSURLRequestUseProtocolCachePolicy
|
58
|
+
timeoutInterval: 60.0];
|
59
|
+
[nsreq setValue: uagent forHTTPHeaderField: @"User-Agent"];
|
60
|
+
[nsreq setHTTPShouldHandleCookies: FALSE];
|
61
|
+
|
62
|
+
flags = req->flags;
|
63
|
+
handler = req->handler;
|
64
|
+
data = req->data;
|
65
|
+
if (req->headers != NULL)
|
66
|
+
[nsreq setAllHTTPHeaderFields: req->headers];
|
67
|
+
if (req->body != NULL && req->bodylen > 0)
|
68
|
+
[nsreq setHTTPBody: [NSData dataWithBytes: req->body length: req->bodylen]];
|
69
|
+
if (req->method != NULL)
|
70
|
+
[nsreq setHTTPMethod: [NSString stringWithUTF8String: req->method]];
|
71
|
+
last.tv_sec = 0;
|
72
|
+
last.tv_usec = 0;
|
73
|
+
size = total = 0;
|
74
|
+
if (req->filepath != NULL)
|
75
|
+
{
|
76
|
+
dest = req->filepath;
|
77
|
+
down = [[NSURLDownload alloc] initWithRequest: nsreq delegate: self];
|
78
|
+
req->filepath = NULL;
|
79
|
+
}
|
80
|
+
else
|
81
|
+
{
|
82
|
+
dest = req->mem;
|
83
|
+
destlen = req->memlen;
|
84
|
+
conn = [[NSURLConnection alloc] initWithRequest: nsreq
|
85
|
+
delegate: self];
|
86
|
+
req->mem = NULL;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
- (void)readHeaders: (NSURLResponse *)response
|
90
|
+
{
|
91
|
+
if ([response respondsToSelector:@selector(allHeaderFields)] && handler != NULL)
|
92
|
+
{
|
93
|
+
shoes_http_event *event = SHOE_ALLOC(shoes_http_event);
|
94
|
+
NSHTTPURLResponse* httpresp = (NSHTTPURLResponse *)response;
|
95
|
+
if ([httpresp statusCode])
|
96
|
+
{
|
97
|
+
SHOE_MEMZERO(event, shoes_http_event, 1);
|
98
|
+
event->stage = SHOES_HTTP_STATUS;
|
99
|
+
event->status = [httpresp statusCode];
|
100
|
+
handler(event, data);
|
101
|
+
}
|
102
|
+
|
103
|
+
NSDictionary *hdrs = [httpresp allHeaderFields];
|
104
|
+
if (hdrs)
|
105
|
+
{
|
106
|
+
NSString *key;
|
107
|
+
NSEnumerator *keys = [hdrs keyEnumerator];
|
108
|
+
while (key = [keys nextObject])
|
109
|
+
{
|
110
|
+
NSString *val = [hdrs objectForKey: key];
|
111
|
+
SHOE_MEMZERO(event, shoes_http_event, 1);
|
112
|
+
event->stage = SHOES_HTTP_HEADER;
|
113
|
+
event->hkey = [key UTF8String];
|
114
|
+
event->hkeylen = strlen(event->hkey);
|
115
|
+
event->hval = [val UTF8String];
|
116
|
+
event->hvallen = strlen(event->hval);
|
117
|
+
handler(event, data);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
SHOE_FREE(event);
|
122
|
+
}
|
123
|
+
}
|
124
|
+
- (void)handleError: (NSError *)error
|
125
|
+
{
|
126
|
+
if (handler != NULL)
|
127
|
+
{
|
128
|
+
shoes_http_event *event = SHOE_ALLOC(shoes_http_event);
|
129
|
+
SHOE_MEMZERO(event, shoes_http_event, 1);
|
130
|
+
event->stage = SHOES_HTTP_ERROR;
|
131
|
+
event->error = error;
|
132
|
+
handler(event, data);
|
133
|
+
SHOE_FREE(event);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
- (NSURLRequest *)connection: (NSURLConnection *)connection
|
137
|
+
willSendRequest: (NSURLRequest *)request
|
138
|
+
redirectResponse: (NSURLResponse *)redirectResponse
|
139
|
+
{
|
140
|
+
NSURLRequest *newRequest = request;
|
141
|
+
if (redirectResponse && !(flags & SHOES_DL_REDIRECTS))
|
142
|
+
newRequest = nil;
|
143
|
+
return newRequest;
|
144
|
+
}
|
145
|
+
- (void)connection: (NSURLConnection *)c didReceiveResponse: (NSURLResponse *)response
|
146
|
+
{
|
147
|
+
[self readHeaders: response];
|
148
|
+
size = total = 0;
|
149
|
+
if ([response expectedContentLength] != NSURLResponseUnknownLength)
|
150
|
+
total = [response expectedContentLength];
|
151
|
+
HTTP_EVENT(handler, SHOES_HTTP_CONNECTED, last, 0, 0, total, data, NULL, [c cancel]);
|
152
|
+
[bytes setLength: 0];
|
153
|
+
}
|
154
|
+
- (void)connection: (NSURLConnection *)c didFailWithError:(NSError *)error
|
155
|
+
{
|
156
|
+
[c release];
|
157
|
+
[self handleError: error];
|
158
|
+
}
|
159
|
+
- (void)connection: (NSURLConnection *)c didReceiveData: (NSData *)chunk
|
160
|
+
{
|
161
|
+
[bytes appendData: chunk];
|
162
|
+
size += [chunk length];
|
163
|
+
HTTP_EVENT(handler, SHOES_HTTP_TRANSFER, last, size * 100.0 / total, size,
|
164
|
+
total, data, NULL, [c cancel]);
|
165
|
+
}
|
166
|
+
- (void)connectionDidFinishLoading: (NSURLConnection *)c
|
167
|
+
{
|
168
|
+
total = [bytes length];
|
169
|
+
if (dest != NULL)
|
170
|
+
{
|
171
|
+
if ([bytes length] > destlen)
|
172
|
+
SHOE_REALLOC_N(dest, char, [bytes length]);
|
173
|
+
[bytes getBytes: dest];
|
174
|
+
}
|
175
|
+
HTTP_EVENT(handler, SHOES_HTTP_COMPLETED, last, 100, total, total, data, [bytes mutableBytes], 1);
|
176
|
+
[c release];
|
177
|
+
[self releaseData];
|
178
|
+
}
|
179
|
+
- (NSURLRequest *)download: (NSURLDownload *)download
|
180
|
+
willSendRequest: (NSURLRequest *)request
|
181
|
+
redirectResponse: (NSURLResponse *)redirectResponse
|
182
|
+
{
|
183
|
+
NSURLRequest *newRequest = request;
|
184
|
+
if (redirectResponse && !(flags & SHOES_DL_REDIRECTS))
|
185
|
+
newRequest = nil;
|
186
|
+
return newRequest;
|
187
|
+
}
|
188
|
+
- (void)download: (NSURLDownload *)download decideDestinationWithSuggestedFilename: (NSString *)filename
|
189
|
+
{
|
190
|
+
NSString *path = [NSString stringWithUTF8String: dest];
|
191
|
+
[download setDestination: path allowOverwrite: YES];
|
192
|
+
}
|
193
|
+
- (void)setDownloadResponse: (NSURLResponse *)aDownloadResponse
|
194
|
+
{
|
195
|
+
[aDownloadResponse retain];
|
196
|
+
[resp release];
|
197
|
+
resp = aDownloadResponse;
|
198
|
+
}
|
199
|
+
- (void)download: (NSURLDownload *)download didReceiveResponse: (NSURLResponse *)response
|
200
|
+
{
|
201
|
+
[self readHeaders: response];
|
202
|
+
size = total = 0;
|
203
|
+
if ([response expectedContentLength] != NSURLResponseUnknownLength)
|
204
|
+
total = [response expectedContentLength];
|
205
|
+
HTTP_EVENT(handler, SHOES_HTTP_CONNECTED, last, 0, 0, total, data, NULL, [download cancel]);
|
206
|
+
[self setDownloadResponse: response];
|
207
|
+
}
|
208
|
+
- (void)download: (NSURLDownload *)download didFailWithError:(NSError *)error
|
209
|
+
{
|
210
|
+
[download release];
|
211
|
+
[self handleError: error];
|
212
|
+
}
|
213
|
+
- (void)download: (NSURLDownload *)download didReceiveDataOfLength: (unsigned)length
|
214
|
+
{
|
215
|
+
size += length;
|
216
|
+
HTTP_EVENT(handler, SHOES_HTTP_TRANSFER, last, size * 100.0 / total, size,
|
217
|
+
total, data, NULL, [download cancel]);
|
218
|
+
}
|
219
|
+
- (void)downloadDidFinish: (NSURLDownload *)download
|
220
|
+
{
|
221
|
+
HTTP_EVENT(handler, SHOES_HTTP_COMPLETED, last, 100, total, total, data, NULL, 1);
|
222
|
+
[download release];
|
223
|
+
[self releaseData];
|
224
|
+
}
|
225
|
+
@end
|
226
|
+
|
227
|
+
void
|
228
|
+
shoes_download(shoes_http_request *req)
|
229
|
+
{
|
230
|
+
ShoesHttp *http = [[ShoesHttp alloc] init];
|
231
|
+
[http download: req];
|
232
|
+
shoes_http_request_free(req);
|
233
|
+
free(req);
|
234
|
+
}
|
235
|
+
|
236
|
+
void
|
237
|
+
shoes_queue_download(shoes_http_request *req)
|
238
|
+
{
|
239
|
+
shoes_download(req);
|
240
|
+
}
|
241
|
+
|
242
|
+
VALUE
|
243
|
+
shoes_http_err(SHOES_DOWNLOAD_ERROR code)
|
244
|
+
{
|
245
|
+
char *errorString = [[code localizedDescription] UTF8String];
|
246
|
+
return rb_str_new2(errorString);
|
247
|
+
}
|
248
|
+
|
249
|
+
SHOES_DOWNLOAD_HEADERS
|
250
|
+
shoes_http_headers(VALUE hsh)
|
251
|
+
{
|
252
|
+
long i;
|
253
|
+
NSDictionary *d = NULL;
|
254
|
+
VALUE keys = rb_funcall(hsh, s_keys, 0);
|
255
|
+
if (RARRAY_LEN(keys) > 0)
|
256
|
+
{
|
257
|
+
d = [[NSMutableDictionary dictionaryWithCapacity: RARRAY_LEN(keys)] retain];
|
258
|
+
for (i = 0; i < RARRAY_LEN(keys); i++)
|
259
|
+
{
|
260
|
+
VALUE key = rb_ary_entry(keys, i);
|
261
|
+
VALUE val = rb_hash_aref(hsh, key);
|
262
|
+
if(!NIL_P(val))
|
263
|
+
[d setValue: [NSString stringWithUTF8String: RSTRING_PTR(val)]
|
264
|
+
forKey: [NSString stringWithUTF8String: RSTRING_PTR(key)]];
|
265
|
+
}
|
266
|
+
}
|
267
|
+
return d;
|
268
|
+
}
|
269
|
+
|
270
|
+
void
|
271
|
+
shoes_http_headers_free(SHOES_DOWNLOAD_HEADERS headers)
|
272
|
+
{
|
273
|
+
[headers release];
|
274
|
+
}
|