GP-4151 fixing wizard pattern to better handle expensive checks between panels.
|
@ -312,11 +312,11 @@ src/main/help/help/topics/FrontEndPlugin/images/SelectSharedProjectType.png||GHI
|
|||
src/main/help/help/topics/FrontEndPlugin/images/ServerInfo.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/SharedProjectInfo.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/UsersPanel.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/UsersPanelMini.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/VersionedFileCOnoServer.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/VersionedFileCOwithServer.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/VersionedFileIcon.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/ViewOtherProjects.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/ViewProjectAccessPanel.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FrontEndPlugin/images/hijack_file.png||GHIDRA||||END|
|
||||
src/main/help/help/topics/FunctionComparison/FunctionComparison.htm||GHIDRA||||END|
|
||||
src/main/help/help/topics/FunctionComparison/images/AddFunctionsPanel.png||GHIDRA||||END|
|
||||
|
|
|
@ -917,7 +917,7 @@
|
|||
"help/shared/arrow.gif" border="0">View Project Access List</B> will be enabled, which will display
|
||||
the following dialog and allow the user to view the project users and their current access privileges only.</P>
|
||||
|
||||
<P align="center"><IMG src="images/UsersPanelMini.png" border="0"></P>
|
||||
<P align="center"><IMG src="images/ViewProjectAccessPanel.png" border="0"></P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 9.5 KiB |
|
@ -601,6 +601,8 @@ public class ListingCodeComparisonPanel
|
|||
private void updateProgramViews() {
|
||||
displays.get(LEFT).setProgramView(getProgram(LEFT), getAddresses(LEFT), "listing1");
|
||||
displays.get(RIGHT).setProgramView(getProgram(RIGHT), getAddresses(RIGHT), "listing2");
|
||||
displays.get(LEFT).goTo(comparisonData.get(LEFT).getInitialLocation());
|
||||
displays.get(RIGHT).goTo(comparisonData.get(LEFT).getInitialLocation());
|
||||
}
|
||||
|
||||
private void nextAreaDiff(boolean forward) {
|
||||
|
|
|
@ -174,10 +174,6 @@ public class ListingDisplay implements ListingDiffChangeListener {
|
|||
markerManager.getOverviewProvider().setProgram(program, indexMap);
|
||||
listingPanel.setBackgroundColorModel(
|
||||
new MarkerServiceBackgroundColorModel(markerManager, program, indexMap));
|
||||
setUpAreaMarkerSets(program, name);
|
||||
if (!view.isEmpty()) {
|
||||
goTo(new ProgramLocation(program, view.getMinAddress()));
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
@ -189,8 +185,9 @@ public class ListingDisplay implements ListingDiffChangeListener {
|
|||
Color unmatchedColor = comparisonOptions.getUnmatchedCodeUnitsBackgroundColor();
|
||||
|
||||
AddressIndexMap indexMap = listingPanel.getAddressIndexMap();
|
||||
listingPanel.getFieldPanel().setBackgroundColorModel(new MarkerServiceBackgroundColorModel(
|
||||
markerManager, program, indexMap));
|
||||
listingPanel.getFieldPanel()
|
||||
.setBackgroundColorModel(new MarkerServiceBackgroundColorModel(
|
||||
markerManager, program, indexMap));
|
||||
|
||||
unmatchedMarkers = markerManager.createAreaMarker(name + " Unmatched Code",
|
||||
"Instructions that are not matched to an instruction in the other function.",
|
||||
|
@ -307,8 +304,9 @@ public class ListingDisplay implements ListingDiffChangeListener {
|
|||
}
|
||||
|
||||
public void setViewerPosition(ViewerPosition position) {
|
||||
listingPanel.getFieldPanel().setViewerPosition(position.getIndex(), position.getXOffset(),
|
||||
position.getYOffset());
|
||||
listingPanel.getFieldPanel()
|
||||
.setViewerPosition(position.getIndex(), position.getXOffset(),
|
||||
position.getYOffset());
|
||||
}
|
||||
|
||||
public void setMouseNavigationEnabled(boolean enabled) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
|
||||
/**
|
||||
|
@ -77,4 +78,9 @@ public class AddressSetComparisonData implements ComparisonData {
|
|||
public boolean isEmpty() {
|
||||
return addresses.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getInitialLocation() {
|
||||
return new ProgramLocation(program, addresses.getMinAddress());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import generic.theme.GThemeDefaults.Colors.Palette;
|
|||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
/**
|
||||
* ComparisonData is an abstract of items that can be compared in a {@link CodeComparisonPanel}.
|
||||
|
@ -68,4 +69,9 @@ public interface ComparisonData {
|
|||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Returns the initial program location to put the cursor when the panel is first displayed
|
||||
*/
|
||||
public ProgramLocation getInitialLocation();
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Objects;
|
|||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
|
||||
/**
|
||||
|
@ -108,4 +109,9 @@ public class DataComparisonData implements ComparisonData {
|
|||
}
|
||||
return endAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getInitialLocation() {
|
||||
return new ProgramLocation(data.getProgram(), data.getMinAddress());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import ghidra.program.model.address.AddressSet;
|
|||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
public class EmptyComparisonData implements ComparisonData {
|
||||
|
||||
|
@ -51,4 +52,9 @@ public class EmptyComparisonData implements ComparisonData {
|
|||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getInitialLocation() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import ghidra.program.model.address.AddressSet;
|
|||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.FunctionSignatureFieldLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
|
||||
/**
|
||||
|
@ -84,4 +86,9 @@ public class FunctionComparisonData implements ComparisonData {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getInitialLocation() {
|
||||
return new FunctionSignatureFieldLocation(function.getProgram(), function.getEntryPoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 59 KiB |
|
@ -20,11 +20,11 @@ import javax.swing.Icon;
|
|||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import docking.wizard.WizardManager;
|
||||
import docking.wizard.WizardDialog;
|
||||
import generic.theme.GIcon;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.feature.vt.gui.plugin.VTPlugin;
|
||||
import ghidra.feature.vt.gui.wizard.VTAddToSessionWizardManager;
|
||||
import ghidra.feature.vt.gui.wizard.add.VTAddToSessionWizardModel;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
public class AddToVersionTrackingSessionAction extends DockingAction {
|
||||
|
@ -46,10 +46,9 @@ public class AddToVersionTrackingSessionAction extends DockingAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
VTAddToSessionWizardManager vtWizardManager = new VTAddToSessionWizardManager(controller);
|
||||
WizardManager wizardManager =
|
||||
new WizardManager("Version Tracking Wizard", true, vtWizardManager);
|
||||
wizardManager.showWizard(controller.getParentComponent());
|
||||
VTAddToSessionWizardModel model = new VTAddToSessionWizardModel(controller);
|
||||
WizardDialog wizardDialog = new WizardDialog(model);
|
||||
wizardDialog.show(controller.getParentComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,11 +21,11 @@ import docking.ActionContext;
|
|||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.wizard.WizardManager;
|
||||
import docking.wizard.WizardDialog;
|
||||
import generic.theme.GIcon;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.feature.vt.gui.plugin.VTPlugin;
|
||||
import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager;
|
||||
import ghidra.feature.vt.gui.wizard.session.VTNewSessionWizardModel;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
public class CreateVersionTrackingSessionAction extends DockingAction {
|
||||
|
@ -58,10 +58,9 @@ public class CreateVersionTrackingSessionAction extends DockingAction {
|
|||
if (!controller.closeVersionTrackingSession()) {
|
||||
return; // user cancelled during save dialog
|
||||
}
|
||||
VTNewSessionWizardManager vtWizardManager = new VTNewSessionWizardManager(controller);
|
||||
WizardManager wizardManager =
|
||||
new WizardManager("Version Tracking Wizard", true, vtWizardManager);
|
||||
wizardManager.showWizard(controller.getParentComponent());
|
||||
VTNewSessionWizardModel model = new VTNewSessionWizardModel(controller);
|
||||
WizardDialog wizardDialog = new WizardDialog(model);
|
||||
wizardDialog.show(controller.getParentComponent());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import javax.swing.JFrame;
|
|||
|
||||
import docking.action.DockingActionIf;
|
||||
import docking.tool.ToolConstants;
|
||||
import docking.wizard.WizardManager;
|
||||
import docking.wizard.WizardDialog;
|
||||
import generic.theme.GIcon;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
|
@ -37,7 +37,7 @@ import ghidra.feature.vt.gui.provider.functionassociation.VTFunctionAssociationP
|
|||
import ghidra.feature.vt.gui.provider.impliedmatches.*;
|
||||
import ghidra.feature.vt.gui.provider.markuptable.VTMarkupItemsTableProvider;
|
||||
import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider;
|
||||
import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager;
|
||||
import ghidra.feature.vt.gui.wizard.session.VTNewSessionWizardModel;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.SaveState;
|
||||
|
@ -268,11 +268,10 @@ public class VTPlugin extends Plugin {
|
|||
if (!controller.closeVersionTrackingSession()) {
|
||||
return false; // user cancelled during save dialog
|
||||
}
|
||||
VTNewSessionWizardManager vtWizardManager =
|
||||
new VTNewSessionWizardManager(controller, programFile1, programFile2);
|
||||
WizardManager wizardManager =
|
||||
new WizardManager("Version Tracking Wizard", true, vtWizardManager);
|
||||
wizardManager.showWizard(tool.getToolFrame());
|
||||
VTNewSessionWizardModel model =
|
||||
new VTNewSessionWizardModel(controller, programFile1, programFile2);
|
||||
WizardDialog wizardDialog = new WizardDialog(model);
|
||||
wizardDialog.show(tool.getToolFrame());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.feature.vt.gui.task;
|
||||
|
||||
import ghidra.feature.vt.gui.wizard.VTWizardUtils;
|
||||
import ghidra.feature.vt.gui.wizard.session.VTWizardUtils;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
public interface AddressRangeListener {
|
||||
|
||||
public void processAddressRange(Address minAddress, Address maxAddress);
|
||||
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import docking.widgets.checkbox.GCheckBox;
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorAddressRestrictionPreference;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.layout.VerticalLayout;
|
||||
|
||||
public class AddressSetOptionsPanel extends AbstractMageJPanel<VTWizardStateKey> {
|
||||
|
||||
private JCheckBox excludeCheckbox;
|
||||
private JCheckBox showAddressSetPanelsCheckbox;
|
||||
|
||||
public AddressSetOptionsPanel() { //
|
||||
setBorder(BorderFactory.createEmptyBorder(40, 40, 0, 0));
|
||||
|
||||
excludeCheckbox = new GCheckBox("Exclude accepted matches", false);
|
||||
String excludeAcceptedTooltip = "This option will cause the correlator algorithm " +
|
||||
"to <b>not</b> consider any functions or data that have already been " +
|
||||
"accepted. Using this option can greatly speed up the processing time " +
|
||||
"of the correlator algorithm; however, this options should only be " +
|
||||
"used when you trust that your accepted matches are correct.";
|
||||
excludeCheckbox.setToolTipText(HTMLUtilities.toWrappedHTML(excludeAcceptedTooltip));
|
||||
|
||||
showAddressSetPanelsCheckbox = new GCheckBox("Limit source and destination address sets");
|
||||
String manuallyLimitTooltip = "Selecting this checkbox will trigger additional wizard " +
|
||||
" panels allowing you to customize the address sets used " +
|
||||
" by the selected algorithm. When not selected, the entire address space is used.";
|
||||
|
||||
showAddressSetPanelsCheckbox.setToolTipText(
|
||||
HTMLUtilities.toWrappedHTML(manuallyLimitTooltip));
|
||||
|
||||
add(excludeCheckbox);
|
||||
add(showAddressSetPanelsCheckbox);
|
||||
setLayout(new VerticalLayout(20));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
// none
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<VTProgramCorrelatorFactory> list = (List<VTProgramCorrelatorFactory>) state.get(
|
||||
VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
|
||||
|
||||
Boolean value = (Boolean) state.get(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES);
|
||||
if (value != null) {
|
||||
excludeCheckbox.setSelected(value.booleanValue());
|
||||
}
|
||||
value = (Boolean) state.get(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS);
|
||||
if (value != null) {
|
||||
showAddressSetPanelsCheckbox.setSelected(value.booleanValue());
|
||||
}
|
||||
else {
|
||||
AddressSetView sourceSelection =
|
||||
(AddressSetView) state.get(VTWizardStateKey.SOURCE_SELECTION);
|
||||
AddressSetView destinationSelection =
|
||||
(AddressSetView) state.get(VTWizardStateKey.DESTINATION_SELECTION);
|
||||
boolean somethingSelected = (sourceSelection != null && !sourceSelection.isEmpty()) ||
|
||||
(destinationSelection != null && !destinationSelection.isEmpty());
|
||||
showAddressSetPanelsCheckbox.setSelected(somethingSelected);
|
||||
}
|
||||
|
||||
if (allowRestrictions(list)) {
|
||||
excludeCheckbox.setEnabled(true);
|
||||
}
|
||||
else {
|
||||
excludeCheckbox.setSelected(false);
|
||||
excludeCheckbox.setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean allowRestrictions(List<VTProgramCorrelatorFactory> list) {
|
||||
for (VTProgramCorrelatorFactory factory : list) {
|
||||
if (factory.getAddressRestrictionPreference() != VTProgramCorrelatorAddressRestrictionPreference.RESTRICTION_NOT_ALLOWED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
return WizardPanelDisplayability.CAN_BE_DISPLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
state.put(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES, excludeCheckbox.isSelected());
|
||||
state.put(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS,
|
||||
showAddressSetPanelsCheckbox.isSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", "Address_Set_Panel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Address Set Options";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import docking.wizard.*;
|
||||
|
||||
public class AddressSetPanel extends AbstractMageJPanel<VTWizardStateKey> {
|
||||
|
||||
private final PluginTool tool;
|
||||
private final String name;
|
||||
private final VTWizardStateKey programDependencyKey;
|
||||
private final VTWizardStateKey addressSetViewKey;
|
||||
private final VTWizardStateKey selectionKey;
|
||||
private final VTWizardStateKey addressSetChoiceKey;
|
||||
private ChooseAddressSetEditorPanel panel;
|
||||
private Program program;
|
||||
|
||||
public AddressSetPanel(PluginTool tool, String name, VTWizardStateKey programFileDependencyKey,
|
||||
VTWizardStateKey programDependencyKey, VTWizardStateKey addressSetViewKey,
|
||||
VTWizardStateKey selectionKey, VTWizardStateKey addressSetChoiceKey) {
|
||||
this.tool = tool;
|
||||
this.name = name;
|
||||
this.programDependencyKey = programDependencyKey;
|
||||
this.addressSetViewKey = addressSetViewKey;
|
||||
this.selectionKey = selectionKey;
|
||||
this.addressSetChoiceKey = addressSetChoiceKey;
|
||||
setLayout(new BorderLayout());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
// no dependencies
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
// Keep this method for now in case we want it as the default for the entire program address set
|
||||
// instead of the program's memory address set.
|
||||
@SuppressWarnings("unused")
|
||||
private AddressSet getAddressFactoryAddressSet(WizardState<VTWizardStateKey> state) {
|
||||
Program programFromState = (Program) state.get(programDependencyKey);
|
||||
AddressFactory factory = programFromState.getAddressFactory();
|
||||
AddressSet everything = new AddressSet();
|
||||
AddressSpace[] addressSpaces = factory.getAddressSpaces();
|
||||
for (AddressSpace addressSpace : addressSpaces) {
|
||||
Address minAddress = addressSpace.getMinAddress();
|
||||
Address maxAddress = addressSpace.getMaxAddress();
|
||||
AddressRangeImpl range = new AddressRangeImpl(minAddress, maxAddress);
|
||||
everything.add(range);
|
||||
}
|
||||
return everything;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", "Address_Set_Panel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
if (panel != null) {
|
||||
remove(panel);
|
||||
}
|
||||
program = (Program) state.get(programDependencyKey);
|
||||
AddressSetView addressSetView = (AddressSetView) state.get(addressSetViewKey);
|
||||
AddressSetView selection = (AddressSetView) state.get(selectionKey);
|
||||
AddressSetChoice addressSetChoice = (AddressSetChoice) state.get(addressSetChoiceKey);
|
||||
if (addressSetChoice == null) {
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
addressSetChoice = AddressSetChoice.SELECTION;
|
||||
}
|
||||
else {
|
||||
addressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
|
||||
}
|
||||
}
|
||||
panel =
|
||||
new ChooseAddressSetEditorPanel(tool, name, program, selection, addressSetView,
|
||||
addressSetChoice);
|
||||
panel.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
});
|
||||
add(panel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
Boolean value = (Boolean) state.get(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS);
|
||||
boolean showPanel = value == null ? false : value.booleanValue();
|
||||
if (!showPanel) {
|
||||
return WizardPanelDisplayability.DO_NOT_DISPLAY;
|
||||
}
|
||||
return WizardPanelDisplayability.CAN_BE_DISPLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
AddressSetView addressSetView = panel.getAddressSetView();
|
||||
state.put(addressSetViewKey, addressSetView);
|
||||
state.put(addressSetChoiceKey, panel.getAddressSetChoice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Select " + name + " Address Range(s)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// not sure if we need this
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
boolean empty = panel.getAddressSetView().isEmpty();
|
||||
String msg = empty ? "At least one address range is required" : "";
|
||||
notifyListenersOfStatusMessage(msg);
|
||||
return !empty;
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
import java.awt.GridLayout;
|
||||
|
||||
import docking.wizard.*;
|
||||
|
||||
public class LimitAddressSetsPanel extends AbstractMageJPanel<VTWizardStateKey> {
|
||||
|
||||
private AddressSetPanel sourcePanel;
|
||||
private AddressSetPanel destinationPanel;
|
||||
|
||||
public LimitAddressSetsPanel(PluginTool tool) {
|
||||
|
||||
setLayout(new GridLayout());
|
||||
sourcePanel =
|
||||
new AddressSetPanel(tool, "Source", VTWizardStateKey.SOURCE_PROGRAM_FILE,
|
||||
VTWizardStateKey.SOURCE_PROGRAM, VTWizardStateKey.SOURCE_ADDRESS_SET_VIEW,
|
||||
VTWizardStateKey.SOURCE_SELECTION, VTWizardStateKey.SOURCE_ADDRESS_SET_CHOICE);
|
||||
destinationPanel =
|
||||
new AddressSetPanel(tool, "Destination", VTWizardStateKey.DESTINATION_PROGRAM_FILE,
|
||||
VTWizardStateKey.DESTINATION_PROGRAM,
|
||||
VTWizardStateKey.DESTINATION_ADDRESS_SET_VIEW,
|
||||
VTWizardStateKey.DESTINATION_SELECTION,
|
||||
VTWizardStateKey.DESTINATION_ADDRESS_SET_CHOICE);
|
||||
add(sourcePanel);
|
||||
add(destinationPanel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", "Select_Address_Ranges_Panel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
sourcePanel.addDependencies(state);
|
||||
destinationPanel.addDependencies(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
sourcePanel.dispose();
|
||||
destinationPanel.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
sourcePanel.enterPanel(state);
|
||||
destinationPanel.enterPanel(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
WizardPanelDisplayability sourceDisplayability =
|
||||
sourcePanel.getPanelDisplayabilityAndUpdateState(state);
|
||||
destinationPanel.getPanelDisplayabilityAndUpdateState(state);
|
||||
// Use the displayability of the source panel as that of the source/destination combined.
|
||||
return sourceDisplayability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
sourcePanel.leavePanel(state);
|
||||
destinationPanel.leavePanel(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
sourcePanel.updateStateObjectWithPanelInfo(state);
|
||||
destinationPanel.updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Select Address Range(s)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
sourcePanel.initialize();
|
||||
destinationPanel.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
return sourcePanel.isValidInformation() && destinationPanel.isValidInformation();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,611 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import static ghidra.framework.main.DataTreeDialogType.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.widgets.button.BrowseButton;
|
||||
import docking.widgets.label.GDLabel;
|
||||
import docking.wizard.*;
|
||||
import generic.theme.GIcon;
|
||||
import generic.theme.GThemeDefaults.Ids.Fonts;
|
||||
import generic.theme.Gui;
|
||||
import ghidra.app.util.task.OpenProgramRequest;
|
||||
import ghidra.app.util.task.OpenProgramTask;
|
||||
import ghidra.feature.vt.api.util.VTSessionFileUtil;
|
||||
import ghidra.framework.main.DataTreeDialog;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
|
||||
/**
|
||||
* Version tracking wizard panel to create a new session.
|
||||
*/
|
||||
public class NewSessionPanel extends AbstractMageJPanel<VTWizardStateKey> {
|
||||
|
||||
// The maximum length to allow for each program's name portion of the session name.
|
||||
// In the filesystem API, when saved, the session name is restricted to 60 characters.
|
||||
// The default VTSession name combines the two program names so split the length between them,
|
||||
// minus text we add below.
|
||||
private static final int VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH = 28;
|
||||
private static final int TEXT_FIELD_LENGTH = 40;
|
||||
private static final Icon SWAP_ICON = new GIcon("icon.version.tracking.new.session.swap");
|
||||
private static final Icon INFO_ICON = new GIcon("icon.version.tracking.new.session.info");
|
||||
|
||||
private JTextField sourceField;
|
||||
private JTextField destinationField;
|
||||
private JButton sourceBrowseButton;
|
||||
private JButton destinationBrowseButton;
|
||||
private JButton swapProgramsButton;
|
||||
private JTextField sessionNameField;
|
||||
private JTextField folderNameField;
|
||||
private DomainFolder folder;
|
||||
private PluginTool tool;
|
||||
|
||||
// All program info objects that the user may have opened while using the wizard. We keep
|
||||
// these around to avoid reopening them and any accompanying upgrading that may be required.
|
||||
// These will be released when the wizard is finished.
|
||||
private Map<DomainFile, ProgramInfo> allProgramInfos = new HashMap<>();
|
||||
private ProgramInfo sourceProgramInfo;
|
||||
private ProgramInfo destinationProgramInfo;
|
||||
|
||||
NewSessionPanel(PluginTool tool) {
|
||||
|
||||
this.tool = tool;
|
||||
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
|
||||
|
||||
JLabel folderLabel = new GDLabel("Project folder ");
|
||||
folderLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
folderLabel.setToolTipText("The folder to store the new Version Tracking Session");
|
||||
folderNameField = new JTextField();
|
||||
Gui.registerFont(folderNameField, Fonts.MONOSPACED);
|
||||
folderNameField.setEditable(false); // force user to browse to choose
|
||||
|
||||
JButton browseFolderButton = new BrowseButton();
|
||||
browseFolderButton.addActionListener(e -> browseDataTreeFolders());
|
||||
|
||||
JLabel newSessionLabel = new GDLabel("New Session Name: ");
|
||||
newSessionLabel.setToolTipText("The name for the new Version Tracking Session");
|
||||
newSessionLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
|
||||
sessionNameField = new JTextField(TEXT_FIELD_LENGTH);
|
||||
sessionNameField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
});
|
||||
|
||||
JLabel sourceLabel = new GDLabel("Source Program: ");
|
||||
sourceLabel.setIcon(INFO_ICON);
|
||||
sourceLabel.setToolTipText("Analyzed program with markup to transfer");
|
||||
sourceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
|
||||
JLabel destinationLabel = new GDLabel("Destination Program: ");
|
||||
destinationLabel.setIcon(INFO_ICON);
|
||||
destinationLabel.setToolTipText("New program that receives the transferred markup");
|
||||
destinationLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
|
||||
sourceField = new JTextField(TEXT_FIELD_LENGTH);
|
||||
sourceField.setEditable(false);
|
||||
|
||||
destinationField = new JTextField(TEXT_FIELD_LENGTH);
|
||||
destinationField.setEditable(false);
|
||||
|
||||
sourceBrowseButton = createSourceBrowseButton();
|
||||
destinationBrowseButton = createDestinationBrowseButton();
|
||||
|
||||
swapProgramsButton = new JButton(SWAP_ICON);
|
||||
swapProgramsButton.setText("swap");
|
||||
swapProgramsButton.setName("SWAP_BUTTON");
|
||||
swapProgramsButton.addActionListener(arg0 -> swapPrograms());
|
||||
|
||||
JPanel mainPanel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
mainPanel.add(Box.createVerticalStrut(15), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
mainPanel.add(folderLabel, gbc);
|
||||
|
||||
gbc.gridx++;
|
||||
mainPanel.add(folderNameField, gbc);
|
||||
|
||||
gbc.gridx++;
|
||||
mainPanel.add(Box.createHorizontalStrut(5), gbc);
|
||||
|
||||
gbc.gridx++;
|
||||
mainPanel.add(browseFolderButton, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
mainPanel.add(Box.createVerticalStrut(10), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
mainPanel.add(newSessionLabel, gbc);
|
||||
|
||||
gbc.gridx++;
|
||||
mainPanel.add(sessionNameField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
mainPanel.add(Box.createVerticalStrut(15), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 4;
|
||||
mainPanel.add(new JSeparator(), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
mainPanel.add(Box.createVerticalStrut(25), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
mainPanel.add(sourceLabel, gbc);
|
||||
|
||||
gbc.gridx++;
|
||||
mainPanel.add(sourceField, gbc);
|
||||
|
||||
gbc.gridx += 2;
|
||||
mainPanel.add(sourceBrowseButton, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.gridwidth = 4;
|
||||
mainPanel.add(swapProgramsButton, gbc);
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridy++;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
mainPanel.add(destinationLabel, gbc);
|
||||
|
||||
gbc.gridx++;
|
||||
mainPanel.add(destinationField, gbc);
|
||||
|
||||
gbc.gridx += 2;
|
||||
mainPanel.add(destinationBrowseButton, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
mainPanel.add(Box.createVerticalStrut(25), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 4;
|
||||
mainPanel.add(new JSeparator(), gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
gbc.gridwidth = 1;
|
||||
mainPanel.add(Box.createVerticalStrut(60), gbc);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(mainPanel, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
private void initializePrograms(WizardState<VTWizardStateKey> state) {
|
||||
DomainFile source = (DomainFile) state.get(VTWizardStateKey.SOURCE_PROGRAM_FILE);
|
||||
DomainFile destintation = (DomainFile) state.get(VTWizardStateKey.DESTINATION_PROGRAM_FILE);
|
||||
|
||||
if (source != null) {
|
||||
setSourceProgram(source);
|
||||
}
|
||||
if (destintation != null) {
|
||||
setDestinationProgram(destintation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the user with a tree of the existing project folders and allows
|
||||
* them to pick one
|
||||
*/
|
||||
private void browseDataTreeFolders() {
|
||||
final DataTreeDialog dataTreeDialog =
|
||||
new DataTreeDialog(this, "Choose a project folder", CHOOSE_FOLDER);
|
||||
|
||||
dataTreeDialog.addOkActionListener(e -> {
|
||||
dataTreeDialog.close();
|
||||
setFolder(dataTreeDialog.getDomainFolder());
|
||||
});
|
||||
dataTreeDialog.showComponent();
|
||||
}
|
||||
|
||||
void setFolder(DomainFolder folder) {
|
||||
this.folder = folder;
|
||||
|
||||
if (folder != null) {
|
||||
folderNameField.setText(folder.toString());
|
||||
}
|
||||
else {
|
||||
folderNameField.setText("< Choose a folder >");
|
||||
}
|
||||
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
|
||||
private void setSourceProgram(DomainFile programFile) {
|
||||
notifyListenersOfStatusMessage(" ");
|
||||
|
||||
String path;
|
||||
if (programFile == null) {
|
||||
sourceProgramInfo = null;
|
||||
path = "";
|
||||
}
|
||||
else {
|
||||
sourceProgramInfo =
|
||||
allProgramInfos.computeIfAbsent(programFile, file -> new ProgramInfo(file));
|
||||
path = programFile.getPathname();
|
||||
}
|
||||
|
||||
sourceField.setText(path);
|
||||
|
||||
updateSessionNameIfBlank();
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
|
||||
private void updateSessionNameIfBlank() {
|
||||
if (!StringUtils.isBlank(sessionNameField.getText())) {
|
||||
return;
|
||||
}
|
||||
if (sourceProgramInfo == null || destinationProgramInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String defaultSessionName =
|
||||
createVTSessionName(sourceProgramInfo.getName(), destinationProgramInfo.getName());
|
||||
sessionNameField.setText(defaultSessionName);
|
||||
}
|
||||
|
||||
private String createVTSessionName(String sourceName, String destinationName) {
|
||||
|
||||
// if together they are within the bounds just return session name with both full names
|
||||
if (sourceName.length() + destinationName.length() <= 2 *
|
||||
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
|
||||
return "VT_" + sourceName + "_" + destinationName;
|
||||
}
|
||||
|
||||
// give destination name all space not used by source name
|
||||
if (sourceName.length() < VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
|
||||
int leftover = VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH - sourceName.length();
|
||||
destinationName = StringUtilities.trimMiddle(destinationName,
|
||||
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH + leftover);
|
||||
return "VT_" + sourceName + "_" + destinationName;
|
||||
}
|
||||
|
||||
// give source name all space not used by destination name
|
||||
if (destinationName.length() < VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
|
||||
int leftover = VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH - destinationName.length();
|
||||
sourceName = StringUtilities.trimMiddle(sourceName,
|
||||
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH + leftover);
|
||||
return "VT_" + sourceName + "_" + destinationName;
|
||||
}
|
||||
|
||||
// if both too long, shorten both of them
|
||||
sourceName = StringUtilities.trimMiddle(sourceName, VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH);
|
||||
destinationName =
|
||||
StringUtilities.trimMiddle(destinationName, VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH);
|
||||
|
||||
return "VT_" + sourceName + "_" + destinationName;
|
||||
}
|
||||
|
||||
private void setDestinationProgram(DomainFile programFile) {
|
||||
notifyListenersOfStatusMessage(" ");
|
||||
|
||||
String path;
|
||||
if (programFile == null) {
|
||||
destinationProgramInfo = null;
|
||||
path = "";
|
||||
}
|
||||
else {
|
||||
destinationProgramInfo =
|
||||
allProgramInfos.computeIfAbsent(programFile, file -> new ProgramInfo(file));
|
||||
path = programFile.getPathname();
|
||||
}
|
||||
|
||||
destinationField.setText(path);
|
||||
updateSessionNameIfBlank();
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
|
||||
private void swapPrograms() {
|
||||
notifyListenersOfStatusMessage(" ");
|
||||
|
||||
ProgramInfo temp = destinationProgramInfo;
|
||||
destinationProgramInfo = sourceProgramInfo;
|
||||
sourceProgramInfo = temp;
|
||||
|
||||
if (sourceProgramInfo != null) {
|
||||
sourceField.setText(sourceProgramInfo.getPathname());
|
||||
}
|
||||
else {
|
||||
sourceField.setText("");
|
||||
}
|
||||
|
||||
if (destinationProgramInfo != null) {
|
||||
destinationField.setText(destinationProgramInfo.getPathname());
|
||||
}
|
||||
else {
|
||||
destinationField.setText("");
|
||||
}
|
||||
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", "New_Session_Panel");
|
||||
}
|
||||
|
||||
private void releaseConsumers() {
|
||||
|
||||
for (ProgramInfo info : allProgramInfos.values()) {
|
||||
info.release(tool);
|
||||
}
|
||||
|
||||
allProgramInfos.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
initializePrograms(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
return WizardPanelDisplayability.MUST_BE_DISPLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
state.put(VTWizardStateKey.SOURCE_PROGRAM_FILE, sourceProgramInfo.getFile());
|
||||
state.put(VTWizardStateKey.DESTINATION_PROGRAM_FILE, destinationProgramInfo.getFile());
|
||||
state.put(VTWizardStateKey.SOURCE_PROGRAM, sourceProgramInfo.getProgram());
|
||||
state.put(VTWizardStateKey.DESTINATION_PROGRAM, destinationProgramInfo.getProgram());
|
||||
state.put(VTWizardStateKey.SESSION_NAME, sessionNameField.getText());
|
||||
state.put(VTWizardStateKey.NEW_SESSION_FOLDER, folder);
|
||||
}
|
||||
|
||||
private boolean openProgram(ProgramInfo programInfo) {
|
||||
|
||||
if (programInfo.hasProgram()) {
|
||||
return true; // already open
|
||||
}
|
||||
|
||||
OpenProgramTask openProgramTask = new OpenProgramTask(programInfo.getFile(), tool);
|
||||
new TaskLauncher(openProgramTask, tool.getActiveWindow());
|
||||
OpenProgramRequest openProgram = openProgramTask.getOpenProgram();
|
||||
programInfo.setProgram(openProgram != null ? openProgram.getProgram() : null);
|
||||
return programInfo.hasProgram();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "New Version Tracking Session";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
sourceProgramInfo = null;
|
||||
destinationProgramInfo = null;
|
||||
sessionNameField.setText("");
|
||||
sourceField.setText("");
|
||||
destinationField.setText("");
|
||||
setFolder(tool.getProject().getProjectData().getRootFolder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
|
||||
if (folder == null) {
|
||||
notifyListenersOfStatusMessage("Choose a project folder to continue!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sourceProgramInfo == null || destinationProgramInfo == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sourceProgramInfo.hasSameFile(destinationProgramInfo)) {
|
||||
notifyListenersOfStatusMessage("Source and Destination Programs must be different");
|
||||
releaseConsumers();
|
||||
return false;
|
||||
}
|
||||
|
||||
String name = sessionNameField.getText().trim();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
notifyListenersOfStatusMessage("Please enter a name for this session");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
tool.getProject().getProjectData().testValidName(name, false);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
notifyListenersOfStatusMessage("'" + name + "' contains invalid characters");
|
||||
return false;
|
||||
}
|
||||
|
||||
DomainFile file = folder.getFile(name);
|
||||
if (file != null) {
|
||||
notifyListenersOfStatusMessage(
|
||||
"'" + file.getPathname() + "' is the name of an existing project file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Known Issue: Opening programs before comitted to using them (i.e., Next is clicked) seems
|
||||
// premature and will subject user to prompts about possible checkout and/or upgrades
|
||||
// with possible slow re-disassembly (see GP-4151)
|
||||
|
||||
if (!isValidDestinationProgramFile() || !isValidSourceProgramFile()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!openProgram(sourceProgramInfo)) {
|
||||
notifyListenersOfStatusMessage(
|
||||
"Can't open source program " + sourceProgramInfo.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!openProgram(destinationProgramInfo)) {
|
||||
notifyListenersOfStatusMessage(
|
||||
"Can't open destination program " + destinationProgramInfo.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
notifyListenersOfStatusMessage(" ");
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidSourceProgramFile() {
|
||||
try {
|
||||
VTSessionFileUtil.validateSourceProgramFile(sourceProgramInfo.file, false);
|
||||
}
|
||||
catch (Exception e) {
|
||||
notifyListenersOfStatusMessage(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidDestinationProgramFile() {
|
||||
try {
|
||||
VTSessionFileUtil.validateDestinationProgramFile(destinationProgramInfo.file, false,
|
||||
false);
|
||||
}
|
||||
catch (Exception e) {
|
||||
notifyListenersOfStatusMessage(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
// none
|
||||
}
|
||||
|
||||
private JButton createSourceBrowseButton() {
|
||||
JButton button = new BrowseButton();
|
||||
button.setName("SOURCE_BUTTON");
|
||||
button.addActionListener(e -> {
|
||||
DomainFile programFile = VTWizardUtils.chooseDomainFile(NewSessionPanel.this,
|
||||
"a source program", VTWizardUtils.PROGRAM_FILTER, null);
|
||||
if (programFile != null) {
|
||||
setSourceProgram(programFile);
|
||||
}
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createDestinationBrowseButton() {
|
||||
JButton button = new BrowseButton();
|
||||
button.setName("DESTINATION_BUTTON");
|
||||
button.addActionListener(e -> {
|
||||
DomainFile programFile = VTWizardUtils.chooseDomainFile(NewSessionPanel.this,
|
||||
"a destination program", VTWizardUtils.PROGRAM_FILTER, null);
|
||||
if (programFile != null) {
|
||||
setDestinationProgram(programFile);
|
||||
}
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
releaseConsumers();
|
||||
}
|
||||
|
||||
// simple object to track a domain file and its program
|
||||
private class ProgramInfo {
|
||||
|
||||
private Program program;
|
||||
private DomainFile file;
|
||||
|
||||
public ProgramInfo(DomainFile file) {
|
||||
this.file = Objects.requireNonNull(file);
|
||||
}
|
||||
|
||||
void setProgram(Program program) {
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
DomainFile getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
String getPathname() {
|
||||
return file.getPathname();
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
void release(Object consumer) {
|
||||
if (program == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (program.getConsumerList().contains(consumer)) {
|
||||
program.release(consumer);
|
||||
}
|
||||
|
||||
program = null;
|
||||
}
|
||||
|
||||
boolean hasSameFile(ProgramInfo other) {
|
||||
return file.getPathname().equals(other.getPathname());
|
||||
}
|
||||
|
||||
boolean hasProgram() {
|
||||
return program != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import docking.options.editor.OptionsEditorPanel;
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.feature.vt.api.util.VTOptions;
|
||||
import ghidra.framework.options.EditorStateFactory;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.layout.MiddleLayout;
|
||||
import ghidra.util.layout.VerticalLayout;
|
||||
import util.CollectionUtils;
|
||||
|
||||
public class OptionsPanel extends AbstractMageJPanel<VTWizardStateKey> {
|
||||
|
||||
private static final Dimension DEFAULT_PREFERRED_SIZE = new Dimension(650, 350);
|
||||
|
||||
private List<OptionsEditorPanel> optionsEditorPanelList;
|
||||
private List<VTOptions> optionsList = null;
|
||||
private PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
notifyListenersOfValidityChanged();
|
||||
}
|
||||
};
|
||||
|
||||
OptionsPanel() {
|
||||
super(new BorderLayout());
|
||||
// restricting use?
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
if (optionsList != null) {
|
||||
for (VTOptions options : optionsList) {
|
||||
if (options != null) {
|
||||
HelpLocation helpLocation = options.getOptionsHelpLocation();
|
||||
if (helpLocation != null) {
|
||||
return helpLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default
|
||||
return new HelpLocation("VersionTrackingPlugin", "Options_Panel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension preferredSize = super.getPreferredSize();
|
||||
if (preferredSize.width < DEFAULT_PREFERRED_SIZE.width) {
|
||||
return DEFAULT_PREFERRED_SIZE;
|
||||
}
|
||||
return preferredSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (optionsEditorPanelList != null) {
|
||||
removeAll();
|
||||
optionsEditorPanelList = null;
|
||||
optionsList = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
dispose();
|
||||
List<VTProgramCorrelatorFactory> correlatorFactoryList = getCorrelators(state);
|
||||
|
||||
optionsList = getCorrelatorOptions(state);
|
||||
if (optionsList == null) {
|
||||
optionsList = generateDefaultOptions(state);
|
||||
}
|
||||
|
||||
JPanel panel = new JPanel(new VerticalLayout(30));
|
||||
|
||||
optionsEditorPanelList = new ArrayList<OptionsEditorPanel>();
|
||||
for (int i = 0; i < correlatorFactoryList.size(); i++) {
|
||||
String correlatorName = correlatorFactoryList.get(i).getName();
|
||||
String title = correlatorName + " Options";
|
||||
if (optionsList.get(i) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EditorStateFactory editorStateFactory = new EditorStateFactory();
|
||||
Options options = optionsList.get(i);
|
||||
List<String> optionNames = options.getLeafOptionNames();
|
||||
if (optionNames.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
Collections.sort(optionNames);
|
||||
OptionsEditorPanel optionsPanel =
|
||||
new OptionsEditorPanel(title, options, optionNames, editorStateFactory);
|
||||
optionsPanel.setOptionsPropertyChangeListener(propertyChangeListener);
|
||||
optionsEditorPanelList.add(optionsPanel);
|
||||
panel.add(optionsPanel);
|
||||
}
|
||||
JPanel outerPanel = new JPanel(new MiddleLayout());
|
||||
outerPanel.add(panel);
|
||||
JScrollPane scrollPane = new JScrollPane(outerPanel);
|
||||
scrollPane.getVerticalScrollBar().setUnitIncrement(5);
|
||||
add(scrollPane);
|
||||
}
|
||||
|
||||
private List<VTOptions> generateDefaultOptions(WizardState<VTWizardStateKey> state) {
|
||||
List<VTOptions> list = new ArrayList<VTOptions>();
|
||||
List<VTProgramCorrelatorFactory> correlatorFactoryList = getCorrelators(state);
|
||||
for (VTProgramCorrelatorFactory vtProgramCorrelatorFactory : correlatorFactoryList) {
|
||||
list.add(vtProgramCorrelatorFactory.createDefaultOptions());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<VTOptions> getCorrelatorOptions(WizardState<VTWizardStateKey> state) {
|
||||
List<?> list = (List<?>) state.get(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
return CollectionUtils.asList(list, VTOptions.class);
|
||||
}
|
||||
|
||||
private List<VTProgramCorrelatorFactory> getCorrelators(WizardState<VTWizardStateKey> state) {
|
||||
List<?> list = (List<?>) state.get(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
return CollectionUtils.asList(list, VTProgramCorrelatorFactory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
|
||||
List<VTOptions> tmpOptions = getCorrelatorOptions(state);
|
||||
if (tmpOptions == null) {
|
||||
tmpOptions = generateDefaultOptions(state);
|
||||
}
|
||||
for (VTOptions vtOptions : tmpOptions) {
|
||||
if (vtOptions == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> names = vtOptions.getOptionNames();
|
||||
if (names.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return WizardPanelDisplayability.MUST_BE_DISPLAYED;
|
||||
}
|
||||
return WizardPanelDisplayability.DO_NOT_DISPLAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
if (optionsList != null) {
|
||||
applyOptions();
|
||||
}
|
||||
|
||||
List<VTOptions> newOptions =
|
||||
optionsList != null ? optionsList : generateDefaultOptions(state);
|
||||
|
||||
state.put(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST, newOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Correlator Options";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
applyOptions();
|
||||
for (VTOptions options : optionsList) {
|
||||
if (options != null) {
|
||||
if (!options.validate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyOptions() {
|
||||
for (OptionsEditorPanel panel : optionsEditorPanelList) {
|
||||
panel.apply();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
state.addDependency(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST,
|
||||
VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,252 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.widgets.conditiontestpanel.*;
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.gui.validator.VTPreconditionValidator;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
public class PreconditionsPanel extends AbstractMageJPanel<VTWizardStateKey> implements Scrollable {
|
||||
private static final Dimension DEFAULT_SIZE = new Dimension(650, 480);
|
||||
private ConditionTestPanel conditionsTestPanel;
|
||||
private boolean testsDone = false;
|
||||
private VTNewSessionWizardManager wizardManager;
|
||||
|
||||
public PreconditionsPanel(VTNewSessionWizardManager panelManager) {
|
||||
|
||||
this.wizardManager = panelManager;
|
||||
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JPanel runButtonPanel = new JPanel();
|
||||
runButtonPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
|
||||
runButtonPanel.setLayout(new FlowLayout());
|
||||
JButton runTestsButton = new JButton("Run Precondition Checks");
|
||||
runTestsButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
conditionsTestPanel.runTests();
|
||||
}
|
||||
});
|
||||
runButtonPanel.add(runTestsButton);
|
||||
|
||||
JButton skipTestsButton = new JButton("Skip");
|
||||
skipTestsButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
conditionsTestPanel.skipTests();
|
||||
wizardManager.getWizardManager().next();
|
||||
}
|
||||
});
|
||||
runButtonPanel.add(skipTestsButton);
|
||||
|
||||
add(runButtonPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", "Preconditions_Panel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
state.addDependency(VTWizardStateKey.PRECONDITION_CHECKS_RUN,
|
||||
VTWizardStateKey.SOURCE_PROGRAM_FILE);
|
||||
state.addDependency(VTWizardStateKey.PRECONDITION_CHECKS_RUN,
|
||||
VTWizardStateKey.DESTINATION_PROGRAM_FILE);
|
||||
|
||||
state.addDependency(VTWizardStateKey.HIGHEST_PRECONDITION_STATUS,
|
||||
VTWizardStateKey.PRECONDITION_CHECKS_RUN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (conditionsTestPanel != null) {
|
||||
conditionsTestPanel.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
initializeRunState(state);
|
||||
|
||||
if (!testsDone) {
|
||||
if (conditionsTestPanel != null) {
|
||||
remove(conditionsTestPanel);
|
||||
}
|
||||
conditionsTestPanel = buildConditionPanel(state);
|
||||
add(conditionsTestPanel, BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeRunState(WizardState<VTWizardStateKey> state) {
|
||||
Boolean b = (Boolean) state.get(VTWizardStateKey.PRECONDITION_CHECKS_RUN);
|
||||
testsDone = b == null ? false : b.booleanValue();
|
||||
}
|
||||
|
||||
private ConditionTestPanel buildConditionPanel(final WizardState<VTWizardStateKey> state) {
|
||||
|
||||
Program sourceProgram = (Program) state.get(VTWizardStateKey.SOURCE_PROGRAM);
|
||||
Program destinationProgram = (Program) state.get(VTWizardStateKey.DESTINATION_PROGRAM);
|
||||
|
||||
VTSession existingResults = (VTSession) state.get(VTWizardStateKey.EXISTING_SESSION);
|
||||
|
||||
List<ConditionTester> list =
|
||||
getConditionTests(sourceProgram, destinationProgram, existingResults);
|
||||
Collections.sort(list, new ConditionsComparator());
|
||||
ConditionTestPanel panel = new ConditionTestPanel(list);
|
||||
panel.addListener(new ConditionTestListener() {
|
||||
@Override
|
||||
public void testsCompleted() {
|
||||
state.put(VTWizardStateKey.PRECONDITION_CHECKS_RUN, Boolean.valueOf(testsDone));
|
||||
testsDone();
|
||||
}
|
||||
});
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void testsDone() {
|
||||
testsDone = true;
|
||||
notifyListenersOfValidityChanged();
|
||||
if (hasAnyErrorStatus()) {
|
||||
Msg.showError(getClass(), this, "Warning - Serious Precondition failures",
|
||||
"The precondition checks discovered one or more serious problems. \n\n"
|
||||
+ "If you continue, your version tracking results may be invalid.\n"
|
||||
+ "You should review the errors, cancel this wizard, and correct the problems.");
|
||||
}
|
||||
}
|
||||
|
||||
private List<ConditionTester> getConditionTests(Program sourceProgram,
|
||||
Program destinationProgram, VTSession existingResults) throws SecurityException {
|
||||
List<ConditionTester> list = new ArrayList<ConditionTester>();
|
||||
|
||||
List<Class<? extends VTPreconditionValidator>> vtValidatorClasses =
|
||||
ClassSearcher.getClasses(VTPreconditionValidator.class);
|
||||
for (Class<? extends VTPreconditionValidator> validatorClass : vtValidatorClasses) {
|
||||
try {
|
||||
Constructor<? extends VTPreconditionValidator> ctor =
|
||||
validatorClass.getConstructor(Program.class, Program.class, VTSession.class);
|
||||
VTPreconditionValidator validator =
|
||||
ctor.newInstance(sourceProgram, destinationProgram, existingResults);
|
||||
list.add(validator);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "error including VTPreconditionValidator " + validatorClass, e);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
|
||||
initializeRunState(state);
|
||||
return testsDone ? WizardPanelDisplayability.CAN_BE_DISPLAYED
|
||||
: WizardPanelDisplayability.MUST_BE_DISPLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
state.put(VTWizardStateKey.PRECONDITION_CHECKS_RUN, Boolean.valueOf(testsDone));
|
||||
state.put(VTWizardStateKey.HIGHEST_PRECONDITION_STATUS, hasAnyErrorStatus());
|
||||
}
|
||||
|
||||
private Boolean hasAnyErrorStatus() {
|
||||
return conditionsTestPanel.getErrorCount() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Precondition Checklist";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
return testsDone;
|
||||
}
|
||||
|
||||
@Override
|
||||
// Overridden to account for the fact that we don't know our preferred size until later in
|
||||
// the wizard flow. At that point, the initial size of the wizard is already too small.
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension superSize = super.getPreferredSize();
|
||||
if (superSize.width > DEFAULT_SIZE.width && superSize.height > DEFAULT_SIZE.height) {
|
||||
return superSize;
|
||||
}
|
||||
return DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return 25;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportHeight() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
private class ConditionsComparator implements Comparator<ConditionTester> {
|
||||
@Override
|
||||
public int compare(ConditionTester o1, ConditionTester o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,221 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.widgets.label.GDHtmlLabel;
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.layout.PairLayout;
|
||||
import util.CollectionUtils;
|
||||
|
||||
public class SummaryPanel extends AbstractMageJPanel<VTWizardStateKey> {
|
||||
private JLabel labelLabel;
|
||||
private JLabel summaryLabel;
|
||||
private static String NEW_SUMMARY_PANEL = "New_Session_Summary_Panel";
|
||||
private static String ADD_SUMMARY_PANEL = "Add_To_Session_Summary_Panel";
|
||||
private String helpName = ADD_SUMMARY_PANEL;
|
||||
|
||||
SummaryPanel() {
|
||||
|
||||
labelLabel = new GDHtmlLabel();
|
||||
summaryLabel = new GDHtmlLabel();
|
||||
|
||||
JPanel mainPanel = new JPanel(new PairLayout(5, 10));
|
||||
mainPanel.add(labelLabel);
|
||||
mainPanel.add(summaryLabel);
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
|
||||
setLayout(new BorderLayout());
|
||||
add(mainPanel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", helpName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
StringBuilder label = new StringBuilder();
|
||||
StringBuilder summary = new StringBuilder();
|
||||
|
||||
label.append("<html>");
|
||||
summary.append("<html>");
|
||||
|
||||
// session mode
|
||||
|
||||
label.append("Operation:");
|
||||
String opDescription = (String) state.get(VTWizardStateKey.WIZARD_OP_DESCRIPTION);
|
||||
helpName = ((opDescription != null) && opDescription.startsWith("New")) ? NEW_SUMMARY_PANEL
|
||||
: ADD_SUMMARY_PANEL;
|
||||
summary.append(opDescription);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
String sessionName = (String) state.get(VTWizardStateKey.SESSION_NAME);
|
||||
|
||||
label.append("Session Name:");
|
||||
summary.append(sessionName);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
String sourceProgramName = null;
|
||||
String destinationProgramName = null;
|
||||
|
||||
DomainFile sourceProgram = (DomainFile) state.get(VTWizardStateKey.SOURCE_PROGRAM_FILE);
|
||||
sourceProgramName = sourceProgram.getName();
|
||||
|
||||
DomainFile destinationProgram =
|
||||
(DomainFile) state.get(VTWizardStateKey.DESTINATION_PROGRAM_FILE);
|
||||
destinationProgramName = destinationProgram.getName();
|
||||
|
||||
// source program
|
||||
|
||||
label.append("Source Program:");
|
||||
summary.append(
|
||||
sourceProgramName == null ? "(null)" : HTMLUtilities.escapeHTML(sourceProgramName));
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
// destination program
|
||||
|
||||
label.append("Destination Program:");
|
||||
summary.append(destinationProgramName == null ? "(null)"
|
||||
: HTMLUtilities.escapeHTML(destinationProgramName));
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
String correlatorLabel = "";
|
||||
String correlatorName = null;
|
||||
|
||||
List<VTProgramCorrelatorFactory> correlators = getCorrelators(state);
|
||||
if (correlators != null) {
|
||||
for (VTProgramCorrelatorFactory correlatorFactory : correlators) {
|
||||
correlatorName = correlatorFactory.getName();
|
||||
|
||||
label.append(correlatorLabel + "Program Correlator:");
|
||||
summary.append(correlatorName == null ? "(null)" : correlatorName);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Boolean excludeAcceptedMatches =
|
||||
(Boolean) state.get(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES);
|
||||
if (excludeAcceptedMatches != null) {
|
||||
label.append("Exclude Accepted Matches:");
|
||||
summary.append(excludeAcceptedMatches.booleanValue() ? "Yes" : "No");
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
}
|
||||
|
||||
Boolean showAddressSetPanels =
|
||||
(Boolean) state.get(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS);
|
||||
if (showAddressSetPanels != null) {
|
||||
boolean manuallySpecifiedAddresses = showAddressSetPanels.booleanValue();
|
||||
AddressSetChoice sourceAddressSetChoice =
|
||||
(AddressSetChoice) state.get(VTWizardStateKey.SOURCE_ADDRESS_SET_CHOICE);
|
||||
AddressSetChoice destinationAddressSetChoice =
|
||||
(AddressSetChoice) state.get(VTWizardStateKey.DESTINATION_ADDRESS_SET_CHOICE);
|
||||
String sourceAddressesInfo =
|
||||
(sourceAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED) ? "Manually Defined"
|
||||
: ((sourceAddressSetChoice == AddressSetChoice.SELECTION))
|
||||
? "Source Tool Selection"
|
||||
: "Entire Source Program";
|
||||
String destinationAddressesInfo =
|
||||
(destinationAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED)
|
||||
? "Manually Defined"
|
||||
: ((destinationAddressSetChoice == AddressSetChoice.SELECTION))
|
||||
? "Destination Tool Selection"
|
||||
: "Entire Destination Program";
|
||||
|
||||
label.append("Source Address Set:");
|
||||
summary.append(sourceAddressesInfo);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
label.append("Destination Address Set:");
|
||||
summary.append(destinationAddressesInfo);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
}
|
||||
|
||||
label.append("</html>");
|
||||
summary.append("</html>");
|
||||
|
||||
labelLabel.setText(label.toString());
|
||||
summaryLabel.setText(summary.toString());
|
||||
}
|
||||
|
||||
private List<VTProgramCorrelatorFactory> getCorrelators(WizardState<VTWizardStateKey> state) {
|
||||
List<?> list = (List<?>) state.get(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
return CollectionUtils.asList(list, VTProgramCorrelatorFactory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
return WizardPanelDisplayability.CAN_BE_DISPLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
// Do nothing. The summary panel only displays information.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Summary";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
// no dependencies; we just confirm what's going to happen
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.task.Task;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import docking.wizard.*;
|
||||
|
||||
public class VTAddToSessionWizardManager extends AbstractMagePanelManager<VTWizardStateKey> {
|
||||
|
||||
private final VTController controller;
|
||||
|
||||
public VTAddToSessionWizardManager(VTController controller) {
|
||||
super(new WizardState<VTWizardStateKey>());
|
||||
this.controller = controller;
|
||||
Program sourceProgram = controller.getSourceProgram();
|
||||
Program destinationProgram = controller.getDestinationProgram();
|
||||
VTSession session = controller.getSession();
|
||||
|
||||
WizardState<VTWizardStateKey> state = getState();
|
||||
state.put(VTWizardStateKey.SOURCE_PROGRAM, sourceProgram);
|
||||
state.put(VTWizardStateKey.DESTINATION_PROGRAM, destinationProgram);
|
||||
state.put(VTWizardStateKey.SOURCE_PROGRAM_FILE, sourceProgram.getDomainFile());
|
||||
state.put(VTWizardStateKey.DESTINATION_PROGRAM_FILE, destinationProgram.getDomainFile());
|
||||
state.put(VTWizardStateKey.EXISTING_SESSION, session);
|
||||
state.put(VTWizardStateKey.SESSION_NAME, session.getName());
|
||||
state.put(VTWizardStateKey.WIZARD_OP_DESCRIPTION, "Add to Version Tracking Session");
|
||||
state.put(VTWizardStateKey.SOURCE_SELECTION, controller.getSelectionInSourceTool());
|
||||
state.put(VTWizardStateKey.DESTINATION_SELECTION,
|
||||
controller.getSelectionInDestinationTool());
|
||||
|
||||
}
|
||||
|
||||
protected ArrayList<MagePanel<VTWizardStateKey>> createPanels() {
|
||||
ArrayList<MagePanel<VTWizardStateKey>> panels =
|
||||
new ArrayList<MagePanel<VTWizardStateKey>>();
|
||||
panels.add(new CorrelatorPanel(controller.getSession()));
|
||||
panels.add(new OptionsPanel());
|
||||
panels.add(new AddressSetOptionsPanel());
|
||||
panels.add(new LimitAddressSetsPanel(controller.getTool()));
|
||||
panels.add(new SummaryPanel());
|
||||
return panels;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFinish() {
|
||||
try {
|
||||
Task task = new AddToSessionTask(controller, getState());
|
||||
new TaskLauncher(task, getWizardManager().getComponent());
|
||||
}
|
||||
finally {
|
||||
getWizardManager().completed(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.util.task.Task;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
|
||||
public class VTNewSessionWizardManager extends AbstractMagePanelManager<VTWizardStateKey> {
|
||||
|
||||
private final VTController controller;
|
||||
|
||||
public VTNewSessionWizardManager(VTController controller) {
|
||||
super(new WizardState<VTWizardStateKey>());
|
||||
this.controller = controller;
|
||||
getState().put(VTWizardStateKey.WIZARD_OP_DESCRIPTION, "New Version Tracking Session");
|
||||
}
|
||||
|
||||
public VTNewSessionWizardManager(VTController controller, DomainFile sourceFile,
|
||||
DomainFile destinationFile) {
|
||||
this(controller);
|
||||
getState().put(VTWizardStateKey.SOURCE_PROGRAM_FILE, sourceFile);
|
||||
getState().put(VTWizardStateKey.DESTINATION_PROGRAM_FILE, destinationFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<MagePanel<VTWizardStateKey>> createPanels() {
|
||||
List<MagePanel<VTWizardStateKey>> panels = new ArrayList<>();
|
||||
panels.add(new NewSessionPanel(controller.getTool()));
|
||||
panels.add(new PreconditionsPanel(this));
|
||||
panels.add(new SummaryPanel());
|
||||
return panels;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFinish() {
|
||||
try {
|
||||
Task task = new CreateNewSessionTask(controller, getState());
|
||||
new TaskLauncher(task, getWizardManager().getComponent());
|
||||
}
|
||||
finally {
|
||||
getWizardManager().completed(true);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
List<MagePanel<VTWizardStateKey>> panels = getPanels();
|
||||
for (MagePanel<VTWizardStateKey> magePanel : panels) {
|
||||
magePanel.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public PluginTool getTool() {
|
||||
return controller.getTool();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
enum VTWizardStateKey {
|
||||
WIZARD_OP_DESCRIPTION, EXISTING_SESSION, SESSION_NAME,
|
||||
|
||||
SOURCE_PROGRAM_FILE, DESTINATION_PROGRAM_FILE,
|
||||
|
||||
SOURCE_PROGRAM, DESTINATION_PROGRAM,
|
||||
|
||||
SOURCE_ADDRESS_SET_VIEW, DESTINATION_ADDRESS_SET_VIEW,
|
||||
|
||||
PRECONDITION_CHECKS_RUN,
|
||||
|
||||
NEW_SESSION_FOLDER,
|
||||
|
||||
ADDRESS_RANGES_MODE,
|
||||
|
||||
PROGRAM_CORRELATOR_FACTORY_LIST,
|
||||
|
||||
PROGRAM_CORRELATOR_OPTIONS_LIST, HIGHEST_PRECONDITION_STATUS,
|
||||
|
||||
SHOW_ADDRESS_SET_PANELS,
|
||||
|
||||
EXCLUDE_ACCEPTED_MATCHES,
|
||||
|
||||
SOURCE_SELECTION, DESTINATION_SELECTION,
|
||||
|
||||
SOURCE_ADDRESS_SET_CHOICE, DESTINATION_ADDRESS_SET_CHOICE;
|
||||
}
|
|
@ -13,9 +13,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@ -23,7 +25,7 @@ import docking.DialogComponentProvider;
|
|||
import docking.widgets.label.GDLabel;
|
||||
import ghidra.app.util.AddressInput;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.layout.PairLayout;
|
||||
|
@ -31,7 +33,7 @@ import ghidra.util.layout.PairLayout;
|
|||
public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
||||
|
||||
private Program program;
|
||||
private AddressRangeListener listener;
|
||||
private Consumer<AddressRange> addressRangeConsumer;
|
||||
|
||||
private JPanel addressRangePanel;
|
||||
private JLabel minLabel;
|
||||
|
@ -40,10 +42,10 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
|||
private AddressInput maxAddressField;
|
||||
|
||||
protected AddRemoveAddressRangeDialog(String type, String programIndicator, Program program,
|
||||
AddressRangeListener listener) {
|
||||
Consumer<AddressRange> addressRangeConsumer) {
|
||||
super(programIndicator + " Address Range", true, true, true, false);
|
||||
this.program = program;
|
||||
this.listener = listener;
|
||||
this.addressRangeConsumer = Objects.requireNonNull(addressRangeConsumer);
|
||||
setHelpLocation(new HelpLocation(HelpTopics.LABEL, "AddEditDialog"));
|
||||
addWorkPanel(createAddressRangePanel());
|
||||
|
||||
|
@ -99,9 +101,7 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
|
|||
@Override
|
||||
protected void okCallback() {
|
||||
if (isValidRange()) {
|
||||
if (listener != null) {
|
||||
listener.processAddressRange(getMinAddress(), getMaxAddress());
|
||||
}
|
||||
addressRangeConsumer.accept(new AddressRangeImpl(getMinAddress(), getMaxAddress()));
|
||||
close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.api.util.VTOptions;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
* Wizard data used by the {@link VTAddToSessionWizardModel} and its steps for the "add to version
|
||||
* tracking session" wizard.
|
||||
*/
|
||||
public class AddToSessionData {
|
||||
public static enum AddressSetChoice {
|
||||
ENTIRE_PROGRAM, SELECTION, MANUALLY_DEFINED
|
||||
}
|
||||
|
||||
private Program sourceProgram;
|
||||
private Program destinationProgram;
|
||||
private VTSession session;
|
||||
private AddressSetView customSourceAddressSet;
|
||||
private AddressSetView customDestinationAddressSet;
|
||||
private AddressSetView sourceSelection;
|
||||
private AddressSetView destinationSelection;
|
||||
private List<VTProgramCorrelatorFactory> correlators;
|
||||
private Map<VTProgramCorrelatorFactory, VTOptions> optionsMap = new HashMap<>();
|
||||
private boolean shouldExcludeAcceptedMatches;
|
||||
private boolean shouldLimitAddressSets;
|
||||
private AddressSetChoice sourceAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
|
||||
private AddressSetChoice destinationAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
|
||||
|
||||
public void setSourceProgram(Program sourceProgram) {
|
||||
this.sourceProgram = sourceProgram;
|
||||
}
|
||||
|
||||
public Program getSourceProgram() {
|
||||
return sourceProgram;
|
||||
}
|
||||
|
||||
public void setDestinationProgram(Program destinationProgram) {
|
||||
this.destinationProgram = destinationProgram;
|
||||
}
|
||||
|
||||
public Program getDestinationProgram() {
|
||||
return destinationProgram;
|
||||
}
|
||||
|
||||
public void setSession(VTSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public VTSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public DomainFile getSourceFile() {
|
||||
return sourceProgram.getDomainFile();
|
||||
}
|
||||
|
||||
public DomainFile getDestinationFile() {
|
||||
return destinationProgram.getDomainFile();
|
||||
}
|
||||
|
||||
public AddressSetChoice getSourceAddressSetChoice() {
|
||||
return sourceAddressSetChoice;
|
||||
}
|
||||
|
||||
public AddressSetChoice getDestinationAddressSetChoice() {
|
||||
return destinationAddressSetChoice;
|
||||
}
|
||||
|
||||
public void setSourceAddressSetChoice(AddressSetChoice choice) {
|
||||
this.sourceAddressSetChoice = choice;
|
||||
}
|
||||
|
||||
public void setDestinationAddressSetChoice(AddressSetChoice choice) {
|
||||
this.destinationAddressSetChoice = choice;
|
||||
}
|
||||
|
||||
public void setSourceSelection(AddressSetView addressSet) {
|
||||
this.sourceSelection = addressSet;
|
||||
// if a source selection is set, the limit option defaults to true;
|
||||
if (addressSet != null && !addressSet.isEmpty()) {
|
||||
shouldLimitAddressSets = true;
|
||||
sourceAddressSetChoice = AddressSetChoice.SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDestinationSelection(AddressSetView addresseSet) {
|
||||
this.destinationSelection = addresseSet;
|
||||
// if a destination selection is set, the limit option defaults to true;
|
||||
if (addresseSet != null && !addresseSet.isEmpty()) {
|
||||
shouldLimitAddressSets = true;
|
||||
destinationAddressSetChoice = AddressSetChoice.SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
public AddressSetView getCustomSourceAddressSet() {
|
||||
return customSourceAddressSet;
|
||||
}
|
||||
|
||||
public void setCustomSourceAddressSet(AddressSetView addressSet) {
|
||||
customSourceAddressSet = addressSet;
|
||||
}
|
||||
|
||||
public void setCustomDestinationAddressSet(AddressSetView addressSet) {
|
||||
customDestinationAddressSet = addressSet;
|
||||
}
|
||||
|
||||
public AddressSetView getCustomDestinationAddressSet() {
|
||||
return customDestinationAddressSet;
|
||||
}
|
||||
|
||||
public AddressSetView getSourceSelection() {
|
||||
return sourceSelection;
|
||||
}
|
||||
|
||||
public AddressSetView getDestinationSelection() {
|
||||
return destinationSelection;
|
||||
}
|
||||
|
||||
public List<VTProgramCorrelatorFactory> getCorrelators() {
|
||||
return correlators;
|
||||
}
|
||||
|
||||
public void setCorrelators(List<VTProgramCorrelatorFactory> correlators) {
|
||||
if (!correlators.equals(this.correlators)) {
|
||||
this.correlators = correlators;
|
||||
// whenever the set of correlators changes, reset the options to force options panel
|
||||
// to show
|
||||
optionsMap = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOptions(Map<VTProgramCorrelatorFactory, VTOptions> optionsMap) {
|
||||
this.optionsMap = optionsMap;
|
||||
}
|
||||
|
||||
public Map<VTProgramCorrelatorFactory, VTOptions> getOptions() {
|
||||
return optionsMap;
|
||||
}
|
||||
|
||||
public boolean shouldExcludeAcceptedMatches() {
|
||||
return shouldExcludeAcceptedMatches;
|
||||
}
|
||||
|
||||
public void setShouldExcludeAcceptedMatches(boolean b) {
|
||||
shouldExcludeAcceptedMatches = b;
|
||||
}
|
||||
|
||||
public boolean shouldLimitAddressSets() {
|
||||
return shouldLimitAddressSets;
|
||||
}
|
||||
|
||||
public void setShouldLimitAddressSets(boolean b) {
|
||||
shouldLimitAddressSets = b;
|
||||
}
|
||||
|
||||
}
|
|
@ -13,16 +13,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import docking.wizard.WizardState;
|
||||
import ghidra.feature.vt.api.main.*;
|
||||
import ghidra.feature.vt.api.util.VTMatchUtil;
|
||||
import ghidra.feature.vt.api.util.VTOptions;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
|
||||
import ghidra.framework.data.DomainObjectAdapterDB;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
|
@ -31,16 +29,15 @@ import ghidra.util.Msg;
|
|||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.Task;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import util.CollectionUtils;
|
||||
|
||||
public class AddToSessionTask extends Task {
|
||||
private final WizardState<VTWizardStateKey> state;
|
||||
private final AddToSessionData data;
|
||||
private final VTController controller;
|
||||
|
||||
public AddToSessionTask(VTController controller, WizardState<VTWizardStateKey> state) {
|
||||
public AddToSessionTask(VTController controller, AddToSessionData data) {
|
||||
super("Merge Version Tracking Session", true, true, true);
|
||||
this.controller = controller;
|
||||
this.state = state;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,49 +48,10 @@ public class AddToSessionTask extends Task {
|
|||
Program sourceProgram = session.getSourceProgram();
|
||||
Program destinationProgram = session.getDestinationProgram();
|
||||
|
||||
Boolean value = (Boolean) state.get(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES);
|
||||
boolean excludeAcceptedMatches = (value == null) ? false : value.booleanValue();
|
||||
boolean excludeAcceptedMatches = data.shouldExcludeAcceptedMatches();
|
||||
|
||||
AddressSetChoice sourceAddressSetChoice =
|
||||
(AddressSetChoice) state.get(VTWizardStateKey.SOURCE_ADDRESS_SET_CHOICE);
|
||||
AddressSetChoice destinationAddressSetChoice =
|
||||
(AddressSetChoice) state.get(VTWizardStateKey.DESTINATION_ADDRESS_SET_CHOICE);
|
||||
if (sourceAddressSetChoice == null) {
|
||||
sourceAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
|
||||
}
|
||||
if (destinationAddressSetChoice == null) {
|
||||
destinationAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
|
||||
}
|
||||
|
||||
AddressSetView sourceAddressSet;
|
||||
switch (sourceAddressSetChoice) {
|
||||
case SELECTION:
|
||||
sourceAddressSet = (AddressSetView) state.get(VTWizardStateKey.SOURCE_SELECTION);
|
||||
break;
|
||||
case MANUALLY_DEFINED:
|
||||
sourceAddressSet =
|
||||
(AddressSetView) state.get(VTWizardStateKey.SOURCE_ADDRESS_SET_VIEW);
|
||||
break;
|
||||
case ENTIRE_PROGRAM:
|
||||
default:
|
||||
sourceAddressSet = sourceProgram.getMemory();
|
||||
break;
|
||||
}
|
||||
AddressSetView destinationAddressSet;
|
||||
switch (destinationAddressSetChoice) {
|
||||
case SELECTION:
|
||||
destinationAddressSet =
|
||||
(AddressSetView) state.get(VTWizardStateKey.DESTINATION_SELECTION);
|
||||
break;
|
||||
case MANUALLY_DEFINED:
|
||||
destinationAddressSet =
|
||||
(AddressSetView) state.get(VTWizardStateKey.DESTINATION_ADDRESS_SET_VIEW);
|
||||
break;
|
||||
case ENTIRE_PROGRAM:
|
||||
default:
|
||||
destinationAddressSet = destinationProgram.getMemory();
|
||||
break;
|
||||
}
|
||||
AddressSetView sourceAddressSet = getSourceAddressSet();
|
||||
AddressSetView destinationAddressSet = getDestinationAddressSet();
|
||||
|
||||
if (excludeAcceptedMatches) {
|
||||
sourceAddressSet = excludeAcceptedMatches(sourceAddressSet, true);
|
||||
|
@ -104,14 +62,14 @@ public class AddToSessionTask extends Task {
|
|||
boolean completedSucessfully = false;
|
||||
try {
|
||||
session.setEventsEnabled(false); // prevent table updates while busy
|
||||
List<VTProgramCorrelatorFactory> correlatorFactories = getCorrelators(state);
|
||||
List<VTOptions> correlatorOptions = getCorrelatorOptions(state);
|
||||
List<VTProgramCorrelatorFactory> correlatorFactories = data.getCorrelators();
|
||||
Map<VTProgramCorrelatorFactory, VTOptions> optionsMap = data.getOptions();
|
||||
List<VTProgramCorrelator> noMatchList = new ArrayList<>();
|
||||
for (int i = 0; i < correlatorFactories.size(); i++) {
|
||||
VTProgramCorrelatorFactory factory = correlatorFactories.get(i);
|
||||
for (VTProgramCorrelatorFactory factory : correlatorFactories) {
|
||||
VTOptions options = optionsMap.get(factory);
|
||||
VTProgramCorrelator correlator =
|
||||
factory.createCorrelator(sourceProgram, sourceAddressSet, destinationProgram,
|
||||
destinationAddressSet, correlatorOptions.get(i));
|
||||
destinationAddressSet, options);
|
||||
|
||||
VTMatchSet resultSet = correlator.correlate(session, monitor);
|
||||
if (resultSet.getMatchCount() == 0) {
|
||||
|
@ -150,6 +108,36 @@ public class AddToSessionTask extends Task {
|
|||
}
|
||||
}
|
||||
|
||||
private AddressSetView getSourceAddressSet() {
|
||||
if (!data.shouldLimitAddressSets()) {
|
||||
return data.getSourceProgram().getMemory();
|
||||
}
|
||||
switch (data.getSourceAddressSetChoice()) {
|
||||
case MANUALLY_DEFINED:
|
||||
return data.getCustomSourceAddressSet();
|
||||
case SELECTION:
|
||||
return data.getSourceSelection();
|
||||
case ENTIRE_PROGRAM:
|
||||
default:
|
||||
return data.getSourceProgram().getMemory();
|
||||
}
|
||||
}
|
||||
|
||||
private AddressSetView getDestinationAddressSet() {
|
||||
if (!data.shouldLimitAddressSets()) {
|
||||
return data.getDestinationProgram().getMemory();
|
||||
}
|
||||
switch (data.getDestinationAddressSetChoice()) {
|
||||
case MANUALLY_DEFINED:
|
||||
return data.getCustomDestinationAddressSet();
|
||||
case SELECTION:
|
||||
return data.getDestinationSelection();
|
||||
case ENTIRE_PROGRAM:
|
||||
default:
|
||||
return data.getDestinationProgram().getMemory();
|
||||
}
|
||||
}
|
||||
|
||||
private void endTransaction(VTSession session, int transactionID,
|
||||
boolean completedSucessfully) {
|
||||
if (transactionID == -1) {
|
||||
|
@ -165,21 +153,8 @@ public class AddToSessionTask extends Task {
|
|||
return -1;
|
||||
}
|
||||
|
||||
private List<VTOptions> getCorrelatorOptions(WizardState<VTWizardStateKey> stateKey) {
|
||||
return CollectionUtils.asList(
|
||||
(List<?>) stateKey.get(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST),
|
||||
VTOptions.class);
|
||||
}
|
||||
|
||||
private List<VTProgramCorrelatorFactory> getCorrelators(
|
||||
WizardState<VTWizardStateKey> stateKey) {
|
||||
return CollectionUtils.asList(
|
||||
(List<?>) stateKey.get(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST),
|
||||
VTProgramCorrelatorFactory.class);
|
||||
}
|
||||
|
||||
private AddressSet excludeAcceptedMatches(AddressSetView addrSetView, boolean source) {
|
||||
VTSession session = (VTSession) state.get(VTWizardStateKey.EXISTING_SESSION);
|
||||
VTSession session = data.getSession();
|
||||
AddressSet addrSet = new AddressSet(addrSetView);
|
||||
if (session != null) {
|
||||
List<VTMatchSet> matchSets = session.getMatchSets();
|
|
@ -0,0 +1,90 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import static ghidra.feature.vt.api.main.VTProgramCorrelatorAddressRestrictionPreference.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.widgets.checkbox.GCheckBox;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.layout.VerticalLayout;
|
||||
|
||||
/**
|
||||
* Panel for choosing the address set to used for performing new correlations when adding to
|
||||
* a version tracking session. Used by the {@link AddressSetOptionsStep}.
|
||||
*/
|
||||
public class AddressSetOptionsPanel extends JPanel {
|
||||
|
||||
private JCheckBox excludeCheckbox;
|
||||
private JCheckBox limitAddressSetsCheckbox;
|
||||
|
||||
public AddressSetOptionsPanel() { //
|
||||
setBorder(BorderFactory.createEmptyBorder(40, 40, 0, 0));
|
||||
|
||||
excludeCheckbox = new GCheckBox("Exclude accepted matches", false);
|
||||
String excludeAcceptedTooltip = "This option will cause the correlator algorithm " +
|
||||
"to <b>not</b> consider any functions or data that have already been " +
|
||||
"accepted. Using this option can greatly speed up the processing time " +
|
||||
"of the correlator algorithm; however, this options should only be " +
|
||||
"used when you trust that your accepted matches are correct.";
|
||||
excludeCheckbox.setToolTipText(HTMLUtilities.toWrappedHTML(excludeAcceptedTooltip));
|
||||
|
||||
limitAddressSetsCheckbox = new GCheckBox("Limit source and destination address sets");
|
||||
String manuallyLimitTooltip = "Selecting this checkbox will trigger additional wizard " +
|
||||
" panels allowing you to customize the address sets used " +
|
||||
" by the selected algorithm. When not selected, the entire address space is used.";
|
||||
|
||||
limitAddressSetsCheckbox.setToolTipText(
|
||||
HTMLUtilities.toWrappedHTML(manuallyLimitTooltip));
|
||||
|
||||
add(excludeCheckbox);
|
||||
add(limitAddressSetsCheckbox);
|
||||
setLayout(new VerticalLayout(20));
|
||||
}
|
||||
|
||||
public void initialize(AddToSessionData data) {
|
||||
|
||||
excludeCheckbox.setSelected(data.shouldExcludeAcceptedMatches());
|
||||
limitAddressSetsCheckbox.setSelected(data.shouldLimitAddressSets());
|
||||
|
||||
if (allowRestrictions(data.getCorrelators())) {
|
||||
excludeCheckbox.setEnabled(true);
|
||||
}
|
||||
else {
|
||||
excludeCheckbox.setSelected(false);
|
||||
excludeCheckbox.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean allowRestrictions(List<VTProgramCorrelatorFactory> list) {
|
||||
for (VTProgramCorrelatorFactory factory : list) {
|
||||
if (factory.getAddressRestrictionPreference() != RESTRICTION_NOT_ALLOWED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateChoices(AddToSessionData data) {
|
||||
data.setShouldExcludeAcceptedMatches(excludeCheckbox.isSelected());
|
||||
data.setShouldLimitAddressSets(limitAddressSetsCheckbox.isSelected());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.wizard.WizardModel;
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Wizard step for configuring address sets when adding correlations to an existing version
|
||||
* tracking session.
|
||||
*/
|
||||
public class AddressSetOptionsStep extends WizardStep<AddToSessionData> {
|
||||
private AddressSetOptionsPanel panel;
|
||||
|
||||
protected AddressSetOptionsStep(WizardModel<AddToSessionData> model) {
|
||||
super(model, "Address Set Options",
|
||||
new HelpLocation("VersionTrackingPlugin", "Address_Set_Panel"));
|
||||
panel = new AddressSetOptionsPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AddToSessionData data) {
|
||||
panel.initialize(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateData(AddToSessionData data) {
|
||||
panel.updateChoices(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return panel;
|
||||
}
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
|
@ -28,18 +28,18 @@ import docking.widgets.button.GRadioButton;
|
|||
import docking.widgets.label.GLabel;
|
||||
import docking.widgets.list.GList;
|
||||
import generic.theme.GIcon;
|
||||
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.layout.MiddleLayout;
|
||||
import ghidra.util.layout.VerticalLayout;
|
||||
|
||||
/**
|
||||
* Panel for manually adjusting address sets.
|
||||
*/
|
||||
public class ChooseAddressSetEditorPanel extends JPanel {
|
||||
|
||||
public static enum AddressSetChoice {
|
||||
ENTIRE_PROGRAM, SELECTION, MANUALLY_DEFINED
|
||||
}
|
||||
|
||||
private static Icon ADD_ICON = new GIcon("icon.version.tracking.add");
|
||||
private static Icon SUBTRACT_ICON = new GIcon("icon.version.tracking.subtract");
|
||||
|
||||
|
@ -210,18 +210,14 @@ public class ChooseAddressSetEditorPanel extends JPanel {
|
|||
}
|
||||
|
||||
protected void showAddRangeDialog() {
|
||||
AddressRangeListener addListener =
|
||||
(minAddress, maxAddress) -> addRange(minAddress, maxAddress);
|
||||
AddRemoveAddressRangeDialog addRangeDialog =
|
||||
new AddRemoveAddressRangeDialog("Add", name, program, addListener);
|
||||
new AddRemoveAddressRangeDialog("Add", name, program, r -> addRange(r));
|
||||
tool.showDialog(addRangeDialog, this.getRootPane());
|
||||
}
|
||||
|
||||
protected void showSubtractRangeDialog() {
|
||||
AddressRangeListener subtractListener =
|
||||
(minAddress, maxAddress) -> subtractRange(minAddress, maxAddress);
|
||||
AddRemoveAddressRangeDialog removeRangeDialog =
|
||||
new AddRemoveAddressRangeDialog("Remove", name, program, subtractListener);
|
||||
new AddRemoveAddressRangeDialog("Remove", name, program, r -> subtractRange(r));
|
||||
tool.showDialog(removeRangeDialog, this.getRootPane());
|
||||
}
|
||||
|
||||
|
@ -246,14 +242,14 @@ public class ChooseAddressSetEditorPanel extends JPanel {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
private synchronized void addRange(Address minAddress, Address maxAddress) {
|
||||
myCurrentAddressSet.addRange(minAddress, maxAddress);
|
||||
private synchronized void addRange(AddressRange range) {
|
||||
myCurrentAddressSet.add(range);
|
||||
listModel.setData(myCurrentAddressSet.toList());
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
private synchronized void subtractRange(Address minAddress, Address maxAddress) {
|
||||
myCurrentAddressSet.deleteRange(minAddress, maxAddress);
|
||||
private synchronized void subtractRange(AddressRange range) {
|
||||
myCurrentAddressSet.delete(range);
|
||||
listModel.setData(myCurrentAddressSet.toList());
|
||||
notifyListeners();
|
||||
}
|
|
@ -13,10 +13,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -25,21 +26,26 @@ import javax.swing.table.TableColumnModel;
|
|||
|
||||
import docking.widgets.table.GTableCellRenderer;
|
||||
import docking.widgets.table.GTableCellRenderingData;
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.api.impl.VTProgramCorrelatorInfo;
|
||||
import ghidra.feature.vt.api.main.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.table.GhidraTable;
|
||||
import utility.function.Callback;
|
||||
|
||||
public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implements Scrollable {
|
||||
/**
|
||||
* Panel for displaying and choosing from a list of version tracking correlators. Used by the
|
||||
* {@link CorrelatorChooserStep} of the "add to version tracking session" wizard.
|
||||
*/
|
||||
public class CorrelatorChooserPanel extends JPanel {
|
||||
|
||||
private VTProgramTableCorrelatorModel model;
|
||||
private GhidraTable table;
|
||||
private Callback statusChangedCallback;
|
||||
|
||||
CorrelatorPanel(VTSession session) {
|
||||
CorrelatorChooserPanel(VTSession session, Callback statusChangedCallback) {
|
||||
setLayout(new BorderLayout());
|
||||
table = createBasicTable(getPreviouslyRunAlgorithms(session));
|
||||
add(new JScrollPane(table), BorderLayout.CENTER);
|
||||
this.statusChangedCallback = statusChangedCallback;
|
||||
}
|
||||
|
||||
private GhidraTable createBasicTable(Set<String> previouslyRunCorrelators) {
|
||||
|
@ -56,16 +62,16 @@ public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implem
|
|||
return table;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notifyListenersOfValidityChanged() {
|
||||
super.notifyListenersOfValidityChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(1000, 400);
|
||||
}
|
||||
|
||||
void notifyStatusChanged() {
|
||||
statusChangedCallback.call();
|
||||
|
||||
}
|
||||
|
||||
private void setColumnSizes() {
|
||||
TableColumnModel columnModel = table.getColumnModel();
|
||||
int width = 0;
|
||||
|
@ -102,87 +108,8 @@ public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implem
|
|||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("VersionTrackingPlugin", "Correlator_Panel");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterPanel(WizardState<VTWizardStateKey> state) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
static WizardPanelDisplayability correlatorDisplayability(WizardState<VTWizardStateKey> state) {
|
||||
return WizardPanelDisplayability.MUST_BE_DISPLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
|
||||
WizardState<VTWizardStateKey> state) {
|
||||
return correlatorDisplayability(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leavePanel(WizardState<VTWizardStateKey> state) {
|
||||
updateStateObjectWithPanelInfo(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
|
||||
java.util.List<VTProgramCorrelatorFactory> selectedFactories = model.getSelectedFactories();
|
||||
if (!selectedFactories.isEmpty()) {
|
||||
state.put(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST, selectedFactories);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Select Correlation Algorithm(s)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInformation() {
|
||||
return !model.getSelectedFactories().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependencies(WizardState<VTWizardStateKey> state) {
|
||||
// no dependencies
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return 25;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportHeight() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScrollableTracksViewportWidth() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
|
||||
return 10;
|
||||
public List<VTProgramCorrelatorFactory> getSelectedCorrelators() {
|
||||
return model.getSelectedFactories();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
@ -209,4 +136,5 @@ public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implem
|
|||
return renderer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Wizard step for choosing which correlators to run when adding to an existing version
|
||||
* tracking session.
|
||||
*/
|
||||
public class CorrelatorChooserStep extends WizardStep<AddToSessionData> {
|
||||
private CorrelatorChooserPanel panel;
|
||||
|
||||
public CorrelatorChooserStep(VTAddToSessionWizardModel model, VTSession session) {
|
||||
super(model, "Select Correlation Algorithm(s)",
|
||||
new HelpLocation("VersionTrackingPlugin", "Correlator_Panel"));
|
||||
|
||||
panel = new CorrelatorChooserPanel(session, this::notifyStatusChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AddToSessionData data) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
List<VTProgramCorrelatorFactory> correlators = panel.getSelectedCorrelators();
|
||||
if (!correlators.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateData(AddToSessionData data) {
|
||||
data.setCorrelators(panel.getSelectedCorrelators());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish(AddToSessionData data) {
|
||||
return data.getCorrelators() != null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.awt.GridLayout;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
* Panel for adjusting address sets for both the source and destination programs at the same time.
|
||||
* Used by the {@link LimitAddressSetsStep} of the "add to version tracking session wizard.
|
||||
*/
|
||||
public class LimitAddressSetsPanel extends JPanel {
|
||||
|
||||
private ChooseAddressSetEditorPanel sourcePanel;
|
||||
private ChooseAddressSetEditorPanel destinationPanel;
|
||||
private PluginTool tool;
|
||||
|
||||
public LimitAddressSetsPanel(PluginTool tool) {
|
||||
|
||||
this.tool = tool;
|
||||
setLayout(new GridLayout());
|
||||
}
|
||||
|
||||
public void initialize(AddToSessionData data) {
|
||||
removeAll();
|
||||
|
||||
sourcePanel = buildSourcePanel(data);
|
||||
destinationPanel = buildDestinationPanel(data);
|
||||
|
||||
add(sourcePanel);
|
||||
add(destinationPanel);
|
||||
}
|
||||
|
||||
private ChooseAddressSetEditorPanel buildSourcePanel(AddToSessionData data) {
|
||||
Program program = data.getSourceProgram();
|
||||
AddressSetView selection = data.getSourceSelection();
|
||||
AddressSetView set = data.getCustomSourceAddressSet();
|
||||
AddressSetChoice choice = data.getSourceAddressSetChoice();
|
||||
return new ChooseAddressSetEditorPanel(tool, "Source", program, selection, set, choice);
|
||||
}
|
||||
|
||||
private ChooseAddressSetEditorPanel buildDestinationPanel(AddToSessionData data) {
|
||||
Program program = data.getDestinationProgram();
|
||||
AddressSetView selection = data.getDestinationSelection();
|
||||
AddressSetView set = data.getCustomDestinationAddressSet();
|
||||
AddressSetChoice choice = data.getDestinationAddressSetChoice();
|
||||
return new ChooseAddressSetEditorPanel(tool, "Destination", program, selection, set,
|
||||
choice);
|
||||
}
|
||||
|
||||
public void apply(AddToSessionData data) {
|
||||
AddressSetChoice sourceChoice = sourcePanel.getAddressSetChoice();
|
||||
AddressSetChoice destinationChoice = destinationPanel.getAddressSetChoice();
|
||||
data.setSourceAddressSetChoice(sourceChoice);
|
||||
data.setDestinationAddressSetChoice(destinationChoice);
|
||||
data.setCustomSourceAddressSet(null);
|
||||
data.setCustomDestinationAddressSet(null);
|
||||
if (sourceChoice == AddressSetChoice.MANUALLY_DEFINED) {
|
||||
data.setCustomSourceAddressSet(sourcePanel.getAddressSetView());
|
||||
}
|
||||
if (destinationChoice == AddressSetChoice.MANUALLY_DEFINED) {
|
||||
data.setCustomDestinationAddressSet(destinationPanel.getAddressSetView());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Wizard step for choosing the addresses to apply for adding correlation runs to an existing
|
||||
* version tracking session.
|
||||
*/
|
||||
public class LimitAddressSetsStep extends WizardStep<AddToSessionData> {
|
||||
private LimitAddressSetsPanel panel;
|
||||
|
||||
public LimitAddressSetsStep(VTAddToSessionWizardModel model, PluginTool tool) {
|
||||
super(model, "Select Address Range(s)",
|
||||
new HelpLocation("VersionTrackingPlugin", "Select_Address_Ranges_Panel"));
|
||||
|
||||
panel = new LimitAddressSetsPanel(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AddToSessionData data) {
|
||||
panel.initialize(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateData(AddToSessionData data) {
|
||||
panel.apply(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(AddToSessionData data) {
|
||||
return data.shouldLimitAddressSets();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return panel;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.options.editor.OptionsEditorPanel;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.feature.vt.api.util.VTOptions;
|
||||
import ghidra.framework.options.EditorStateFactory;
|
||||
import ghidra.util.layout.VerticalLayout;
|
||||
import utility.function.Callback;
|
||||
|
||||
/**
|
||||
* Panel for displaying version tracking correlator options for selected correlators. Used by
|
||||
* the {@link OptionsStep} of the "add to version tracking session" wizard to configure the
|
||||
* selected correlators from a previous step.
|
||||
*/
|
||||
public class OptionsPanel extends JPanel {
|
||||
|
||||
private static final Dimension DEFAULT_PREFERRED_SIZE = new Dimension(650, 350);
|
||||
|
||||
private List<OptionsEditorPanel> optionsEditorPanelList = new ArrayList<>();
|
||||
private Callback statusChangedCallback;
|
||||
private Map<VTProgramCorrelatorFactory, VTOptions> optionsMap = new HashMap<>();
|
||||
|
||||
private JPanel stagingPanel;
|
||||
|
||||
OptionsPanel(Callback statusChangedCallback) {
|
||||
super(new BorderLayout());
|
||||
this.statusChangedCallback = statusChangedCallback;
|
||||
|
||||
stagingPanel = new JPanel(new BorderLayout());
|
||||
stagingPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
JScrollPane scrollPane = new JScrollPane(stagingPanel);
|
||||
scrollPane.getVerticalScrollBar().setUnitIncrement(5);
|
||||
add(scrollPane);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension preferredSize = super.getPreferredSize();
|
||||
if (preferredSize.width < DEFAULT_PREFERRED_SIZE.width) {
|
||||
return DEFAULT_PREFERRED_SIZE;
|
||||
}
|
||||
return preferredSize;
|
||||
}
|
||||
|
||||
public boolean isApplicable(List<VTProgramCorrelatorFactory> correlators) {
|
||||
updateOptionsMap(correlators);
|
||||
return !optionsMap.isEmpty();
|
||||
}
|
||||
|
||||
private void updateOptionsMap(List<VTProgramCorrelatorFactory> correlators) {
|
||||
optionsMap.keySet().retainAll(correlators);
|
||||
for (VTProgramCorrelatorFactory correlator : correlators) {
|
||||
if (!optionsMap.containsKey(correlator)) {
|
||||
VTOptions defaultOptions = correlator.createDefaultOptions();
|
||||
if (defaultOptions != null) {
|
||||
optionsMap.put(correlator, defaultOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initialize(List<VTProgramCorrelatorFactory> correlators) {
|
||||
updateOptionsMap(correlators);
|
||||
JPanel panel = new JPanel(new VerticalLayout(30));
|
||||
optionsEditorPanelList.clear();
|
||||
for (VTProgramCorrelatorFactory correlator : correlators) {
|
||||
OptionsEditorPanel optionsPanel = buildOptionsPanel(correlator);
|
||||
if (optionsPanel != null) {
|
||||
optionsEditorPanelList.add(optionsPanel);
|
||||
optionsPanel.setOptionsPropertyChangeListener(e -> statusChangedCallback.call());
|
||||
panel.add(optionsPanel);
|
||||
}
|
||||
}
|
||||
|
||||
stagingPanel.removeAll();
|
||||
stagingPanel.add(panel, BorderLayout.CENTER);
|
||||
stagingPanel.revalidate();
|
||||
}
|
||||
|
||||
private OptionsEditorPanel buildOptionsPanel(VTProgramCorrelatorFactory factory) {
|
||||
VTOptions options = optionsMap.get(factory);
|
||||
if (options == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String title = factory.getName() + " Options";
|
||||
|
||||
EditorStateFactory editorStateFactory = new EditorStateFactory();
|
||||
List<String> optionNames = options.getLeafOptionNames();
|
||||
if (optionNames.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Collections.sort(optionNames);
|
||||
return new OptionsEditorPanel(title, options, optionNames, editorStateFactory);
|
||||
}
|
||||
|
||||
public boolean hasValidOptions() {
|
||||
applyOptions();
|
||||
for (VTOptions options : optionsMap.values()) {
|
||||
if (options != null) {
|
||||
if (!options.validate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyOptions() {
|
||||
for (OptionsEditorPanel panel : optionsEditorPanelList) {
|
||||
panel.apply();
|
||||
}
|
||||
}
|
||||
|
||||
Map<VTProgramCorrelatorFactory, VTOptions> getOptionsMap() {
|
||||
return optionsMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.wizard.WizardModel;
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Wizard step for configuring options for the selected correlators when adding to an existing
|
||||
* version tracking session.
|
||||
*/
|
||||
public class OptionsStep extends WizardStep<AddToSessionData> {
|
||||
private OptionsPanel panel;
|
||||
|
||||
protected OptionsStep(WizardModel<AddToSessionData> model) {
|
||||
super(model, "Correlator Options",
|
||||
new HelpLocation("VersionTrackingPlugin", "Options_Panel"));
|
||||
|
||||
panel = new OptionsPanel(this::notifyStatusChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AddToSessionData data) {
|
||||
panel.initialize(data.getCorrelators());
|
||||
// set the options here so that we know this step was visited
|
||||
data.setOptions(panel.getOptionsMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(AddToSessionData data) {
|
||||
return panel.isApplicable(data.getCorrelators());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return panel.hasValidOptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateData(AddToSessionData data) {
|
||||
data.setOptions(panel.getOptionsMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return panel;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.wizard.WizardModel;
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
|
||||
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
|
||||
import ghidra.feature.vt.gui.wizard.session.SummaryPanel;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Wizard step in the "add to tracking session" wizard for summarizing the information that
|
||||
* will be used to add correlations to a version tracking session.
|
||||
*/
|
||||
public class SummaryStep extends WizardStep<AddToSessionData> {
|
||||
private SummaryPanel summaryPanel;
|
||||
|
||||
protected SummaryStep(WizardModel<AddToSessionData> model) {
|
||||
super(model, "Summary",
|
||||
new HelpLocation("VersionTrackingPlugin", "New_Session_Summary_Panel"));
|
||||
|
||||
summaryPanel = new SummaryPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AddToSessionData data) {
|
||||
StringBuilder label = new StringBuilder();
|
||||
StringBuilder summary = new StringBuilder();
|
||||
|
||||
label.append("<html>");
|
||||
summary.append("<html>");
|
||||
|
||||
// session mode
|
||||
|
||||
label.append("Operation:");
|
||||
summary.append("Add to Version Tracking Session");
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
String sessionName = data.getSession().getName();
|
||||
|
||||
label.append("Session Name:");
|
||||
summary.append(sessionName);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
String sourceProgramName = null;
|
||||
String destinationProgramName = null;
|
||||
|
||||
DomainFile sourceProgram = data.getSourceFile();
|
||||
sourceProgramName = sourceProgram.getName();
|
||||
|
||||
DomainFile destinationProgram = data.getDestinationFile();
|
||||
destinationProgramName = destinationProgram.getName();
|
||||
|
||||
// source program
|
||||
|
||||
label.append("Source Program:");
|
||||
summary.append(HTMLUtilities.escapeHTML(sourceProgramName));
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
// destination program
|
||||
|
||||
label.append("Destination Program:");
|
||||
summary.append(HTMLUtilities.escapeHTML(destinationProgramName));
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
String correlatorLabel = "";
|
||||
String correlatorName = null;
|
||||
|
||||
List<VTProgramCorrelatorFactory> correlators = data.getCorrelators();
|
||||
for (VTProgramCorrelatorFactory correlatorFactory : correlators) {
|
||||
correlatorName = correlatorFactory.getName();
|
||||
|
||||
label.append(correlatorLabel + "Program Correlator:");
|
||||
summary.append(correlatorName == null ? "(null)" : correlatorName);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
}
|
||||
boolean excludeAcceptedMatches = data.shouldExcludeAcceptedMatches();
|
||||
label.append("Exclude Accepted Matches:");
|
||||
summary.append(excludeAcceptedMatches ? "Yes" : "No");
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
AddressSetChoice sourceAddressSetChoice = data.getSourceAddressSetChoice();
|
||||
AddressSetChoice destinationAddressSetChoice = data.getDestinationAddressSetChoice();
|
||||
String sourceAddressesInfo =
|
||||
(sourceAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED) ? "Manually Defined"
|
||||
: ((sourceAddressSetChoice == AddressSetChoice.SELECTION))
|
||||
? "Source Tool Selection"
|
||||
: "Entire Source Program";
|
||||
String destinationAddressesInfo =
|
||||
(destinationAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED)
|
||||
? "Manually Defined"
|
||||
: ((destinationAddressSetChoice == AddressSetChoice.SELECTION))
|
||||
? "Destination Tool Selection"
|
||||
: "Entire Destination Program";
|
||||
|
||||
label.append("Source Address Set:");
|
||||
summary.append(sourceAddressesInfo);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
label.append("Destination Address Set:");
|
||||
summary.append(destinationAddressesInfo);
|
||||
label.append("<br>");
|
||||
summary.append("<br>");
|
||||
|
||||
label.append("</html>");
|
||||
summary.append("</html>");
|
||||
|
||||
summaryPanel.initialize(label.toString(), summary.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(AddToSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateData(AddToSessionData data) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return summaryPanel;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import docking.wizard.WizardModel;
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.task.Task;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
|
||||
/**
|
||||
* Wizard model for adding correlation runs to an existing version tracking session.
|
||||
*/
|
||||
public class VTAddToSessionWizardModel extends WizardModel<AddToSessionData> {
|
||||
|
||||
private final VTController controller;
|
||||
|
||||
public VTAddToSessionWizardModel(VTController controller) {
|
||||
super("Add to Version Tracking Session", new AddToSessionData());
|
||||
this.controller = controller;
|
||||
Program sourceProgram = controller.getSourceProgram();
|
||||
Program destinationProgram = controller.getDestinationProgram();
|
||||
VTSession session = controller.getSession();
|
||||
|
||||
data.setSourceProgram(sourceProgram);
|
||||
data.setDestinationProgram(destinationProgram);
|
||||
data.setSession(session);
|
||||
data.setSourceSelection(controller.getSelectionInSourceTool());
|
||||
data.setDestinationSelection(controller.getSelectionInDestinationTool());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addWizardSteps(List<WizardStep<AddToSessionData>> list) {
|
||||
list.add(new CorrelatorChooserStep(this, controller.getSession()));
|
||||
list.add(new OptionsStep(this));
|
||||
list.add(new AddressSetOptionsStep(this));
|
||||
list.add(new LimitAddressSetsStep(this, controller.getTool()));
|
||||
list.add(new SummaryStep(this));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doFinish() {
|
||||
Task task = new AddToSessionTask(controller, data);
|
||||
new TaskLauncher(task, wizardDialog.getComponent());
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
package ghidra.feature.vt.gui.wizard.add;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -26,6 +26,9 @@ import ghidra.feature.vt.api.util.VTAbstractProgramCorrelatorFactory;
|
|||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* Table model for showing version tracking correlators.
|
||||
*/
|
||||
public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgramCorrelatorFactory> {
|
||||
|
||||
static final String NAME_COLUMN_NAME = "Name";
|
||||
|
@ -47,9 +50,9 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
|
|||
private Set<String> previouslyRunCorrelators;
|
||||
private Set<VTProgramCorrelatorFactory> selectedFactories =
|
||||
new HashSet<>();
|
||||
private CorrelatorPanel panel;
|
||||
private CorrelatorChooserPanel panel;
|
||||
|
||||
public VTProgramTableCorrelatorModel(CorrelatorPanel panel,
|
||||
public VTProgramTableCorrelatorModel(CorrelatorChooserPanel panel,
|
||||
Set<String> previouslyRunCorrelators) {
|
||||
this.panel = panel;
|
||||
this.previouslyRunCorrelators = previouslyRunCorrelators;
|
||||
|
@ -57,7 +60,9 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
|
|||
}
|
||||
|
||||
public List<VTProgramCorrelatorFactory> getSelectedFactories() {
|
||||
return new ArrayList<>(selectedFactories);
|
||||
List<VTProgramCorrelatorFactory> factories = new ArrayList<>(selectedFactories);
|
||||
factories.sort(comparator);
|
||||
return factories;
|
||||
}
|
||||
|
||||
private static List<VTProgramCorrelatorFactory> generateList() {
|
||||
|
@ -136,7 +141,7 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
|
|||
else {
|
||||
selectedFactories.remove(factory);
|
||||
}
|
||||
panel.notifyListenersOfValidityChanged();
|
||||
panel.notifyStatusChanged();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -13,11 +13,10 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
package ghidra.feature.vt.gui.wizard.session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import docking.wizard.WizardState;
|
||||
import ghidra.feature.vt.api.db.VTSessionDB;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
|
@ -29,13 +28,13 @@ import ghidra.util.task.Task;
|
|||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class CreateNewSessionTask extends Task {
|
||||
private final WizardState<VTWizardStateKey> state;
|
||||
private final NewSessionData data;
|
||||
private final VTController controller;
|
||||
|
||||
public CreateNewSessionTask(VTController controller, WizardState<VTWizardStateKey> state) {
|
||||
public CreateNewSessionTask(VTController controller, NewSessionData data) {
|
||||
super("Create New Version Tracking Session", true, true, true);
|
||||
this.controller = controller;
|
||||
this.state = state;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,16 +42,16 @@ public class CreateNewSessionTask extends Task {
|
|||
VTSessionDB session = null;
|
||||
String name = null;
|
||||
try {
|
||||
Program sourceProgram = (Program) state.get(VTWizardStateKey.SOURCE_PROGRAM);
|
||||
Program destinationProgram = (Program) state.get(VTWizardStateKey.DESTINATION_PROGRAM);
|
||||
Program sourceProgram = data.getSourceProgram();
|
||||
Program destinationProgram = data.getDestinationProgram();
|
||||
|
||||
session = new VTSessionDB("New Session", sourceProgram, destinationProgram, this);
|
||||
|
||||
sourceProgram.release(controller.getTool());
|
||||
destinationProgram.release(controller.getTool());
|
||||
|
||||
name = (String) state.get(VTWizardStateKey.SESSION_NAME);
|
||||
DomainFolder folder = (DomainFolder) state.get(VTWizardStateKey.NEW_SESSION_FOLDER);
|
||||
name = data.getSessionName();
|
||||
DomainFolder folder = data.getSessionFolder();
|
||||
try {
|
||||
folder.createFile(name, session, monitor);
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.session;
|
||||
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
* Wizard data used by the {@link VTNewSessionWizardModel} and its steps for the "create new version
|
||||
* tracking session" wizard.
|
||||
*/
|
||||
public class NewSessionData {
|
||||
private Program sourceProgram;
|
||||
private Program destinationProgram;
|
||||
private DomainFile sourceFile;
|
||||
private DomainFile destinationFile;
|
||||
private DomainFolder sessionFolder;
|
||||
private String sessionName;
|
||||
private boolean preconditionChecksCompleted;
|
||||
|
||||
public DomainFile getSourceFile() {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
public DomainFile getDestinationFile() {
|
||||
return destinationFile;
|
||||
}
|
||||
|
||||
public Program getSourceProgram() {
|
||||
return sourceProgram;
|
||||
}
|
||||
|
||||
public Program getDestinationProgram() {
|
||||
return destinationProgram;
|
||||
}
|
||||
|
||||
public String getSessionName() {
|
||||
return sessionName;
|
||||
}
|
||||
|
||||
public DomainFolder getSessionFolder() {
|
||||
return sessionFolder;
|
||||
}
|
||||
|
||||
public void setSourceFile(DomainFile file, PluginTool tool) {
|
||||
this.sourceFile = file;
|
||||
if (isProgramInvalidForFile(file, sourceProgram)) {
|
||||
sourceProgram.release(tool);
|
||||
sourceProgram = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isProgramInvalidForFile(DomainFile file, Program program) {
|
||||
|
||||
if (program == null) {
|
||||
return false;
|
||||
}
|
||||
if (program.getDomainFile().equals(file)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setDestinationFile(DomainFile file, PluginTool tool) {
|
||||
this.destinationFile = file;
|
||||
if (isProgramInvalidForFile(file, destinationProgram)) {
|
||||
sourceProgram.release(tool);
|
||||
sourceProgram = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSourceProgram(Program program) {
|
||||
this.sourceProgram = program;
|
||||
preconditionChecksCompleted = false;
|
||||
}
|
||||
|
||||
public void setDestinationProgram(Program program) {
|
||||
this.destinationProgram = program;
|
||||
preconditionChecksCompleted = false;
|
||||
}
|
||||
|
||||
public void setSessionName(String name) {
|
||||
this.sessionName = name;
|
||||
}
|
||||
|
||||
public void setSessionFolder(DomainFolder folder) {
|
||||
this.sessionFolder = folder;
|
||||
}
|
||||
|
||||
public boolean hasPerformedPreconditionChecks() {
|
||||
return preconditionChecksCompleted;
|
||||
}
|
||||
|
||||
public void setPerformedPreconditionChecks(boolean b) {
|
||||
preconditionChecksCompleted = b;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.session;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.widgets.conditiontestpanel.*;
|
||||
import docking.wizard.WizardModel;
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.gui.validator.VTPreconditionValidator;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import utility.function.Callback;
|
||||
|
||||
public class PreconditionsPanel extends JPanel {
|
||||
private static final Dimension DEFAULT_SIZE = new Dimension(650, 480);
|
||||
private ConditionTestPanel conditionsTestPanel;
|
||||
private boolean testsDone = false;
|
||||
private Callback statusChangedCallback;
|
||||
|
||||
public PreconditionsPanel(WizardModel<NewSessionData> model,
|
||||
Callback statusChangedCallback) {
|
||||
this.statusChangedCallback = statusChangedCallback;
|
||||
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JPanel runButtonPanel = new JPanel();
|
||||
runButtonPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
|
||||
runButtonPanel.setLayout(new FlowLayout());
|
||||
JButton runTestsButton = new JButton("Run Precondition Checks");
|
||||
runTestsButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
conditionsTestPanel.runTests();
|
||||
}
|
||||
});
|
||||
runButtonPanel.add(runTestsButton);
|
||||
|
||||
JButton skipTestsButton = new JButton("Skip");
|
||||
skipTestsButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
conditionsTestPanel.skipTests();
|
||||
model.goNext();
|
||||
}
|
||||
});
|
||||
runButtonPanel.add(skipTestsButton);
|
||||
|
||||
add(runButtonPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
if (conditionsTestPanel != null) {
|
||||
conditionsTestPanel.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private ConditionTestPanel buildConditionPanel(Program source, Program destination) {
|
||||
List<ConditionTester> list = getConditionTests(source, destination);
|
||||
Collections.sort(list, (t1, t2) -> t1.getName().compareTo(t2.getName()));
|
||||
ConditionTestPanel panel = new ConditionTestPanel(list);
|
||||
panel.addListener(new ConditionTestListener() {
|
||||
@Override
|
||||
public void testsCompleted() {
|
||||
testsDone();
|
||||
}
|
||||
});
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void testsDone() {
|
||||
testsDone = true;
|
||||
statusChangedCallback.call();
|
||||
if (hasAnyErrorStatus()) {
|
||||
Msg.showError(getClass(), this, "Warning - Serious Precondition failures",
|
||||
"The precondition checks discovered one or more serious problems. \n\n" +
|
||||
"If you continue, your version tracking results may be invalid.\n" +
|
||||
"You should review the errors, cancel this wizard, and correct the problems.");
|
||||
}
|
||||
}
|
||||
|
||||
private List<ConditionTester> getConditionTests(Program sourceProgram,
|
||||
Program destinationProgram) throws SecurityException {
|
||||
List<ConditionTester> list = new ArrayList<ConditionTester>();
|
||||
|
||||
List<Class<? extends VTPreconditionValidator>> vtValidatorClasses =
|
||||
ClassSearcher.getClasses(VTPreconditionValidator.class);
|
||||
for (Class<? extends VTPreconditionValidator> validatorClass : vtValidatorClasses) {
|
||||
try {
|
||||
Constructor<? extends VTPreconditionValidator> ctor =
|
||||
validatorClass.getConstructor(Program.class, Program.class, VTSession.class);
|
||||
VTPreconditionValidator validator =
|
||||
ctor.newInstance(sourceProgram, destinationProgram, null);
|
||||
list.add(validator);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "error including VTPreconditionValidator " + validatorClass, e);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Boolean hasAnyErrorStatus() {
|
||||
return conditionsTestPanel.getErrorCount() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
// Overridden to account for the fact that we don't know our preferred size until later in
|
||||
// the wizard flow. At that point, the initial size of the wizard is already too small.
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension superSize = super.getPreferredSize();
|
||||
if (superSize.width > DEFAULT_SIZE.width && superSize.height > DEFAULT_SIZE.height) {
|
||||
return superSize;
|
||||
}
|
||||
return DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
public void initializeTests(Program sourceProgram, Program destinationProgram) {
|
||||
testsDone = false;
|
||||
if (conditionsTestPanel != null) {
|
||||
remove(conditionsTestPanel);
|
||||
}
|
||||
conditionsTestPanel = buildConditionPanel(sourceProgram, destinationProgram);
|
||||
add(conditionsTestPanel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public boolean hasRunTests() {
|
||||
return testsDone;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.feature.vt.gui.wizard.session;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.wizard.WizardModel;
|
||||
import docking.wizard.WizardStep;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Wizard step for running version tracking precondition tests when creating a new version tracking
|
||||
* session.
|
||||
*/
|
||||
public class PreconditionsStep extends WizardStep<NewSessionData> {
|
||||
private PreconditionsPanel preconditionsPanel;
|
||||
|
||||
protected PreconditionsStep(WizardModel<NewSessionData> model) {
|
||||
super(model, "Precondition Checklist",
|
||||
new HelpLocation("VersionTrackingPlugin", "Preconditions_Panel"));
|
||||
|
||||
preconditionsPanel = new PreconditionsPanel(model, this::notifyStatusChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(NewSessionData data) {
|
||||
if (!data.hasPerformedPreconditionChecks()) {
|
||||
Program sourceProgram = data.getSourceProgram();
|
||||
Program destinationProgram = data.getDestinationProgram();
|
||||
preconditionsPanel.initializeTests(sourceProgram, destinationProgram);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
boolean hasRunTests = preconditionsPanel.hasRunTests();
|
||||
if (hasRunTests) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateData(NewSessionData data) {
|
||||
data.setPerformedPreconditionChecks(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(NewSessionData data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFinish(NewSessionData data) {
|
||||
return data.hasPerformedPreconditionChecks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return preconditionsPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose(NewSessionData data) {
|
||||
preconditionsPanel.dispose();
|
||||
}
|
||||
|
||||
}
|