package org.limewire.ui.swing.downloads.table; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.AbstractAction; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import net.miginfocom.swing.MigLayout; import org.jdesktop.application.Resource; import org.limewire.core.api.download.DownloadItem; import org.limewire.core.api.download.DownloadPropertyKey; import org.limewire.core.api.malware.VirusEngine; import org.limewire.setting.BooleanSetting; import org.limewire.ui.swing.components.HTMLLabel; import org.limewire.ui.swing.components.LimeJDialog; import org.limewire.ui.swing.settings.SwingUiSettings; import org.limewire.ui.swing.util.GuiUtils; import org.limewire.ui.swing.util.I18n; import org.limewire.ui.swing.util.NativeLaunchUtils; import com.google.inject.Inject; /** * Content panel for the Anti-Virus Info dialog in the downloads table. */ public class AVInfoPanel extends JPanel { private static final String AVHOME = "#antivirus"; private static final String AVHOME_URL = "http://www.avg.com/"; private static final String DANGEROUS = "#dangerous"; private static final String DANGEROUS_URL = "http://www.gnutellaforums.com/"; @Resource private Font doNotShowFont; @Resource private Color doNotShowForeground; @Resource private Font headingFont; @Resource private Color headingForeground; @Resource private Font messageFont; @Resource private Color messageForeground; @Resource private Font threatHeadingFont; @Resource private Color threatHeadingForeground; @Resource private Icon threatIcon; @Resource private Icon vendorIcon; private JLabel headingLabel; private HTMLLabel messageLabel; private JButton okButton; private JCheckBox doNotShowCheckBox; private JLabel vendorLabel; /** * Constructs an AVInfoPanel. */ @Inject public AVInfoPanel() { GuiUtils.assignResources(this); headingLabel = new JLabel(); messageLabel = new HTMLLabel(); messageLabel.setHtmlFont(messageFont); messageLabel.setHtmlForeground(messageForeground); messageLabel.setMargin(new Insets(0, 0, 0, 0)); messageLabel.setOpaque(false); messageLabel.setOpenUrlsNatively(false); messageLabel.addHyperlinkListener(new MessageListener()); okButton = new JButton(); doNotShowCheckBox = new JCheckBox(); doNotShowCheckBox.setFont(doNotShowFont); doNotShowCheckBox.setForeground(doNotShowForeground); doNotShowCheckBox.setOpaque(false); doNotShowCheckBox.setText(I18n.tr("Do not show message again")); vendorLabel = new JLabel(vendorIcon); } /** * Displays the AV vendor message. */ public void showVendorMessage() { setLayout(new MigLayout("insets 25 15 15 15, gap 0 0")); headingLabel.setFont(headingFont); headingLabel.setForeground(headingForeground); headingLabel.setText(I18n.tr("Anti-Virus Protection")); // Set message text. We also set the preferred size to control the // message and dialog width. String message = I18n.tr("LimeWire's Anti-Virus protection is powered by AVG. AVG scans, detects and deletes files that are suspected to contain viruses or spyware. <a href=\"{0}\">Learn more</a>", AVHOME); messageLabel.setText(message); messageLabel.setPreferredSize(new Dimension(300, messageLabel.getPreferredSize().height)); // Set OK button action. okButton.setAction(new AbstractAction(I18n.tr("OK")) { @Override public void actionPerformed(ActionEvent e) { disposeWindow(); } }); // Hide checkbox option. doNotShowCheckBox.setVisible(false); // Add components to container. add(headingLabel, "span, align left, wrap"); add(messageLabel, "span, align left, wrap 15"); add(okButton, "alignx left, aligny bottom"); add(vendorLabel, "alignx right, aligny bottom, push"); // Display as modal dialog. showDialog(I18n.tr("About AVG Anti-Virus")); } /** * Displays the dangerous file message. This applies to files marked as * hazardous by the internal dangerous file checker. * * @param item the item representing the downloaded file * @param showOption true to show option to turn off warning */ public void showDangerMessage(DownloadItem item, boolean showOption) { String heading = I18n.tr("Dangerous File"); String message = I18n.tr("{0} is considered a dangerous file and has automatically been deleted for your protection. <a href=\"{1}\">Learn more</a>", item.getFileName(), DANGEROUS); showWarningMessage(heading, message, showOption, false, SwingUiSettings.WARN_DOWNLOAD_DANGEROUS, SwingUiSettings.HIDE_DOWNLOAD_DANGEROUS); } /** * Displays the threat detected message. This applies to infected files * as determined by the virus scanner. * * @param item the item representing the downloaded file * @param showOption true to show option to turn off warning */ public void showThreatMessage(DownloadItem item, boolean showOption) { String heading = I18n.tr("Threat Detected"); String message = I18n.tr("{0} is suspected to contain a virus or spyware and has automatically been deleted for your protection. LimeWire's Anti-Virus protection is powered by AVG.", item.getFileName()); showWarningMessage(heading, message, showOption, true, SwingUiSettings.WARN_DOWNLOAD_THREAT_FOUND, SwingUiSettings.HIDE_DOWNLOAD_THREAT_FOUND); } /** * Displays the failure message. This applies to files that could not be * scanned due to a problem with the virus scanner. * * @param item the item representing the downloaded file * @param showOption true to show option to turn off warning */ public void showFailureMessage(DownloadItem item, boolean showOption) { VirusEngine.HintReason reason = (VirusEngine.HintReason)item.getDownloadProperty(DownloadPropertyKey.ANTIVIRUS_FAIL_HINT); if(reason == null) { reason = VirusEngine.HintReason.NO_HINT; } String heading, message; switch(reason) { case NO_DEFINITIONS: heading = I18n.tr("Can't Scan Yet"); message = I18n.tr("{0} could not be inspected because the virus scanner is still downloading its first set of virus definitions. LimeWire Anti-Virus protection is powered by AVG.", item.getFileName()); break; case NOT_SUPPORTED: heading = I18n.tr("Unable to Scan"); message = I18n.tr("{0} could not be inspected because the virus scanner cannot be loaded. LimeWire Anti-Virus protection is powered by AVG.", item.getFileName()); break; default: heading = I18n.tr("Unable to Scan"); message = I18n.tr("{0} could not be inspected due to a problem with the virus scanner. LimeWire Anti-Virus protection is powered by AVG.", item.getFileName()); break; } showWarningMessage(heading, message, showOption, true, SwingUiSettings.WARN_DOWNLOAD_SCAN_FAILED, SwingUiSettings.HIDE_DOWNLOAD_SCAN_FAILED); } /** * Displays a warning message with the specified heading and message text. */ private void showWarningMessage(String heading, String message, boolean showOption, boolean showVendor, BooleanSetting warningSetting, BooleanSetting hideSetting) { // Skip if do-not-show option is visible and the warning is turned off. if (showOption && !warningSetting.getValue()) { return; } setLayout(new MigLayout("insets 25 15 15 15, gap 0 0, hidemode 3")); JLabel iconLabel = new JLabel(threatIcon); headingLabel.setFont(threatHeadingFont); headingLabel.setForeground(threatHeadingForeground); headingLabel.setText(heading); // Set message text. We also set the preferred size to control the // message and dialog width. messageLabel.setText(message); messageLabel.setPreferredSize(new Dimension(330, messageLabel.getPreferredSize().height)); // Set OK button action. okButton.setAction(new CloseAction(warningSetting, hideSetting)); // Set up checkbox option. doNotShowCheckBox.setSelected(hideSetting.getValue()); doNotShowCheckBox.setVisible(showOption); // Add components to container. add(iconLabel, "spany, alignx left, aligny top, gaptop 6, gapright 15"); add(headingLabel, "span, align left, wrap"); add(messageLabel, "span, align left, wrap 15"); add(okButton, "alignx left, aligny bottom"); add(doNotShowCheckBox, "alignx left, aligny bottom, gapleft 5"); if (showVendor) add(vendorLabel, "alignx right, aligny bottom, push"); // Display as modal dialog. showDialog(I18n.tr("Warning")); } /** * Displays this panel in a modal dialog. */ private void showDialog(String title) { // Create dialog. final JFrame owner = GuiUtils.getMainFrame(); final JDialog dialog = new LimeJDialog(owner, title, true); // Set dialog properties. dialog.setLayout(new BorderLayout()); dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); dialog.setResizable(false); // Add content to dialog. setBackground(owner.getBackground()); dialog.add(this, BorderLayout.CENTER); // Add listener to resize and position dialog after opening. This is // necessary because we don't know the actual height of the message // component (JEditorPane) until after the window is displayed. This // will properly size the dialog for any message length. dialog.addWindowListener(new WindowAdapter() { @Override public void windowOpened(WindowEvent e) { dialog.pack(); dialog.setLocationRelativeTo(owner); } }); // Position and display dialog. dialog.pack(); dialog.setLocationRelativeTo(owner); dialog.setVisible(true); } /** * Closes the window containing this panel. */ private void disposeWindow() { Container ancestor = getTopLevelAncestor(); if (ancestor instanceof Window) { ((Window) ancestor).dispose(); } } /** * Action to close window. If the do-not-show option is visible, it is * applied to the appropriate setting. */ private class CloseAction extends AbstractAction { private final BooleanSetting warningSetting; private final BooleanSetting hideSetting; public CloseAction(BooleanSetting warningSetting, BooleanSetting hideSetting) { super(I18n.tr("OK")); this.warningSetting = warningSetting; this.hideSetting = hideSetting; } @Override public void actionPerformed(ActionEvent e) { // Apply "do not show" option if visible. if (doNotShowCheckBox.isVisible()) { warningSetting.setValue(!doNotShowCheckBox.isSelected()); hideSetting.setValue(doNotShowCheckBox.isSelected()); } // Dispose of parent window. disposeWindow(); } } /** * Listener to handle hyperlink events in the message. */ private class MessageListener implements HyperlinkListener { @Override public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if (AVHOME.equals(e.getDescription())) { NativeLaunchUtils.openURL(AVHOME_URL); } else if (DANGEROUS.equals(e.getDescription())) { NativeLaunchUtils.openURL(DANGEROUS_URL); } } } } }