How to use openssl to base 64 decode? - c++

I am developing in C++ using Boost.Asio. I want to be able to base64 decode data and since Boost.Asio links to openssl I want to use it's functions to do so and not add an extra dependency(eg crypto++). I have found this code here that shows how to do it. (change int finalLen = BIO_read(bmem, (void*)pOut, outLen); to inLen )
I don't know if it works. I just pass to it some test data that I verify with an online decoder found here(2) (select decode safely as text and count the symbols). The test string I use is this one: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" (without the ""). Both the online decoder and a quick crypto++ implementation return 23 chars. But the code I mentioned above using openssl returns 0. Am I doing something wrong? Is openssl suitable for base64 decoding?
Please provide me a solution (if one exists). Thanks for you time.

pff sorry my mistake. I forgot to allocate memory for pOut. The code seems to work now.

Related

Get raw buffer for in-memory dataset in GDAL C++ API

I have generated a GeoTiff dataset in-memory using GDALTranslate() with a /vsimem/ filepath. I need access to the buffer for the actual GeoTiff file to put it in a stream for an external API. My understanding is that this should be possible with VSIGetMemFileBuffer(), however I can't seem to get this to return anything other than nullptr.
My code is essentially as follows:
//^^ GDALDataset* srcDataset created somewhere up here ^^
//psOptions struct has "-b 4" and "-of GTiff" settings.
const char* filep = "/vsimem/foo.tif";
GDALDataset* gtiffData = GDALTranslate(filep, srcDataset, psOptions, nullptr);
vsi_l_offset size = 0;
GByte* buf = VSIGetMemFileBuffer(filep, &size, true); //<-- returns nullptr
gtiffData seems to be a real dataset on inspection, it has all the appropriate properties (number of bands, raster size, etc). When I provide a real filesystem location to GDALTranslate() rather than the /vsimem/ path and load it up in QGIS it renders correctly too.
Looking a the source for VSIGetMemFileBuffer(), this should really only be returning nullptr if the file can't be found. This suggests i'm using it incorrectly. Does anyone know what the correct usage is?
Bonus points: Is there a better way to do this (stream the file out)?
Thanks!
I don't know anything about the C++ API. But in Python, the snippet below is what I sometimes use to get the contents of an in-mem file. In my case mainly VRT's but it shouldn't be any different for other formats.
But as said, I don't know if the VSI-api translate 1-on-1 to C++.
from osgeo import gdal
filep = "/vsimem/foo.tif"
# get the file size
stat = gdal.VSIStatL(filep, gdal.VSI_STAT_SIZE_FLAG)
# open file
vsifile = gdal.VSIFOpenL(filep, 'r')
# read entire contents
vsimem_content = gdal.VSIFReadL(1, stat.size, vsifile)
In the case of a VRT the content would be text, shown with something like print(vsimem_content.decode()). For a tiff it would of course be binary data.
I came back to this after putting in a workaround, and upon swapping things back over it seems to work fine. #mmomtchev suggested looking at the CPL_DEBUG output, which showed nothing unusual (and was silent during the actual VSIGetMemFileBuffer call).
In particular, for other reasons I had to put a GDALWarp call in between calling GDALTranslate and accessing the buffer, and it seems that this is what makes the difference. My guess is that GDALWarp is calling VSIFOpenL internally - although I can't find this in the source - and this does some kind of initialisation for VSIGetMemFileBuffer. Something to try for anyone else who encounters this.

Websocket server handshake response

I am trying to set up websocket communication. I can open the websocket, but I can't figure out how to get the handshake response correct. According to several sites:
"Additionally, the server can decide on extension/subprotocol requests here; see Miscellaneous for details. The Sec-WebSocket-Accept part is interesting. The server must derive it from the Sec-WebSocket-Key that the client sent. To get it, concatenate the client's Sec-WebSocket-Key and "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" together (it's a "magic string"), take the SHA-1 hash of the result, and return the base64 encoding of the hash...So if the Key was "dGhlIHNhbXBsZSBub25jZQ==", the Accept will be "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=".
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
But I cannot seem to reproduce these results at all. I've tried many encoders/decoders, and tried to find alternate interpretations of the instructions above, but none of them work. I also have not found any examples of code doing this.
Input: dGhlIHNhbXBsZSBub25jZQ==
Magic string(never changes):258EAFA5-E914-47DA-95CA-C5AB0DC85B11
Output: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
The only way I have ever gotten the correct answer is through this site. It seems to get the SHA1 encoding wrong but the overall 64 bit answer is correct? Anyway, help would be appreciated.
Pseudocode:
sec_websocket_key = "dGhlIHNhbXBsZSBub25jZQ=="
magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
return base64(sha1(sec_websocket_key .. magic_string))
Here's a real implementation that'll work in a UNIX shell, assuming you have OpenSSL installed:
SEC_WEBSOCKET_KEY="dGhlIHNhbXBsZSBub25jZQ=="
MAGIC_STRING="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
echo -n "$SEC_WEBSOCKET_KEY$MAGIC_STRING" \
| openssl sha1 -binary \
| openssl base64
Make sure that you're using SHA1 -- not SHA256 -- and that the implementation you're using returns raw data, not a hex digest. The output of the hash function should be 160 bits (20 bytes) long.
Also, keep in mind that, even though Sec-WebSocket-Key looks like Base64 data, you don't need to decode it. It's included in the hash as-is.

Can I decode € (euro sign) as a char and not as a wstring/wchar?

Let's try explain my problem. I have to receive a message from a server (programmed in delphi) and do some things with that message in the client side (which is the side I programm, in c++).
Let's say that the message is: "Hello €" that means that I have to work with std::wstring as €(euro sign) needs 2 bytes instead of 1 byte, so knowing that I have made all my work with wstrings and if I set the message it works fine. Now, I have to receive the real one from the server, and here comes the problem.
The person on the server side is sending that message as a string. He uses a EncodeString() function in delphi and he says that he is not gonna change it. So my question is: If I Decode that string into a string in c++, and then I convert it into a wstring, will it work? Or will I have problems and have other message on my string var instead of "Hello €".
If yes, if I can receive that string with no problem, then I have another problem. The function that I have to use to decode the string is void DecodeString(char *buffer, int length);
so normally if you receive a text, you do something like:
char Text[255];
DescodeString(Text, length); // length is a number decoded before
So... can I decode it with no problem and have in Text the "Hello €" message? with that I'll just need to convert it and get the wstring.
Thank you
EDIT:
I'll add another example. If i know that the server is going to send me always a text of length 30 max, in the server they do something like:
EncodeByte(lengthText);
EncodeString(text)
and in the client you do:
int length;
char myText[30];
DecodeByte(length);
DecodeString(myText,length);
and then, you can work with myText as a string lately.
Hope that helps a little more. I'm sorry for not having more information but I'm new in that work and I don't know much more about the server.
EDIT 2
Trying to summarize... The thing is that I have to receive a message and do something with it, with the tool I said I have to decode it. So as de DecodeString() needs a char and I need a wstring, I just need a way to get the data received by the server, decode it with decodeString() and get it into a wstring, but I don't really know if its possible, and if it is, I'm not sure about how to do it and what type of vars use to get it
EDIT 3
Finally! I know what code pages are using. Seems that the client uses the ANSI ones and that the server doesn't, so.. I'll have to tell to the person who does that part to change it to the ANSI ones. Thanks everybody for helping me with my big big ignorance about the existence of code pages.
Since you're using wstring, I guess that you are on Windows (wstring isn't popular on *nix).
If so, you need the Delphi app to send you UTF-16, which you can use in the wstring constructor. Example:
char* input = "\x0ac\x020"; // UTF-16 encoding for euro sign
wchar_t* input2 = reinterpret_cast<wchar_t*>(input);
wstring ws(input2);
If you're Linux/Mac, etc, you need to receive UTF-32.
This method is far from perfect though. There can be pitfalls and edge cases for unicodes beyond 0xffff (chinese, etc). Supporting that probably requires a PhD.

Reading contents of a qcow2 image using `bdrv_pread(..)` or alternatives

I wanted to read contents off a .qcow2 image using bdrv_pread(...) functions in QEMU.
Say, the full path of my image is /path/to/myimage.qcow2, I want to be able to read 'n' bytes of data off of this image at a particular offset. Now the bdrv_pread functions takes these arguments 'BlockDriverState *bs, int64_t offset, void *buf, int count1', how exactly do I initialize the BlockDriverState (device?) from the path of the image. All other parameters other than BlockDriverState are clear to me.
Thanks.
If your goal is to access a qcow2 file from your own program I would recommend not trying to use the QEMU functions. These are going to have a lot of state associated with QEMU that is not necessary if all you want to do is read the contents of the qcow2 file. Instead you could look at the qcow2 specification or if you want to work at one higher level of abstraction you could look at the libguestfs library, which states that it has an API for accessing the supported VM disk formats (although I have never used it myself). There is some example code here that can help you get started.

TinyXML: how to parse a file pointer

I'm trying to connect the output of popen, a file pointer, to the input of TinyXML.
According to the main page, the best way to do it is using the parse method:
C style input:
* based on FILE*
* the Parse() and LoadFile() methods
I believe I need to use the TIXML_USE_STL to get to this. How do I go about finding examples and import it?
A reply since deleted pointed me in the right direction on the docs
http://www.grinninglizard.com/tinyxmldocs/index.html
Thanks.
Now, i just need to figure out how to link and import it.
I'm not hugely familiar with TinyXML, but does LoadFile() not work in its overloaded version which takes a FILE *?
http://www.grinninglizard.com/tinyxmldocs/classTiXmlDocument.html#a12
EDIT: Ah, the problem is that TinyXML doesn't support reading from a stream (see the link above). Your only choice then is to read the stream manually into a buffer and pass it to TinyXML's Parse().
You can read the file data into some buffer (say SomeCharBuffer), append null terminator to it and do
TiXmlDocument doc;
doc.Parse(SomeCharBuffer);