Skip to content

Commit 19e3976

Browse files
Merge pull request #178 from contentstack/staging
DX | 01-04-2025 | Release
2 parents 19068dd + 91f22a3 commit 19e3976

13 files changed

+652
-206
lines changed

Diff for: CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# CHANGELOG
22

3+
## v2.1.0
4+
5+
### Date: 1-Apr-2025
6+
7+
- code vulnerabilities fixes
8+
- timeline feature implementation
9+
- snyk fixes
10+
311
## v2.0.3
412

513
### Date: 3-March-2025

Diff for: pom.xml

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>com.contentstack.sdk</groupId>
77
<artifactId>java</artifactId>
8-
<version>2.0.3</version>
8+
<version>2.1.0</version>
99
<packaging>jar</packaging>
1010
<name>contentstack-java</name>
1111
<description>Java SDK for Contentstack Content Delivery API</description>
@@ -20,23 +20,23 @@
2020
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
2121
<maven-javadoc-plugin.version>3.4.1</maven-javadoc-plugin.version>
2222
<dotenv-source.version>3.0.0</dotenv-source.version>
23-
<rxjava-source.version>3.1.9</rxjava-source.version>
23+
<rxjava-source.version>3.1.10</rxjava-source.version>
2424
<retrofit-source.version>2.11.0</retrofit-source.version>
2525
<loggin.version>5.0.0-alpha.11</loggin.version>
2626
<jococo-plugin.version>0.8.5</jococo-plugin.version>
27-
<lombok-source.version>1.18.34</lombok-source.version>
28-
<junit-jupiter.version>5.10.1</junit-jupiter.version>
27+
<lombok-source.version>1.18.36</lombok-source.version>
28+
<junit-jupiter.version>5.11.4</junit-jupiter.version>
2929
<junit-jupiter-engine.version>5.8.0-M1</junit-jupiter-engine.version>
3030
<gson.version>2.8.8</gson.version>
3131
<json-simple-version>1.1.1</json-simple-version>
3232
<maven-site-plugin.version>3.3</maven-site-plugin.version>
3333
<maven-gpg-plugin.version>1.5</maven-gpg-plugin.version>
3434
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
3535
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
36-
<json-version>20240303</json-version>
36+
<json-version>20250107</json-version>
3737
<jacoco-maven-plugin-version>0.8.7</jacoco-maven-plugin-version>
3838
<maven-release-plugin-version>2.5.3</maven-release-plugin-version>
39-
<contentstack-utils-version>1.2.7</contentstack-utils-version>
39+
<contentstack-utils-version>1.2.15</contentstack-utils-version>
4040
</properties>
4141

4242
<parent>
@@ -187,7 +187,7 @@
187187
<dependency>
188188
<groupId>com.fasterxml.jackson.core</groupId>
189189
<artifactId>jackson-databind</artifactId>
190-
<version>2.18.0</version>
190+
<version>2.18.2</version>
191191
</dependency>
192192
</dependencies>
193193

Diff for: src/main/java/com/contentstack/sdk/AssetLibrary.java

+46-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ protected void setStackInstance(@NotNull Stack stack) {
3131
this.headers = stack.headers;
3232
}
3333

34+
//Sanitization of keys
35+
private boolean isValidKey(String key) {
36+
return key.matches("^[a-zA-Z0-9_.]+$");
37+
}
38+
39+
//Sanitization of values
40+
private boolean isValidValue(Object value) {
41+
if(value instanceof String){
42+
return ((String) value).matches("^[a-zA-Z0-9_.\\-\\s]+$");
43+
}
44+
return true;
45+
}
46+
47+
//Sanitization of values list
48+
private boolean isValidValueList(Object[] values) {
49+
for (Object value : values) {
50+
if (value instanceof String) {
51+
if (!((String) value).matches("^[a-zA-Z0-9_.\\-\\s]+$")) {
52+
return false;
53+
}
54+
}
55+
}
56+
return true;
57+
}
58+
3459
/**
3560
* Sets header.
3661
*
@@ -151,7 +176,11 @@ public int getCount() {
151176
* </pre>
152177
*/
153178
public AssetLibrary addParam(@NotNull String paramKey, @NotNull Object paramValue) {
154-
urlQueries.put(paramKey, paramValue);
179+
if (isValidKey(paramKey) && isValidValue(paramValue)) {
180+
urlQueries.put(paramKey, paramValue);
181+
} else {
182+
logger.warning("Invalid key or value");
183+
}
155184
return this;
156185
}
157186

@@ -172,8 +201,12 @@ public AssetLibrary addParam(@NotNull String paramKey, @NotNull Object paramValu
172201
* </pre>
173202
*/
174203
public AssetLibrary removeParam(@NotNull String paramKey){
175-
if(urlQueries.has(paramKey)){
176-
urlQueries.remove(paramKey);
204+
if(isValidKey(paramKey)) {
205+
if(urlQueries.has(paramKey)){
206+
urlQueries.remove(paramKey);
207+
}
208+
} else {
209+
logger.warning("Invalid key");
177210
}
178211
return this;
179212
}
@@ -255,7 +288,9 @@ private HashMap<String, Object> getUrlParams(JSONObject urlQueriesJSON) {
255288
while (iter.hasNext()) {
256289
String key = iter.next();
257290
Object value = urlQueriesJSON.opt(key);
258-
hashMap.put(key, value);
291+
if(isValidKey(key) && isValidValue(value)) {
292+
hashMap.put(key, value);
293+
}
259294
}
260295
}
261296
return hashMap;
@@ -311,9 +346,13 @@ public enum ORDERBY {
311346
}
312347

313348
public AssetLibrary where(String key, String value) {
314-
JSONObject queryParams= new JSONObject();
315-
queryParams.put(key,value);
316-
urlQueries.put("query", queryParams);
349+
if(isValidKey(key) && isValidValue(value)){
350+
JSONObject queryParams = new JSONObject();
351+
queryParams.put(key,value);
352+
urlQueries.put("query", queryParams);
353+
} else {
354+
throw new IllegalArgumentException("Invalid key or value");
355+
}
317356
return this;
318357
}
319358

Diff for: src/main/java/com/contentstack/sdk/AssetsModel.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ class AssetsModel {
2020
*/
2121
public AssetsModel(JSONObject response) {
2222
JSONArray listResponse = null;
23-
Object rawAssets = response.get("assets"); // Get assets
23+
Object rawAssets = response.opt("assets"); // Get assets
2424
if (rawAssets instanceof List) { // Check if it's an ArrayList
2525
List<?> assetsList = (List<?>) rawAssets;
2626
listResponse = new JSONArray(assetsList); // Convert to JSONArray
27+
} else if (rawAssets != null) {
28+
throw new IllegalArgumentException("Invalid type for 'assets' key: " + rawAssets.getClass().getName());
2729
}
2830
if (listResponse != null) {
2931
listResponse.forEach(model -> {

Diff for: src/main/java/com/contentstack/sdk/CSConnectionRequest.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public void setParams(Object... objects) {
8383
}
8484

8585
@Override
86-
public void sendRequest() {
86+
public synchronized void sendRequest() {
8787
CSHttpConnection connection = new CSHttpConnection(urlToCall, this);
8888
connection.setController(controller);
8989
connection.setHeaders(header);
@@ -99,7 +99,7 @@ public void sendRequest() {
9999
}
100100

101101
@Override
102-
public void onRequestFailed(JSONObject error, int statusCode, ResultCallBack callBackObject) {
102+
public synchronized void onRequestFailed(JSONObject error, int statusCode, ResultCallBack callBackObject) {
103103
Error errResp = new Error();
104104
if (error.has(ERROR_MESSAGE)) {
105105
String errMsg = error.optString(ERROR_MESSAGE);
@@ -119,7 +119,7 @@ public void onRequestFailed(JSONObject error, int statusCode, ResultCallBack cal
119119
}
120120

121121
@Override
122-
public void onRequestFinished(CSHttpConnection request) {
122+
public synchronized void onRequestFinished(CSHttpConnection request) {
123123
JSONObject jsonResponse = request.getResponse();
124124
if (request.getController().equalsIgnoreCase(Constants.QUERYOBJECT)) {
125125
EntriesModel model = new EntriesModel(jsonResponse);

Diff for: src/main/java/com/contentstack/sdk/Config.java

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public class Config {
3131
protected Proxy proxy = null;
3232
protected String[] earlyAccess = null;
3333
protected ConnectionPool connectionPool = new ConnectionPool();
34+
public String releaseId;
35+
public String previewTimestamp;
36+
3437

3538
protected List<ContentstackPlugin> plugins = null;
3639

Diff for: src/main/java/com/contentstack/sdk/ContentTypesModel.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ public void setJSON(JSONObject responseJSON) {
2020
if (responseJSON != null) {
2121
String ctKey = "content_type";
2222
if (responseJSON.has(ctKey) && responseJSON.opt(ctKey) instanceof LinkedHashMap) {
23-
this.response = new JSONObject((LinkedHashMap<?, ?>) responseJSON.get(ctKey));
23+
try {
24+
this.response = new JSONObject((LinkedHashMap<?, ?>) responseJSON.get(ctKey));
25+
} catch (Exception e) {
26+
System.err.println("Error processing 'content_type': " + e.getMessage());
27+
}
2428
}
2529
String ctListKey = "content_types";
2630
if (responseJSON.has(ctListKey) && responseJSON.opt(ctListKey) instanceof ArrayList) {
31+
try {
2732
ArrayList<LinkedHashMap<?, ?>> contentTypes = (ArrayList) responseJSON.get(ctListKey);
2833
List<Object> objectList = new ArrayList<>();
2934
if (!contentTypes.isEmpty()) {
@@ -32,13 +37,18 @@ public void setJSON(JSONObject responseJSON) {
3237
// Convert LinkedHashMap to JSONObject
3338
JSONObject jsonModel = new JSONObject((LinkedHashMap<?, ?>) model);
3439
objectList.add(jsonModel);
40+
} else {
41+
System.err.println("Invalid type in 'content_types' list. Expected LinkedHashMap.");
3542
}
3643
});
3744
}
3845
this.response = new JSONArray(objectList);
3946
this.responseJSONArray = new JSONArray(objectList);
40-
}
47+
} catch (Exception e) {
48+
System.err.println("Error processing 'content_types': " + e.getMessage());
4149
}
50+
}
51+
}
4252
}
4353

4454
public Object getResponse() {

Diff for: src/main/java/com/contentstack/sdk/EntryModel.java

+40-19
Original file line numberDiff line numberDiff line change
@@ -46,29 +46,47 @@ public EntryModel(JSONObject response) {
4646
}
4747

4848
if (this.jsonObject.has(UID_KEY)) {
49-
this.uid = (String) this.jsonObject.opt(UID_KEY);
49+
this.uid = this.jsonObject.optString(UID_KEY, null);
5050
}
5151
if (this.jsonObject.has(TITLE_KEY)) {
52-
this.title = (String) this.jsonObject.opt(TITLE_KEY);
52+
this.title = this.jsonObject.optString(TITLE_KEY, null);
5353
}
5454
if (this.jsonObject.has(LOCALE_KEY)) {
55-
this.language = (String) this.jsonObject.opt(LOCALE_KEY);
55+
this.language = this.jsonObject.optString(LOCALE_KEY,null);
5656
}
5757
if (this.jsonObject.has(URL_KEY)) {
58-
this.url = (String) this.jsonObject.opt(URL_KEY);
58+
this.url = this.jsonObject.optString(URL_KEY,null);
5959
}
6060
if (this.jsonObject.has("description")) {
61-
this.description = this.jsonObject.opt("description");
62-
}
63-
this.images = (JSONArray) this.jsonObject.opt("images");
64-
this.isDirectory = (Boolean) this.jsonObject.opt("is_dir");
65-
this.updatedAt = (String) this.jsonObject.opt("updated_at");
66-
this.updatedBy = (String) this.jsonObject.opt("updated_by");
67-
this.createdAt = (String) this.jsonObject.opt("created_at");
68-
this.createdBy = (String) this.jsonObject.opt("created_by");
69-
this.locale = (String) this.jsonObject.opt(LOCALE_KEY);
70-
this.inProgress = (Boolean) this.jsonObject.opt("_in_progress");
71-
this.version = this.jsonObject.opt("_version") != null ? (int) this.jsonObject.opt("_version") : 1;
61+
this.description = this.jsonObject.optString("description");
62+
}
63+
if(this.jsonObject.has("images") && this.jsonObject.opt("images") instanceof JSONArray) {
64+
this.images = this.jsonObject.optJSONArray("images");
65+
}
66+
if(this.jsonObject.has("is_dir") && this.jsonObject.opt("is_dir") instanceof Boolean) {
67+
this.isDirectory = this.jsonObject.optBoolean("is_dir");
68+
}
69+
if(this.jsonObject.has("updated_at")) {
70+
this.updatedAt = this.jsonObject.optString("updated_at");
71+
}
72+
if(this.jsonObject.has("updated_by")) {
73+
this.updatedBy = this.jsonObject.optString("updated_by");
74+
}
75+
if(this.jsonObject.has("created_at")) {
76+
this.createdAt = this.jsonObject.optString("created_at");
77+
}
78+
if(this.jsonObject.has("created_by")) {
79+
this.createdBy = this.jsonObject.optString("created_by");
80+
}
81+
if(this.jsonObject.has(LOCALE_KEY)) {
82+
this.locale = this.jsonObject.optString(LOCALE_KEY);
83+
}
84+
if(this.jsonObject.has("_in_progress") && this.jsonObject.opt("_in_progress") instanceof Boolean) {
85+
this.inProgress = this.jsonObject.optBoolean("_in_progress");
86+
}
87+
if(this.jsonObject.has("_version") && this.jsonObject.opt("_version") instanceof Integer) {
88+
this.version = this.jsonObject.optInt("_version",1);
89+
}
7290
if (this.jsonObject.has(PUBLISH_DETAIL_KEY)) {
7391
parsePublishDetail();
7492
}
@@ -77,12 +95,15 @@ public EntryModel(JSONObject response) {
7795

7896
private void parsePublishDetail() {
7997
if (this.jsonObject.opt(PUBLISH_DETAIL_KEY) instanceof JSONObject) {
80-
this.publishDetails = (JSONObject) this.jsonObject.opt(PUBLISH_DETAIL_KEY);
81-
this.environment = this.publishDetails.optString("environment");
82-
this.time = this.publishDetails.optString("time");
83-
this.user = this.publishDetails.optString("user");
98+
this.publishDetails = this.jsonObject.optJSONObject(PUBLISH_DETAIL_KEY);
99+
if(this.publishDetails != null) {
100+
this.environment = this.publishDetails.optString("environment");
101+
this.time = this.publishDetails.optString("time");
102+
this.user = this.publishDetails.optString("user");
103+
}
84104
}
85105
this.metadata = new HashMap<>();
86106
this.metadata.put(PUBLISH_DETAIL_KEY, this.publishDetails);
87107
}
88108
}
109+

0 commit comments

Comments
 (0)