Why won't MFC::CHttpFile 'PUT' for me? - c++

My code talks to a little Java application provided by a vendor. This Java app sets up a web server at localhost:57000 which is used to control the state of 'the machine'. For the purpose of this question, I need to change the state of 'the machine' from 'off' to 'on'. To make this happen I'm supposed to HTTP PUT the following string to 'the machine' at http://localhost:57000/settings.xml:
<settings><machine_state><status>on</status></machine_state></settings>
This Curl command works perfectly:
curl -X PUT -H "Content-Type:application/xml" -d #settings.xml http://localhost:57000/settings.xml"
where the local file 'settings.xml' has the above xml string in it.
I want to do what Curl is doing with MFC's WININET classes. The following code should IMHO do exactly the same thing that curl does. Sadly, although the localhost web server returns a code 200 it ignores my xml string. What little thing am I missing?
int MyHttp::HttpPutThread() NOTHROW
{
try {
m_xml = "<settings><machine_state><status>on</status></machine_state></settings>";
m_url = "settings.xml"
CInternetSession session;
SetSessionOptions(session);
CString server = "localhost:57920";
boost::scoped_ptr<CHttpConnection> phttp(session.GetHttpConnection(server));
LPCTSTR accept = 0;//"text/xml";
boost::scoped_ptr<CHttpFile> phttpfile(phttp->OpenRequest(
"PUT", //verb
"settings.xml", //object name
0, //referer
1, //context
&accept, // accept types
0, //version
INTERNET_FLAG_EXISTING_CONNECT));
CString header = "Content-Type:application/xml\r\n";
if(phttpfile->SendRequest(header,(LPVOID)m_xml.GetBuffer(), m_xml.GetLength()))
{ // LOG_DEBUG (Same as TRACE) output are shown in comment
DWORD code(0);
phttpfile->QueryInfoStatusCode(code);
LOG_DEBUG("HttpPutThread result code: %d", code); // '200'
CString object = phttpfile->GetObject();
LOG_DEBUG("object: %s", object); // 'settings.xml'
CString statustxt;
phttpfile->QueryInfo(HTTP_QUERY_STATUS_TEXT,statustxt);
LOG_DEBUG("status text:%s", statustxt); // 'HTTP/1.0 200 OK'
CString rawheaders;
phttpfile->QueryInfo(HTTP_QUERY_RAW_HEADERS,rawheaders);
LOG_DEBUG("raw headers:%s", rawheaders); // http://localhost:57000/settings.xml
LOG_DEBUG("File url:%s",phttpfile->GetFileURL());
LOG_DEBUG("Verb:%s", phttpfile->GetVerb()); // 'PUT'
} else
{
//This does not happen
LOG_DEBUG("PUT failed in AffHttp::HttpPutThread");
}
} catch(CInternetException* pe)
{
//No exceptions are thrown
LOG_DEBUG("Exception HttpPutThread:%d", pe->m_dwError);
pe->Delete();
}
return 0;
}
Thanks in advance.

I wound up replacing the MFC classes with my own low level socket code to send exactly the same text in exactly the same order as Curl did. It seemed like the little embedded 'jetty' Java server just objected to one of the headers generated by the MFC classes.

Related

Cannot set Scanner Capability because L_TwainStartCapsNeg returns error -84

I'm trying to use the Leadtools API version 21 for automatically scanning some documents and here is a sudo code of what I have done (it runs in a secondary thread and the unlock has been done in the main thread):
void CheckRetCode(int rc)
{
if (SUCCESS != rc)
{
L_TCHAR errMsg[1024];
memset(errMsg, 0, sizeof(errMsg));
L_GetFriendlyErrorMessage(rc, errMsg, 1024, L_FALSE);
throw TLeadException(errMsg, rc);
}
}
void OnThreadExecute(void)
{
HTWAINSESSION hSession = nullptr;
APPLICATIONDATA appData;
L_INT nRet;
L_TCHAR pszTwnSourceName[1024];
LTWAINSOURCE sInfo;
memset(&appData, 0, sizeof(APPLICATIONDATA));
appData.uStructSize = sizeof(APPLICATIONDATA);
appData.hWnd = hWnd;// hWnd is valid handle of my main window
appData.uLanguage = TWLG_ENGLISH_USA;
appData.uCountry = TWCY_USA;
wcscpy(appData.szManufacturerName, L"MyCompanyName");
wcscpy(appData.szAppProductFamily, L"MyProductName");
wcscpy(appData.szAppName, appData.szAppProductFamily);
wcscpy(appData.szVersionInfo, L"Version 0.1.0.1");
nRet = L_TwainInitSession2(&hSession, &appData, LTWAIN_INIT_MULTI_THREADED);
CheckRetCode(nRet);// the exception gets catched elsewhere but no error reported here
memset(pszTwnSourceName, 0, sizeof(pszTwnSourceName));
wcscpy(pszTwnSourceName, L"EPSON Artisan837/PX830"); // the name of the scanner is verifyed
sInfo.uStructSize = sizeof(LTWAINSOURCE);
sInfo.pszTwainSourceName = pszTwnSourceName;
CheckRetCode(L_TwainSelectSource(hSession, &sInfo)); // No error reported here
CheckRetCode(L_TwainStartCapsNeg(hSession)); // in here I get the return value -84 which is reported as "TWAIN DS or DSM reported error, app shouldn't (no need for your app to report the error)."
// the rest of the code but we cannot get there since above code reports error
}
Can anyone tell me what I'm doing wrong? Is there a step that I'm missing here?
EditThe function L_TwainSelectSource() make no effort to make sure the supplied source is valid and does not even return an error. As result, if you set the selected source to a garbage name, it will act as if it accepted it. From that point on if you try to Get/Set anything or try to acquire an image, every function returns -84.
Thank you
Sam
To test your code, I put the main window’s handle in a global variable:
globalhWnd = hWnd;
And modified your function to use that handle like this:
void OnThreadExecute(void *)
{
...
appData.hWnd = globalhWnd; // hWnd is valid handle of my main window
...
}
Then created a thread for it from the main program like this:
globalhWnd = hWnd;
_beginthread(OnThreadExecute, 0, 0);
I tried this with 5 different Twain sources: 2 virtual and 3 physical scanners (one of them an old Epson). All 5 drivers returned SUCCESS when calling L_TwainStartCapsNeg() from within the thread.
Two possibilities come to mind:
The problem might be caused by something else in your code other than the thread function.
Or the problem could be specific to your Twain driver.
To rule out the first possibility, I suggest creating a small test project that only creates a similar thread and does nothing else and trying it with different scanners. If it causes the same problem with all scanners, send that test project (not your full application) to support#leadtools.com and our support engineers with test it for you.
If the problem only happens with a specific Twain driver, try contacting the scanner’s vendor to see if they have an updated driver.

libmodsecurity as a library to process my own web requests

Is it possible to use libmodsecurity as a library and process requests on my own? I was messing with the examples in the repo ModSecurity examples, but I cant figure out how to make it take my request. I tried with simple_example_using_c.c but with no success. Is anyone have idea if this is possible?
#include <stdio.h>
#include <stdlib.h>
#include <modsecurity/modsecurity.h>
#include <modsecurity/rules_set.h>
char rulez[] ="basic_rules.conf";
const char *request = "" \
"GET /?test=test HTTP/\n" \
"Host: localhost:9999\n" \
"Content-Length: 27\n" \
"Content-Type: application/x-www-form-urlencoded\n";
int main(){
ModSecurity *modsec;
RulesSet *setRulez;
Transaction *transakcyja;
const char *error;
modsec = msc_init();
printf(msc_who_am_i(modsec));
msc_set_connector_info(modsec, "ModSecurity simple API");
setRulez = msc_create_rules_set();
int rulz = msc_rules_add_file(setRulez, rulez, &error);
if(rulz == -1){
fprintf(stderr, "huston rulez problem \n");
fprintf(stderr, "%s\n", error);
return -1;
}
msc_rules_dump(setRulez);
transakcyja = msc_new_transaction(modsec, setRulez, NULL);
if(transakcyja == NULL){
fprintf(stderr, "Init bad");
return -1;
}
msc_process_connection(transakcyja, "127.0.0.1", 9998, "127.0.0.1", 9999);
msc_process_uri(transakcyja, "http://127.0.0.1:9999/?k=test&test=test", "GET", "1.1");
msc_process_request_body(transakcyja);
msc_process_response_headers(transakcyja, 200, "HTTP 1.3");
msc_process_response_body(transakcyja);
msc_process_logging(transakcyja);
msc_rules_cleanup(setRulez);
msc_cleanup(modsec);
return 0;
}
Edit: I know something more now but, anyone know how to pass request to transaction? I know there is addRequestHeader() but it takes one header at the time, I can't really figure it out.
I think you have to understand how ModSecurity works.
There are five phases of all transaction:
parse request headers
parse request body
parse response headers
parse response body
make logs (and check transaction variables, eg. anomaly scores (in case of CRS))
(And plus the phase 0: process the connection itself.)
In the examples you can see couple of functions for each phases.
This is a common HTTP request:
POST /set.php HTTP/1.1
Host: foobar.com
User-Agent: something
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
a=1&b=2
Now if you already create a transaction object, you have to add the data of phases to that.
First see the status line, and add the necessary parts - consider your application already has the information, like client IP (std::string cip), port (int cport), and server IP (std::string dip), port (int dport). You also have the URI (std::string uri), method (std::string method) and the version of protocoll (std::string vers). You also need an object with type modsecurity::ModSecurityIntervention *it.
// phase 0
trans->processConnection(cip.c_str(), cport, dip.c_str(), dport);
trans->processURI(uri.c_str(), method.c_str(), vers.c_str());
trans->intervention(it);
Now you have to check the it variable, eg. it.status. For more information, check the source.
Now consider you have a variable (a list) which contains the parsed headers. Now you have to add these headers one by one to the transaction:
for(your_iterator it=headerType.begin(); it != headerType.end(); ++it) {
const std::string key = it->first.as<std::string>(); // key
const std::string val = it->second.as<std::string>(); // val
trans->addRequestHeader(key, val);
}
Now you can process the headers and check the results. Note, that if you process a phase, the engine evaluates all rules, where the phase values is relevant: 1, 2, 3, 4 or 5.
// phase 1
trans->processRequestHeaders();
trans->intervention(it);
In next steps, you have to add the request body and process it, then get the response headers and body (from the upstream), and repeat the steps above...
Hope now you can see how does it works.
I've made a utility, which runs the CRS test cases on libmodecurity3 while it uses CRS rules. The tool available here: ftwrunner.
Hope this helped.

How to make Chrome Dev Tools show the JavaScript source

I slightly modified the hello-world.cc sample, importing some code from d8. Then, using websocketpp and asio, I added a WebSocket Server to the program.
Also, I used V8 inspector from an embedder standpoint to add a simple implementation for the inspector protocol back-end.
Now, when I start my program and then use Chrome to navigate to chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9002, I receive the following messages from the CDT:
{"id":1,"method":"Profiler.enable"}
for witch the response is:
{"id":1,"result":{}}
then
{"id":2,"method":"Runtime.enable"}
for this one a notification and a response are sent:
{"method":"Runtime.executionContextCreated",
"params":{"context":{"id":1,"origin":"","name":"MyApplication"}}}
{"id":2,"result":{}}
then:
{"id":3,"method":"Debugger.enable"}
again, a notification and a response sent back to the front-end:
{"method":"Debugger.scriptParsed",
"params":{
"scriptId":"4","url":"func_add.js","startLine":0,
"startColumn":0,"endLine":0,"endColumn":35,
"executionContextId":1,"hash":"365568ee6245be1376631dbf20e7de9d42c9adf1",
"isLiveEdit":false,"sourceMapURL":"","hasSourceURL":false,
"isModule":false,"length":35
}
}
{"id":3,"result":{"debuggerId":"(DC239109305DBEF825A955524584A826)"}}
For the moment, I will not add to the question the other messages received from the front-end, and the responses sent.
The last exchange is:
{"id":7,"method":"Runtime.runIfWaitingForDebugger"}
{"id":7,"result":{}}
My problem: in CDT, the Sources tab is empty (and therefore, I can't try to put a breakpoint).
My code to inject JS in V8:
const char * pszScript = "function add( a, b) { return a+b; }";
v8::Local<v8::String> source =
v8::String::NewFromUtf8(isolate, pszScript, v8::NewStringType::kNormal).ToLocalChecked();
v8::Local<v8::String> name =
v8::String::NewFromUtf8(isolate, "func_add.js", v8::NewStringType::kNormal).ToLocalChecked();
ExecuteString( isolate, source, name );
My ExecuteString function:
bool ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source,
v8::Local<v8::Value> name) {
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Context::Scope context_scope(context);
v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
v8::MaybeLocal<v8::Value> maybe_result;
bool success = true;
v8::ScriptOrigin origin(name);
v8::ScriptCompiler::Source script_source(source, origin);
v8::MaybeLocal<v8::Script> maybe_script;
maybe_script = v8::ScriptCompiler::Compile(context, &script_source);
v8::Local<v8::Script> script;
if (!maybe_script.ToLocal(&script)) {
// Print errors that happened during compilation.
ReportException(isolate, &try_catch);
return false;
}
maybe_result = script->Run(context);
v8::Local<v8::Value> result;
if (!maybe_result.ToLocal(&result)) {
// Print errors that happened during execution.
ReportException(isolate, &try_catch);
return false;
}
if (!result->IsUndefined()) {
// If all went well and the result wasn't undefined then print
// the returned value.
v8::String::Utf8Value str(isolate, result);
fwrite(*str, sizeof(**str), str.length(), stdout);
printf("\n");
} else {
printf("undefined\n");
}
return success;
}
I think I am doing something wrong, as I should be able to see some func_add.js source in CDT with the content function add( a, b) { return a+b; }
W/o checking the source code at all, I remember having some bad times at this exact use case.
try adding to your source parameter a protocol.
CDT needs any protocol file, http, https to create the sources tree.
It will also use this uri to request for maps, or any other source code related thing.
v8::Local<v8::String> name =
v8::String::NewFromUtf8(isolate, "file://func_add.js", v8::NewStringType::kNormal).ToLocalChecked();
ExecuteString( isolate, source, name );
It also happens from time to time, that depending on your v8 implementation, official chrome is not able to show source code, debug, etc.
Try using chrome canary if this is the case.
The protocol implementation is as I described in your referenced post.
Hope this helps.
In your code, I don't see where you discover your Context to the Inspector object, but something like this must happen somewhere in your code:
inspector_->contextCreated(
v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView(
reinterpret_cast<const uint8_t *>("ABCD"), 4)));
I do this right after creating the Context and setting its global object.
CDT will query script contents with a message of the form:
{"id":8,"method":"Debugger.getScriptSource","params":{"scriptId":"7"}}
While the implementation is very simple, there are many reasons why your code simply will not show up.
Hope that helps.

c++ - WebSocketPP multiple clients

I have problem with WebSocketPP Server. I want it to handle multiple clients.
Here is my OnOpen method:
void Server::onOpen(
Server* srv,
WSServer* ws,
websocketpp::connection_hdl& hdl)
{
ServerPlayerTracker con;
con.con = &hdl;
con.protocolVersion = 0;
con.verified = false;
con.playerID = srv->playerCount++;
con.roomID = 0;
srv->players.push_back(con);
}
But in disconnection i have problem. I cant find what player with ID disconnected. Here is my OnClose method:
void Server::onClose(
Server* srv,
WSServer* ws,
websocketpp::connection_hdl& hdl)
{
for (int i = 0; i < srv->players.size(); i++)
{
if (srv->players[i].connected)
{
if ((*srv->players[i].con).lock() == hdl.lock())
{
printf("[!] Player disconnected with ID: %d\n",
srv->players[i].playerID);
srv->players.erase(srv->players.begin() + i);
}
}
}
}
In line (*srv->players[i].con).lock() == hdl.lock() it throws exception like
'this was 0xFFFFFFFFFFFFFFF7.' in file 'memory' line 75. I think it's problem with converting weak_ptr to shared_ptr. Is there any way to fix that?
My comments seemed enough to fix the problem (see comments).
For future reference and to indicate that this problem has been answered, I have created this answer.
I'm not 100% sure what is (or is not) working in your current code, since it's quite different from the way the connections are stored and retrieved within the example code (See websocketPP github/documentation example "associative storage").
Using the example, it should be rather easy to set up a multiple client structure, in the way it was intended by the library creator.
For your specific error, I believe you're on the right track about the shared/weak pointer conversion.
Best solution would be to use the list in the way it's used in the example.
Especially interesting is the "con_list" which saves all connections.
It's a typedef of std::map<connection_hdl,connection_data,std::owner_less<conn‌​ection_hdl>> con_list; con_list m_connections; and should enable you to store and retrieve connections (and their session data).

gSOAP Chaining C++ Server Classes to Accept Messages on the Same Port Not Working

We have six WSDLs compiled within the same project, and due to some limits of hardware we can only open one port for listening.
For doing this, we choose the approach described by chapter 7.2.8 How to Chain C++ Server Classes to Accept Messages on the Same Port in this gSOAP Manual.
However, when using this approach in we encounter many sever issues:
1. If lots of requests arrive concurrently, then sometimes soap_begin_serve reports error with error=-1, socket is closed immediately by soap server after it is established
2. If we call xxx.destory() after soap_free_stream(), then soap_accept() will
report an error of bad file descriptor and not work anymore (solved)
Anybody knows what are the reasons of above phoenomenon? How to solve them?
Our code is very close to the example except a few changes, see below section.
//server thread
Abc::soapABCService server; // generated with soapcpp2 -i -x -n -QAbc
server.bind(NULL, 12345, 100);
server.soap_mode = SOAP_KEEP_ALIVE | SOAP_UTF_CSTRING;
server.recv_timeout = server.send_timeout = 60;
while (true)
{
server.accept();
...
pthread_create(&pid, NULL, handle_new_request, server.copy());
} // while(true)
// work thread - the thread function
void *handle_new_request(void* arg)
{
// generated with soapcpp2 -i -x -n -QAbc
Abc::soapABCService *abc = (Abc::soapABCService*)arg;
Uvw::soapUVWService uvw; // generated with soapcpp2 -i -x -n -QUvw
Xyz::soapXYZService xyz; // generated with soapcpp2 -i -x -n -QXyz
if(soap_begin_serve(abc))
{
//sometimes it reports error
//due to unkown reason, socket was closed by soap server
abc->soap_stream_fault(std::cerr);
}
else if (abc->dispatch() == SOAP_NO_METHOD)
{
soap_copy_stream(&uvw, abc);
uww.state = SOAP_COPY;
if (uvw.dispatch() == SOAP_NO_METHOD)
{
soap_copy_stream(&xyz, &uvw);
xyz.state = SOAP_COPY;
if (xyz.dispatch())
{
soap_send_fault(&xyz); // send fault to client
xyz.soap_stream_fault(std::cerr);
}
soap_free_stream(&xyz); // free the copy
xyz.destroy();
}
else
{
soap_send_fault(&uvw); // send fault to client
uvw.soap_stream_fault(std::cerr);
}
soap_free_stream(&uvw); // free the copy
uvw.destroy();
}
else if (abc->error)
{
abc->soap_stream_fault(std::cerr);
}
else
{
}
abc->destroy();
delete abc;
abc = NULL;
}
Finally I found the reason why some connections were closed by the server rightly after they were established.
It's not the gSOAP server's fault, it's because all connections were coming from a same machine, these clients were set up to reuse address and port reuse caused this problem.