How to read URLs containing question marks in C using microhttpd.h - c

I am trying to parse the URL in C using microhttpd library.
daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT, NULL, NULL, &answer_to_connection, NULL, MHD_OPTION_HTTPS_MEM_KEY, key_pem, MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END);
When I run the function MHD_start_daemon a call back function answer_to_connection is called.
static int answer_to_connection(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
{
printf("URL:%s\n", url);
}
One of the parameters of answer_to_connection is const char *url. The url variable contains the string after https://localhost:port example: for http://128.19.24.123:8888/cars/ferrari the url value will be /cars/ferrari
But in case of http://128.19.24.123:8888/cars?value=ferrari the url is printing only cars.
I want to print cars?value=ferrari. How can I do that?
There is a tutorial on microhttpd library at https://www.gnu.org/software/libmicrohttpd/tutorial.html
But I can't find any solution to this problem there.

CAVEAT EMPTOR: I have not used this library, this answer is based on a quick perusal of the API.
It looks like you can't access the whole original URL, because microhttpd parses it for you. Instead you access the individual query string values using MHD_lookup_connection_value, like this:
value = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "value");
That would return a pointer to the value of the query string argument, or null if not found.
You can also use MHD_get_connection_values to iterate over the query string components. In that case you would call it like this:
num = MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, iterator, cls);
iterator would be a callback function to receive the GET query arguments, one by one.
See also: the Handling requests section in the manual.

Related

NanoPB Callback functions

I am working on a project which includes the use of NanoPB.
Currently I have the situation where in my protofile I have multiple callback fields.
I now must encode and decode these callback fields using my own written callback functions.
My question is:
I have a message defined in the protofile which contains callback fields and non callback fields. If I create an callback encode function, should I make this for a specific field or for the entire message?
My protofile looks like this:
syntax = "proto2";
message stringCallback{
required string name = 1;
required string surname = 2;
required int32 age = 3;
}
An example of encoding a string:
bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
char *str = "Hello world!";
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
If I create an callback encode function, should I make this for a specific field or for the entire message?
Whatever is most suitable for your purpose.
The example callback you show is not particularly useful. If you only wanted to take a string from char*, you could just set (nanopb).type = FT_POINTER on the field.
If your callback actions are the same for multiple fields, by all means, reuse the same function. If there is a difference, make separate functions.

Using C to modify response in VCL

The varnish docs say that we can include C snippets inside a VCL file, like
sub vcl_hash {
C{
int i = /* Some logic to get a number */
}C
}
But now how can I use the value of the integer i to set a response header, or cookie
See varnish.vcc
And the functions:
VRT_SetHdr
VRT_GetHdr
in varnish 4 there is ctx variabl defined for the context (as opposed to sp in varnish 3 ) (source)
example:
sub vcl_hash {
C{
const char *hash = calc_hash(...);
const struct gethdr_s hdr = {
HDR_BERESP,
"\010X-Hash:" // length prefixed string, in octal
};
VRT_SetHdr(ctx, &hdr, hash, vrt_magic_string_end);
}C
}
see here for another example
Why don't you just use VCL?
set resp.http.x-header = header to set any header you wanna set.
I'd encourage you to write a vmod directly, It'll be way more comfortable. You can find a (old but still relevant) guide here: https://info.varnish-software.com/blog/creating-a-vmod-vmod-str

C Curl 400 Bad Request keyword "on"

I wrote a C Program that calls a webservice with cURL. I started my test by hardcoding the address of the webservice with parameters like this :
http://....php?type=adresse&texte=XYZ
It worked fine so I've tried to concatenate a variable for field texte has shown below but it failed and returned me 400 Bad Request.
We checked the content of the request and there is a keyword "on" in front of the webservice address and I don't know where that come from.
on http://....php?type=adresse&texte=xyz&indDebut=0&indFin=1&epsg=900913&format=json"
char* mystrcat( char* dest, char* src )
{
while (*dest) dest++;
while (*dest++ = *src++);
return --dest;
}
recherche = "G0A3B0";
pcbak_adresse(recherche);
const char * pcbak_adresse(const char *details)
{
...
char * lien;
const char * fin_lien;
lien = "http://....php?type=adresse&texte=";
fin_lien = "&indDebut=0&indFin=1&epsg=900913&format=json";
/*Concatenation function*/
mystrcat(details, fin_lien);
mystrcat(lien, details);
/* Set CURL parameters */
curl_easy_setopt(curlHandler, CURLOPT_URL, lien);
curl_easy_setopt(curlHandler, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curlHandler, CURLOPT_WRITEFUNCTION, callback_func);
curl_easy_setopt(curlHandler, CURLOPT_WRITEDATA, &str);
res = curl_easy_perform(curlHandler);
/* Check for errors */
if (res != CURLE_OK)
return curl_easy_strerror(res);
...
}
Thanks for your help!
No matter what mystrcat() is,
mystrcat(lien, details);
is wrong.
If it creates a new string composed by the two inputs, it's not being captured anywhere.
If it tries to write to lien it's undefined behavior. Because you cannot modify string literals which is what lien is.
The same reasoning probably applies to details, but you didn't post details declaration and/or definition.
Do not use anything like strcat() except if you want to do it only once.
To concatenate strings use something like a structure where you store the length of the current string, the size of the target array, and of course the target array. You can then resize the target when you need to, you don't need to find the end of the target string every time (which is what strcat() will do), you also have the advantage of controlling how you append to the string with a lot of detail.
To achieve what you want, you can do this
char lien[256];
int length;
length = snprintf(
lien,
sizeof(lien),
"http://....php?type=adresse&texte=%s&indDebut=0&indFin=1&epsg=900913&format=json",
details
);
if ((length >= sizeof(lien)) || (length == -1))
return error_occurred_here();
Also, returning a static string (which probably is what curl_easy_strerror() returns), and a tentatively dynamic one from the same function is bad design, because,
You can't tell whether it's an error or the JSON returned from the link.
You will need some method to determine whether it's a static string or the one generated in the function in order to free() it.

Parse JSON message manually in C

I need to parse manually, without external libraries, a JSON message coming from a server, in C language.
The message coming from server would be like:
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 72[CR+LF]
}[CR+LF]
or
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 150[CR+LF]
}[CR+LF]
I need the number after STP:. The number is different in each message structure, so I need to get that number from the JSON structure. I can't use external libraries because this code is in an embedded system and exernal code is not allowed.
I tried this following:
int main (){
const char response_message[35] = "{\r\n\"Tmg\":\"R\",\r\n\"STP\":72,\r\n}";
const char needle[8] = "P\":";
char *ret;
ret = strstr(response_message, needle);
printf("The number is: %s\n", ret);
return 0;
}
But obviously, I am getting this result:
The number is: P":72,
}
So I need to only get the number, how can I get this?
Thanks
You can use a hacked solution. Use strstr () to find "STP": then find the following , or } and extract the digits in between.
And that's a hack. Not guaranteed to work. For something that's guaranteed to work, you use a JSON parser.

How to get metadata from Libextractor into a struct

I want to use Libextractor to get keywords/metadata for files.
The basic example for it is -
struct EXTRACTOR_PluginList *plugins
= EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&EXTRACTOR_meta_data_print, stdout);
EXTRACTOR_plugin_remove_all (plugins);
However, this calls the function EXTRACTOR_meta_data_print which "prints" it to "stdout"
I'm looking at a way to get this information to another function - i.e. pass or store this in memory for further working. The documentation was not clear to me. Any help or experience regarding this?
I've tried to install libextractor and failed to get it working (it always returns a NULL plugin pointer upon call to EXTRACTOR_plugin_add_defaults()), so what I will write next is NOT TESTED:
from : http://www.gnu.org/software/libextractor/manual/libextractor.html#Extracting
Function Pointer: int
(*EXTRACTOR_MetaDataProcessor)(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
and
Type of a function that libextractor calls for each meta data item found.
cls
closure (user-defined)
plugin_name
name of the plugin that produced this value;
special values can be used (i.e. '<zlib>' for
zlib being used in the main libextractor library
and yielding meta data);
type
libextractor-type describing the meta data;
format basic
format information about data
data_mime_type
mime-type of data (not of the original file);
can be NULL (if mime-type is not known);
data
actual meta-data found
data_len
number of bytes in data
Return 0 to continue extracting, 1 to abort.
So you would just have to write your own function called whatever you want, and have this declaration be like:
int whateveryouwant(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
{
// Do your stuff here
if(stop)
return 1; // Stops
else
return 0; // Continues
}
and call it via:
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&whateveryouwant,
NULL/* here be dragons */);
Like described in http://www.gnu.org/software/libextractor/manual/libextractor.html#Generalities "3.3 Introduction to the libextractor library"
[here be dragons]: That is a parameter left for the user's use (even if it's redundant to say so). As defined in the doc: "For each meta data item found, GNU libextractor will call the ‘proc’ function, passing ‘proc_cls’ as the first argument to ‘proc’."
Where "the proc function" being the function you added (whateveryouwant() here) and proc_cls being an arbitrary pointer (can be anything) for you to pass data to the function. Like a pointer to stdout in the example, in order to print to stdout. That being said, I suspect that the function writes to a FILE* and not inevitably to stdout; so if you open a file for writing, and pass its "file decriptor" as last EXTRACTOR_extract()'s parameter you would probably end with a file filled with the information you can currently read on your screen. That wouldn't be a proper way to access the information, but if you're looking into a quick and dirty way to test some behavior or some feature; that could do it, until you write a proper function.
Good luck with your code!

Resources