Better way to store cookie for commandline application - c++

I want to store cookie for my commandline application, for now I am using a file base approach where in I am using a file to store the data returned by server for future use in my command line application and encrypt the file.
The code goes like this
if ((sHeader.find("Session_ID")) != std::string::npos)
{
int iFound1 = sHeader.find("{");
int iFound2 = sHeader.find("}", iFound1);
int iLen = iFound2 - iFound1 - 1;
std::string sessionID = sHeader.substr((iFound1 + 1), iLen);
if (!sessionIdSet)
{
std::ofstream outputFile;
outputFile.open("session.txt");
if (outputFile.is_open())
{
outputFile << "Session_ID = " << sessionID << "\n" ;
outputFile << "IP = " << cli.getIP() << "\n";
outputFile.close();
sessionIdSet = true;
}
}
}
What can be a better approach to do it,, one i found is using %appdata% but i need some mechanism that is independent of underlying platform.

Related

N_API How to send int value parameters to Napi::CallbackInfo

This My first node.js and n_api. I have been using PHP/APACHI. But I need the c++ library for my web And I decided to using n_api.
The problem is that the value sent by ajax is always 0 in c++.
I don't know what is problem.
ex) I using a vscode.
const testAddon = require('./build/Release/firstaddon.node');
var http = require('http');
var url = require('url');
var fs = require('fs');
const express = require('express');
const app = express();
bodyParser = require('body-parser');
var port = '1080';
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.post('/server', function(req, res){
var responseData = {};
responseData.pID = req.body.pID;
console.log(responseData.pID); <<============= here, value is correct.
const prevInstance = new testAddon.ClassExample(4.3);
var value = prevInstance.getFile(responseData.pID);
console.log(value);
res.json(responseData);
});
If ajax sends 2, console.log(responseData.pID) //2 appears. It is normal.
Below is the classtest.cpp
Napi::Value ClassTest::GetFile(const Napi::CallbackInfo &info)
{
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
using namespace std;
if (info.Length() != 1 || !info[0].IsNumber())
{
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
}
Napi::Number file_id = info[0].As<Napi::Number>();
int num = this->actualClass_->openFile(file_id); <<== here, file id
return Napi::Number::New(info.Env(), num);
}
And ActualClass.cpp Files showing problems.
int ActualClass::openFile(int id)
{
ifstream fin;
cout << id << endl; <<============================ here, always '0'
filename += to_string(id) += ".txt";
fin.open(filename.c_str(), ios_base::in | ios_base::binary);
if (fin.is_open())
{
while (fin.read((char *)&sdo, sizeof(sdo)))
{
cout << setw(20) << sdo.name << ":"
<< setprecision(0) << setw(12) << sdo.width
<< setprecision(2) << setw(6) << sdo.height
<< setprecision(4) << setw(6) << sdo.size << endl;
slist.push_back(sdo);
}
fin.close();
}
else if (!fin.is_open())
{
cerr << "can't open file " << filename << ".\n";
exit(EXIT_FAILURE);
}
return sdo.size;
}
Only files 1 to 4 are prepared.
But, the argument value entering the function is always 0.
Result is "can't open file 0.txt".
How can I solve it?
Napi::Number file_id = info[0].As<Napi::Number>();
I know here it is converted to an int value that can be handled by C++. Is there anything else I don't know?
Thanks for reading.
You need to cast it to the number with the help of the Napi::Number::Int32Value call. (You can also use Napi::Number::Int64Value for bigger numbers)
Try this.
int file_id = info[0].ToNumber().Int32Value();
Also unrelated to the question, but worth mentioning that when you are doing ThrowAsJavaScriptException() the actual C++ code keeps executing, you better return undefined to avoid nasty bugs.
if (info.Length() != 1 || !info[0].IsNumber())
{
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
return Env.Undefined();
}
A more clean way will be to enable the CPP exceptions and just throw the error in that place.
if (info.Length() != 1 || !info[0].IsNumber())
{
throw Napi::TypeError::New(env, "Number expected");
}

Using TimeStamp, to define name of .txt log file

Im working on a system, where i want to incooporate a log in form of a .txt file.
This file should be created everytime the program is started, and will in the future be written to, when i've created all my errorcodes.
To keep these log files unique, i wanted to use timestamp. For getting these stamps i've used the following code:
string GetDateStamp() {
time_t now = time(0);
struct tm tstruct;
char stamp[80];
tstruct = *localtime(&now);
strftime(stamp, sizeof(stamp), "%Y-%m-%d-%X", &tstruct);
return stamp;
}
This function is then called in another function, where i check if the dir for the log is created, if it is not, then it creates it.
void OpenNewLogFile(string& filepath)
{
string datestamp;
string logpath = filepath + "Log\\";
if (_mkdir(logpath.c_str()) == 0)
{
cout << "dir created" << endl;
}
else if(_mkdir(logpath.c_str()) == EEXIST)
{
cout << "dir already exists" << endl;
}
else if (_mkdir(logpath.c_str()) == ENOENT)
{
cout << "path could not be found" << endl;
}
ofstream outfile;
datestamp = GetDateStamp();
string createFile="";
createFile = logpath + datestamp + ".txt";
cout << createFile << endl;
outfile.open(createFile);
}
The code is present in a header file, and called upon from my main cpp.
The output i get now, is the path as follows:
C:...\Log\2020-08-10-15:59:22.txt
but no .txt file appears in my log dir.
Maybe the solution is right in front of me, but sadly i cannot see it.
Hope some of you can help me out :-)

Windows path problems using libssh C++ wrapper

I am having problems with Windows file path separators using the libssh c++ wrapper libsshpp.
Suppose I have following code:
#define SSH_NO_CPP_EXCEPTIONS
#include "libssh/libsshpp.hpp"
#include <iostream>
#pragma comment(lib, "ssh")
int main()
{
ssh::Session session;
int sessionMsg = -1;
std::string host = "myhost.com";
std::string user = "username";
std::string idfile = "%s\\.ssh\\id_ed25519";
std::string hostkeys = "ssh-ed25519";
std::string keyExchange = "curve25519-sha256";
session.setOption(SSH_OPTIONS_HOST, host.c_str());
session.setOption(SSH_OPTIONS_USER, user.c_str());
session.setOption(SSH_OPTIONS_STRICTHOSTKEYCHECK, (long)0);
session.setOption(SSH_OPTIONS_HOSTKEYS, hostkeys.c_str());
session.setOption(SSH_OPTIONS_KEY_EXCHANGE, keyExchange.c_str());
session.setOption(SSH_OPTIONS_ADD_IDENTITY, idfile.c_str());
std::cout << "Trying to connect to " << host << " with user " << user << "...\n";
session.connect();
if (session.isServerKnown() != SSH_SERVER_KNOWN_OK) {
std::cout << "Server unknown.\n";
if (session.writeKnownhost() != SSH_OK) {
std::cout << "Unable to write to known_hosts file.\n";
}
else {
session.connect();
}
}
sessionMsg = session.userauthPublickeyAuto();
std::string err = session.getError();
if (sessionMsg != SSH_AUTH_SUCCESS) {
if (!err.empty()) {
std::cout << err;
}
std::cout << "Auth failed.";
}
else {
std::cout << err.empty() ? session.getIssueBanner() : err;
}
}
In the beginning I had set the idfile value to just id_ed25519 but then libssh complained: Failed to read private key: C:\Users\MyUser/.ssh/id_ed25519 (notice the switching slashes). After changing it to %s\\.ssh\\id_ed25519 it seemed to have had a positive impact on the connection routine, however now I keep falling into the (session.writeKnownhost() != SSH_OK) code part.
Now, I am wondering if this might be due to the same "switching slashes" problem which came up for the private key file path because apparently libssh wants to access C:\Users\MyUser\.ssh\known_hosts but quite possibly the path is set as something like C:\Users\MyUser/.ssh/known_hosts.
My question is: is there a possibility to change the path seperators to windows-style somehow in the session or is there something else I am overseeing or doing wrong here?
I was able to solve the problem adding the SSH_OPTIONS_SSH_DIR option and changing the private key and known_hosts paths (now relative to the ssh directory path):
// note here: %s will be replaced by libssh with the home directory path
std::string sshDir = "%s//.ssh";
std::string idFile = "id_ed25519";
std::string knownHosts = "known_hosts";
// ...
session.setOption(SSH_OPTIONS_USER, user.c_str());
session.setOption(SSH_OPTIONS_SSH_DIR, sshDir.c_str()); // <-- added
// ...

IOS text file is empty after apparently successful writing

IN IOS app, module written in C++ I am writing my data (map of basic strings and integers) to a text file. Using following method:
bool Recognizer::saveMap(const char * s)
{
if(trainingData.model && !trainingData.model.empty()) {
const string filename = string(s);
std::ofstream file(s, ios_base::trunc );
try{
if(! file.is_open())
{
file.open(s);
}
for (map<String,int>::iterator it=trainingData.idMap.begin(); it!=trainingData.idMap.end(); ++it)
{
cout << it->second << " " << it->first << endl;
file << it->first << endl << it->second << endl;
}
file.close();
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
std::streampos fileLength = iosFileSize(s);
cout << "Saved map to: " << filename << " length: " << fileLength << endl;
return true;
}
return false;
}
My contains one entry and console output indicates that two lines: string, string representing number have been written to my file.
Subsequent opening file for reading and reading using getline or using stream operator indicates that file is empty:
bool Recognizer::loadMap(const char * s)
{
std::streampos fileLenght = iosFileSize(s);
std::ifstream file(s, ios::in);
try{
if(file.is_open())
{
string name;
string lineName;
string lineTag;
int tag;
int count = 0;
while(getline(file,name))
{
if(getline(file,lineTag))
{
tag = stoi(lineTag,0,10);
count++;
cout << tag << " " << name << endl;
trainingData.idMap[name]=tag;
trainingData.namesMap[tag]=name;
}
}trainingData.personsCount=count;
file.close();
}
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
cout << "Loaded map from: " << s << " lenght: "<< fileLenght << endl;
return true;
}
I also copied from one of stackoverflow answers method returning file lenght and using it to verify lenghth of the file after write operation:
std::streampos iosFileSize( const char* filePath ){
std::streampos fsize = 0;
std::ifstream file( filePath, std::ios::binary );
fsize = file.tellg();
file.seekg( 0, std::ios::end );
fsize = file.tellg() - fsize;
file.close();
return fsize;
}
The file path passed to saveMap and loadMap seems to be legit. With path that the app could not write to, attempt to write caused exception.
There are no errors returned by write operation but both, attempts to read and iosFileSize() indicate that file is empty.
I am not sure if i need call file.open() and file.close() or file is open and closed automatically when output stream is created and later goes out of scope.
I experimented with those with the same result ( call to file.is_open returns true so the block calling file.open() is skipped.
What am I doing wrong?
I appreciate all responses.
It does not seem like you call file.flush(); anywhere in Recognizer::saveMap() after writing to the file stream. std::ofstream::flush() saves changes you've made to the file. Add file.flush(); between when you make changes to the code and when you close the file. See if that remedies your issue.
I also had the same issue. Using file.flush() everytime after you insert to a file can save your file.
However if you insert something like this, say,
file << "Insert This"; You will need to add file.flush().
But some people have issues, like if you just insert file << "Insert This" << endl; , this works fine. The key point here is that, std::endl calls flush() everytime it is used internally. you can say it is a shortend form of "\n" + flush().
I believe from looking at your code that you are overwriting your data when you open the file in the second program you should be using something like this.
std::fstream fs;
fs.open ("test.txt", ios::app)
instead of doing the ios::in

Http upload with progress info, in C++ (Poco/Boost)

I'm trying to upload a big file to my http server.
And i need to show a upload progress.
How can i get HOW MANY BYTES are sent during the upload?
Need send events to my GUI.
In poco, i don't know where to put the callback.
_session.sendRequest(_request)
_session.receiveResponse(_response)
Any ideas? or links, Thanks!!
This was 'partially' discussed in 08. Ironically I am looking for exactly the same thing.
http://sourceforge.net/mailarchive/message.php?msg_id=20619477
EDIT: 02/14/12
This is not the best, but it works... probably would best to write 1k blocks at a time.
I'd like to see your suggestions.
std::string szMessage;
.... /* fill your szMessage such as with a Form.write() */ ..
CountingOutputStream _cos( _session.sendRequest(_request) )
std::streamsize len = 0;
string::iterator it;
for ( it=szMessage.begin() ; it < szMessage.end(); it++ ) {
len ++;
_cos.put(*it);
if(len %4096 ==0)
cout << "len: " << len << endl;
}
cout << "Chars printed: " << len << endl;
std::istream& rsout = _session.receiveResponse(_response)
std::ostringstream ostr;
StreamCopier::copyStream(rsout, ostr);
// Retrieve response is not necessary if we have the resp code
std::cout << endl; response.write(cout);
std::cout << ostr.str();
int code = response.getStatus();
if (code != nRespCode) {
stringstream s;
s << "HTTP Error(*): " << code;
throw Poco::IOException(s.str());
}