Accessing a Javascript variable inside an HTML file - javascript

I'm doing a little bit of reverse engineering on the Rapportive API in Gmail.
I make this request
import requests
url ='https://api.linkedin.com/uas/js/xdrpc.html'
r = requests.get(url)
print r.text
The response is an empty HTML file that has a lot of Javascript in it. On line 3661, it sets the RequestHeader for the subsequent call to Rapportive:
ak.setRequestHeader("oauth_token", ae);
Is there a way I can request that page and then return ae?

I think you can try:
Get the page as you already does;
Remove all non-javascript elements from the response page;
Prepend a javascript (described below) in the page's javascript to override some code;
Execute it with eval('<code>');
Check if the token has been set correctly;
I'm proposing the following code to override the XMLHttpRequest.setRequestHeader functionality to be able to get the token:
// this will keep the token
var headerToken;
// create a backup method
XMLHttpRequest.prototype.setRequestHeaderBkp =
XMLHttpRequest.prototype.setRequestHeader;
// override the "setRequestHeader" method
XMLHttpRequest.prototype.setRequestHeader = function(key, val)
{
if ('oauth_token' === key)
headerToken = val;
this.setRequestHeaderBkp(key, val);
}

If you are just interested in retrieving the token can't you just do a regex match:
var str = '<script>var a = 1;...ak.setRequestHeader("oauth_token", ae);...</script>';
var token = str.match(/setRequestHeader\("oauth_token",\s*([^)]+)/)[1];
Although this assumes ae is the actual string value. If it's a variable this approach wouldn't work as easily.
Edit: If it's a variable you could do something like:
str.replace(/\w+\.setRequestHeader\([^,]+,\s*([^)]+)\s*\);/, 'oauthToken = \1';
Before running the JavaScript returned from the page, then the global oauthToken (notice the missing 'var') will contain the value of the token, assuming the the evaluation of the code is run in the same scope as the caller.

Related

Fiddlerscript to send a modified request to the server wont work

Ive created a fiddlescript rule that I thought would wait for a specific object:value, automatically send the a portion of the json value back to a different URI as a post request with the same header information such as cookies.
When the script is activated I receive an error. I assume its something to do with the json object value.
static function OnBeforeResponse(oSession: Session) {
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "application/json")) {
oSession["ui-backcolor"] = "blue";
oSession.utilDecodeResponse();
}
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "application/json") && oSession.utilFindInResponse("faceId", false) > -1) {
oSession["ui-backcolor"] = "green";
oSession.utilDecodeResponse();
var oBody = System.Text.Encoding.UTF8.GetString(oSession.requestBodyBytes);
var j = Fiddler.WebFormats.JSON.JsonDecode(oBody);
var facId = j.JSONObject["faceId"];
var reqBod = '{"faceId":"' + facId + '"}';
oSession.oRequest.headers.HTTPMethod == "POST";
oSession.utilSetRequestBody(reqBod);
oSession.url = "https://urltosendpostrequest.com/Search";
FiddlerObject.utilIssueRequest(oSession);
}
I expected the server to accept the modified POST request but instead the script runs into an error.
FiddlerScript OnBeforeResponse0 failed. X
There was a problem with your FiddlerScript.
Function expected Function expected at Microsoft.)Script.Latainding.CallValue(Object val, Objects arguments, Boolean construct, Boolean brackets, VsaEngine engine, Object thisob, Binder binder, Culturelnfo culture, Strings namedParameters) at Microsoft.JScript.Latainding.Call(Binder binder, Objects arguments, ParameterModifier]] modifiers, Culturelnfo culture, Strings namedParameters, Boolean construct, Boolean brackets, VsaEngine engine) at Microsoft.JScript.Latainding.Call(ObjectS arguments, Boolean construct, Boolean brackets, VsaEngine engine) at Fiddler.ScriptNamespace.Handlers.OnBeforeResponse(Session oSession) at Fiddler.ScriptBase. 1:1(Session OD) in CA.lenkins\Fiddler_Windows\workspace\Fiddler2\Common\Application\ Scripting\ScriptBase.csiline 921
You are mixing access to the request and the response header/body. Also it seems that it is not clear to you that the POST data belongs to the request not the response. Therefore make sure you are manipulating the correct data (the request or the response).
Or do you want to capture the request and send a custom response back to the client? If yes you should look at the AutoResponder Flag x-replywithfile.
You script has code in OnBeforeResponse therefore you can only access properties and methods that are related to the response.
However you have the following code which tries to access the request (which is of course impossible as the request has already been forwarded):
oSession.oRequest.headers.HTTPMethod == "POST";
oSession.utilSetRequestBody(reqBod);
FiddlerObject.utilIssueRequest(oSession);

Parsing JSON from a file path is not working properly

I am trying to parse a list of JSON files iteratively. Using PHP I have managed to compile the list of JSON files in a directly into a a single JSON object. Now I would like to parse each of these objects and output a property from each of them in HTML. I am sure that the JSON I am initially passing works. Any ideas? here is the error and the function.
$(document).ready(function(){
console.log("something")
for(var i = 2; i < Object.keys(jsTrips).length; i++){
var data_file = "http://localhos:8080/trips/" + jsTrips[i];
var currTrip = JSON.parse(data_file)
document.getElementsByClassName(i).innerHTML = currJSON.start_time;
}
console.log("finished")
});
ignore the missing t in localhost. The problem persists even when the typo is fixed
Thanks in advance!!
UPDATE:
The Javascript object jsTrips is formatted like this:
{2: name.json, 3:name.json, 4:name.json}
The the JSON files named in jsTrips are formatted like this:
{start_time: some start time, coords: [{lat: ##, long: ##}, {lat: ##, long: ##}...], end_time: some end time}
To address the error you see:
SyntaxError: JSON.parse: Unexpected character at Line 1 Column 1
The JSON.parse() method parses a JSON string, constructing the JavaScript value or object described by the string. You are feeding it a URL when it is expecting [ or { as the first character. So h causes a Syntax Error.
Assuming you define the Object jsTrips someplace in your code, and this is a more basic object, I would suggest the following:
$(function(){
console.log("Start jsTrips");
var i = 0;
$.each(jsTrips, function(k, v){
if(i >= 2){
$.getJSON("http://localhos:8080/trips/" + v, function(data_file){
$("." + i).html(data_file.start_time);
});
}
i++;
}
console.log("Finished");
});
This code also assumes there are HTML Elements with attributes like class="2". It would be better to update your Post with an example of the Objects and an example of the JSON being returned.
Now, if the Index of the Object is the class name, then it might look more like:
$.getJSON("http://localhos:8080/trips/" + v, function(data_file){
$("." + k).html(data_file.start_time);
}
Again, need to know what you're sending and what you expect to get back.
jQuery.getJSON() Load JSON-encoded data from the server using a GET HTTP request.
See More: https://api.jquery.com/jquery.getjson/
Update
Now using JSONP method via $.getJSON(), this will help address CORS:
$(function() {
var jsTrips = {
2: "file-1.json",
3: "file-2.json",
4: "file-3.json"
};
console.log("Start jsTrips");
$.each(jsTrips, function(k, v) {
var url = "http://localhos:8080/trips/" + v;
console.log("GET " + url);
$.getJSON(url + "?callback=?", function(json) {
$("." + k).html(json.start_time);
});
});
console.log("Finished");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
As you can see, this builds the new URL from your jsTrips as expected. You can get the start_time from the JSON directly. You don't need to parse it when JSON is expected.
In regards to the new CORS issue, this is more complicated. Basically, you're not calling the same URI so the browser is protecting itself from outside code.
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.
An example of a cross-origin request: The frontend JavaScript code for a web application served from http://domain-a.com uses XMLHttpRequest to make a request for http://api.domain-b.com/data.json.
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request HTTP resources from the same origin the application was loaded from, unless the response from the other origin includes the right CORS headers.
See more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS & https://www.sitepoint.com/jsonp-examples/
If you are unable to change the port being used for the target JSON files, which I suspect is creating the CORS issue, you can consider using JSONP method versus GET method. Comment and let me know if this is the case, and I can update the answer. Example included in update.
Hope that helps.
This will not probably be a complete answer, because I don't really understand the question. But maybe it will help.
You told us you compiled in PHP one file from several JSON files, in general, if you have object in JSON file, it will look like { ...some key-values here... }, if you have array there, it will be [ ...some key-values here... ].
So when you compile several files with objects into one, you'll get {...some key-values here...} {...some key-values here...} and JSON does not know how to parse those, it will throw error:
console.log(JSON.parse('{"key": "value"}{"key": "value"}'))
This will work just fine, only one object there:
console.log(JSON.parse('{"key": "value"}'))
So, if for some reason you really need to compile several JSON files into one, there is a solution - to make such resulting file with new lines as separators. Than in JS you can split your file by new line, and parse each line without issues.
Like so:
const arrayOfJSONs = Array(10).fill(null).map((_,i) => JSON.stringify({key: i, keyXTen: i * 10}))
// then you join them in one big file with \\n new lines as separators
const oneBigFile = arrayOfJSONs.join("\n");
console.log("oneBigFile:\n", oneBigFile)
// on the client you get your one big file, and then parse each line like so
const parsedJSONs = oneBigFile.split("\n").map(JSON.parse)
console.log("parsedJSONs\n", parsedJSONs)
JSON.parse take string input
Javacript fetch
$(document).ready(function(){
console.log("something")
for(var i = 2; i < Object.keys(jsTrips).length; i++){
var data_file = "http://localhos:8080/trips/" + jsTrips[i];
fetch(data_file).then((res) => res.json())
.then((currJSON) => {
// document.getElementsByClassName(i).innerHTML = currJSON.start_time;
// update your DOM here
})
}
console.log("finished")
});
JQuery $.getJSON
$(document).ready(function(){
console.log("something")
for(var i = 2; i < Object.keys(jsTrips).length; i++){
var data_file = "http://localhos:8080/trips/" + jsTrips[i];
$.getJSON(data_file, (currJSON) => {
// document.getElementsByClassName(i).innerHTML = currJSON.start_time;
// Update DOM here
});
}
console.log("finished")
});

How to escape initial json data in jade?

I use nodeJS/express as the backend and jade as a template engine. My Javascript part required some variables from the server. Generally, this can be done like this:
script(type='text/javascript').
var user = !{JSON.stringify(userObject)};
All works fine except the case when userObject has <script>[some text]</script> block. Please don't ask why this block appears in userObject because this is an internal thing and I just want to handle this case.
Because of the fact that the Javascript parser executes earlier than the HTML parser my embedding gets broken with the error:
<script>
var user = {
name: 'Erik',
about: '<script>about me</script>'
};
</script>
Uncaught SyntaxError: Invalid or unexpected token
The error happens due to the about me</script> line because it closes the main <script> tag.
So my question is: what is proper way to handle this error?
If you don't want to add an endpoint and do a GET request to it for the data, there are two more crude solutions. Note that these are kludgey hacks. I still think the best way to solve this is with an AJAX request to an API endpoint with the required data within the <script> tag.
1) Have functions that strip out the < and > characters and apply them before and after.
E.g. In the Express endpoint:
function replaceTags(aboutSection) {
aboutSection = aboutSection.replace(/</g, '%StartBracket%');
aboutSection = aboutSection.replace(/>/g, '%CloseBracket%');
return aboutSection;
}
In the client side code:
function undoReplace(aboutSection) {
aboutSection = aboutSection.replace(/%StartBracket%/g, '<');
aboutSection = aboutSection.replace(/%CloseBracket%/g, '>');
return aboutSection;
}
I'm using regex with the g tag to make sure everything, not just the first instance, is replaced.
2) If you don't need the about section, you could delete it before passing it to the endpoint.

Mailgun in .xsjs

is there a way to send an email via Mailgun with html page as its content that is longer than ~2000 characters?
I have this code, that works perfectly for short html as I believe it is sent in URL address:
var obj = $.request.body.asString();
var req = new $.web.WebRequest($.net.http.POST, "/messages");
req.headers.set('Content-Type', encodeURIComponent("application/x-www-form-urlencoded"));
req.parameters.set("domain", "mailgundomain.com");
req.parameters.set("from", "me#mailgundomain.com");
req.parameters.set("to", 'to#email.com');
req.parameters.set("subject", "subject");
req.parameters.set("html", obj); //email content
In the code above I receive the file and save it to 'org' variable and then send it to mail. What I need is to probably get my "too large" .html file to the body and then show it as a content of the email. As you probably can see, I'm quite new in .xsjs so the more detailed answer the better. If you need any more info, feel free to ask. Thank you.
Edit1: I should add that when I try to send a larger file, the response I get is "414 Request-URI Too Large".
EDIT
This seems to be the right approach, jointly figured out by the OP and myself:
var obj = $.request.body.asString();
var req = new $.web.WebRequest($.net.http.POST, "/messages");
// request headers
req.headers.set('Content-Type', "application/x-www-form-urlencoded");
// request URL parameters
req.parameters.set("domain", "mailgundomain.com");
req.parameters.set("from", "me#mailgundomain.com");
req.parameters.set("to", 'to#email.com');
req.parameters.set("subject", "subject");
// request body
req.setBody(encodeURIComponent(message));
The $.web.WebRequest class sends everything you set in the .parameters collection as an URL parameter, even if the request method is POST. This is perfectly all-right, POST requests may have URL parameters. However, URLs are length-limited, as you have noticed.
The body of a POST request is not length-limited, but you have to do the proper content encoding on your own. The body of a application/x-www-form-urlencoded type request follows the same rules as the URL - key=value pairs separated by & characters.
var obj = $.request.body.asString();
var req = new $.web.WebRequest($.net.http.POST, "/messages");
req.headers.set('Content-Type', "application/x-www-form-urlencoded");
var message = {
domain: "mailgundomain.com",
from: "me#mailgundomain.com",
to: "to#email.com",
subject: "subject",
html: obj
};
req.setBody(urlEncode(message));
where urlEncodedFormat() is a little helper function:
function urlEncode(obj) {
return Object.keys(obj).map(function (key) {
return encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
}).join("&");
}
Turning objects into an URL-encoded string is a pretty common operation. It's likely that one of the libraries you use already contains a function that does that.
While the above function is is probably correct (there might be edge cases with undefined or null values), it's preferable not to use a hand-rolled variant. Spend some time looking for the right function in your libraries.
Maybe WebRequest already does the right thing on its own, I have no way to test it, though. Try setting the message object as the body directly:
req.setBody(message);

passing value to JSP via javaScript

boolean canModify = UTIL.hasSecurity("PFTMODFY") && something;
function name() {
I need to pass a value false to something when the page loads.
}
window.onLoad = name
How can i pass a value from JavaScript to JSP on the page load
I think you mean it the other way around, have server-side code output a value that JavaScript can see at page-load time.
Sending from your server code (JSP) to your client code (JavaScript)
Just output it like you would anything else, e.g.:
<%
boolean canModify = UTIL.hasSecurity("PFTMODFY") && something;
%>
var canModify = <%=canModify%>;
// ^ ^
// | +-- server-side variable
// +-- client-side variable
When the JSP actually runs, the script code returned to the client will simply be
var canModify = false;
or
var canModify = true;
That's a boolean; if you need to output a string, you need to put the quotes around it and be careful that you escape anything within it that should be escaped inside a JavaScript literal string (like a backslash, for instance, and whatever quote character you're using).
Sending from your client code (JavaScript) to your server code (JSP)
But if you really mean you want to send a value back to the server on page load (which seems odd, but hey), you'd have to use Ajax for that. If you're going to be doing Ajax stuff, I'd recommend using a library like jQuery, Closure, Prototype, YUI, or any of several others as they can dramatically simplify the process for you. For instance, using jQuery, this client-side code sends a value back to the server:
jQuery.get("/your/page/url", {"name": "value"});
(or jQuery.post for things that make changes). Using Prototype, it'd be:
new Ajax.Request("/your/page/url", {
method: "GET", // or, of couse, "POST"
parameters: {"name": "value"}
});
All of the libs I mentioned above have similarly easy-to-use mechanisms for sending data to the server. Note that this mechanism is bound by the Same Origin Policy.
You don't need a library for this, of course — anything a library can do, you can do yourself. The features I've listed above are all wrappers for the XMLHttpRequest object (Wikipedia, MSDN, MDC). See the linked resources for examples.
Non-Ajax hack
I shouldn't have said you need to use Ajax for this, more like you want to. :-) If, for some reason, you really didn't want to use Ajax you could do it by adding something to the page with JavaScript that triggers a retrieval from the server, and then include your value as a flag in that request. For instance:
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.src = "/path/to/jsp?name=" + encodeURIComponent(value);
document.getElementsByTagName('head')[0].appendChild(link);
Your JSP would do whatever it needs to do with the query string, and then return anything that's valid in a stylesheet (/* */, for instance). Or if you don't want to use a style sheet link, use an img tag and return a transparent pixel; etc.
But I wouldn't do that. I'd use Ajax.

Categories

Resources