package org.joget.plugin.property.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.joget.commons.util.LogUtil;
import org.joget.commons.util.SecurityUtil;
import org.joget.commons.util.StringUtil;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* Utility method used to deal with Plugin Properties Options values (JSON format)
*
*/
public class PropertyUtil {
public final static String PASSWORD_PROTECTED_VALUE = "****SECURE_VALUE****-";
public final static String TYPE_PASSWORD = "password";
public final static String TYPE_ELEMENT_SELECT = "elementselect";
/**
* Parses default properties string (JSON format) from Plugin Properties
* Options (JSON format)
* @param json
* @return
*/
public static String getDefaultPropertyValues(String json) {
try {
JSONArray pages = new JSONArray(json);
JSONObject values = new JSONObject();
//loop page
for (int i = 0; i < pages.length(); i++) {
JSONObject page = (JSONObject) pages.get(i);
if (page.has("properties")) {
//loop properties
JSONArray properties = (JSONArray) page.get("properties");
for (int j = 0; j < properties.length(); j++) {
JSONObject property = (JSONObject) properties.get(j);
if (property.has("value")) {
values.put(property.getString("name"), property.get("value"));
}
}
}
}
return values.toString();
} catch (Exception ex) {
LogUtil.error("PropertyUtil", ex, json);
}
return "{}";
}
/**
* Parses the Plugin Properties Options values (JSON format) into a properties
* map
* @param json
* @return
*/
public static Map<String, Object> getPropertiesValueFromJson(String json) {
try {
if (json != null) {
json = json.replaceAll("\n","\\\\n").replaceAll("\r","\\\\r");
}
JSONObject obj = new JSONObject(json);
return getProperties(obj);
} catch (Exception e) {
LogUtil.error(PropertyUtil.class.getName(), e, e.getMessage());
}
return new HashMap<String, Object>();
}
/**
* Convenient method used by system to parses a JSON object in to a map
* @param obj
* @return
*/
public static Map<String, Object> getProperties(JSONObject obj) {
Map<String, Object> properties = new HashMap<String, Object>();
try {
if (obj != null) {
Iterator keys = obj.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
if (!obj.isNull(key)) {
Object value = obj.get(key);
if (value instanceof JSONArray) {
properties.put(key, getProperties((JSONArray) value));
} else if (value instanceof JSONObject) {
properties.put(key, getProperties((JSONObject) value));
} else {
String stringValue = obj.getString(key);
if ("{}".equals(stringValue)) {
properties.put(key, new HashMap<String, Object>());
} else {
properties.put(key, stringValue);
}
}
} else {
properties.put(key, "");
}
}
}
} catch (Exception e) {
}
return properties;
}
private static Object[] getProperties(JSONArray arr) throws Exception {
Collection<Object> array = new ArrayList<Object>();
if (arr != null && arr.length() > 0) {
for (int i = 0; i < arr.length(); i++) {
Object value = arr.get(i);
if (value != null) {
if (value instanceof JSONArray) {
array.add(getProperties((JSONArray) value));
} else if (value instanceof JSONObject) {
array.add(getProperties((JSONObject) value));
} else if (value instanceof String) {
array.add(value);
}
}
}
}
return array.toArray();
}
/**
* Convenient method used by system to hide secure values in Plugin Properties
* Options values (JSON format)
* @param json
* @return
*/
public static String propertiesJsonLoadProcessing(String json) {
//parse content
if (json != null && json.contains(SecurityUtil.ENVELOPE)) {
Pattern pattern = Pattern.compile(SecurityUtil.ENVELOPE + "((?!" + SecurityUtil.ENVELOPE + ").)*" + SecurityUtil.ENVELOPE);
Matcher matcher = pattern.matcher(json);
Set<String> sList = new HashSet<String>();
while (matcher.find()) {
sList.add(matcher.group(0));
}
try {
if (!sList.isEmpty()) {
int count = 0;
for (String s : sList) {
json = json.replaceAll(StringUtil.escapeRegex(s), SecurityUtil.ENVELOPE + PASSWORD_PROTECTED_VALUE + count + SecurityUtil.ENVELOPE);
count++;
}
}
} catch (Exception ex) {
LogUtil.error(PropertyUtil.class.getName(), ex, "");
}
}
return json;
}
/**
* Convenient method used by system to reverse the replaced/hided secure values in Plugin Properties
* Options values (JSON format)
* @param oldJson
* @param newJson
* @return
*/
public static String propertiesJsonStoreProcessing(String oldJson, String newJson) {
Map<String, String> passwordProperty = new HashMap<String, String>();
if (oldJson != null && !oldJson.isEmpty() && oldJson.contains(SecurityUtil.ENVELOPE)) {
Pattern pattern = Pattern.compile(SecurityUtil.ENVELOPE + "((?!" + SecurityUtil.ENVELOPE + ").)*" + SecurityUtil.ENVELOPE);
Matcher matcher = pattern.matcher(oldJson);
Set<String> sList = new HashSet<String>();
while (matcher.find()) {
sList.add(matcher.group(0));
}
if (!sList.isEmpty()) {
int count = 0;
for (String s : sList) {
passwordProperty.put(SecurityUtil.ENVELOPE + PASSWORD_PROTECTED_VALUE + count + SecurityUtil.ENVELOPE, s);
count++;
}
}
}
if (newJson != null && !newJson.isEmpty() && (newJson.contains(SecurityUtil.ENVELOPE) || newJson.contains(PASSWORD_PROTECTED_VALUE))) {
Pattern pattern = Pattern.compile(SecurityUtil.ENVELOPE + "((?!" + SecurityUtil.ENVELOPE + ").)*" + SecurityUtil.ENVELOPE);
Matcher matcher = pattern.matcher(newJson);
Set<String> sList = new HashSet<String>();
while (matcher.find()) {
sList.add(matcher.group(0));
}
Pattern pattern2 = Pattern.compile("\"("+StringUtil.escapeRegex(PASSWORD_PROTECTED_VALUE)+"[^\"]*)\"");
Matcher matcher2 = pattern2.matcher(newJson);
while (matcher2.find()) {
sList.add(SecurityUtil.ENVELOPE + matcher2.group(1) + SecurityUtil.ENVELOPE);
newJson = newJson.replaceAll(StringUtil.escapeRegex(matcher2.group(1)), SecurityUtil.ENVELOPE + matcher2.group(1) + SecurityUtil.ENVELOPE);
}
//For datalist binder initialization (getBuilderDataColumnList)
if (newJson.startsWith(PASSWORD_PROTECTED_VALUE)) {
sList.add(SecurityUtil.ENVELOPE + newJson + SecurityUtil.ENVELOPE);
newJson = SecurityUtil.ENVELOPE + newJson + SecurityUtil.ENVELOPE;
}
try {
if (!sList.isEmpty()) {
for (String s : sList) {
if (s.contains(PASSWORD_PROTECTED_VALUE)) {
newJson = newJson.replaceAll(StringUtil.escapeRegex(s), passwordProperty.get(s));
} else {
String tempS = s.replaceAll(SecurityUtil.ENVELOPE, "");
tempS = SecurityUtil.encrypt(tempS);
newJson = newJson.replaceAll(StringUtil.escapeRegex(s), tempS);
}
}
}
} catch (Exception ex) {
LogUtil.error(PropertyUtil.class.getName(), ex, "");
}
}
return newJson;
}
}