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.
Files changed (275) hide show
  1. data/.gitignore +12 -0
  2. data/CHANGELOG +29 -0
  3. data/COPYING +30 -0
  4. data/README.md +76 -0
  5. data/README.old +117 -0
  6. data/Rakefile +130 -0
  7. data/Rakefile.bk +651 -0
  8. data/app.yaml +7 -0
  9. data/bin/main.skel +104 -0
  10. data/bugs/issue-012e9468ddc7b0cb7e1503413a8a11c4f8707b67.yaml +21 -0
  11. data/bugs/issue-0711ff8b67baa63586f11d0096fee9dd4436bf58.yaml +23 -0
  12. data/bugs/issue-07f87998d93eb401e22395c11085676389b935c4.yaml +22 -0
  13. data/bugs/issue-0bff2d80008803cbc7efbcdacdc60ef2163664d2.yaml +22 -0
  14. data/bugs/issue-0c66f223d19efbca7b692f3b91961f407ad7abec.yaml +24 -0
  15. data/bugs/issue-183bc3c7a8f575aff2b24e0bf22aa0dfcc8e4fc2.yaml +29 -0
  16. data/bugs/issue-1bad1e60a04cb3adb6a8f3ded128af2e16b56ffe.yaml +18 -0
  17. data/bugs/issue-1f1d43f76bf4de79d7f94adbae6dd506a9d81633.yaml +41 -0
  18. data/bugs/issue-320924117cadb045cc91f2a6fca922b4d81d4bb5.yaml +20 -0
  19. data/bugs/issue-33e5c8355fbf65252ea9e939714651df8bd8cb3b.yaml +25 -0
  20. data/bugs/issue-36f7c8262a72bcd5e28cfa4ed29328b8237ea79b.yaml +20 -0
  21. data/bugs/issue-39bf04ee50c3bef67b89b8e9beb28657805587ce.yaml +18 -0
  22. data/bugs/issue-3e28ba7754f73d02ef416eef989af707a8c00f01.yaml +23 -0
  23. data/bugs/issue-3f638cc03f41f9c3fdf217355321f1563f8fee45.yaml +22 -0
  24. data/bugs/issue-41e48e14f1ef4f6deb69be68165d7dd3ffd99156.yaml +22 -0
  25. data/bugs/issue-4c9408166a2aa5dd333bbb05520deebf4ded08e0.yaml +22 -0
  26. data/bugs/issue-55c687e108ecd5aeb8e0d0aeb4294984f84acd3e.yaml +18 -0
  27. data/bugs/issue-5811d34692cc292717a58ec1df1f8948cf30d826.yaml +28 -0
  28. data/bugs/issue-5a7c1f59a0526f9cea7fb366867cf1e6ed8ef69d.yaml +22 -0
  29. data/bugs/issue-688a2c2566bef6a03efa57a4ae1f7cfa8fc74444.yaml +21 -0
  30. data/bugs/issue-78b16c7988ade2ef96e716fa8cb9a004bd4ced65.yaml +33 -0
  31. data/bugs/issue-804ee49f9800154eddf0650690c7a9bb5626253f.yaml +27 -0
  32. data/bugs/issue-807dd1c610b2e941a5d454e26b2eac27e89a0ab4.yaml +22 -0
  33. data/bugs/issue-822ee33ec11ebd25f90ea86e8438de7891e63aee.yaml +18 -0
  34. data/bugs/issue-82ff7152cebb8a1cb065b864cb4fe22de2328146.yaml +29 -0
  35. data/bugs/issue-856afbdcdd4970ad54b8ce4a6c017fbaab45f49d.yaml +31 -0
  36. data/bugs/issue-8d49e32fb21522651c67490adb4d80076dbb14e1.yaml +24 -0
  37. data/bugs/issue-91583359653a9d530c1e32be72d874d847a306e7.yaml +21 -0
  38. data/bugs/issue-af41a5229613172764e7d3c98431172db337053d.yaml +20 -0
  39. data/bugs/issue-bd9856b3788dd429c998a5af1b2aae8221cb80b7.yaml +28 -0
  40. data/bugs/issue-be22aef5c564fb7b5e9938343136a9cd6a2edb7b.yaml +22 -0
  41. data/bugs/issue-bf8697523c77c326e7e35fc82cf3dd739ae92310.yaml +27 -0
  42. data/bugs/issue-cdd4b4795f34d6ff46e56ece10f8216a4a5456b2.yaml +25 -0
  43. data/bugs/issue-d9bfb5581d745ef9deb3b9b2e08ef74d1cd43082.yaml +20 -0
  44. data/bugs/issue-e0ce2f687cc096f35715d28b0af88589f4ab6cc6.yaml +18 -0
  45. data/bugs/issue-e4b0aca4a10a574b333aeaecaaf221dbc5ed22c6.yaml +38 -0
  46. data/bugs/issue-f263746594b95ba778455730478ee8df60ee639d.yaml +22 -0
  47. data/bugs/project.yaml +72 -0
  48. data/builddeps.sh +102 -0
  49. data/fonts/Coolvetica.ttf +0 -0
  50. data/fonts/Lacuna.ttf +0 -0
  51. data/gemlib/shoes.rb +1 -0
  52. data/lib/shoes.rb +548 -0
  53. data/lib/shoes/cache.rb +54 -0
  54. data/lib/shoes/chipmunk.rb +35 -0
  55. data/lib/shoes/data.rb +39 -0
  56. data/lib/shoes/help.rb +468 -0
  57. data/lib/shoes/image.rb +25 -0
  58. data/lib/shoes/inspect.rb +128 -0
  59. data/lib/shoes/log.rb +48 -0
  60. data/lib/shoes/minitar.rb +986 -0
  61. data/lib/shoes/override.rb +38 -0
  62. data/lib/shoes/pack.rb +543 -0
  63. data/lib/shoes/search.rb +46 -0
  64. data/lib/shoes/setup.rb +329 -0
  65. data/lib/shoes/shy.rb +131 -0
  66. data/lib/shoes/shybuilder.rb +44 -0
  67. data/lib/shoes/version.rb +3 -0
  68. data/make/darwin/deps.vlc +12 -0
  69. data/make/darwin/dylibs.shoes +22 -0
  70. data/make/darwin/dylibs.video +11 -0
  71. data/make/darwin/env.rb +81 -0
  72. data/make/darwin/tasks.rb +105 -0
  73. data/make/linux/env.rb +65 -0
  74. data/make/linux/tasks.rb +61 -0
  75. data/make/make.rb +85 -0
  76. data/make/mingw/dlls +19 -0
  77. data/make/mingw/env.rb +69 -0
  78. data/make/mingw/tasks.rb +70 -0
  79. data/make/rakefile_common.rb +8 -0
  80. data/manual-snapshots/class-book.png +0 -0
  81. data/manual-snapshots/expert-definr.png +0 -0
  82. data/manual-snapshots/expert-funnies.png +0 -0
  83. data/manual-snapshots/expert-irb.png +0 -0
  84. data/manual-snapshots/expert-minesweeper.png +0 -0
  85. data/manual-snapshots/expert-othello.png +0 -0
  86. data/manual-snapshots/expert-pong.png +0 -0
  87. data/manual-snapshots/expert-tankspank.png +0 -0
  88. data/manual-snapshots/good-arc.png +0 -0
  89. data/manual-snapshots/good-clock.png +0 -0
  90. data/manual-snapshots/good-follow.png +0 -0
  91. data/manual-snapshots/good-reminder.png +0 -0
  92. data/manual-snapshots/good-vjot.png +0 -0
  93. data/manual-snapshots/simple-accordion.png +0 -0
  94. data/manual-snapshots/simple-anim-shapes.png +0 -0
  95. data/manual-snapshots/simple-anim-text.png +0 -0
  96. data/manual-snapshots/simple-arc.png +0 -0
  97. data/manual-snapshots/simple-bounce.png +0 -0
  98. data/manual-snapshots/simple-calc.png +0 -0
  99. data/manual-snapshots/simple-chipmunk.png +0 -0
  100. data/manual-snapshots/simple-control-sizes.png +0 -0
  101. data/manual-snapshots/simple-curve.png +0 -0
  102. data/manual-snapshots/simple-dialogs.png +0 -0
  103. data/manual-snapshots/simple-downloader.png +0 -0
  104. data/manual-snapshots/simple-draw.png +0 -0
  105. data/manual-snapshots/simple-editor.png +0 -0
  106. data/manual-snapshots/simple-form.png +0 -0
  107. data/manual-snapshots/simple-mask.png +0 -0
  108. data/manual-snapshots/simple-menu.png +0 -0
  109. data/manual-snapshots/simple-menu1.png +0 -0
  110. data/manual-snapshots/simple-rubygems.png +0 -0
  111. data/manual-snapshots/simple-slide.png +0 -0
  112. data/manual-snapshots/simple-sphere.png +0 -0
  113. data/manual-snapshots/simple-sqlite3.png +0 -0
  114. data/manual-snapshots/simple-timer.png +0 -0
  115. data/manual-snapshots/simple-video.png +0 -0
  116. data/platform/mac/Info.plist +55 -0
  117. data/platform/mac/build-deps.sh +658 -0
  118. data/platform/mac/command-manual.rb +1 -0
  119. data/platform/mac/deps-osx.patch +159 -0
  120. data/platform/mac/dmg_ds_store +0 -0
  121. data/platform/mac/pangorc +2 -0
  122. data/platform/mac/pkg-dmg +1447 -0
  123. data/platform/mac/shoes +31 -0
  124. data/platform/mac/shoes-launch +7 -0
  125. data/platform/mac/stub.m +178 -0
  126. data/platform/mac/version.plist +14 -0
  127. data/platform/msw/base.nsi +644 -0
  128. data/platform/msw/installer-1.bmp +0 -0
  129. data/platform/msw/installer-2.bmp +0 -0
  130. data/platform/msw/shoes.exe.manifest +17 -0
  131. data/platform/msw/shoes.ico +0 -0
  132. data/platform/msw/stub-inject.c +59 -0
  133. data/platform/msw/stub.c +271 -0
  134. data/platform/msw/stub32.h +14 -0
  135. data/platform/msw/stub32.rc +16 -0
  136. data/platform/nix/INSTALL +56 -0
  137. data/platform/nix/Makefile +144 -0
  138. data/platform/nix/shoes.launch +20 -0
  139. data/platform/skel.rb +27 -0
  140. data/rakefile_darwin.rb +7 -0
  141. data/rakefile_linux.rb +3 -0
  142. data/rakefile_mingw.rb +7 -0
  143. data/samples/class-book.rb +43 -0
  144. data/samples/class-book.yaml +387 -0
  145. data/samples/expert-definr.rb +23 -0
  146. data/samples/expert-funnies.rb +51 -0
  147. data/samples/expert-irb.rb +112 -0
  148. data/samples/expert-minesweeper.rb +267 -0
  149. data/samples/expert-othello.rb +319 -0
  150. data/samples/expert-pong.rb +62 -0
  151. data/samples/expert-tankspank.rb +385 -0
  152. data/samples/good-arc.rb +37 -0
  153. data/samples/good-clock.rb +51 -0
  154. data/samples/good-follow.rb +26 -0
  155. data/samples/good-reminder.rb +174 -0
  156. data/samples/good-vjot.rb +56 -0
  157. data/samples/simple-accordion.rb +75 -0
  158. data/samples/simple-anim-shapes.rb +17 -0
  159. data/samples/simple-anim-text.rb +13 -0
  160. data/samples/simple-arc.rb +23 -0
  161. data/samples/simple-bounce.rb +24 -0
  162. data/samples/simple-calc.rb +70 -0
  163. data/samples/simple-chipmunk.rb +26 -0
  164. data/samples/simple-control-sizes.rb +24 -0
  165. data/samples/simple-curve.rb +26 -0
  166. data/samples/simple-dialogs.rb +29 -0
  167. data/samples/simple-downloader.rb +27 -0
  168. data/samples/simple-draw.rb +13 -0
  169. data/samples/simple-editor.rb +28 -0
  170. data/samples/simple-form.rb +28 -0
  171. data/samples/simple-form.shy +0 -0
  172. data/samples/simple-mask.rb +21 -0
  173. data/samples/simple-menu.rb +31 -0
  174. data/samples/simple-menu1.rb +35 -0
  175. data/samples/simple-rubygems.rb +29 -0
  176. data/samples/simple-slide.rb +45 -0
  177. data/samples/simple-sphere.rb +28 -0
  178. data/samples/simple-sqlite3.rb +13 -0
  179. data/samples/simple-timer.rb +13 -0
  180. data/samples/simple-video.rb +13 -0
  181. data/shoes.gemspec +21 -0
  182. data/shoes/app.c +591 -0
  183. data/shoes/app.h +110 -0
  184. data/shoes/appwin32.h +13 -0
  185. data/shoes/appwin32.rc +28 -0
  186. data/shoes/canvas.c +2202 -0
  187. data/shoes/canvas.h +682 -0
  188. data/shoes/code.h +14 -0
  189. data/shoes/config.h +232 -0
  190. data/shoes/effects.c +243 -0
  191. data/shoes/effects.h +7 -0
  192. data/shoes/http.h +44 -0
  193. data/shoes/http/common.h +86 -0
  194. data/shoes/http/curl.c +259 -0
  195. data/shoes/http/nsurl.m +274 -0
  196. data/shoes/http/windownload.c +114 -0
  197. data/shoes/http/winhttp.c +216 -0
  198. data/shoes/http/winhttp.h +19 -0
  199. data/shoes/image.c +1020 -0
  200. data/shoes/internal.c +46 -0
  201. data/shoes/internal.h +63 -0
  202. data/shoes/native.h +110 -0
  203. data/shoes/native/cocoa.h +105 -0
  204. data/shoes/native/cocoa.m +1557 -0
  205. data/shoes/native/gtk.c +1257 -0
  206. data/shoes/native/windows.c +2392 -0
  207. data/shoes/ruby.c +5221 -0
  208. data/shoes/ruby.h +299 -0
  209. data/shoes/world.c +243 -0
  210. data/shoes/world.h +63 -0
  211. data/static/Shoes.icns +0 -0
  212. data/static/avatar.png +0 -0
  213. data/static/code_highlighter.js +188 -0
  214. data/static/code_highlighter_ruby.js +26 -0
  215. data/static/icon-debug.png +0 -0
  216. data/static/icon-error.png +0 -0
  217. data/static/icon-info.png +0 -0
  218. data/static/icon-warn.png +0 -0
  219. data/static/listbox_button1.png +0 -0
  220. data/static/listbox_button2.png +0 -0
  221. data/static/man-app.png +0 -0
  222. data/static/man-builds.png +0 -0
  223. data/static/man-builds1.png +0 -0
  224. data/static/man-editor-notepad.png +0 -0
  225. data/static/man-editor-osx.png +0 -0
  226. data/static/man-ele-background.png +0 -0
  227. data/static/man-ele-border.png +0 -0
  228. data/static/man-ele-button.png +0 -0
  229. data/static/man-ele-check.png +0 -0
  230. data/static/man-ele-editbox.png +0 -0
  231. data/static/man-ele-editline.png +0 -0
  232. data/static/man-ele-image.png +0 -0
  233. data/static/man-ele-listbox.png +0 -0
  234. data/static/man-ele-progress.png +0 -0
  235. data/static/man-ele-radio.png +0 -0
  236. data/static/man-ele-shape.png +0 -0
  237. data/static/man-ele-textblock.png +0 -0
  238. data/static/man-ele-video.png +0 -0
  239. data/static/man-intro-dmg.png +0 -0
  240. data/static/man-intro-exe.png +0 -0
  241. data/static/man-look-tiger.png +0 -0
  242. data/static/man-look-ubuntu.png +0 -0
  243. data/static/man-look-vista.png +0 -0
  244. data/static/man-run-osx.png +0 -0
  245. data/static/man-run-vista.png +0 -0
  246. data/static/man-run-xp.png +0 -0
  247. data/static/man-shot1.png +0 -0
  248. data/static/manual-en.txt +3531 -0
  249. data/static/manual-ja.txt +2825 -0
  250. data/static/manual.css +167 -0
  251. data/static/menu-corner1.png +0 -0
  252. data/static/menu-corner2.png +0 -0
  253. data/static/menu-gray.png +0 -0
  254. data/static/menu-left.png +0 -0
  255. data/static/menu-right.png +0 -0
  256. data/static/menu-top.png +0 -0
  257. data/static/shoes-dmg.jpg +0 -0
  258. data/static/shoes-icon-blue.png +0 -0
  259. data/static/shoes-icon.png +0 -0
  260. data/static/shoes-manual-apps.gif +0 -0
  261. data/static/shoes_main_window.png +0 -0
  262. data/static/stripe.png +0 -0
  263. data/static/stubs/blank.exe +0 -0
  264. data/static/stubs/blank.hfz +0 -0
  265. data/static/stubs/blank.run +375 -0
  266. data/static/stubs/cocoa-install +0 -0
  267. data/static/stubs/sh-install +49 -0
  268. data/static/stubs/shoes-stub-inject.exe +0 -0
  269. data/static/stubs/shoes-stub.exe +0 -0
  270. data/static/tutor-back.png +0 -0
  271. data/test/shoes_test.rb +8 -0
  272. data/test/test_helper.rb +25 -0
  273. data/use-deps +12 -0
  274. data/use-tmp-dep +8 -0
  275. metadata +509 -0
@@ -0,0 +1,7 @@
1
+ //
2
+ // shoes/effects.h
3
+ // The presently meager effects API.
4
+ //
5
+ void shoes_gaussian_blur_filter(cairo_t *, VALUE, shoes_place *);
6
+ void shoes_shadow_filter(cairo_t *, VALUE, shoes_place *);
7
+ void shoes_glow_filter(cairo_t *, VALUE, shoes_place *);
@@ -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
@@ -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
@@ -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
+ }
@@ -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
+ }