-
Notifications
You must be signed in to change notification settings - Fork 16
feat/CUS-9990-Added class to get latest downloaded zip, extract files and store filepaths inside zip #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
akhil-testsigma
merged 1 commit into
dev
from
feat/CUS-9990-Added-class-to-get-latest-downloaded-zip,-extract-files-and-store-filepaths-inside-zip
Jan 11, 2026
Merged
feat/CUS-9990-Added class to get latest downloaded zip, extract files and store filepaths inside zip #298
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project | ||
| xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <groupId>com.testsigma.addons</groupId> | ||
| <artifactId>unzipfileandupload</artifactId> | ||
| <version>1.0.3</version> | ||
| <packaging>jar</packaging> | ||
|
|
||
| <properties> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| <maven.compiler.source>11</maven.compiler.source> | ||
| <maven.compiler.target>11</maven.compiler.target> | ||
| <testsigma.sdk.version>1.2.8_cloud</testsigma.sdk.version> | ||
| <junit.jupiter.version>5.8.0-M1</junit.jupiter.version> | ||
| <testsigma.addon.maven.plugin>1.0.0</testsigma.addon.maven.plugin> | ||
| <maven.source.plugin.version>3.2.1</maven.source.plugin.version> | ||
| <lombok.version>1.18.30</lombok.version> | ||
|
|
||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>com.testsigma</groupId> | ||
| <artifactId>testsigma-java-sdk</artifactId> | ||
| <version>${testsigma.sdk.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.projectlombok</groupId> | ||
| <artifactId>lombok</artifactId> | ||
| <version>${lombok.version}</version> | ||
| <optional>true</optional> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter-api</artifactId> | ||
| <version>${junit.jupiter.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.testng</groupId> | ||
| <artifactId>testng</artifactId> | ||
| <version>6.14.3</version> | ||
| </dependency> | ||
| <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --> | ||
| <dependency> | ||
| <groupId>org.seleniumhq.selenium</groupId> | ||
| <artifactId>selenium-java</artifactId> | ||
| <version>4.33.0</version> | ||
| </dependency> | ||
| <!-- https://mvnrepository.com/artifact/io.appium/java-client --> | ||
| <dependency> | ||
| <groupId>io.appium</groupId> | ||
| <artifactId>java-client</artifactId> | ||
| <version>9.4.0</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-annotations</artifactId> | ||
| <version>2.13.0</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.commons</groupId> | ||
| <artifactId>commons-lang3</artifactId> | ||
| <version>3.17.0</version> | ||
| </dependency> | ||
|
|
||
| </dependencies> | ||
| <build> | ||
| <finalName>unzipfileandupload</finalName> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-shade-plugin</artifactId> | ||
| <version>3.2.4</version> | ||
| <executions> | ||
| <execution> | ||
| <phase>package</phase> | ||
| <goals> | ||
| <goal>shade</goal> | ||
| </goals> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-source-plugin</artifactId> | ||
| <version>${maven.source.plugin.version}</version> | ||
| <executions> | ||
| <execution> | ||
| <id>attach-sources</id> | ||
| <goals> | ||
| <goal>jar</goal> | ||
| </goals> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </project> |
121 changes: 121 additions & 0 deletions
121
...andupload/src/main/java/com/testsigma/addons/web/ExtractLatestDownloadedZipFilePaths.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| package com.testsigma.addons.web; | ||
|
|
||
| import com.testsigma.addons.web.util.DownloadUtilities; | ||
| import com.testsigma.addons.web.util.DownloadUtilitiesFactory; | ||
| import com.testsigma.sdk.ApplicationType; | ||
| import com.testsigma.sdk.Result; | ||
| import com.testsigma.sdk.WebAction; | ||
| import com.testsigma.sdk.annotation.Action; | ||
| import com.testsigma.sdk.annotation.RunTimeData; | ||
| import com.testsigma.sdk.annotation.TestData; | ||
| import lombok.Data; | ||
| import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| import org.openqa.selenium.NoSuchElementException; | ||
|
|
||
| import java.io.File; | ||
| import java.io.FileOutputStream; | ||
| import java.io.InputStream; | ||
| import java.io.OutputStream; | ||
| import java.util.Enumeration; | ||
| import java.util.zip.ZipEntry; | ||
| import java.util.zip.ZipFile; | ||
|
|
||
| @Data | ||
| @Action( | ||
| actionText = "ZIP: Extract complete file paths from latest zip file in the downloads and store it in runtime-variable variable-name", | ||
| description = "Extracts absolute file paths (excluding __MACOSX entries) from the latest downloaded zip file and stores them in a runtime variable", | ||
| applicationType = ApplicationType.WEB | ||
| ) | ||
| public class ExtractLatestDownloadedZipFilePaths extends WebAction { | ||
|
|
||
| @TestData(reference = "variable-name", isRuntimeVariable = true) | ||
| private com.testsigma.sdk.TestData runtimeVariable; | ||
|
|
||
| @RunTimeData | ||
| private com.testsigma.sdk.RunTimeData runTimeData; | ||
|
|
||
| @Override | ||
| protected Result execute() throws NoSuchElementException { | ||
| Result result = Result.SUCCESS; | ||
|
|
||
| DownloadUtilities downloadUtilities = | ||
| DownloadUtilitiesFactory.create(driver, logger); | ||
|
|
||
| try { | ||
| logger.info("Initiated execution"); | ||
|
|
||
| // Get latest downloaded ZIP file (copied to agent temp location) | ||
| File downloadedZipFile = | ||
| downloadUtilities.copyFileFromDownloads("zip", null); | ||
|
|
||
| logger.info("ZIP local path: " + downloadedZipFile.getAbsolutePath()); | ||
|
|
||
| StringBuilder filePaths = new StringBuilder(); | ||
|
|
||
| try (ZipFile zipFile = new ZipFile(downloadedZipFile)) { | ||
| Enumeration<? extends ZipEntry> entries = zipFile.entries(); | ||
| boolean first = true; | ||
|
|
||
| // Base directory where ZIP exists | ||
| File zipBaseDir = downloadedZipFile.getParentFile(); | ||
|
|
||
| while (entries.hasMoreElements()) { | ||
| ZipEntry entry = entries.nextElement(); | ||
|
|
||
| if (entry.isDirectory() || entry.getName().startsWith("__MACOSX")) { | ||
| continue; | ||
| } | ||
|
|
||
| File fullPath = new File(zipBaseDir, entry.getName()); | ||
|
|
||
| File parent = fullPath.getParentFile(); | ||
| if (!parent.exists()) { | ||
| parent.mkdirs(); | ||
| } | ||
|
|
||
| try (InputStream is = zipFile.getInputStream(entry); | ||
| OutputStream os = new FileOutputStream(fullPath)) { | ||
| byte[] buffer = new byte[1024]; | ||
| int length; | ||
| while ((length = is.read(buffer)) > 0) { | ||
| os.write(buffer, 0, length); | ||
| } | ||
| } | ||
|
|
||
| if (!first) { | ||
| filePaths.append(", "); | ||
| } | ||
|
|
||
| filePaths.append(fullPath.getAbsolutePath()); | ||
| first = false; | ||
| } | ||
| } | ||
|
|
||
| if (filePaths.length() == 0) { | ||
| throw new Exception("Zip contains no valid files to extract"); | ||
| } | ||
|
|
||
| runTimeData.setKey(runtimeVariable.getValue().toString()); | ||
| runTimeData.setValue(filePaths.toString()); | ||
|
|
||
| logger.info("Extracted file paths: " + filePaths); | ||
|
|
||
| setSuccessMessage( | ||
| "Successfully extracted file paths from the zip and stored in runtime variable '" | ||
| + runTimeData.getKey() + "' with value: " + runTimeData.getValue() | ||
| ); | ||
|
|
||
| } catch (RuntimeException e) { | ||
| logger.warn("Unable to locate latest ZIP file " + e); | ||
| setErrorMessage("Unable to find the latest zip file in downloads"); | ||
| result = Result.FAILED; | ||
|
|
||
| } catch (Exception e) { | ||
| logger.warn("ZIP processing failed " + ExceptionUtils.getStackTrace(e)); | ||
| setErrorMessage("Failed to extract file paths from zip: " + ExceptionUtils.getMessage(e)); | ||
| result = Result.FAILED; | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
| } | ||
76 changes: 76 additions & 0 deletions
76
unzipfileandupload/src/main/java/com/testsigma/addons/web/UnzipCSVGZFile.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| package com.testsigma.addons.web; | ||
|
|
||
| import com.testsigma.sdk.WebAction; | ||
| import com.testsigma.sdk.ApplicationType; | ||
| import com.testsigma.sdk.annotation.Action; | ||
| import com.testsigma.sdk.annotation.TestData; | ||
| import com.testsigma.sdk.annotation.RunTimeData; | ||
|
|
||
| import lombok.Data; | ||
|
|
||
| import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| import java.io.File; | ||
| import java.io.FileInputStream; | ||
| import java.io.FileOutputStream; | ||
| import java.io.IOException; | ||
| import java.util.zip.GZIPInputStream; | ||
| import java.util.zip.ZipEntry; | ||
| import java.util.zip.ZipInputStream; | ||
|
|
||
| @Data | ||
| @Action(actionText = "Unzip the .CSV.GZ file absolutefilepath to destination destfilepath and store the filepath into a variable testdata", | ||
| description = "Unzip the .CSV.GZ file and store the extracted file path", | ||
| applicationType = ApplicationType.WEB, | ||
| useCustomScreenshot = false) | ||
| public class UnzipCSVGZFile extends WebAction { | ||
|
|
||
| @TestData(reference = "absolutefilepath") | ||
| private com.testsigma.sdk.TestData testData1; | ||
| @TestData(reference = "destfilepath") | ||
| private com.testsigma.sdk.TestData testData2; | ||
| @TestData(reference = "testdata" , isRuntimeVariable = true) | ||
| private com.testsigma.sdk.TestData testData3; | ||
|
|
||
| @RunTimeData | ||
| private com.testsigma.sdk.RunTimeData runTimeData; | ||
|
|
||
| @Override | ||
| public com.testsigma.sdk.Result execute() { | ||
| //Your Awesome code starts here | ||
| logger.info("Initiating execution"); | ||
| com.testsigma.sdk.Result result = com.testsigma.sdk.Result.SUCCESS; | ||
| try { | ||
| String zipFilePath = testData1.getValue().toString(); | ||
| String destDir = testData2.getValue().toString(); | ||
| String fileNameUpload = "output" + System.currentTimeMillis() + ".csv"; | ||
| String filePath = destDir + File.separator + fileNameUpload; | ||
| unzip(zipFilePath, filePath); | ||
| logger.info("Storing the filepath in runtime variable"); | ||
| runTimeData.setValue(filePath); | ||
| runTimeData.setKey(testData3.getValue().toString()); | ||
| logger.info("Stored successfully"); | ||
| setSuccessMessage("File was unzipped and stored successfully in : " + testData3.getValue().toString() + " and the filepath is :" + filePath); | ||
| } catch (Exception e) { | ||
| String errorMessage = ExceptionUtils.getStackTrace(e); | ||
| result = com.testsigma.sdk.Result.FAILED; | ||
| setErrorMessage(errorMessage); | ||
| logger.warn(errorMessage); | ||
| } | ||
| return result; | ||
| } | ||
| private void unzip(String zipFilePath, String destFilepath) throws IOException { | ||
| logger.info("Extracting the file"); | ||
| FileInputStream fis = new FileInputStream(zipFilePath); | ||
| GZIPInputStream gis = new GZIPInputStream(fis); | ||
| FileOutputStream fos = new FileOutputStream(destFilepath); | ||
| byte[] buffer = new byte[1024]; | ||
| int len; | ||
| while ((len = gis.read(buffer)) > 0) { | ||
| fos.write(buffer, 0, len); | ||
| } | ||
| fos.close(); | ||
| gis.close(); | ||
| fis.close(); | ||
| logger.info("Successfully extracted to location: " + destFilepath); | ||
| } | ||
|
Comment on lines
+61
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resource leak in unzip method. The streams are not closed with try-with-resources. If an exception occurs during decompression, the streams may remain open, leading to resource leaks. 🛡️ Proposed fix private void unzip(String zipFilePath, String destFilepath) throws IOException {
logger.info("Extracting the file");
- FileInputStream fis = new FileInputStream(zipFilePath);
- GZIPInputStream gis = new GZIPInputStream(fis);
- FileOutputStream fos = new FileOutputStream(destFilepath);
- byte[] buffer = new byte[1024];
- int len;
- while ((len = gis.read(buffer)) > 0) {
- fos.write(buffer, 0, len);
+ try (FileInputStream fis = new FileInputStream(zipFilePath);
+ GZIPInputStream gis = new GZIPInputStream(fis);
+ FileOutputStream fos = new FileOutputStream(destFilepath)) {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = gis.read(buffer)) > 0) {
+ fos.write(buffer, 0, len);
+ }
}
- fos.close();
- gis.close();
- fis.close();
logger.info("Successfully extracted to location: " + destFilepath);
}🤖 Prompt for AI Agents |
||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Zip Slip vulnerability: Validate entry paths before extraction.
Malicious ZIP files can contain entries with paths like
../../../etc/passwd. The code directly usesentry.getName()to construct the output path without validating that it stays within the intended extraction directory.Proposed fix to prevent path traversal
🤖 Prompt for AI Agents