1 package com.jsql.util;
2
3 import com.jsql.model.InjectionModel;
4 import com.jsql.model.exception.JSqlException;
5 import com.jsql.model.injection.method.AbstractMethodInjection;
6 import org.apache.commons.lang3.StringUtils;
7 import org.apache.logging.log4j.LogManager;
8 import org.apache.logging.log4j.Logger;
9 import org.json.JSONArray;
10 import org.json.JSONException;
11 import org.json.JSONObject;
12
13 import java.util.AbstractMap.SimpleEntry;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.regex.Pattern;
18
19 public class JsonUtil {
20
21 private static final Logger LOGGER = LogManager.getRootLogger();
22
23 private final InjectionModel injectionModel;
24
25 public JsonUtil(InjectionModel injectionModel) {
26 this.injectionModel = injectionModel;
27 }
28
29 public static Object getJson(String param) {
30 Object jsonEntity;
31 try {
32 jsonEntity = new JSONObject(param);
33 } catch (JSONException exceptionJSONObject) {
34 try {
35 jsonEntity = new JSONArray(param);
36 } catch (JSONException exceptionJSONArray) {
37 jsonEntity = new Object();
38 }
39 }
40 return jsonEntity;
41 }
42
43 public static List<SimpleEntry<String, String>> createEntries(Object jsonEntity, String parentName, SimpleEntry<String, String> parentXPath) {
44 List<SimpleEntry<String, String>> attributesXPath = new ArrayList<>();
45 if (jsonEntity instanceof JSONObject) {
46 JsonUtil.scanJsonObject(jsonEntity, parentName, parentXPath, attributesXPath);
47 } else if (jsonEntity instanceof JSONArray) {
48 JsonUtil.scanJsonArray(jsonEntity, parentName, parentXPath, attributesXPath);
49 }
50 return attributesXPath;
51 }
52
53 private static void scanJsonArray(Object jsonEntity, String parentName, SimpleEntry<String, String> parentXPath, List<SimpleEntry<String, String>> attributesXPath) {
54 var jsonArrayEntity = (JSONArray) jsonEntity;
55 for (var i = 0 ; i < jsonArrayEntity.length() ; i++) {
56 Object value = jsonArrayEntity.get(i);
57 String xpath = parentName +"["+ i +"]";
58
59
60 if (value instanceof JSONArray || value instanceof JSONObject) {
61 attributesXPath.addAll(JsonUtil.createEntries(value, xpath, parentXPath));
62 } else if (value instanceof String) {
63 SimpleEntry<String, String> stringValue = new SimpleEntry<>(xpath, (String) value);
64 attributesXPath.add(stringValue);
65
66 if (parentXPath == null) {
67 jsonArrayEntity.put(i, value.toString().replaceAll(Pattern.quote(InjectionModel.STAR) +"$", StringUtils.EMPTY));
68 } else if (stringValue.equals(parentXPath)) {
69 jsonArrayEntity.put(i, value + InjectionModel.STAR);
70 }
71 }
72 }
73 }
74
75 private static void scanJsonObject(Object jsonEntity, String parentName, SimpleEntry<String, String> parentXPath, List<SimpleEntry<String, String>> attributesXPath) {
76 var jsonObjectEntity = (JSONObject) jsonEntity;
77 Iterator<?> keys = jsonObjectEntity.keys();
78 while (keys.hasNext()) {
79 String key = (String) keys.next();
80 var value = jsonObjectEntity.get(key);
81 String xpath = parentName +"."+ key;
82
83
84 if (value instanceof JSONArray || value instanceof JSONObject) {
85 attributesXPath.addAll(JsonUtil.createEntries(value, xpath, parentXPath));
86 } else if (value instanceof String) {
87
88 SimpleEntry<String, String> stringValue = new SimpleEntry<>(xpath, (String) value);
89 attributesXPath.add(stringValue);
90
91 if (parentXPath == null) {
92 jsonObjectEntity.put(key, value.toString().replaceAll(Pattern.quote(InjectionModel.STAR) +"$", StringUtils.EMPTY));
93 } else if (stringValue.equals(parentXPath)) {
94 jsonObjectEntity.put(key, value + InjectionModel.STAR);
95 }
96 }
97 }
98 }
99
100 public boolean testJsonParam(AbstractMethodInjection methodInjection, SimpleEntry<String, String> paramStar) {
101 var hasFoundInjection = false;
102
103
104 paramStar.setValue(paramStar.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY));
105
106
107 Object jsonEntity = JsonUtil.getJson(paramStar.getValue());
108
109
110 List<SimpleEntry<String, String>> attributesJson = JsonUtil.createEntries(jsonEntity, "root", null);
111
112
113 for (SimpleEntry<String, String> parentXPath: attributesJson) {
114 JsonUtil.createEntries(jsonEntity, "root", null);
115 JsonUtil.createEntries(jsonEntity, "root", parentXPath);
116
117 paramStar.setValue(jsonEntity.toString());
118
119 try {
120 LOGGER.log(
121 LogLevelUtil.CONSOLE_INFORM,
122 "{} JSON {}={} with {}",
123 () -> I18nUtil.valueByKey("LOG_CHECKING"),
124 parentXPath::getKey,
125 () -> parentXPath.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY),
126 methodInjection::name
127 );
128
129
130
131 hasFoundInjection = this.injectionModel.getMediatorStrategy().testStrategies(paramStar);
132
133
134 break;
135 } catch (JSqlException e) {
136
137 LOGGER.log(
138 LogLevelUtil.CONSOLE_ERROR,
139 String.format(
140 "No injection found for JSON %s parameter %s=%s",
141 methodInjection.name(),
142 parentXPath.getKey(),
143 parentXPath.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY)
144 )
145 );
146 } finally {
147
148
149 methodInjection.getParams()
150 .forEach(e -> e.setValue(
151 e.getValue().replaceAll(Pattern.quote(InjectionModel.STAR) +"$", StringUtils.EMPTY)
152 ));
153
154
155 if (!hasFoundInjection) {
156 paramStar.setValue(
157 paramStar.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY)
158 );
159 }
160 }
161 }
162 return hasFoundInjection;
163 }
164 }