The app receives request which looks like(http://127.0.0.1:8000/?type%3DGCPrint%26get%3DPaperNames%3A%E9%BB%98%E8%AE%A4%E6%89%93%E5%8D%B0%E6%9C%BA) from client's XMLHttpRequest. The url is encoded by encodeURI() or encodeURIComponent() with javascript.
How can I get the canonical form url correctly?
I have reached the sdk and followed a demo, but the result is not correct, the last part of url is chinese characters.
Here is my test code
void UrlDecode()
{
wstring url = L"http://127.0.0.1:8000/?type%3DGCPrint%26get%3DPaperNames%3A%E9%BB%98%E8%AE%A4%E6%89%93%E5%8D%B0%E6%9C%BA";
DWORD bufSize = url.size()+1;
wstring buffer(url.size()+1, L'\0');
HRESULT hr = UrlCanonicalize(url.c_str(), &buffer[0], &bufSize, URL_UNESCAPE|URL_ESCAPE_UNSAFE);
if (SUCCEEDED(hr))
{
wcout.imbue(locale(""));
wcout<<buffer;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
UrlDecode();
//system("pause");
return 0;
}
And the result is
#RC Brand #enhzflep thanks for your help.
I have tried UriParser, but there are some Encoding problems either.
At last I find a code snippnet, it works for me.
Firstly, convert the url to MultiByte string(murl) with CP_UTF8.
Then, decode murl with function urldecode, get decoded url durl.
Finally, Convert durl to WideChar with CP_UTF8.
Related
In the end, my goal is to send a raw image data from the front-end, then split that image into however many pages, and lastly send that pdf back to the front-end for download.
But every time I use the theDoc.addImageFile(), it tells me that the "Image is not in a suitable format". I'm using this as reference: https://www.websupergoo.com/helppdfnet/source/5-abcpdf/doc/1-methods/addimagefile.htm
To troubleshoot, I thought that the image might not be rendering correctly, so I added a File.WriteAllBytes to view the rendered image and it was exactly what I wanted, but still not adding to the PDF. I also tried sending the actual path of a previously rendered image thinking that the new image might not have been fully created yet, but it also gave me the same error. Lastly, I thought PNGs might be problematic and changed to JPG but it did not work.
Here is the code:
[HttpPost]
public IActionResult PrintToPDF(string imageString)
{
// Converts dataUri to bytes
var base64Data = Regex.Match(imageString, #"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
/* Ultimately will be removed, but used for debugging image */
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string imgName= "Test.jpg";
string filename = Path.Combine(path, imgName);
System.IO.File.WriteAllBytes(filename, binData);
/***********************************************************/
using (Doc theDoc = new Doc())
{
// Using explicit path
theDoc.AddImageFile(#"C:\Users\User\Documents\Test.jpg", 1);
// Using variable
//theDoc.AddImageFile(filename, 1);
// What I really want
//theDoc.AddImageFile(binData , 1);
theDoc.Page = theDoc.AddPage();
theDoc.AddText("Thanks");
Response.Headers.Clear();
Response.Headers.Add("content-disposition", "attachment; filename=test.pdf");
return new FileStreamResult(theDoc.GetStream(), "application/pdf");
}
}
Try something like this (not tested, but cleaned up from my own code):
public int AddImageFile(Doc doc, byte[] data, int insertBeforePageID)
{
int pageid;
using (var img = new XImage())
{
img.SetData(data);
doc.Page = doc.AddPage(insertBeforePageID);
pageid = doc.Page;
doc.AddImage(img);
img.Clear();
}
return pageid;
}
To add a JPEG from a byte array you need Doc.AddImageData instead of Doc.AddImageFile. Note that AddImageFile / AddImageData do not support PNG - for that you would definitely need to use an XImage. The XImage.SetData documentation has the currently supported image formats.
I am using this tutorial. I am also using a same Node MCU ESP8266. Ii connected it to my home network. The local ip address is also displayed but it doesn't connected to my thingspeak channel and it stuck at the waiting for the client.
I also checked that my thingspeak API is correct and my home network is also working.
It looks like you are using the Arduino IDE to program the NodeMCU. If this is the case, then all you have to do create a WiFiClient, then construct an HTTP POST request, and send it to ThingSpeak using the client.
Here are the relevant lines from my tutorial:
Before your setup add the lines:
#include <ESP8266WiFi.h>
WiFiClient client;
const char* server = "api.thingspeak.com";
String writeAPIKey = "XXXXXXXXXXXXXXXX";
In your loop, add the following lines to read A0 and send it to ThingSpeak:
if (client.connect(server, 80)) {
// Measure Analog Input (A0)
int valueA0 = analogRead(A0);
// Construct API request body
String body = "field1=";
body += String(valueA0);
Serial.print("A0: ");
Serial.println(valueA0);
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: " + writeAPIKey + "\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(body.length());
client.print("\n\n");
client.print(body);
client.print("\n\n");
}
client.stop();
// wait 20 seconds and post again
delay(20000);
Use ESP8266HTTPClient HTTP lib to post to ThingSpeak via ESP8266. Here is an example function. Call it with a data parameter to write into your ThingSpeak channel:
#include <ESP8266HTTPClient.h>
#define TSPEAK_HOST "http://api.thingspeak.com"
#define TSPEAK_API_KEY "YOUR_THINGSPEAK_API_KEY"
#define LEN_HTTP_PATH_MAX 256
HTTPClient http;
unsigned short postThingSpeak(char* data)
{
boolean httpCode = 0;
char httpPath[LEN_HTTP_PATH_MAX];
memset(httpPath, 0, LEN_HTTP_PATH_MAX);
snprintf(httpPath, LEN_HTTP_PATH_MAX, "%s/update?api_key=%s&field1=%s", TSPEAK_HOST, TSPEAK_API_KEY, data);
Serial.printf("Path to post : %s\n", httpPath);
http.begin(httpPath);
httpCode = http.GET();
Serial.printf("Return : %d\n", httpCode);
Serial.printf("Incoming Body : %s\n", http.getString().c_str());
http.end();
return httpCode;
}
I know that this question has been asked many times however in my case the suggested codes and solutions aren't cutting it. The network reply is still my case empty and the error code is 0.
Here's my function:
QString NWork::send(QVector<QString> &data) const{
//QNetworkAccessManager qnam = new QNetworkAccessManager();
QNetworkAccessManager qnam;
try{
QString json = NWork::to_JSON(data);
QByteArray json_data(json.toUtf8());
QNetworkRequest request;
request.setUrl(QUrl(NWork::connection));
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Content-Length", json_data);
reply = qnam.post(request, json_data);
//reply = qnam.get(request);
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString s(reply -> readAll());
qDebug()<<"code "<<status<<"Content "<<s;
//return QString::fromUtf8(response.data(),response.size());
}catch(std::exception x){
std::cout<<x.what()<<std::endl;
}
return "";
}
Making connections of the form suggested by many like
connect(qnam,SIGNAL(destroyed(QNetworkReply*)),this,SLOT(read(QNetworkReply*)));
have no effect on all. The request is reaching the PHP script and I know this by writing the request data in a file. It does so for every request. Echoing anything back even with a text/html header is not working.
Yes, I have tried my PHP script with a HTML AJAX request program and it works. It writes to file, and returns a response to the browser. Same code in both cases.
Here's my PHP code:
header("Access-Control-Allow-Origin: *");
$k = file_get_contents("php://input");
$file = "/file/path/log.k";
//echo $file;
$handle = fopen($file, "a+");
if($handle){
echo $k;
fwrite($handle, $k."\n");
fclose($handle);
}
header("Content-Type: text/html");
echo "line 22 ".$que;
exit(0);
I've checked my apache2 error logs and none are invoked. Why is it not working in my case?
I know this is almost a year old question but I just started teaching myself Qt and I recently ran into this issue as well and was bought to this page. So for those who are also stuck on this, here is how I solved it.
First change the connect from:
connect(qnam,SIGNAL(destroyed(QNetworkReply*)),this,SLOT(read(QNetworkReply*)));
to:
connect(reply, SIGNAL(finished()), this, SLOT(onReply()));
Then add it to your code after the post call like so:
reply = qnam.post(request, json_data);
connect(reply, SIGNAL(finished()), this, SLOT(onReply()));
The finished method is part of the QNetworkReply signals and is fired when the reply is finished. The method inside of SLOT is a Q_SLOT that you have to define in your hpp. Then move your code to your onReply method it would look similar to this:
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QString response = reply->readAll();
if (reply)
{
if (reply->error() == QNetworkReply::NoError)
{
const int available = reply->bytesAvailable();
if (available > 0)
{
const QByteArray buffer = reply->readAll();
response = QString::fromUtf8(buffer);
// success = true;
}
}
else
{
response = tr("Error: %1 status: %2").arg(reply->errorString(), reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString());
}
qDebug()<<"code: "<<reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString()<<" response: "<<response;
reply->deleteLater();
}
sources: QNetworkReply, BlackBerry Sample App Maven source code
these steps are what i did.
1) i just got IWebBrowser2 interface pointer from pUnkSite in SetSite as most bhos do in usual.
2) in OnDocumentComplete,
2-1) got IHTMLDocument interface pointer successfully from IWebBrowser2.
2-2) got html text from IHTMLDocument
i confirmed that these steps above worked correctly.
but what i really want to do is that the bho shows messagebox containing the html of current page whenever user want to get html text (for example, user clicks on "get html" button).
so, when user clicks on "get html" button, i wrote a function to do that like below.
void CBHO::ClickedOnGetHtml()
{
CComPtr<IDispatch> spDispDoc;
HRESULT hr = m_spWebBrowser->get_Document(&spDispDoc); // m_spWebBrowser from SetSite
if (SUCCEEDED(hr))
{
CComQIPtr<IHTMLDocument2> spHtmlDoc;
spHtmlDoc = spDispDoc;
CComPtr<IDispatch> spDisp;
spHtmlDoc->get_Script(&spDisp); <- exception occured here in ie8. (worked correctly in ie6, but not in ie8.)
}
}
this is the call stacks at the exception occured.
mshtml.dll!GetCurrentServiceProvider() + 0xc bytes
mshtml.dll!GetCallerCommandTarget() + 0xa6 bytes
mshtml.dll!COmWindowProxy::SecureObject() - 0x600c5 bytes
mshtml.dll!CDocument::get_Script() + 0x9c bytes
BHO.dll!CBHO::ClickedOnGetHtml() line 37 + 0x2d bytes C++
more interesting thing is that it worked correctly in ie6, but not worked in ie8.
(is there any changes on ie8 compared to ie6 ?)
please leave any advises or comments on this problem,
thanks in advance.
Try to use outerHTML property to obtain page HTML:
CString GetOuterHTML(IWebBrowser2* pWebBrowser)
{
CComDispatchDriver pDocDisp;
if(SUCCEEDED(pWebBrowser->get_Document(&pDocDisp)) && pDocDisp != NULL)
{
CComQIPtr<IHTMLDocument3> pDoc3 = pDocDisp;
if(pDoc3 != NULL)
{
CComPtr<IHTMLElement> pRootElem;
if(SUCCEEDED(pDoc3->get_documentElement(&pRootElem)) && pRootElem != NULL)
{
CComBSTR bstrText;
if(SUCCEEDED(pRootElem->get_outerHTML(&bstrText)))
{
return bstrText;
}
}
}
}
return L"";
}
Specifically what i'm trying to do is Generate a PassStub field for a Remote Assistance ticket. The problem is that my results look like binary data but somehow Microsoft generates printable characters.
In [MS-RAI]: Remote Assistance Initiation Protocol Specification <16> Section 6: Microsoft says that the "PassStub" field "is encrypted using PROV_RSA_FULL predefined Cryptographic provider with MD5 hashing and CALG_RC4, the RC4 stream encryption algorithm."
There is a data flow diagram here:
http://msdn.microsoft.com/en-us/library/cc240189(PROT.10).aspx#id16
The diagram shows the hashed password being encrypted with a "RA SessionID" which looks like this: u0RIQibSMntm0wAHQZ2mhatI63sjMjX15kh/vnciytOix8z6w+36B01OiJoB5uYe
When I call CryptEncrypt the result is binary data about the length of the SessionID. Microsoft somehow gets something that looks like this: "Po^1BiNrHBvHGP"
Here is the code i'm trying to use to do this:
HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
HCRYPTHASH hHash;
BOOL bret=0;
passwordlen = SysStringByteLen(L"password");
char RASessionID[] = "u0RIQibSMntm0wAHQZ2mhatI63sjMjX15kh/vnciytOix8z6w+36B01OiJoB5uYe";
//----------------------------------------------------------------
// Acquire a cryptographic provider context handle.
if(!CryptAcquireContext(&hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0))
{
return FALSE;
}
//----------------------------------------------------------------
// Create an empty hash object.
if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
{
return FALSE;
}
if(!CryptHashData(hHash, (BYTE *)bpassword, passwordlen, 0))
{
return FALSE;
}
//----------------------------------------------------------------
// Create a session key based on the hash of the password.
if(!CryptDeriveKey(hCryptProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, &hKey))
{
return FALSE;
}
DWORD rasessionidlen = strlen(rasessionid);
char* proxystub = (char*)malloc(rasessionidlen*2);
strcpy(proxystub, rasessionid);
bret = CryptEncrypt(hKey, NULL, TRUE, 0, (BYTE*)proxystub, &rasessionidlen, rasessionidlen*2);
return bret;
The "RA SessionID" looks like it is base64-encoded. My guess would be that the pass-stub is base64-encoded too - except that your example: "Po^1BiNrHBvHGP" is too short and contains a ^. Is that a real example?
You might also need to base64-decode the RA Session ID before feeding it to CryptEncrypt.