aboutsummaryrefslogtreecommitdiff
path: root/extension/curlmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extension/curlmanager.cpp')
-rw-r--r--extension/curlmanager.cpp897
1 files changed, 897 insertions, 0 deletions
diff --git a/extension/curlmanager.cpp b/extension/curlmanager.cpp
new file mode 100644
index 0000000..973d133
--- /dev/null
+++ b/extension/curlmanager.cpp
@@ -0,0 +1,897 @@
+#include "curlmanager.h"
+
+#ifdef PLATFORM_LINUX
+#include <netinet/in.h>
+#endif
+
+
+cURLManager g_cURLManager;
+
+
+struct data_t {
+ data_t(cURLHandle *_handle, size_t _bytes, size_t _nmemb):
+ handle(_handle), buffer(NULL), bytes(_bytes), nmemb(_nmemb)
+ {
+ }
+ cURLHandle *handle;
+ char *buffer;
+ size_t bytes;
+ size_t nmemb;
+ size_t return_value;
+};
+
+/* Write Function */
+static size_t curl_write_function_default(void *ptr, size_t bytes, size_t nmemb, void *stream)
+{
+ FILE *file = (FILE *)stream;
+#ifdef WIN32
+ if(file->_file >= 3)
+#else
+ if(file->_fileno >= 3)
+#endif
+ {
+ return fwrite(ptr, bytes, nmemb, file);
+ }
+ return (bytes * nmemb);
+}
+
+static size_t Call_Write_Function(cURLHandle *handle, const char *buffer, size_t bytes, size_t nmemb)
+{
+ IPluginFunction *pFunc = handle->callback_Function[cURL_CallBack_WRITE_FUNCTION];
+ assert((pFunc != NULL));
+ cell_t result = bytes * nmemb;
+ if(pFunc != NULL)
+ {
+ pFunc->PushCell(handle->hndl);
+ pFunc->PushStringEx((char *)buffer, nmemb+1, SM_PARAM_STRING_COPY|SM_PARAM_STRING_BINARY, 0);
+ pFunc->PushCell(bytes);
+ pFunc->PushCell(nmemb);
+ pFunc->PushCell(handle->UserData[UserData_Type_Write_Func]);
+ pFunc->Execute(&result);
+ }
+ return result;
+}
+
+static void sm_write_function_FrameAction(void *data)
+{
+ if(data == NULL)
+ return;
+
+ data_t *wdata = (data_t*)data;
+ wdata->return_value = Call_Write_Function(wdata->handle, wdata->buffer, wdata->bytes, wdata->nmemb);
+ wdata->handle->thread->EventSignal();
+}
+
+static size_t curl_write_function_SM(void *ptr, size_t bytes, size_t nmemb, void *stream)
+{
+ cURLHandle *handle = (cURLHandle *)stream;
+
+ size_t ret;
+ if(handle->thread == NULL)
+ {
+ char *buffer = new char[nmemb+1];
+ memcpy(buffer,ptr, nmemb);
+ buffer[nmemb] = '\0';
+ ret = Call_Write_Function(handle, buffer, bytes, nmemb);
+ delete [] buffer;
+ } else {
+ if(g_cURL_SM.IsShutdown())
+ return (bytes * nmemb);
+
+ data_t *data = new data_t(handle, bytes, nmemb);
+ data->buffer = new char[nmemb+1];
+ memcpy(data->buffer,ptr, nmemb);
+ data->buffer[nmemb] = '\0';
+
+ smutils->AddFrameAction(sm_write_function_FrameAction, data);
+ handle->thread->EventWait();
+
+ ret = data->return_value;
+ delete [] data->buffer;
+ delete data;
+
+ if(g_cURL_SM.IsShutdown())
+ return (bytes * nmemb);
+ }
+
+ return ret;
+}
+
+/* Read Function */
+static size_t Call_Read_Function(cURLHandle *handle, size_t bytes, size_t nmemb)
+{
+ IPluginFunction *pFunc = handle->callback_Function[cURL_CallBack_READ_FUNCTION];
+ assert((pFunc != NULL));
+ cell_t result = bytes * nmemb;
+ if(pFunc != NULL)
+ {
+ pFunc->PushCell(handle->hndl);
+ pFunc->PushCell(bytes);
+ pFunc->PushCell(nmemb);
+ pFunc->PushCell(handle->UserData[UserData_Type_Read_Func]);
+ pFunc->Execute(&result);
+ }
+ return result;
+}
+
+static void sm_read_function_FrameAction(void *data)
+{
+ if(data == NULL)
+ return;
+
+ data_t *rdata = (data_t*)data;
+ rdata->return_value = Call_Read_Function(rdata->handle, rdata->bytes, rdata->nmemb);
+ rdata->handle->thread->EventSignal();
+}
+
+
+static size_t curl_read_function_SM(char *ptr, size_t bytes, size_t nmemb, void *stream)
+{
+ cURLHandle *handle = (cURLHandle *)stream;
+
+ size_t ret = 0;
+ if(handle->thread == NULL)
+ {
+ ret = Call_Read_Function(handle, bytes, nmemb);
+ } else {
+ if(g_cURL_SM.IsShutdown())
+ return 0;
+
+ data_t *data = new data_t(handle, bytes, nmemb);
+
+ smutils->AddFrameAction(sm_read_function_FrameAction, data);
+ handle->thread->EventWait();
+
+ ret = data->return_value;
+ delete data;
+
+ if(g_cURL_SM.IsShutdown())
+ return 0;
+ }
+
+ if(ret > 0)
+ {
+ memcpy(ptr,handle->send_buffer.data(), handle->send_buffer.size());
+ }
+
+ return ret;
+}
+
+static curl_socket_t curl_opensocket_function(void *clientp, curlsocktype purpose, struct curl_sockaddr *address)
+{
+ cURLHandle *handle = (cURLHandle *)clientp;
+ if(handle->is_udp)
+ {
+ address->socktype = SOCK_DGRAM;
+ address->protocol = IPPROTO_UDP;
+ address->family = AF_INET;
+ }
+
+ return socket(address->family, address->socktype, address->protocol);
+}
+
+void cURLManager::SDK_OnLoad()
+{
+ curlhandle_list_mutex = threader->MakeMutex();
+ shutdown_event = threader->MakeEventSignal();
+ closehelper_list_mutex = threader->MakeMutex();
+
+ waiting = false;
+}
+
+void cURLManager::SDK_OnUnload()
+{
+ curlhandle_list_mutex->Lock();
+ if(g_cURLThread_List.size() > 0)
+ {
+ printf("[%s] Waiting %d cURL Threads Terminate...\n",SMEXT_CONF_LOGTAG,g_cURLThread_List.size());
+
+ SourceHook::List<cURLThread *>::iterator iter = g_cURLThread_List.begin();
+ cURLThread *pInfo;
+ while (iter != g_cURLThread_List.end())
+ {
+ pInfo = (*iter);
+ if(pInfo->waiting) {
+ pInfo->event->Signal();
+ }
+ iter++;
+ }
+
+ curlhandle_list_mutex->Unlock();
+
+ waiting = true;
+ shutdown_event->Wait();
+
+ printf("[%s] All cURL Thread Terminated !!!\n",SMEXT_CONF_LOGTAG);
+ } else {
+ curlhandle_list_mutex->Unlock();
+ }
+
+ shutdown_event->DestroyThis();
+ curlhandle_list_mutex->DestroyThis();
+
+ shutdown_event = NULL;
+ curlhandle_list_mutex = NULL;
+ g_cURLThread_List.clear();
+
+ g_CloseHelper_List.clear();
+}
+
+void cURLManager::CreatecURLThread(cURLThread *thread)
+{
+ if(g_cURL_SM.IsShutdown())
+ {
+ delete thread;
+ return;
+ }
+ curlhandle_list_mutex->Lock();
+ g_cURLThread_List.push_back(thread);
+ curlhandle_list_mutex->Unlock();
+
+ threader->MakeThread(thread);
+}
+
+void cURLManager::RemovecURLThread(cURLThread *thread)
+{
+ if(g_cURL_SM.IsShutdown())
+ {
+ RemovecURLHandle(thread->handle);
+ }
+
+ curlhandle_list_mutex->Lock();
+ g_cURLThread_List.remove(thread);
+
+ if(waiting)
+ {
+ if(g_cURLThread_List.size() == 0)
+ {
+ curlhandle_list_mutex->Unlock();
+ shutdown_event->Signal();
+ return;
+ }
+ }
+ curlhandle_list_mutex->Unlock();
+}
+
+void cURLManager::AddCloseHelperHandle(ICloseHelper *helper)
+{
+ closehelper_list_mutex->Lock();
+ if(g_CloseHelper_List.find(helper) == g_CloseHelper_List.end())
+ {
+ g_CloseHelper_List.push_back(helper);
+ }
+ closehelper_list_mutex->Unlock();
+}
+
+void cURLManager::RemoveCloseHelperHandle(ICloseHelper *helper)
+{
+ closehelper_list_mutex->Lock();
+ g_CloseHelper_List.remove(helper);
+ closehelper_list_mutex->Unlock();
+}
+
+void cURLManager::RemoveLinkedICloseHelper(cURLHandle *handle)
+{
+ closehelper_list_mutex->Lock();
+
+ SourceHook::List<ICloseHelper *>::iterator iter;
+ ICloseHelper *pInfo;
+ for (iter=g_CloseHelper_List.begin(); iter!=g_CloseHelper_List.end(); iter++)
+ {
+ pInfo = (*iter);
+ if(pInfo->_handle == handle)
+ {
+ pInfo->_handle = NULL;
+ if(pInfo->_marked_delete)
+ {
+ pInfo->Delete();
+ iter = g_CloseHelper_List.erase(iter);
+ }
+ }
+ }
+
+ closehelper_list_mutex->Unlock();
+}
+
+void cURLManager::RemovecURLHandle(cURLHandle *handle)
+{
+ if(!handle || handle->running)
+ return;
+
+ if(handle->thread != NULL)
+ {
+ handle->thread->handle = NULL;
+ }
+ curl_easy_cleanup(handle->curl);
+ handle->curl = NULL;
+
+ SourceHook::List<cURLOpt_string *>::iterator iter;
+ cURLOpt_string *pInfo;
+ for (iter=handle->opt_string_list.begin(); iter!=handle->opt_string_list.end(); iter++)
+ {
+ pInfo = (*iter);
+ delete [] pInfo->value;
+ delete pInfo;
+ }
+ handle->opt_string_list.clear();
+
+ SourceHook::List<cURLOpt_int *>::iterator iter2;
+ cURLOpt_int*pInfo2;
+ for (iter2=handle->opt_int_list.begin(); iter2!=handle->opt_int_list.end(); iter2++)
+ {
+ pInfo2 = (*iter2);
+ delete pInfo2;
+ }
+ handle->opt_int_list.clear();
+
+ SourceHook::List<cURLOpt_pointer *>::iterator iter3;
+ cURLOpt_pointer *pInfo3;
+ for(iter3=handle->opt_pointer_list.begin(); iter3!=handle->opt_pointer_list.end(); iter3++)
+ {
+ pInfo3 = (*iter3);
+ delete pInfo3;
+ }
+ handle->opt_pointer_list.clear();
+
+ SourceHook::List<cURLOpt_int64 *>::iterator iter4;
+ cURLOpt_int64 *pInfo4;
+ for(iter4=handle->opt_int64_list.begin(); iter4!=handle->opt_int64_list.end(); iter4++)
+ {
+ pInfo4 = (*iter4);
+ delete pInfo4;
+ }
+ handle->opt_int64_list.clear();
+
+ handle->send_buffer.clear();
+
+ RemoveLinkedICloseHelper(handle);
+
+ delete handle;
+}
+
+bool cURLManager::AddcURLOptionString(cURLHandle *handle, CURLoption opt, char *value)
+{
+ if(!handle || handle->running || !value)
+ return false;
+
+ std::string value_str;
+
+ bool supported = false;
+ switch(opt)
+ {
+ case CURLOPT_URL:
+ {
+ char *lowercase_value = UTIL_ToLowerCase(value);
+ std::string value_str_lower(lowercase_value);
+ delete [] lowercase_value;
+
+ if(!value_str_lower.compare(0,6, "udp://"))
+ {
+ handle->is_udp = true;
+ value_str.assign(&value[6]);
+ } else {
+ value_str = value;
+ handle->is_udp = false;
+ }
+ supported = true;
+ break;
+ }
+ case CURLOPT_PROXY:
+ case CURLOPT_PROXYUSERPWD:
+ case CURLOPT_RANGE:
+ case CURLOPT_USERPWD:
+ case CURLOPT_KEYPASSWD:
+ case CURLOPT_POSTFIELDS:
+ case CURLOPT_REFERER:
+ case CURLOPT_FTPPORT:
+ case CURLOPT_USERAGENT:
+ case CURLOPT_COOKIE:
+ case CURLOPT_ENCODING:
+ case CURLOPT_CUSTOMREQUEST:
+ case CURLOPT_WRITEINFO:
+ case CURLOPT_INTERFACE:
+ case CURLOPT_KRBLEVEL:
+ case CURLOPT_SSL_CIPHER_LIST:
+ case CURLOPT_SSLCERTTYPE:
+ case CURLOPT_SSLKEYTYPE:
+ case CURLOPT_SSLENGINE:
+ case CURLOPT_FTP_ACCOUNT:
+ case CURLOPT_COOKIELIST:
+ case CURLOPT_FTP_ALTERNATIVE_TO_USER:
+ case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
+ case CURLOPT_USERNAME:
+ case CURLOPT_PASSWORD:
+ case CURLOPT_PROXYUSERNAME:
+ case CURLOPT_PROXYPASSWORD:
+ case CURLOPT_NOPROXY:
+ case CURLOPT_SOCKS5_GSSAPI_SERVICE:
+ case CURLOPT_MAIL_FROM:
+ case CURLOPT_RTSP_SESSION_ID:
+ case CURLOPT_RTSP_STREAM_URI:
+ case CURLOPT_RTSP_TRANSPORT:
+ value_str.assign(value);
+ supported = true;
+ break;
+ case CURLOPT_COOKIEFILE:
+ case CURLOPT_COOKIEJAR:
+ case CURLOPT_RANDOM_FILE:
+ case CURLOPT_EGDSOCKET:
+ case CURLOPT_SSLCERT:
+ case CURLOPT_SSLKEY:
+ case CURLOPT_CAINFO:
+ case CURLOPT_CAPATH:
+ case CURLOPT_NETRC_FILE:
+ case CURLOPT_SSH_PUBLIC_KEYFILE:
+ case CURLOPT_SSH_PRIVATE_KEYFILE:
+ case CURLOPT_CRLFILE:
+ case CURLOPT_ISSUERCERT:
+ case CURLOPT_SSH_KNOWNHOSTS:
+ {
+ char realpath[PLATFORM_MAX_PATH];
+ g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", value);
+ value_str.assign(realpath);
+ supported = true;
+ break;
+ }
+ }
+
+ assert((supported != false));
+ if(!supported)
+ return false;
+
+ cURLOpt_string *stringopt = new cURLOpt_string();
+ stringopt->opt = opt;
+ stringopt->value = new char[value_str.size()+1];
+ memset(stringopt->value, 0, value_str.size()+1);
+ memcpy(stringopt->value,value_str.c_str(), value_str.size());
+
+ handle->opt_string_list.push_back(stringopt);
+
+ return true;
+}
+
+bool cURLManager::AddcURLOptionInt(cURLHandle *handle, CURLoption opt, int value)
+{
+ if(!handle || handle->running)
+ return false;
+
+ bool supported = false;
+ switch(opt)
+ {
+ case CURLOPT_PORT:
+ case CURLOPT_NOPROGRESS:
+ case CURLOPT_VERBOSE:
+ case CURLOPT_PROXYTYPE:
+ case CURLOPT_HTTPPROXYTUNNEL:
+ case CURLOPT_TIMEOUT:
+ case CURLOPT_SSL_VERIFYPEER:
+ case CURLOPT_SSL_VERIFYHOST:
+ case CURLOPT_UPLOAD:
+ case CURLOPT_INFILESIZE:
+ case CURLOPT_LOW_SPEED_LIMIT:
+ case CURLOPT_LOW_SPEED_TIME:
+ case CURLOPT_RESUME_FROM:
+ case CURLOPT_CRLF:
+ case CURLOPT_SSLVERSION:
+ case CURLOPT_TIMECONDITION:
+ case CURLOPT_TIMEVALUE:
+ case CURLOPT_HEADER:
+ case CURLOPT_NOBODY:
+ case CURLOPT_FAILONERROR:
+ case CURLOPT_POST:
+ case CURLOPT_DIRLISTONLY:
+ case CURLOPT_APPEND:
+ case CURLOPT_NETRC:
+ case CURLOPT_FOLLOWLOCATION:
+ case CURLOPT_TRANSFERTEXT:
+ case CURLOPT_PUT:
+ case CURLOPT_AUTOREFERER:
+ case CURLOPT_PROXYPORT:
+ case CURLOPT_POSTFIELDSIZE:
+ case CURLOPT_MAXREDIRS:
+ case CURLOPT_FILETIME:
+ case CURLOPT_MAXCONNECTS:
+ case CURLOPT_CLOSEPOLICY:
+ case CURLOPT_FRESH_CONNECT:
+ case CURLOPT_FORBID_REUSE:
+ case CURLOPT_CONNECTTIMEOUT:
+ case CURLOPT_HTTPGET:
+ case CURLOPT_HTTP_VERSION:
+ case CURLOPT_FTP_USE_EPSV:
+ case CURLOPT_SSLENGINE_DEFAULT:
+ case CURLOPT_DNS_USE_GLOBAL_CACHE:
+ case CURLOPT_DNS_CACHE_TIMEOUT:
+ case CURLOPT_COOKIESESSION:
+ case CURLOPT_BUFFERSIZE:
+ case CURLOPT_NOSIGNAL:
+ case CURLOPT_UNRESTRICTED_AUTH:
+ case CURLOPT_FTP_USE_EPRT:
+ case CURLOPT_HTTPAUTH:
+ case CURLOPT_FTP_CREATE_MISSING_DIRS:
+ case CURLOPT_PROXYAUTH:
+ case CURLOPT_FTP_RESPONSE_TIMEOUT:
+ case CURLOPT_IPRESOLVE:
+ case CURLOPT_MAXFILESIZE:
+ case CURLOPT_USE_SSL:
+ case CURLOPT_TCP_NODELAY:
+ case CURLOPT_FTPSSLAUTH:
+ case CURLOPT_IGNORE_CONTENT_LENGTH:
+ case CURLOPT_FTP_SKIP_PASV_IP:
+ case CURLOPT_FTP_FILEMETHOD:
+ case CURLOPT_LOCALPORT:
+ case CURLOPT_LOCALPORTRANGE:
+ case CURLOPT_CONNECT_ONLY:
+ case CURLOPT_SSL_SESSIONID_CACHE:
+ case CURLOPT_SSH_AUTH_TYPES:
+ case CURLOPT_FTP_SSL_CCC:
+ case CURLOPT_TIMEOUT_MS:
+ case CURLOPT_CONNECTTIMEOUT_MS:
+ case CURLOPT_HTTP_TRANSFER_DECODING:
+ case CURLOPT_HTTP_CONTENT_DECODING:
+ case CURLOPT_NEW_FILE_PERMS:
+ case CURLOPT_NEW_DIRECTORY_PERMS:
+ case CURLOPT_POSTREDIR:
+ case CURLOPT_PROXY_TRANSFER_MODE:
+ case CURLOPT_ADDRESS_SCOPE:
+ case CURLOPT_CERTINFO:
+ case CURLOPT_TFTP_BLKSIZE:
+ case CURLOPT_PROTOCOLS:
+ case CURLOPT_REDIR_PROTOCOLS:
+ case CURLOPT_FTP_USE_PRET:
+ case CURLOPT_RTSP_REQUEST:
+ case CURLOPT_RTSP_CLIENT_CSEQ:
+ case CURLOPT_RTSP_SERVER_CSEQ:
+ case CURLOPT_WILDCARDMATCH:
+ case CURLOPT_TRANSFER_ENCODING:
+ case CURLOPT_GSSAPI_DELEGATION:
+ supported = true;
+ break;
+ }
+
+ assert((supported != false));
+ if(!supported)
+ return false;
+
+ cURLOpt_int *intopt = new cURLOpt_int();
+ intopt->opt = opt;
+ intopt->value = value;
+
+ handle->opt_int_list.push_back(intopt);
+
+ return true;
+}
+
+bool cURLManager::AddcURLOptionInt64(cURLHandle *handle, CURLoption opt, long long value)
+{
+ if(!handle || handle->running)
+ return false;
+
+ bool supported = false;
+ switch(opt)
+ {
+ case CURLOPT_INFILESIZE_LARGE:
+ case CURLOPT_RESUME_FROM_LARGE:
+ case CURLOPT_MAXFILESIZE_LARGE:
+ case CURLOPT_POSTFIELDSIZE_LARGE:
+ case CURLOPT_MAX_SEND_SPEED_LARGE:
+ case CURLOPT_MAX_RECV_SPEED_LARGE:
+ supported = true;
+ break;
+ }
+
+ assert((supported != false));
+ if(!supported)
+ return false;
+
+ cURLOpt_int64 *int64opt = new cURLOpt_int64();
+ int64opt->opt = opt;
+ int64opt->value = (curl_off_t)value;
+
+ handle->opt_int64_list.push_back(int64opt);
+ return true;
+}
+
+bool cURLManager::AddcURLOptionFunction(IPluginContext *pContext, cURLHandle *handle, CURLoption opt, IPluginFunction *pFunction, int value)
+{
+ if(!handle || handle->running)
+ return false;
+
+ cURL_CallBack index = cURL_CallBack_NOTHING;
+ switch(opt)
+ {
+ case CURLOPT_WRITEFUNCTION:
+ index = cURL_CallBack_WRITE_FUNCTION;
+ handle->UserData[UserData_Type_Write_Func] = value;
+ break;
+ case CURLOPT_READFUNCTION:
+ index = cURL_CallBack_READ_FUNCTION;
+ handle->UserData[UserData_Type_Read_Func] = value;
+ break;
+ }
+
+ if(index == cURL_CallBack_NOTHING)
+ return false;
+
+ handle->callback_Function[index] = pFunction;
+ return true;
+}
+
+
+bool cURLManager::AddcURLOptionHandle(IPluginContext *pContext, cURLHandle *handle, HandleSecurity *sec, CURLoption opt, Handle_t hndl)
+{
+ if(!handle || handle->running)
+ return false;
+
+ void *pointer = NULL;
+ int err = SP_ERROR_NONE;
+ ICloseHelper *helper = NULL;
+
+ switch(opt)
+ {
+ case CURLOPT_WRITEDATA:
+ case CURLOPT_HEADERDATA:
+ case CURLOPT_READDATA:
+ case CURLOPT_STDERR:
+ case CURLOPT_INTERLEAVEDATA:
+ {
+ cURL_OpenFile *openfile = NULL;
+ err = handlesys->ReadHandle(hndl, g_cURLFile, sec, (void **)&openfile);
+ if(openfile != NULL)
+ {
+ pointer = openfile->pFile;
+ openfile->_handle = handle;
+ helper = openfile;
+ }
+ break;
+ }
+ case CURLOPT_HTTPPOST:
+ {
+ WebForm *webform = NULL;
+ err = handlesys->ReadHandle(hndl, g_WebForm, sec, (void **)&webform);
+ if(webform != NULL) {
+ pointer = webform->first;
+ webform->_handle = handle;
+ helper = webform;
+
+ SourceHook::List<cURL_slist_pack *>::iterator iter;
+ cURL_slist_pack *pInfo;
+ for(iter=webform->slist_record.begin(); iter!=webform->slist_record.end(); iter++)
+ {
+ pInfo = (*iter);
+ pInfo->_handle = handle;
+ AddCloseHelperHandle(pInfo);
+ }
+ }
+ break;
+ }
+ case CURLOPT_HTTPHEADER:
+ case CURLOPT_QUOTE:
+ case CURLOPT_POSTQUOTE:
+ case CURLOPT_TELNETOPTIONS:
+ case CURLOPT_PREQUOTE:
+ case CURLOPT_HTTP200ALIASES:
+ case CURLOPT_MAIL_RCPT:
+ case CURLOPT_RESOLVE:
+ {
+ cURL_slist_pack *slist = NULL;
+ err = handlesys->ReadHandle(hndl, g_cURLSlist, sec, (void **)&slist);
+ if(slist != NULL) {
+ pointer = slist->chunk;
+ slist->_handle = handle;
+ helper = slist;
+ }
+ break;
+ }
+ }
+
+ if(err != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return false;
+ }
+
+ assert((pointer != NULL));
+ if(pointer == NULL)
+ return false;
+
+
+ cURLOpt_pointer *pointeropt = new cURLOpt_pointer();
+ pointeropt->opt = opt;
+ pointeropt->value = pointer;
+
+ handle->opt_pointer_list.push_back(pointeropt);
+
+ AddCloseHelperHandle(helper);
+ return true;
+}
+
+void cURLManager::LoadcURLOption(cURLHandle *handle)
+{
+ if(!handle || handle->opt_loaded)
+ return;
+
+ handle->opt_loaded = true;
+
+ curl_easy_setopt(handle->curl, CURLOPT_ERRORBUFFER, handle->errorBuffer);
+
+ curl_easy_setopt(handle->curl, CURLOPT_OPENSOCKETFUNCTION, curl_opensocket_function);
+ curl_easy_setopt(handle->curl, CURLOPT_OPENSOCKETDATA, handle);
+
+ if(handle->callback_Function[cURL_CallBack_WRITE_FUNCTION] == NULL) {
+ curl_easy_setopt(handle->curl, CURLOPT_WRITEFUNCTION, curl_write_function_default);
+ } else {
+ curl_easy_setopt(handle->curl, CURLOPT_WRITEFUNCTION, curl_write_function_SM);
+ curl_easy_setopt(handle->curl, CURLOPT_WRITEDATA, handle);
+ }
+
+ if(handle->callback_Function[cURL_CallBack_READ_FUNCTION] != NULL) {
+ curl_easy_setopt(handle->curl, CURLOPT_READFUNCTION, curl_read_function_SM);
+ curl_easy_setopt(handle->curl, CURLOPT_READDATA, handle);
+ }
+
+
+ SourceHook::List<cURLOpt_string *>::iterator iter;
+ cURLOpt_string *pInfo;
+ for(iter=handle->opt_string_list.begin(); iter!=handle->opt_string_list.end(); iter++)
+ {
+ pInfo = (*iter);
+ if((handle->lasterror = curl_easy_setopt(handle->curl, pInfo->opt, pInfo->value)) != CURLE_OK)
+ return;
+ }
+
+ SourceHook::List<cURLOpt_int *>::iterator iter2;
+ cURLOpt_int *pInfo2;
+ for(iter2=handle->opt_int_list.begin(); iter2!=handle->opt_int_list.end(); iter2++)
+ {
+ pInfo2 = (*iter2);
+ if((handle->lasterror = curl_easy_setopt(handle->curl, pInfo2->opt, pInfo2->value)) != CURLE_OK)
+ return;
+ }
+
+ SourceHook::List<cURLOpt_pointer *>::iterator iter3;
+ cURLOpt_pointer *pInfo3;
+ for(iter3=handle->opt_pointer_list.begin(); iter3!=handle->opt_pointer_list.end(); iter3++)
+ {
+ pInfo3 = (*iter3);
+ //Not allow use CURLOPT_WRITEDATA, CURLOPT_READDATA, if write/read function set
+ if((handle->callback_Function[cURL_CallBack_WRITE_FUNCTION] != NULL && pInfo3->opt == CURLOPT_WRITEDATA)
+ || (handle->callback_Function[cURL_CallBack_READ_FUNCTION] != NULL && pInfo3->opt == CURLOPT_READDATA))
+ {
+ continue;
+ }
+ if((handle->lasterror = curl_easy_setopt(handle->curl, pInfo3->opt, pInfo3->value)) != CURLE_OK)
+ return;
+ }
+
+ SourceHook::List<cURLOpt_int64 *>::iterator iter4;
+ cURLOpt_int64 *pInfo4;
+ for(iter4=handle->opt_int64_list.begin(); iter4!=handle->opt_int64_list.end(); iter4++)
+ {
+ pInfo4 = (*iter4);
+ if((handle->lasterror = curl_easy_setopt(handle->curl, pInfo4->opt, (curl_off_t)pInfo4->value)) != CURLE_OK)
+ return;
+ }
+}
+
+CURLFORMcode cURLManager::cURLFormAdd(IPluginContext *pContext, const cell_t *params, WebForm *handle)
+{
+ assert((handle != NULL));
+ if(handle == NULL)
+ return CURL_FORMADD_INCOMPLETE;
+
+ unsigned int numparams = (unsigned)params[0];
+ unsigned int startparam = 2;
+ if(numparams <= 1 || numparams > 22)
+ return CURL_FORMADD_INCOMPLETE;
+
+ // there are only 10 available/supported CURLFORM_*
+ CURLformoption form_opts[11] = {CURLFORM_NOTHING};
+
+ char *form_data[10];
+ memset(form_data, 0, sizeof(form_data));
+
+ cell_t *addr;
+ int count = 0;
+ int err;
+ int value;
+ for(unsigned int i=startparam;i<=numparams;i++)
+ {
+ if((err=pContext->LocalToPhysAddr(params[i], &addr)) != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return CURL_FORMADD_INCOMPLETE;
+ }
+ CURLformoption form_code = (CURLformoption)*addr;
+ switch(form_code)
+ {
+ case CURLFORM_COPYNAME:
+ case CURLFORM_COPYCONTENTS:
+ case CURLFORM_FILECONTENT:
+ case CURLFORM_FILE:
+ case CURLFORM_CONTENTTYPE:
+ case CURLFORM_FILENAME:
+ if((err=pContext->LocalToString(params[i+1], &form_data[count])) != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return CURL_FORMADD_INCOMPLETE;
+ }
+ if(form_code == CURLFORM_FILE || form_code == CURLFORM_FILECONTENT) // absolute path
+ {
+ char realpath[PLATFORM_MAX_PATH];
+ g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", form_data[count]);
+
+ form_data[count] = realpath;
+ }
+ form_opts[count] = form_code;
+ count++;
+ i++;
+ break;
+ case CURLFORM_NAMELENGTH:
+ case CURLFORM_CONTENTSLENGTH:
+ if((err=pContext->LocalToPhysAddr(params[i+1], &addr)) != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return CURL_FORMADD_INCOMPLETE;
+ }
+ form_opts[count] = form_code;
+ value = *addr;
+ form_data[count] = (char *)value;
+ count++;
+ i++;
+ break;
+ case CURLFORM_CONTENTHEADER:
+ {
+ if((err=pContext->LocalToPhysAddr(params[i+1], &addr)) != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return CURL_FORMADD_INCOMPLETE;
+ }
+ cURL_slist_pack *slist;
+ HandleError hndl_err;
+ HandleSecurity sec(pContext->GetIdentity(), myself_Identity);
+ if((hndl_err = handlesys->ReadHandle(*addr, g_cURLSlist, &sec, (void **)&slist)) != HandleError_None)
+ {
+ pContext->ThrowNativeError("Invalid curl_slist Handle %x (error %d)", params[1], hndl_err);
+ return CURL_FORMADD_INCOMPLETE;
+ }
+ form_opts[count] = form_code;
+ form_data[count] = (char *)slist->chunk;
+ handle->slist_record.push_back(slist); // when webform add into curlhandle, will add slist handle to close helper
+ count++;
+ i++;
+ break;
+ }
+ case CURLFORM_END:
+ form_opts[count] = CURLFORM_END;
+ goto end;
+ }
+ }
+
+end:
+ CURLFORMcode ret = curl_formadd(&handle->first, &handle->last,
+ form_opts[0],
+ form_data[0],
+ form_opts[1],
+ form_data[1],
+ form_opts[2],
+ form_data[2],
+ form_opts[3],
+ form_data[3],
+ form_opts[4],
+ form_data[4],
+ form_opts[5],
+ form_data[5],
+ form_opts[6],
+ form_data[6],
+ form_opts[7],
+ form_data[7],
+ form_opts[8],
+ form_data[8],
+ form_opts[9],
+ form_data[9],
+ form_opts[10]
+ );
+ return ret;
+}
+
+