When using regular JSP forms for printing to the client, configuring the web.xml properly works for me (http://stackoverflow.com/questions/2147958/how-do-i-prevent-people-from-doing-xss-in-java).
Is there any "best practice" on how to escape/entityze strings which will be send via JSON to a jQuery function, which then populates the DOM with these values? Any recommended libraries or Spring Web Framework build-ins?
jQuery $.ajax-call to Spring MVC
Spring MVC responds in JSON
(magic encoding happens, e.g. <a> becomes <a> ) <= this one
jQuery receives the JSON and populates the DOM XSS-safe
Thanks in advance!
edit: I am also sometimes sending HTML on purpose, so the solution would need to be able to only handle the user input. It will probably turn out that every user-poisoned string will have to be sanitized manually?
try this class which I wrote for my use .
it may be useful check wether any case is missing . . . as no detailed testing is done on this yet.
If any issue arise please let me know. . .
(add corresponding jar Apache commons and net.sf.json)
package myutil;
import java.util.Iterator;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringEscapeUtils;
public class JSONCleaner {
public static void main(String[] args) {
// TODO Auto-generated method stub
JSONObject jsonchild2=new JSONObject();
jsonchild2.put("subchlidkey1", "subchildvalue1");
jsonchild2.put("subchlidkey2", "subchildvalue2");
jsonchild2.put("subchlidkey3", "subchildvalue3");
JSONObject jsonchild=new JSONObject();
jsonchild.put("chlidkey1", "childvalue1");
jsonchild.put("chlidkey2", "childvalue2");
jsonchild.put("chlidkey3", "childvalue3");
JSONArray jsonarray=new JSONArray();
jsonarray.add("option1");
jsonarray.add("<p>option2</p>");
jsonarray.add(jsonchild2);
JSONObject json=new JSONObject();
json.put("name", "<b>nirbhay</b>");
json.put("age", 23);
json.put("jsonChildObject", jsonchild);
json.put("weight", 65);
json.put("array", jsonarray);
System.out.println(cleanJSONObject(json));
//System.out.println(json.getString("name"));
}
public static JSONObject cleanJSONObject(JSONObject jsonObject)
{
JSONObject returnJson=new JSONObject();
Iterator<?> keys = jsonObject.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
//System.out.println(jsonObject.get(key));
if(jsonObject.optJSONObject(key)==null)
{
if(jsonObject.optJSONArray(key)!=null)
{
returnJson.put(key, cleanJSONArray(jsonObject.getJSONArray(key)));
}
else
{
returnJson.put(key, StringEscapeUtils.escapeHtml(jsonObject.getString(key)));
}
}
else
{
returnJson.put(key,cleanJSONObject(jsonObject.optJSONObject(key)));
}
}
return returnJson;
}
private static JSONArray cleanJSONArray(JSONArray array)
{
JSONArray returnArray=new JSONArray();
for(int i=0,j=array.size();i<j;i++)
{
if(array.optJSONObject(i)==null)
{
if(array.optJSONArray(i) != null)
{
returnArray.add(cleanJSONArray((JSONArray) array.get(i)));
}
else
{
returnArray.add(StringEscapeUtils.escapeHtml(array.getString(i)));
}
}
else
{
returnArray.add(cleanJSONObject((JSONObject) array.get(i)));
}
}
return returnArray;
}
}
Related
Create a web script to get the parameters of the document in java
Example url
localhost:8080/alfresco/s/get-document-data?nodeRef=workspace://SpacesStore/3b3597e5-b5ec-41d5-b63b-54b050dccd1b&property=cm:name
For implementation we use NodeService
nodeService.getProperty (new NodeRef (nodeRef), LmrContentModel.getQname (property));
As a result the script should return Json object of a kind
{
"nodeRef": "workspace: // SpacesStore / 3b3597e5-b5ec-41d5-b63b-54b050dccd1b",
"value": "value property - the one we got from nodRef"
}
Create a web script to retrieve all subfolder settings along the way.
Please help!
public class SimpleWebScript extends AbstractWebScript {
#Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
try {
List<ChildAssociationRef> nodeRef = nodeService.getChildAssocs(companyHomeRef);
for (ChildAssociationRef childAssoc : nodeRef) {
NodeRef childNodeRef = childAssoc.getChildRef();
JSONObject obj = new JSONObject();
obj.put("nodeRef", childAssoc);
obj.put("value", childAssoc.getQName());
String jsonString = obj.toString();
res.getWriter().write(jsonString);
ServiceRegistry serviceRegistry = (ServiceRegistry) context.getBean("ServiceRegistry");
}
} catch (JSONException e) {
throw new WebScriptException("Unable to serialize JSON");
}
}
}
<beans>
<bean id="webscript.org.alfresco.simple.get"
class="org.alfresco.repository.SimpleWebScript"
parent="webscript">
</bean>
</beans>
<webscript>
<shortname>Document</shortname>
<description></description>
<url>/demoSimple?nodeRef={nodeRef}&attach={attach?}</url>
<format default="json"></format>
<authentication>user</authentication>
<family>Alfresco Document</family>
</webscript>
Here I want to get the parameters of the document here is the code but it doesn't work, what's wrong with it?
I am trying to detect if my string is a JSON object or a JSON array.
Here are my examples:
jsonObject = "{"key":"value1", "id":"1"}";
jsonArray = "[{"key":"value0", "id":"0"},{"key":"value1", "id":"1"}]"
The JSON array is detected correctly but the JSON object is not correct.
Here is my code:
import com.jayway.jsonpath.Configuration;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
public class json {
public static void main(String[] args) {
String jsonObject = "{\"key\":\"value1\", \"id\":\"1\"}";
Object documentObject = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject);
// Why is documentObject not recognized as an object?
if (documentObject instanceof JSONArray) {
System.out.println("jsonObject is JSONArray");
} else if (documentObject instanceof JSONObject) {
System.out.println("jsonObject is JSONObject");
} else {
System.out.println("jsonObject is UNKNOWN");
}
String jsonArray = "[{\"key\":\"value0\", \"id\":\"0\"},{\"key\":\"value1\", \"id\":\"1\"}]";
Object documentArray = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray);
// jsonArray is recognized properly
if (documentArray instanceof JSONArray) {
System.out.println("jsonArray is JSONArray");
} else if (documentArray instanceof JSONObject) {
System.out.println("jsonArray is JSONObject");
} else {
System.out.println("jsonArray is UNKNOWN");
}
}
}
And the output:
jsonObject is UNKNOWN
jsonArray is JSONArray
What is wrong?
First of all, as #Henry points out, if you want to distinguish between a JSON object and a JSON array, the simple way is to check the first non-whitespace character.
As to why your code doesn't work, it seems that parse(jsonObject) is returning an instance of LinkedHashMap. At least that is what I am seeing for the following versions:
<dependencies>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
It turns out that this is the default behavior of the jayway jsonpath library. The default configuration specifies an order-aware representation of the JSON object. With json-smart, that is implemented as a LinkedHashMap.
So, the test for a JSON object (if you do it this way, using these libraries to read your JSON) should be:
if (object instanceof Map) {
System.out.println("object is a JSON object");
}
Most probably this issue is because of JSONObject(org.json.JSONObject) is incompatible with cloudant library.
Is any alternative way to use any other Object?
I am using below cloudant libraries,
<dependency>
<groupId>com.cloudant</groupId>
<artifactId>cloudant-client</artifactId>
<version>2.6.2</version>
</dependency>
Here is my code
package data.repositories;
import org.json.JSONObject;
import com.cloudant.client.api.*;
import com.cloudant.client.api.CloudantClient;
import com.cloudant.client.api.Database;
import com.cloudant.client.api.model.Response;
import util.Config;
public class DatabaseRepository {
CloudantClient client = ClientBuilder.account(Config.CLOUDANT_ACCOUNT_NAME)
.username(Config.CLOUDANT_USER_NAME)
.password(Config.CLOUDANT_PASSWORD).build();
public DatabaseRepository() {
JSONObject
}
public void Save(String dbName) {
Database db = client.database("dbTempName", true);
JSONObject jsonObject = new JSONObject("{hello: data}");
db.save(jsonObject);
}
}
Document saved in cloudant database is,
{
"_id": "1c7f223f74a54e7c9f4c8a713feaa537",
"_rev": "1-a3cd12379eec936b61f899c8278c9d62",
"map": {
"hello": "data"
}
}
I'm not familiar with cloudant but my guess is JsonObject has a property called "map" that holds your json string data (probably there's a myArray property too), and cloudant serializes it into json, thus adding those unnecessary values.
my suggestions:
1) try to save your json string directly like db.save("{hello: data}") to avoid serialization
2) if you really need to create a JsonObject try to customize cloudant's serialization process to avoid that extra fields.
in response to comment:
from what I read here, then I think you need a pojo, which when serialized into json would look like:
{ 'hello' : 'data' }
which is something like:
public class MyClass implements Serializable {
String hello;
public MyClass(String hello) {
this.hello = hello;
}
public String getHello() {
return hello;
}
}
then save it like:
db.save(new MyClass("data"));
or you can use a hashmap instead of a pojo:
Map<String, Object> map = new Hashmap ...
map.put("hello", "data");
db.save(map);
Look at the example in the README for the repo. It shows that you want a POJO, but you don't have to implement Serializable. Just create a class that has _id and _rev properties that are Strings. Then add Javascript object compatible properties as desired.
// A Java type that can be serialized to JSON
public class ExampleDocument {
private String _id = "example_id";
private String _rev = null;
private boolean isExample;
public ExampleDocument(boolean isExample) {
this.isExample = isExample;
}
public String toString() {
return "{ id: " + _id + ",\nrev: " + _rev + ",\nisExample: " + isExample + "\n}";
}
}
// Create an ExampleDocument and save it in the database
db.save(new ExampleDocument(true));
Although I haven't tried it, the Hashmap approach may work also, as discussed in this tutorial: https://www.ibm.com/blogs/bluemix/2014/07/cloudant_on_bluemix/.
// create a simple doc to place into your new database
Map<String, Object> doc = new HashMap<String, Object>();
doc.put("_id", UUID.randomUUID().toString());
doc.put("season", "summer");
doc.put("climate", "arid");
dbc.create(doc);
In question It seems org.json.JSONObject used And it is not compatible with cloudant client library. I tried with google object it is working good for me.
Issue got resolved by using google com.google.gson.JsonObject instead of org.json.JSONObject.
Correct Full code is given below,
Database db = client.database("dbTempName", true);
// Used google.gson.JsonObject instead of org.json.JSONObject.
com.google.gson.JsonParser parser = new com.google.gson.JsonParser();
com.google.gson.JsonObject jsonObject = parser.parse("{\"hello\": \"data\"}").getAsJsonObject();
db.save(jsonObject);
I am working in an XPages application with the OpenNTF Domino API to explore the Graph data modelling capabilities. As example I have taken the Teamroom that ships with IBM Domino.
I have defined a method to migrate responses documents into the Grap db but I get the error message: Cannot make a static reference to the non-static method
Here is what the method looks like:
private void migrateResponses(DFramedTransactionalGraph<DGraph> profilesGraph) {
try {
Database db = Factory.getSession().getCurrentDatabase();
View view = db.getView("responsesOnly");
DocumentCollection col = view.getAllDocuments();
System.out.println("number of docs found " + col.getCount());
for (Document response : col) {
System.out.println("form:" + response.getFormName());
System.out.println("id:" + response.getUniversalID());
org.openntf.domino.ext.Document parent = response.getParentDocument();
if (null == parent.getParentDocument()){
//has no parent document so this parent document is a MainTopic/Post
Post post = profilesGraph.addVertex(parent.getMetaversalID(), Post.class);
Response vertexResponse = profilesGraph.addVertex(response.getUniversalID(), Response.class);
vertexResponse.setSubject(response.getItemValueString("Subject"));
Post.addResponse(vertexResponse);
}
}
profilesGraph.commit();
} catch (Throwable t) {
XspOpenLogUtil.logError(t);
}
}
The error occurs in line:
Post.addResponse(vertexResponse);
Here is what my Post class looks like:
package com.wordpress.quintessens.graph.teamroom;
import org.openntf.domino.graph2.annotations.AdjacencyUnique;
import org.openntf.domino.graph2.builtin.DVertexFrame;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.frames.Property;
import com.tinkerpop.frames.modules.typedgraph.TypeValue;
#TypeValue("post")
public interface Post extends DVertexFrame {
#Property("$$Key")
public String getKey();
#Property("subject")
public String getSubject();
#Property("subject")
public void setSubject(String n);
// real edges!
#AdjacencyUnique(label = "hasWritten", direction = Direction.OUT)
public Iterable<Profile> getAuthors();
#AdjacencyUnique(label = "hasReaction", direction = Direction.IN)
public void addResponse(Response response);
#AdjacencyUnique(label = "hasReaction", direction = Direction.IN)
public void removeResponse(Response response);
#AdjacencyUnique(label = "hasReaction", direction = Direction.IN)
public Iterable<Response> getResponses();
}
Do you have a suggestion how I should adapt my code to make it work?
Unless OpenNTF or TinkerPop are doing some kind of magic with the supplied annotations, you are attempting to call a non-static method on an interface. Are you sure that you don't want to change:
Post.addResponse(vertexResponse);
to
post.addResponse(vertexResponse);
I am trying several examples from Jest to use as a POC for ElasticSearch integration.
Right now, I am trying just a basic GET. I created a POJO called Document. In there are some basic setters and getters are some fields. I populate it and then use GSON to generate the JSON text.
From this generated JSON, I go into ElasticSearch Sense and do the following:
PUT /reports/documents/3
{
// JSON code
}
This generates just fine. I then try using Get to pull the values out from Java, like so:
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://localhost:9200")
.multiThreaded(true)
.build());
client = factory.getObject();
Get get = new Get.Builder("reports", "3").type("documents").build();
try {
JestResult result = client.execute(get);
String json = result.getJsonString();
System.out.println(json);
Document doc = null;
doc = result.getSourceAsObject(Document.class);
System.out.println("is doc null? " + doc == null);
}catch (Exception e) {
System.err.println("Error getting document");
e.printStackTrace();
}
The String json returns what I would expect (showing _index, _type, _id and of course _source). However, doc always comes out as NULL. I am not sure why that is happening.
Just to see if this was just a Get problem, I proceeded to try to Search.I did the following code snippet:
try {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("reportNumber", "101221895CRT-004"));
Search search = new Search.Builder(searchSourceBuilder.toString())
// multiple index or types can be added.
.addIndex("reports")
.addType("documents")
.build();
SearchResult result = client.execute(search);
//List<Document> results = result.getSourceAsObjectList(Document.class);
List<SearchResult.Hit<Document, Void>> hits = result.getHits(Document.class);
for (SearchResult.Hit hit : hits) {
Document source = (Document) hit.source;
Void ex = (Void) hit.explanation;
System.out.println();
}
System.out.println("Result size: " + hits.size());
}catch (Exception e) {
System.err.println("Error searching");
e.printStackTrace();
}
When looking at result, the JSON of the object is shown. However, the List<Document> results comes out as NULL. When using hits, the size of hits is correct, but the "source" and "ex" are both NULL.
Any ideas on what I am doing wrong with this?
UPDATE
After reading Cihat's comment, I went ahead and added in logging. It turns out I am getting an error when trying to convert a date (hence why it's always coming back as NULL).
I get the following error message:
Unhandled exception occurred while converting source to the object .com.someCompanyName.data.Document
com.google.gson.JsonSyntaxException: java.text.ParseException: Unparseable date: "Nov 6, 2014 8:29:00 AM"
I have tried all different formats:
11/06/2014 8:29:00 AM (and without time and making year just 14)
06-NOV-2014 8:29:00 AM (and without time and making year just 14)
2014-11-06 8:29:00 AM (same thing with time and year changes)
2014-NOV-06 8:29:00 AM (same thing with time and year changes)
06/11/2014 8:29:00 AM (same thing)
All of those failed. I am sure I tried some other formats, so not sure what format the date should be in. I even tried the exact date from DateFormat JavaDocs and it still failed. Every time I do a search, it says to define the Dateformat in the GsonBuilder, but in Jest I do not have access to that.
This test case demonstrates indexing a document with Jest and then getting the same document back out. Not a complete answer, but hopefully it is useful to see something that is known to work.
import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.core.Get;
import io.searchbox.core.Index;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.MatcherAssert.*;
import org.junit.Test;
public class JestRoundtripIT {
public static final String INDEX = "reports";
public static final String TYPE = "documents";
public static final String ID = "3";
#Test
public void documentRoundTrip() throws Exception {
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://localhost:9200")
.multiThreaded(true)
.build());
JestClient client = factory.getObject();
Document original = new Document()
.withAuthor("Shay Banon")
.withContent("You know, for search...");
JestResult indexResult = client.execute(
new Index.Builder(original)
.index(INDEX)
.type(TYPE)
.id(ID)
.build());
assertThat(indexResult.isSucceeded(), equalTo(true));
JestResult getResult = client.execute(
new Get.Builder(INDEX, ID)
.type(TYPE)
.build());
assertThat(getResult.isSucceeded(), equalTo(true));
Document fromEs = getResult.getSourceAsObject(Document.class);
assertThat(fromEs, notNullValue());
assertThat(fromEs.getAuthor(), equalTo(original.getAuthor()));
assertThat(fromEs.getContent(), equalTo(original.getContent()));
}
public static class Document {
protected String author;
protected String content;
public Document withAuthor( String author ) {
this.author = author;
return this;
}
public Document withContent( String content ) {
this.content = content;
return this;
}
public String getAuthor() {
return author;
}
public void setAuthor( String author ) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent( String content ) {
this.content = content;
}
}
}