curb 0.5.8.0-x86-darwin-10
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of curb might be problematic. Click here for more details.
- data/LICENSE +51 -0
- data/README +157 -0
- data/Rakefile +297 -0
- data/doc.rb +42 -0
- data/ext/curb.c +339 -0
- data/ext/curb.h +50 -0
- data/ext/curb.o +0 -0
- data/ext/curb_core.bundle +0 -0
- data/ext/curb_easy.c +2932 -0
- data/ext/curb_easy.h +103 -0
- data/ext/curb_easy.o +0 -0
- data/ext/curb_errors.c +630 -0
- data/ext/curb_errors.h +128 -0
- data/ext/curb_errors.o +0 -0
- data/ext/curb_macros.h +114 -0
- data/ext/curb_multi.c +487 -0
- data/ext/curb_multi.h +26 -0
- data/ext/curb_multi.o +0 -0
- data/ext/curb_postfield.c +511 -0
- data/ext/curb_postfield.h +40 -0
- data/ext/curb_postfield.o +0 -0
- data/ext/curb_upload.c +80 -0
- data/ext/curb_upload.h +30 -0
- data/ext/curb_upload.o +0 -0
- data/ext/extconf.rb +162 -0
- data/lib/curb.rb +184 -0
- data/lib/curl.rb +2 -0
- data/tests/alltests.rb +3 -0
- data/tests/bug_curb_easy_blocks_ruby_threads.rb +52 -0
- data/tests/bug_instance_post_differs_from_class_post.rb +53 -0
- data/tests/bug_multi_segfault.rb +10 -0
- data/tests/bug_require_last_or_segfault.rb +40 -0
- data/tests/helper.rb +168 -0
- data/tests/require_last_or_segfault_script.rb +36 -0
- data/tests/tc_curl_download.rb +32 -0
- data/tests/tc_curl_easy.rb +664 -0
- data/tests/tc_curl_multi.rb +422 -0
- data/tests/tc_curl_postfield.rb +141 -0
- data/tests/unittests.rb +2 -0
- metadata +96 -0
data/ext/curb_multi.h
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
/* curb_multi.h - Curl easy mode
|
2
|
+
* Copyright (c)2008 Todd A. Fisher.
|
3
|
+
* Licensed under the Ruby License. See LICENSE for details.
|
4
|
+
*
|
5
|
+
* $Id$
|
6
|
+
*/
|
7
|
+
#ifndef __CURB_MULTI_H
|
8
|
+
#define __CURB_MULTI_H
|
9
|
+
|
10
|
+
#include "curb.h"
|
11
|
+
#include "curb_easy.h"
|
12
|
+
#include <curl/multi.h>
|
13
|
+
|
14
|
+
typedef struct {
|
15
|
+
int active;
|
16
|
+
int running;
|
17
|
+
VALUE requests; /* hash of handles currently added */
|
18
|
+
CURLM *handle;
|
19
|
+
} ruby_curl_multi;
|
20
|
+
|
21
|
+
extern VALUE cCurlMulti;
|
22
|
+
void init_curb_multi();
|
23
|
+
VALUE ruby_curl_multi_new(VALUE klass);
|
24
|
+
|
25
|
+
|
26
|
+
#endif
|
data/ext/curb_multi.o
ADDED
Binary file
|
@@ -0,0 +1,511 @@
|
|
1
|
+
/* curb_postfield.c - Field class for POST method
|
2
|
+
* Copyright (c)2006 Ross Bamford.
|
3
|
+
* Licensed under the Ruby License. See LICENSE for details.
|
4
|
+
*
|
5
|
+
* $Id: curb_postfield.c 30 2006-12-09 12:30:24Z roscopeco $
|
6
|
+
*/
|
7
|
+
#include "curb_postfield.h"
|
8
|
+
#include "curb_errors.h"
|
9
|
+
|
10
|
+
extern VALUE mCurl;
|
11
|
+
|
12
|
+
static VALUE idCall;
|
13
|
+
|
14
|
+
#ifdef RDOC_NEVER_DEFINED
|
15
|
+
mCurl = rb_define_module("Curl");
|
16
|
+
#endif
|
17
|
+
|
18
|
+
VALUE cCurlPostField;
|
19
|
+
|
20
|
+
|
21
|
+
/* ================= APPEND FORM FUNC ================ */
|
22
|
+
|
23
|
+
/* This gets called by the post method on Curl::Easy for each postfield
|
24
|
+
* supplied in the arguments. It's job is to add the supplied field to
|
25
|
+
* the list that's being built for a perform.
|
26
|
+
*
|
27
|
+
* THIS FUNC MODIFIES ITS ARGUMENTS. See curl_formadd(3) for details.
|
28
|
+
*/
|
29
|
+
void append_to_form(VALUE self,
|
30
|
+
struct curl_httppost **first,
|
31
|
+
struct curl_httppost **last) {
|
32
|
+
ruby_curl_postfield *rbcpf;
|
33
|
+
CURLFORMcode result = -1;
|
34
|
+
|
35
|
+
Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
|
36
|
+
|
37
|
+
if (rbcpf->name == Qnil) {
|
38
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot post unnamed field");
|
39
|
+
} else {
|
40
|
+
if ((rbcpf->local_file != Qnil) || (rbcpf->remote_file != Qnil)) {
|
41
|
+
// is a file upload field
|
42
|
+
if (rbcpf->content_proc != Qnil) {
|
43
|
+
// with content proc
|
44
|
+
rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, self);
|
45
|
+
|
46
|
+
if (rbcpf->remote_file == Qnil) {
|
47
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot post file upload field with no filename");
|
48
|
+
} else {
|
49
|
+
if (rbcpf->content_type == Qnil) {
|
50
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
51
|
+
CURLFORM_BUFFER, StringValuePtr(rbcpf->remote_file),
|
52
|
+
CURLFORM_BUFFERPTR, StringValuePtr(rbcpf->buffer_str),
|
53
|
+
CURLFORM_BUFFERLENGTH, RSTRING_LEN(rbcpf->buffer_str),
|
54
|
+
CURLFORM_END);
|
55
|
+
} else {
|
56
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
57
|
+
CURLFORM_BUFFER, StringValuePtr(rbcpf->remote_file),
|
58
|
+
CURLFORM_BUFFERPTR, StringValuePtr(rbcpf->buffer_str),
|
59
|
+
CURLFORM_BUFFERLENGTH, RSTRING_LEN(rbcpf->buffer_str),
|
60
|
+
CURLFORM_CONTENTTYPE, StringValuePtr(rbcpf->content_type),
|
61
|
+
CURLFORM_END);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
} else if (rbcpf->content != Qnil) {
|
65
|
+
// with content
|
66
|
+
if (rbcpf->remote_file == Qnil) {
|
67
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot post file upload field with no filename");
|
68
|
+
} else {
|
69
|
+
if (rbcpf->content_type == Qnil) {
|
70
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
71
|
+
CURLFORM_BUFFER, StringValuePtr(rbcpf->remote_file),
|
72
|
+
CURLFORM_BUFFERPTR, StringValuePtr(rbcpf->content),
|
73
|
+
CURLFORM_BUFFERLENGTH, RSTRING_LEN(rbcpf->content),
|
74
|
+
CURLFORM_END);
|
75
|
+
} else {
|
76
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
77
|
+
CURLFORM_BUFFER, StringValuePtr(rbcpf->remote_file),
|
78
|
+
CURLFORM_BUFFERPTR, StringValuePtr(rbcpf->content),
|
79
|
+
CURLFORM_BUFFERLENGTH, RSTRING_LEN(rbcpf->content),
|
80
|
+
CURLFORM_CONTENTTYPE, StringValuePtr(rbcpf->content_type),
|
81
|
+
CURLFORM_END);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
} else if (rbcpf->local_file != Qnil) {
|
85
|
+
// with local filename
|
86
|
+
if (rbcpf->local_file == Qnil) {
|
87
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot post file upload field no filename");
|
88
|
+
} else {
|
89
|
+
if (rbcpf->remote_file == Qnil) {
|
90
|
+
rbcpf->remote_file = rbcpf->local_file;
|
91
|
+
}
|
92
|
+
|
93
|
+
if (rbcpf->content_type == Qnil) {
|
94
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
95
|
+
CURLFORM_FILE, StringValuePtr(rbcpf->local_file),
|
96
|
+
CURLFORM_FILENAME, StringValuePtr(rbcpf->remote_file),
|
97
|
+
CURLFORM_END);
|
98
|
+
} else {
|
99
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
100
|
+
CURLFORM_FILE, StringValuePtr(rbcpf->local_file),
|
101
|
+
CURLFORM_FILENAME, StringValuePtr(rbcpf->remote_file),
|
102
|
+
CURLFORM_CONTENTTYPE, StringValuePtr(rbcpf->content_type),
|
103
|
+
CURLFORM_END);
|
104
|
+
}
|
105
|
+
}
|
106
|
+
} else {
|
107
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot post file upload field with no data");
|
108
|
+
}
|
109
|
+
} else {
|
110
|
+
// is a content field
|
111
|
+
if (rbcpf->content_proc != Qnil) {
|
112
|
+
rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, self);
|
113
|
+
|
114
|
+
if (rbcpf->content_type == Qnil) {
|
115
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
116
|
+
CURLFORM_PTRCONTENTS, StringValuePtr(rbcpf->buffer_str),
|
117
|
+
CURLFORM_CONTENTSLENGTH, RSTRING_LEN(rbcpf->buffer_str),
|
118
|
+
CURLFORM_END);
|
119
|
+
} else {
|
120
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
121
|
+
CURLFORM_PTRCONTENTS, StringValuePtr(rbcpf->buffer_str),
|
122
|
+
CURLFORM_CONTENTSLENGTH, RSTRING_LEN(rbcpf->buffer_str),
|
123
|
+
CURLFORM_CONTENTTYPE, StringValuePtr(rbcpf->content_type),
|
124
|
+
CURLFORM_END);
|
125
|
+
}
|
126
|
+
} else if (rbcpf->content != Qnil) {
|
127
|
+
if (rbcpf->content_type == Qnil) {
|
128
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
129
|
+
CURLFORM_PTRCONTENTS, StringValuePtr(rbcpf->content),
|
130
|
+
CURLFORM_CONTENTSLENGTH, RSTRING_LEN(rbcpf->content),
|
131
|
+
CURLFORM_END);
|
132
|
+
} else {
|
133
|
+
result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
|
134
|
+
CURLFORM_PTRCONTENTS, StringValuePtr(rbcpf->content),
|
135
|
+
CURLFORM_CONTENTSLENGTH, RSTRING_LEN(rbcpf->content),
|
136
|
+
CURLFORM_CONTENTTYPE, StringValuePtr(rbcpf->content_type),
|
137
|
+
CURLFORM_END);
|
138
|
+
}
|
139
|
+
} else {
|
140
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot post content field with no data");
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
if (result != 0) {
|
146
|
+
const char *reason = NULL;
|
147
|
+
|
148
|
+
switch (result) {
|
149
|
+
case CURL_FORMADD_MEMORY:
|
150
|
+
reason = "Memory allocation failed";
|
151
|
+
break;
|
152
|
+
case CURL_FORMADD_OPTION_TWICE:
|
153
|
+
reason = "Duplicate option";
|
154
|
+
break;
|
155
|
+
case CURL_FORMADD_NULL:
|
156
|
+
reason = "Unexpected NULL string";
|
157
|
+
break;
|
158
|
+
case CURL_FORMADD_UNKNOWN_OPTION:
|
159
|
+
reason = "Unknown option";
|
160
|
+
break;
|
161
|
+
case CURL_FORMADD_INCOMPLETE:
|
162
|
+
reason = "Incomplete form data";
|
163
|
+
break;
|
164
|
+
case CURL_FORMADD_ILLEGAL_ARRAY:
|
165
|
+
reason = "Illegal array [BINDING BUG]";
|
166
|
+
break;
|
167
|
+
case CURL_FORMADD_DISABLED:
|
168
|
+
reason = "Installed libcurl cannot support requested feature(s)";
|
169
|
+
break;
|
170
|
+
default:
|
171
|
+
reason = "Unknown error";
|
172
|
+
}
|
173
|
+
|
174
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to add field (%s)", reason);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
|
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);
|
187
|
+
}
|
188
|
+
|
189
|
+
void curl_postfield_free(ruby_curl_postfield *rbcpf) {
|
190
|
+
free(rbcpf);
|
191
|
+
}
|
192
|
+
|
193
|
+
|
194
|
+
/* ================= ALLOC METHODS ====================*/
|
195
|
+
|
196
|
+
/*
|
197
|
+
* call-seq:
|
198
|
+
* Curl::PostField.content(name, content) => #<Curl::PostField...>
|
199
|
+
* Curl::PostField.content(name, content, content_type = nil) => #<Curl::PostField...>
|
200
|
+
* Curl::PostField.content(name, content_type = nil) { |field| ... } => #<Curl::PostField...>
|
201
|
+
*
|
202
|
+
* Create a new Curl::PostField, supplying the field name, content,
|
203
|
+
* and, optionally, Content-type (curl will attempt to determine this if
|
204
|
+
* not specified).
|
205
|
+
*
|
206
|
+
* The block form allows a block to supply the content for this field, called
|
207
|
+
* during the perform. The block should return a ruby string with the field
|
208
|
+
* data.
|
209
|
+
*/
|
210
|
+
static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass) {
|
211
|
+
ruby_curl_postfield *rbcpf = ALLOC(ruby_curl_postfield);
|
212
|
+
|
213
|
+
// wierdness - we actually require two args, unless a block is provided, but
|
214
|
+
// we have to work that out below.
|
215
|
+
rb_scan_args(argc, argv, "12&", &rbcpf->name, &rbcpf->content, &rbcpf->content_type, &rbcpf->content_proc);
|
216
|
+
|
217
|
+
// special handling if theres a block, second arg is actually content_type
|
218
|
+
if (rbcpf->content_proc != Qnil) {
|
219
|
+
if (rbcpf->content != Qnil) {
|
220
|
+
// we were given a content-type
|
221
|
+
rbcpf->content_type = rbcpf->content;
|
222
|
+
rbcpf->content = Qnil;
|
223
|
+
} else {
|
224
|
+
// default content type
|
225
|
+
rbcpf->content_type = Qnil;
|
226
|
+
}
|
227
|
+
} else {
|
228
|
+
// no block, so make sure content was provided
|
229
|
+
if (rbcpf->content == Qnil) {
|
230
|
+
rb_raise(rb_eArgError, "Incorrect number of arguments (expected 2 or 3)");
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
/* assoc objects */
|
235
|
+
rbcpf->local_file = Qnil;
|
236
|
+
rbcpf->remote_file = Qnil;
|
237
|
+
rbcpf->buffer_str = Qnil;
|
238
|
+
|
239
|
+
return Data_Wrap_Struct(cCurlPostField, curl_postfield_mark, curl_postfield_free, rbcpf);
|
240
|
+
}
|
241
|
+
|
242
|
+
/*
|
243
|
+
* call-seq:
|
244
|
+
* Curl::PostField.file(name, local_file_name) => #<Curl::PostField...>
|
245
|
+
* Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #<Curl::PostField...>
|
246
|
+
* Curl::PostField.file(name, remote_file_name) { |field| ... } => #<Curl::PostField...>
|
247
|
+
*
|
248
|
+
* Create a new Curl::PostField for a file upload field, supplying the local filename
|
249
|
+
* to read from, and optionally the remote filename (defaults to the local name).
|
250
|
+
*
|
251
|
+
* The block form allows a block to supply the content for this field, called
|
252
|
+
* during the perform. The block should return a ruby string with the field
|
253
|
+
* data.
|
254
|
+
*/
|
255
|
+
static VALUE ruby_curl_postfield_new_file(int argc, VALUE *argv, VALUE klass) {
|
256
|
+
// TODO needs to handle content-type too
|
257
|
+
ruby_curl_postfield *rbcpf = ALLOC(ruby_curl_postfield);
|
258
|
+
|
259
|
+
rb_scan_args(argc, argv, "21&", &rbcpf->name, &rbcpf->local_file, &rbcpf->remote_file, &rbcpf->content_proc);
|
260
|
+
|
261
|
+
// special handling if theres a block, second arg is actually remote name.
|
262
|
+
if (rbcpf->content_proc != Qnil) {
|
263
|
+
if (rbcpf->local_file != Qnil) {
|
264
|
+
// we were given a local file
|
265
|
+
if (rbcpf->remote_file == Qnil) {
|
266
|
+
// we weren't given a remote, so local is actually remote
|
267
|
+
// (correct block call form)
|
268
|
+
rbcpf->remote_file = rbcpf->local_file;
|
269
|
+
}
|
270
|
+
|
271
|
+
// Shouldn't get a local file, so can ignore it.
|
272
|
+
rbcpf->local_file = Qnil;
|
273
|
+
}
|
274
|
+
} else {
|
275
|
+
if (rbcpf->remote_file == Qnil) {
|
276
|
+
rbcpf->remote_file = rbcpf->local_file;
|
277
|
+
}
|
278
|
+
}
|
279
|
+
|
280
|
+
/* assoc objects */
|
281
|
+
rbcpf->content = Qnil;
|
282
|
+
rbcpf->content_type = Qnil;
|
283
|
+
rbcpf->buffer_str = Qnil;
|
284
|
+
|
285
|
+
return Data_Wrap_Struct(cCurlPostField, curl_postfield_mark, curl_postfield_free, rbcpf);
|
286
|
+
}
|
287
|
+
|
288
|
+
/* ================= ATTRIBUTES ====================*/
|
289
|
+
|
290
|
+
/*
|
291
|
+
* call-seq:
|
292
|
+
* field.name = "name" => "name"
|
293
|
+
*
|
294
|
+
* Set the POST field name for this PostField.
|
295
|
+
*/
|
296
|
+
static VALUE ruby_curl_postfield_name_set(VALUE self, VALUE name) {
|
297
|
+
CURB_OBJECT_SETTER(ruby_curl_postfield, name);
|
298
|
+
}
|
299
|
+
|
300
|
+
/*
|
301
|
+
* call-seq:
|
302
|
+
* field.name => "name"
|
303
|
+
*
|
304
|
+
* Obtain the POST field name for this PostField.
|
305
|
+
*/
|
306
|
+
static VALUE ruby_curl_postfield_name_get(VALUE self) {
|
307
|
+
CURB_OBJECT_GETTER(ruby_curl_postfield, name);
|
308
|
+
}
|
309
|
+
|
310
|
+
/*
|
311
|
+
* call-seq:
|
312
|
+
* field.content = "content" => "content"
|
313
|
+
*
|
314
|
+
* Set the POST field content for this PostField. Ignored when a
|
315
|
+
* content_proc is supplied via either +Curl::PostField.file+ or
|
316
|
+
* +set_content_proc+.
|
317
|
+
*/
|
318
|
+
static VALUE ruby_curl_postfield_content_set(VALUE self, VALUE content) {
|
319
|
+
CURB_OBJECT_SETTER(ruby_curl_postfield, content);
|
320
|
+
}
|
321
|
+
|
322
|
+
/*
|
323
|
+
* call-seq:
|
324
|
+
* field.content => "content"
|
325
|
+
*
|
326
|
+
* Obtain the POST field content for this PostField.
|
327
|
+
*/
|
328
|
+
static VALUE ruby_curl_postfield_content_get(VALUE self) {
|
329
|
+
CURB_OBJECT_GETTER(ruby_curl_postfield, content);
|
330
|
+
}
|
331
|
+
|
332
|
+
/*
|
333
|
+
* call-seq:
|
334
|
+
* field.content_type = "content_type" => "content_type"
|
335
|
+
*
|
336
|
+
* Set the POST field Content-type for this PostField.
|
337
|
+
*/
|
338
|
+
static VALUE ruby_curl_postfield_content_type_set(VALUE self, VALUE content_type) {
|
339
|
+
CURB_OBJECT_SETTER(ruby_curl_postfield, content_type);
|
340
|
+
}
|
341
|
+
|
342
|
+
/*
|
343
|
+
* call-seq:
|
344
|
+
* field.content_type => "content_type"
|
345
|
+
*
|
346
|
+
* Get the POST field Content-type for this PostField.
|
347
|
+
*/
|
348
|
+
static VALUE ruby_curl_postfield_content_type_get(VALUE self) {
|
349
|
+
CURB_OBJECT_GETTER(ruby_curl_postfield, content_type);
|
350
|
+
}
|
351
|
+
|
352
|
+
/*
|
353
|
+
* call-seq:
|
354
|
+
* field.local_file = "filename" => "filename"
|
355
|
+
*
|
356
|
+
* Set the POST field local filename for this PostField (when performing
|
357
|
+
* a file upload). Ignored when a content_proc is supplied via either
|
358
|
+
* +Curl::PostField.file+ or +set_content_proc+.
|
359
|
+
*/
|
360
|
+
static VALUE ruby_curl_postfield_local_file_set(VALUE self, VALUE local_file) {
|
361
|
+
CURB_OBJECT_SETTER(ruby_curl_postfield, local_file);
|
362
|
+
}
|
363
|
+
|
364
|
+
/*
|
365
|
+
* call-seq:
|
366
|
+
* field.local_file => "filename"
|
367
|
+
*
|
368
|
+
* Get the POST field local filename for this PostField (when performing
|
369
|
+
* a file upload).
|
370
|
+
*/
|
371
|
+
static VALUE ruby_curl_postfield_local_file_get(VALUE self) {
|
372
|
+
CURB_OBJECT_GETTER(ruby_curl_postfield, local_file);
|
373
|
+
}
|
374
|
+
|
375
|
+
/*
|
376
|
+
* call-seq:
|
377
|
+
* field.remote_file = "filename" => "filename"
|
378
|
+
*
|
379
|
+
* Set the POST field remote filename for this PostField (when performing
|
380
|
+
* a file upload). If no remote filename is provided, and no content_proc
|
381
|
+
* is supplied, the local filename is used. If no remote filename is
|
382
|
+
* specified when a content_proc is used, an exception will be raised
|
383
|
+
* during the perform.
|
384
|
+
*/
|
385
|
+
static VALUE ruby_curl_postfield_remote_file_set(VALUE self, VALUE remote_file) {
|
386
|
+
CURB_OBJECT_SETTER(ruby_curl_postfield, remote_file);
|
387
|
+
}
|
388
|
+
|
389
|
+
/*
|
390
|
+
* call-seq:
|
391
|
+
* field.local_file => "filename"
|
392
|
+
*
|
393
|
+
* Get the POST field remote filename for this PostField (when performing
|
394
|
+
* a file upload).
|
395
|
+
*/
|
396
|
+
static VALUE ruby_curl_postfield_remote_file_get(VALUE self) {
|
397
|
+
CURB_OBJECT_GETTER(ruby_curl_postfield, remote_file);
|
398
|
+
}
|
399
|
+
|
400
|
+
/*
|
401
|
+
* call-seq:
|
402
|
+
* field.set_content_proc { |field| ... } => <old proc>
|
403
|
+
*
|
404
|
+
* Set a content proc for this field. This proc will be called during the
|
405
|
+
* perform to supply the content for this field, overriding any setting
|
406
|
+
* of +content+ or +local_file+.
|
407
|
+
*/
|
408
|
+
static VALUE ruby_curl_postfield_content_proc_set(int argc, VALUE *argv, VALUE self) {
|
409
|
+
CURB_HANDLER_PROC_SETTER(ruby_curl_postfield, content_proc);
|
410
|
+
}
|
411
|
+
|
412
|
+
/*
|
413
|
+
* call-seq:
|
414
|
+
* field.to_str => "name=value"
|
415
|
+
* field.to_s => "name=value"
|
416
|
+
*
|
417
|
+
* Obtain a String representation of this PostField in url-encoded
|
418
|
+
* format. This is used to construct the post data for non-multipart
|
419
|
+
* POSTs.
|
420
|
+
*
|
421
|
+
* Only content fields may be converted to strings.
|
422
|
+
*/
|
423
|
+
static VALUE ruby_curl_postfield_to_str(VALUE self) {
|
424
|
+
// FIXME This is using the deprecated curl_escape func
|
425
|
+
ruby_curl_postfield *rbcpf;
|
426
|
+
VALUE result = Qnil;
|
427
|
+
|
428
|
+
Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
|
429
|
+
|
430
|
+
if ((rbcpf->local_file == Qnil) && (rbcpf->remote_file == Qnil)) {
|
431
|
+
if (rbcpf->name != Qnil) {
|
432
|
+
|
433
|
+
char *tmpchrs = curl_escape(RSTRING_PTR(rbcpf->name), RSTRING_LEN(rbcpf->name));
|
434
|
+
|
435
|
+
if (!tmpchrs) {
|
436
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
|
437
|
+
} else {
|
438
|
+
VALUE tmpcontent = Qnil;
|
439
|
+
VALUE escd_name = rb_str_new2(tmpchrs);
|
440
|
+
curl_free(tmpchrs);
|
441
|
+
|
442
|
+
if (rbcpf->content_proc != Qnil) {
|
443
|
+
tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
|
444
|
+
} else if (rbcpf->content != Qnil) {
|
445
|
+
tmpcontent = rbcpf->content;
|
446
|
+
} else {
|
447
|
+
tmpcontent = rb_str_new2("");
|
448
|
+
}
|
449
|
+
if (TYPE(tmpcontent) != T_STRING) {
|
450
|
+
if (rb_respond_to(tmpcontent, rb_intern("to_s"))) {
|
451
|
+
tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
|
452
|
+
}
|
453
|
+
else {
|
454
|
+
rb_raise(rb_eRuntimeError, "postfield(%s) is not a string and does not respond_to to_s", RSTRING_PTR(escd_name) );
|
455
|
+
}
|
456
|
+
}
|
457
|
+
//fprintf(stderr, "encoding content: %ld - %s\n", RSTRING_LEN(tmpcontent), RSTRING_PTR(tmpcontent) );
|
458
|
+
tmpchrs = curl_escape(RSTRING_PTR(tmpcontent), RSTRING_LEN(tmpcontent));
|
459
|
+
if (!tmpchrs) {
|
460
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
|
461
|
+
} else {
|
462
|
+
VALUE escd_content = rb_str_new2(tmpchrs);
|
463
|
+
curl_free(tmpchrs);
|
464
|
+
|
465
|
+
result = escd_name;
|
466
|
+
rb_str_cat(result, "=", 1);
|
467
|
+
rb_str_concat(result, escd_content);
|
468
|
+
}
|
469
|
+
}
|
470
|
+
} else {
|
471
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string");
|
472
|
+
}
|
473
|
+
} else {
|
474
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot convert non-content field to string");
|
475
|
+
}
|
476
|
+
|
477
|
+
return result;
|
478
|
+
}
|
479
|
+
|
480
|
+
|
481
|
+
/* =================== INIT LIB =====================*/
|
482
|
+
void init_curb_postfield() {
|
483
|
+
VALUE sc;
|
484
|
+
|
485
|
+
idCall = rb_intern("call");
|
486
|
+
|
487
|
+
cCurlPostField = rb_define_class_under(mCurl, "PostField", rb_cObject);
|
488
|
+
|
489
|
+
/* Class methods */
|
490
|
+
rb_define_singleton_method(cCurlPostField, "content", ruby_curl_postfield_new_content, -1);
|
491
|
+
rb_define_singleton_method(cCurlPostField, "file", ruby_curl_postfield_new_file, -1);
|
492
|
+
|
493
|
+
sc = rb_singleton_class(cCurlPostField);
|
494
|
+
rb_undef(sc, rb_intern("new"));
|
495
|
+
|
496
|
+
rb_define_method(cCurlPostField, "name=", ruby_curl_postfield_name_set, 1);
|
497
|
+
rb_define_method(cCurlPostField, "name", ruby_curl_postfield_name_get, 0);
|
498
|
+
rb_define_method(cCurlPostField, "content=", ruby_curl_postfield_content_set, 1);
|
499
|
+
rb_define_method(cCurlPostField, "content", ruby_curl_postfield_content_get, 0);
|
500
|
+
rb_define_method(cCurlPostField, "content_type=", ruby_curl_postfield_content_type_set, 1);
|
501
|
+
rb_define_method(cCurlPostField, "content_type", ruby_curl_postfield_content_type_get, 0);
|
502
|
+
rb_define_method(cCurlPostField, "local_file=", ruby_curl_postfield_local_file_set, 1);
|
503
|
+
rb_define_method(cCurlPostField, "local_file", ruby_curl_postfield_local_file_get, 0);
|
504
|
+
rb_define_method(cCurlPostField, "remote_file=", ruby_curl_postfield_remote_file_set, 1);
|
505
|
+
rb_define_method(cCurlPostField, "remote_file", ruby_curl_postfield_remote_file_get, 0);
|
506
|
+
|
507
|
+
rb_define_method(cCurlPostField, "set_content_proc", ruby_curl_postfield_content_proc_set, -1);
|
508
|
+
|
509
|
+
rb_define_method(cCurlPostField, "to_str", ruby_curl_postfield_to_str, 0);
|
510
|
+
rb_define_alias(cCurlPostField, "to_s", "to_str");
|
511
|
+
}
|