Add JSch (SFTP) debug logging
-App Settings->Log-File for Debugging->SFTP debug logging -Logs to android log (logcat) if log file is not enabled -Logs to Kp2a log file if it is enabled -Logs are tagged as "KP2AJFS[JSch]" -When enabled, logs ALL levels (DEBUG+). NOTE: Sensitive SSH connection information may be logged!!
This commit is contained in:
@@ -58,12 +58,12 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
private static string LogFilename
|
||||
public static string LogFilename
|
||||
{
|
||||
get { return Application.Context.FilesDir.CanonicalPath +"/keepass2android.log"; }
|
||||
}
|
||||
|
||||
private static bool LogToFile
|
||||
public static bool LogToFile
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.jcraft.jsch.Logger;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
|
||||
public class Kp2aJSchLogger implements Logger {
|
||||
|
||||
private static final String PREFIX = "KP2AJFS[JSch]";
|
||||
|
||||
private interface ILogger {
|
||||
void log(String message);
|
||||
}
|
||||
|
||||
private static final class LogEntry {
|
||||
private final String levelTag;
|
||||
private final ILogger logger;
|
||||
|
||||
LogEntry(String levelTag, ILogger logger) {
|
||||
this.levelTag = levelTag;
|
||||
this.logger = logger;
|
||||
}
|
||||
}
|
||||
private static final ILogger DEBUG = msg -> Log.d(PREFIX, msg);
|
||||
private static final LogEntry DEBUG_ENTRY = new LogEntry("D", DEBUG);
|
||||
private static final ILogger ERROR = msg -> Log.e(PREFIX, msg);
|
||||
private static final LogEntry DEFAULT_ENTRY = DEBUG_ENTRY;
|
||||
|
||||
private static final Map<Integer, LogEntry> loggers = Map.of(
|
||||
Logger.DEBUG, DEBUG_ENTRY,
|
||||
Logger.INFO, new LogEntry("I", msg -> Log.i(PREFIX, msg)),
|
||||
Logger.WARN, new LogEntry("W", msg -> Log.w(PREFIX, msg)),
|
||||
Logger.ERROR, new LogEntry("E", ERROR),
|
||||
Logger.FATAL, new LogEntry("F", msg -> Log.wtf(PREFIX, msg))
|
||||
);
|
||||
|
||||
|
||||
private final String logFilename;
|
||||
|
||||
public Kp2aJSchLogger(String logFilename) {
|
||||
this.logFilename = logFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int level) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(int level, String message) {
|
||||
if (isEnabled(level))
|
||||
getLogger(level).log(message);
|
||||
}
|
||||
|
||||
private ILogger getLogger(int level) {
|
||||
LogEntry entry = loggers.get(level);
|
||||
if (entry == null)
|
||||
entry = DEFAULT_ENTRY;
|
||||
|
||||
ILogger logger;
|
||||
if (logFilename != null) {
|
||||
logger = createFileLogger(entry);
|
||||
} else {
|
||||
logger = entry.logger;
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
private ILogger createFileLogger(LogEntry entry) {
|
||||
try {
|
||||
final PrintWriter p = new PrintWriter(new FileWriter(logFilename, true));
|
||||
return msg -> {
|
||||
try {
|
||||
String fullMsg = String.join(" ", entry.levelTag, PREFIX, msg);
|
||||
p.println(fullMsg);
|
||||
} catch (Exception e) {
|
||||
ERROR.log(e.getMessage());
|
||||
} finally {
|
||||
p.close();
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
ERROR.log(e.getMessage());
|
||||
return entry.logger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +375,14 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
}
|
||||
|
||||
public void setJschLogging(boolean enabled, String logFilename) {
|
||||
if (enabled) {
|
||||
JSch.setLogger(new Kp2aJSchLogger(logFilename));
|
||||
} else {
|
||||
JSch.setLogger(null);
|
||||
}
|
||||
}
|
||||
|
||||
private String createKeyPair(String key_filename) throws JSchException, IOException {
|
||||
String public_key_filename = key_filename + ".pub";
|
||||
File file = new File(key_filename);
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
<string name="TrayTotp_SeedField_key">TrayTotp_SeedField_key</string>
|
||||
<string name="TrayTotp_prefs_key">TrayTotp_prefs_key</string>
|
||||
<string name="DebugLog_key">DebugLog_key</string>
|
||||
<string name="JSchDebug_key">JSchDebug_key</string>
|
||||
<string name="DebugLog_prefs_key">DebugLog_prefs_key</string>
|
||||
<string name="DebugLog_send_key">DebugLog_send</string>
|
||||
<string name="AutofillDisabledQueriesPreference_key">AutofillDisabledQueriesPreference_key</string>
|
||||
|
||||
@@ -680,6 +680,7 @@
|
||||
<string name="TrayTotp_prefs">TrayTotp</string>
|
||||
<string name="DebugLog_prefs_prefs">Log-File for Debugging</string>
|
||||
<string name="DebugLog_title">Use log file</string>
|
||||
<string name="JSchDebug_title">SFTP debug logging</string>
|
||||
<string name="DebugLog_summary">Write app output to a local log file</string>
|
||||
<string name="DebugLog_send">Send debug log...</string>
|
||||
|
||||
|
||||
@@ -670,10 +670,17 @@
|
||||
android:defaultValue="false"
|
||||
android:title="@string/DebugLog_title"
|
||||
android:key="@string/DebugLog_key" />
|
||||
|
||||
<Preference
|
||||
android:enabled="true"
|
||||
android:title="@string/DebugLog_send"
|
||||
android:key="@string/DebugLog_send_key" />
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/JSchDebug_title"
|
||||
android:key="@string/JSchDebug_key" />
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace keepass2android
|
||||
|
||||
FindPreference(GetString(Resource.String.DebugLog_key)).PreferenceChange += OnDebugLogChanged;
|
||||
FindPreference(GetString(Resource.String.DebugLog_send_key)).PreferenceClick += OnSendDebug;
|
||||
FindPreference(GetString(Resource.String.JSchDebug_key)).PreferenceChange += OnJSchDebugChanged;
|
||||
|
||||
HashSet<string> supportedLocales = new HashSet<string>() { "en", "af", "ar", "az", "be", "bg", "ca", "cs", "da", "de", "el", "es", "eu", "fa", "fi", "fr", "gl", "he", "hr", "hu", "id", "in", "it", "iw", "ja", "ko", "ml", "nb", "nl", "nn", "no", "pl", "pt", "ro", "ru", "si", "sk", "sl", "sr", "sv", "tr", "uk", "vi", "zh" };
|
||||
|
||||
@@ -417,16 +418,31 @@ namespace keepass2android
|
||||
|
||||
private void OnDebugLogChanged(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
Kp2aLog.CreateLogFile();
|
||||
}
|
||||
if ((bool)e.NewValue)
|
||||
Kp2aLog.CreateLogFile();
|
||||
else
|
||||
{
|
||||
Kp2aLog.FinishLogFile();
|
||||
}
|
||||
Kp2aLog.FinishLogFile();
|
||||
|
||||
}
|
||||
bool jschLogEnable = PreferenceManager.GetDefaultSharedPreferences(Application.Context)
|
||||
.GetBoolean(Application.Context.GetString(Resource.String.JSchDebug_key), false);
|
||||
SetJSchLogging(jschLogEnable);
|
||||
}
|
||||
|
||||
private void OnJSchDebugChanged(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
SetJSchLogging((bool)e.NewValue);
|
||||
}
|
||||
|
||||
private void SetJSchLogging(bool enabled)
|
||||
{
|
||||
var sftpStorage = new Keepass2android.Javafilestorage.SftpStorage(Context);
|
||||
string? logFilename = null;
|
||||
if (Kp2aLog.LogToFile)
|
||||
{
|
||||
logFilename = Kp2aLog.LogFilename;
|
||||
}
|
||||
sftpStorage.SetJschLogging(enabled, logFilename);
|
||||
}
|
||||
|
||||
private void AlgorithmPrefChange(object sender, Preference.PreferenceChangeEventArgs preferenceChangeEventArgs)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user