diff --git a/resources/Labels.txt b/resources/Labels.txt index a73b4a55..b2ab8c0e 100755 --- a/resources/Labels.txt +++ b/resources/Labels.txt @@ -19,6 +19,7 @@ menu.commands.copy=&Copy IP Ctrl+C menu.commands.copyDetails=Co&py details menu.commands.show=Show menu.commands.open=Open +menu.commands.open.edit=Edit openers... menu.favorites=Fa&vorites menu.favorites.add=Add current... Ctrl+D menu.favorites.edit=Manage favorites... @@ -57,14 +58,20 @@ title.saveSelection=Export Selected Results title.gettingStarted=Getting Started title.favorite.add=Add a favorite title.favorite.edit=Edit favorites +title.openers.edit=Edit Openers title.find=Find text.ip=IP text.threads=Threads: text.favorite.add=Enter the name of the new favorite text.favorite.edit=Below you can rearrange or delete favorites +text.openers.edit=Below you can edit or add new openers text.find=Enter the text to search for text.find.notFound=Nothing was found. text.find.restart=Would you like to start from the beginning? +text.openers.name=Opener name (menu item): +text.openers.string=Execution string: +text.openers.directory=Working directory: +text.openers.isCommandLine=Command-line program text.about=%NAME\n\nVersion %VERSION\n%COPYLEFT\n\n%WEBSITE\n%MAILTO\n\nThis is an Open Source Software released under the GPL. text.gettingStarted=Dummy text.gettingStarted1=Angry IP Scanner is an IP address scanner tool.\n\nIt is used for scanning IP addresses for finding alive hosts, gathering any kind of needed information about each host. @@ -80,10 +87,17 @@ button.ipUp.img=images/buttons/ipup.gif button.up=&Up button.down=&Down button.delete=De&lete +button.save=&Save +button.insert=&Insert list.unknown.img=images/list/unknown.gif list.dead.img=images/list/dead.gif list.alive.img=images/list/alive.gif list.addinfo.img=images/list/addinfo.gif +opener.web=Web Browser +opener.ftp=FTP +opener.telnet=Telnet +opener.ssh=SSH +opener.netbios=Windows Shares feeder.range=IP Range feeder.range.startIP=IP Range: feeder.range.endIP=to @@ -136,6 +150,10 @@ exception.ExporterException.failed=Exporting failed exception.ExporterException.exporter.unknown=Unknown file type, please specify correct extension in the file name. exception.ExporterException.xml.noAppend=Appending to XML files is not supported. exception.ExporterException.fetcher.notFound=Not enough data in the scanning results to export to this file type. +exception.UserErrorException.openURL.failed=Unable to launch your default browser, sorry.\nURL: +exception.UserErrorException.opener.failed=Unable to launch an external process, sorry.\nCommand-line: +exception.UserErrorException.opener.unknownFetcher=The referenced fetcher cannot be resolved in the current scanning result: +exception.UserErrorException.opener.nullFetcherValue=The replacement value of the fetcher is empty in the scanning results: exception.UserErrorException.commands.noSelection=No IP address selected exception.UserErrorException.commands.noResults=No scanning results available yet, please perform a scan first exception.UserErrorException.favorite.alreadyExists=A favorite with the same name already exists, please try a different one diff --git a/src/net/azib/ipscan/Main.java b/src/net/azib/ipscan/Main.java index bffb51e2..fec06e19 100755 --- a/src/net/azib/ipscan/Main.java +++ b/src/net/azib/ipscan/Main.java @@ -16,6 +16,7 @@ import org.eclipse.swt.widgets.Shell; import net.azib.ipscan.config.Config; import net.azib.ipscan.config.Labels; import net.azib.ipscan.gui.MainWindow; +import net.azib.ipscan.gui.UserErrorException; /** * The main executable class. @@ -80,9 +81,14 @@ public class Main { String localizedMessage; try { // try to load localized message - String exceptionClassName = getClassShortName(e.getClass()); - String originalMessage = e.getMessage(); - localizedMessage = Labels.getInstance().getString("exception." + exceptionClassName + (originalMessage != null ? "." + originalMessage : "")); + if (e instanceof UserErrorException) { + localizedMessage = e.getMessage(); + } + else { + String exceptionClassName = getClassShortName(e.getClass()); + String originalMessage = e.getMessage(); + localizedMessage = Labels.getInstance().getString("exception." + exceptionClassName + (originalMessage != null ? "." + originalMessage : "")); + } // add cause summary, if it exists if (e.getCause() != null) { localizedMessage += "\n\n" + e.getCause().toString(); diff --git a/src/net/azib/ipscan/config/Config.java b/src/net/azib/ipscan/config/Config.java index 3eea7265..f88732af 100755 --- a/src/net/azib/ipscan/config/Config.java +++ b/src/net/azib/ipscan/config/Config.java @@ -18,7 +18,9 @@ public final class Config { /** easily accessible global configuration */ private static GlobalConfig globalConfig; /** favorites are stored here */ - private static FavoritesConfig favoritesConfig; + private static NamedListConfig favoritesConfig; + /** openers are stored here */ + private static OpenersConfig openersConfig; /** various dimensions are stored here */ private static DimensionsConfig dimensionsConfig; @@ -32,12 +34,14 @@ public final class Config { preferences = Preferences.userRoot().node("ipscan"); globalConfig = new GlobalConfig(); favoritesConfig = new FavoritesConfig(); + openersConfig = new OpenersConfig(); dimensionsConfig = new DimensionsConfig(); } - + public static void store() { globalConfig.store(); favoritesConfig.store(); + openersConfig.store(); dimensionsConfig.store(); } @@ -55,10 +59,20 @@ public final class Config { /** * @return Favorites config (quick access); */ - public static FavoritesConfig getFavoritesConfig() { + public static NamedListConfig getFavoritesConfig() { return favoritesConfig; } + + /** + * @return Openers config (quick access); + */ + public static OpenersConfig getOpenersConfig() { + return openersConfig; + } + /** + * @return Dimensions config (quick access); + */ public static DimensionsConfig getDimensionsConfig() { return dimensionsConfig; } diff --git a/src/net/azib/ipscan/config/FavoritesConfig.java b/src/net/azib/ipscan/config/FavoritesConfig.java deleted file mode 100755 index 02d0c268..00000000 --- a/src/net/azib/ipscan/config/FavoritesConfig.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * - */ -package net.azib.ipscan.config; - -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.prefs.Preferences; - -/** - * FavoritesConfig - * - * @author anton - */ -public class FavoritesConfig { - - private Preferences preferences = Config.getPreferences(); - private Map favorites = new LinkedHashMap(); - - // package local constructor - FavoritesConfig() { - load(); - } - - /** - * This constructor is for tests - * @param preferences - */ - FavoritesConfig(Preferences preferences) { - this.preferences = preferences; - load(); - } - - /** - * Loads preferences - */ - void load() { - if (preferences == null) { - return; - } - - String[] favoritePrefs = preferences.get("favorites", "").split("###"); - for (int i = 0; i < favoritePrefs.length; i += 2) { - if (favoritePrefs[i].length() > 0) { - favorites.put(favoritePrefs[i], favoritePrefs[i+1]); - } - } - } - - /** - * Stores the currently available favorites - */ - public void store() { - StringBuffer sb = new StringBuffer(32); - for (Iterator i = favorites.entrySet().iterator(); i.hasNext();) { - Map.Entry e = (Map.Entry) i.next(); - sb.append(e.getKey()).append("###").append(e.getValue()).append("###"); - } - if (sb.length() > 3) { - sb.delete(sb.length() - 3, sb.length()); - } - preferences.put("favorites", sb.toString()); - } - - /** - * @param name favorite name - * @param feederInfo feederInfo to restore feeder state - */ - public void add(String name, String feederInfo) { - favorites.put(name, feederInfo); - } - - /** - * @param name favorite name - * @return feederInfo string - */ - public String get(String name) { - return (String) favorites.get(name); - } - - /** - * @return an Iterator for iterating names of available favorites - */ - public Iterator iterateNames() { - return favorites.keySet().iterator(); - } - - public int size() { - return favorites.size(); - } - - /** - * Updates favorites, retaining only those that are passed in the array. - * The order of elements will be the same as in the array. - * - * @param names - */ - public void update(String[] names) { - // rebuild the map (to recreate the new order of elements) - Map newFavorites = new LinkedHashMap(); - for (int i = 0; i < names.length; i++) { - newFavorites.put(names[i], favorites.get(names[i])); - } - favorites = newFavorites; - } - -} diff --git a/src/net/azib/ipscan/config/NamedListConfig.java b/src/net/azib/ipscan/config/NamedListConfig.java new file mode 100755 index 00000000..12ff4403 --- /dev/null +++ b/src/net/azib/ipscan/config/NamedListConfig.java @@ -0,0 +1,113 @@ +/** + * + */ +package net.azib.ipscan.config; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.prefs.Preferences; + +/** + * This is a generic named list config. + * Can be used for storing favorites, openers, and other + * user-defined configuration. + * + * @author anton + */ +public class NamedListConfig { + + private String preferenceName; + private Preferences preferences = Config.getPreferences(); + private Map namedList = new LinkedHashMap(); + + // package local constructor + NamedListConfig(String preferenceName) { + this.preferenceName = preferenceName; + load(); + } + + /** + * This constructor is for tests + * @param preferences + */ + NamedListConfig(Preferences preferences, String preferenceName) { + this.preferenceName = preferenceName; + this.preferences = preferences; + load(); + } + + /** + * Loads preferences + */ + public void load() { + if (preferences == null) { + return; + } + + String[] namedListPrefs = preferences.get(preferenceName, "").split("###"); + for (int i = 0; i < namedListPrefs.length; i += 2) { + if (namedListPrefs[i].length() > 0) { + namedList.put(namedListPrefs[i], namedListPrefs[i+1]); + } + } + } + + /** + * Stores the currently available named list + */ + public void store() { + StringBuffer sb = new StringBuffer(32); + for (Iterator i = namedList.entrySet().iterator(); i.hasNext();) { + Map.Entry e = (Map.Entry) i.next(); + sb.append(e.getKey()).append("###").append(e.getValue()).append("###"); + } + if (sb.length() > 3) { + sb.delete(sb.length() - 3, sb.length()); + } + preferences.put(preferenceName, sb.toString()); + } + + /** + * @param name displayed to the user + * @param value to store according to the name + */ + public void add(String name, String value) { + namedList.put(name, value); + } + + /** + * @param name favorite name + * @return stored value + */ + public String get(String name) { + return (String) namedList.get(name); + } + + /** + * @return an Iterator for iterating names of available favorites + */ + public Iterator iterateNames() { + return namedList.keySet().iterator(); + } + + public int size() { + return namedList.size(); + } + + /** + * Updates the list, retaining only items that are passed in the array. + * The order of elements will be the same as in the array. + * + * @param names + */ + public void update(String[] names) { + // rebuild the map (to recreate the new order of elements) + Map newList = new LinkedHashMap(); + for (int i = 0; i < names.length; i++) { + newList.put(names[i], namedList.get(names[i])); + } + namedList = newList; + } + +} diff --git a/src/net/azib/ipscan/config/OpenersConfig.java b/src/net/azib/ipscan/config/OpenersConfig.java new file mode 100755 index 00000000..904785fe --- /dev/null +++ b/src/net/azib/ipscan/config/OpenersConfig.java @@ -0,0 +1,31 @@ +/** + * + */ +package net.azib.ipscan.config; + +/** + * OpenersConfig + * + * @author anton + */ +public class OpenersConfig extends NamedListConfig { + + public OpenersConfig() { + super("openers"); + + if (size() == 0) { + Labels labels = Labels.getInstance(); + // add default openers + add(labels.getString("opener.web"), "http://${fetcher.ip}/"); + add(labels.getString("opener.netbios"), "\\\\${fetcher.ip}"); + add(labels.getString("opener.ftp"), "ftp://${fetcher.ip}/"); + add(labels.getString("opener.telnet"), "telnet ${fetcher.ip}"); + add(labels.getString("opener.ssh"), "ssh ${fetcher.ip}"); + } + } + + + + + +} diff --git a/src/net/azib/ipscan/core/ScanningResultList.java b/src/net/azib/ipscan/core/ScanningResultList.java index 017009e0..e3d7e355 100755 --- a/src/net/azib/ipscan/core/ScanningResultList.java +++ b/src/net/azib/ipscan/core/ScanningResultList.java @@ -33,7 +33,14 @@ public class ScanningResultList { scanningResults.set(index, result); } - public synchronized String getIPDetails(int index) { + /** + * Returns all results for a particular IP address as a String. + * This is used in showing the IP Details dialog box. + * + * @param index + * @return + */ + public synchronized String getResultsAsString(int index) { // TODO: what if a String is retrieved??? ScanningResult scanningResult = (ScanningResult) scanningResults.get(index); StringBuffer details = new StringBuffer(1024); @@ -63,7 +70,7 @@ public class ScanningResultList { /** * @return an Iterator of scanning results */ - public Iterator iterator() { + public synchronized Iterator iterator() { return scanningResults.iterator(); } @@ -71,6 +78,10 @@ public class ScanningResultList { return scanningResults.get(tableIndex) instanceof ScanningResult; } + /** + * @param tableIndex + * @return a results of a single IP adress, corresponding to an index + */ public synchronized ScanningResult getResult(int tableIndex) { // TODO: error handling return (ScanningResult) scanningResults.get(tableIndex); diff --git a/src/net/azib/ipscan/fetchers/FetcherRegistry.java b/src/net/azib/ipscan/fetchers/FetcherRegistry.java index 28d34ff0..fe1bed87 100755 --- a/src/net/azib/ipscan/fetchers/FetcherRegistry.java +++ b/src/net/azib/ipscan/fetchers/FetcherRegistry.java @@ -54,4 +54,19 @@ public class FetcherRegistry { return fetchers; } + /** + * Searches for selected fetcher with the given label + * @param label + * @return the index, if found, or -1 + */ + public int getSelectedFetcherIndex(String label) { + // TODO: this probably needs to be changed to reflect selected fetchers and be more effective + for (int i = 0; i < fetchers.size(); i++) { + if (label.equals(((Fetcher)fetchers.get(i)).getLabel())) { + return i; + } + } + return -1; + } + } diff --git a/src/net/azib/ipscan/gui/AboutWindow.java b/src/net/azib/ipscan/gui/AboutWindow.java index b7d1a9d2..6ed98ff6 100755 --- a/src/net/azib/ipscan/gui/AboutWindow.java +++ b/src/net/azib/ipscan/gui/AboutWindow.java @@ -23,24 +23,12 @@ import org.eclipse.swt.widgets.Text; * * @author anton */ -public class AboutWindow { - - private Shell shell; // @jve:decl-index=0:visual-constraint="10,10" +public class AboutWindow extends AbstractModalDialog { public AboutWindow() { createShell(); } - public void open() { - shell.open(); - Display display = Display.getCurrent(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - shell.dispose(); - } - /** * This method initializes shell */ diff --git a/src/net/azib/ipscan/gui/AbstractModalDialog.java b/src/net/azib/ipscan/gui/AbstractModalDialog.java new file mode 100755 index 00000000..09d4414c --- /dev/null +++ b/src/net/azib/ipscan/gui/AbstractModalDialog.java @@ -0,0 +1,28 @@ +/** + * + */ +package net.azib.ipscan.gui; + +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * This is the base of a modal dialog window + * + * @author anton + */ +public abstract class AbstractModalDialog { + + protected Shell shell = null; + + public void open() { + shell.open(); + Display display = Display.getCurrent(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + shell.dispose(); + } + +} diff --git a/src/net/azib/ipscan/gui/DetailsWindow.java b/src/net/azib/ipscan/gui/DetailsWindow.java index 441a844e..c16ee821 100755 --- a/src/net/azib/ipscan/gui/DetailsWindow.java +++ b/src/net/azib/ipscan/gui/DetailsWindow.java @@ -19,26 +19,15 @@ import org.eclipse.swt.widgets.Text; * * @author anton */ -public class DetailsWindow { +public class DetailsWindow extends AbstractModalDialog { private ResultTable resultTable; - private Shell shell; public DetailsWindow(ResultTable resultTable) { this.resultTable = resultTable; createShell(resultTable.getShell()); } - public void open() { - shell.open(); - Display display = Display.getCurrent(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - shell.dispose(); - } - /** * This method initializes shell */ diff --git a/src/net/azib/ipscan/gui/EditFavoritesDialog.java b/src/net/azib/ipscan/gui/EditFavoritesDialog.java index a2a75374..f857faa0 100755 --- a/src/net/azib/ipscan/gui/EditFavoritesDialog.java +++ b/src/net/azib/ipscan/gui/EditFavoritesDialog.java @@ -6,8 +6,8 @@ package net.azib.ipscan.gui; import java.util.Iterator; import net.azib.ipscan.config.Config; -import net.azib.ipscan.config.FavoritesConfig; import net.azib.ipscan.config.Labels; +import net.azib.ipscan.config.NamedListConfig; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; @@ -25,25 +25,14 @@ import org.eclipse.swt.widgets.Shell; * * @author anton */ -public class EditFavoritesDialog { +public class EditFavoritesDialog extends AbstractModalDialog { - private Shell shell = null; private List favoritesList; public EditFavoritesDialog() { createShell(); } - public void open() { - shell.open(); - Display display = Display.getCurrent(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - shell.dispose(); - } - /** * This method initializes shell */ @@ -105,7 +94,7 @@ public class EditFavoritesDialog { } private void saveFavorites() { - FavoritesConfig favoritesConfig = Config.getFavoritesConfig(); + NamedListConfig favoritesConfig = Config.getFavoritesConfig(); favoritesConfig.update(favoritesList.getItems()); favoritesConfig.store(); } diff --git a/src/net/azib/ipscan/gui/EditOpenersDialog.java b/src/net/azib/ipscan/gui/EditOpenersDialog.java new file mode 100755 index 00000000..148987be --- /dev/null +++ b/src/net/azib/ipscan/gui/EditOpenersDialog.java @@ -0,0 +1,248 @@ +/** + * + */ +package net.azib.ipscan.gui; + +import java.util.Iterator; + +import net.azib.ipscan.config.Config; +import net.azib.ipscan.config.Labels; +import net.azib.ipscan.config.OpenersConfig; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +/** + * EditOpenersDialog + * + * @author anton + */ +public class EditOpenersDialog extends AbstractModalDialog { + + private List openersList; + private Group editGroup; + private Text openerNameText; + private Text openerStringText; + private Text openerDirText; + private SaveButtonListener saveButtonListener; + + public EditOpenersDialog() { + createShell(); + } + + /** + * This method initializes shell + */ + private void createShell() { + Display currentDisplay = Display.getCurrent(); + Shell parent = currentDisplay != null ? currentDisplay.getActiveShell() : null; + shell = new Shell(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM); + + shell.setText(Labels.getInstance().getString("title.openers.edit")); + shell.setSize(new Point(405, 295)); + shell.setLayout(null); + + Label messageLabel = new Label(shell, SWT.NONE); + messageLabel.setText(Labels.getInstance().getString("text.openers.edit")); + messageLabel.setBounds(new Rectangle(10, 10, 282, 14)); + + openersList = new List(shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + openersList.setBounds(new Rectangle(10, 30, 135, 200)); + for (Iterator i = Config.getOpenersConfig().iterateNames(); i.hasNext();) { + String name = (String) i.next(); + openersList.add(name); + } + openersList.addListener(SWT.Selection, new ItemSelectListener()); + + Button upButton = new Button(shell, SWT.NONE); + upButton.setText(Labels.getInstance().getString("button.up")); + upButton.setBounds(new Rectangle(150, 30, 40, 25)); + upButton.addListener(SWT.Selection, new UpButtonListener()); + + Button downButton = new Button(shell, SWT.NONE); + downButton.setText(Labels.getInstance().getString("button.down")); + downButton.setBounds(new Rectangle(150, 60, 40, 25)); + downButton.addListener(SWT.Selection, new DownButtonListener()); + + Button insertButton = new Button(shell, SWT.NONE); + insertButton.setText(Labels.getInstance().getString("button.insert")); + insertButton.setBounds(new Rectangle(150, 105, 40, 25)); + insertButton.addListener(SWT.Selection, new InsertButtonListener()); + + Button deleteButton = new Button(shell, SWT.NONE); + deleteButton.setText(Labels.getInstance().getString("button.delete")); + deleteButton.setBounds(new Rectangle(150, 135, 40, 25)); + deleteButton.addListener(SWT.Selection, new DeleteButtonListener()); + + Button saveButton = new Button(shell, SWT.NONE); + saveButton.setText(Labels.getInstance().getString("button.save")); + saveButton.setBounds(new Rectangle(150, 165, 40, 25)); + saveButtonListener = new SaveButtonListener(); + saveButton.addListener(SWT.Selection, saveButtonListener); + + Button okButton = new Button(shell, SWT.NONE); + okButton.setText(Labels.getInstance().getString("button.OK")); + okButton.setBounds(new Rectangle(180, 240, 75, 22)); + shell.setDefaultButton(okButton); + + Button cancelButton = new Button(shell, SWT.NONE); + cancelButton.setText(Labels.getInstance().getString("button.cancel")); + cancelButton.setBounds(new Rectangle(265, 240, 75, 22)); + + editGroup = new Group(shell, SWT.NONE); + editGroup.setBounds(205, 30, 185, 200); + RowLayout rowLayout = new RowLayout(SWT.VERTICAL); + rowLayout.fill = true; + rowLayout.justify = true; + rowLayout.marginTop = 13; + editGroup.setLayout(rowLayout); + + Label openerNameLabel = new Label(editGroup, SWT.NONE); + openerNameLabel.setText(Labels.getInstance().getString("text.openers.name")); + openerNameLabel.setSize(SWT.DEFAULT, 18); + openerNameText = new Text(editGroup, SWT.BORDER); + openerNameText.setSize(SWT.DEFAULT, 22); + + Label openerStringLabel = new Label(editGroup, SWT.NONE); + openerStringLabel.setText(Labels.getInstance().getString("text.openers.string")); + openerStringLabel.setSize(SWT.DEFAULT, 18); + openerStringText = new Text(editGroup, SWT.BORDER); + openerStringText.setSize(SWT.DEFAULT, 22); + + Label openerDirLabel = new Label(editGroup, SWT.NONE); + openerDirLabel.setText(Labels.getInstance().getString("text.openers.directory")); + openerDirLabel.setSize(SWT.DEFAULT, 18); + openerDirText = new Text(editGroup, SWT.BORDER); + openerDirText.setSize(SWT.DEFAULT, 22); + + Button isCommanLineCheckbox = new Button(editGroup, SWT.CHECK); + isCommanLineCheckbox.setText(Labels.getInstance().getString("text.openers.isCommandLine")); + isCommanLineCheckbox.setSize(SWT.DEFAULT, 18); + + editGroup.layout(); + + okButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { + public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { + saveOpeners(); + shell.close(); + } + }); + cancelButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { + public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { + Config.getOpenersConfig().load(); + shell.close(); + } + }); + } + + private void saveOpeners() { + // save any possible changes in the text boxes + saveButtonListener.handleEvent(null); + // now save everything else + OpenersConfig openersConfig = Config.getOpenersConfig(); + openersConfig.update(openersList.getItems()); + openersConfig.store(); + } + + private class UpButtonListener implements Listener { + + public void handleEvent(Event event) { + if (openersList.isSelected(0)) { + // do not move anything if the first item is selected + return; + } + + int[] selectedItems = openersList.getSelectionIndices(); + for (int i = 0; i < selectedItems.length; i++) { + // here, index is always > 0 + int index = selectedItems[i]; + + openersList.deselect(index); + String oldItem = openersList.getItem(index - 1); + openersList.setItem(index - 1, openersList.getItem(index)); + openersList.setItem(index, oldItem); + openersList.select(index - 1); + } + + openersList.setTopIndex(selectedItems[0] - 2); + } + } + + private class DownButtonListener implements Listener { + + public void handleEvent(Event event) { + if (openersList.isSelected(openersList.getItemCount() - 1)) { + // do not move anything if the last items is selected + return; + } + + int[] selectedItems = openersList.getSelectionIndices(); + for (int i = selectedItems.length - 1; i >= 0; i--) { + // here, index is always < getItemCount() + int index = selectedItems[i]; + + openersList.deselect(index); + String oldItem = openersList.getItem(index + 1); + openersList.setItem(index + 1, openersList.getItem(index)); + openersList.setItem(index, oldItem); + openersList.select(index + 1); + } + + openersList.setTopIndex(selectedItems[0]); + } + } + + private class DeleteButtonListener implements Listener { + + public void handleEvent(Event event) { + openersList.remove(openersList.getSelectionIndices()); + } + } + + private class SaveButtonListener implements Listener { + + public void handleEvent(Event event) { + String openerName = openerNameText.getText(); + String openerValue = openerStringText.getText(); + Config.getOpenersConfig().add(openerName, openerValue); + openersList.setItem(openersList.getSelectionIndex(), openerName); + } + } + + private class InsertButtonListener implements Listener { + + public void handleEvent(Event event) { + int selectionIndex = openersList.getSelectionIndex(); + if (selectionIndex < 0) { + selectionIndex = openersList.getItemCount(); + } + openersList.add("", selectionIndex); + openersList.setSelection(selectionIndex); + } + } + + private class ItemSelectListener implements Listener { + + public void handleEvent(Event event) { + int selectionIndex = openersList.getSelectionIndex(); + String openerName = openersList.getItem(selectionIndex); + editGroup.setText(openerName); + String openerValue = Config.getOpenersConfig().get(openerName); + openerNameText.setText(openerName); + openerStringText.setText(openerValue); + // TODO: load other stuff too + } + } + +} diff --git a/src/net/azib/ipscan/gui/GettingStartedWindow.java b/src/net/azib/ipscan/gui/GettingStartedWindow.java index 6039b03f..64ef6d5c 100755 --- a/src/net/azib/ipscan/gui/GettingStartedWindow.java +++ b/src/net/azib/ipscan/gui/GettingStartedWindow.java @@ -20,9 +20,8 @@ import org.eclipse.swt.widgets.Text; * * @author anton */ -public class GettingStartedWindow { +public class GettingStartedWindow extends AbstractModalDialog { - private Shell shell; // @jve:decl-index=0:visual-constraint="10,10" private int activePage = 1; private Text gettingStartedText; private Button closeButton; @@ -32,16 +31,6 @@ public class GettingStartedWindow { createShell(); } - public void open() { - shell.open(); - Display display = Display.getCurrent(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - shell.dispose(); - } - /** * This method initializes shell */ diff --git a/src/net/azib/ipscan/gui/InputDialog.java b/src/net/azib/ipscan/gui/InputDialog.java index f0f8cf6a..7ff1e1f3 100755 --- a/src/net/azib/ipscan/gui/InputDialog.java +++ b/src/net/azib/ipscan/gui/InputDialog.java @@ -19,9 +19,8 @@ import org.eclipse.swt.widgets.Button; * * @author anton */ -public class InputDialog { +public class InputDialog extends AbstractModalDialog { - private Shell shell = null; // @jve:decl-index=0:visual-constraint="10,10" private Label messageLabel = null; private Text text = null; private Button okButton = null; @@ -73,7 +72,7 @@ public class InputDialog { }); } - public void setText(String text) { + private void setText(String text) { this.text.setText(text); this.text.setSelection(0, -1); } @@ -83,14 +82,9 @@ public class InputDialog { * * @return the entered text or null in case of cancel. */ - public String open() { - shell.open(); - Display display = Display.getCurrent(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - shell.dispose(); + public String open(String text) { + setText(text); + super.open(); return message; } diff --git a/src/net/azib/ipscan/gui/MainMenu.java b/src/net/azib/ipscan/gui/MainMenu.java index a27ca8f3..586307c7 100755 --- a/src/net/azib/ipscan/gui/MainMenu.java +++ b/src/net/azib/ipscan/gui/MainMenu.java @@ -31,6 +31,7 @@ public class MainMenu { private Menu resultsContextMenu; private Menu favoritesMenu; private Menu columnsMenu; + private Menu openersMenu; public MainMenu(MainWindow mainWindow) { @@ -45,6 +46,19 @@ public class MainMenu { // generate the menu from the definition generateMenu(shell, menuDefinition, mainMenu); + openersMenu = new Menu(shell, SWT.DROP_DOWN); + MenuItem openersMenuItem = new MenuItem(mainMenu.getItem(2).getMenu(), SWT.CASCADE); + openersMenuItem.setText(Labels.getInstance().getString("menu.commands.open")); + openersMenuItem.setMenu(openersMenu); + CommandsActions.ShowOpenersMenu showOpenersMenuListener = new CommandsActions.ShowOpenersMenu(mainWindow, openersMenu); + openersMenu.addListener(SWT.Show, showOpenersMenuListener); + MenuItem menuItem = new MenuItem(openersMenu, SWT.PUSH); + menuItem.setText(Labels.getInstance().getString("menu.commands.open.edit")); + menuItem.addListener(SWT.Selection, new CommandsActions.EditOpeners()); + menuItem = new MenuItem(openersMenu, SWT.SEPARATOR); + // run the listener to populate the menu initially and initialize accelerators + showOpenersMenuListener.handleEvent(null); + // retrieve results context menu, that is the same as "commands" menu // note: the index of 2 is hardcoded and may theoretically change // TODO: probably something better should be done here @@ -94,7 +108,6 @@ public class MainMenu { new Object[] {"menu.commands.copyDetails", null, null}, null, new Object[] {"menu.commands.show", null, null}, - new Object[] {"menu.commands.open", null, null}, } }, new Object[] {"menu.favorites", diff --git a/src/net/azib/ipscan/gui/OptionsWindow.java b/src/net/azib/ipscan/gui/OptionsWindow.java index 3c6657d4..d15f74b9 100755 --- a/src/net/azib/ipscan/gui/OptionsWindow.java +++ b/src/net/azib/ipscan/gui/OptionsWindow.java @@ -29,9 +29,8 @@ import org.eclipse.swt.layout.RowLayout; * * @author anton */ -public class OptionsWindow { +public class OptionsWindow extends AbstractModalDialog { - private Shell shell = null; // @jve:decl-index=0:visual-constraint="10,10" private TabFolder tabFolder; private Composite scanningTab; private Composite displayTab; @@ -54,16 +53,6 @@ public class OptionsWindow { loadOptions(); } - public void open() { - shell.open(); - Display display = Display.getCurrent(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) - display.sleep(); - } - shell.dispose(); - } - /** * This method initializes shell */ diff --git a/src/net/azib/ipscan/gui/ResultTable.java b/src/net/azib/ipscan/gui/ResultTable.java index b8ebf0b9..393590cd 100755 --- a/src/net/azib/ipscan/gui/ResultTable.java +++ b/src/net/azib/ipscan/gui/ResultTable.java @@ -144,7 +144,7 @@ public class ResultTable extends Table { */ public String getIPDetails() { int selectedIndex = getSelectionIndex(); - return scanningResults.getIPDetails(selectedIndex); + return scanningResults.getResultsAsString(selectedIndex); } /** diff --git a/src/net/azib/ipscan/gui/UserErrorException.java b/src/net/azib/ipscan/gui/UserErrorException.java index 8a7af0a6..a5eb4cad 100755 --- a/src/net/azib/ipscan/gui/UserErrorException.java +++ b/src/net/azib/ipscan/gui/UserErrorException.java @@ -3,6 +3,8 @@ */ package net.azib.ipscan.gui; +import net.azib.ipscan.config.Labels; + /** * Exception for throwing in case of user errors. * These generally result in showing an error message. @@ -14,12 +16,16 @@ public class UserErrorException extends RuntimeException { private static final long serialVersionUID = 123283472834982L; public UserErrorException(String label) { - super(label); + super(Labels.getInstance().getString("exception.UserErrorException." + label)); } public UserErrorException(String label, Throwable cause) { - super(label); + this(label); initCause(cause); } + + public UserErrorException(String label, String rawInfo) { + super(Labels.getInstance().getString("exception.UserErrorException." + label) + rawInfo); + } } diff --git a/src/net/azib/ipscan/gui/actions/BrowserLauncher.java b/src/net/azib/ipscan/gui/actions/BrowserLauncher.java new file mode 100755 index 00000000..8b61f788 --- /dev/null +++ b/src/net/azib/ipscan/gui/actions/BrowserLauncher.java @@ -0,0 +1,51 @@ +/** + * + */ +package net.azib.ipscan.gui.actions; + +import java.lang.reflect.Method; + +import net.azib.ipscan.gui.UserErrorException; + +/** + * BrowserLauncher + * + * @author anton + */ +public class BrowserLauncher { + + /** + * Opens an URL in the default browser. + * Supports Linux/Unix, MacOS, and Windows + * @param url + */ + public static void openURL(String url) { + String osName = System.getProperty("os.name"); + + try { + if (osName.startsWith("Windows")) { + Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); + } + else + if (osName.startsWith("Mac OS")) { + Class fileMgr = Class.forName("com.apple.eio.FileManager"); + Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] { String.class }); + openURL.invoke(null, new Object[] { url }); + } + else { // assume Linux or other Unix + // TODO: what if browser is already running as another user, not root? + String[] browsers = { "htmlview", "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" }; + String browser = null; + for (int count = 0; count < browsers.length && browser == null; count++) + if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0) + browser = browsers[count]; + if (browser == null) + throw new Exception("Could not find web browser"); + Runtime.getRuntime().exec(new String[] { browser, url }); + } + } + catch (Exception e) { + throw new UserErrorException("openURL.failed", url); + } + } +} diff --git a/src/net/azib/ipscan/gui/actions/CommandsActions.java b/src/net/azib/ipscan/gui/actions/CommandsActions.java index 71c3b46a..71d77736 100755 --- a/src/net/azib/ipscan/gui/actions/CommandsActions.java +++ b/src/net/azib/ipscan/gui/actions/CommandsActions.java @@ -3,16 +3,28 @@ */ package net.azib.ipscan.gui.actions; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.azib.ipscan.config.Config; +import net.azib.ipscan.fetchers.FetcherRegistry; import net.azib.ipscan.gui.DetailsWindow; +import net.azib.ipscan.gui.EditOpenersDialog; +import net.azib.ipscan.gui.MainWindow; import net.azib.ipscan.gui.ResultTable; import net.azib.ipscan.gui.UserErrorException; +import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; /** * Commands and Context menu Actions. * All these operate on the items, selected in the results list. + * TODO: check for selection everywhere * * @author anton */ @@ -44,4 +56,113 @@ public class CommandsActions { throw new UserErrorException("commands.noSelection"); } } + + public static class ShowOpenersMenu implements Listener { + + private Menu openersMenu; + private Listener openersSelectListener; + + public ShowOpenersMenu(MainWindow mainWindow, Menu openersMenu) { + this.openersMenu = openersMenu; + this.openersSelectListener = new SelectOpener(mainWindow); + } + + public void handleEvent(Event event) { + MenuItem[] menuItems = openersMenu.getItems(); + for (int i = 2; i < menuItems.length; i++) { + menuItems[i].dispose(); + } + + // update menu items + int index = 0; + for (Iterator i = Config.getOpenersConfig().iterateNames(); i.hasNext();) { + MenuItem menuItem = new MenuItem(openersMenu, SWT.CASCADE); + String name = (String)i.next(); + + index++; + if (index <= 9) { + name += "\tCtrl+" + index; + menuItem.setAccelerator(SWT.CONTROL | ('0' + index)); + } + + menuItem.setText(name); + menuItem.setData(new Integer(index)); + menuItem.addListener(SWT.Selection, openersSelectListener); + } + + + } + + } + + public static class EditOpeners implements Listener { + + public void handleEvent(Event event) { + new EditOpenersDialog().open(); + } + } + + public static class SelectOpener implements Listener { + + private MainWindow mainWindow; + + public SelectOpener(MainWindow mainWindow) { + this.mainWindow = mainWindow; + } + + public void handleEvent(Event event) { + MenuItem menuItem = (MenuItem) event.widget; + String name = menuItem.getText(); + int indexOf = name.lastIndexOf('\t'); + if (indexOf >= 0) { + name = name.substring(0, indexOf); + } + String openerString = Config.getOpenersConfig().get(name); + + int selectedItem = mainWindow.getResultTable().getSelectionIndex(); + if (selectedItem < 0) { + throw new UserErrorException("commands.noSelection"); + } + + openerString = prepareOpenerStringForItem(openerString, selectedItem); + + new OpenerLauncher().launch(openerString); + } + + /** + * Replaces references to scanned values in an opener string. + * Refefernces look like ${fetcher_label} + * @param openerString + * @return opener string with values replaced + */ + String prepareOpenerStringForItem(String openerString, int selectedItem) { + Pattern paramsPattern = Pattern.compile("\\$\\{(.+?)\\}"); + Matcher matcher = paramsPattern.matcher(openerString); + StringBuffer sb = new StringBuffer(64); + while (matcher.find()) { + // resolve the required fetcher + String fetcherName = matcher.group(1); + int fetcherIndex = FetcherRegistry.getInstance().getSelectedFetcherIndex(fetcherName); + if (fetcherIndex < 0) { + throw new UserErrorException("opener.unknownFetcher", fetcherName); + } + + // retrieve the scanned value + String scannedValue = getScannedValue(selectedItem, fetcherIndex); + if (scannedValue == null) { + throw new UserErrorException("opener.nullFetcherValue", fetcherName); + } + + matcher.appendReplacement(sb, scannedValue); + } + matcher.appendTail(sb); + return sb.toString(); + } + + String getScannedValue(int selectedItem, int fetcherIndex) { + return (String) mainWindow.getResultTable().getScanningResults().getResult(selectedItem).getValues().get(fetcherIndex); + } + + } + } diff --git a/src/net/azib/ipscan/gui/actions/FavoritesActions.java b/src/net/azib/ipscan/gui/actions/FavoritesActions.java index b45999c2..112d29e6 100755 --- a/src/net/azib/ipscan/gui/actions/FavoritesActions.java +++ b/src/net/azib/ipscan/gui/actions/FavoritesActions.java @@ -6,8 +6,8 @@ package net.azib.ipscan.gui.actions; import java.util.Iterator; import net.azib.ipscan.config.Config; -import net.azib.ipscan.config.FavoritesConfig; import net.azib.ipscan.config.Labels; +import net.azib.ipscan.config.NamedListConfig; import net.azib.ipscan.gui.EditFavoritesDialog; import net.azib.ipscan.gui.InputDialog; import net.azib.ipscan.gui.MainWindow; @@ -38,11 +38,10 @@ public class FavoritesActions { InputDialog inputDialog = new InputDialog( Labels.getInstance().getString("title.favorite.add"), Labels.getInstance().getString("text.favorite.add")); - inputDialog.setText(feederInfo); - String favoriteName = inputDialog.open(); + String favoriteName = inputDialog.open(feederInfo); if (favoriteName != null) { - FavoritesConfig favoritesConfig = Config.getFavoritesConfig(); + NamedListConfig favoritesConfig = Config.getFavoritesConfig(); if (favoritesConfig.get(favoriteName) != null) { throw new UserErrorException("favorite.alreadyExists"); } @@ -90,7 +89,7 @@ public class FavoritesActions { public void handleEvent(Event event) { // populate favorites in the menu - FavoritesConfig favoritesConfig = Config.getFavoritesConfig(); + NamedListConfig favoritesConfig = Config.getFavoritesConfig(); // note: 3 is the number of items in the menu when no favorites exist // dispose old favorites diff --git a/src/net/azib/ipscan/gui/actions/GotoActions.java b/src/net/azib/ipscan/gui/actions/GotoActions.java index a7aeb25b..a42834e4 100755 --- a/src/net/azib/ipscan/gui/actions/GotoActions.java +++ b/src/net/azib/ipscan/gui/actions/GotoActions.java @@ -73,8 +73,7 @@ public class GotoActions { public void handleEvent(Event event) { InputDialog dialog = new InputDialog(Labels.getInstance().getString("title.find"), Labels.getInstance().getString("text.find")); - dialog.setText(lastText); - String text = dialog.open(); + String text = dialog.open(lastText); if (text == null) { return; } diff --git a/src/net/azib/ipscan/gui/actions/HelpActions.java b/src/net/azib/ipscan/gui/actions/HelpActions.java index e7267a52..421b09dd 100755 --- a/src/net/azib/ipscan/gui/actions/HelpActions.java +++ b/src/net/azib/ipscan/gui/actions/HelpActions.java @@ -9,7 +9,6 @@ import net.azib.ipscan.gui.GettingStartedWindow; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.MessageBox; /** * HelpActions @@ -31,10 +30,8 @@ public class HelpActions { } public static class Website implements Listener { - public void handleEvent(Event event) { - MessageBox messageBox = new MessageBox(event.display.getActiveShell()); - messageBox.setMessage(Version.WEBSITE); - messageBox.open(); + public void handleEvent(Event event) { + BrowserLauncher.openURL(Version.WEBSITE); } } diff --git a/src/net/azib/ipscan/gui/actions/OpenerLauncher.java b/src/net/azib/ipscan/gui/actions/OpenerLauncher.java new file mode 100755 index 00000000..2269319c --- /dev/null +++ b/src/net/azib/ipscan/gui/actions/OpenerLauncher.java @@ -0,0 +1,35 @@ +/** + * + */ +package net.azib.ipscan.gui.actions; + +import java.io.IOException; + +import net.azib.ipscan.gui.UserErrorException; + +/** + * OpenerLauncher + * + * @author anton + */ +public class OpenerLauncher { + + public void launch(String openerString) { + // check for URLs + if (openerString.startsWith("http:") || openerString.startsWith("https:") || openerString.startsWith("ftp:") || openerString.startsWith("mailto:")) { + BrowserLauncher.openURL(openerString); + } + else { + // run a process here + try { + // TODO: we probably need to support shell patterns, etc + Runtime.getRuntime().exec(openerString); + } + catch (IOException e) { + throw new UserErrorException("opener.failed", openerString); + } + } + + } + +} diff --git a/test/net/azib/ipscan/config/FavoritesConfigTest.java b/test/net/azib/ipscan/config/FavoritesConfigTest.java deleted file mode 100755 index 525785a6..00000000 --- a/test/net/azib/ipscan/config/FavoritesConfigTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * - */ -package net.azib.ipscan.config; - -import java.util.Iterator; -import java.util.prefs.Preferences; - -import junit.framework.TestCase; - -/** - * FavoritesConfigTest - * - * @author anton - */ -public class FavoritesConfigTest extends TestCase { - - private Preferences preferences; - private FavoritesConfig config; - - protected void setUp() throws Exception { - preferences = Preferences.userRoot().node("ipscan-test"); - config = new FavoritesConfig(preferences); - } - - protected void tearDown() throws Exception { - preferences.removeNode(); - } - - public void testAdd() { - config.add("Mega favorite", "aaa:xxx"); - assertEquals("aaa:xxx", config.get("Mega favorite")); - assertEquals(1, config.size()); - } - - public void testLoad() throws Exception { - preferences.put("favorites", "aa###aaa###bb###bbb###cc###ccc"); - FavoritesConfig favorites = new FavoritesConfig(preferences); - - assertEquals("aaa", favorites.get("aa")); - assertEquals("bbb", favorites.get("bb")); - assertEquals("ccc", favorites.get("cc")); - assertEquals(3, favorites.size()); - } - - public void testOrder() throws Exception { - preferences.put("favorites", "aa###aaa###bb###bbb###cc###ccc"); - FavoritesConfig favorites = new FavoritesConfig(preferences); - - Iterator favoriteNames = favorites.iterateNames(); - assertEquals("aa", favoriteNames.next()); - assertEquals("bb", favoriteNames.next()); - assertEquals("cc", favoriteNames.next()); - assertFalse(favoriteNames.hasNext()); - } - - public void testStore() throws Exception { - FavoritesConfig favorites = new FavoritesConfig(preferences); - - favorites.add("x", "y"); - favorites.add("Buga muga x,1,2,3,4,5", "opopo op : , . l ; - # | @@"); - favorites.add("127.0.0.1", "192.168.2.25"); - favorites.store(); - - assertEquals("x###y###Buga muga x,1,2,3,4,5###opopo op : , . l ; - # | @@###127.0.0.1###192.168.2.25", preferences.get("favorites", "")); - } - - public void testUpdate() { - config.add("z", "zzz"); - config.add("y", "yyy"); - config.add("x", "xxx"); - - config.update(new String[] {"x", "z"}); - - Iterator i = config.iterateNames(); - assertEquals("xxx", config.get((String)i.next())); - assertEquals("zzz", config.get((String)i.next())); - assertFalse(i.hasNext()); - } - -} diff --git a/test/net/azib/ipscan/config/NamedListConfigTest.java b/test/net/azib/ipscan/config/NamedListConfigTest.java new file mode 100755 index 00000000..17d2ac1e --- /dev/null +++ b/test/net/azib/ipscan/config/NamedListConfigTest.java @@ -0,0 +1,82 @@ +/** + * + */ +package net.azib.ipscan.config; + +import java.util.Iterator; +import java.util.prefs.Preferences; + +import junit.framework.TestCase; + +/** + * NamedListConfigTest + * + * @author anton + */ +public class NamedListConfigTest extends TestCase { + + private static final String PREFERENCE_NAME = "blah"; + private Preferences preferences; + private NamedListConfig config; + + protected void setUp() throws Exception { + preferences = Preferences.userRoot().node("ipscan-test"); + config = new NamedListConfig(preferences, PREFERENCE_NAME); + } + + protected void tearDown() throws Exception { + preferences.removeNode(); + } + + public void testAdd() { + config.add("Mega favorite", "aaa:xxx"); + assertEquals("aaa:xxx", config.get("Mega favorite")); + assertEquals(1, config.size()); + } + + public void testLoad() throws Exception { + preferences.put(PREFERENCE_NAME, "aa###aaa###bb###bbb###cc###ccc"); + NamedListConfig config = new NamedListConfig(preferences, PREFERENCE_NAME); + + assertEquals("aaa", config.get("aa")); + assertEquals("bbb", config.get("bb")); + assertEquals("ccc", config.get("cc")); + assertEquals(3, config.size()); + } + + public void testOrder() throws Exception { + preferences.put(PREFERENCE_NAME, "aa###aaa###bb###bbb###cc###ccc"); + NamedListConfig config = new NamedListConfig(preferences, PREFERENCE_NAME); + + Iterator namesIterator = config.iterateNames(); + assertEquals("aa", namesIterator.next()); + assertEquals("bb", namesIterator.next()); + assertEquals("cc", namesIterator.next()); + assertFalse(namesIterator.hasNext()); + } + + public void testStore() throws Exception { + NamedListConfig config = new NamedListConfig(preferences, PREFERENCE_NAME); + + config.add("x", "y"); + config.add("Buga muga x,1,2,3,4,5", "opopo op : , . l ; - # | @@"); + config.add("127.0.0.1", "192.168.2.25"); + config.store(); + + assertEquals("x###y###Buga muga x,1,2,3,4,5###opopo op : , . l ; - # | @@###127.0.0.1###192.168.2.25", preferences.get(PREFERENCE_NAME, "")); + } + + public void testUpdate() { + config.add("z", "zzz"); + config.add("y", "yyy"); + config.add("x", "xxx"); + + config.update(new String[] {"x", "z"}); + + Iterator i = config.iterateNames(); + assertEquals("xxx", config.get((String)i.next())); + assertEquals("zzz", config.get((String)i.next())); + assertFalse(i.hasNext()); + } + +} diff --git a/test/net/azib/ipscan/gui/actions/CommandsActionsTest.java b/test/net/azib/ipscan/gui/actions/CommandsActionsTest.java new file mode 100755 index 00000000..32295e24 --- /dev/null +++ b/test/net/azib/ipscan/gui/actions/CommandsActionsTest.java @@ -0,0 +1,54 @@ +/** + * + */ +package net.azib.ipscan.gui.actions; + +import net.azib.ipscan.config.Config; +import net.azib.ipscan.config.Labels; +import net.azib.ipscan.gui.UserErrorException; +import net.azib.ipscan.gui.actions.CommandsActions.SelectOpener; +import junit.framework.TestCase; + +/** + * CommandsActionsTest + * + * @author anton + */ +public class CommandsActionsTest extends TestCase { + + public void testReplaceValues() { + Config.initialize(); + CommandsActions.SelectOpener so = new SelectOpener(null) { + String getScannedValue(int selectedItem, int fetcherIndex) { + switch (fetcherIndex) { + case 0: + return "127.0.0.1"; + case 1: + return "PING"; + default: + return null; + } + } + }; + + assertEquals("\\\\127.0.0.1", so.prepareOpenerStringForItem("\\\\${fetcher.ip}", 0)); + assertEquals("PING$$$127.0.0.1xxx${}", so.prepareOpenerStringForItem("${fetcher.ping}$$$${fetcher.ip}xxx${}", 0)); + assertEquals("http://127.0.0.1:80/www", so.prepareOpenerStringForItem("http://${fetcher.ip}:80/www", 0)); + + try { + so.prepareOpenerStringForItem("${noSuchFetcher}", 0); + fail(); + } + catch (UserErrorException e) { + assertEquals(Labels.getInstance().getString("exception.UserErrorException.opener.unknownFetcher") + "noSuchFetcher", e.getMessage()); + } + + try { + so.prepareOpenerStringForItem("${fetcher.ping.ttl}", 0); + fail(); + } + catch (UserErrorException e) { + assertEquals(Labels.getInstance().getString("exception.UserErrorException.opener.nullFetcherValue") + "fetcher.ping.ttl", e.getMessage()); + } + } +}