I'm using the Botan library for encryption within Qt. I have it working to where I can encrypt and decrypt from one file to another, but I'm trying to alter it to encrypt from a file to a QDomDocument (encrypted file will just be an XML file), and decrypt back from a QDomDocument to a file.
This is what I have so far for the actual encryption (filePlainText/fileEnc are just txt file paths).
std::ifstream in(filePlainText.c_str(),std::ios::binary);
std::ofstream out(fileEnc.c_str(),std::ios::binary);
Pipe pipe(get_cipher("AES-256/CBC",key,iv,ENCRYPTION),new DataSink_Stream(out));
pipe.start_msg();
in >> pipe;
pipe.end_msg();
out.flush();
out.close();
in.close();
DataSink_Stream accepts a ofsteam or ostream. So I figure I need to use an ostream when decrypting from file to variable. But how can I store the contents of the ostream into something I can feed into a QDomDocument?
Then for encrypting back into a file, use an istream into an ofstream, but how can I take feed the QDomDocument content into an istream?
QDomDocument can be read from and written to a QByteArray and you can read from / write to a std::string with std::ostringstream / std::istringstream.
So if you combine these, you would have something like:
// before the encoding
const QByteArray & buffer = document.toByteArray(-1);
std::istringstream in(std::string(buffer.data(), buffer.size()));
... // encoding
And for the decoding part:
// before the decoding
std::ostringstream out;
... // decoding
// after the decoding
const std::string & buffer = out.str();
document.setContent(QByteArray(buffer.c_str(), buffer.size()));
Related
I have a QString containing a special character (µ) encoded in UTF-8:
QString data = "197,45 \xc2\xb5m";
I need to send that string via a Linux pipe to another program. I tried to convert the string into something like this:
char msg[15];
for(int i = 0; i < data.length(); i++) {
msg[i] = data.toUtf8()[i];
}
msg[data.length()] = '\0';
I send msg to the pipe, but I only receive "197,45 µ", not "197,45 µm". I try to read the data on the read end with:
char data[15];
read(fd, data, nbytes);
I don't know much about character/string conversion, so I would be glad if you could explain how I should approach this problem. Thank you.
What you are doing seems to be mainly "serializing the data" into a binary pipe, so an option that could make sense is to use a QDataStream which is designed for that purpose.
Something like:
QByteArray buffer;
QDataStream stream(&buffer, QIODevice::WriteOnly);
QString data = "197,45 \xc2\xb5m";
stream << data;
sendToPipe(buffer.constData(), buffer.size());
And the similar on the other side, using operator>> to read the data from the stream.
QByteArray buffer(dataPtr, size);
QDataStream stream(buffer);
QString data;
stream >> data;
It is conceptually wrong to store UTF-8 encoded bytes in a QString. Use QByteArray for that, OR use QString::fromUtf8() to convert your UTF-8 string literals to a proper QString. To go back, use the qUtf8Printable macro or QString::toUtf8 to get a QByteArray.
I'm new to C++, I have an image named "test.jpg", i convert it to base64 and decode it again like this:
std::ifstream inputFile;
inputFile.open("test.jpg",std::ios::binary);
std::filebuf* pbuf = inputFile.rdbuf();
inputFile.seekg (0, ios::end);
int length = inputFile.tellg();
// allocate memory to contain file data
char* buffer=new char[length];
// get file data
pbuf->sgetn (buffer,length);
inputFile.close();
CBase64 base64;
string encodedData = base64.base64_encode((unsigned char*)buffer,length);
delete[] buffer;
string decodedData = base64.base64_decode(encodedData);
ofstream outPutFile;
outPutFile.open("test2.jpg",ios::binary | ios::out);
outPutFile.write(decodedData.c_str(), decodedData.length());
outPutFile.close();
the "test2.jpg" has exact same size as "test.jpg"(the original file) but, i can't open it.
i couldn't find what is the problem.
i got it working. i just replaced:
outPutFile.open("test2.jpg",ios::binary | ios::out);
with
outPutFile.open("test2.jpg", ios_base::out | ios_base::binary);
std::string path = "file.txt";
std::string cfgString = "data";
std::ofstream output(path.c_str(), ios_base::out | std::ios::binary);
if (output.is_open()) {
output.write(cfgString.data(), cfgString.length());
}
output.close();
Apparently, there is no superficial problem with your file writing logic even though there are some irregularities. The biggest problem is in your main logic.
The program seems to be simple program of copying a file. What you are doing is reading a file, converting its data to base64 string and then again decoding the data to std::string. Now one small problem. Conversion of base64 string cannot be successfully done into a null terminated ANSI string for obvious reasons that any 0 in decoded binary data will terminate the string prematurely. Secondly you are opening a file in binary mode to write but trying to write std::string in the file. But that doesn't matter as you data has already been corrupted in your previous operation.
To solve this, you can simply use file copying example as this or make sure you write only binary data with care to your output file which means read in binary from input file and write to output file the same buffer. No base64 encoding decoding is required.
it looks like you forgot to write
inputFile.seekg (0, ios::beg);
after getting file length. it means you try to read from the end of the file instead of its beginning.
I have an IStream which I know it contains a PNG file, but I can't write its content into a file like normal I/O stream, I don't know if I am doing something wrong or I should do a different thing for writing IStream into file.
IStream *imageStream;
std::wstring imageName;
packager.ReadPackage(imageStream, &imageName);
std::ofstream test("mypic.png");
test<< imageStream;
Based on the IStream reference you gave here is some untested code that should do roughly what you want:
void output_image(IStream* imageStream, const std::string& file_name)
{
std::ofstream ofs(file_name, std::ios::binary); // binary mode!!
char buffer[1024]; // temporary transfer buffer
ULONG pcbRead; // number of bytes actually read
// keep going as long as read was successful and we have data to write
while(imageStream->Read(buffer, sizeof(buffer), &pcbRead) == S_OK && pcbRead > 0)
{
ofs.write(buffer, pcbRead);
}
ofs.close();
}
I receive a binary file via POST in a C++ CGI script and I'm using the Cgicc library to get its contents like so:
std::ofstream myfile;
myfile.open ("file.out", std::ios::in | std::ios::binary);
try
{
cgicc::Cgicc cgi;
cgicc::const_file_iterator file = cgi.getFile("bitmap");
if(file != cgi.getFiles().end())
{
file->writeToStream(myfile);
}
}
catch(std::exception &exception)
{
std::cout << exception.what();
}
The result is a binary file containing the bytes.
Now, because each byte should represent one pixel of an 8 bit bitmap file, I want to construct the entire bitmap file. In order to achieve this, I think I can use the easyBMP library, but since I need to create the image pixel by pixel, I need to somehow iterate over the received bytes. Does anyone know how this can be achieved? Can I get an iterator somehow to an std::ostream / std::ostrstream / std::ostringstream?
std::ostringstream stream;
file->writeToStream(stream);
//foreach byte in stream do { ... }
If you use std::ostringstream you can get std::string from it, using std::ostringstream::str function http://cplusplus.com/reference/iostream/ostringstream/str/ . Also, you can open your file and read it...
I am programming a face detection algorithm. In my code I'm parsing an XML file (in a recursion way, very inefficient takes my about 4 minutes to parse the whole XML file). I'd like to save the XML content using Iosteam binary to a file. I'm using a struct in C++ in order to use the raw data.
My goal is to parse the XML only if the raw data file is not exist.
The method work like this:
If the raw data file is not exist, parse the XML file and save the data to a file.
If the raw data file exist, read the raw data from the file
My problem is: whenever I open the raw data file and read from it. I get to read only small amount of byte from the file, I don't know how much, but in a certain point I receive only 0x00 data on my buffer.
My guess: I believe this has to do with the OS buffer, Which has a certain amount of buffer for read and write operations. I might be wrong about this. Though I'm not sure which one from the operations doesn't work well, it's either the write or read.
I was thinking to write / read the raw data char by char or line by line. In the other hand the file doesn't contain a text, which means that I can't read line by line or char by char.
The raw data size is
size_t datasize = DataSize(); == 196876 (Byte)
Which is retrieve in this function
/* Get the upper bound for predefined cascade size */
size_t CCacadeInterpreter::DataSize()
{
// this is an upper boundary for the whole hidden cascade size
size_t datasize = sizeof(HaarClassifierCascade) * TOTAL_CASCADE+
sizeof(HaarStageClassifier)*TOTAL_STAGES +
sizeof(HaarClassifier) * TOTAL_CLASSIFIERS +
sizeof(void*)*(TOTAL_CASCADE+TOTAL_STAGES+TOTAL_CLASSIFIERS);
return datasize;
}
The method work like this
BYTE * CCacadeInterpreter::Interpreter()
{
printf("|Phase - Load cascade from memory | CCacadeInterpreter::Interpreter | \n");
size_t datasize = DataSize();
// Create a memory structure
nextFreeSpace = pStartMemoryLocation = new BYTE [datasize];
memset(nextFreeSpace,0x00,datasize);
// Try to open a predefined cascade file on the current folder (instead of parsing the file again)
fstream stream;
stream.open(cascadeSavePath); // ...try existing file
if (stream.is_open())
{
stream.seekg(0,ios::beg);
stream.read((char*)pStartMemoryLocation , datasize); // **ream from file**
stream.close();
printf("|Load cascade from saved memory location | CCacadeInterpreter::Interpreter | \n");
printf("Completed\n\n");
stream.close();
return pStartMemoryLocation;
}
// Open the cascade file and parse the cascade xml file
std::fstream cascadeFile;
cascadeFile.open(cascadeDestanationPath, std::fstream::in); // open the file with read only attributes
if (!cascadeFile.is_open())
{
printf("Error: couldn't open cascade XML file\n");
delete pStartMemoryLocation;
return NULL;
}
// Read the file XML file , line by line
string buffer, str;
getline(cascadeFile,str);
while(cascadeFile)
{
buffer+=str;
getline(cascadeFile,str);
}
cascadeFile.close();
split(buffer, '<',m_tokens);
// Parsing begins
pHaarClassifierCascade = (HaarClassifierCascade*)nextFreeSpace;
nextFreeSpace += sizeof(HaarClassifierCascade);
pHaarClassifierCascade->count=0;
pHaarClassifierCascade->orig_window_size_height=20;
pHaarClassifierCascade->orig_window_size_width=20;
m_deptInTree=0;
m_numOfStage = 0;
m_numOfTotalClassifiers=0;
while (m_tokens.size())
{
Parsing();
}
// Save the current cascade into a file
SaveBlockToMemory(pStartMemoryLocation,datasize);
printf("\nCompleted\n\n");
return pStartMemoryLocation;
}
bool CCacadeInterpreter::SaveBlockToMemory(BYTE * pStartMemoryLocation,size_t dataSize)
{
fstream stream;
if (stream.is_open() )
stream.close();
stream.open(cascadeSavePath); // ...try existing file
if (!stream.is_open()) // ...else, create new file...
stream.open(cascadeSavePath, ios_base::in | ios_base::out | ios_base::trunc);
stream.seekg(0,ios::beg);
stream.write((char*)pStartMemoryLocation,dataSize);
stream.close();
return true;
}
Try using the Boost IOstreams library.
It has an easy to use wrrapers for file handling