3

I'm trying to construct an HTTP form using libcurl but I can't get it to work properly. Every time I call curl_formadd it returns CURL_FORMADD_OPTION_TWICE. The only information about this error indicates that libcurl thinks I'm trying to add two form elements with the same name, even though its the first call to curl_formadd and I'm only adding one element!

  Declare Function curl_global_init Lib "libcurl" (flags As Integer) As Integer
  Declare Function curl_formadd Lib "libcurl" (FirstItem As Ptr, LastItem As Ptr, Option1 As Integer, Value1 As Ptr, Option2 As Integer, Value2 As Ptr, EndMarker As Integer) As Integer

  Const CURLFORM_COPYCONTENTS = 2
  Const CURLFORM_COPYNAME = 1
  Const CURLFORM_END = 17

  Dim formname, formvalue As MemoryBlock
  formname = "NAME"
  formvalue = "CONTENTS"

  If curl_global_init(3) = 0 Then
    Dim first, last As Ptr
    Dim err As Integer
    err = curl_formadd(first, last, CURLFORM_COPYNAME, formname, CURLFORM_COPYCONTENTS, formvalue, CURLFORM_END)
    Break
    ' err is 2 (CURL_FORMADD_OPTION_TWICE) 
  End If

What is this error trying to tell me?

Andrew Lambert
  • 1,869
  • 1
  • 17
  • 31

1 Answers1

3

Reading the 'man' page for curl_formadd(), it says there:

The pointers firstitem and lastitem should both be pointing to NULL in the first call to this function.

You, however, pass NULL for these.

You also seem to be passing the strings incorrectly. Try defining the Value1 and Value2 parameters "as CString", then pass normal Strings, not Memoryblocks.

Lastly, you gave CURLFORM_COPYCONTENTS the wrong code. It's not 2 but 4. See the CURLformoption enum in curl.h: "CFINIT(NOTHING)" gets value 0, and every item past that gets one higher, so CFINIT(COPYCONTENTS) gets 4.

Here's the code that works for me:

Declare Function curl_global_init Lib "libcurl" (flags As Integer) As Integer
Declare Function curl_formadd Lib "libcurl" (ByRef FirstItem As Ptr, ByRef LastItem As Ptr, Option1 As Integer, Value1 As CString, Option2 As Integer, Value2 As CString, EndMarker As Integer) As Integer

Const CURLFORM_COPYCONTENTS = 4
Const CURLFORM_COPYNAME = 1
Const CURLFORM_END = 17
const CURL_GLOBAL_ALL = 3

Dim formname, formvalue As String
formname = "NAME"
formvalue = "CONTENTS"

If curl_global_init(CURL_GLOBAL_ALL) = 0 Then
  Dim first, last As Ptr
  Dim err As Integer
  err = curl_formadd(first, last, CURLFORM_COPYNAME, formname, CURLFORM_COPYCONTENTS, formvalue, CURLFORM_END)
  Break
  ' err is 0
End If
Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • Thanks, but I still get `CURL_FORMADD_OPTION_TWICE`. – Andrew Lambert May 02 '14 at 16:36
  • The error code 2 does not mean CURL_FORMADD_OPTION_TWICE, but an error code listed as explained here: "non-zero means an error occurred corresponding to a CURL_FORMADD_* constant defined in " – Thomas Tempelmann May 03 '14 at 18:06
  • `CURL_FORMADD_OPTION_TWICE` is the `CURL_FORMADD_*` constant with a value of 2. If that's not correct, what does `2` indicate? – Andrew Lambert May 03 '14 at 18:29
  • Declaring `value1` and `value2` as `CString` does not seem to affect the outcome (still get `2`) – Andrew Lambert May 03 '14 at 21:02
  • I already explained how to find out what the error code 2 means in my 2nd comment. If you look into curl.h, searching for "curl_formadd", you'll find the comment listing the return codes for that function. Apparently, 2 means CURL_FORMADD_OPTION_TWICE, meaning: "one option is given twice for one Form". No idea what that means. Maybe your form data is incorrect, having duplicate IDs. – Thomas Tempelmann May 09 '14 at 21:32
  • I guess you need to find some sample code in plain C first that uses this function to see how it works, you're probably using it wrong. – Thomas Tempelmann May 09 '14 at 21:37
  • Your second comment says that 2 *isn't* `CURL_FORMADD_OPTION_TWICE` but is one of the `CURL_FORMADD_` constants, but `CURL_FORMADD_OPTION_TWICE` *is* the `CURL_FORMADD_` constant whose value is 2. – Andrew Lambert May 10 '14 at 06:22
  • One of the big problems with the C examples is that `curl_formadd` is a variadic function but RB doesn't allow variadic declares. – Andrew Lambert May 10 '14 at 06:24
  • Did you see my updated answer? It solves you question – Thomas Tempelmann May 10 '14 at 09:40
  • No, I hadn't noticed the edit but that seems to have done it! Thank you! – Andrew Lambert May 10 '14 at 16:37