Skip to content

Commit

Permalink
Merge branch 'release/1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
alldroll committed Aug 5, 2016
2 parents 148f8e9 + 975c109 commit 8ce2f32
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 4 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ public hook_death()
```
p.s. for more information see tests

### Notice

* functions curl_form_add, curl_destroy_form, curl_slist_append, curl_destroy_slist
are not thread safe now, so please, if you share curl_slist, curl_form handles
between threaded performs, make sure, that you use this functions after all performs
* there are wrong test number + test name for some test cases because of thread_exec

### Natives

Expand Down Expand Up @@ -192,4 +198,24 @@ native curl_destroy_slist(Handle:slist);
* @return True on success, otherwise False
*/
native curl_slist_append(Handle:slist, const str[]);
/**
* Initialize CurlWebForm (pair of curl_httppost struct objects)
* @return Handle
*/
native Handle:curl_create_form();
/**
* Destroy CurlWebForm
* @param form Handle
* @return True on success, otherwise False
*/
native Handle:curl_destroy_form(Handle:form);
/**
* Add a section to a multipart/formdata HTTP POST
* @param form Handle
* any...
*/
native CURLFORMcode:curl_form_add(Handle:form, any:...);
```
97 changes: 97 additions & 0 deletions base_curl.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include "curl_header.h"
#include "curl_wrap.h"
#include "am-fixedarray.h"

static void FreeCurl(void* p, unsigned int num) {
Curl* curl = (Curl*) p;
Expand All @@ -12,6 +13,11 @@ static void FreeSList(void* p, unsigned int num) {
delete slist;
}

static void FreeForm(void* p, unsigned int num) {
CurlWebForm* form = (CurlWebForm*) p;
delete form;
}

// native Handle:curl_init();
static cell AMX_NATIVE_CALL AMX_CurlInit(AMX* amx, cell* params) {
Curl* curl = Curl::Initialize();
Expand Down Expand Up @@ -121,6 +127,15 @@ static cell AMX_NATIVE_CALL AMX_CurlSetOptHandle(AMX* amx, cell* params) {

return curl->SetOptionHandle(opt, val);
}

case CURLOPT_HTTPPOST: {
void* val = GetHandle(params[3], HANDLE_CURL_FORM);
if (!val) {
return -1;
}

return curl->SetOptionHandle(opt, val);
}
}

return 0;
Expand Down Expand Up @@ -250,6 +265,85 @@ static cell AMX_NATIVE_CALL AMX_CurlSListAppend(AMX* amx, cell* params) {
return true;
}

// native Handle:curl_create_form()
static cell AMX_NATIVE_CALL AMX_CurlCreateForm(AMX* amx, cell* params) {
CurlWebForm* form = new CurlWebForm();
if (!form) { /* is it ok ? */
MF_LogError(amx, AMX_ERR_NATIVE, "Couldn't alloc curl handle");
return -1;
}

return MakeHandle(form, HANDLE_CURL_FORM, FreeForm);
}

// native curl_destroy_form(Handle:form)
static cell AMX_NATIVE_CALL AMX_CurlDestroyForm(AMX* amx, cell* params) {
bool success = true;
if (!FreeHandle(params[1])) {
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
success = false;
}

return success;
}

// native curl_form_add(Handle:form, any:...)
static cell AMX_NATIVE_CALL AMX_CurlFormAdd(AMX* amx, cell* params) {
CurlWebForm* form = (CurlWebForm*)GetHandle(params[1], HANDLE_CURL_FORM);
if (!form) {
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[1]);
return false;
}

CURLFORMcode result = CURL_FORMADD_OK;
int params_number = params[0], i = 2, j = 0, pairs;

if ((params_number - 2) % 2 != 0) {
return CURL_FORMADD_INCOMPLETE;
}

pairs = (params_number - 2) >> 1;

ke::FixedArray<ke::AString> strings(pairs);
ke::FixedArray<curl_forms> arr(pairs);

for (; i < params_number && result == CURL_FORMADD_OK; ++i, ++j) {
cell part1 = *MF_GetAmxAddr(amx, params[i]);
CURLformoption option = (CURLformoption)part1;

if (CURLFORM_END == option) {
arr[j].option = CURLFORM_END;
break;
}

++i;
arr[j].option = option;

if (curl_module_form_is_cell_option(option) ||
curl_module_form_is_string_option(option)
) {
int len;
strings[j] = MF_GetAmxString(amx, params[i], 0, &len);
arr[j].value = strings[j].chars();
} else if (CURLFORM_CONTENTHEADER == option) {
CurlSList* slist = (CurlSList*)GetHandle(params[i], HANDLE_CURL_SLIST);
if (!slist) {
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid handle: %d", params[i]);
result = CURL_FORMADD_INCOMPLETE;
} else {
arr[j].value = (char*)slist;
}
}
}

if (result == CURL_FORMADD_OK) {
form->SetArray(arr.buffer());
result = form->last_error();
}

return result;
}

AMX_NATIVE_INFO g_BaseCurlNatives[] = {
{"curl_init", AMX_CurlInit},
{"curl_close", AMX_CurlClose},
Expand All @@ -265,5 +359,8 @@ AMX_NATIVE_INFO g_BaseCurlNatives[] = {
{"curl_create_slist", AMX_CurlCreateSList},
{"curl_destroy_slist", AMX_CurlDestroySList},
{"curl_slist_append", AMX_CurlSListAppend},
{"curl_create_form", AMX_CurlCreateForm},
{"curl_destroy_form", AMX_CurlDestroyForm},
{"curl_form_add", AMX_CurlFormAdd},
{NULL, NULL}
};
3 changes: 2 additions & 1 deletion curl_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ enum HandleType
HANDLE_CURL = 0,
HANDLE_CURL_READ,
HANDLE_CURL_WRITE,
HANDLE_CURL_SLIST
HANDLE_CURL_SLIST,
HANDLE_CURL_FORM
};

typedef void (*FREEHANDLE)(void *, unsigned int);
Expand Down
34 changes: 34 additions & 0 deletions lib/curl_wrap.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "curl_wrap.h"
#include "am-vector.h"

static size_t ReadFunction(
char* data, size_t bytes, size_t nitems, void* ctx
Expand Down Expand Up @@ -64,6 +65,33 @@ static void SetDefaultOptions(Curl* ctx) {
curl_easy_setopt(h, CURLOPT_NOSIGNAL, 1);
}

CurlWebForm::CurlWebForm():
first_(NULL),
last_(NULL),
last_error_(CURL_FORMADD_OK) {}

CurlWebForm::~CurlWebForm() {
if (first_) {
curl_formfree(first_);
}
}

curl_httppost* CurlWebForm::GetFormData() {
return first_;
}

bool CurlWebForm::SetArray(const curl_forms* arr) {
last_error_ = curl_formadd(
&first_,
&last_,
CURLFORM_ARRAY,
arr,
CURLFORM_END
);

return last_error_ == CURL_FORMADD_OK;
}

CurlRead::CurlRead() : method(CURL_IGNORE), file(NULL) {}

CurlWrite::CurlWrite() : method(CURL_RETURN), file(NULL) {
Expand Down Expand Up @@ -110,6 +138,12 @@ CURLcode Curl::SetOptionHandle(CURLoption option, void* handle) {
code = curl_easy_setopt(curl_, option, wrapper->slist);
break;
}

case CURLOPT_HTTPPOST: {
CurlWebForm* wrapper = (CurlWebForm*) handle;
code = curl_easy_setopt(curl_, option, wrapper->GetFormData());
break;
}
}

return code;
Expand Down
37 changes: 36 additions & 1 deletion lib/curl_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "curl/curl.h"
#include "am-string.h"
#include "am-hashmap.h"
#include "opts.h"

#define BUFFER_SIZE 3072
Expand All @@ -26,6 +25,24 @@ extern bool inline curl_module_is_string_option(CURLoption option) {
return curl_module_is_option(option, CURL_OPT_STRING);
}

bool inline curl_module_form_is_option(CURLformoption option, int type) {
#define _(op, t) (op == option && type == t) ||
return SUPPORTED_FORM_OPT_LIST(_) /*||*/ false;
#undef _
}

extern bool inline curl_module_form_is_cell_option(CURLformoption option) {
return curl_module_form_is_option(option, CURL_OPT_CELL);
}

extern bool inline curl_module_form_is_handle_option(CURLformoption option) {
return curl_module_form_is_option(option, CURL_OPT_HANDLE);
}

extern bool inline curl_module_form_is_string_option(CURLformoption option) {
return curl_module_form_is_option(option, CURL_OPT_STRING);
}

class CurlSList {
public:
CurlSList(curl_slist* _slist) {
Expand All @@ -40,6 +57,24 @@ class CurlSList {
curl_slist* slist;
};

class CurlWebForm {
public:
CurlWebForm();
~CurlWebForm();

CURLFORMcode last_error() {
return last_error_;
}

curl_httppost* GetFormData();
bool SetArray(const curl_forms* arr);

private:
curl_httppost* first_;
curl_httppost* last_;
CURLFORMcode last_error_;
};

enum CurlMethodT {
CURL_FILE,
CURL_RETURN,
Expand Down
11 changes: 11 additions & 0 deletions lib/opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,15 @@
_(CURLOPT_HTTPPOST, CURL_OPT_HANDLE) \


#define SUPPORTED_FORM_OPT_LIST(_) \
_(CURLFORM_COPYNAME, CURL_OPT_STRING) \
_(CURLFORM_COPYCONTENTS, CURL_OPT_STRING) \
_(CURLFORM_FILECONTENT, CURL_OPT_STRING) \
_(CURLFORM_FILE, CURL_OPT_STRING) \
_(CURLFORM_CONTENTTYPE, CURL_OPT_STRING) \
_(CURLFORM_FILENAME, CURL_OPT_STRING) \
_(CURLFORM_NAMELENGTH, CURL_OPT_CELL) \
_(CURLFORM_CONTENTSLENGTH, CURL_OPT_CELL) \
_(CURLFORM_CONTENTHEADER, CURL_OPT_HANDLE) \

#endif
68 changes: 68 additions & 0 deletions test/curl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,53 @@ enum CURLoption {
CURLOPT_LASTENTRY /* the last unused */
};

enum CURLFORMcode {
CURL_FORMADD_OK, /* first, no error */

CURL_FORMADD_MEMORY,
CURL_FORMADD_OPTION_TWICE,
CURL_FORMADD_NULL,
CURL_FORMADD_UNKNOWN_OPTION,
CURL_FORMADD_INCOMPLETE,
CURL_FORMADD_ILLEGAL_ARRAY,
CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */

CURL_FORMADD_LAST /* last */
};

#define CFINIT(%1) CURLFORM_%1

enum CURLformoption {
CFINIT(NOTHING), /********* the first one is unused ************/

/* */
CFINIT(COPYNAME),
CFINIT(PTRNAME),
CFINIT(NAMELENGTH),
CFINIT(COPYCONTENTS),
CFINIT(PTRCONTENTS),
CFINIT(CONTENTSLENGTH),
CFINIT(FILECONTENT),
CFINIT(ARRAY),
CFINIT(OBSOLETE),
CFINIT(FILE),

CFINIT(BUFFER),
CFINIT(BUFFERPTR),
CFINIT(BUFFERLENGTH),

CFINIT(CONTENTTYPE),
CFINIT(CONTENTHEADER),
CFINIT(FILENAME),
CFINIT(END),
CFINIT(OBSOLETE2),

CFINIT(STREAM),

CURLFORM_LASTENTRY /* the last unused */
};


/**
* Initialize a cUrl session
* @return Handle
Expand Down Expand Up @@ -766,6 +813,7 @@ native CURLcode:curl_setopt_string(Handle:ch, CURLoption:option, const value[]);
*/
native CURLcode:curl_setopt_handle(Handle:ch, CURLoption:option, Handle:handle);


/**
* Callback used by curl_exec, curl_thread_exec
*
Expand Down Expand Up @@ -841,3 +889,23 @@ native curl_destroy_slist(Handle:slist);
* @return True on success, otherwise False
*/
native curl_slist_append(Handle:slist, const str[]);

/**
* Initialize CurlWebForm (pair of curl_httppost struct objects)
* @return Handle
*/
native Handle:curl_create_form();

/**
* Destroy CurlWebForm
* @param form Handle
* @return True on success, otherwise False
*/
native Handle:curl_destroy_form(Handle:form);

/**
* Add a section to a multipart/formdata HTTP POST
* @param form Handle
* any...
*/
native CURLFORMcode:curl_form_add(Handle:form, any:...);
Loading

0 comments on commit 8ce2f32

Please sign in to comment.