createReleaseFiles(XMLConfiguration zapVersionsXml) {
40 | return Collections.singletonList(
41 | new ReleaseFile(
42 | "Weekly Cross Platform Package",
43 | "cp-p",
44 | toMegaBytes(zapVersionsXml.getString(DAILY_SIZE_ELEMENT)),
45 | zapVersionsXml.getString(DAILY_URL_ELEMENT)));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/HandleMainRelease.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2020 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import org.gradle.api.file.RegularFileProperty;
23 | import org.gradle.api.tasks.InputFile;
24 | import org.zaproxy.gradle.ReleaseState.VersionChange;
25 |
26 | /**
27 | * Task that handles a main release, if any.
28 | *
29 | * Sends a repository dispatch to release the main Docker images.
30 | */
31 | public abstract class HandleMainRelease extends SendRepositoryDispatch {
32 |
33 | @InputFile
34 | public abstract RegularFileProperty getReleaseState();
35 |
36 | @Override
37 | void send() {
38 | ReleaseState releaseState = ReleaseState.read(getReleaseState().getAsFile().get());
39 | if (isNewMainRelease(releaseState)) {
40 | super.send();
41 | }
42 | }
43 |
44 | private static boolean isNewMainRelease(ReleaseState releaseState) {
45 | VersionChange mainRelease = releaseState.getMainRelease();
46 | return mainRelease != null && mainRelease.isNewVersion();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/HandleWeeklyRelease.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2020 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import org.gradle.api.file.RegularFileProperty;
23 | import org.gradle.api.tasks.InputFile;
24 | import org.zaproxy.gradle.ReleaseState.VersionChange;
25 |
26 | /**
27 | * Task that handles a weekly release, if any.
28 | *
29 | *
Sends a repository dispatch to release the Docker weekly image.
30 | */
31 | public abstract class HandleWeeklyRelease extends SendRepositoryDispatch {
32 |
33 | @InputFile
34 | public abstract RegularFileProperty getReleaseState();
35 |
36 | @Override
37 | void send() {
38 | ReleaseState releaseState = ReleaseState.read(getReleaseState().getAsFile().get());
39 | if (isNewWeeklyRelease(releaseState)) {
40 | super.send();
41 | }
42 | }
43 |
44 | private static boolean isNewWeeklyRelease(ReleaseState releaseState) {
45 | VersionChange weeklyRelease = releaseState.getWeeklyRelease();
46 | return weeklyRelease != null && weeklyRelease.isNewVersion();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/ReleaseData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2020 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.IOException;
23 | import java.io.UncheckedIOException;
24 | import java.io.Writer;
25 | import java.nio.file.Files;
26 | import java.nio.file.Path;
27 | import java.util.ArrayList;
28 | import java.util.List;
29 | import org.snakeyaml.engine.v2.api.Dump;
30 | import org.snakeyaml.engine.v2.api.DumpSettings;
31 | import org.snakeyaml.engine.v2.api.RepresentToNode;
32 | import org.snakeyaml.engine.v2.api.StreamDataWriter;
33 | import org.snakeyaml.engine.v2.common.FlowStyle;
34 | import org.snakeyaml.engine.v2.nodes.MappingNode;
35 | import org.snakeyaml.engine.v2.nodes.Node;
36 | import org.snakeyaml.engine.v2.nodes.NodeTuple;
37 | import org.snakeyaml.engine.v2.nodes.ScalarNode;
38 | import org.snakeyaml.engine.v2.nodes.Tag;
39 | import org.snakeyaml.engine.v2.representer.StandardRepresenter;
40 |
41 | class ReleaseData {
42 |
43 | private static final DumpSettings SETTINGS =
44 | DumpSettings.builder().setDefaultFlowStyle(FlowStyle.BLOCK).build();
45 | private static final Dump DUMP = new Dump(SETTINGS, new ReleaseFileRepresenter(SETTINGS));
46 |
47 | private final List releaseFiles;
48 |
49 | public ReleaseData(List releaseFiles) {
50 | this.releaseFiles = new ArrayList<>(releaseFiles);
51 | }
52 |
53 | public void save(Path file, String comment) throws IOException {
54 | try (Writer writer = Files.newBufferedWriter(file)) {
55 | writer.write(comment);
56 | writer.write("\n---\n");
57 | DUMP.dump(releaseFiles, new StreamDataWriterAdapter(writer));
58 | } catch (UncheckedIOException e) {
59 | throw new IOException("Failed to save to: " + file, e.getCause());
60 | }
61 | }
62 |
63 | static class ReleaseFile {
64 | private final String name;
65 | private final String id;
66 | private final String size;
67 | private final String link;
68 |
69 | ReleaseFile(String name, String id, String size, String link) {
70 | this.name = name;
71 | this.id = id;
72 | this.size = size;
73 | this.link = link;
74 | }
75 | }
76 |
77 | private static class ReleaseFileRepresenter extends StandardRepresenter {
78 |
79 | ReleaseFileRepresenter(DumpSettings settings) {
80 | super(settings);
81 | this.representers.put(ReleaseFile.class, new RepresentReleaseFile());
82 | }
83 |
84 | private class RepresentReleaseFile implements RepresentToNode {
85 |
86 | @Override
87 | public Node representData(Object data) {
88 | ReleaseFile releaseFile = (ReleaseFile) data;
89 | List nodeData = new ArrayList<>(4);
90 | MappingNode node =
91 | new MappingNode(Tag.MAP, nodeData, settings.getDefaultFlowStyle());
92 | nodeData.add(new NodeTuple(string("name"), string(releaseFile.name)));
93 | nodeData.add(new NodeTuple(string("id"), string(releaseFile.id)));
94 | nodeData.add(new NodeTuple(string("size"), string(releaseFile.size)));
95 | nodeData.add(new NodeTuple(string("link"), string(releaseFile.link)));
96 | return node;
97 | }
98 |
99 | private ScalarNode string(String value) {
100 | return new ScalarNode(Tag.STR, value, settings.getDefaultScalarStyle());
101 | }
102 | }
103 | }
104 |
105 | private static class StreamDataWriterAdapter implements StreamDataWriter {
106 |
107 | private final Writer writer;
108 |
109 | StreamDataWriterAdapter(Writer writer) {
110 | this.writer = writer;
111 | }
112 |
113 | @Override
114 | public void write(String str) {
115 | processIoAction(() -> writer.write(str));
116 | }
117 |
118 | @Override
119 | public void write(String str, int off, int len) {
120 | processIoAction(() -> writer.write(str, off, len));
121 | }
122 |
123 | @Override
124 | public void flush() {
125 | processIoAction(writer::flush);
126 | }
127 |
128 | private static void processIoAction(IoAction action) {
129 | try {
130 | action.apply();
131 | } catch (IOException e) {
132 | throw new UncheckedIOException(e);
133 | }
134 | }
135 | }
136 |
137 | private interface IoAction {
138 | void apply() throws IOException;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/ReleaseState.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2020 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import com.fasterxml.jackson.annotation.JsonInclude;
23 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
24 | import com.fasterxml.jackson.annotation.JsonProperty;
25 | import com.fasterxml.jackson.databind.ObjectMapper;
26 | import com.fasterxml.jackson.databind.PropertyNamingStrategies;
27 | import com.fasterxml.jackson.databind.annotation.JsonNaming;
28 | import java.io.File;
29 | import java.io.IOException;
30 | import java.util.List;
31 |
32 | /** The release state computed from {@code ZapVersions.xml} files. */
33 | @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
34 | @JsonInclude(value = Include.NON_NULL)
35 | public class ReleaseState {
36 |
37 | @JsonProperty private VersionChange mainRelease;
38 | @JsonProperty private VersionChange weeklyRelease;
39 |
40 | @JsonProperty private List addOns;
41 |
42 | public ReleaseState() {}
43 |
44 | public VersionChange getMainRelease() {
45 | return mainRelease;
46 | }
47 |
48 | public void setMainRelease(VersionChange mainRelease) {
49 | this.mainRelease = mainRelease;
50 | }
51 |
52 | public VersionChange getWeeklyRelease() {
53 | return weeklyRelease;
54 | }
55 |
56 | public void setWeeklyRelease(VersionChange weeklyRelease) {
57 | this.weeklyRelease = weeklyRelease;
58 | }
59 |
60 | public void setAddOns(List addOns) {
61 | this.addOns = addOns;
62 | }
63 |
64 | public List getAddOns() {
65 | return addOns;
66 | }
67 |
68 | /**
69 | * Writes this {@code ReleaseState} to the given file.
70 | *
71 | * @param file the file to write the release state.
72 | * @throws TaskException if an error occurred while writing the release state.
73 | */
74 | public void write(File file) {
75 | try {
76 | new ObjectMapper().writeValue(file, this);
77 | } catch (IOException e) {
78 | throw new TaskException("Failed to write the release state: " + e.getMessage(), e);
79 | }
80 | }
81 |
82 | /**
83 | * Reads a {@code ReleaseState} from the given file.
84 | *
85 | * @param file the file with the release state.
86 | * @return a new {@code ReleaseState} with the contents from the file.
87 | * @throws TaskException if an error occurred while reading the release state.
88 | */
89 | public static ReleaseState read(File file) {
90 | try {
91 | return new ObjectMapper().readValue(file, ReleaseState.class);
92 | } catch (IOException e) {
93 | throw new TaskException("Failed to read the release state: " + e.getMessage(), e);
94 | }
95 | }
96 |
97 | @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
98 | @JsonInclude(value = Include.NON_EMPTY)
99 | public static class VersionChange {
100 |
101 | @JsonProperty private String previousVersion;
102 |
103 | @JsonProperty private String currentVersion;
104 |
105 | @JsonProperty private boolean newVersion;
106 |
107 | public VersionChange() {}
108 |
109 | public VersionChange(String previousVersion, String currentVersion) {
110 | this.previousVersion = previousVersion;
111 | this.currentVersion = currentVersion;
112 | this.newVersion = previousVersion == null || !previousVersion.equals(currentVersion);
113 | }
114 |
115 | public boolean isNewVersion() {
116 | return newVersion;
117 | }
118 |
119 | public String getPreviousVersion() {
120 | return previousVersion;
121 | }
122 |
123 | public void setPreviousVersion(String previousVersion) {
124 | this.previousVersion = previousVersion;
125 | }
126 |
127 | public String getCurrentVersion() {
128 | return currentVersion;
129 | }
130 |
131 | public void setCurrentVersion(String currentVersion) {
132 | this.currentVersion = currentVersion;
133 | }
134 | }
135 |
136 | @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
137 | @JsonInclude(value = Include.NON_EMPTY)
138 | public static class AddOnChange extends VersionChange {
139 |
140 | @JsonProperty private String id;
141 |
142 | public AddOnChange() {}
143 |
144 | public AddOnChange(String id, String previousVersion, String currentVersion) {
145 | super(previousVersion, currentVersion);
146 | this.id = id;
147 | }
148 |
149 | public String getId() {
150 | return id;
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/SendRepositoryDispatch.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2020 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import com.fasterxml.jackson.core.JsonProcessingException;
23 | import com.fasterxml.jackson.databind.ObjectMapper;
24 | import java.io.IOException;
25 | import java.io.OutputStream;
26 | import java.net.HttpURLConnection;
27 | import java.net.ProtocolException;
28 | import java.net.URI;
29 | import java.nio.charset.StandardCharsets;
30 | import java.util.Base64;
31 | import java.util.LinkedHashMap;
32 | import java.util.Map;
33 | import org.apache.commons.io.IOUtils;
34 | import org.gradle.api.DefaultTask;
35 | import org.gradle.api.provider.MapProperty;
36 | import org.gradle.api.provider.Property;
37 | import org.gradle.api.tasks.Input;
38 | import org.gradle.api.tasks.Optional;
39 | import org.gradle.api.tasks.TaskAction;
40 |
41 | /** A task that sends a {@code repository_dispatch} to a GitHub repo. */
42 | public abstract class SendRepositoryDispatch extends DefaultTask {
43 |
44 | private static final int EXPECTED_STATUS_CODE = HttpURLConnection.HTTP_NO_CONTENT;
45 | private static final int NO_STATUS_CODE = -1;
46 |
47 | @Input
48 | public abstract Property getGitHubUser();
49 |
50 | @Input
51 | public abstract Property getGitHubRepo();
52 |
53 | @Input
54 | public abstract Property getEventType();
55 |
56 | @Input
57 | @Optional
58 | public abstract MapProperty getClientPayload();
59 |
60 | @TaskAction
61 | void send() {
62 | HttpURLConnection connection = createConnection();
63 | writeRepositoryDispatch(connection);
64 |
65 | int statusCode = getStatusCode(connection);
66 | if (statusCode == EXPECTED_STATUS_CODE) {
67 | return;
68 | }
69 |
70 | if (statusCode == NO_STATUS_CODE) {
71 | throw new TaskException("Unable to get a response.");
72 | }
73 |
74 | StringBuilder errorMessage = new StringBuilder();
75 | errorMessage.append(
76 | String.format(
77 | "Repository dispatch was not successful, expected status code %s received %s.",
78 | EXPECTED_STATUS_CODE, statusCode));
79 |
80 | String response = readResponse(connection);
81 | if (response != null && !response.isEmpty()) {
82 | errorMessage.append("\nResponse:\n").append(response);
83 | }
84 | throw new TaskException(errorMessage.toString());
85 | }
86 |
87 | private HttpURLConnection createConnection() {
88 | String url =
89 | String.format("https://api.github.com/repos/%s/dispatches", getGitHubRepo().get());
90 | HttpURLConnection connection;
91 | try {
92 | connection = (HttpURLConnection) new URI(url).toURL().openConnection();
93 | } catch (Exception e) {
94 | throw new TaskException("Failed to create the connection:", e);
95 | }
96 | connection.setDoOutput(true);
97 | connection.setUseCaches(false);
98 | try {
99 | connection.setRequestMethod("POST");
100 | } catch (ProtocolException e) {
101 | throw new TaskException("Failed to create the connection:", e);
102 | }
103 | connection.setRequestProperty("Accept", "application/vnd.github.v3+json");
104 | connection.setRequestProperty("Content-Type", "application/json");
105 |
106 | GitHubUser user = getGitHubUser().get();
107 | String userName = user.getName();
108 | String token = user.getAuthToken();
109 | byte[] usernameAuthToken = (userName + ":" + token).getBytes(StandardCharsets.UTF_8);
110 | String authorization = "Basic " + Base64.getEncoder().encodeToString(usernameAuthToken);
111 | connection.setRequestProperty("Authorization", authorization);
112 |
113 | return connection;
114 | }
115 |
116 | private void writeRepositoryDispatch(HttpURLConnection connection) {
117 | byte[] repositoryDispatch;
118 | try {
119 | repositoryDispatch = createRepositoryDispatch();
120 | } catch (JsonProcessingException e) {
121 | throw new TaskException("Failed to create the request body:", e);
122 | }
123 |
124 | try (OutputStream os = connection.getOutputStream()) {
125 | os.write(repositoryDispatch);
126 | } catch (IOException e) {
127 | throw new TaskException("Failed to write the repository dispatch:", e);
128 | }
129 | }
130 |
131 | private byte[] createRepositoryDispatch() throws JsonProcessingException {
132 | Map repositoryDispatch = new LinkedHashMap<>();
133 | repositoryDispatch.put("event_type", getEventType().get());
134 |
135 | Map clientPayload = getClientPayload().getOrNull();
136 | if (clientPayload != null && !clientPayload.isEmpty()) {
137 | repositoryDispatch.put("client_payload", clientPayload);
138 | }
139 |
140 | return new ObjectMapper().writeValueAsBytes(repositoryDispatch);
141 | }
142 |
143 | private int getStatusCode(HttpURLConnection connection) {
144 | try {
145 | return connection.getResponseCode();
146 | } catch (IOException e) {
147 | getLogger()
148 | .warn("Failed to read the repository dispatch status code: " + e.getMessage());
149 | }
150 | return NO_STATUS_CODE;
151 | }
152 |
153 | private String readResponse(HttpURLConnection connection) {
154 | try {
155 | return IOUtils.toString(connection.getErrorStream(), StandardCharsets.UTF_8);
156 | } catch (IOException e) {
157 | getLogger().warn("Failed to read the repository dispatch response: " + e.getMessage());
158 | }
159 | return null;
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/TaskException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2020 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | /** An exception that occurred while running a task. */
23 | public class TaskException extends RuntimeException {
24 |
25 | private static final long serialVersionUID = 1L;
26 |
27 | public TaskException(String message) {
28 | super(message);
29 | }
30 |
31 | public TaskException(String message, Throwable cause) {
32 | super(message, cause);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/TaskUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.net.URI;
25 | import java.net.URL;
26 | import java.nio.charset.StandardCharsets;
27 | import java.nio.file.Files;
28 | import java.nio.file.Path;
29 | import java.util.Set;
30 | import java.util.stream.Collectors;
31 | import org.apache.commons.codec.digest.DigestUtils;
32 | import org.gradle.api.Task;
33 | import org.gradle.api.file.RegularFileProperty;
34 |
35 | final class TaskUtils {
36 |
37 | private static final String COMMENT_LINE = "#";
38 |
39 | private TaskUtils() {}
40 |
41 | private static final String HTTPS_SCHEME = "HTTPS";
42 | private static final String ADD_ON_EXTENSION = ".zap";
43 |
44 | static Path downloadAddOn(Task task, String urlString) throws Exception {
45 | return downloadAddOn(task, urlString, task.getTemporaryDir().toPath());
46 | }
47 |
48 | static Path downloadAddOn(Task task, String urlString, Path outputDir) throws Exception {
49 | return downloadFile(task, urlString, outputDir.resolve(extractFileName(urlString)));
50 | }
51 |
52 | static Path downloadFile(Task task, String urlString, Path outputFile) throws Exception {
53 | URL url = new URI(urlString).toURL();
54 | if (!HTTPS_SCHEME.equalsIgnoreCase(url.getProtocol())) {
55 | throw new IllegalArgumentException(
56 | "The provided URL does not use HTTPS scheme: " + url.getProtocol());
57 | }
58 |
59 | if (Files.exists(outputFile)) {
60 | task.getLogger().info("File already exists at specified path, skipping download.");
61 | return outputFile;
62 | }
63 |
64 | try (InputStream in = url.openStream()) {
65 | Files.copy(in, outputFile);
66 | } catch (IOException e) {
67 | throw new IOException("Failed to download the file: " + e.getMessage(), e);
68 | }
69 | task.getLogger().info("File downloaded to: " + outputFile);
70 | return outputFile;
71 | }
72 |
73 | private static String extractFileName(String url) {
74 | int idx = url.lastIndexOf("/");
75 | if (idx == -1) {
76 | throw new IllegalArgumentException(
77 | "The provided URL does not have a file name: " + url);
78 | }
79 | String fileName = url.substring(idx + 1);
80 | if (!fileName.endsWith(ADD_ON_EXTENSION)) {
81 | throw new IllegalArgumentException(
82 | "The provided URL does not have a file with zap extension: " + fileName);
83 | }
84 | return fileName;
85 | }
86 |
87 | static String calculateChecksum(Path file, String checksumAlgorithm, String expectedChecksum)
88 | throws IOException {
89 | String checksum = new DigestUtils(checksumAlgorithm).digestAsHex(file.toFile());
90 | if (expectedChecksum == null
91 | || expectedChecksum.isEmpty()
92 | || checksum.equals(expectedChecksum)) {
93 | return checksum;
94 | }
95 |
96 | throw new IllegalArgumentException(
97 | String.format(
98 | "Checksums do not match for: %s\nExpected:\n%s\nActual:\n%s",
99 | file, expectedChecksum, checksum));
100 | }
101 |
102 | static Set readAllowedAddOns(RegularFileProperty fileProperty) throws IOException {
103 | Path file = fileProperty.getAsFile().get().toPath();
104 | return Files.readAllLines(file, StandardCharsets.UTF_8).stream()
105 | .filter(s -> !s.startsWith(COMMENT_LINE) || !s.isEmpty())
106 | .collect(Collectors.toSet());
107 | }
108 |
109 | static boolean hasSecureScheme(URL url) {
110 | if (url == null) {
111 | return false;
112 | }
113 | return HTTPS_SCHEME.equalsIgnoreCase(url.getProtocol());
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/UpdateAddOnZapVersionsEntries.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2019 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.IOException;
23 | import java.net.URI;
24 | import java.net.URL;
25 | import java.nio.file.Files;
26 | import java.nio.file.Path;
27 | import java.time.LocalDate;
28 | import org.gradle.api.file.RegularFileProperty;
29 | import org.gradle.api.model.ObjectFactory;
30 | import org.gradle.api.provider.Property;
31 | import org.gradle.api.tasks.Input;
32 | import org.gradle.api.tasks.InputFile;
33 | import org.gradle.api.tasks.Optional;
34 | import org.gradle.api.tasks.TaskAction;
35 | import org.gradle.api.tasks.options.Option;
36 |
37 | /** A task that updates {@code ZapVersions.xml} files with an add-on. */
38 | public abstract class UpdateAddOnZapVersionsEntries extends AbstractUpdateZapVersionsEntries
39 | implements AddOnZapVersionsUpdater {
40 |
41 | private final Property fromUrl;
42 | private final Property downloadUrl;
43 | private final Property releaseDate;
44 |
45 | public UpdateAddOnZapVersionsEntries() {
46 | ObjectFactory objects = getProject().getObjects();
47 | this.fromUrl = objects.property(String.class);
48 | this.downloadUrl = objects.property(String.class);
49 | this.downloadUrl.set(fromUrl);
50 | this.releaseDate = objects.property(LocalDate.class);
51 | this.releaseDate.set(LocalDate.now());
52 |
53 | setDescription("Updates ZapVersions.xml files with an add-on.");
54 | }
55 |
56 | @Option(option = "file", description = "The file system path to the add-on.")
57 | public void setFile(String path) {
58 | getFromFile().set(getProject().file(path));
59 | }
60 |
61 | @InputFile
62 | @Optional
63 | public abstract RegularFileProperty getFromFile();
64 |
65 | @Option(option = "url", description = "The URL to the add-on.")
66 | public void setUrl(String url) {
67 | fromUrl.set(url);
68 | }
69 |
70 | @Input
71 | @Optional
72 | public Property getFromUrl() {
73 | return fromUrl;
74 | }
75 |
76 | @Option(option = "downloadUrl", description = "The URL from where the add-on is downloaded.")
77 | public void setDownloadUrl(String url) {
78 | downloadUrl.set(url);
79 | }
80 |
81 | @Input
82 | @Optional
83 | public Property getDownloadUrl() {
84 | return downloadUrl;
85 | }
86 |
87 | @Option(option = "releaseDate", description = "The release date.")
88 | public void setReleaseDate(String date) {
89 | releaseDate.set(LocalDate.parse(date));
90 | }
91 |
92 | @Input
93 | public Property getReleaseDate() {
94 | return releaseDate;
95 | }
96 |
97 | @TaskAction
98 | public void update() throws Exception {
99 | if (getFromFile().isPresent()) {
100 | if (fromUrl.isPresent()) {
101 | throw new IllegalArgumentException(
102 | "Only one of the properties, URL or file, can be set at the same time.");
103 | }
104 |
105 | if (!downloadUrl.isPresent()) {
106 | throw new IllegalArgumentException(
107 | "The download URL must be provided when specifying the file.");
108 | }
109 | } else if (!fromUrl.isPresent()) {
110 | throw new IllegalArgumentException(
111 | "Either one of the properties, URL or file, must be set.");
112 | }
113 |
114 | if (downloadUrl.get().isEmpty()) {
115 | throw new IllegalArgumentException("The download URL must not be empty.");
116 | }
117 |
118 | try {
119 | URL url = new URI(downloadUrl.get()).toURL();
120 | if (!TaskUtils.hasSecureScheme(url)) {
121 | throw new IllegalArgumentException(
122 | "The provided download URL does not use HTTPS scheme: "
123 | + url.getProtocol());
124 | }
125 | } catch (Exception e) {
126 | throw new IllegalArgumentException(
127 | "Failed to parse the download URL: " + e.getMessage(), e);
128 | }
129 |
130 | updateAddOn(getAddOn(), getDownloadUrl().get(), getReleaseDate().get());
131 | }
132 |
133 | private Path getAddOn() throws Exception {
134 | if (getFromFile().isPresent()) {
135 | Path addOn = getFromFile().getAsFile().get().toPath();
136 | if (!Files.isRegularFile(addOn)) {
137 | throw new IllegalArgumentException(
138 | "The provided path does not exist or it's not a file: " + addOn);
139 | }
140 | return addOn;
141 | }
142 |
143 | return TaskUtils.downloadAddOn(this, fromUrl.get());
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/UpdateAndCreatePullRequestAddOnRelease.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.nio.file.Path;
23 | import java.time.LocalDate;
24 | import java.util.ArrayList;
25 | import java.util.List;
26 | import org.gradle.api.provider.Property;
27 | import org.gradle.api.tasks.Input;
28 | import org.gradle.api.tasks.options.Option;
29 |
30 | public abstract class UpdateAndCreatePullRequestAddOnRelease extends CreatePullRequest
31 | implements AddOnZapVersionsUpdater {
32 |
33 | private final Property envVar;
34 | private StringBuilder commitDescription;
35 |
36 | public UpdateAndCreatePullRequestAddOnRelease() {
37 | this.envVar = getProject().getObjects().property(String.class);
38 | this.commitDescription = new StringBuilder();
39 |
40 | getCommitSummary().set("Release add-on(s)");
41 | getCommitDescription().set(getProject().provider(commitDescription::toString));
42 |
43 | setDescription(
44 | "Updates ZapVersions and creates a pull request to release an add-on (or several).");
45 | }
46 |
47 | @Option(
48 | option = "envVar",
49 | description = "The name of the env var that has the add-on release data.")
50 | public void setEnvVar(String name) {
51 | getEnvVar().set(name);
52 | }
53 |
54 | @Input
55 | public Property getEnvVar() {
56 | return envVar;
57 | }
58 |
59 | @Override
60 | public void pullRequest() throws Exception {
61 | commitDescription.append("Release the following add-ons:");
62 |
63 | List releasedAddOns = new ArrayList<>();
64 | String data = System.getenv(getEnvVar().get());
65 | for (AddOnReleaseData.Release release : AddOnReleaseData.read(data).getAddOns()) {
66 | String downloadUrl = release.getUrl();
67 |
68 | Path addOn = TaskUtils.downloadAddOn(this, downloadUrl);
69 | calculateChecksum(addOn, release.getChecksum());
70 | updateAddOn(
71 | addOn,
72 | downloadUrl,
73 | LocalDate.now(),
74 | addOnEntry ->
75 | releasedAddOns.add(
76 | "\n - "
77 | + addOnEntry.getName()
78 | + " version "
79 | + addOnEntry.getVersion()));
80 | }
81 | releasedAddOns.stream().sorted().forEach(commitDescription::append);
82 |
83 | super.pullRequest();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/UpdateFlathubData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2025 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 | import java.nio.charset.StandardCharsets;
26 | import java.nio.file.Files;
27 | import java.nio.file.Path;
28 | import java.nio.file.StandardCopyOption;
29 | import java.time.LocalDate;
30 | import java.util.Iterator;
31 | import java.util.Optional;
32 | import java.util.regex.Matcher;
33 | import java.util.regex.Pattern;
34 | import java.util.zip.ZipEntry;
35 | import java.util.zip.ZipFile;
36 | import org.apache.commons.configuration.XMLConfiguration;
37 | import org.gradle.api.file.RegularFileProperty;
38 | import org.gradle.api.tasks.InputFile;
39 | import org.gradle.api.DefaultTask;
40 | import org.gradle.api.provider.Property;
41 | import org.gradle.api.tasks.Input;
42 | import org.gradle.api.tasks.TaskAction;
43 | import org.zaproxy.gradle.ReleaseState.VersionChange;
44 |
45 | public abstract class UpdateFlathubData extends DefaultTask {
46 |
47 | @InputFile
48 | public abstract RegularFileProperty getReleaseState();
49 |
50 | @InputFile
51 | public abstract RegularFileProperty getZapVersions();
52 |
53 | @Input
54 | public abstract Property getBaseDirectory();
55 |
56 | @TaskAction
57 | void executeTasks() throws Exception {
58 | ReleaseState releaseState = ReleaseState.read(getReleaseState().getAsFile().get());
59 | if (!isNewMainRelease(releaseState)) {
60 | return;
61 | }
62 |
63 | XMLConfiguration zapVersionsXml = new CustomXmlConfiguration();
64 | zapVersionsXml.load(getZapVersions().get().getAsFile());
65 |
66 | String version = zapVersionsXml.getString("core.version");
67 | String url = zapVersionsXml.getString("core.linux.url");
68 | String hash = zapVersionsXml.getString("core.linux.hash").split(":", 2)[1];
69 |
70 | Path repo = getBaseDirectory().get().toPath();
71 |
72 | updateAppData(repo, version);
73 | updateJson(repo, url, hash);
74 | }
75 |
76 | private static boolean isNewMainRelease(ReleaseState releaseState) {
77 | VersionChange mainRelease = releaseState.getMainRelease();
78 | return mainRelease != null && mainRelease.isNewVersion();
79 | }
80 |
81 | private static void updateAppData(Path dir, String version) throws IOException {
82 | Path file = dir.resolve("org.zaproxy.ZAP.appdata.xml");
83 | String contents = Files.readString(file);
84 |
85 | Matcher matcher = Pattern.compile("").matcher(contents);
86 | if (!matcher.find()) {
87 | throw new IOException("The XML entry release was not found in: " + file);
88 | }
89 | StringBuilder sb = new StringBuilder();
90 | matcher.appendReplacement(sb, "");
91 | matcher.appendTail(sb);
92 |
93 | Files.writeString(file, sb.toString());
94 | }
95 |
96 | private static void updateJson(Path dir, String url, String hash) throws IOException {
97 | Path file = dir.resolve("org.zaproxy.ZAP.json");
98 | String contents = Files.readString(file);
99 |
100 | Matcher matcher = Pattern.compile("url\": \"([^\\\"]+)\"").matcher(contents);
101 | if (!matcher.find()) {
102 | throw new IOException("The JSON url property was not found in: " + file);
103 | }
104 | StringBuilder sb = new StringBuilder();
105 | matcher.appendReplacement(sb, "url\": \"" + url + "\"");
106 | matcher.appendTail(sb);
107 |
108 | matcher = Pattern.compile("sha256\": \"([^\\\"]+)\"").matcher(sb.toString());
109 | if (!matcher.find()) {
110 | throw new IOException("The JSON sha256 property was not found in: " + file);
111 | }
112 | sb.setLength(0);
113 | matcher.appendReplacement(sb, "sha256\": \"" + hash + "\"");
114 | matcher.appendTail(sb);
115 |
116 | Files.writeString(file, sb.toString());
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/UpdateGettingStartedWebsitePage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2024 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 | import java.nio.charset.StandardCharsets;
26 | import java.nio.file.Files;
27 | import java.nio.file.Path;
28 | import java.nio.file.StandardCopyOption;
29 | import java.util.Iterator;
30 | import java.util.Optional;
31 | import java.util.regex.Matcher;
32 | import java.util.regex.Pattern;
33 | import java.util.zip.ZipEntry;
34 | import java.util.zip.ZipFile;
35 | import org.gradle.api.DefaultTask;
36 | import org.gradle.api.provider.Property;
37 | import org.gradle.api.tasks.Input;
38 | import org.gradle.api.tasks.TaskAction;
39 |
40 | public abstract class UpdateGettingStartedWebsitePage extends DefaultTask {
41 |
42 | @Input
43 | public abstract Property> getAddOn();
44 |
45 | @Input
46 | public abstract Property getFilenameRegex();
47 |
48 | @Input
49 | public abstract Property getGettingStartedPage();
50 |
51 | @Input
52 | public abstract Property getPdfDirectory();
53 |
54 | @TaskAction
55 | void executeTasks() throws Exception {
56 | Optional optionalAddOn = getAddOn().get();
57 | if (optionalAddOn.isEmpty()) {
58 | return;
59 | }
60 |
61 | File addOn = optionalAddOn.get();
62 | Pattern filenamePattern = Pattern.compile(getFilenameRegex().get());
63 | String filename = null;
64 |
65 | try (ZipFile zip = new ZipFile(addOn)) {
66 | boolean found = false;
67 | for (Iterator extends ZipEntry> it = zip.entries().asIterator();
68 | it.hasNext() && !found; ) {
69 | ZipEntry entry = it.next();
70 | if (!filenamePattern.matcher(entry.getName()).find()) {
71 | continue;
72 | }
73 |
74 | found = true;
75 | filename = extractFilename(entry.getName());
76 | try (InputStream zis = zip.getInputStream(entry)) {
77 | Path target = getPdfDirectory().get().toPath().resolve(filename);
78 | Files.copy(zis, target, StandardCopyOption.REPLACE_EXISTING);
79 | }
80 | }
81 | }
82 |
83 | if (filename == null) {
84 | throw new IOException(
85 | "No file matching the provided filename pattern was found in the add-on.");
86 | }
87 |
88 | updateFilename(filename, filenamePattern, getGettingStartedPage().get().toPath());
89 | }
90 |
91 | private static String extractFilename(String path) {
92 | return path.substring(path.indexOf('/') + 1);
93 | }
94 |
95 | private static void updateFilename(String filename, Pattern filenamePattern, Path file)
96 | throws IOException {
97 | String contents = new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
98 | Matcher matcher = filenamePattern.matcher(contents);
99 | if (!matcher.find()) {
100 | throw new IOException("The filename pattern was not found in: " + file);
101 | }
102 | StringBuilder sb = new StringBuilder();
103 | matcher.appendReplacement(sb, filename);
104 | matcher.appendTail(sb);
105 | Files.write(file, sb.toString().getBytes(StandardCharsets.UTF_8));
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/UpdateZapVersionWebsiteData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.File;
23 | import java.nio.charset.StandardCharsets;
24 | import java.nio.file.Files;
25 | import java.nio.file.Path;
26 | import javax.inject.Inject;
27 | import org.gradle.api.DefaultTask;
28 | import org.gradle.api.file.ConfigurableFileCollection;
29 | import org.gradle.api.file.RegularFileProperty;
30 | import org.gradle.api.provider.Property;
31 | import org.gradle.api.tasks.InputFile;
32 | import org.gradle.api.tasks.InputFiles;
33 | import org.gradle.api.tasks.TaskAction;
34 | import org.gradle.workers.WorkAction;
35 | import org.gradle.workers.WorkParameters;
36 | import org.gradle.workers.WorkQueue;
37 | import org.gradle.workers.WorkerExecutor;
38 | import org.zaproxy.gradle.ReleaseState.VersionChange;
39 |
40 | /** Task that updates the ZAP version in files. */
41 | public abstract class UpdateZapVersionWebsiteData extends DefaultTask {
42 |
43 | @InputFile
44 | public abstract RegularFileProperty getReleaseState();
45 |
46 | @InputFiles
47 | public abstract ConfigurableFileCollection getDataFiles();
48 |
49 | @Inject
50 | public abstract WorkerExecutor getWorkerExecutor();
51 |
52 | @TaskAction
53 | public void update() {
54 | ReleaseState releaseState = ReleaseState.read(getReleaseState().getAsFile().get());
55 | if (!isNewMainRelease(releaseState)) {
56 | return;
57 | }
58 |
59 | VersionChange mainRelease = releaseState.getMainRelease();
60 | String previousVersion = mainRelease.getPreviousVersion();
61 | String currentVersion = mainRelease.getCurrentVersion();
62 |
63 | String previousVersionNoPatch = removePatchVersion(previousVersion);
64 | String currentVersionNoPatch = removePatchVersion(currentVersion);
65 |
66 | WorkQueue workQueue = getWorkerExecutor().noIsolation();
67 |
68 | for (File file : getDataFiles()) {
69 | workQueue.submit(
70 | ReplaceVersions.class,
71 | parameters -> {
72 | parameters.getFile().set(file);
73 |
74 | parameters.getPreviousVersion().set(previousVersion);
75 | parameters.getCurrentVersion().set(currentVersion);
76 |
77 | parameters.getPreviousVersionNoPatch().set(previousVersionNoPatch);
78 | parameters.getCurrentVersionNoPatch().set(currentVersionNoPatch);
79 | });
80 | }
81 | }
82 |
83 | private static boolean isNewMainRelease(ReleaseState releaseState) {
84 | VersionChange mainRelease = releaseState.getMainRelease();
85 | return mainRelease != null && mainRelease.isNewVersion();
86 | }
87 |
88 | public interface ReplaceVersionsParameters extends WorkParameters {
89 |
90 | RegularFileProperty getFile();
91 |
92 | Property getPreviousVersion();
93 |
94 | Property getCurrentVersion();
95 |
96 | Property getPreviousVersionNoPatch();
97 |
98 | Property getCurrentVersionNoPatch();
99 | }
100 |
101 | public abstract static class ReplaceVersions implements WorkAction {
102 |
103 | @Override
104 | public void execute() {
105 | try {
106 | Path file = getParameters().getFile().getAsFile().get().toPath();
107 | String contents = new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
108 | Files.write(
109 | file,
110 | contents.replace(
111 | getParameters().getPreviousVersion().get(),
112 | getParameters().getCurrentVersion().get())
113 | .replace(
114 | getParameters().getPreviousVersionNoPatch().get(),
115 | getParameters().getCurrentVersionNoPatch().get())
116 | .getBytes(StandardCharsets.UTF_8));
117 | } catch (Exception e) {
118 | throw new RuntimeException(e);
119 | }
120 | }
121 | }
122 |
123 | private static String removePatchVersion(String version) {
124 | int idx = version.lastIndexOf('.');
125 | if (idx == -1) {
126 | return version;
127 | }
128 | return version.substring(0, idx);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/UpdateZapVersionsEntries.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle;
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 | import java.nio.file.Files;
25 | import java.nio.file.Path;
26 | import java.util.function.Consumer;
27 | import org.apache.commons.configuration.XMLConfiguration;
28 | import org.gradle.api.file.ConfigurableFileCollection;
29 | import org.gradle.api.provider.Property;
30 | import org.gradle.api.tasks.Input;
31 | import org.gradle.api.tasks.InputFiles;
32 |
33 | interface UpdateZapVersionsEntries {
34 |
35 | @InputFiles
36 | ConfigurableFileCollection getInto();
37 |
38 | @Input
39 | Property getChecksumAlgorithm();
40 |
41 | default void updateZapVersionsFiles(Consumer consumer) throws Exception {
42 | if (getChecksumAlgorithm().get().isEmpty()) {
43 | throw new IllegalArgumentException("The checksum algorithm must not be empty.");
44 | }
45 |
46 | for (File zapVersionsFile : getInto()) {
47 | if (!Files.isRegularFile(zapVersionsFile.toPath())) {
48 | throw new IllegalArgumentException(
49 | "The provided path is not a file: " + zapVersionsFile);
50 | }
51 |
52 | XMLConfiguration zapVersionsXml = new CustomXmlConfiguration();
53 | zapVersionsXml.load(zapVersionsFile);
54 | consumer.accept(zapVersionsXml);
55 | zapVersionsXml.save(zapVersionsFile);
56 | }
57 | }
58 |
59 | default String createChecksumString(Path file) throws IOException {
60 | return createChecksumString(file, null);
61 | }
62 |
63 | default String createChecksumString(Path file, String expectedChecksum) throws IOException {
64 | return getChecksumAlgorithm().get() + ":" + calculateChecksum(file, expectedChecksum);
65 | }
66 |
67 | default String calculateChecksum(Path file, String expectedChecksum) throws IOException {
68 | return TaskUtils.calculateChecksum(file, getChecksumAlgorithm().get(), expectedChecksum);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/crowdin/BuildEntry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.crowdin;
21 |
22 | import java.util.List;
23 |
24 | public class BuildEntry {
25 |
26 | private String repo;
27 | private List tasks;
28 |
29 | public String getRepo() {
30 | return repo;
31 | }
32 |
33 | public List getTasks() {
34 | return tasks;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/crowdin/BuildTask.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.crowdin;
21 |
22 | import java.util.List;
23 |
24 | public class BuildTask {
25 |
26 | private String name;
27 | private List args;
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public List getArgs() {
34 | return args;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/crowdin/DeployCrowdinTranslations.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.crowdin;
21 |
22 | import com.fasterxml.jackson.core.type.TypeReference;
23 | import com.fasterxml.jackson.databind.ObjectMapper;
24 | import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
25 | import java.io.File;
26 | import java.io.IOException;
27 | import java.nio.file.Path;
28 | import java.util.ArrayList;
29 | import java.util.List;
30 | import javax.inject.Inject;
31 | import org.apache.tools.ant.taskdefs.condition.Os;
32 | import org.eclipse.jgit.api.Git;
33 | import org.gradle.api.DefaultTask;
34 | import org.gradle.api.file.DirectoryProperty;
35 | import org.gradle.api.file.RegularFileProperty;
36 | import org.gradle.api.provider.Property;
37 | import org.gradle.api.tasks.Input;
38 | import org.gradle.api.tasks.InputDirectory;
39 | import org.gradle.api.tasks.InputFile;
40 | import org.gradle.api.tasks.Internal;
41 | import org.gradle.api.tasks.TaskAction;
42 | import org.gradle.process.ExecOperations;
43 | import org.zaproxy.gradle.CreatePullRequestImpl;
44 | import org.zaproxy.gradle.GitHubRepo;
45 | import org.zaproxy.gradle.GitHubUser;
46 |
47 | /** A task to deploy the resulting Crowdin translations into Git repositories. */
48 | public abstract class DeployCrowdinTranslations extends DefaultTask {
49 |
50 | private static final String PACKAGES_DIR_TOKEN = "%packages_dir%";
51 | private static final String OWNER = "zaproxy";
52 |
53 | public DeployCrowdinTranslations() {
54 | DirectoryProperty buildDirectory = getProject().getLayout().getBuildDirectory();
55 | getTranslationsPackageDirectory()
56 | .convention(buildDirectory.dir("crowdinTranslationPackages"));
57 | getRepositoriesDirectory()
58 | .convention(buildDirectory.dir("deployCrowdinTranslationsRepos").get().getAsFile());
59 | getBaseBranchName().convention("main");
60 | }
61 |
62 | @Inject
63 | protected ExecOperations getExecOperations() {
64 | throw new UnsupportedOperationException();
65 | }
66 |
67 | @InputFile
68 | public abstract RegularFileProperty getDeployConfiguration();
69 |
70 | @InputDirectory
71 | public abstract DirectoryProperty getTranslationsPackageDirectory();
72 |
73 | @Input
74 | public abstract Property getRepositoriesDirectory();
75 |
76 | @Internal
77 | public abstract Property getBaseBranchName();
78 |
79 | @Internal
80 | public abstract Property getBranchName();
81 |
82 | @Internal
83 | public abstract Property getUser();
84 |
85 | @Internal
86 | public abstract Property getCommitSummary();
87 |
88 | @Internal
89 | public abstract Property getCommitDescription();
90 |
91 | @TaskAction
92 | void executeTasks() throws Exception {
93 | Path reposDir = getRepositoriesDirectory().get().toPath();
94 | String packagesDir =
95 | getTranslationsPackageDirectory()
96 | .get()
97 | .getAsFile()
98 | .toPath()
99 | .toAbsolutePath()
100 | .toString();
101 |
102 | for (BuildEntry buildEntry : readBuildEntries()) {
103 | Path repoDir = reposDir.resolve(buildEntry.getRepo());
104 | GitHubRepo ghRepo = new GitHubRepo(OWNER, buildEntry.getRepo(), repoDir.toFile());
105 |
106 | getProject().mkdir(repoDir);
107 | String cloneUrl =
108 | CreatePullRequestImpl.GITHUB_BASE_URL
109 | + ghRepo.getOwner()
110 | + "/"
111 | + ghRepo.getName()
112 | + ".git";
113 | Git.cloneRepository().setURI(cloneUrl).setDirectory(repoDir.toFile()).call();
114 |
115 | runTasks(repoDir, buildEntry.getTasks(), packagesDir);
116 |
117 | CreatePullRequestImpl.create(
118 | ghRepo,
119 | getUser().get(),
120 | getBranchName().get(),
121 | getBaseBranchName().get(),
122 | getCommitSummary().get(),
123 | getCommitDescription().get());
124 | }
125 | }
126 |
127 | private void runTasks(Path repoDir, List tasks, String packagesDir) {
128 | for (BuildTask task : tasks) {
129 | List execArgs = new ArrayList<>(2);
130 | execArgs.add(task.getName());
131 | if (task.getArgs() != null && !task.getArgs().isEmpty()) {
132 | task.getArgs().replaceAll(arg -> replacePackagesDirToken(arg, packagesDir));
133 | execArgs.addAll(task.getArgs());
134 | }
135 | runGradle(repoDir, execArgs);
136 | }
137 | }
138 |
139 | private static String replacePackagesDirToken(String arg, String packagesDir) {
140 | return arg.replace(PACKAGES_DIR_TOKEN, packagesDir);
141 | }
142 |
143 | private void runGradle(Path repoDir, List args) {
144 | List execArgs = new ArrayList<>();
145 | execArgs.add("-Dorg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m");
146 | execArgs.add("-q");
147 | execArgs.addAll(args);
148 | getExecOperations()
149 | .exec(
150 | spec -> {
151 | spec.environment(System.getenv());
152 | spec.setWorkingDir(repoDir);
153 | spec.setExecutable(gradleWrapper());
154 | spec.args(execArgs);
155 | })
156 | .assertNormalExitValue();
157 | }
158 |
159 | private List readBuildEntries() throws IOException {
160 | File file = getDeployConfiguration().get().getAsFile();
161 | return new ObjectMapper(new YAMLFactory())
162 | .readValue(file, new TypeReference>() {});
163 | }
164 |
165 | private static String gradleWrapper() {
166 | if (Os.isFamily(Os.FAMILY_UNIX)) {
167 | return "./gradlew";
168 | }
169 | return "gradlew.bat";
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/website/HelpSetFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.website;
21 |
22 | import java.io.IOException;
23 | import java.net.MalformedURLException;
24 | import java.net.URL;
25 | import java.net.URLClassLoader;
26 | import java.util.Locale;
27 | import java.util.function.Function;
28 | import javax.help.HelpSet;
29 | import javax.help.HelpSetException;
30 | import org.zaproxy.zap.control.AddOn;
31 | import org.zaproxy.zap.extension.help.ExtensionHelp;
32 | import org.zaproxy.zap.utils.LocaleUtils;
33 |
34 | /**
35 | * Factory of {@link HelpSet}, created from an add-on (if present).
36 | *
37 | * First checks if the add-on declares the {@code HelpSet}, otherwise it searches in the default
38 | * locations.
39 | */
40 | final class HelpSetFactory {
41 |
42 | private HelpSetFactory() {}
43 |
44 | /**
45 | * Creates the {@code HelpSet} for the given add-on.
46 | *
47 | * @param addOn the add-on that might contain the {@code HelpSet}.
48 | * @param helpAddOn {@code true} if the given add-on has the core help, {@code false} otherwise.
49 | * @return the {@code HelpSet} or {@code null} if not found.
50 | * @throws WebsitePageGenerationException if an error occurred while searching or creating the
51 | * {@code HelpSet}.
52 | */
53 | static HelpSet createHelpSet(AddOn addOn, boolean helpAddOn) {
54 | try (URLClassLoader classLoader =
55 | new URLClassLoader(
56 | new URL[] {addOn.getFile().toURI().toURL()},
57 | HelpSetFactory.class.getClassLoader())) {
58 | if (helpAddOn) {
59 | return createHelpSet(classLoader, ExtensionHelp.HELP_SET_FILE_NAME, "");
60 | }
61 |
62 | AddOn.HelpSetData helpSetData = addOn.getHelpSetData();
63 | if (!helpSetData.isEmpty()) {
64 | return createHelpSet(
65 | classLoader, helpSetData.getBaseName(), helpSetData.getLocaleToken());
66 | }
67 |
68 | for (String extension : addOn.getExtensions()) {
69 | URL url = getHelpSetUrl(classLoader, extension);
70 | if (url != null) {
71 | return createHelpSet(classLoader, url);
72 | }
73 | }
74 | return null;
75 | } catch (MalformedURLException e) {
76 | throw new WebsitePageGenerationException("Failed to convert the file path to URL:", e);
77 | } catch (IOException e) {
78 | throw new WebsitePageGenerationException(
79 | "Failed to read the contents of the add-on:", e);
80 | }
81 | }
82 |
83 | private static HelpSet createHelpSet(
84 | ClassLoader classLoader, String baseName, String localeToken) {
85 | URL helpSetUrl = findHelpSet(baseName, localeToken, classLoader::getResource);
86 |
87 | if (helpSetUrl == null) {
88 | throw new WebsitePageGenerationException(
89 | "Declared HelpSet not found in the add-on, with base name: "
90 | + baseName
91 | + (localeToken.isEmpty() ? "" : " and locale token: " + localeToken));
92 | }
93 | return createHelpSet(classLoader, helpSetUrl);
94 | }
95 |
96 | private static URL findHelpSet(
97 | String baseName, String localeToken, Function function) {
98 | return LocaleUtils.findResource(
99 | baseName,
100 | ExtensionHelp.HELP_SET_FILE_EXTENSION,
101 | localeToken,
102 | Locale.ROOT,
103 | function);
104 | }
105 |
106 | private static HelpSet createHelpSet(ClassLoader classLoader, URL helpSetUrl) {
107 | try {
108 | return new HelpSet(classLoader, helpSetUrl);
109 | } catch (HelpSetException e) {
110 | throw new WebsitePageGenerationException(
111 | "An error occured while loading the HelpSet from the add-on.", e);
112 | }
113 | }
114 |
115 | private static URL getHelpSetUrl(ClassLoader classLoader, String extension) {
116 | String extensionPackage = extension.substring(0, extension.lastIndexOf('.'));
117 | String localeToken = "%LC%";
118 | Function getResource = classLoader::getResource;
119 | URL helpSetUrl =
120 | findHelpSet(
121 | extensionPackage
122 | + ".resources.help"
123 | + localeToken
124 | + "."
125 | + ExtensionHelp.HELP_SET_FILE_NAME,
126 | localeToken,
127 | getResource);
128 | if (helpSetUrl == null) {
129 | // Search in old location
130 | helpSetUrl =
131 | findHelpSet(
132 | extensionPackage
133 | + ".resource.help"
134 | + localeToken
135 | + "."
136 | + ExtensionHelp.HELP_SET_FILE_NAME,
137 | localeToken,
138 | getResource);
139 | }
140 | return helpSetUrl;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/website/SourceImage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.website;
21 |
22 | import java.net.URL;
23 |
24 | /** An image contained in the add-on. */
25 | class SourceImage {
26 |
27 | private final String src;
28 | private final URL url;
29 |
30 | SourceImage(String src, URL url) {
31 | this.src = src;
32 | this.url = url;
33 | }
34 |
35 | URL getUrl() {
36 | return url;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return src;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/website/SourcePage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.website;
21 |
22 | import java.net.URL;
23 | import java.util.Objects;
24 | import org.jsoup.nodes.Document;
25 |
26 | /** A source page (HTML) contained in the add-on. */
27 | class SourcePage {
28 |
29 | private final PageFrontMatter frontMatter;
30 | private final URL path;
31 | private final String relativePath;
32 | private final String sitePath;
33 | private final String siteUrl;
34 | private final Document document;
35 | private final boolean section;
36 |
37 | SourcePage(PageFrontMatter frontMatter, String sitePath) {
38 | this.frontMatter = frontMatter;
39 | this.path = null;
40 | this.relativePath = null;
41 | this.sitePath = sitePath;
42 | this.siteUrl = null;
43 | this.document = null;
44 | this.section = false;
45 | }
46 |
47 | SourcePage(
48 | PageFrontMatter frontMatter,
49 | URL path,
50 | String relativePath,
51 | String sitePath,
52 | String siteUrl,
53 | Document document,
54 | boolean section) {
55 | this.frontMatter = frontMatter;
56 | this.path = Objects.requireNonNull(path);
57 | this.relativePath = Objects.requireNonNull(relativePath);
58 | this.sitePath = Objects.requireNonNull(sitePath);
59 | this.siteUrl = Objects.requireNonNull(siteUrl);
60 | this.document = document;
61 | this.section = section;
62 | }
63 |
64 | PageFrontMatter getFrontMatter() {
65 | return frontMatter;
66 | }
67 |
68 | URL getPath() {
69 | return path;
70 | }
71 |
72 | String getRelativePath() {
73 | return relativePath;
74 | }
75 |
76 | String getSitePath() {
77 | return sitePath;
78 | }
79 |
80 | String getSiteUrl() {
81 | return siteUrl;
82 | }
83 |
84 | Document getDocument() {
85 | return document;
86 | }
87 |
88 | boolean isSection() {
89 | return section;
90 | }
91 |
92 | @Override
93 | public int hashCode() {
94 | return relativePath.hashCode();
95 | }
96 |
97 | @Override
98 | public boolean equals(Object obj) {
99 | if (this == obj) {
100 | return true;
101 | }
102 | if (obj == null) {
103 | return false;
104 | }
105 | if (getClass() != obj.getClass()) {
106 | return false;
107 | }
108 | SourcePage other = (SourcePage) obj;
109 | return relativePath.equals(other.relativePath);
110 | }
111 |
112 | @Override
113 | public String toString() {
114 | return relativePath;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/website/Utils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.website;
21 |
22 | import java.net.URI;
23 | import java.net.URL;
24 | import java.util.Locale;
25 | import java.util.regex.Pattern;
26 | import org.apache.commons.lang3.StringUtils;
27 | import org.zaproxy.gradle.website.TocTree.TocItem;
28 |
29 | /** Utility methods needed for website page generation. */
30 | final class Utils {
31 |
32 | private static final String ABSOLUTE_SCHEME = "//";
33 | private static final String HTTP_SCHEME = "http://";
34 | private static final String HTTPS_SCHEME = "https://";
35 | private static final String MAILTO_SCHEME = "mailto:";
36 | private static final String WWW_SUBDOMAIN = "www.";
37 |
38 | private static final Pattern HTML_EXTENSION =
39 | Pattern.compile("\\.html$", Pattern.CASE_INSENSITIVE);
40 |
41 | private static final String MARKDOWN_EXTENSION = ".md";
42 |
43 | private Utils() {}
44 |
45 | static String createContentsDirName(TocItem tocItem) {
46 | String url = tocItem.getTarget().toString();
47 | int idx = url.lastIndexOf('/');
48 | return url.substring(0, idx);
49 | }
50 |
51 | static String createAddOnDirName(TocItem addOnTocItem) {
52 | return addOnTocItem
53 | .getText()
54 | .toLowerCase(Locale.ROOT)
55 | .replaceAll("[ /:]", "-")
56 | .replaceAll("-{2,}", "-");
57 | }
58 |
59 | static String createSiteFileName(String path, String newFileExtension) {
60 | StringBuilder strBuilderFileName = new StringBuilder();
61 | String[] segments = path.split("/", -1);
62 | for (int i = 0; i < segments.length - 1; i++) {
63 | strBuilderFileName.append(StringUtils.capitalize(segments[i]));
64 | }
65 | String fileName = StringUtils.capitalize(segments[segments.length - 1]);
66 | strBuilderFileName.append(HTML_EXTENSION.matcher(fileName).replaceFirst(newFileExtension));
67 |
68 | return strBuilderFileName.toString();
69 | }
70 |
71 | static String createSitePath(String path) {
72 | return HTML_EXTENSION
73 | .matcher(path)
74 | .replaceFirst(MARKDOWN_EXTENSION)
75 | .toLowerCase(Locale.ROOT);
76 | }
77 |
78 | static String createSiteUrl(String path) {
79 | return HTML_EXTENSION.matcher(path).replaceFirst("/").toLowerCase(Locale.ROOT);
80 | }
81 |
82 | static String createRedirectPath(String urlPath, String childPath) {
83 | return urlPath
84 | + HTML_EXTENSION.matcher(childPath).replaceFirst("/").toLowerCase(Locale.ROOT);
85 | }
86 |
87 | static URL createUrlFor(URL file, String path) {
88 | try {
89 | var resolved = new URI(file.getPath()).resolve(path);
90 | return new URI(file.getProtocol(), resolved.toASCIIString(), null).toURL();
91 | } catch (Exception e) {
92 | throw new WebsitePageGenerationException(
93 | "Failed to create the URL with " + file + " and " + path, e);
94 | }
95 | }
96 |
97 | static String normalisedPath(String baseDir, URL file, String path) {
98 | return normalisedPath(baseDir, createUrlFor(file, path));
99 | }
100 |
101 | static String normalisedPath(String baseDir, URL url) {
102 | return normalisePath(baseDir, url.toString());
103 | }
104 |
105 | private static String normalisePath(String baseDir, String path) {
106 | if (!startsWithDir(path, baseDir)) {
107 | throw new WebsitePageGenerationException(
108 | "Path " + path + " not under base dir " + baseDir);
109 | }
110 | return path.substring(baseDir.length() + 1);
111 | }
112 |
113 | static String normalisedImagePath(String baseDir, String imagesDirName, URL url) {
114 | String path = url.toString();
115 | if (startsWithDir(path, baseDir)) {
116 | path = normalisePath(baseDir, path);
117 | if (path.startsWith(imagesDirName)) {
118 | path = path.substring(imagesDirName.length() + 1);
119 | }
120 | } else {
121 | path = path.substring(path.lastIndexOf('/') + 1);
122 | }
123 | return path;
124 | }
125 |
126 | private static boolean startsWithDir(String path, String dir) {
127 | return path.startsWith(normaliseFileSystemPath(dir));
128 | }
129 |
130 | static String normaliseFileSystemPath(String path) {
131 | return path.replace('\\', '/');
132 | }
133 |
134 | static boolean isExternalLink(String href) {
135 | return StringUtils.startsWithIgnoreCase(href, HTTP_SCHEME)
136 | || StringUtils.startsWithIgnoreCase(href, HTTPS_SCHEME)
137 | || StringUtils.startsWithIgnoreCase(href, ABSOLUTE_SCHEME)
138 | || StringUtils.startsWithIgnoreCase(href, MAILTO_SCHEME)
139 | || StringUtils.startsWithIgnoreCase(href, WWW_SUBDOMAIN);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/website/WebsitePageGenerationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2021 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.website;
21 |
22 | public class WebsitePageGenerationException extends RuntimeException {
23 |
24 | private static final long serialVersionUID = 1L;
25 |
26 | WebsitePageGenerationException() {
27 | super();
28 | }
29 |
30 | WebsitePageGenerationException(String message) {
31 | super(message);
32 | }
33 |
34 | WebsitePageGenerationException(String message, Throwable cause) {
35 | super(message, cause);
36 | }
37 |
38 | WebsitePageGenerationException(Throwable cause) {
39 | super(cause);
40 | }
41 |
42 | protected WebsitePageGenerationException(
43 | String message,
44 | Throwable cause,
45 | boolean enableSuppression,
46 | boolean writableStackTrace) {
47 | super(message, cause, enableSuppression, writableStackTrace);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/buildSrc/src/main/java/org/zaproxy/gradle/website/WebsiteSbomPageGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2023 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.gradle.website;
21 |
22 | import com.fasterxml.jackson.databind.JsonNode;
23 | import com.fasterxml.jackson.databind.ObjectMapper;
24 | import com.fasterxml.jackson.databind.node.ArrayNode;
25 | import java.io.StringWriter;
26 | import java.nio.charset.StandardCharsets;
27 | import java.nio.file.Files;
28 | import java.nio.file.Path;
29 | import java.util.Set;
30 | import java.util.TreeSet;
31 | import java.util.stream.Collectors;
32 | import java.util.stream.StreamSupport;
33 |
34 | public class WebsiteSbomPageGenerator {
35 |
36 | private static final ObjectMapper MAPPER = new ObjectMapper();
37 | private static final String NOTICE =
38 | "This page was automatically generated from the add-on's SBOM.";
39 |
40 | public static void generate(
41 | Path bomPath,
42 | String bomUrl,
43 | String pageTitle,
44 | String addOnId,
45 | String addOnVersion,
46 | Path outputFile)
47 | throws Exception {
48 | PageFrontMatter frontMatter = new PageFrontMatter("sbom", pageTitle, 1);
49 | JsonNode bomJson = MAPPER.readTree(bomPath.toFile());
50 | Set resultComponents = new TreeSet<>();
51 | var componentsJsonArray = (ArrayNode) bomJson.get("components");
52 | for (JsonNode component : componentsJsonArray) {
53 | resultComponents.add(
54 | new PageFrontMatter.SbomDataComponent(
55 | component.get("name").asText(),
56 | component.get("version").asText(),
57 | createLicensesString(component)));
58 | }
59 | frontMatter.setSbomData(
60 | new PageFrontMatter.SbomData(
61 | bomJson.get("bomFormat").asText(), bomUrl, resultComponents));
62 | frontMatter.setAddOnData(new PageFrontMatter.AddOnData(addOnId, addOnVersion));
63 | var writer = new StringWriter();
64 | frontMatter.writeTo(NOTICE, writer);
65 | Files.write(outputFile, writer.toString().getBytes(StandardCharsets.UTF_8));
66 | }
67 |
68 | private static String createLicensesString(JsonNode component) {
69 | var licenses = (ArrayNode) component.get("licenses");
70 | if (licenses == null) {
71 | return "";
72 | }
73 |
74 | return StreamSupport.stream(licenses.spliterator(), false)
75 | .map(WebsiteSbomPageGenerator::licenseObjectToString)
76 | .filter(e -> e != null)
77 | .collect(Collectors.joining(", "));
78 | }
79 |
80 | private static String licenseObjectToString(JsonNode l) {
81 | if (!l.has("license")) {
82 | return get(l, "expression");
83 | }
84 | var license = l.get("license");
85 | var id = get(license, "id");
86 | if (id != null) {
87 | return id;
88 | }
89 | return get(license, "name");
90 | }
91 |
92 | private static String get(JsonNode node, String property) {
93 | if (node.has(property)) {
94 | return node.get(property).asText();
95 | }
96 | return null;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/org/zaproxy/gradle/GitHubRepo.kt:
--------------------------------------------------------------------------------
1 | package org.zaproxy.gradle
2 |
3 | import java.io.File
4 |
5 | data class GitHubRepo(val owner: String, val name: String, val dir: File) {
6 |
7 | override fun toString() = "$owner/$name"
8 | }
9 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/org/zaproxy/gradle/GitHubUser.kt:
--------------------------------------------------------------------------------
1 | package org.zaproxy.gradle
2 |
3 | data class GitHubUser(val name: String, val email: String, val authToken: String?)
4 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/org/zaproxy/gradle/ZapTask.kt:
--------------------------------------------------------------------------------
1 | import org.gradle.api.plugins.JavaPluginExtension
2 | import org.gradle.api.tasks.JavaExec
3 | import org.gradle.kotlin.dsl.get
4 |
5 | open class ZapTask : JavaExec() {
6 |
7 | init {
8 | group = "ZAP"
9 | classpath = project.configurations["runtimeClasspath"] +
10 | project.extensions.getByType(JavaPluginExtension::class.java).sourceSets["main"].output
11 | dependsOn("classes")
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/docs/headers/README.MD:
--------------------------------------------------------------------------------
1 | # Standard license headers to be used in zaproxy repos.
2 |
3 | Replace `$YEAR` with the current year.
--------------------------------------------------------------------------------
/docs/headers/license.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright $YEAR The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
--------------------------------------------------------------------------------
/docs/headers/license.script:
--------------------------------------------------------------------------------
1 | #
2 | # Zed Attack Proxy (ZAP) and its related class files.
3 | #
4 | # ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | #
6 | # Copyright $YEAR The ZAP Development Team
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # http://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
--------------------------------------------------------------------------------
/docs/issue-templates/README.MD:
--------------------------------------------------------------------------------
1 | # Standard issue responses
2 |
3 | Standard issue responses to be used by the ZAP Core Team.
4 |
5 | For ease of use they can be manually added to https://github.com/settings/replies
6 |
7 | ### Question As Issue
8 | Please do not ask questions as issues.
9 |
10 | The ZAP User Group is the place to ask them: https://groups.google.com/g/zaproxy-users
11 |
12 | ### Non ZAP Issue
13 | This applies to a third party component that is not maintained by the ZAP Team. Please look for their preferred support mechanism.
14 |
15 | You can also try the [ZAP User Group](https://groups.google.com/g/zaproxy-users).
16 |
17 | ### Virus Report
18 | Thank you for letting us know. We will try to get in touch with the vendor, but this issue is being closed as it is really a problem with their detection and not our code.
19 |
20 | See https://www.zaproxy.org/faq/why-does-my-antivirus-tool-flag-zap/
21 |
22 | ### Browser Not Found
23 | Please follow this FAQ: https://www.zaproxy.org/faq/no-browser/
24 |
25 | You will see that the last line is: "If all fails then ask on the [ZAP User Group](https://groups.google.com/g/zaproxy-users), but make sure you mention you have checked this FAQ otherwise you will just be redirected back to here!"
26 |
27 |
--------------------------------------------------------------------------------
/files/launch/2.6.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | ZAP 2.7.0 is available now!
6 |
7 | Use the ZAP "Help / Check for Updates..." menu option to download it.
8 |
9 |
--------------------------------------------------------------------------------
/files/launch/2.7.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | ZAP 2.8.0 with the Heads Up Display is available now!
6 |
7 | Use the ZAP "Help / Check for Updates..." menu option to download it.
8 |
--------------------------------------------------------------------------------
/files/launch/2.8.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | Explore your application with ZAP
6 |
7 | This browser is automatically configured to proxy via ZAP and to ignore certificate warnings.
8 | The more effectively you explore your application the better ZAP will understand and be able to attack it.
9 |
10 | The ZAP HUD
11 |
12 | This version includes the ZAP Heads Up Display (HUD).
13 | The HUD is a brand new innovative interface that brings ZAP into the browser.
14 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
15 | see security information from ZAP and also allowing you to interact with it.
16 | The HUD includes a tutorial which will introduce you to all of the features it provides -
17 | you are strongly recommended to take it.
18 |
19 |
20 |
21 |
23 | Sumisiyasat sa iyong aplikasyon sa ZAP
24 |
25 | Ang browser ay awtomatikong isinasaayos sa proxy sa pamamagitan ng ZAP ay huwag pansinin ang mga sertipiko na mga babala.
26 |
27 | Ang pinaka epektibong pagtuklas sa iyong aplikasyon ang mas mahusay na ZAP ay mauunawaan at pwede kang umatake nito.
28 |
29 | The ZAP HUD
30 |
31 | This version includes the ZAP Heads Up Display (HUD).
32 | The HUD is a brand new innovative interface that brings ZAP into the browser.
33 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
34 | see security information from ZAP and also allowing you to interact with it.
35 | The HUD includes a tutorial which will introduce you to all of the features it provides -
36 | you are strongly recommended to take it.
37 |
38 |
39 |
40 |
42 | Explorez votre application avec ZAP
43 |
44 | Ce navigateur est automatiquement configuré en proxy via ZAP et ignore les avertissements de certificat.
45 |
46 | Plus vous explorez efficacement votre application, mieux ZAP comprendrez il et pourrez l'attaquer.
47 |
48 | The ZAP HUD
49 |
50 | This version includes the ZAP Heads Up Display (HUD).
51 | The HUD is a brand new innovative interface that brings ZAP into the browser.
52 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
53 | see security information from ZAP and also allowing you to interact with it.
54 | The HUD includes a tutorial which will introduce you to all of the features it provides -
55 | you are strongly recommended to take it.
56 |
57 |
58 |
59 |
61 | Jelajahi aplikasi Anda dengan ZAP
62 |
63 | Peramban ini secara otomatis dikonfigurasi untuk menggunakan proxy melalui ZAP dan mengabaikan peringatan sertifikat.
64 |
65 | Lebih efektif Anda menjelajahi aplikasi, ZAP akan mengerti dan dapat menyerangnya dengan lebih baik.
66 |
67 | The ZAP HUD
68 |
69 | This version includes the ZAP Heads Up Display (HUD).
70 | The HUD is a brand new innovative interface that brings ZAP into the browser.
71 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
72 | see security information from ZAP and also allowing you to interact with it.
73 | The HUD includes a tutorial which will introduce you to all of the features it provides -
74 | you are strongly recommended to take it.
75 |
76 |
77 |
78 |
80 | Uygulamanızı ZAP ile keşfedin
81 | Bu tarayıcı ZAP üzerinden otomatik olarak vekil sunucu olarak ve sertifika uyarılarını göz ardı etmek için yapılandırılmıştır.
82 | Uygulamanızda ne kadar verimli dolaşırsanız, ZAP yapıyı o kadar iyi anlayacak ve etkin olarak saldırabilecektir.
83 |
84 | The ZAP HUD
85 |
86 | This version includes the ZAP Heads Up Display (HUD).
87 | The HUD is a brand new innovative interface that brings ZAP into the browser.
88 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
89 | see security information from ZAP and also allowing you to interact with it.
90 | The HUD includes a tutorial which will introduce you to all of the features it provides -
91 | you are strongly recommended to take it.
92 |
--------------------------------------------------------------------------------
/files/launch/README.md:
--------------------------------------------------------------------------------
1 | # Quick Start Launch Pages
2 | This directory contains files containing the HTML displayed by default when
3 | ZAP launches browsers via the Quick Start add-on.
4 |
5 | ## Locale support
6 | The files can support multiple locales.
7 | Each section must be separated via the string:
8 | ```
9 |
10 | ```
11 |
12 | The first line of the first section should be:
13 | ```
14 |
15 | ```
16 |
17 | The first line of following sections should contain the relevant locale:
18 | ```
19 |
20 | ```
21 |
--------------------------------------------------------------------------------
/files/launch/dev.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | Explore your application with ZAP
6 |
7 | This browser is automatically configured to proxy via ZAP and to ignore certificate warnings.
8 | The more effectively you explore your application the better ZAP will understand and be able to attack it.
9 |
10 | The ZAP HUD
11 |
12 | This version includes the ZAP Heads Up Display (HUD).
13 | The HUD is a brand new innovative interface that brings ZAP into the browser.
14 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
15 | see security information from ZAP and also allowing you to interact with it.
16 | The HUD includes a tutorial which will introduce you to all of the features it provides -
17 | you are strongly recommended to take it.
18 |
19 |
20 |
21 |
23 | Sumisiyasat sa iyong aplikasyon sa ZAP
24 |
25 | Ang browser ay awtomatikong isinasaayos sa proxy sa pamamagitan ng ZAP ay huwag pansinin ang mga sertipiko na mga babala.
26 |
27 | Ang pinaka epektibong pagtuklas sa iyong aplikasyon ang mas mahusay na ZAP ay mauunawaan at pwede kang umatake nito.
28 |
29 | The ZAP HUD
30 |
31 | This version includes the ZAP Heads Up Display (HUD).
32 | The HUD is a brand new innovative interface that brings ZAP into the browser.
33 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
34 | see security information from ZAP and also allowing you to interact with it.
35 | The HUD includes a tutorial which will introduce you to all of the features it provides -
36 | you are strongly recommended to take it.
37 |
38 |
39 |
40 |
42 | Explorez votre application avec ZAP
43 |
44 | Ce navigateur est automatiquement configuré en proxy via ZAP et ignore les avertissements de certificat.
45 |
46 | Plus vous explorez efficacement votre application, mieux ZAP comprendrez il et pourrez l'attaquer.
47 |
48 | The ZAP HUD
49 |
50 | This version includes the ZAP Heads Up Display (HUD).
51 | The HUD is a brand new innovative interface that brings ZAP into the browser.
52 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
53 | see security information from ZAP and also allowing you to interact with it.
54 | The HUD includes a tutorial which will introduce you to all of the features it provides -
55 | you are strongly recommended to take it.
56 |
57 |
58 |
59 |
61 | Jelajahi aplikasi Anda dengan ZAP
62 |
63 | Peramban ini secara otomatis dikonfigurasi untuk menggunakan proxy melalui ZAP dan mengabaikan peringatan sertifikat.
64 |
65 | Lebih efektif Anda menjelajahi aplikasi, ZAP akan mengerti dan dapat menyerangnya dengan lebih baik.
66 |
67 | The ZAP HUD
68 |
69 | This version includes the ZAP Heads Up Display (HUD).
70 | The HUD is a brand new innovative interface that brings ZAP into the browser.
71 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
72 | see security information from ZAP and also allowing you to interact with it.
73 | The HUD includes a tutorial which will introduce you to all of the features it provides -
74 | you are strongly recommended to take it.
75 |
76 |
77 |
78 |
80 | Uygulamanızı ZAP ile keşfedin
81 | Bu tarayıcı ZAP üzerinden otomatik olarak vekil sunucu olarak ve sertifika uyarılarını göz ardı etmek için yapılandırılmıştır.
82 | Uygulamanızda ne kadar verimli dolaşırsanız, ZAP yapıyı o kadar iyi anlayacak ve etkin olarak saldırabilecektir.
83 |
84 | The ZAP HUD
85 |
86 | This version includes the ZAP Heads Up Display (HUD).
87 | The HUD is a brand new innovative interface that brings ZAP into the browser.
88 | When you navigate to a target site then the HUD will overlay information into your browser allowing you to
89 | see security information from ZAP and also allowing you to interact with it.
90 | The HUD includes a tutorial which will introduce you to all of the features it provides -
91 | you are strongly recommended to take it.
92 |
--------------------------------------------------------------------------------
/files/news/2_10.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 29
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 38
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 44
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_13.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 48
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_14.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 52
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_15.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 53
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_16.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 54
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/blog/2025-03-25-zap-2-16-1/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/2_9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/download/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/files/news/dev.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 54
5 |
6 | - ZAP 2.16.1 is available now
7 | https://www.zaproxy.org/blog/2025-03-25-zap-2-16-1/
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/gradle/ci.gradle.kts:
--------------------------------------------------------------------------------
1 | // Build tweaks when running in GitHub CI
2 |
3 | fun isEnvVarTrue(envvar: String) = System.getenv(envvar) == "true"
4 |
5 | if (isEnvVarTrue("CI") && System.getenv("GITHUB_WORKFLOW") == "Java CI") {
6 |
7 | tasks.withType(Test::class).configureEach {
8 | testLogging {
9 | exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
10 | }
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/gradle/crowdin.yml:
--------------------------------------------------------------------------------
1 | projects:
2 | - id: 9301
3 | - id: 32705
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zaproxy/zap-admin/ab815105beadb225f19c174024e0d08831b6f353/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionSha256Sum=fba8464465835e74f7270bbf43d6d8a8d7709ab0a43ce1aa3323f73e9aa0c612
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
5 | networkTimeout=10000
6 | validateDistributionUrl=true
7 | zipStoreBase=GRADLE_USER_HOME
8 | zipStorePath=wrapper/dists
9 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/scripts/generate_events_page.js:
--------------------------------------------------------------------------------
1 | // This is a ZAP standalone script - it will only run in ZAP.
2 | // It generates the data for the events page at https://www.zaproxy.org/docs/internal-events/
3 | // The pages were created after starting a ZAP weekly release with the '-addoninstallall' option.
4 |
5 | // Change the FILE below to match the local alerts data file
6 | var FILE = "/zap/wrk/zaproxy-website/site/data/events.yaml";
7 |
8 | var FileWriter = Java.type('java.io.FileWriter');
9 | var PrintWriter = Java.type('java.io.PrintWriter');
10 | var ZAP = Java.type('org.zaproxy.zap.ZAP');
11 |
12 | var fw = new FileWriter(FILE);
13 | var pw = new PrintWriter(fw);
14 |
15 | function isInExtensions(path) {
16 | return path.startsWith("org.zaproxy.addon") ||
17 | (path.startsWith("org.zaproxy.zap.extension")
18 | && ! path.startsWith("org.zaproxy.zap.extension.alert")
19 | && ! path.startsWith("org.zaproxy.zap.extension.ascan")
20 | && ! path.startsWith("org.zaproxy.zap.extension.brk")
21 | && ! path.startsWith("org.zaproxy.zap.extension.spider"));
22 | }
23 |
24 | pw.println ("# The events raised in ZAP");
25 | pw.println ("---");
26 |
27 | var publishers = ZAP.eventBus.getPublisherNames().toArray();
28 | for (var i=0; i < publishers.length; i++) {
29 | var events = ZAP.eventBus.getEventTypesForPublisher(publishers[i]).toArray();
30 | for (var j=0; j < events.length; j++) {
31 | // Assume the core to start with
32 | var publisherJava = publishers[i].replaceAll("\\.", "\\/") + ".java";
33 | var link = "https://github.com/zaproxy/zaproxy/blob/main/zap/src/main/java/" + publisherJava;
34 | if (isInExtensions(publishers[i])) {
35 | var pkg = publishers[i].split(".")[4];
36 | if (publishers[i].startsWith("org.zaproxy.addon")) {
37 | pkg = publishers[i].split(".")[3];
38 | }
39 | if (publishers[i].startsWith("org.zaproxy.zap.extension.hud")) {
40 | link = "https://github.com/zaproxy/zap-hud/tree/main/src/main/java/" + publisherJava;
41 | } else {
42 | link = "https://github.com/zaproxy/zap-extensions/blob/main/addOns/" + pkg + "/src/main/java/" + publisherJava;
43 | }
44 | }
45 |
46 | pw.println();
47 | pw.println("- publisher: " + publishers[i]);
48 | pw.println(" link: " + link);
49 | pw.println(" event: " + events[j]);
50 | }
51 | }
52 | pw.close();
53 |
--------------------------------------------------------------------------------
/scripts/raise_issue.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Raises an issue with the specified options.
5 |
6 | Usage example:
7 |
8 | ./raise-issue.py -t "Issue name" -f file -a zaproxy -p changeme
9 |
10 | """
11 | import argparse
12 | import json
13 | import requests
14 |
15 | def make_github_issue(title, owner, repo, user, password, body=None, assignee=None, milestone=None, labels=None):
16 | '''Create an issue on github.com using the given parameters.'''
17 | # url to create issues via POST
18 | url = 'https://api.github.com/repos/%s/%s/issues' % (owner, repo)
19 | # Create an authenticated session to create the issue
20 | session = requests.Session()
21 | session.auth = (user, password)
22 | # Create our issue
23 | issue = {'title': title,
24 | 'body': body,
25 | 'assignee': assignee}
26 | # 'milestone': milestone,
27 | # 'labels': labels}
28 | # Add the issue to our repository
29 | r = session.post(url, json.dumps(issue))
30 | if r.status_code == 201:
31 | print 'Successfully created Issue "%s"' % title
32 | else:
33 | print 'Could not create Issue "%s"' % title
34 | print 'Response:', r.content
35 | return r.content
36 |
37 |
38 | def get_args():
39 | parser = argparse.ArgumentParser(description=__doc__)
40 |
41 | parser.add_argument('-t', '--title',
42 | required=True,
43 | help='Issue title')
44 |
45 | parser.add_argument('-f', '--file',
46 | required=True,
47 | help='File containing the issue body')
48 |
49 | parser.add_argument('-o', '--owner',
50 | default='zaproxy',
51 | help='Repo owner, e.g. zaproxy')
52 |
53 | parser.add_argument('-r', '--repo',
54 | default='zap-admin',
55 | help='Repo, e.g. zap-admin')
56 |
57 | parser.add_argument('-u', '--user',
58 | default='zapbot',
59 | help='User, e.g. zapbot')
60 |
61 | parser.add_argument('-p', '--password',
62 | required=True,
63 | help='Password / credentials')
64 |
65 | parser.add_argument('-a', '--assignee',
66 | required=False,
67 | help='Assigne, e.g. zapbot')
68 |
69 | parsed_args = parser.parse_args()
70 | return vars(parsed_args)
71 |
72 | def main():
73 | cli_args = get_args()
74 |
75 | with open(cli_args['file'], 'r') as content_file:
76 | content = content_file.read()
77 |
78 | return make_github_issue(cli_args['title'], cli_args['owner'], cli_args['repo'], cli_args['user'],
79 | cli_args['password'], body=content, assignee=cli_args['assignee'])
80 |
81 |
82 | if __name__ == '__main__':
83 | main()
84 |
--------------------------------------------------------------------------------
/scripts/report_addons_to_release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Simple script for raising issues with details of any add-ons ready to be published
3 | # Run from the top level directory, eg:
4 | # zap-admin/scripts/report_addons_to_release.sh
5 | #
6 | # It assumed all repos are in the cwd and are up to date
7 | # Suitable credentials should be in the ~/.netrc file
8 |
9 | cd zap-admin
10 | # The ``` are to escape all of the characters in the issue, otherwise it messes up a bit ;)
11 | echo "\`\`\`" > addons_to_release
12 | ./gradlew pendingAddOnReleases >> addons_to_release
13 | echo "\`\`\`" >> addons_to_release
14 |
15 | # Extract the password
16 | netrc=`cat ~/.netrc`
17 | words=( $netrc )
18 | pwd=${words[5]}
19 |
20 | scripts/raise_issue.py -t "Addons ready to release " -f addons_to_release -a zapbot -p "$pwd"
21 | rm addons_to_release
22 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.zaproxy.common.settings") version "0.5.0"
3 | id("com.diffplug.spotless") version "6.25.0" apply false
4 | }
5 |
6 | rootProject.name = "zap-admin"
7 |
--------------------------------------------------------------------------------
/src/main/addons-help-website.txt:
--------------------------------------------------------------------------------
1 | # The IDs of the add-ons that should have the help generated to the website.
2 |
3 | # Main help.
4 | help
5 |
6 | # Remaining add-ons, in alphabetic order.
7 | accessControl
8 | alertFilters
9 | alertReport
10 | allinonenotes
11 | ascanrulesAlpha
12 | ascanrulesBeta
13 | ascanrules
14 | # 3rd-party, does not have help.
15 | # attacksurfacedetector
16 | authhelper
17 | authstats
18 | automation
19 | beanshell
20 | browserView
21 | bruteforce
22 | bugtracker
23 | callgraph
24 | callhome
25 | client
26 | commonlib
27 | communityScripts
28 | custompayloads
29 | database
30 | dev
31 | diff
32 | directorylistv1
33 | directorylistv2_3_lc
34 | directorylistv2_3
35 | domxss
36 | encoder
37 | evalvillain
38 | exim
39 | formhandler
40 | fuzz
41 | fuzzai
42 | fuzzdboffensive
43 | fuzzdb
44 | gettingStarted
45 | graaljs
46 | graphql
47 | groovy
48 | grpc
49 | highlighter
50 | hud
51 | imagelocationscanner
52 | invoke
53 | jruby
54 | jsonview
55 | # 3rd-party, does not have help.
56 | # jwt
57 | jython
58 | kotlin
59 | neonmarker
60 | network
61 | oast
62 | onlineMenu
63 | openapi
64 | packpentester
65 | packscanrules
66 | packscripts
67 | paramdigger
68 | plugnhack
69 | postman
70 | pscan
71 | pscanrulesAlpha
72 | pscanrulesBeta
73 | pscanrules
74 | quickstart
75 | # 3rd-party, does not have help.
76 | # reflect
77 | regextester
78 | replacer
79 | reports
80 | requester
81 | retest
82 | retire
83 | reveal
84 | revisit
85 | saml
86 | scanpolicies
87 | scripts
88 | selenium
89 | sequence
90 | soap
91 | spider
92 | spiderAjax
93 | sqliplugin
94 | sse
95 | svndigger
96 | tips
97 | tokengen
98 | treetools
99 | viewstate
100 | wappalyzer
101 | webdriverlinux
102 | webdrivermacos
103 | webdriverwindows
104 | websocket
105 | zest
106 |
107 |
--------------------------------------------------------------------------------
/src/main/crowdin-tasks.yml:
--------------------------------------------------------------------------------
1 | - repo: "zaproxy"
2 | tasks:
3 | - name: "crowdinCopyProjectTranslations"
4 | args: [ "--from=%packages_dir%", "--file-filter=_kaa" ]
5 |
6 | - repo: "zap-core-help"
7 | tasks:
8 | - name: ":addOns:crowdinCopyProjectTranslations"
9 | args: [ "--from=%packages_dir%", "--file-filter=_kaa" ]
10 | - name: "updateHelpSetXmlLangAttr"
11 |
12 | - repo: "zap-extensions"
13 | tasks:
14 | - name: "crowdinCopyProjectTranslations"
15 | args: [ "--from=%packages_dir%", "--file-filter=_kaa" ]
16 | - name: "postProcessLocalizedHelpPages"
17 | - name: "spotlessApply"
18 |
19 | - repo: "community-scripts"
20 | tasks:
21 | - name: "crowdinCopyProjectTranslations"
22 | args: [ "--from=%packages_dir%", "--file-filter=_kaa" ]
23 | - name: "postProcessLocalizedHelpPages"
24 |
25 | - repo: "fuzzdb-offensive"
26 | tasks:
27 | - name: "crowdinCopyProjectTranslations"
28 | args: [ "--from=%packages_dir%", "--file-filter=_kaa" ]
29 | - name: "postProcessLocalizedHelpPages"
30 |
31 | - repo: "zap-hud"
32 | tasks:
33 | - name: "crowdinCopyProjectTranslations"
34 | args: [ "--from=%packages_dir%", "--file-filter=_kaa" ]
35 | - name: "postProcessLocalizedHelpPages"
36 |
--------------------------------------------------------------------------------
/src/main/java/org/zaproxy/admin/AddOnsTask.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2018 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import java.io.BufferedInputStream;
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 | import java.nio.file.FileVisitResult;
26 | import java.nio.file.Files;
27 | import java.nio.file.Path;
28 | import java.nio.file.Paths;
29 | import java.nio.file.SimpleFileVisitor;
30 | import java.nio.file.attribute.BasicFileAttributes;
31 | import java.text.Collator;
32 | import java.util.ArrayList;
33 | import java.util.Arrays;
34 | import java.util.List;
35 | import java.util.Locale;
36 | import java.util.Set;
37 | import java.util.TreeSet;
38 | import org.apache.log4j.Level;
39 | import org.apache.log4j.Logger;
40 | import org.apache.log4j.varia.NullAppender;
41 | import org.zaproxy.zap.Version;
42 | import org.zaproxy.zap.control.AddOn;
43 | import org.zaproxy.zap.control.AddOn.Status;
44 | import org.zaproxy.zap.control.ZapAddOnXmlFile;
45 |
46 | /** A task for add-ons in zap-extensions repo. */
47 | public abstract class AddOnsTask {
48 |
49 | static {
50 | NullAppender na = new NullAppender();
51 | Logger.getRootLogger().addAppender(na);
52 | Logger.getRootLogger().setLevel(Level.OFF);
53 | }
54 |
55 | private static final String ZAP_ADD_ON_FILE_NAME = "ZapAddOn.xml";
56 |
57 | protected static Set getAllAddOns() throws IOException {
58 | Set addOns = new TreeSet<>();
59 | addAddOns(addOns, Paths.get("../zap-extensions/src"));
60 | addAddOns(addOns, Paths.get("../zap-extensions_beta/src"));
61 | addAddOns(addOns, Paths.get("../zap-extensions_alpha/src"));
62 | return addOns;
63 | }
64 |
65 | private static void addAddOns(final Set addOns, Path path) throws IOException {
66 | Files.walkFileTree(
67 | path,
68 | new SimpleFileVisitor() {
69 |
70 | @Override
71 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
72 | throws IOException {
73 | if (isValidZapAddOnXmlFile(file)) {
74 | try (InputStream is =
75 | new BufferedInputStream(Files.newInputStream(file))) {
76 | Path addOnDir = file.getParent();
77 | String addOnId = addOnDir.getFileName().toString();
78 | ZapAddOnXmlFile zapAddOnXmlFile = new ZapAddOnXmlFile(is);
79 | addOns.add(
80 | new AddOnData(
81 | addOnDir,
82 | addOnId,
83 | zapAddOnXmlFile.getName(),
84 | zapAddOnXmlFile.getVersion(),
85 | AddOn.Status.valueOf(zapAddOnXmlFile.getStatus()),
86 | zapAddOnXmlFile.getChanges()));
87 | }
88 | }
89 | return FileVisitResult.CONTINUE;
90 | }
91 | });
92 | }
93 |
94 | private static boolean isValidZapAddOnXmlFile(Path file) {
95 | if (ZAP_ADD_ON_FILE_NAME.equals(file.getFileName().toString())) {
96 | // Ignore example ZapAddOn.xml file
97 | return !file.toString().contains("src/org/zaproxy/zap/extension/ZapAddOn.xml");
98 | }
99 | return false;
100 | }
101 |
102 | protected static class AddOnData implements Comparable {
103 |
104 | private final Path dir;
105 | private final String id;
106 | private final String name;
107 | private final Version version;
108 | private final AddOn.Status status;
109 | private final List changes;
110 |
111 | public AddOnData(
112 | Path dir, String id, String name, Version version, Status status, String changes) {
113 | super();
114 | this.dir = dir;
115 | this.id = id;
116 | this.name = name;
117 | this.version = version;
118 | this.status = status;
119 | this.changes = prepareChanges(changes);
120 | }
121 |
122 | public Path getDir() {
123 | return dir;
124 | }
125 |
126 | public String getId() {
127 | return id;
128 | }
129 |
130 | public String getName() {
131 | return name;
132 | }
133 |
134 | public Version getVersion() {
135 | return version;
136 | }
137 |
138 | public AddOn.Status getStatus() {
139 | return status;
140 | }
141 |
142 | public List getChanges() {
143 | return changes;
144 | }
145 |
146 | @Override
147 | public int compareTo(AddOnData other) {
148 | if (other == null) {
149 | return 1;
150 | }
151 |
152 | int result = status.compareTo(other.status);
153 | if (result != 0) {
154 | return -result;
155 | }
156 |
157 | return Collator.getInstance(Locale.ENGLISH).compare(id, other.id);
158 | }
159 |
160 | private static List prepareChanges(String changes) {
161 | List preparedChanges = new ArrayList<>(Arrays.asList(changes.split("
")));
162 | for (int i = 0; i < preparedChanges.size(); i++) {
163 | String string = preparedChanges.get(i).trim();
164 | if (string.isEmpty()) {
165 | preparedChanges.remove(i);
166 | i--;
167 | } else {
168 | preparedChanges.set(
169 | i,
170 | string.replaceAll("^\\t*", "")
171 | .replaceAll("^ *", "")
172 | .replaceAll("^(\\r?\\n)*", "")
173 | .replaceAll("(\\r?\\n)*$", ""));
174 | }
175 | }
176 | return preparedChanges;
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/src/main/java/org/zaproxy/admin/CheckLatestReleaseNotes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2017 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.File;
24 | import java.io.FilenameFilter;
25 | import java.io.IOException;
26 | import java.nio.charset.StandardCharsets;
27 | import java.nio.file.Files;
28 | import java.util.HashSet;
29 | import java.util.Set;
30 | import java.util.TreeMap;
31 |
32 | /**
33 | * Command line tool for checking the latest release notes dont contain issues in previous ones.
34 | *
35 | * @author simon
36 | */
37 | public class CheckLatestReleaseNotes {
38 |
39 | private static final String RELEASE_NOTES_PATH =
40 | "../zap-core-help/addOns/help/src/main/javahelp/contents/releases/";
41 |
42 | private static Set getIssues(File f) throws IOException {
43 | Set set = new HashSet();
44 | try (BufferedReader reader = Files.newBufferedReader(f.toPath(), StandardCharsets.UTF_8)) {
45 | while (true) {
46 | String line = reader.readLine();
47 | if (line == null) {
48 | break;
49 | }
50 | if (line.startsWith("Issue ")) {
51 | String[] split = line.split(" ", 0);
52 | set.add(Integer.parseInt(split[1]));
53 | }
54 | }
55 | }
56 | return set;
57 | }
58 |
59 | public static void main(String[] args) throws IOException {
60 | TreeMap> map = new TreeMap>();
61 | File relNotesDir = new File(RELEASE_NOTES_PATH);
62 | if (!relNotesDir.exists()) {
63 | System.out.println("No such directory : " + relNotesDir.getAbsolutePath());
64 | return;
65 | }
66 | File[] relNotes =
67 | relNotesDir.listFiles(
68 | new FilenameFilter() {
69 |
70 | @Override
71 | public boolean accept(File dir, String name) {
72 | return name.endsWith(".html") && !name.startsWith("releases");
73 | }
74 | });
75 |
76 | for (File relNote : relNotes) {
77 | map.put(relNote.getName(), getIssues(relNote));
78 | }
79 |
80 | Set latest = null;
81 | for (String key : map.descendingKeySet()) {
82 | if (latest == null) {
83 | latest = map.get(key);
84 | } else {
85 | for (Integer issue : map.get(key)) {
86 | if (latest.contains(issue)) {
87 | System.out.println("Issue : " + issue + " was included in " + key);
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/org/zaproxy/admin/CountDownloads.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2015 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import java.io.IOException;
23 | import net.sf.json.JSONArray;
24 | import net.sf.json.JSONObject;
25 |
26 | /**
27 | * Command line tool for printing a summary of the tag assets downloaded from GitHub.
28 | *
29 | * @author simon
30 | */
31 | public class CountDownloads {
32 |
33 | // Note 100 is the maximum page size allowed - will need to use paging to get any more
34 | private static final String RELEASES_URL =
35 | "https://api.github.com/repos/zaproxy/zaproxy/releases";
36 |
37 | private static final String TAG_URL =
38 | "https://api.github.com/repos/zaproxy/zaproxy/releases/tags/";
39 |
40 | private static void parseRelease(JSONObject tag) throws Exception {
41 | if (tag == null) {
42 | return;
43 | }
44 | String tagName = tag.getString("tag_name");
45 | System.out.println("Tag " + tagName);
46 |
47 | JSONArray assets = tag.getJSONArray("assets");
48 | int total = 0;
49 | for (int j = 0; j < assets.size(); j++) {
50 | JSONObject asset = assets.getJSONObject(j);
51 | int count = asset.getInt("download_count");
52 | total += count;
53 | // System.out.println("\t" + asset.getString("name") + " : " + count);
54 | }
55 | System.out.println("\tTotal Downloads: " + total);
56 | }
57 |
58 | private static JSONObject getRelease(String tag) throws Exception {
59 | try {
60 | return JSONObject.fromObject(Utils.readUrl(TAG_URL + tag));
61 | } catch (IOException e) {
62 | System.out.println("Tag " + tag + "\n\tNo stats");
63 | return null;
64 | }
65 | }
66 |
67 | public static void main(String[] args) throws Exception {
68 | // Loop through tags, print names
69 | String jsonStr = Utils.readUrl(RELEASES_URL);
70 |
71 | JSONArray json = JSONArray.fromObject(jsonStr);
72 |
73 | if (json.size() >= 100) {
74 | System.out.println(
75 | "WARNING: 100 tags returned - will need to implement paging to get the rest!");
76 | }
77 |
78 | for (int i = 0; i < json.size(); i++) {
79 | parseRelease(json.getJSONObject(i));
80 | }
81 |
82 | // Explicitly request the most recent main releases
83 | parseRelease(getRelease("v2.10.0"));
84 | parseRelease(getRelease("v2.9.0"));
85 | parseRelease(getRelease("v2.8.0"));
86 | parseRelease(getRelease("2.7.0"));
87 | parseRelease(getRelease("2.6.0"));
88 | parseRelease(getRelease("2.5.0"));
89 | parseRelease(getRelease("2.4.3"));
90 | parseRelease(getRelease("2.4.2"));
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/org/zaproxy/admin/GenerateReleaseNotes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2015 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import java.util.Arrays;
23 | import java.util.Collection;
24 | import java.util.HashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 | import org.apache.commons.text.StringEscapeUtils;
28 | import org.kohsuke.github.GHIssue;
29 | import org.kohsuke.github.GHIssueState;
30 | import org.kohsuke.github.GHLabel;
31 | import org.kohsuke.github.GHRepository;
32 | import org.kohsuke.github.GitHub;
33 |
34 | /**
35 | * Command line tool for generating release notes from GitHub issues and tags. For now the variables
36 | * are hardcoded - at some point they should be made parameters.
37 | *
38 | * @author simon
39 | */
40 | public class GenerateReleaseNotes {
41 |
42 | static enum IssueType {
43 | dev,
44 | bug,
45 | ignore,
46 | unk
47 | };
48 |
49 | private static final String REPO = "zaproxy/zaproxy";
50 | private static final int MILESTONE_NUMBER = 9;
51 |
52 | public static void main(String[] args) throws Exception {
53 |
54 | GHRepository ghRepo = GitHub.connectAnonymously().getRepository(REPO);
55 | List issues =
56 | ghRepo.getIssues(GHIssueState.CLOSED, ghRepo.getMilestone(MILESTONE_NUMBER));
57 |
58 | Map devIssuesMap = new HashMap();
59 | Map bugIssuesMap = new HashMap();
60 | Map unkIssuesMap = new HashMap();
61 | Map issueTagsMap = new HashMap();
62 |
63 | for (GHIssue issue : issues) {
64 | IssueType issueType = IssueType.unk;
65 | Collection labels = issue.getLabels();
66 | StringBuilder sb = new StringBuilder();
67 | for (GHLabel label : labels) {
68 | String tag = label.getName();
69 | sb.append(tag);
70 | sb.append(" ");
71 |
72 | if (tag.equalsIgnoreCase("development")
73 | || tag.equalsIgnoreCase("enhancement")
74 | || tag.equalsIgnoreCase("Type-enhancement")) {
75 | issueType = IssueType.dev;
76 | // Carry on in case its got another 'overiding' tag
77 | }
78 | if (tag.equalsIgnoreCase("bug") || tag.equalsIgnoreCase("Type-defect")) {
79 | issueType = IssueType.bug;
80 | // Carry on in case its got another 'overiding' tag
81 | }
82 | if (tag.equalsIgnoreCase("API Client")
83 | || tag.equalsIgnoreCase("Docker")
84 | || tag.equalsIgnoreCase("third-party")
85 | || tag.equalsIgnoreCase("jenkins")
86 | || tag.equalsIgnoreCase("Component-Docs")
87 | || tag.equalsIgnoreCase("invalid")
88 | || tag.equalsIgnoreCase("duplicate")
89 | || tag.equalsIgnoreCase("historic")
90 | || tag.equalsIgnoreCase("wontfix")
91 | || tag.equalsIgnoreCase("minor")
92 | || tag.equalsIgnoreCase("add-on")
93 | || tag.equalsIgnoreCase("Type-Other")
94 | || tag.equalsIgnoreCase("Type-review")
95 | || tag.equalsIgnoreCase("Type-task")
96 | || tag.equalsIgnoreCase("competition")
97 | || tag.equalsIgnoreCase("InsufficientEvidence")
98 | || tag.equalsIgnoreCase("question")
99 | || tag.equalsIgnoreCase("weekly")) {
100 | issueType = IssueType.ignore;
101 | break;
102 | }
103 | }
104 | int number = issue.getNumber();
105 | issueTagsMap.put(number, sb.toString());
106 |
107 | switch (issueType) {
108 | case dev:
109 | devIssuesMap.put(number, issue.getTitle());
110 | break;
111 | case bug:
112 | bugIssuesMap.put(number, issue.getTitle());
113 | break;
114 | case unk:
115 | unkIssuesMap.put(number, issue.getTitle());
116 | break;
117 | case ignore:
118 | break;
119 | }
120 | }
121 |
122 | System.out.println("Enhancements
");
123 | System.out.println("");
124 | Object[] devIssues = devIssuesMap.keySet().toArray();
125 | Arrays.sort(devIssues);
126 | for (Object key : devIssues) {
127 | printIssue(devIssuesMap, key);
128 | }
129 | System.out.println("
");
130 | System.out.println("");
131 |
132 | System.out.println("Bug fixes
");
133 | System.out.println("");
134 | Object[] bugIssues = bugIssuesMap.keySet().toArray();
135 | Arrays.sort(bugIssues);
136 | for (Object key : bugIssues) {
137 | printIssue(bugIssuesMap, key);
138 | }
139 | System.out.println("
");
140 | System.out.println("");
141 |
142 | if (unkIssuesMap.size() > 0) {
143 | System.out.println("Unclassified:");
144 | System.out.println("");
145 | Object[] unkIssues = unkIssuesMap.keySet().toArray();
146 | Arrays.sort(unkIssues);
147 | for (Object key : unkIssues) {
148 | System.out.println("Issue " + key + " : " + unkIssuesMap.get(key));
149 | System.out.println("\tLink: https://github.com/zaproxy/zaproxy/issues/" + key);
150 | String tags = issueTagsMap.get(key);
151 | if (tags != null && tags.length() > 0) {
152 | System.out.println("\tTags: " + issueTagsMap.get(key));
153 | }
154 | }
155 | }
156 | }
157 |
158 | private static void printIssue(Map issues, Object number) {
159 | System.out.print("Issue ");
162 | System.out.print(number);
163 | System.out.print(" : ");
164 | System.out.print(StringEscapeUtils.escapeHtml4(issues.get(number)));
165 | System.out.print("\n");
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/org/zaproxy/admin/PendingAddOnReleases.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2016 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import java.nio.file.Paths;
23 | import java.time.LocalDate;
24 | import java.time.Period;
25 | import java.time.ZoneOffset;
26 | import java.util.Iterator;
27 | import java.util.Set;
28 | import java.util.TreeSet;
29 | import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
30 | import org.zaproxy.zap.control.AddOn;
31 | import org.zaproxy.zap.control.AddOn.Status;
32 | import org.zaproxy.zap.control.AddOnCollection;
33 | import org.zaproxy.zap.utils.ZapXmlConfiguration;
34 |
35 | public class PendingAddOnReleases extends AddOnsTask {
36 |
37 | private static final String ZAP_VERSIONS_FILE_NAME = "ZapVersions-2.7.xml";
38 |
39 | public static void main(String[] args) throws Exception {
40 | LocalDate now = LocalDate.now(ZoneOffset.UTC);
41 | boolean showChanges = true;
42 |
43 | ZapXmlConfiguration zapVersions =
44 | new ZapXmlConfiguration(Paths.get(ZAP_VERSIONS_FILE_NAME).toFile());
45 | AddOnCollection addOnCollection =
46 | new AddOnCollection(zapVersions, AddOnCollection.Platform.daily);
47 |
48 | zapVersions.setExpressionEngine(new XPathExpressionEngine());
49 |
50 | Set addOns = getAllAddOns();
51 | int totalAddOns = addOns.size();
52 |
53 | Set unreleasedAddOns = new TreeSet<>();
54 | Set unchangedAddOns = new TreeSet<>();
55 |
56 | for (Iterator it = addOns.iterator(); it.hasNext(); ) {
57 | AddOnData addOnData = it.next();
58 | AddOn addOn = addOnCollection.getAddOn(addOnData.getId());
59 | if (addOn == null) {
60 | unreleasedAddOns.add(addOnData);
61 | it.remove();
62 | } else if (addOn.getVersion().compareTo(addOnData.getVersion()) >= 0) {
63 | it.remove();
64 | } else if (addOnData.getChanges().isEmpty()) {
65 | unchangedAddOns.add(addOnData);
66 | it.remove();
67 | }
68 | }
69 |
70 | if (!unreleasedAddOns.isEmpty()) {
71 | System.out.println("=============================");
72 | System.out.println(
73 | "Unreleased add-ons (" + unreleasedAddOns.size() + " of " + totalAddOns + ")");
74 | System.out.println("=============================");
75 | for (AddOnData addOn : unreleasedAddOns) {
76 | System.out.println(
77 | addOn.getStatus() + "\t" + addOn.getName() + " v" + addOn.getVersion());
78 | }
79 | System.out.println("=============================\n");
80 | }
81 |
82 | if (!addOns.isEmpty()) {
83 | System.out.println("=======================================");
84 | System.out.println(
85 | "New versions pending release (" + addOns.size() + " of " + totalAddOns + ")");
86 | System.out.println("=======================================");
87 | Status currentStatus = null;
88 | for (AddOnData addOn : addOns) {
89 | if (currentStatus != addOn.getStatus()) {
90 | currentStatus = addOn.getStatus();
91 | System.out.println(currentStatus);
92 | }
93 | LocalDate releaseDate =
94 | LocalDate.parse(zapVersions.getString("/addon_" + addOn.getId() + "/date"));
95 | System.out.println(
96 | " * "
97 | + addOn.getName()
98 | + " v"
99 | + addOn.getVersion()
100 | + " ("
101 | + Period.between(releaseDate, now)
102 | + ")");
103 |
104 | if (showChanges) {
105 | for (String change : addOn.getChanges()) {
106 | System.out.println(" - " + change);
107 | }
108 | }
109 | }
110 | System.out.println("=======================================\n");
111 | }
112 |
113 | if (!unchangedAddOns.isEmpty()) {
114 | System.out.println("=============================");
115 | System.out.println(
116 | "Unchanged add-ons (" + unchangedAddOns.size() + " of " + totalAddOns + ")");
117 | System.out.println("=============================");
118 | for (AddOnData addOn : unchangedAddOns) {
119 | System.out.println(
120 | addOn.getStatus() + "\t" + addOn.getName() + " v" + addOn.getVersion());
121 | }
122 | System.out.println("=============================\n");
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/org/zaproxy/admin/Utils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2018 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import java.io.BufferedReader;
23 | import java.io.IOException;
24 | import java.io.InputStreamReader;
25 | import java.net.URI;
26 | import java.net.URISyntaxException;
27 | import java.nio.charset.StandardCharsets;
28 |
29 | /** Utilities for common tasks. */
30 | public class Utils {
31 |
32 | private Utils() {
33 | // Utility class.
34 | }
35 |
36 | public static String readUrl(String urlString) throws IOException, URISyntaxException {
37 | try (BufferedReader reader =
38 | new BufferedReader(
39 | new InputStreamReader(
40 | new URI(urlString).toURL().openStream(), StandardCharsets.UTF_8))) {
41 | StringBuilder builder = new StringBuilder();
42 | int read;
43 | char[] chars = new char[1024];
44 | while ((read = reader.read(chars)) != -1) {
45 | builder.append(chars, 0, read);
46 | }
47 | return builder.toString();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/resources/org/zaproxy/admin/resources/help/contents/addon.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @@name@@
7 |
8 |
9 |
10 | @@name@@
11 | @@intro@@
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/org/zaproxy/admin/resources/help/contents/images/cake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zaproxy/zap-admin/ab815105beadb225f19c174024e0d08831b6f353/src/main/resources/org/zaproxy/admin/resources/help/contents/images/cake.png
--------------------------------------------------------------------------------
/src/main/resources/org/zaproxy/admin/resources/help/helpset.hs:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | @@name@@ | ZAP Extension
7 |
8 |
9 | top
10 |
11 |
12 |
13 |
14 | TOC
15 |
16 | org.zaproxy.zap.extension.help.ZapTocView
17 | toc.xml
18 |
19 |
20 |
21 | Index
22 |
23 | javax.help.IndexView
24 | index.xml
25 |
26 |
27 |
28 | Search
29 |
30 | javax.help.SearchView
31 |
32 | JavaHelpSearch
33 |
34 |
35 |
36 |
37 | Favorites
38 |
39 | javax.help.FavoritesView
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/main/resources/org/zaproxy/admin/resources/help/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/org/zaproxy/admin/resources/help/map.jhm:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/org/zaproxy/admin/resources/help/toc.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/test/java/org/zaproxy/admin/ValidateZapVersionsXmlTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Zed Attack Proxy (ZAP) and its related class files.
3 | *
4 | * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5 | *
6 | * Copyright 2018 The ZAP Development Team
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | package org.zaproxy.admin;
21 |
22 | import static org.assertj.core.api.Assertions.assertThat;
23 |
24 | import java.io.File;
25 | import java.net.URISyntaxException;
26 | import java.net.URL;
27 | import java.nio.file.Paths;
28 | import org.apache.log4j.Logger;
29 | import org.apache.log4j.varia.NullAppender;
30 | import org.junit.jupiter.api.BeforeAll;
31 | import org.junit.jupiter.params.ParameterizedTest;
32 | import org.junit.jupiter.params.provider.EnumSource;
33 | import org.zaproxy.zap.control.AddOnCollection;
34 | import org.zaproxy.zap.control.AddOnCollection.Platform;
35 | import org.zaproxy.zap.utils.ZapXmlConfiguration;
36 |
37 | /** Validates that ZAP is able to load the {@code ZapVersions.xml} files. */
38 | public class ValidateZapVersionsXmlTest {
39 |
40 | @BeforeAll
41 | public static void suppressLogging() {
42 | Logger.getRootLogger().addAppender(new NullAppender());
43 | }
44 |
45 | @ParameterizedTest
46 | @EnumSource(value = Platform.class)
47 | public void shouldLoadCurrentVersion(Platform platform) throws Exception {
48 | // Given
49 | File zapVersionsCurr = resource("/ZapVersions-2.7.xml");
50 | // When
51 | AddOnCollection aoc =
52 | new AddOnCollection(new ZapXmlConfiguration(zapVersionsCurr), platform);
53 | // Then
54 | assertReleaseAndAddOnsPresent(zapVersionsCurr, aoc, platform);
55 | }
56 |
57 | private static void assertReleaseAndAddOnsPresent(
58 | File zapVersionsFile, AddOnCollection aoc, Platform platform) {
59 | assertThat(aoc.getZapRelease())
60 | .as(
61 | "Release not found in %s using %s platform.",
62 | zapVersionsFile.getName(), platform)
63 | .isNotNull();
64 | assertThat(aoc.getAddOns())
65 | .as("No add-ons in %s using %s platform.", zapVersionsFile.getName(), platform)
66 | .isNotEmpty();
67 | }
68 |
69 | @ParameterizedTest
70 | @EnumSource(value = Platform.class)
71 | public void shouldLoadDevVersion(Platform platform) throws Exception {
72 | // Given
73 | File zapVersionsDev = resource("/ZapVersions-dev.xml");
74 | // When
75 | AddOnCollection aoc =
76 | new AddOnCollection(new ZapXmlConfiguration(zapVersionsDev), platform);
77 | // Then
78 | assertReleaseAndAddOnsPresent(zapVersionsDev, aoc, platform);
79 | }
80 |
81 | @ParameterizedTest
82 | @EnumSource(value = Platform.class)
83 | public void shouldLoadNonAddOnsVariant(Platform platform) throws Exception {
84 | // Given
85 | File zapVersions = resource("/ZapVersions.xml");
86 | // When
87 | AddOnCollection aoc = new AddOnCollection(new ZapXmlConfiguration(zapVersions), platform);
88 | // Then
89 | assertThat(aoc.getZapRelease()).isNotNull();
90 | }
91 |
92 | private static File resource(String path) {
93 | URL resourceURL = ValidateZapVersionsXmlTest.class.getResource(path);
94 | assertThat(resourceURL).as("File %s not found.", path).isNotNull();
95 |
96 | try {
97 | return Paths.get(resourceURL.toURI()).toFile();
98 | } catch (URISyntaxException e) {
99 | throw new RuntimeException(e);
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------