Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "ftp"
version = "2.14.0"
version = "2.14.1"
authors = ["Ballerina"]
keywords = ["FTP", "SFTP", "remote file", "file transfer", "client", "service"]
repository = "https://github.com/ballerina-platform/module-ballerina-ftp"
Expand Down Expand Up @@ -45,5 +45,5 @@ path = "./lib/commons-lang3-3.18.0.jar"
[[platform.java21.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "ftp-native"
version = "2.14.0"
path = "../native/build/libs/ftp-native-2.14.0.jar"
version = "2.14.1"
path = "../native/build/libs/ftp-native-2.14.1-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/CompilerPlugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ id = "ftp-compiler-plugin"
class = "io.ballerina.stdlib.ftp.plugin.FtpCompilerPlugin"

[[dependency]]
path = "../compiler-plugin/build/libs/ftp-compiler-plugin-2.14.0.jar"
path = "../compiler-plugin/build/libs/ftp-compiler-plugin-2.14.1-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ distribution-version = "2201.12.0"
[[package]]
org = "ballerina"
name = "ftp"
version = "2.14.0"
version = "2.14.1"
dependencies = [
{org = "ballerina", name = "io"},
{org = "ballerina", name = "jballerina.java"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina/tests/client_endpoint_negative_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function testConnectionWithInvalidConfiguration() returns error? {
public function testReadNonExistingFile() returns error? {
stream<byte[] & readonly, io:Error?>|Error str = (<Client>clientEp)->get("/home/in/nonexisting.txt");
if str is Error {
test:assertEquals(str.message(), "Failed to read file: ftp://wso2:wso2123@127.0.0.1:21212/home/in/nonexisting.txt not found",
test:assertEquals(str.message(), "Failed to read file: ftp://wso2:***@127.0.0.1:21212/home/in/nonexisting.txt not found",
msg = "Unexpected error during the `get` operation of an non-existing file.");
} else {
test:assertFail(msg = "Found a non-error response while accessing a non-existing file path");
Expand Down
2 changes: 1 addition & 1 deletion ballerina/tests/client_endpoint_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ public function testDeleteFile() returns error? {
}
} else {
test:assertEquals(str.message(),
"Failed to read file: ftp://wso2:wso2123@127.0.0.1:21212/home/in/test1.txt not found",
"Failed to read file: ftp://wso2:***@127.0.0.1:21212/home/in/test1.txt not found",
msg = "Correct error is not given when the file is deleted." + str.message());
}
}
Expand Down
2 changes: 1 addition & 1 deletion ballerina/tests/secure_client_endpoint_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ public function testSecureDeleteFileContent() returns error? {
}
} else {
test:assertEquals(str.message(),
"Failed to read file: sftp://wso2:wso2123@127.0.0.1:21213/tempFile1.txt not found",
"Failed to read file: sftp://wso2:***@127.0.0.1:21213/tempFile1.txt not found",
msg = "Correct error is not given when trying to get a non-existing file.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import java.util.HashMap;
import java.util.Map;

import static io.ballerina.stdlib.ftp.transport.server.util.FileTransportUtils.maskUrlPassword;

/**
* Implementation for {@link VfsClientConnector} interface.
*/
Expand All @@ -68,8 +70,9 @@ public VfsClientConnectorImpl(Map<String, String> config)
fileURI = connectorConfig.get(FtpConstants.URI);
path = fsManager.resolveFile(fileURI, opts);
} catch (FileSystemException e) {
String safeUri = maskUrlPassword(fileURI);
throw new RemoteFileSystemConnectorException("Error while connecting to the FTP server with URL: "
+ (fileURI != null ? fileURI : ""), e.getCause());
+ (safeUri != null ? safeUri : ""), e.getCause());
}
}

Expand All @@ -94,7 +97,7 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP
case MKDIR:
if (fileObject.exists()) {
throw new RemoteFileSystemConnectorException("Directory exists: "
+ fileObject.getName().getURI());
+ maskUrlPassword(fileObject.getName().getURI()));
}
fileObject.createFolder();
break;
Expand Down Expand Up @@ -130,7 +133,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP
}
} else {
throw new RemoteFileSystemConnectorException(
"Failed to delete file: " + fileObject.getName().getURI() + " not found");
"Failed to delete file: " + maskUrlPassword(fileObject.getName().getURI())
+ " not found");
}
break;
case RMDIR:
Expand All @@ -141,7 +145,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP
}
} else {
throw new RemoteFileSystemConnectorException(
"Failed to delete directory: " + fileObject.getName().getURI() + " not found");
"Failed to delete directory: " + maskUrlPassword(fileObject.getName().getURI())
+ " not found");
}
break;
case RENAME:
Expand All @@ -157,15 +162,16 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP
fileObject.moveTo(finalPath);
} else {
throw new RemoteFileSystemConnectorException(
"The file at " + newPath.getURL().toString()
"The file at " + maskUrlPassword(newPath.getURL().toString())
+ " already exists or it is a directory");
}
}
}
}
} else {
throw new RemoteFileSystemConnectorException(
"Failed to rename file: " + fileObject.getName().getURI() + " not found");
"Failed to rename file: " + maskUrlPassword(fileObject.getName().getURI())
+ " not found");
}
break;
case GET:
Expand All @@ -180,7 +186,8 @@ public void send(RemoteFileSystemMessage message, FtpAction action, String fileP
pathClose = false;
} else {
throw new RemoteFileSystemConnectorException(
"Failed to read file: " + fileObject.getName().getURI() + " not found");
"Failed to read file: " + maskUrlPassword(fileObject.getName().getURI())
+ " not found");
}
break;
case SIZE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.time.Duration;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static io.ballerina.stdlib.ftp.util.FtpConstants.ENDPOINT_CONFIG_PREFERRED_METHODS;
Expand All @@ -46,8 +45,8 @@ public final class FileTransportUtils {

private FileTransportUtils() {}

private static final Pattern URL_PATTERN = Pattern.compile("[a-z]+://.*");
private static final Pattern PASSWORD_PATTERN = Pattern.compile(":(?:[^/]+)@");
private static final Pattern URL_PATTERN = Pattern.compile("^[a-z][a-z0-9+.-]*://", Pattern.CASE_INSENSITIVE);
private static final Pattern USERINFO_WITH_PASSWORD = Pattern.compile("://([^/@:]+):([^/@]*)@");

/**
* A utility method for setting the relevant configurations for the file system in question.
Expand Down Expand Up @@ -115,12 +114,12 @@ private static void setSftpOptions(Map<String, String> options, FileSystemOption
*/
@ExcludeCoverageFromGeneratedReport
public static String maskUrlPassword(String url) {
Matcher urlMatcher = URL_PATTERN.matcher(url);
if (urlMatcher.find()) {
Matcher pwdMatcher = PASSWORD_PATTERN.matcher(url);
return pwdMatcher.replaceFirst("\":***@\"");
} else {
if (url == null) {
return null;
}
if (!URL_PATTERN.matcher(url).find()) {
return url;
}
return USERINFO_WITH_PASSWORD.matcher(url).replaceFirst("://$1:***@");
}
}
10 changes: 7 additions & 3 deletions native/src/main/java/io/ballerina/stdlib/ftp/util/FtpUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static io.ballerina.stdlib.ftp.transport.server.util.FileTransportUtils.maskUrlPassword;
import static io.ballerina.stdlib.ftp.util.FtpConstants.ENDPOINT_CONFIG_PREFERRED_METHODS;
import static io.ballerina.stdlib.ftp.util.FtpConstants.FTP_ANONYMOUS_PASSWORD;
import static io.ballerina.stdlib.ftp.util.FtpConstants.FTP_ANONYMOUS_USERNAME;
Expand Down Expand Up @@ -151,14 +152,17 @@ public static Map<String, String> getAuthMap(BMap config) {
* @return an error which will be propagated to ballerina user.
*/
public static BError createError(String message, String errorTypeName) {
return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(message),
String safeMessage = maskUrlPassword(message);
return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(safeMessage),
null, null);
}

public static BError createError(String message, Throwable cause, String errorTypeName) {
return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(message),
String safeMessage = maskUrlPassword(message);
return ErrorCreator.createError(ModuleUtils.getModule(), errorTypeName, StringUtils.fromString(safeMessage),
cause == null ? null : cause instanceof BError ?
(BError) cause : ErrorCreator.createError(StringUtils.fromString(cause.getMessage())), null);
(BError) cause : ErrorCreator.createError(StringUtils
.fromString(maskUrlPassword(cause.getMessage()))), null);
}

public static Throwable findRootCause(Throwable throwable) {
Expand Down
Loading