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 string) {
63 SimpleEntry<String, String> stringValue = new SimpleEntry<>(xpath, string);
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 string) {
87 SimpleEntry<String, String> stringValue = new SimpleEntry<>(xpath, string);
88 attributesXPath.add(stringValue);
89
90 if (parentXPath == null) {
91 jsonObjectEntity.put(key, value.toString().replaceAll(Pattern.quote(InjectionModel.STAR) +"$", StringUtils.EMPTY));
92 } else if (stringValue.equals(parentXPath)) {
93 jsonObjectEntity.put(key, value + InjectionModel.STAR);
94 }
95 }
96 }
97 }
98
99 public boolean testJsonParam(AbstractMethodInjection methodInjection, SimpleEntry<String, String> paramStar) {
100 var hasFoundInjection = false;
101
102
103 paramStar.setValue(paramStar.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY));
104
105
106 Object jsonEntity = JsonUtil.getJson(paramStar.getValue());
107
108
109 List<SimpleEntry<String, String>> attributesJson = JsonUtil.createEntries(jsonEntity, "root", null);
110
111
112 for (SimpleEntry<String, String> parentXPath: attributesJson) {
113 JsonUtil.createEntries(jsonEntity, "root", null);
114 JsonUtil.createEntries(jsonEntity, "root", parentXPath);
115
116 paramStar.setValue(jsonEntity.toString());
117
118 try {
119 LOGGER.log(
120 LogLevelUtil.CONSOLE_INFORM,
121 "{} JSON {}={} with {}",
122 () -> I18nUtil.valueByKey("LOG_CHECKING"),
123 parentXPath::getKey,
124 () -> parentXPath.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY),
125 methodInjection::name
126 );
127
128
129
130 hasFoundInjection = this.injectionModel.getMediatorStrategy().testStrategies(paramStar);
131
132
133 break;
134 } catch (JSqlException e) {
135
136 LOGGER.log(
137 LogLevelUtil.CONSOLE_ERROR,
138 String.format(
139 "No injection found for JSON %s parameter %s=%s",
140 methodInjection.name(),
141 parentXPath.getKey(),
142 parentXPath.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY)
143 )
144 );
145 } finally {
146
147
148 methodInjection.getParams().forEach(e -> e.setValue(
149 e.getValue().replaceAll(Pattern.quote(InjectionModel.STAR) +"$", StringUtils.EMPTY)
150 ));
151
152
153 if (!hasFoundInjection) {
154 paramStar.setValue(
155 paramStar.getValue().replace(InjectionModel.STAR, StringUtils.EMPTY)
156 );
157 }
158 }
159 }
160 return hasFoundInjection;
161 }
162 }