From e89d7ffacc6a714fa983343e8188c598ff9f7754 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 6 Oct 2025 17:47:20 +1100 Subject: [PATCH] Request paramaters, simple escape sequences --- src/defs/defs.cpp | 3 +- src/modules/request/request.cpp | 61 +++++++++++++++++++++++++++++---- src/utils/escapes/escapes.cpp | 34 ++++++++++++++++++ src/utils/escapes/escapes.h | 5 +++ 4 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 src/utils/escapes/escapes.cpp create mode 100644 src/utils/escapes/escapes.h diff --git a/src/defs/defs.cpp b/src/defs/defs.cpp index dfdfc36..3f9818f 100644 --- a/src/defs/defs.cpp +++ b/src/defs/defs.cpp @@ -5,6 +5,7 @@ #include #include #include "../datatypes/lists/lists.h" +#include "../utils/escapes/escapes.h" InstructionType strToInstructionType(std::string in) { if (in == "println") return InstructionType::Println; @@ -84,7 +85,7 @@ Value::Value(std::string stringval) { if (stringval.length() >= 2 && stringval.front() == '"' && stringval.back() == '"') { valtype = ValueType::String; - string_val = stringval.substr(1, stringval.length() - 2); + string_val = interpretEscapeSequences(stringval.substr(1, stringval.length() - 2)); return; } diff --git a/src/modules/request/request.cpp b/src/modules/request/request.cpp index 9d79ba7..67a9ef4 100644 --- a/src/modules/request/request.cpp +++ b/src/modules/request/request.cpp @@ -15,14 +15,21 @@ size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* use return totalSize; } -std::string curlWrapper(std::string url, RequestType requestType, std::string data = "") { +std::string curlWrapper(std::string url, RequestType requestType, std::vector headers = {"Content-Type: text/plain"}, std::string data = "") { CURL* curl = curl_easy_init(); std::string response; + + struct curl_slist *list = NULL; + if (curl) { + for (const std::string& header : headers) { + list = curl_slist_append(list, header.c_str()); + } curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_USERAGENT, "kyn-libcurl-agent/1.0"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); if (requestType == RequestType::POST) { curl_easy_setopt(curl, CURLOPT_POST, 1L); @@ -51,17 +58,57 @@ Value modules::request(std::vector args) { } if (args[0].valtype == ValueType::Identifier) { if (args[0].string_val == "get") { - std::string response = curlWrapper(args[1].string_val, RequestType::GET); - if (response == "KYNERR") return Value("Error"); - return Value(response); + if (args.size() == 3) { + if (args[2].valtype == ValueType::List) { + std::vector headers; + for (const Value& value : args[2].list) { + if (value.valtype == ValueType::String) { + headers.push_back(value.string_val); + } else { + error("Expecting second argument of submodule get to be a list of strings"); + return Value("Error"); + } + } + std::string response = curlWrapper(args[1].string_val, RequestType::GET, headers); + if (response == "KYNERR") return Value("Error"); + return Value(response); + } else { + error("Expecting second argument of submodule get to be a list of strings"); + return Value("Error"); + } + } else { + std::string response = curlWrapper(args[1].string_val, RequestType::GET); + if (response == "KYNERR") return Value("Error"); + return Value(response); + } } else if (args[0].string_val == "post") { if (args.size() < 3 || args[2].valtype != ValueType::String) { error("post submodule of request expects a string as 2nd arg"); return Value("Error"); } - std::string response = curlWrapper(args[1].string_val, RequestType::POST, args[2].string_val); - if (response == "KYNERR") return Value("Error"); - return Value(response); + if (args.size() == 4) { + if (args[3].valtype == ValueType::List) { + std::vector headers; + for (const Value& value : args[3].list) { + if (value.valtype == ValueType::String) { + headers.push_back(value.string_val); + } else { + error("Expecting third argument of submodule post to be a list of strings"); + return Value("Error"); + } + } + std::string response = curlWrapper(args[1].string_val, RequestType::POST, headers, args[2].string_val); + if (response == "KYNERR") return Value("Error"); + return Value(response); + } else { + error("Expecting third argument of submodule post to be a list of strings"); + return Value("Error"); + } + } else { + std::string response = curlWrapper(args[1].string_val, RequestType::POST, {"Content-Type: text/plain"}, args[2].string_val); + if (response == "KYNERR") return Value("Error"); + return Value(response); + } } } error("Unknown submodule for request. Only 'get' and 'post' are available."); diff --git a/src/utils/escapes/escapes.cpp b/src/utils/escapes/escapes.cpp new file mode 100644 index 0000000..d4be934 --- /dev/null +++ b/src/utils/escapes/escapes.cpp @@ -0,0 +1,34 @@ +#include "escapes.h" +#include + +std::string interpretEscapeSequences(std::string input) { + std::string output; + for (size_t i = 0; i < input.length(); ++i) { + if (input[i] == '\\' && i + 1 < input.length()) { + char next = input[i + 1]; + switch (next) { + case 'n': output += '\n'; break; + case 't': output += '\t'; break; + case 'r': output += '\r'; break; + case 'b': output += '\b'; break; + case 'f': output += '\f'; break; + case 'a': output += '\a'; break; + case 'v': output += '\v'; break; + case '\\': output += '\\'; break; + case '\'': output += '\''; break; + case '\"': output += '\"'; break; + case '0': output += '\0'; break; + default: + output += '\\'; + output += next; + break; + } + ++i; + } else { + output += input[i]; + } + } + return output; +} + + diff --git a/src/utils/escapes/escapes.h b/src/utils/escapes/escapes.h new file mode 100644 index 0000000..714690e --- /dev/null +++ b/src/utils/escapes/escapes.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +std::string interpretEscapeSequences(std::string input);