aboutsummaryrefslogtreecommitdiff
path: root/extension/natives.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extension/natives.cpp')
-rw-r--r--extension/natives.cpp608
1 files changed, 608 insertions, 0 deletions
diff --git a/extension/natives.cpp b/extension/natives.cpp
new file mode 100644
index 0000000..ef9c2fc
--- /dev/null
+++ b/extension/natives.cpp
@@ -0,0 +1,608 @@
+#include <stdlib.h>
+#include "extension.h"
+#include "curlmanager.h"
+#include "opensslmanager.h"
+#include <sh_string.h>
+#include <curl/curl.h>
+
+#define SETUP_CURL_HANDLE()\
+ cURLHandle *handle;\
+ HandleError err;\
+ HandleSecurity sec(pContext->GetIdentity(), myself_Identity);\
+ if((err = handlesys->ReadHandle(params[1], g_cURLHandle, &sec, (void **)&handle)) != HandleError_None)\
+ {\
+ return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);\
+ }
+
+#define SETUP_CURL_WEBFORM()\
+ WebForm *handle;\
+ HandleError err;\
+ HandleSecurity sec(pContext->GetIdentity(), myself_Identity);\
+ if((err = handlesys->ReadHandle(params[1], g_WebForm, &sec, (void **)&handle)) != HandleError_None)\
+ {\
+ return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);\
+ }
+
+#define SETUP_CURL_SLIST()\
+ cURL_slist_pack *handle;\
+ HandleError err;\
+ HandleSecurity sec(pContext->GetIdentity(), myself_Identity);\
+ if((err = handlesys->ReadHandle(params[1], g_cURLSlist, &sec, (void **)&handle)) != HandleError_None)\
+ {\
+ return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);\
+ }
+
+
+static cell_t sm_curl_easy_init(IPluginContext *pContext, const cell_t *params)
+{
+ CURL *curl = curl_easy_init();
+ if(curl == NULL)
+ {
+ return BAD_HANDLE;
+ }
+
+ cURLHandle *handle = new cURLHandle();
+ memset(handle->errorBuffer,0,sizeof(handle->errorBuffer));
+ memset(handle->callback_Function, 0, sizeof(handle->callback_Function));
+ memset(handle->UserData,0,sizeof(handle->UserData));
+ handle->curl = curl;
+
+ Handle_t hndl = handlesys->CreateHandle(g_cURLHandle, handle, pContext->GetIdentity(), myself_Identity, NULL);
+ if(!hndl)
+ {
+ curl_easy_cleanup(handle->curl);
+ delete handle;
+ return BAD_HANDLE;
+ }
+
+ handle->hndl = hndl;
+ return hndl;
+}
+
+static cell_t sm_curl_easy_setopt_string(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ char *buffer;
+ pContext->LocalToString(params[3], &buffer);
+
+ return g_cURLManager.AddcURLOptionString(handle, (CURLoption)params[2], buffer);
+}
+
+static cell_t sm_curl_easy_setopt_int(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ return g_cURLManager.AddcURLOptionInt(handle, (CURLoption)params[2], params[3]);
+}
+
+static cell_t sm_curl_easy_setopt_int_array(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ cell_t *array;
+ cell_t array_size = params[3];
+ pContext->LocalToPhysAddr(params[2], &array);
+
+ bool valid = true;
+ for(int i=0; i<array_size; i++)
+ {
+ cell_t c1_addr = params[2] + (i * sizeof(cell_t)) + array[i];
+ cell_t *c1_r;
+ pContext->LocalToPhysAddr(c1_addr, &c1_r);
+
+ bool ret = g_cURLManager.AddcURLOptionInt(handle, (CURLoption)c1_r[0], c1_r[1]);
+ if(!ret)
+ {
+ valid = false;
+ }
+ }
+ return valid;
+}
+
+static cell_t sm_curl_easy_setopt_int64(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ char *buffer;
+ pContext->LocalToString(params[3], &buffer);
+
+#ifdef WIN32
+ long long int value = _atoi64(buffer);
+#else
+ long long int value = atoll(buffer);
+#endif
+ return g_cURLManager.AddcURLOptionInt64(handle, (CURLoption)params[2], value);
+}
+
+static cell_t sm_curl_easy_setopt_handle(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ return g_cURLManager.AddcURLOptionHandle(pContext, handle, &sec, (CURLoption)params[2], params[3]);
+}
+
+static cell_t sm_curl_easy_setopt_function(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ IPluginFunction *pFunction = pContext->GetFunctionById(params[3]);
+ if(!pFunction)
+ {
+ return pContext->ThrowNativeError("Invalid function %x", params[3]);
+ }
+
+ return g_cURLManager.AddcURLOptionFunction(pContext, handle, (CURLoption)params[2], pFunction, params[4]);
+}
+
+static cell_t sm_curl_easy_perform_thread(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
+ if(!pFunction)
+ {
+ return pContext->ThrowNativeError("Invalid function %x", params[2]);
+ }
+
+ handle->UserData[UserData_Type_Complete] = params[3];
+ handle->callback_Function[cURL_CallBack_COMPLETE] = pFunction;
+ cURLThread *thread = new cURLThread(handle, cURLThread_Type_PERFORM);
+ g_cURLManager.CreatecURLThread(thread);
+
+ return 1;
+}
+
+static cell_t sm_curl_easy_perform(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ handle->running = true;
+ CURLcode code = curl_easy_perform(handle->curl);
+ handle->running = false;
+ curl_easy_getinfo(handle->curl, CURLINFO_LASTSOCKET, &handle->sockextr);
+
+ return code;
+}
+
+static cell_t sm_curl_easy_getinfo_string(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ int type = (CURLINFO_TYPEMASK & (int)params[2]);
+
+ CURLcode code = CURLE_BAD_FUNCTION_ARGUMENT;
+ if(type == CURLINFO_STRING)
+ {
+ char *string_buffer;
+ code = curl_easy_getinfo(handle->curl, (CURLINFO)params[2], &string_buffer);
+ if(code == CURLE_OK)
+ {
+ pContext->StringToLocalUTF8(params[3], params[4], string_buffer, NULL);
+ }
+ }
+
+ return code;
+}
+
+static cell_t sm_curl_easy_getinfo_int(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ int type = (CURLINFO_TYPEMASK & (int)params[2]);
+
+ cell_t *addr;
+ pContext->LocalToPhysAddr(params[3], &addr);
+ CURLcode code = CURLE_BAD_FUNCTION_ARGUMENT;
+
+ switch(type)
+ {
+ case CURLINFO_LONG:
+ long long_buffer;
+ code = curl_easy_getinfo(handle->curl, (CURLINFO)params[2], &long_buffer);
+ if(code == CURLE_OK)
+ {
+ *addr = (cell_t)long_buffer;
+ }
+ break;
+ case CURLINFO_DOUBLE:
+ double double_buffer;
+ code = curl_easy_getinfo(handle->curl, (CURLINFO)params[2], &double_buffer);
+ if(code == CURLE_OK)
+ {
+ *addr = sp_ftoc((float)double_buffer);
+ }
+ break;
+ }
+ return code;
+}
+
+static cell_t sm_curl_load_opt(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ g_cURLManager.LoadcURLOption(handle);
+ return handle->lasterror;
+}
+
+static cell_t sm_curl_get_error_buffer(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ pContext->StringToLocalUTF8(params[2], params[3], handle->errorBuffer, NULL);
+ return 1;
+}
+
+static cell_t sm_curl_easy_escape(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ char *url;
+ pContext->LocalToString(params[2], &url);
+
+ char *buffer = curl_easy_escape(handle->curl, url, strlen(url));
+ if(buffer == NULL)
+ return 0;
+
+ pContext->StringToLocalUTF8(params[3], params[4], buffer, NULL);
+ curl_free(buffer);
+ return 1;
+}
+
+static cell_t sm_curl_easy_unescape(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ char *url;
+ pContext->LocalToString(params[2], &url);
+
+ int outlen;
+ char *buffer = curl_easy_unescape(handle->curl, url, strlen(url), &outlen);
+ if(buffer == NULL)
+ return 0;
+
+ pContext->StringToLocalUTF8(params[3], params[4], buffer, NULL);
+ curl_free(buffer);
+ return outlen;
+}
+
+static cell_t sm_curl_easy_strerror(IPluginContext *pContext, const cell_t *params)
+{
+ const char *error_code = curl_easy_strerror((CURLcode)params[1]);
+ pContext->StringToLocalUTF8(params[2], params[3], error_code, NULL);
+ return 1;
+}
+
+/* send & recv */
+static cell_t sm_curl_easy_send_recv(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ IPluginFunction *pFunction_send = pContext->GetFunctionById(params[2]);
+ if(!pFunction_send)
+ {
+ return pContext->ThrowNativeError("Invalid function %x", params[2]);
+ }
+
+ IPluginFunction *pFunction_recv = pContext->GetFunctionById(params[3]);
+ if(!pFunction_recv)
+ {
+ return pContext->ThrowNativeError("Invalid function %x", params[3]);
+ }
+
+ IPluginFunction *pFunction_complete = pContext->GetFunctionById(params[4]);
+ if(!pFunction_complete)
+ {
+ return pContext->ThrowNativeError("Invalid function %x", params[4]);
+ }
+
+ handle->send_timeout = params[6];
+ handle->recv_timeout = params[7];
+ handle->UserData[UserData_Type_Send_Recv] = params[9];
+ handle->callback_Function[cURL_CallBack_SEND] = pFunction_send;
+ handle->callback_Function[cURL_CallBack_RECV] = pFunction_recv;
+ handle->callback_Function[cURL_CallBack_COMPLETE] = pFunction_complete;
+ cURLThread *thread = new cURLThread(handle, cURLThread_Type_SEND_RECV);
+ thread->SetRecvBufferSize(params[8]);
+ thread->SetSenRecvAction((SendRecv_Act)params[5]);
+ g_cURLManager.CreatecURLThread(thread);
+
+ return 1;
+}
+
+static cell_t sm_curl_send_recv_Signal(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ if(handle->thread == NULL)
+ return 0;
+
+ cURLThread *thread = handle->thread;
+ if(thread->GetRunType() != cURLThread_Type_SEND_RECV ||
+ !handle->running || !thread->IsWaiting()) // is send & recv thread, running, is waiting
+ {
+ return 0;
+ }
+
+ thread->SetSenRecvAction((SendRecv_Act)params[2]);
+ thread->EventSignal();
+
+ return 1;
+}
+
+
+static cell_t sm_curl_send_recv_IsWaiting(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ cURLThread *thread = handle->thread;
+ if(thread == NULL || thread->GetRunType() != cURLThread_Type_SEND_RECV || !handle->running)
+ return 0;
+
+ return (thread->IsWaiting()) ? 1 : 0;
+}
+
+
+static cell_t sm_curl_set_send_buffer(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ char *buffer;
+ pContext->LocalToString(params[2], &buffer);
+
+ if(params[3] == -1)
+ {
+ handle->send_buffer.assign(buffer);
+ } else {
+ handle->send_buffer.assign(buffer,params[3]);
+ }
+
+ return 1;
+}
+
+static cell_t sm_curl_set_receive_size(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ if(handle->thread != NULL)
+ {
+ handle->thread->SetRecvBufferSize((unsigned int)params[2]);
+ }
+ return 1;
+}
+
+static cell_t sm_curl_set_send_timeout(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ if(params[2] > 0)
+ handle->send_timeout = params[2];
+
+ return 1;
+}
+
+static cell_t sm_curl_set_recv_timeout(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_HANDLE();
+
+ if(params[2] > 0)
+ handle->recv_timeout = params[2];
+
+ return 1;
+}
+
+/* Stuff */
+static cell_t sm_curl_version(IPluginContext *pContext, const cell_t *params)
+{
+ pContext->StringToLocalUTF8(params[1], params[2], curl_version(), NULL);
+ return 1;
+}
+
+static cell_t sm_curl_features(IPluginContext *pContext, const cell_t *params)
+{
+ curl_version_info_data *vinfo = curl_version_info(CURLVERSION_NOW);
+ return vinfo->features;
+}
+
+static cell_t sm_curl_protocols(IPluginContext *pContext, const cell_t *params)
+{
+ curl_version_info_data *vinfo = curl_version_info(CURLVERSION_NOW);
+
+ SourceHook::String buffer;
+ const char * const *proto;
+ for(proto=vinfo->protocols; *proto; ++proto) {
+ buffer.append(*proto);
+ buffer.append(" ");
+ }
+ buffer.trim();
+ pContext->StringToLocalUTF8(params[1], params[2], buffer.c_str(), NULL);
+ return 1;
+}
+
+static cell_t sm_curl_OpenFile(IPluginContext *pContext, const cell_t *params)
+{
+ char *name, *mode;
+ int err;
+ if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return 0;
+ }
+ if ((err=pContext->LocalToString(params[2], &mode)) != SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(err, NULL);
+ return 0;
+ }
+
+ char realpath[PLATFORM_MAX_PATH];
+ g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
+
+ FILE *pFile = fopen(realpath, mode);
+ if(!pFile)
+ return 0;
+
+ cURL_OpenFile *openfile = new cURL_OpenFile();
+ openfile->pFile = pFile;
+
+ return handlesys->CreateHandle(g_cURLFile, openfile, pContext->GetIdentity(), myself_Identity, NULL);
+}
+
+static cell_t sm_curl_httppost(IPluginContext *pContext, const cell_t *params)
+{
+ WebForm *webform = new WebForm();
+
+ Handle_t hndl = handlesys->CreateHandle(g_WebForm, webform, pContext->GetIdentity(), myself_Identity, NULL);
+ if(!hndl)
+ {
+ delete webform;
+ return BAD_HANDLE;
+ }
+ return hndl;
+}
+
+static cell_t sm_curl_formadd(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_WEBFORM();
+
+ return (cell_t)g_cURLManager.cURLFormAdd(pContext, params, handle);
+}
+
+static cell_t sm_curl_slist_append(IPluginContext *pContext, const cell_t *params)
+{
+ SETUP_CURL_SLIST();
+
+ char *data;
+ pContext->LocalToString(params[2], &data);
+
+ handle->chunk = curl_slist_append(handle->chunk, data);
+ return 1;
+}
+
+static cell_t sm_curl_slist(IPluginContext *pContext, const cell_t *params)
+{
+ cURL_slist_pack *slist_pack = new cURL_slist_pack();
+
+ Handle_t hndl = handlesys->CreateHandle(g_cURLSlist, slist_pack, pContext->GetIdentity(), myself_Identity, NULL);
+ if(!hndl)
+ {
+ delete slist_pack;
+ return BAD_HANDLE;
+ }
+ return hndl;
+}
+
+static cell_t sm_curl_hash_file(IPluginContext *pContext, const cell_t *params)
+{
+ IPluginFunction *pFunction = pContext->GetFunctionById(params[3]);
+ if(!pFunction)
+ {
+ return pContext->ThrowNativeError("Invalid function %x", params[3]);
+ }
+
+ char *filepath;
+ pContext->LocalToString(params[1], &filepath);
+ int len = strlen(filepath);
+
+ Openssl_Hash_pack *hash_pack = new Openssl_Hash_pack();
+ hash_pack->UserData = params[4];
+ hash_pack->path = new char[len+1];
+ strncpy(hash_pack->path, filepath, len);
+ hash_pack->path[len] = '\0';
+
+ hash_pack->hash_callback = pFunction;
+ hash_pack->algorithm = (Openssl_Hash)params[2];
+
+ OpensslThread *thread = new OpensslThread(hash_pack, OpensslThread_Type_HASH_FILE);
+ threader->MakeThread(thread);
+
+ return 1;
+}
+
+static cell_t sm_curl_hash_string(IPluginContext *pContext, const cell_t *params)
+{
+ Openssl_Hash hashType = (Openssl_Hash)params[3];
+ if
+ (
+ hashType == Openssl_Hash_MD2
+ || hashType == Openssl_Hash_SHA
+ )
+ {
+ return pContext->ThrowNativeError("Deprecated hash function %x - Sorry!", params[3]);
+ }
+
+ char *input;
+ unsigned int data_size = (unsigned int)params[2];
+ if(data_size > 0)
+ {
+ cell_t *addr;
+ pContext->LocalToPhysAddr(params[1], &addr);
+ input = (char *)addr;
+ data_size = params[2];
+ } else {
+ pContext->LocalToString(params[1], &input);
+ data_size = strlen(input);
+ }
+
+ unsigned char output[128];
+ int outlength = 0;
+ bool ret = g_OpensslManager.HashString((Openssl_Hash)params[3], (unsigned char *)input, data_size, &output[0], &outlength);
+ if(!ret || outlength == 0)
+ return 0;
+
+ char buffer[256];
+ int pos = 0;
+ for(int i=0; i<outlength; i++)
+ {
+ sprintf(&buffer[pos],"%02x",(unsigned char)output[i]);
+ pos+=2;
+ }
+ size_t bytes;
+ pContext->StringToLocalUTF8(params[4], params[5], buffer, &bytes);
+ return 1;
+}
+
+sp_nativeinfo_t g_cURLNatives[] =
+{
+ {"curl_easy_init", sm_curl_easy_init},
+ {"curl_easy_setopt_string", sm_curl_easy_setopt_string},
+ {"curl_easy_setopt_int", sm_curl_easy_setopt_int},
+ {"curl_easy_setopt_int_array", sm_curl_easy_setopt_int_array},
+ {"curl_easy_setopt_int64", sm_curl_easy_setopt_int64},
+ {"curl_easy_setopt_handle", sm_curl_easy_setopt_handle},
+ {"curl_easy_setopt_function", sm_curl_easy_setopt_function},
+ {"curl_easy_perform_thread", sm_curl_easy_perform_thread},
+ {"curl_easy_perform", sm_curl_easy_perform},
+ {"curl_easy_getinfo_string", sm_curl_easy_getinfo_string},
+ {"curl_easy_getinfo_int", sm_curl_easy_getinfo_int},
+ {"curl_load_opt", sm_curl_load_opt},
+ {"curl_easy_escape", sm_curl_easy_escape},
+ {"curl_easy_unescape", sm_curl_easy_unescape},
+ {"curl_easy_strerror", sm_curl_easy_strerror},
+ {"curl_get_error_buffer", sm_curl_get_error_buffer},
+
+ {"curl_easy_send_recv", sm_curl_easy_send_recv},
+ {"curl_set_send_buffer", sm_curl_set_send_buffer},
+ {"curl_send_recv_Signal", sm_curl_send_recv_Signal},
+ {"curl_send_recv_IsWaiting", sm_curl_send_recv_IsWaiting},
+ {"curl_set_receive_size", sm_curl_set_receive_size},
+ {"curl_set_send_timeout", sm_curl_set_send_timeout},
+ {"curl_set_recv_timeout", sm_curl_set_recv_timeout},
+
+ {"curl_version", sm_curl_version},
+ {"curl_features", sm_curl_features},
+ {"curl_protocols", sm_curl_protocols},
+ {"curl_OpenFile", sm_curl_OpenFile},
+
+ {"curl_httppost", sm_curl_httppost},
+ {"curl_formadd", sm_curl_formadd},
+
+ {"curl_slist_append", sm_curl_slist_append},
+ {"curl_slist", sm_curl_slist},
+
+ {"curl_hash_file", sm_curl_hash_file},
+ {"curl_hash_string", sm_curl_hash_string},
+
+ {NULL, NULL}
+};
+
+