string_view points to another string - c++

I'm using Boost 1.70 and found a rather puzzling issue where sometimes boost::string_view seems to point to another string.
This is the function call where a boost::string_view is created as follows:
boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
return prepareError(req, message, beast_http::status::not_found);
And this is the prepareError() method which gets called where something really odd happens. The fist version uses message.to_string() while constructing a string variable:
template<class Body, class Allocator>
beast_http::response<beast_http::string_body> prepareError(beast_http::request<Body, beast_http::basic_fields<Allocator>>& req,
boost::beast::string_view message, beast_http::status statusCode) {
beast_http::response<beast_http::string_body> res{statusCode, req.version()};
res.set(beast_http::field::server, SERVER_VERSION_STRING);
res.set(beast_http::field::content_type, MIMETYPE_JSON);
if (_allowCrossOrigin) {
res.set(beast_http::field::access_control_allow_origin, "*");
}
res.keep_alive(req.keep_alive());
int sc = (int)statusCode;
std::string json = std::string("{\n error_code:") +
std::to_string(sc) + std::string(",\n") +
std::string(" error_description:\"") +
message.to_string() + std::string("\"\n}");
res.body() = json;
res.prepare_payload();
return res;
}
This json variable will contain the following string for example:
Printing description of json:
(std::__1::string) json = "{\n error_code:404,\n error_description:\"{\n error_code:404,\n error_descript\"\n}"
This is really odd. In the debugger the message variable contains an empty string. And as you can see from the method call this should not be the expected result for that string.
This is the same method with the only difference that there is a temporary assignment of the message variable, which is a string_view, to a std::string.
template<class Body, class Allocator>
beast_http::response<beast_http::string_body> prepareError(beast_http::request<Body, beast_http::basic_fields<Allocator>>& req,
boost::beast::string_view message, beast_http::status statusCode) {
beast_http::response<beast_http::string_body> res{statusCode, req.version()};
res.set(beast_http::field::server, SERVER_VERSION_STRING);
res.set(beast_http::field::content_type, MIMETYPE_JSON);
if (_allowCrossOrigin) {
res.set(beast_http::field::access_control_allow_origin, "*");
}
res.keep_alive(req.keep_alive());
int sc = (int)statusCode;
std::string msg = message.to_string();
std::string json = std::string("{\n error_code:") +
std::to_string(sc) + std::string(",\n") +
std::string(" error_description:\"") +
msg + std::string("\"\n}");
res.body() = json;
res.prepare_payload();
return res;
}
This gives the expected string:
Printing description of json:
(std::__1::string) json = "{\n error_code:404,\n error_description:\"The resource '/zones' was not found.\"\n}"

Your error comes from
boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
You create a temporary string on the right hand side, and set the view to point to it. After the line ends, that temporary string is destroyed and your view now points to invalid memory.
What you need to do is pass the temporary directly to the function, like this:
return prepareError(req, "The resource '" + target.to_string() + "' was not found.", beast_http::status::not_found);
Or, capture the result into a std::string variable, and then pass that to the function.

Error is from:
boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
You build a temporary string which end at end of the statement.
So you have dangling view next line.
You have to build string there directly.

Related

Why do profile pic URLs returned from graph.facebook result in a 404

The backend of my application makes a request to:
https://graph.facebook.com/v2.8/me?access_token=<firebase-access-token>&fields=id,name,first_name,birthday,email,picture.type(large){url}&format=json&method=get&pretty=0&suppress_http_code=1
I get a successful (200) response with the JSON data I expect and picture field as such:
"picture": {
"data": {
"url": "https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=<asid>&height=200&width=200&ext=<ext>&hash=<hash>"
}
}
(where in place of <asid> and <ext>, there are numbers and <hash> is some alphanumeric string).
However, when I make a GET request to the platform-lookaside URL above, I get a 404 error.
It's been happening every time since my very first graph.facebook request for the same user. The very first one returned a platform-lookaside URL which pointed to a proper image (not sure if this is simply coincidence).
Is there something I'm doing wrong or is this likely a bug with the Facebook API?
FB currently seems to have issues with some CDNs and therefore your issue might be only temporary. You should also see missing/broken images on some places on fb dot com. Worst time to debug your issue :)
Try this code it worked for me
GraphRequest request = GraphRequest.newMeRequest(
AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
// Insert your code here
try {
String name = object.getString("name");
String email = object.getString("email");
String last_name = object.getString("last_name");
String first_name = object.getString("first_name");
String middle_name = object.getString("middle_name");
String link = object.getString("link");
String picture = object.getJSONObject("picture").getJSONObject("data").getString("url");
Log.e("Email = ", " " + email);
Log.e("facebookLink = ", " " + link);
Log.e("name = ", " " + name);
Log.e("last_name = ", " " + last_name);
Log.e("first_name = ", " " + first_name);
Log.e("middle_name = ", " " + middle_name);
Log.e("pictureLink = ", " " + picture);
} catch (JSONException e) {
e.printStackTrace();
Log.e("Sttaaaaaaaaaaaaaaaaa", e.getMessage());
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,link,last_name,first_name,middle_name,picture");
request.setParameters(parameters);
request.executeAsync();

json serialize c++

I have this C++ code, and am having trouble json serializing it.
string uInput;
string const& retInput;
while(!std::cin.eof()) {
getline(cin, uInput);
JSONExample source; //JSON enabled class from jsonserialize.h
source.text = uInput;
//create JSON from producer
std::string json = JSON::producer<JSONExample>::convert(source); //string -> returns {"JSONExample":{"text":"hi"}}
//then create new instance from a consumer...
JSONExample sink = JSON::consumer<JSONExample>::convert(json);
//retInput = serialize(sink);
// Json::FastWriter fastWriter;
// retInput = fastWriter.write(uInput);
retInput = static_cast<string const&>(uInput);
pubnub::futres fr_2 = pb_2.publish(chan, retInput);
cout << "user input as json which should be published is " << retInput<< std::endl;
while(!cin.eof()) {
getline(cin, uInput);
newInput = "\"\\\"";
newInput += uInput;
newInput += "\\\"\"";
Instead of typing in the message like "\"hi\"", this code takes "hi" and does it.
If the change you described made the "Invalid JSON" disappear, then a "more correct" solution would be, AFAICT, to change the publish() line to:
pubnub::futres fr_2 = pb_2.publish(chan, json);
Because json already has JSON serialized data. Of course, if that JSON is what you want to publish.

C++REST SDK, parse JSON that contains (0xEF 0xBF 0xBF) character

I have a REST API that returns a string with files metadata. Among those files I have one that has "￿" (0xEF0xBF0xBF, link) character in name. When I try to parse such a response I get exception that says:
e = {_message="* Line 1, Column 13 Syntax error: Malformed string literal" }
This is the string I'm trying to parse:
{"files":[["Thunderbolt ￿Gigabit￿ Ethernet ￿Adapter.txt",["bc288518-c426-4dbd-9600-a213a35d1c04",1447772221866,9,"Bartosz","Siewior"]],["System.Windows.Interactivity.dll",["56ce759b-019b-4723-8fca-7af877908971",1440507238241,55904,"Bartosz","Siewior"]]],"folderPermission":[["MODIFY"]],"directories":[]}
The code I'm using to receive and parse the string:
// ...
client.request(request).then([&](web::http::http_response response) {
status_code = response.status_code();
//response.extract_json(true).then([&](pplx::task<web::json::value> previousTask) {
response.extract_string().then([&](pplx::task<utility::string_t> previousTask) {
try {
utility::string_t str_response = previousTask.get();
web::json::value root;
root = web::json::value::parse(str_response);
}
catch (const web::http::http_exception& e) {
std::wstringstream ss;
ss << e.what();
str_response = ss.str();
}
catch (const web::json::json_exception& e) {
std::wstringstream ss;
ss << e.what();
str_response = ss.str();
}
TaskExecutionData data = { task.id, status_code, str_response.c_str() };
callback(data);
}).wait();
}).wait();
VS2013 JSON Visualizer can parse and show the result properly: VS_json_visualizer
I've tried C++REST version 2.5.0 and 2.6.0, neither of them is able to parse that string... Do you have any ides?
Answer from Casablanca's team:
The issue is that on windows we parse using UTF16 and the particular character you're having issues with maps to 0xFFFF. This is also the character returned by std::char_traits::eof(), so we detect the code point as an "end of stream" signal and terminate the parse appropriately.
The UTF8 parser should not have these issues, so as a workaround you can probably do something similar to how the current web::json::value::parse() function works in json_parsing.cpp:1245, except using char as the template parameter instead of utility::char_t.

How to get protobuf enum as string?

Is it possible to obtain the string equivalent of protobuf enums in C++?
e.g.:
The following is the message description:
package MyPackage;
message MyMessage
{
enum RequestType
{
Login = 0;
Logout = 1;
}
optional RequestType requestType = 1;
}
In my code I wish to do something like this:
MyMessage::RequestType requestType = MyMessage::RequestType::Login;
// requestTypeString will be "Login"
std::string requestTypeString = ProtobufEnumToString(requestType);
The EnumDescriptor and EnumValueDescriptor classes can be used for this kind of manipulation, and the
the generated .pb.h and .pb.cc names are easy enough to read, so you can look through them to get details on the functions they offer.
In this particular case, the following should work (untested):
std::string requestTypeString = MyMessage_RequestType_Name(requestType);
See the answer of Josh Kelley, use the EnumDescriptor and EnumValueDescriptor.
The EnumDescriptor documentation says:
To get a EnumDescriptor
To get the EnumDescriptor for a generated enum type, call
TypeName_descriptor(). Use DescriptorPool to construct your own
descriptors.
To get the string value, use FindValueByNumber(int number)
const EnumValueDescriptor * EnumDescriptor::FindValueByNumber(int number) const
Looks up a value by number.
Returns NULL if no such value exists. If multiple values have this >number,the first one defined is returned.
Example, get the protobuf enum:
enum UserStatus {
AWAY = 0;
ONLINE = 1;
OFFLINE = 2;
}
The code to read the string name from a value and the value from a string name:
const google::protobuf::EnumDescriptor *descriptor = UserStatus_descriptor();
std::string name = descriptor->FindValueByNumber(UserStatus::ONLINE)->name();
int number = descriptor->FindValueByName("ONLINE")->number();
std::cout << "Enum name: " << name << std::endl;
std::cout << "Enum number: " << number << std::endl;

get the first parameter of a string using regular expression

function getParameterByName(name, str) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(str);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
I'm using this algorithm for getting the value from the string, found it in internet
my string is
mihpayid=403993715510554486&mode=CC&status=success&unmappedstatus=captured&key=JBZaLc&txnid=t39SfgBZFEFLwhxEC&amount=1000.0&addedon=2014-12-06+17%3A34%3A26&productinfo=Devthon&firstname=sasi.kanth80%40gmail.c&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=sasi.kanth80%40gmail.com
I'm able to get all the parameters like status key
But I'm unable to get the mihpayid value which is the first parameter
How can I get that any suggestion?
getParameterByName("success", data);
You can make use of this function which will form a flattened array looking like
[key,value, anotherkey,anothervalue,...] so we could just find the value by adding one to the index of key.
function getParameterByName(name, str) {
var arr = str.split('&').map(function(s){
return s.split('=')
}).join().split(","); // flatten the array
return decodeURIComponent(arr[arr.indexOf(name) + 1]);
}
A regular expression like /([a-zA-Z0-9]*)=([^&]*)/ig will return all matches with the variable and value conveniently sorted.
I think your solution is really close, it's just missing a couple of things. One not sure if it is a typo or not but the line var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"); ends in a comma. Outside of this the only thing you needed to do is update the following [\\?&] to [\\?&]?
function getParameterByName(name, str) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]?" + name + "=([^&#]*)");
results = regex.exec(str);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
data="mihpayid=403993715510554486&mode=CC&status=success&unmappedstatus=captured&key=JBZaLc&txnid=t39SfgBZFEFLwhxEC&amount=1000.0&addedon=2014-12-06+17%3A34%3A26&productinfo=Devthon&firstname=sasi.kanth80%40gmail.c&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=sasi.kanth80%40gmail.com";
console.clear();
console.log(getParameterByName("unmappedstatus", data));
console.log(getParameterByName("status", data));
console.log(getParameterByName("mihpayid", data));
Results in Console:
regex:10 Console was cleared
regex:11 captured
regex:12 success
regex:13 403993715510554486
regex:1 undefined