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