Merge branch 'main' of ssh://git.zander.im/Zander671/curator
This commit is contained in:
commit
797615877b
@ -12,9 +12,6 @@ public class Start {
|
||||
public static final String CURATOR_VERSION = "1.0";
|
||||
|
||||
public static void main(String[] args) {
|
||||
// TODO debug
|
||||
System.setProperty("sun.java2d.uiScale", "2");
|
||||
|
||||
registerSecretsFactories();
|
||||
SwingUtilities.invokeLater(() -> new LibrarySelectFrame(args));
|
||||
}
|
||||
|
@ -117,8 +117,9 @@ public class Library {
|
||||
private LocalCache localCache;
|
||||
private RemoteStore remoteStore;
|
||||
|
||||
public Library(File local, URI remote, Secrets secrets) throws ManifestParseException, IOException {
|
||||
public Library(File local, URI remote, boolean passiveMode, Secrets secrets) throws ManifestParseException, IOException {
|
||||
remoteStore = new RemoteStore(remote, secrets);
|
||||
remoteStore.setPassiveMode(passiveMode);
|
||||
localCache = new LocalCache(local);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import java.net.ProtocolException;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.net.PrintCommandListener;
|
||||
import org.apache.commons.net.ftp.FTP;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
@ -34,6 +35,7 @@ public class RemoteStore {
|
||||
private final FTPClient ftp;
|
||||
private int connectionLevel = 0;
|
||||
private boolean ignoreManifest = false;
|
||||
private boolean passiveMode;
|
||||
|
||||
public RemoteStoreFileTypeHandler fileTypeHandler = new RemoteStoreFileTypeHandler();
|
||||
|
||||
@ -42,10 +44,14 @@ public class RemoteStore {
|
||||
if (!url.isAbsolute() || url.getScheme().equals("ftp")) {
|
||||
ftp = new FTPClient();
|
||||
} else if (url.getScheme().equals("ftps")) {
|
||||
ftp = new FTPSClient(false);
|
||||
ftp = new FTPSClient("TLS", false);
|
||||
((FTPSClient) ftp).setEndpointCheckingEnabled(true);
|
||||
} else {
|
||||
throw new ProtocolException("unknown protocol: '" + url.getScheme() + "'");
|
||||
}
|
||||
// Uncomment this to print all FTP commands
|
||||
// ftp.addProtocolCommandListener(new PrintCommandListener(System.out, true));
|
||||
ftp.setListHiddenFiles(true);
|
||||
this.secrets = secrets;
|
||||
}
|
||||
|
||||
@ -61,6 +67,24 @@ public class RemoteStore {
|
||||
this.ignoreManifest = ignoreManifest;
|
||||
}
|
||||
|
||||
public boolean isPassiveMode() {
|
||||
return passiveMode;
|
||||
}
|
||||
|
||||
public void setPassiveMode(boolean passiveMode) throws IOException {
|
||||
this.passiveMode = passiveMode;
|
||||
if (connectionLevel != 0) {
|
||||
String modeString = passiveMode ? "passive" : "active";
|
||||
LOGGER.info("Switching to " + modeString + " mode");
|
||||
if (passiveMode) {
|
||||
ftp.enterLocalPassiveMode();
|
||||
} else {
|
||||
ftp.enterLocalActiveMode();
|
||||
}
|
||||
checkFtpResponse("Failed to switch to " + modeString + " mode");
|
||||
}
|
||||
}
|
||||
|
||||
public void fetchManifest() throws IOException {
|
||||
doFtpActions(() -> {
|
||||
FTPFile info = fileInformation(MANIFEST_PATH);
|
||||
@ -199,10 +223,27 @@ public class RemoteStore {
|
||||
return fileInformation(path) != null;
|
||||
}
|
||||
|
||||
private boolean isRootDir(String path) {
|
||||
return path.matches("^(/+\\.{0,2})+$");
|
||||
}
|
||||
|
||||
public FTPFile fileInformation(String path) throws IOException {
|
||||
if (isRootDir(path)) {
|
||||
return null;
|
||||
}
|
||||
AtomicReference<FTPFile> file = new AtomicReference<FTPFile>();
|
||||
doFtpActions(() -> {
|
||||
file.set(ftp.mlistFile(resolvePath(path)));
|
||||
String pp = getParentPath(path);
|
||||
if (pp == null) {
|
||||
pp = getBasePath();
|
||||
}
|
||||
String name = getFileName(path);
|
||||
FTPFile[] files = ftp.listFiles(pp);
|
||||
for (FTPFile f : files) {
|
||||
if (f.getName().equals(name)) {
|
||||
file.set(f);
|
||||
}
|
||||
}
|
||||
});
|
||||
return file.get();
|
||||
}
|
||||
@ -216,6 +257,14 @@ public class RemoteStore {
|
||||
throw new IOException("Invalid ftp secrets! Username: '" + secrets.getUsername() + "'");
|
||||
}
|
||||
LOGGER.info("Logged info ftp as user '{}'", secrets.getUsername());
|
||||
if (ftp instanceof FTPSClient) {
|
||||
FTPSClient ftps = (FTPSClient) ftp;
|
||||
ftps.execPBSZ(0);
|
||||
checkFtpResponse("Failed to send PBSZ command");
|
||||
ftps.execPROT("P");
|
||||
checkFtpResponse("Failed to send PROT command");
|
||||
}
|
||||
setPassiveMode(passiveMode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +356,10 @@ public class RemoteStore {
|
||||
pb.append("/");
|
||||
ftp.makeDirectory(pb.toString());
|
||||
}
|
||||
checkFtpResponse("Could not create directory: " + pp);
|
||||
info = fileInformation(pp);
|
||||
// if (info == null || !info.isDirectory()) {
|
||||
// throw new IOException("Failed to create directory: " + pp);
|
||||
// }
|
||||
LOGGER.info("Created directory: {}", pp);
|
||||
} else if (!info.isDirectory()) {
|
||||
throw new IOException("Not a directory: " + pp);
|
||||
@ -319,8 +371,15 @@ public class RemoteStore {
|
||||
if (ftp.isConnected()) {
|
||||
int r = ftp.getReplyCode();
|
||||
if (!FTPReply.isPositiveCompletion(r)) {
|
||||
LOGGER.info(error);
|
||||
throw new IOException(error);
|
||||
String replyString = ftp.getReplyString();
|
||||
if (replyString.endsWith("\n")) {
|
||||
replyString = replyString.substring(0, replyString.length() - 1);
|
||||
}
|
||||
if (replyString.endsWith(".")) {
|
||||
replyString = replyString.substring(0, replyString.length() - 1);
|
||||
}
|
||||
LOGGER.info("{}: {}", error, replyString);
|
||||
throw new IOException(error + ": " + replyString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -365,6 +424,19 @@ public class RemoteStore {
|
||||
if (i == -1) {
|
||||
return null;
|
||||
}
|
||||
return cp.substring(0, i);
|
||||
String pp = cp.substring(0, i);
|
||||
while (!pp.isEmpty() && pp.charAt(pp.length() - 1) == '/') {
|
||||
pp = pp.substring(0, pp.length() - 1);
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
||||
private static String getFileName(String path) {
|
||||
String cp = cleanPath(path);
|
||||
int i = cp.lastIndexOf("/");
|
||||
if (i == -1) {
|
||||
return cp;
|
||||
}
|
||||
return cp.substring(i + 1);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class PassSecretsFactory extends SecretsFactory {
|
||||
|
||||
public static boolean isBackendSupported() {
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec("which pass");
|
||||
Process p = Runtime.getRuntime().exec(new String[] {"which", "pass"});
|
||||
if (!p.waitFor(1000, TimeUnit.MILLISECONDS)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
@ -44,6 +45,8 @@ public class LibraryCreateDialog extends JDialog {
|
||||
private final JTextField usernameField;
|
||||
private final JLabel passwordLabel;
|
||||
private final JPasswordField passwordField;
|
||||
private final JLabel ftpModeLabel;
|
||||
private final JComboBox<String> ftpModeCombo;
|
||||
private final JCheckBox defaultPathCheck;
|
||||
private final JLabel pathLabel;
|
||||
private final FileChooserField pathField;
|
||||
@ -66,6 +69,8 @@ public class LibraryCreateDialog extends JDialog {
|
||||
usernameField = new JTextField(10);
|
||||
passwordLabel = new JLabel("Password:");
|
||||
passwordField = new JPasswordField(10);
|
||||
ftpModeLabel = new JLabel("FTP Mode:");
|
||||
ftpModeCombo = new JComboBox<String>(new String[] { "Passive", "Active" });
|
||||
defaultPathCheck = new JCheckBox("Use default library location");
|
||||
defaultPathCheck.setSelected(true);
|
||||
pathLabel = new JLabel("Library Path:");
|
||||
@ -223,12 +228,21 @@ public class LibraryCreateDialog extends JDialog {
|
||||
entryPanel.add(passwordField, gbc);
|
||||
gbc.gridy = 5;
|
||||
gbc.gridx = 0;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.anchor = GridBagConstraints.LINE_END;
|
||||
entryPanel.add(ftpModeLabel, gbc);
|
||||
gbc.gridx = 1;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.anchor = GridBagConstraints.LINE_START;
|
||||
entryPanel.add(ftpModeCombo, gbc);
|
||||
gbc.gridy = 6;
|
||||
gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.gridwidth = 2;
|
||||
entryPanel.add(defaultPathCheck, gbc);
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridy = 6;
|
||||
gbc.gridy = 7;
|
||||
gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.LINE_END;
|
||||
entryPanel.add(pathLabel, gbc);
|
||||
@ -266,4 +280,8 @@ public class LibraryCreateDialog extends JDialog {
|
||||
return pathField.getPathField().getText();
|
||||
}
|
||||
|
||||
public boolean isFtpPassiveMode() {
|
||||
return ftpModeCombo.getSelectedItem().equals("Passive");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
@ -44,6 +45,8 @@ public class LibraryEditDialog extends JDialog {
|
||||
private final JTextField usernameField;
|
||||
private final JLabel passwordLabel;
|
||||
private final JPasswordField passwordField;
|
||||
private final JLabel ftpModeLabel;
|
||||
private final JComboBox<String> ftpModeCombo;
|
||||
private final JCheckBox defaultPathCheck;
|
||||
private final JLabel pathLabel;
|
||||
private final FileChooserField pathField;
|
||||
@ -55,7 +58,9 @@ public class LibraryEditDialog extends JDialog {
|
||||
private final JPanel buttonPanel;
|
||||
private final JPanel panel;
|
||||
|
||||
public LibraryEditDialog(Window parent, String name, String url, String ftp, String username, String password, String file, Runnable cacheClearCallback) {
|
||||
public LibraryEditDialog(Window parent, String name, String url, String ftp,
|
||||
String username, String password, boolean passiveMode, String file,
|
||||
Runnable cacheClearCallback) {
|
||||
super(parent, "Edit Library");
|
||||
nameLabel = new JLabel("Name:");
|
||||
nameField = new JTextField(10);
|
||||
@ -72,6 +77,9 @@ public class LibraryEditDialog extends JDialog {
|
||||
passwordLabel = new JLabel("Password:");
|
||||
passwordField = new JPasswordField(10);
|
||||
passwordField.setText(password);
|
||||
ftpModeLabel = new JLabel("FTP Mode:");
|
||||
ftpModeCombo = new JComboBox<String>(new String[] { "Passive", "Active" });
|
||||
ftpModeCombo.setSelectedIndex(passiveMode ? 0 : 1);
|
||||
defaultPathCheck = new JCheckBox("Use default library location");
|
||||
pathLabel = new JLabel("Library Path:");
|
||||
pathField = new FileChooserField(10, file, new File(LibrarySelectFrame.DEFAULT_LIBRARY_PATH));
|
||||
@ -84,64 +92,64 @@ public class LibraryEditDialog extends JDialog {
|
||||
pathField.getChooser().setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
pathField.getChooser().setDialogTitle("Select Library Location");
|
||||
nameField.getDocument().addDocumentListener(new DocumentListener(){
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (defaultPathCheck.isSelected()) {
|
||||
pathField.getPathField().setText(LibrarySelectFrame.DEFAULT_LIBRARY_PATH + "/" + nameField.getText());
|
||||
}
|
||||
}
|
||||
});
|
||||
defaultPathCheck.addItemListener((e) -> {
|
||||
private void update() {
|
||||
if (defaultPathCheck.isSelected()) {
|
||||
pathField.getPathField().setText(LibrarySelectFrame.DEFAULT_LIBRARY_PATH + "/" + nameField.getText());
|
||||
pathField.setEnabled(false);
|
||||
} else {
|
||||
pathField.setEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
defaultPathCheck.addItemListener((e) -> {
|
||||
if (defaultPathCheck.isSelected()) {
|
||||
pathField.getPathField().setText(LibrarySelectFrame.DEFAULT_LIBRARY_PATH + "/" + nameField.getText());
|
||||
pathField.setEnabled(false);
|
||||
} else {
|
||||
pathField.setEnabled(true);
|
||||
}
|
||||
});
|
||||
entryPanel = new JPanel(new GridBagLayout());
|
||||
buildEntryPanel();
|
||||
cancelButton = new JButton("Cancel");
|
||||
cancelButton.setMnemonic(KeyEvent.VK_C);
|
||||
cancelButton.addActionListener((e) -> {
|
||||
dispose();
|
||||
});
|
||||
dispose();
|
||||
});
|
||||
clearCacheButton = new JButton("Clear Cache");
|
||||
clearCacheButton.setMnemonic(KeyEvent.VK_L);
|
||||
clearCacheButton.addActionListener((e) -> {
|
||||
int c = JOptionPane.showConfirmDialog(this, "Are you sure you would like to clear this library's cache?",
|
||||
"Clear Cahce", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||
if (cacheClearCallback != null && c == JOptionPane.YES_OPTION) {
|
||||
cacheClearCallback.run();
|
||||
}
|
||||
});
|
||||
int c = JOptionPane.showConfirmDialog(this, "Are you sure you would like to clear this library's cache?",
|
||||
"Clear Cahce", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||
if (cacheClearCallback != null && c == JOptionPane.YES_OPTION) {
|
||||
cacheClearCallback.run();
|
||||
}
|
||||
});
|
||||
helpButton = new JButton("?");
|
||||
helpButton.addActionListener((e) -> DocumentationViewer.show(this, "Libraries/Local Library Settings"));
|
||||
saveButton = new JButton("Save");
|
||||
saveButton.setMnemonic(KeyEvent.VK_S);
|
||||
saveButton.setEnabled(false);
|
||||
saveButton.addActionListener((e) -> {
|
||||
if (nameField.getText().contains("/")) {
|
||||
JOptionPane.showMessageDialog(this, "Library names cannot contain the '/' character!", "Library Error", JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
dispose();
|
||||
response = RESPONSE_SAVE;
|
||||
}
|
||||
});
|
||||
if (nameField.getText().contains("/")) {
|
||||
JOptionPane.showMessageDialog(this, "Library names cannot contain the '/' character!", "Library Error", JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
dispose();
|
||||
response = RESPONSE_SAVE;
|
||||
}
|
||||
});
|
||||
buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
|
||||
buttonPanel.add(cancelButton);
|
||||
@ -150,30 +158,30 @@ public class LibraryEditDialog extends JDialog {
|
||||
buttonPanel.add(clearCacheButton);
|
||||
buttonPanel.add(saveButton);
|
||||
final DocumentListener formFillListener = new DocumentListener(){
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (!nameField.getText().isBlank() && !ftpField.getText().isBlank()
|
||||
&& !usernameField.getText().isBlank() && !pathField.getPathField().getText().isBlank()) {
|
||||
saveButton.setEnabled(true);
|
||||
} else {
|
||||
saveButton.setEnabled(false);
|
||||
}
|
||||
private void update() {
|
||||
if (!nameField.getText().isBlank() && !ftpField.getText().isBlank()
|
||||
&& !usernameField.getText().isBlank() && !pathField.getPathField().getText().isBlank()) {
|
||||
saveButton.setEnabled(true);
|
||||
} else {
|
||||
saveButton.setEnabled(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
nameField.getDocument().addDocumentListener(formFillListener);
|
||||
ftpField.getDocument().addDocumentListener(formFillListener);
|
||||
usernameField.getDocument().addDocumentListener(formFillListener);
|
||||
@ -245,11 +253,20 @@ public class LibraryEditDialog extends JDialog {
|
||||
gbc.gridy = 5;
|
||||
gbc.gridx = 0;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.anchor = GridBagConstraints.LINE_END;
|
||||
entryPanel.add(ftpModeLabel, gbc);
|
||||
gbc.gridx = 1;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.anchor = GridBagConstraints.LINE_START;
|
||||
entryPanel.add(ftpModeCombo, gbc);
|
||||
gbc.gridy = 6;
|
||||
gbc.gridx = 0;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.anchor = GridBagConstraints.CENTER;
|
||||
gbc.gridwidth = 2;
|
||||
entryPanel.add(defaultPathCheck, gbc);
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridy = 6;
|
||||
gbc.gridy = 7;
|
||||
gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.LINE_END;
|
||||
entryPanel.add(pathLabel, gbc);
|
||||
@ -287,4 +304,8 @@ public class LibraryEditDialog extends JDialog {
|
||||
return pathField.getPathField().getText();
|
||||
}
|
||||
|
||||
public boolean isFtpPassiveMode() {
|
||||
return ftpModeCombo.getSelectedItem().equals("Passive");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import java.awt.event.KeyEvent;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
@ -39,6 +40,8 @@ public class LibraryImportDialog extends JDialog {
|
||||
private final JTextField usernameField;
|
||||
private final JLabel passwordLabel;
|
||||
private final JPasswordField passwordField;
|
||||
private final JLabel ftpModeLabel;
|
||||
private final JComboBox<String> ftpModeCombo;
|
||||
private final JLabel fileLabel;
|
||||
private final FileChooserField fileField;
|
||||
private final JPanel entryPanel;
|
||||
@ -58,6 +61,8 @@ public class LibraryImportDialog extends JDialog {
|
||||
usernameField = new JTextField(10);
|
||||
passwordLabel = new JLabel("Password:");
|
||||
passwordField = new JPasswordField(10);
|
||||
ftpModeLabel = new JLabel("FTP Mode:");
|
||||
ftpModeCombo = new JComboBox<String>(new String[] { "Passive", "Active" });
|
||||
fileLabel = new JLabel("Source:");
|
||||
fileField = new FileChooserField(10);
|
||||
fileField.getChooser().setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
@ -69,17 +74,17 @@ public class LibraryImportDialog extends JDialog {
|
||||
cancelButton = new JButton("Cancel");
|
||||
cancelButton.setMnemonic(KeyEvent.VK_C);
|
||||
cancelButton.addActionListener((e) -> {
|
||||
dispose();
|
||||
});
|
||||
dispose();
|
||||
});
|
||||
helpButton = new JButton("?");
|
||||
helpButton.addActionListener((e) -> DocumentationViewer.show(this, "Libraries/Local Library Settings"));
|
||||
importButton = new JButton("Import");
|
||||
importButton.setMnemonic(KeyEvent.VK_I);
|
||||
importButton.setEnabled(false);
|
||||
importButton.addActionListener((e) -> {
|
||||
dispose();
|
||||
response = RESPONSE_IMPORT;
|
||||
});
|
||||
dispose();
|
||||
response = RESPONSE_IMPORT;
|
||||
});
|
||||
buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
|
||||
buttonPanel.add(cancelButton);
|
||||
@ -87,26 +92,26 @@ public class LibraryImportDialog extends JDialog {
|
||||
buttonPanel.add(helpButton);
|
||||
buttonPanel.add(importButton);
|
||||
final DocumentListener formFillListener = new DocumentListener(){
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
importButton.setEnabled(!ftpField.getText().isBlank() && !usernameField.getText().isBlank() && !fileField.getPathField().getText().isBlank());
|
||||
}
|
||||
};
|
||||
private void update() {
|
||||
importButton.setEnabled(!ftpField.getText().isBlank() && !usernameField.getText().isBlank() && !fileField.getPathField().getText().isBlank());
|
||||
}
|
||||
};
|
||||
ftpField.getDocument().addDocumentListener(formFillListener);
|
||||
usernameField.getDocument().addDocumentListener(formFillListener);
|
||||
fileField.getPathField().getDocument().addDocumentListener(formFillListener);
|
||||
@ -167,6 +172,15 @@ public class LibraryImportDialog extends JDialog {
|
||||
gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.LINE_END;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
entryPanel.add(ftpModeLabel, gbc);
|
||||
gbc.gridx = 1;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.anchor = GridBagConstraints.LINE_START;
|
||||
entryPanel.add(ftpModeCombo, gbc);
|
||||
gbc.gridy = 5;
|
||||
gbc.gridx = 0;
|
||||
gbc.anchor = GridBagConstraints.LINE_END;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
entryPanel.add(fileLabel, gbc);
|
||||
gbc.gridx = 1;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
@ -198,4 +212,8 @@ public class LibraryImportDialog extends JDialog {
|
||||
return fileField.getPathField().getText();
|
||||
}
|
||||
|
||||
public boolean isFtpPassiveMode() {
|
||||
return ftpModeCombo.getSelectedItem().equals("Passive");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,12 +80,15 @@ public class LibrarySelectFrame extends JFrame {
|
||||
public String name;
|
||||
public String url;
|
||||
public String ftp;
|
||||
public boolean passiveMode;
|
||||
public File file;
|
||||
|
||||
public LibraryEntry(String name, String url, String ftp, File file) {
|
||||
public LibraryEntry(String name, String url, String ftp,
|
||||
boolean passiveMode, File file) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.ftp = ftp;
|
||||
this.passiveMode = passiveMode;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@ -101,7 +104,9 @@ public class LibrarySelectFrame extends JFrame {
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof LibraryEntry) {
|
||||
LibraryEntry e = (LibraryEntry) o;
|
||||
return e.name.equals(name) && e.url.equals(url) && e.file.getPath().equals(file.getPath());
|
||||
return e.name.equals(name) && e.url.equals(url) &&
|
||||
e.file.getPath().equals(file.getPath()) &&
|
||||
e.passiveMode == passiveMode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -201,7 +206,8 @@ public class LibrarySelectFrame extends JFrame {
|
||||
nld.setVisible(true);
|
||||
if (nld.getResponse() == LibraryCreateDialog.RESPONSE_CREATE) {
|
||||
createLibrary(nld.getLibraryName(), nld.getURL(), nld.getFTP(),
|
||||
nld.getUsername(), nld.getPassword(), new File(nld.getLibraryFile()));
|
||||
nld.getUsername(), nld.getPassword(),
|
||||
nld.isFtpPassiveMode(), new File(nld.getLibraryFile()));
|
||||
}
|
||||
});
|
||||
importItem = new JMenuItem("Import");
|
||||
@ -209,7 +215,8 @@ public class LibrarySelectFrame extends JFrame {
|
||||
LibraryImportDialog lid = new LibraryImportDialog(this);
|
||||
lid.setVisible(true);
|
||||
if (lid.getResponse() == LibraryImportDialog.RESPONSE_IMPORT) {
|
||||
importLibrary(lid.getURL(), lid.getFTP(), lid.getUsername(), lid.getPassword(), new File(lid.getFile()));
|
||||
importLibrary(lid.getURL(), lid.getFTP(), lid.getUsername(),
|
||||
lid.getPassword(), lid.isFtpPassiveMode(), new File(lid.getFile()));
|
||||
}
|
||||
});
|
||||
listPopup = new JPopupMenu();
|
||||
@ -287,7 +294,8 @@ public class LibrarySelectFrame extends JFrame {
|
||||
LibraryImportDialog lid = new LibraryImportDialog(this);
|
||||
lid.setVisible(true);
|
||||
if (lid.getResponse() == LibraryImportDialog.RESPONSE_IMPORT) {
|
||||
importLibrary(lid.getURL(), lid.getFTP(), lid.getUsername(), lid.getPassword(), new File(lid.getFile()));
|
||||
importLibrary(lid.getURL(), lid.getFTP(), lid.getUsername(),
|
||||
lid.getPassword(), lid.isFtpPassiveMode(), new File(lid.getFile()));
|
||||
}
|
||||
});
|
||||
newButton = new JButton("New");
|
||||
@ -297,7 +305,8 @@ public class LibrarySelectFrame extends JFrame {
|
||||
nld.setVisible(true);
|
||||
if (nld.getResponse() == LibraryCreateDialog.RESPONSE_CREATE) {
|
||||
createLibrary(nld.getLibraryName(), nld.getURL(), nld.getFTP(),
|
||||
nld.getUsername(), nld.getPassword(), new File(nld.getLibraryFile()));
|
||||
nld.getUsername(), nld.getPassword(),
|
||||
nld.isFtpPassiveMode(), new File(nld.getLibraryFile()));
|
||||
}
|
||||
});
|
||||
deleteButton = new JButton("Delete");
|
||||
@ -468,7 +477,9 @@ public class LibrarySelectFrame extends JFrame {
|
||||
}
|
||||
|
||||
private String formatLibraryUrl(String url) {
|
||||
if (!url.matches("^https?\\:\\/\\/.*")) {
|
||||
if (url.isBlank()) {
|
||||
return "";
|
||||
} else if (!url.matches("^https?\\:\\/\\/.*")) {
|
||||
return "https://" + url;
|
||||
}
|
||||
return url;
|
||||
@ -476,9 +487,10 @@ public class LibrarySelectFrame extends JFrame {
|
||||
|
||||
private void editLibrary(LibraryEntry en) {
|
||||
Secrets s = SECRETS_FACTORY.createSecrets(SECRETS_KEY + en.name);
|
||||
LibraryEditDialog led = new LibraryEditDialog(this, en.name, en.url, en.ftp,
|
||||
s.getUsername(), s.getPassword(), en.file.getPath(),
|
||||
() -> clearLibraryCache(en));
|
||||
LibraryEditDialog led = new LibraryEditDialog(this, en.name, en.url,
|
||||
en.ftp, s.getUsername(), s.getPassword(),
|
||||
en.passiveMode, en.file.getPath(),
|
||||
() -> clearLibraryCache(en));
|
||||
led.setVisible(true);
|
||||
if (led.getResponse() == LibraryEditDialog.RESPONSE_SAVE) {
|
||||
String testName = "";
|
||||
@ -506,6 +518,7 @@ public class LibrarySelectFrame extends JFrame {
|
||||
en.name = led.getLibraryName();
|
||||
en.url = formatLibraryUrl(led.getURL());
|
||||
en.ftp = led.getFTP();
|
||||
en.passiveMode = led.isFtpPassiveMode();
|
||||
en.file = nf;
|
||||
saveLibraryList();
|
||||
list.repaint();
|
||||
@ -548,7 +561,7 @@ public class LibrarySelectFrame extends JFrame {
|
||||
settingsPutObject("last-library", en);
|
||||
Secrets s = SECRETS_FACTORY.createSecrets(SECRETS_KEY + en.name);
|
||||
try {
|
||||
Library lib = new Library(en.file, new URI(en.ftp), s);
|
||||
Library lib = new Library(en.file, new URI(en.ftp), en.passiveMode, s);
|
||||
LibrarySyncDialog lsd = new LibrarySyncDialog(null, lib);
|
||||
if (lsd.sync() == LibrarySyncDialog.STATUS_OK) {
|
||||
return lib;
|
||||
@ -622,7 +635,8 @@ public class LibrarySelectFrame extends JFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private void importLibrary(String url, String ftp, String username, String password, File dir) {
|
||||
private void importLibrary(String url, String ftp, String username,
|
||||
String password, boolean passiveMode, File dir) {
|
||||
File cf = null;
|
||||
try {
|
||||
cf = dir.getCanonicalFile();
|
||||
@ -640,7 +654,7 @@ public class LibrarySelectFrame extends JFrame {
|
||||
Secrets s = SECRETS_FACTORY.createSecrets(SECRETS_KEY + name);
|
||||
s.setUsername(username);
|
||||
s.setPassword(password);
|
||||
LibraryEntry en = new LibraryEntry(name, url, ftp, cf);
|
||||
LibraryEntry en = new LibraryEntry(name, url, ftp, passiveMode, cf);
|
||||
LIBRARY_ENTRIES.add(0, en);
|
||||
openLibrary(en, false);
|
||||
}
|
||||
@ -702,7 +716,8 @@ public class LibrarySelectFrame extends JFrame {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createLibrary(String name, String url, String ftp, String username, String password, File file) {
|
||||
private void createLibrary(String name, String url, String ftp,
|
||||
String username, String password, boolean passiveMode, File file) {
|
||||
File cf = null;
|
||||
try {
|
||||
cf = file.getCanonicalFile();
|
||||
@ -726,7 +741,7 @@ public class LibrarySelectFrame extends JFrame {
|
||||
recursiveDelete(cf);
|
||||
break;
|
||||
case LibraryExistsDialog.RESPONSE_IMPORT:
|
||||
importLibrary(url, ftp, username, password, file);
|
||||
importLibrary(url, ftp, username, password, passiveMode, file);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
@ -756,7 +771,7 @@ public class LibrarySelectFrame extends JFrame {
|
||||
Secrets s = SECRETS_FACTORY.createSecrets(SECRETS_KEY + name);
|
||||
s.setUsername(username);
|
||||
s.setPassword(password);
|
||||
LibraryEntry en = new LibraryEntry(name, url, ftp, cf);
|
||||
LibraryEntry en = new LibraryEntry(name, url, ftp, passiveMode, cf);
|
||||
LIBRARY_ENTRIES.add(0, en);
|
||||
openLibrary(en, false);
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package zander.ui.media.map;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
@ -128,9 +130,12 @@ public class OSMLocationEncoder implements LocationEncoder {
|
||||
|
||||
private static URL getURLForQuery(String query) {
|
||||
try {
|
||||
final String encodedQuery = URLEncoder.encode(query, StandardCharsets.UTF_8);
|
||||
return new URL("https://nominatim.openstreetmap.org/search.php?format=jsonv2&q=" + encodedQuery);
|
||||
} catch (MalformedURLException e) {
|
||||
final String encodedQuery = URLEncoder.encode(query,
|
||||
StandardCharsets.UTF_8);
|
||||
return new URI(
|
||||
"https://nominatim.openstreetmap.org/search.php?format=jsonv2&q=" +
|
||||
encodedQuery).toURL();
|
||||
} catch (URISyntaxException | MalformedURLException e) {
|
||||
LOGGER.error("Could not generate url for query: '{}'", query, e);
|
||||
throw new Error("Could not create URL!", e);
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 29 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 19 KiB |
@ -4,18 +4,22 @@
|
||||
<h1 style="text-align: center">Local Library Settings</h1>
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
These dialogs create, import or alter the settings of libraries. These settings are primarily
|
||||
for use of Curator and will not affect the Art Museum website.
|
||||
These dialogs create, import or alter the settings of libraries. These
|
||||
settings are primarily for use of Curator and will not affect the Art
|
||||
Museum website.
|
||||
</p>
|
||||
<p>
|
||||
<b>Local vs Remote Library</b>
|
||||
<br>
|
||||
Remore libraries are instances of the Art Museum website. They are connected to by FTP.
|
||||
Any changes made to them will be reflected in their respective Art Museum instance.
|
||||
Remore libraries are instances of the Art Museum website. They are
|
||||
connected to by FTP. Any changes made to them will be reflected in their
|
||||
respective Art Museum instance.
|
||||
<br>
|
||||
Local libraries, or caches, are instances of libraries located on your computer. When you connect
|
||||
to a remote library, a local library is automatically created and sync with its remote counterpart.
|
||||
Every time you connect to a remote library, its local counterpart is updated in this way.
|
||||
Local libraries, or caches, are instances of libraries located on your
|
||||
computer. When you connect to a remote library, a local library is
|
||||
automatically created and sync with its remote counterpart. Every time
|
||||
you connect to a remote library, its local counterpart is updated in this
|
||||
way.
|
||||
</p>
|
||||
<img width="500" src="library-create-dialog.png"></img>
|
||||
<p>The library creation and remote import dialog.</p>
|
||||
@ -29,16 +33,25 @@
|
||||
<p>The local library import dialog.</p>
|
||||
<h2>Options</h2>
|
||||
<ul>
|
||||
<li><b>Name</b>: library name in the select dialog. Does not affect website.</li>
|
||||
<li><b>URL</b>: url in the select dialog. Can be blank. Does not affect the website.</li>
|
||||
<li><b>FTP</b>: FTP server to connect to. Must be in the format of 'ftp://hostname:port/path/to/library'.
|
||||
Protocol can also be FTPS by replacing 'ftp://' with 'ftps://'.</li>
|
||||
<li><b>Username & Password</b>: username and password to use to connect to FTP server.</li>
|
||||
<li><b>Library Location (Source)</b>: location to save caches in. If 'User default library location'
|
||||
is checked, it will be stored in the directory set in the global settings menu.
|
||||
<li><b>Name</b>: library name in the select dialog. Does not affect
|
||||
website.</li>
|
||||
<li><b>URL</b>: url in the select dialog. Can be blank. Does not affect
|
||||
the website.</li>
|
||||
<li><b>FTP</b>: FTP server to connect to. Must be in the format of
|
||||
'ftp://hostname:port/path/to/library'. Encryption is supported via
|
||||
FTPS. To enable it, replace 'ftp://' with 'ftps://'.</li>
|
||||
<li><b>Username & Password</b>: username and password to use to connect to
|
||||
FTP server.</li>
|
||||
<li><b>FTP Mode</b>: Whether to use active (PORT) or passive (PASV) FTP
|
||||
mode. If you are unsure, it's best to start with passive and change to
|
||||
active if you are having trouble connecting.</li>
|
||||
<li><b>Library Location (Source)</b>: location to save caches in. If 'User
|
||||
default library location' is checked, it will be stored in the directory
|
||||
set in the global settings menu.
|
||||
<a href="help:Libraries/Global Settings">See: Global Settings</a></li>
|
||||
<li><b>Clear Cahce</b>: clear library cahce. This does <b>NOT</b> affect the remote library. It only
|
||||
clears the local cache. Doing this will cause a full re-download of the remote library next time it is
|
||||
<li><b>Clear Cahce</b>: clear library cahce. This does <b>NOT</b> affect
|
||||
the remote library. It only clears the local cache. Doing this will
|
||||
cause a full re-download of the remote library next time it is
|
||||
oppened.</li>
|
||||
</ul>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user