How to access the same JSON file from both javascript and python? - javascript

NOTE: This is not for web programming. We use javascript to interface with low level hardware, hence let's not go with jQuery APIs etc.
I have a javascript file that performs a sequence of actions on a device, and I have a python file that will be invoked later to validate these actions. There is a set of hardware information hard-coded in both javascript file and python file. I want to avoid this duplication of information by putting these info into a JSON file so both can access it.
// Javascript
var hardware_info = JSON.parse(load('hardware.json'));
// load() is probably not standard javascript API, but it basically copies that code into the existing script.
Already failed by this step because 'hardware.json' is not using javascript syntax...
I already validated the json using jshint/jslint, hardware.json looks like this:
{
"hardware1": {
"ID": "xxx"
},
"hardware2": {
"ID": "yyy"
}
}
The following Python works well for accessing the json, there is not much to it:
with open('hardware.json', 'r') as f:
data = json.load(f)

It looks like load() executes the specified file, not read it and return the contents. If this is your only option to read another file, then I suggest you use JSONP instead of JSON.
JSONP works by adding a callback around the data. Instead of:
{"key": "value"}
the file contains a function call with the data being passed in:
callback({"key": "value"});
This is meant to be executed by a JavaScript engine, causing it to execute the callback. load() would execute your file, and the callback function would be called as a result, passing in the data.
When used on the web, you'd call a JSONP service and pass in the name of the callback the service should add, but when just sharing a configuration file between a JS engine and Python, you'd hardcode that callback name.
In Python, you'd have to strip off the callback text before loading it as JSON data. That could be as easy as just removing the first N and last M characters:
with open('hardware.json', 'r') as f:
jsonp_data = f.read()
# remove first 9 and last 3 characters to remove JSONP callback
data = json.loads(jsonp_data[9:-3])
A little more sophisticated technique could use newlines:
callback(
{"key": "value"}
);
to make it easier to remove the first and last line in Python. Or you could use jsonp_data.partition('(')[-1].jsonp.rpartition(')')[0] to take everything between the first ( and the last ) character in the string. Etc.

Related

The file is emptied when I use file_put_contents

Main issue was solved in comments, although one of the bonus questions is still open and the other's solution could use some improvement
All of this takes place on a webhosting service, the folder structure is as follows:
The JavaScript and PHP files are in /public_html/, the JSON is in /public_html/data/.
In my JS code, I'm sending a POST request with some data for my JSON file:
console.log(objdata.buildings[0].coords);
var params = JSON.stringify(objdata);
if (objdata.buildings[0].coords != " "){
$.ajax({
type: "POST",
data: params,
url: "writecoords.php",
success: function(data){
console.log(params);
console.log(data);
console.log("AJAX success");
},
error: function(){
console.log("failed to send POST");
alert("error");
}
});
}
PHP file:
<?php
function debug_to_console($data){
if(is_array($data) || is_object($data))
{
echo("\n".json_encode($data));
} else {
echo("\n".$data);
}
}
$newJSON = json_decode(file_get_contents('php://input'));
debug_to_console($newJSON);
if (is_writable('data/strogi.json')) {
$a = file_put_contents('data/strogi.json', $newJSON);
if(! $a)
debug_to_console("Wrote nothing");
debug_to_console("PHP write success");
} else {
debug_to_console("PHP write failed");
}
?>
As you can see, I perform a check at every possible point to see if I'm actually processing non-empty data -- I log the value of the key in question, the AJAX request is sent only if it was changed, I log the data being sent and I log the data my PHP file receives and decodes.
I also check if the file is writable to avoid a possible permission problem, and only then I try to write to the file. The file comes out empty and I get the following outputs in console
params is my JSON object as a single line;
data is: my JSON object as a single line with line breaks before every new object and all cyrillic converted to \u format, "Wrote nothing!", "PHP write success";
"AJAX success"
If I check the strogi.json file after this, it's absolutely empty.
To rule out a problem with the format of passed JSON object, I tried writing to a simple test.txt file in the same directory as the .php, which turns out empty as well.
I tried using the method described here, but nothing changed.
I tried using a FTP upload (the method is pointed out somewhere in the comments here), and I got "No such file or directory" returned both for the strogi.json and test.txt files. I used both public_html/test.txt and test.txt as file name.
I tried using the combination of locks FILE_APPEND | LOCK_EX, and no changes happen to either of the files.
My questions are:
Why?
Can a different solution be used if all of this is taking place in the .done() callback for $.getJSON() called on the same file?
Follow-up question worthy of a separate section:
coords is a 3-dimensional array
[
[[x1,y1],[x2,y2],...]]
]
where the external array contains up to two arrays. The first array contains points of the external polygon and (if present) second array contains points of the internal polygon that serves as a cutout.
The code in question is an attempt to make submitting the coords array to strogi.json work for at least one object.
What I'm trying to do, in general, is
$.getJSON() the data/strogi.json file
go through the buildings[] array of objects inside it in the .done()
callback
for each object, check if "coords" is " " (default value)
If it is, a constructor is called to build a polygon using a map API, and when construction is finished, $.ajax is used to submit coords extracted through one of API's functions.
As of now, I'm submitting the whole JSON object, because I'm only working with one of the inner objects, but I imagine resubmitting the whole thing is excessive with multiple objects presented.
Is there a way to pass objdata.buildings[i].coords with the index i to PHP to change the "coords" key value in JSON for a certain buildings[i] object?
Do I need to make any changes to the way I'm processing data to make my JSON valid upon further reads? I assume I'd have to change the "coords" value from [[[x1,y1],[x2,y2]]] (the way it's passed now) to something like this (pastebin because there's no code formatting even though I'm using the 4 space indent)
for it to work, right? How do I do that? partly solved by going through the array in JS with two for() loops and applying toString() to every coordinate, there's gotta be a better way

Different JSON pages

i have 2 web pages containing same JSON string. one work fine with java-script function.but other one is completely not working.the only different between these two is url.
here is the page that is working fine with the js function.
(http://jsfiddle.net/echo/jsonp/?test=some+html+content&callback=?)
here is the one that is not working with the js function.
(http://sanjeewa88.byethost31.com/EMPStore/test_json.html)
here is my java-script function
function doJSON() {
$.getJSON('http://jsfiddle.net/echo/jsonp/?test=some+html+content&callback=?', function (data) {
$('#allemployees').append("<li>" + data.test+ "</li>");
});
}
what's wrong with second page and how i fix it to access that page through js function.
PS-
i want to display these data in a listview. first one is displaying that remote data on the listview.but second one which having same json string is not displaying anything.
On the page you provide the json you have to accept a para callback and use this parameter to generate the function name.
look what's happen when you call jsfiddle callback with an other name:
http://jsfiddle.net/echo/jsonp/?test=some+html+content&callback=poney
give:
poney({"test": "some html content"});
You have more information here: jQueryDoc
If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.

Javascript - Sanitize Malicious code from file (string)

I have a data javascript file, which is being dynamically added to website via some custom code.
This file comes from a third party vendor, who could potentially add malicious code in the file
Before this file is added to the website, I would like to parse through it, and look for malicious code, such as redirects or alerts, that inherently get executed upon a files inclusion in the project/website.
For example, my js file could look like this :
alert ('i am malicious');
var IAmGoodData =
[
{ Name :'test', Type:'Test2 },
{ Name :'test1', Type:'Test21' },
{ Name :'test2', Type:'Test22' }
]
I load this file into a object via a XMLHttpRequest call, and when this call returns, I can use the variable (which is my file text) and search it for words:
var client = new XMLHttpRequest();
client.open('GET', 'folder/fileName.js');
client.onreadystatechange = function()
{
ScanText(client.responseText);
}
client.send();
function ScanText(text)
{
alert(text);
var index = text.search('alert'); //Here i can search for keywords
}
The last line would return index of 0, as the word alert is found at index 0 in the file.
Questions:
Is there a more efficient way to search for keywords in the file?
What specific keywords should i be searching for to prevent malicious code being run? ie redirects, popups, sounds etc.....
Instead of having them include var IAmGoodData =, make them simply provide JSON (which is basically what the rest of the file is, or seems to be). Then you parse it as JSON, using JSON.parse(). If it fails, they either didn't follow the JSON format well, or have external code, and in either case you would ignore the response.
For example, you'd expect data from the external file like:
[
{ Name :'test', Type:'Test2' },
{ Name :'test1', Type:'Test21' },
{ Name :'test2', Type:'Test22' }
]
which needs to be properly serialized as JSON (double quotes instead of single quotes, and double quotes around the keys). In your code, you'd use:
var json;
try {
json = JSON.parse(client.responseText);
catch (ex) {
// Invalid JSON
}
if (json) {
// Do something with the response
}
Then you could loop over json and access the Name and Type properties of each.
Random Note:
In your client.onreadystatechange callback, make sure you check client.readyState === 4 && client.status === 200, to know that the request was successful and is done.
This is extremely difficult to do. There are no intrinsically malicious keywords or functions in JavaScript, there are malicious applications. You could be getting false positives for "malicious" activity and prevent a legitimate code with a real purpose from being executed. And at the same time, anyone with a little bit of imagination could bypass any "preventive" method you may implement.
I'd suggest you look for a different approach. This is one of those problems (like CAPTCHA) in which it's trivial for a human to solve while for a machine is practically impossible to do so. You could try having a moderator or some human evaluator to interpret the code and accept it.
You should have them provide valid JSON rather than arbitrary Javascript.
You can then call JSON.parse() to read their data without any risk of code execution.
In short, data is not code, and should not be able to contain code.
You shouldn't. The user should be allowed to type whatever they want, and it's your job to display it.
It all depends on where it is being put, of course:
Database: mysql_real_escape_string or equivalent for whatever engine you're using.
HTML: htmlspecialchars in PHP, createTextNode or .replace(/</g,"<") in JavaScript
JavaScript: json_encode in PHP, JSON.stringify in JavaScript.
At the end of the day, just don't be Yahoo

JMeter modifying output to file from XML Stream

I'm attempting to write a JMeter script which after receiving and XML response from a server, extracts a string from it on the fly (drops the first part of the response) and writes it to a file.
Currently I use a Save Response Data to write to ChannelData_UAT_1 (filename). All good, it writes happily.
Then I add a BSF PreProcessor BEFORE it, and use javascript to try and extract the string. It's a bunch of XML tags, I want everything from "<Markets>" onwards.
I use:
function extract_markets(str)
{
marketIndex = str.indexOf("<Markets");
__log(marketIndex);
length = str.length;
marketString = str.substring(markeIndex, length-1);
return str;
}
vars.put('ChannelData_UAT_1', extract_markets(vars.get('ChannelData_UAT_1')));
As far as I can tell, ChannelData_UAT_1 is the variable the data is in. However this is only mentioned in the Save Response Data. But I can't do it afterwards otherwise it'll have already written to the file.
The current performance is for it to receive the response and write to the file. No filtering is done - as if my javascript didn't exist.
Anything small or obvious that I've missed? Suggestions?
I believe the issue stems from the fact that ChannelData_UAT_1 is not a variable and how Save Response Data works.
ChannelData_UAT_1 is the file name, not the content of the file.
You need to modify the contents of the "Response". You can replace the value of the page response with the value of your function.
I think the code would look something like this:
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.samplers.SampleResult;
prev.setResponseData(extract_markets(vars.get('ChannelData_UAT_1')));
Source:
http://www.javadocexamples.com/java_examples/org/apache/jmeter/samplers/SampleResult/

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