curb 0.8.4 → 1.3.5

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +522 -0
  3. data/Rakefile +79 -26
  4. data/ext/banned.h +32 -0
  5. data/ext/curb.c +549 -230
  6. data/ext/curb.h +19 -10
  7. data/ext/curb_easy.c +1935 -366
  8. data/ext/curb_easy.h +16 -0
  9. data/ext/curb_errors.c +115 -18
  10. data/ext/curb_errors.h +8 -5
  11. data/ext/curb_macros.h +33 -21
  12. data/ext/curb_multi.c +1858 -272
  13. data/ext/curb_multi.h +10 -3
  14. data/ext/curb_postfield.c +149 -77
  15. data/ext/curb_postfield.h +1 -0
  16. data/ext/curb_upload.c +38 -11
  17. data/ext/curb_upload.h +2 -0
  18. data/ext/extconf.rb +353 -35
  19. data/lib/curb.rb +1 -0
  20. data/lib/curl/easy.rb +314 -78
  21. data/lib/curl/multi.rb +134 -28
  22. data/lib/curl.rb +217 -11
  23. data/tests/bug_crash_on_debug.rb +14 -28
  24. data/tests/bug_crash_on_progress.rb +32 -16
  25. data/tests/bug_curb_easy_blocks_ruby_threads.rb +10 -15
  26. data/tests/bug_curb_easy_post_with_string_no_content_length_header.rb +6 -30
  27. data/tests/bug_follow_redirect_288.rb +83 -0
  28. data/tests/bug_instance_post_differs_from_class_post.rb +3 -5
  29. data/tests/bug_issue102.rb +1 -1
  30. data/tests/bug_issue_noproxy.rb +56 -0
  31. data/tests/bug_issue_post_redirect.rb +93 -0
  32. data/tests/bug_issue_spnego.rb +41 -0
  33. data/tests/bug_multi_segfault.rb +1 -0
  34. data/tests/bug_raise_on_callback.rb +30 -0
  35. data/tests/helper.rb +400 -44
  36. data/tests/leak_trace.rb +237 -0
  37. data/tests/mem_check.rb +3 -0
  38. data/tests/tc_curl.rb +31 -1
  39. data/tests/tc_curl_download.rb +12 -7
  40. data/tests/tc_curl_easy.rb +911 -63
  41. data/tests/tc_curl_easy_cookielist.rb +277 -0
  42. data/tests/tc_curl_easy_request_target.rb +41 -0
  43. data/tests/tc_curl_easy_resolve.rb +48 -0
  44. data/tests/tc_curl_maxfilesize.rb +12 -0
  45. data/tests/tc_curl_multi.rb +855 -53
  46. data/tests/tc_curl_native_coverage.rb +145 -0
  47. data/tests/tc_curl_postfield.rb +207 -30
  48. data/tests/tc_curl_protocols.rb +37 -0
  49. data/tests/tc_fiber_scheduler.rb +543 -0
  50. data/tests/tc_ftp_options.rb +39 -0
  51. data/tests/tc_gc_compact.rb +223 -0
  52. data/tests/tc_test_server_methods.rb +110 -0
  53. data/tests/timeout.rb +30 -6
  54. metadata +59 -36
  55. data/README +0 -194
data/ext/curb_multi.h CHANGED
@@ -8,19 +8,26 @@
8
8
  #define __CURB_MULTI_H
9
9
 
10
10
  #include "curb.h"
11
- #include "curb_easy.h"
12
11
  #include <curl/multi.h>
13
12
 
13
+ struct st_table;
14
+
14
15
  typedef struct {
15
16
  int active;
16
17
  int running;
17
- VALUE requests; /* hash of handles currently added */
18
+ char closed;
19
+ char perform_active;
20
+ char callback_active;
21
+ char allow_close_during_perform;
18
22
  CURLM *handle;
23
+ struct st_table *attached;
19
24
  } ruby_curl_multi;
20
25
 
21
26
  extern VALUE cCurlMulti;
27
+ extern const rb_data_type_t ruby_curl_multi_data_type;
28
+
22
29
  void init_curb_multi();
23
- VALUE ruby_curl_multi_new(VALUE klass);
30
+ void rb_curl_multi_forget_easy(ruby_curl_multi *rbcm, void *rbce_ptr);
24
31
 
25
32
 
26
33
  #endif
data/ext/curb_postfield.c CHANGED
@@ -32,7 +32,7 @@ void append_to_form(VALUE self,
32
32
  ruby_curl_postfield *rbcpf;
33
33
  CURLFORMcode result = -1;
34
34
 
35
- Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
35
+ TypedData_Get_Struct(self, ruby_curl_postfield, &ruby_curl_postfield_data_type, rbcpf);
36
36
 
37
37
  if (rbcpf->name == Qnil) {
38
38
  rb_raise(eCurlErrInvalidPostField, "Cannot post unnamed field");
@@ -177,27 +177,52 @@ void append_to_form(VALUE self,
177
177
 
178
178
 
179
179
  /* ================== MARK/FREE FUNC ==================*/
180
- void curl_postfield_mark(ruby_curl_postfield *rbcpf) {
181
- rb_gc_mark(rbcpf->name);
182
- rb_gc_mark(rbcpf->content);
183
- rb_gc_mark(rbcpf->content_type);
184
- rb_gc_mark(rbcpf->local_file);
185
- rb_gc_mark(rbcpf->remote_file);
186
- rb_gc_mark(rbcpf->buffer_str);
180
+ static void curl_postfield_mark(void *ptr) {
181
+ ruby_curl_postfield *rbcpf = (ruby_curl_postfield *)ptr;
182
+ if (rbcpf) {
183
+ rb_gc_mark(rbcpf->name);
184
+ rb_gc_mark(rbcpf->content);
185
+ rb_gc_mark(rbcpf->content_type);
186
+ rb_gc_mark(rbcpf->content_proc);
187
+ rb_gc_mark(rbcpf->local_file);
188
+ rb_gc_mark(rbcpf->remote_file);
189
+ rb_gc_mark(rbcpf->buffer_str);
190
+ }
187
191
  }
188
192
 
189
- void curl_postfield_free(ruby_curl_postfield *rbcpf) {
190
- free(rbcpf);
193
+ static void curl_postfield_free(void *ptr) {
194
+ if (ptr) free(ptr);
191
195
  }
192
196
 
197
+ static size_t curl_postfield_memsize(const void *ptr) {
198
+ (void)ptr;
199
+ return sizeof(ruby_curl_postfield);
200
+ }
201
+
202
+ const rb_data_type_t ruby_curl_postfield_data_type = {
203
+ "Curl::PostField",
204
+ {
205
+ curl_postfield_mark,
206
+ curl_postfield_free,
207
+ curl_postfield_memsize,
208
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
209
+ NULL, /* compact */
210
+ #endif
211
+ },
212
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
213
+ NULL, NULL, /* parent, data */
214
+ RUBY_TYPED_FREE_IMMEDIATELY
215
+ #endif
216
+ };
217
+
193
218
 
194
219
  /* ================= ALLOC METHODS ====================*/
195
220
 
196
221
  /*
197
222
  * call-seq:
198
- * Curl::PostField.content(name, content) => #&lt;Curl::PostField...&gt;
199
- * Curl::PostField.content(name, content, content_type = nil) => #&lt;Curl::PostField...&gt;
200
- * Curl::PostField.content(name, content_type = nil) { |field| ... } => #&lt;Curl::PostField...&gt;
223
+ * Curl::PostField.content(name, content) => #<Curl::PostField...>
224
+ * Curl::PostField.content(name, content, content_type = nil) => #<Curl::PostField...>
225
+ * Curl::PostField.content(name, content_type = nil) { |field| ... } => #<Curl::PostField...>
201
226
  *
202
227
  * Create a new Curl::PostField, supplying the field name, content,
203
228
  * and, optionally, Content-type (curl will attempt to determine this if
@@ -208,7 +233,11 @@ void curl_postfield_free(ruby_curl_postfield *rbcpf) {
208
233
  * data.
209
234
  */
210
235
  static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass) {
211
- ruby_curl_postfield *rbcpf = ALLOC(ruby_curl_postfield);
236
+ VALUE self;
237
+ ruby_curl_postfield *rbcpf;
238
+
239
+ self = TypedData_Make_Struct(klass, ruby_curl_postfield, &ruby_curl_postfield_data_type, rbcpf);
240
+ MEMZERO(rbcpf, ruby_curl_postfield, 1);
212
241
 
213
242
  // wierdness - we actually require two args, unless a block is provided, but
214
243
  // we have to work that out below.
@@ -236,14 +265,14 @@ static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass)
236
265
  rbcpf->remote_file = Qnil;
237
266
  rbcpf->buffer_str = Qnil;
238
267
 
239
- return Data_Wrap_Struct(cCurlPostField, curl_postfield_mark, curl_postfield_free, rbcpf);
268
+ return self;
240
269
  }
241
270
 
242
271
  /*
243
272
  * call-seq:
244
- * Curl::PostField.file(name, local_file_name) => #&lt;Curl::PostField...&gt;
245
- * Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #&lt;Curl::PostField...&gt;
246
- * Curl::PostField.file(name, remote_file_name) { |field| ... } => #&lt;Curl::PostField...&gt;
273
+ * Curl::PostField.file(name, local_file_name) => #<Curl::PostField...>
274
+ * Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #<Curl::PostField...>
275
+ * Curl::PostField.file(name, remote_file_name) { |field| ... } => #<Curl::PostField...>
247
276
  *
248
277
  * Create a new Curl::PostField for a file upload field, supplying the local filename
249
278
  * to read from, and optionally the remote filename (defaults to the local name).
@@ -254,7 +283,11 @@ static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass)
254
283
  */
255
284
  static VALUE ruby_curl_postfield_new_file(int argc, VALUE *argv, VALUE klass) {
256
285
  // TODO needs to handle content-type too
257
- ruby_curl_postfield *rbcpf = ALLOC(ruby_curl_postfield);
286
+ VALUE self;
287
+ ruby_curl_postfield *rbcpf;
288
+
289
+ self = TypedData_Make_Struct(klass, ruby_curl_postfield, &ruby_curl_postfield_data_type, rbcpf);
290
+ MEMZERO(rbcpf, ruby_curl_postfield, 1);
258
291
 
259
292
  rb_scan_args(argc, argv, "21&", &rbcpf->name, &rbcpf->local_file, &rbcpf->remote_file, &rbcpf->content_proc);
260
293
 
@@ -282,7 +315,7 @@ static VALUE ruby_curl_postfield_new_file(int argc, VALUE *argv, VALUE klass) {
282
315
  rbcpf->content_type = Qnil;
283
316
  rbcpf->buffer_str = Qnil;
284
317
 
285
- return Data_Wrap_Struct(cCurlPostField, curl_postfield_mark, curl_postfield_free, rbcpf);
318
+ return self;
286
319
  }
287
320
 
288
321
  /* ================= ATTRIBUTES ====================*/
@@ -399,7 +432,7 @@ static VALUE ruby_curl_postfield_remote_file_get(VALUE self) {
399
432
 
400
433
  /*
401
434
  * call-seq:
402
- * field.set_content_proc { |field| ... } => &lt;old proc&gt;
435
+ * field.set_content_proc { |field| ... } => <old proc>
403
436
  *
404
437
  * Set a content proc for this field. This proc will be called during the
405
438
  * perform to supply the content for this field, overriding any setting
@@ -421,71 +454,108 @@ static VALUE ruby_curl_postfield_content_proc_set(int argc, VALUE *argv, VALUE s
421
454
  * Only content fields may be converted to strings.
422
455
  */
423
456
  static VALUE ruby_curl_postfield_to_str(VALUE self) {
424
- // FIXME This is using the deprecated curl_escape func
425
457
  ruby_curl_postfield *rbcpf;
426
458
  VALUE result = Qnil;
427
459
  VALUE name = Qnil;
428
460
  char *tmpchrs;
429
-
430
- Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
461
+ #ifdef HAVE_CURL_EASY_ESCAPE
462
+ CURL *curl_handle = NULL;
463
+ #endif
464
+
465
+ TypedData_Get_Struct(self, ruby_curl_postfield, &ruby_curl_postfield_data_type, rbcpf);
431
466
 
432
- if (rbcpf->name != Qnil) {
433
- name = rbcpf->name;
434
- if (rb_type(name) == T_STRING) {
435
- name = rbcpf->name;
436
- } else if (rb_respond_to(name,rb_intern("to_s"))) {
467
+ if (rbcpf->name != Qnil) {
468
+ name = rbcpf->name;
469
+ if (TYPE(name) != T_STRING) {
470
+ if (rb_respond_to(name, rb_intern("to_s")))
437
471
  name = rb_funcall(name, rb_intern("to_s"), 0);
438
- }
439
- else {
440
- name = Qnil; // we can't handle this object
441
- }
442
- }
443
- if (name == Qnil) {
444
- rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string %s:%d, make sure your field name responds_to :to_s", __FILE__, __LINE__);
472
+ else
473
+ name = Qnil;
445
474
  }
475
+ }
476
+ if (name == Qnil) {
477
+ rb_raise(eCurlErrInvalidPostField,
478
+ "Cannot convert unnamed field to string %s:%d, make sure your field name responds_to :to_s",
479
+ __FILE__, __LINE__);
480
+ }
481
+ /* Force field name to UTF-8 before escaping */
482
+ VALUE name_utf8 = rb_str_export_to_enc(name, rb_utf8_encoding());
446
483
 
447
- tmpchrs = curl_escape(StringValuePtr(name), (int)RSTRING_LEN(name));
448
-
449
- if (!tmpchrs) {
450
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
451
- } else {
452
- VALUE tmpcontent = Qnil;
453
- VALUE escd_name = rb_str_new2(tmpchrs);
454
- curl_free(tmpchrs);
455
-
456
- if (rbcpf->content_proc != Qnil) {
457
- tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
458
- } else if (rbcpf->content != Qnil) {
459
- tmpcontent = rbcpf->content;
460
- } else if (rbcpf->local_file != Qnil) {
461
- tmpcontent = rbcpf->local_file;
462
- } else if (rbcpf->remote_file != Qnil) {
463
- tmpcontent = rbcpf->remote_file;
464
- } else {
465
- tmpcontent = rb_str_new2("");
466
- }
467
- if (TYPE(tmpcontent) != T_STRING) {
468
- if (rb_respond_to(tmpcontent, rb_intern("to_s"))) {
469
- tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
470
- }
471
- else {
472
- rb_raise(rb_eRuntimeError, "postfield(%s) is not a string and does not respond_to to_s", RSTRING_PTR(escd_name) );
473
- }
474
- }
475
- //fprintf(stderr, "encoding content: %ld - %s\n", RSTRING_LEN(tmpcontent), RSTRING_PTR(tmpcontent) );
476
- tmpchrs = curl_escape(RSTRING_PTR(tmpcontent), (int)RSTRING_LEN(tmpcontent));
477
- if (!tmpchrs) {
478
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
479
- } else {
480
- VALUE escd_content = rb_str_new2(tmpchrs);
481
- curl_free(tmpchrs);
482
-
483
- result = escd_name;
484
- rb_str_cat(result, "=", 1);
485
- rb_str_concat(result, escd_content);
486
- }
484
+ #ifdef HAVE_CURL_EASY_ESCAPE
485
+ curl_handle = curl_easy_init();
486
+ if (!curl_handle) {
487
+ rb_raise(eCurlErrInvalidPostField, "Failed to initialize curl handle for escaping");
488
+ }
489
+ tmpchrs = curl_easy_escape(curl_handle, StringValuePtr(name_utf8), (int)RSTRING_LEN(name_utf8));
490
+ if (!tmpchrs) {
491
+ curl_easy_cleanup(curl_handle);
492
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name");
493
+ }
494
+ #else
495
+ tmpchrs = curl_escape(StringValuePtr(name_utf8), (int)RSTRING_LEN(name_utf8));
496
+ if (!tmpchrs) {
497
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name");
498
+ }
499
+ #endif
500
+
501
+ VALUE escd_name = rb_str_new2(tmpchrs);
502
+ #ifdef HAVE_CURL_EASY_ESCAPE
503
+ curl_free(tmpchrs);
504
+ #else
505
+ curl_free(tmpchrs);
506
+ #endif
507
+
508
+ VALUE tmpcontent = Qnil;
509
+ if (rbcpf->content_proc != Qnil) {
510
+ tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
511
+ } else if (rbcpf->content != Qnil) {
512
+ tmpcontent = rbcpf->content;
513
+ } else if (rbcpf->local_file != Qnil) {
514
+ tmpcontent = rbcpf->local_file;
515
+ } else if (rbcpf->remote_file != Qnil) {
516
+ tmpcontent = rbcpf->remote_file;
517
+ } else {
518
+ tmpcontent = rb_str_new2("");
519
+ }
520
+ if (TYPE(tmpcontent) != T_STRING) {
521
+ if (rb_respond_to(tmpcontent, rb_intern("to_s")))
522
+ tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
523
+ else {
524
+ #ifdef HAVE_CURL_EASY_ESCAPE
525
+ curl_easy_cleanup(curl_handle);
526
+ #endif
527
+ rb_raise(rb_eRuntimeError,
528
+ "postfield(%s) is not a string and does not respond_to to_s",
529
+ RSTRING_PTR(escd_name));
487
530
  }
488
-
531
+ }
532
+ /* Force content to UTF-8 before escaping */
533
+ VALUE content_utf8 = rb_str_export_to_enc(tmpcontent, rb_utf8_encoding());
534
+ #ifdef HAVE_CURL_EASY_ESCAPE
535
+ tmpchrs = curl_easy_escape(curl_handle, StringValuePtr(content_utf8), (int)RSTRING_LEN(content_utf8));
536
+ if (!tmpchrs) {
537
+ curl_easy_cleanup(curl_handle);
538
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content");
539
+ }
540
+ #else
541
+ tmpchrs = curl_escape(StringValuePtr(content_utf8), (int)RSTRING_LEN(content_utf8));
542
+ if (!tmpchrs) {
543
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content");
544
+ }
545
+ #endif
546
+
547
+ VALUE escd_content = rb_str_new2(tmpchrs);
548
+ #ifdef HAVE_CURL_EASY_ESCAPE
549
+ curl_free(tmpchrs);
550
+ curl_easy_cleanup(curl_handle);
551
+ #else
552
+ curl_free(tmpchrs);
553
+ #endif
554
+
555
+ result = escd_name;
556
+ rb_str_cat(result, "=", 1);
557
+ rb_str_concat(result, escd_content);
558
+
489
559
  return result;
490
560
  }
491
561
 
@@ -498,6 +568,8 @@ void init_curb_postfield() {
498
568
 
499
569
  cCurlPostField = rb_define_class_under(mCurl, "PostField", rb_cObject);
500
570
 
571
+ rb_undef_alloc_func(cCurlPostField);
572
+
501
573
  /* Class methods */
502
574
  rb_define_singleton_method(cCurlPostField, "content", ruby_curl_postfield_new_content, -1);
503
575
  rb_define_singleton_method(cCurlPostField, "file", ruby_curl_postfield_new_file, -1);
data/ext/curb_postfield.h CHANGED
@@ -30,6 +30,7 @@ typedef struct {
30
30
  } ruby_curl_postfield;
31
31
 
32
32
  extern VALUE cCurlPostField;
33
+ extern const rb_data_type_t ruby_curl_postfield_data_type;
33
34
 
34
35
  void append_to_form(VALUE self,
35
36
  struct curl_httppost **first,
data/ext/curb_upload.c CHANGED
@@ -10,13 +10,36 @@ VALUE cCurlUpload;
10
10
  mCurl = rb_define_module("Curl");
11
11
  #endif
12
12
 
13
- static void curl_upload_mark(ruby_curl_upload *rbcu) {
14
- if (rbcu->stream && !NIL_P(rbcu->stream)) rb_gc_mark(rbcu->stream);
13
+ static void curl_upload_mark(void *ptr) {
14
+ ruby_curl_upload *rbcu = (ruby_curl_upload *)ptr;
15
+ if (rbcu && rbcu->stream && !NIL_P(rbcu->stream)) rb_gc_mark(rbcu->stream);
15
16
  }
16
- static void curl_upload_free(ruby_curl_upload *rbcu) {
17
- free(rbcu);
17
+
18
+ static void curl_upload_free(void *ptr) {
19
+ if (ptr) free(ptr);
20
+ }
21
+
22
+ static size_t curl_upload_memsize(const void *ptr) {
23
+ (void)ptr;
24
+ return sizeof(ruby_curl_upload);
18
25
  }
19
26
 
27
+ const rb_data_type_t ruby_curl_upload_data_type = {
28
+ "Curl::Upload",
29
+ {
30
+ curl_upload_mark,
31
+ curl_upload_free,
32
+ curl_upload_memsize,
33
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
34
+ NULL, /* compact */
35
+ #endif
36
+ },
37
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
38
+ NULL, NULL, /* parent, data */
39
+ RUBY_TYPED_FREE_IMMEDIATELY
40
+ #endif
41
+ };
42
+
20
43
  /*
21
44
  * call-seq:
22
45
  * internal class for sending large file uploads
@@ -24,9 +47,12 @@ static void curl_upload_free(ruby_curl_upload *rbcu) {
24
47
  VALUE ruby_curl_upload_new(VALUE klass) {
25
48
  VALUE upload;
26
49
  ruby_curl_upload *rbcu = ALLOC(ruby_curl_upload);
50
+ if (!rbcu) {
51
+ rb_raise(rb_eNoMemError, "Failed to allocate memory for Curl::Upload");
52
+ }
27
53
  rbcu->stream = Qnil;
28
54
  rbcu->offset = 0;
29
- upload = Data_Wrap_Struct(klass, curl_upload_mark, curl_upload_free, rbcu);
55
+ upload = TypedData_Wrap_Struct(klass, &ruby_curl_upload_data_type, rbcu);
30
56
  return upload;
31
57
  }
32
58
 
@@ -36,7 +62,7 @@ VALUE ruby_curl_upload_new(VALUE klass) {
36
62
  */
37
63
  VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream) {
38
64
  ruby_curl_upload *rbcu;
39
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
65
+ TypedData_Get_Struct(self, ruby_curl_upload, &ruby_curl_upload_data_type, rbcu);
40
66
  rbcu->stream = stream;
41
67
  return stream;
42
68
  }
@@ -46,7 +72,7 @@ VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream) {
46
72
  */
47
73
  VALUE ruby_curl_upload_stream_get(VALUE self) {
48
74
  ruby_curl_upload *rbcu;
49
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
75
+ TypedData_Get_Struct(self, ruby_curl_upload, &ruby_curl_upload_data_type, rbcu);
50
76
  return rbcu->stream;
51
77
  }
52
78
  /*
@@ -55,8 +81,8 @@ VALUE ruby_curl_upload_stream_get(VALUE self) {
55
81
  */
56
82
  VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
57
83
  ruby_curl_upload *rbcu;
58
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
59
- rbcu->offset = FIX2LONG(offset);
84
+ TypedData_Get_Struct(self, ruby_curl_upload, &ruby_curl_upload_data_type, rbcu);
85
+ rbcu->offset = NUM2LONG(offset);
60
86
  return offset;
61
87
  }
62
88
  /*
@@ -65,13 +91,14 @@ VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
65
91
  */
66
92
  VALUE ruby_curl_upload_offset_get(VALUE self) {
67
93
  ruby_curl_upload *rbcu;
68
- Data_Get_Struct(self, ruby_curl_upload, rbcu);
69
- return INT2FIX(rbcu->offset);
94
+ TypedData_Get_Struct(self, ruby_curl_upload, &ruby_curl_upload_data_type, rbcu);
95
+ return LONG2NUM(rbcu->offset);
70
96
  }
71
97
 
72
98
  /* =================== INIT LIB =====================*/
73
99
  void init_curb_upload() {
74
100
  cCurlUpload = rb_define_class_under(mCurl, "Upload", rb_cObject);
101
+ rb_undef_alloc_func(cCurlUpload);
75
102
  rb_define_singleton_method(cCurlUpload, "new", ruby_curl_upload_new, 0);
76
103
  rb_define_method(cCurlUpload, "stream=", ruby_curl_upload_stream_set, 1);
77
104
  rb_define_method(cCurlUpload, "stream", ruby_curl_upload_stream_get, 0);
data/ext/curb_upload.h CHANGED
@@ -19,6 +19,8 @@ typedef struct {
19
19
  } ruby_curl_upload;
20
20
 
21
21
  extern VALUE cCurlUpload;
22
+ extern const rb_data_type_t ruby_curl_upload_data_type;
23
+
22
24
  void init_curb_upload();
23
25
 
24
26
  VALUE ruby_curl_upload_new(VALUE klass);