mirror of
https://github.com/igniterealtime/Spark.git
synced 2026-08-18 02:56:24 +00:00
SPARK-2268: handle file URLs better
This commit is contained in:
@ -180,11 +180,7 @@ public class SparkTransferManager {
|
||||
// commandPanel.add(viewDownloads);
|
||||
// viewDownloads.addActionListener(new ActionListener() {
|
||||
// public void actionPerformed(ActionEvent e) {
|
||||
// try {
|
||||
// Desktop.getDesktop().browse(Downloads.getDownloadDirectory().toURI());
|
||||
// } catch (IOException e1) {
|
||||
// Log.error("Could not find file-browser");
|
||||
// }
|
||||
// BrowserLauncher.openFolder(Downloads.getDownloadDirectory());
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jivesoftware.spark.util;
|
||||
|
||||
import org.jivesoftware.Spark;
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
|
||||
import java.awt.Desktop;
|
||||
@ -22,39 +23,171 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.trimToNull;
|
||||
|
||||
@SuppressWarnings("HttpUrlsUsage")
|
||||
public class BrowserLauncher {
|
||||
|
||||
/**
|
||||
* Opens a URL, file path, Windows UNC path, or Samba share when clicked in a chat.
|
||||
* Supports: http(s), ftp, file, www, smb://, \\server\share, and local file paths.
|
||||
*
|
||||
* @param url the URL or path to open
|
||||
*/
|
||||
public static void openURL(String url) {
|
||||
url = trimToNull(url);
|
||||
if (url == null) {
|
||||
Log.error("Cannot open empty or null URL");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (url.startsWith("http") || url.startsWith("ftp") || url.startsWith("file") || url.startsWith("www")) {
|
||||
if (url.startsWith("file") && url.contains(" ")) {
|
||||
url = url.replace(" ", "%20");
|
||||
// Handle web protocols
|
||||
if (isWebProtocol(url)) {
|
||||
openWebUrl(url);
|
||||
return;
|
||||
}
|
||||
if (url.startsWith("www")) {
|
||||
url = "http://" + url;
|
||||
// Handle Samba/SMB URLs
|
||||
if (url.startsWith("smb://") || url.startsWith("nfs://")) {
|
||||
openSambaUrl(url);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Desktop.getDesktop().browse(new URI(url));
|
||||
} catch (Exception ex) {
|
||||
// fallback on Linux
|
||||
Runtime.getRuntime().exec("xdg-open " + url);
|
||||
// Handle Windows UNC paths
|
||||
if (isWindowsUncPath(url)) {
|
||||
openInFileManager(url);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (url.startsWith("webdav://") || url.startsWith("dav://") || url.startsWith("davs://")) {
|
||||
openWebDav(url);
|
||||
return;
|
||||
}
|
||||
if (url.startsWith("sftp://") ||
|
||||
url.startsWith("ftp://") || url.startsWith("ftps://")) {
|
||||
openInFileManager(url);
|
||||
return;
|
||||
}
|
||||
// Handle file:// with spaces
|
||||
if (url.startsWith("file://")) {
|
||||
url = url.substring(7).replace("%20", " ");
|
||||
}
|
||||
// Handle local file paths
|
||||
File f = new File(url);
|
||||
if (f.exists() && Desktop.isDesktopSupported()) {
|
||||
if (f.exists()) {
|
||||
openInFileManager(f.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
// Last resort: try as URL with https prefix
|
||||
openAsHttpsUrl(url);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.error("Unable to open url: " + url, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the URL uses a web protocol (http, https, ftp, file, www).
|
||||
*/
|
||||
private static boolean isWebProtocol(String url) {
|
||||
return url.startsWith("https://") || url.startsWith("http://") || url.startsWith("www.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the path is a Windows UNC path (starts with \\ or //).
|
||||
*/
|
||||
private static boolean isWindowsUncPath(String path) {
|
||||
return path.startsWith("\\\\") || path.startsWith("//");
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a Samba URL (smb://server/share).
|
||||
* On Windows, converts to UNC path
|
||||
*/
|
||||
private static void openSambaUrl(String url) throws IOException {
|
||||
if (Spark.isWindows()) {
|
||||
// Convert smb://server/share to \\server\share
|
||||
String uncPath = url.substring(6); // Remove "smb://" or "nfs://"
|
||||
uncPath = "\\\\" + uncPath.replace("/", "\\");
|
||||
openInFileManager(uncPath);
|
||||
return;
|
||||
}
|
||||
openInFileManager(url);
|
||||
}
|
||||
|
||||
private static void openWebDav(String url) throws IOException {
|
||||
if (Spark.isWindows()) {
|
||||
// Convert davs://server/share to https://server/share
|
||||
String davUrl = url.replace("webdav://", "http://");
|
||||
davUrl = davUrl.replace("dav://", "http://");
|
||||
davUrl = davUrl.replace("davs://", "https://");
|
||||
openInFileManager(davUrl);
|
||||
return;
|
||||
}
|
||||
openInFileManager(url);
|
||||
}
|
||||
|
||||
public static void openInFileManager(String path) {
|
||||
File file = new File(path);
|
||||
openInFileManager(file);
|
||||
}
|
||||
|
||||
public static void openInFileManager(File file) {
|
||||
try {
|
||||
Desktop.getDesktop().open(file);
|
||||
} catch (IOException e) {
|
||||
Log.warning("Unable to open file directly, opening in edit mode: " + file + ": " + e);
|
||||
try {
|
||||
Desktop.getDesktop().edit(file);
|
||||
} catch (IOException e2) {
|
||||
Log.warning("Unable to open file directly, opening containing folder instead: " + file + ": " + e2);
|
||||
try {
|
||||
Desktop.getDesktop().open(f);
|
||||
} catch (Exception ex) {
|
||||
if (!url.startsWith("//")) {
|
||||
url = "//" + url;
|
||||
}
|
||||
Desktop.getDesktop().browse(new URI("http:" + url));
|
||||
openContainingFolder(file);
|
||||
} catch (IOException e3) {
|
||||
Log.error("Unable to open folder: " + file + ": " + e3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a URL with a recognized web protocol.
|
||||
*/
|
||||
private static void openWebUrl(String url) throws Exception {
|
||||
// Handle www. prefix
|
||||
if (url.startsWith("www.")) {
|
||||
url = "https://" + url;
|
||||
}
|
||||
catch (Exception e) {
|
||||
Log.error("Unable to open url " + url, e);
|
||||
try {
|
||||
Desktop.getDesktop().browse(new URI(url));
|
||||
} catch (Exception ex) {
|
||||
// Fallback for Linux systems
|
||||
Runtime.getRuntime().exec(new String[]{"xdg-open", url});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to open a URL by adding https:// prefix.
|
||||
*/
|
||||
private static void openAsHttpsUrl(String url) throws Exception {
|
||||
if (!url.startsWith("//")) {
|
||||
url = "//" + url;
|
||||
}
|
||||
URI uri = new URI("https:" + url);
|
||||
Desktop.getDesktop().browse(uri);
|
||||
}
|
||||
|
||||
private static void openContainingFolder(File file) throws IOException {
|
||||
if (Spark.isWindows()) {
|
||||
Runtime.getRuntime().exec(new String[]{
|
||||
"explorer.exe",
|
||||
"/select," + file.getAbsolutePath()
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null) {
|
||||
Desktop.getDesktop().open(parent);
|
||||
} else {
|
||||
throw new IOException("Unable to determine parent folder for: " + file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,4 +201,12 @@ public class BrowserLauncher {
|
||||
Log.error("Unable to open folder: " + file, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
// openURL("C:\\Users\\Admin\\Desktop\\avatar.jpg");
|
||||
// openURL("C:\\Users\\Admin\\Desktop\\avatar.jpg");
|
||||
openURL("D:\\work\\Spark\\core\\src\\main\\resources\\images\\alert.png");
|
||||
// openURL("ftp://jkl.mn");
|
||||
// openURL("ftp://jkl.mn");
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ package org.jivesoftware.sparkimpl.plugin.alerts;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@ -54,6 +53,7 @@ import org.jivesoftware.spark.ui.MessageListener;
|
||||
import org.jivesoftware.spark.ui.SparkTabHandler;
|
||||
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
|
||||
import org.jivesoftware.spark.ui.status.StatusBar;
|
||||
import org.jivesoftware.spark.util.BrowserLauncher;
|
||||
import org.jivesoftware.spark.util.ModelUtil;
|
||||
import org.jivesoftware.spark.util.ResourceUtils;
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
@ -440,9 +440,9 @@ public class BroadcastPlugin extends SparkTabHandler implements Plugin, StanzaLi
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
try {
|
||||
Log.warning("Open the URL in default browser" + e.getURL());
|
||||
Desktop.getDesktop().browse(e.getURL().toURI());
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
Log.error(ex.getCause());
|
||||
BrowserLauncher.openURL(e.getURL().toURI().toString());
|
||||
} catch (URISyntaxException ex) {
|
||||
Log.error(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -17,7 +17,6 @@ package org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
@ -57,6 +56,7 @@ import org.jivesoftware.spark.preference.Preference;
|
||||
import org.jivesoftware.spark.ui.ChatRoom;
|
||||
import org.jivesoftware.spark.ui.ContactItem;
|
||||
import org.jivesoftware.spark.ui.ContactList;
|
||||
import org.jivesoftware.spark.util.BrowserLauncher;
|
||||
import org.jivesoftware.spark.util.ByteFormat;
|
||||
import org.jivesoftware.spark.util.GraphicUtils;
|
||||
import org.jivesoftware.spark.util.ResourceUtils;
|
||||
@ -442,7 +442,7 @@ public class ReceiveFileTransfer extends JPanel {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
launchFile(downloadedFile);
|
||||
BrowserLauncher.openInFileManager(downloadedFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -463,7 +463,7 @@ public class ReceiveFileTransfer extends JPanel {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() == 2) {
|
||||
launchFile(downloadedFile);
|
||||
BrowserLauncher.openInFileManager(downloadedFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -554,7 +554,7 @@ public class ReceiveFileTransfer extends JPanel {
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
launchFile(downloadedFile);
|
||||
BrowserLauncher.openInFileManager(downloadedFile);
|
||||
}
|
||||
});
|
||||
|
||||
@ -784,41 +784,4 @@ public class ReceiveFileTransfer extends JPanel {
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to open the file. If no associated application can be found, or if that application fails to launch, or
|
||||
* if the provided file is a directory, a file browser that shows the content of the folder in which the file
|
||||
* resides is shown.
|
||||
*
|
||||
* @param file the file to be shown.
|
||||
*/
|
||||
private void launchFile(File file) {
|
||||
if (!Desktop.isDesktopSupported()) {
|
||||
Log.warning("Cannot launch file (not supported in this environment).");
|
||||
return;
|
||||
}
|
||||
|
||||
final Desktop desktop = Desktop.getDesktop();
|
||||
try {
|
||||
desktop.open(file);
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
// Potentially trying to open on a network path that has spaces (SPARK-1350). Try again, using a URI.
|
||||
desktop.browse(getFileURI(file));
|
||||
return;
|
||||
} catch (Exception ex1) {
|
||||
// The specified file has no associated application or the associated application fails to be launched.
|
||||
// Show the folder containing the file as a last-ditch effort (SPARK-2199).
|
||||
if (file.isFile() && file.getParentFile() != null) {
|
||||
try {
|
||||
desktop.open(file.getParentFile());
|
||||
return;
|
||||
} catch (IOException ex2) {
|
||||
// Log the original exception (see below)
|
||||
}
|
||||
}
|
||||
}
|
||||
// In case of failure, log the original exception, which is likely to be most relevant.
|
||||
Log.warning("Unable to open file: " + file.getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ package org.jivesoftware.sparkimpl.plugin.filetransfer.transfer.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
@ -25,7 +24,6 @@ import java.awt.Insets;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.*;
|
||||
@ -46,11 +44,11 @@ import org.jivesoftware.spark.component.FileDragLabel;
|
||||
import org.jivesoftware.spark.ui.ChatRoom;
|
||||
import org.jivesoftware.spark.ui.ContactItem;
|
||||
import org.jivesoftware.spark.ui.ContactList;
|
||||
import org.jivesoftware.spark.util.BrowserLauncher;
|
||||
import org.jivesoftware.spark.util.ByteFormat;
|
||||
import org.jivesoftware.spark.util.GraphicUtils;
|
||||
import org.jivesoftware.spark.util.SwingWorker;
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
import org.jivesoftware.sparkimpl.settings.Sizes;
|
||||
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
@ -248,7 +246,7 @@ public class SendFileTransfer extends JPanel {
|
||||
label.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
openFile(fileToSend);
|
||||
BrowserLauncher.openInFileManager(fileToSend);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -263,14 +261,6 @@ public class SendFileTransfer extends JPanel {
|
||||
});
|
||||
}
|
||||
|
||||
private void openFile(File downloadedFile) {
|
||||
try {
|
||||
Desktop.getDesktop().open(downloadedFile);
|
||||
} catch (IOException e) {
|
||||
Log.error("An error occurred while trying to open downloaded file: " + downloadedFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBar(final OutgoingFileTransfer transfer, String nickname, String kBperSecond) {
|
||||
FileTransfer.Status status = transfer.getStatus();
|
||||
switch (status) {
|
||||
|
||||
@ -17,12 +17,12 @@ package org.jivesoftware.sparkimpl.plugin.fileupload;
|
||||
|
||||
import org.jivesoftware.resource.Res;
|
||||
import org.jivesoftware.resource.SparkRes;
|
||||
import org.jivesoftware.smackx.filetransfer.FileTransfer.Status;
|
||||
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.component.FileDragLabel;
|
||||
import org.jivesoftware.spark.ui.ContactItem;
|
||||
import org.jivesoftware.spark.ui.ContactList;
|
||||
import org.jivesoftware.spark.util.BrowserLauncher;
|
||||
import org.jivesoftware.spark.util.ByteFormat;
|
||||
import org.jivesoftware.spark.util.GraphicUtils;
|
||||
import org.jivesoftware.spark.util.SwingWorker;
|
||||
@ -38,10 +38,8 @@ import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
@ -49,7 +47,6 @@ import java.awt.Insets;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
@ -161,7 +158,7 @@ public class FileUploadChatComponent extends JPanel {
|
||||
label.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
openFile(fileToSend);
|
||||
BrowserLauncher.openInFileManager(fileToSend);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -176,14 +173,6 @@ public class FileUploadChatComponent extends JPanel {
|
||||
});
|
||||
}
|
||||
|
||||
private void openFile(File downloadedFile) {
|
||||
try {
|
||||
Desktop.getDesktop().open(downloadedFile);
|
||||
} catch (IOException e) {
|
||||
Log.error("An error occurred while trying to open downloaded file: " + downloadedFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBar(final OutgoingFileTransfer transfer, String nickname, String kBperSecond) {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user