mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
Merge remote-tracking branch 'upstream/develop' into 5130_exportCSV
This commit is contained in:
commit
29bdc2ee52
@ -45,6 +45,9 @@
|
||||
|
||||
<dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/>
|
||||
<dependency conf="core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.3"/>
|
||||
<dependency org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/>
|
||||
<!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
|
||||
<dependency org="javax.ws.rs" name="javax.ws.rs-api" rev="2.0"/>
|
||||
<override org="jakarta.ws.rs" module="jakarta.ws.rs-api" rev="2.1.5"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
@ -111,6 +111,10 @@ file.reference.grpc-context-1.19.0.jar=release/modules/ext/grpc-context-1.19.0.j
|
||||
file.reference.opencensus-api-0.19.2.jar=release/modules/ext/opencensus-api-0.19.2.jar
|
||||
file.reference.opencensus-contrib-http-util-0.19.2.jar=release/modules/ext/opencensus-contrib-http-util-0.19.2.jar
|
||||
file.reference.threetenbp-1.3.3.jar=release/modules/ext/threetenbp-1.3.3.jar
|
||||
file.reference.okhttp-2.7.5-javadoc.jar=release/modules/ext/okhttp-2.7.5-javadoc.jar
|
||||
file.reference.okhttp-2.7.5-sources.jar=release/modules/ext/okhttp-2.7.5-sources.jar
|
||||
file.reference.okhttp-2.7.5.jar=release/modules/ext/okhttp-2.7.5.jar
|
||||
file.reference.okio-1.6.0.jar=release/modules/ext/okio-1.6.0.jar
|
||||
javac.source=1.8
|
||||
javac.compilerargs=-Xlint -Xlint:-serial
|
||||
license.file=../LICENSE-2.0.txt
|
||||
|
@ -773,6 +773,14 @@
|
||||
<runtime-relative-path>ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/okhttp-2.7.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/okhttp-2.7.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/okio-1.6.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/okio-1.6.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
|
@ -66,6 +66,7 @@ DataSourceSummaryDialog.window.title=Data Sources Summary
|
||||
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
|
||||
DataSourceSummaryNode.column.files.header=Files
|
||||
DataSourceSummaryNode.column.results.header=Results
|
||||
DataSourceSummaryNode.column.status.header=Ingest Status
|
||||
DataSourceSummaryNode.column.tags.header=Tags
|
||||
DataSourceSummaryNode.column.type.header=Type
|
||||
DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source
|
||||
|
@ -37,8 +37,10 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryNode.DataSourceSummaryEntryNode;
|
||||
import static javax.swing.SwingConstants.RIGHT;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -50,9 +52,10 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceBrowser.class.getName());
|
||||
private static final int COUNT_COLUMN_WIDTH = 25;
|
||||
private static final int USAGE_COLUMN_WIDTH = 120;
|
||||
private static final int DATA_SOURCE_COLUMN_WIDTH = 325;
|
||||
private static final int COUNT_COLUMN_WIDTH = 20;
|
||||
private static final int INGEST_STATUS_WIDTH = 50;
|
||||
private static final int USAGE_COLUMN_WIDTH = 110;
|
||||
private static final int DATA_SOURCE_COLUMN_WIDTH = 280;
|
||||
private final Outline outline;
|
||||
private final org.openide.explorer.view.OutlineView outlineView;
|
||||
private final ExplorerManager explorerManager;
|
||||
@ -69,6 +72,7 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
outlineView = new org.openide.explorer.view.OutlineView();
|
||||
this.setVisible(true);
|
||||
outlineView.setPropertyColumns(
|
||||
Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(),
|
||||
Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(),
|
||||
Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(),
|
||||
Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_results_header(),
|
||||
@ -90,6 +94,8 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
column.setPreferredWidth(COUNT_COLUMN_WIDTH);
|
||||
} else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_type_header())) {
|
||||
column.setPreferredWidth(USAGE_COLUMN_WIDTH);
|
||||
} else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_status_header())) {
|
||||
column.setPreferredWidth(INGEST_STATUS_WIDTH);
|
||||
} else {
|
||||
column.setPreferredWidth(DATA_SOURCE_COLUMN_WIDTH);
|
||||
}
|
||||
@ -182,6 +188,47 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the DataSourceBrowser to display up to date status information for
|
||||
* the data sources.
|
||||
*
|
||||
* @param dataSourceId the ID of the data source which should be updated
|
||||
* @param newStatus the new status which the data source should have
|
||||
*/
|
||||
void refresh(long dataSourceId, IngestJobInfo.IngestJobStatusType newStatus) {
|
||||
|
||||
//attempt to update the status of any datasources that had status which was STARTED
|
||||
for (DataSourceSummary summary : dataSourceSummaryList) {
|
||||
if (summary.getDataSource().getId() == dataSourceId) {
|
||||
summary.setIngestStatus(newStatus);
|
||||
}
|
||||
}
|
||||
//figure out which nodes were previously selected
|
||||
Node[] selectedNodes = explorerManager.getSelectedNodes();
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList));
|
||||
List<Node> nodesToSelect = new ArrayList<>();
|
||||
for (Node node : explorerManager.getRootContext().getChildren().getNodes()) {
|
||||
if (node instanceof DataSourceSummaryEntryNode) {
|
||||
//there should only be one selected node as multi-select is disabled
|
||||
for (Node selectedNode : selectedNodes) {
|
||||
if (((DataSourceSummaryEntryNode) node).getDataSource().equals(((DataSourceSummaryEntryNode) selectedNode).getDataSource())) {
|
||||
nodesToSelect.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//reselect the previously selected Nodes
|
||||
try {
|
||||
explorerManager.setSelectedNodes(nodesToSelect.toArray(new Node[nodesToSelect.size()]));
|
||||
} catch (PropertyVetoException ex) {
|
||||
logger.log(Level.WARNING, "Error selecting previously selected nodes", ex);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
|
@ -18,15 +18,27 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Wrapper object for a DataSource and the information associated with it.
|
||||
*
|
||||
*/
|
||||
class DataSourceSummary {
|
||||
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DataSourceSummary.class.getName());
|
||||
private static final String INGEST_JOB_STATUS_QUERY = "status_id FROM ingest_jobs WHERE obj_id=";
|
||||
private final DataSource dataSource;
|
||||
private IngestJobStatusType status = null;
|
||||
private final String type;
|
||||
private final long filesCount;
|
||||
private final long resultsCount;
|
||||
@ -45,12 +57,26 @@ class DataSourceSummary {
|
||||
*/
|
||||
DataSourceSummary(DataSource dSource, String typeValue, Long numberOfFiles, Long numberOfResults, Long numberOfTags) {
|
||||
dataSource = dSource;
|
||||
getStatusFromDatabase();
|
||||
type = typeValue == null ? "" : typeValue;
|
||||
filesCount = numberOfFiles == null ? 0 : numberOfFiles;
|
||||
resultsCount = numberOfResults == null ? 0 : numberOfResults;
|
||||
tagsCount = numberOfTags == null ? 0 : numberOfTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status of the ingest job from the case database
|
||||
*/
|
||||
private void getStatusFromDatabase() {
|
||||
try {
|
||||
IngestJobQueryCallback callback = new IngestJobQueryCallback();
|
||||
Case.getCurrentCaseThrows().getSleuthkitCase().getCaseDbAccessManager().select(INGEST_JOB_STATUS_QUERY + dataSource.getId(), callback);
|
||||
status = callback.getStatus();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error getting status for data source from case database", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DataSource
|
||||
*
|
||||
@ -60,6 +86,16 @@ class DataSourceSummary {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually set the ingest job status
|
||||
*
|
||||
* @param ingestStatus the status which the ingest job should have
|
||||
* currently, null to display empty string
|
||||
*/
|
||||
void setIngestStatus(IngestJobStatusType ingestStatus) {
|
||||
status = ingestStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of this DataSource
|
||||
*
|
||||
@ -87,6 +123,16 @@ class DataSourceSummary {
|
||||
return resultsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IngestJobStatusType associated with this data source.
|
||||
*
|
||||
* @return the IngestJobStatusType associated with this data source. Can be
|
||||
* null if the IngestJobStatusType is not STARTED or COMPLETED.
|
||||
*/
|
||||
IngestJobStatusType getIngestStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of tagged content objects in this DataSource
|
||||
*
|
||||
@ -95,4 +141,40 @@ class DataSourceSummary {
|
||||
long getTagsCount() {
|
||||
return tagsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to parse result set, getting the status to be associated with
|
||||
* this data source
|
||||
*/
|
||||
class IngestJobQueryCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
private IngestJobStatusType jobStatus = null;
|
||||
|
||||
@Override
|
||||
public void process(ResultSet rs) {
|
||||
try {
|
||||
while (rs.next()) {
|
||||
IngestJobStatusType currentStatus = IngestJobStatusType.fromID(rs.getInt("status_id"));
|
||||
if (currentStatus == IngestJobStatusType.COMPLETED) {
|
||||
jobStatus = currentStatus;
|
||||
} else if (currentStatus == IngestJobStatusType.STARTED) {
|
||||
jobStatus = currentStatus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.WARNING, "Error getting status for ingest job", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status which was determined for this callback
|
||||
*
|
||||
* @return the status of the data source which was queried for
|
||||
*/
|
||||
IngestJobStatusType getStatus() {
|
||||
return jobStatus;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,18 @@
|
||||
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Map;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.IngestJobInfo;
|
||||
|
||||
/**
|
||||
* Dialog for displaying the Data Sources Summary information
|
||||
@ -38,7 +42,6 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
private final DataSourceSummaryDetailsPanel detailsPanel;
|
||||
private final DataSourceBrowser dataSourcesPanel;
|
||||
private final IngestJobInfoPanel ingestHistoryPanel;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceSummaryDialog.class.getName());
|
||||
|
||||
/**
|
||||
* Creates new form DataSourceSummaryDialog for displaying a summary of the
|
||||
@ -73,6 +76,17 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
||||
this.repaint();
|
||||
}
|
||||
});
|
||||
//add listener to refresh jobs with Started status when they complete
|
||||
IngestManager.getInstance().addIngestJobEventListener((PropertyChangeEvent evt) -> {
|
||||
if (evt instanceof DataSourceAnalysisCompletedEvent) {
|
||||
DataSourceAnalysisCompletedEvent dsEvent = (DataSourceAnalysisCompletedEvent) evt;
|
||||
if (dsEvent.getResult() == Reason.ANALYSIS_COMPLETED) {
|
||||
dataSourcesPanel.refresh(dsEvent.getDataSource().getId(), IngestJobInfo.IngestJobStatusType.COMPLETED);
|
||||
} else if (dsEvent.getResult() == Reason.ANALYSIS_CANCELLED) {
|
||||
dataSourcesPanel.refresh(dsEvent.getDataSource().getId(), null);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.pack();
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
static final class DataSourceSummaryEntryNode extends AbstractNode {
|
||||
|
||||
private final DataSource dataSource;
|
||||
private final String status;
|
||||
private final String type;
|
||||
private final long filesCount;
|
||||
private final long resultsCount;
|
||||
@ -124,6 +125,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
DataSourceSummaryEntryNode(DataSourceSummary dataSourceSummary) {
|
||||
super(Children.LEAF);
|
||||
dataSource = dataSourceSummary.getDataSource();
|
||||
status = dataSourceSummary.getIngestStatus() == null ? "" : dataSourceSummary.getIngestStatus().getDisplayName();
|
||||
type = dataSourceSummary.getType();
|
||||
filesCount = dataSourceSummary.getFilesCount();
|
||||
resultsCount = dataSourceSummary.getResultsCount();
|
||||
@ -143,6 +145,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
}
|
||||
|
||||
@Messages({"DataSourceSummaryNode.column.dataSourceName.header=Data Source Name",
|
||||
"DataSourceSummaryNode.column.status.header=Ingest Status",
|
||||
"DataSourceSummaryNode.column.type.header=Type",
|
||||
"DataSourceSummaryNode.column.files.header=Files",
|
||||
"DataSourceSummaryNode.column.results.header=Results",
|
||||
@ -157,6 +160,7 @@ final class DataSourceSummaryNode extends AbstractNode {
|
||||
}
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_dataSourceName_header(), Bundle.DataSourceSummaryNode_column_dataSourceName_header(), Bundle.DataSourceSummaryNode_column_dataSourceName_header(),
|
||||
dataSource));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), status));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(),
|
||||
type));
|
||||
sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(),
|
||||
|
@ -83,7 +83,7 @@ MediaViewImagePanel.zoomResetButton.text=Reset
|
||||
MediaViewImagePanel.zoomTextField.text=
|
||||
MediaViewImagePanel.rotationTextField.text=
|
||||
MediaViewImagePanel.rotateLeftButton.toolTipText=
|
||||
HtmlPanel.showImagesToggleButton.text=Show Images
|
||||
HtmlPanel.showImagesToggleButton.text=Download Images
|
||||
MediaPlayerPanel.audioSlider.toolTipText=
|
||||
MediaPlayerPanel.VolumeIcon.text=\ \ \ \ \ Volume
|
||||
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
|
||||
|
@ -22,7 +22,7 @@ GstVideoPanel.cannotProcFile.err=The media player cannot process this file.
|
||||
GstVideoPanel.noOpenCase.errMsg=No open case available.
|
||||
Html_text_display_error=The HTML text cannot be displayed, it may not be correctly formed HTML.
|
||||
HtmlPanel_showImagesToggleButton_hide=Hide Images
|
||||
HtmlPanel_showImagesToggleButton_show=Show Images
|
||||
HtmlPanel_showImagesToggleButton_show=Download Images
|
||||
HtmlViewer_file_error=This file is missing or unreadable.
|
||||
MediaFileViewer.initGst.gstException.msg=Error initializing gstreamer for audio/video viewing and frame extraction capabilities. Video and audio viewing will be disabled.
|
||||
GstVideoPanel.setupVideo.infoLabel.text=Playback of deleted videos is not supported, use an external player.
|
||||
@ -145,7 +145,7 @@ MediaViewImagePanel.zoomResetButton.text=Reset
|
||||
MediaViewImagePanel.zoomTextField.text=
|
||||
MediaViewImagePanel.rotationTextField.text=
|
||||
MediaViewImagePanel.rotateLeftButton.toolTipText=
|
||||
HtmlPanel.showImagesToggleButton.text=Show Images
|
||||
HtmlPanel.showImagesToggleButton.text=Download Images
|
||||
MediaPlayerPanel.audioSlider.toolTipText=
|
||||
MediaPlayerPanel.VolumeIcon.text=\ \ \ \ \ Volume
|
||||
MediaPlayerPanel.progressLabel.text=00:00:00/00:00:00
|
||||
|
@ -18,7 +18,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="showImagesToggleButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="95" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="75" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="htmlJPanel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -18,6 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@ -25,8 +30,9 @@ import javafx.concurrent.Worker;
|
||||
import javafx.scene.web.WebView;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.scene.Scene;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Node;
|
||||
import net.htmlparser.jericho.Attribute;
|
||||
import net.htmlparser.jericho.OutputDocument;
|
||||
import net.htmlparser.jericho.Source;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
@ -38,6 +44,7 @@ import org.w3c.dom.events.EventTarget;
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class HtmlPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(HtmlPanel.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TEXT_TYPE = "text/plain";
|
||||
private final JFXPanel jfxPanel = new JFXPanel();
|
||||
@ -92,26 +99,76 @@ final class HtmlPanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out input HTML string
|
||||
* Cleans out input HTML string so it will not access resources over the internet
|
||||
*
|
||||
* @param htmlInString The HTML string to cleanse
|
||||
*
|
||||
* @return The cleansed HTML String
|
||||
*/
|
||||
private String cleanseHTML(String htmlInString) {
|
||||
org.jsoup.nodes.Document doc = Jsoup.parse(htmlInString);
|
||||
// remove all 'img' tags.
|
||||
doc.select("img").stream().forEach(Node::remove);
|
||||
// remove all 'span' tags, these are often images which are ads
|
||||
doc.select("span").stream().forEach(Node::remove);
|
||||
return doc.html();
|
||||
String returnString = "";
|
||||
try {
|
||||
Source source = new Source(new StringReader(htmlInString));
|
||||
OutputDocument document = new OutputDocument(source);
|
||||
//remove background images
|
||||
source.getAllTags().stream().filter((tag) -> (tag.toString().contains("background-image"))).forEachOrdered((tag) -> {
|
||||
document.remove(tag);
|
||||
});
|
||||
//remove images
|
||||
source.getAllElements("img").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove frames
|
||||
source.getAllElements("frame").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove iframes
|
||||
source.getAllElements("iframe").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove pictures
|
||||
source.getAllElements("picture").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove svg
|
||||
source.getAllElements("svg").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove audio
|
||||
source.getAllElements("audio").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove video
|
||||
source.getAllElements("video").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove tracks
|
||||
source.getAllElements("track").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove embeded external elements
|
||||
source.getAllElements("embed").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove linked elements
|
||||
source.getAllElements("link").forEach((element) -> {
|
||||
document.remove(element.getAllTags());
|
||||
});
|
||||
//remove other URI elements such as input boxes
|
||||
List<Attribute> attributesToRemove = source.getURIAttributes();
|
||||
document.remove(attributesToRemove);
|
||||
returnString = document.toString();
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Unable to read html for cleaning out URI elements with Jericho", ex);
|
||||
}
|
||||
return returnString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the panel to reflect the current show/hide images setting.
|
||||
*/
|
||||
@Messages({
|
||||
"HtmlPanel_showImagesToggleButton_show=Show Images",
|
||||
"HtmlPanel_showImagesToggleButton_show=Download Images",
|
||||
"HtmlPanel_showImagesToggleButton_hide=Hide Images",
|
||||
"Html_text_display_error=The HTML text cannot be displayed, it may not be correctly formed HTML.",})
|
||||
private void refresh() {
|
||||
@ -164,7 +221,7 @@ final class HtmlPanel extends javax.swing.JPanel {
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(showImagesToggleButton)
|
||||
.addGap(0, 95, Short.MAX_VALUE))
|
||||
.addGap(0, 75, Short.MAX_VALUE))
|
||||
.addComponent(htmlJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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 org.sleuthkit.autopsy.texttranslation.translators;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.Response;
|
||||
import java.awt.Component;
|
||||
import java.io.IOException;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.texttranslation.TextTranslator;
|
||||
import org.sleuthkit.autopsy.texttranslation.TranslationException;
|
||||
|
||||
/**
|
||||
* Translates text by making HTTP requests to Bing Translator. This requires a
|
||||
* valid subscription key for a Microsoft Azure account.
|
||||
*/
|
||||
@ServiceProvider(service = TextTranslator.class)
|
||||
public class BingTranslator implements TextTranslator {
|
||||
|
||||
//The target language follows the to= in the string below. You can include multiple target
|
||||
//languages separated by commas. A full list of supported languages is here:
|
||||
//https://docs.microsoft.com/en-us/azure/cognitive-services/translator/language-support
|
||||
private static final String BASE_URL = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=";
|
||||
private static final int MAX_STRING_LENGTH = 5000;
|
||||
private final BingTranslatorSettingsPanel settingsPanel;
|
||||
private final BingTranslatorSettings settings = new BingTranslatorSettings();
|
||||
// This sends messages to Microsoft.
|
||||
private final OkHttpClient CLIENT = new OkHttpClient();
|
||||
|
||||
/**
|
||||
* Create a Bing Translator
|
||||
*/
|
||||
public BingTranslator() {
|
||||
settingsPanel = new BingTranslatorSettingsPanel(settings.getAuthenticationKey(), settings.getTargetLanguageCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tranlationurl for the specified language code
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param languageCode language code for language to translate to
|
||||
*
|
||||
* @return a string representation of the url to request translation from
|
||||
*/
|
||||
static String getTranlatorUrl(String languageCode) {
|
||||
return BASE_URL + languageCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an input text to the JSON format required by Bing Translator,
|
||||
* posts it to Microsoft, and returns the JSON text response.
|
||||
*
|
||||
* @param string The input text to be translated.
|
||||
*
|
||||
* @return The translation response as a JSON string
|
||||
*
|
||||
* @throws IOException if the request could not be executed due to
|
||||
* cancellation, a connectivity problem or timeout.
|
||||
*/
|
||||
public String postTranslationRequest(String string) throws IOException {
|
||||
MediaType mediaType = MediaType.parse("application/json");
|
||||
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("Text", string);
|
||||
jsonArray.add(jsonObject);
|
||||
String bodyString = jsonArray.toString();
|
||||
|
||||
RequestBody body = RequestBody.create(mediaType,
|
||||
bodyString);
|
||||
Request request = new Request.Builder()
|
||||
.url(getTranlatorUrl(settings.getTargetLanguageCode())).post(body)
|
||||
.addHeader("Ocp-Apim-Subscription-Key", settings.getAuthenticationKey())
|
||||
.addHeader("Content-type", "application/json").build();
|
||||
Response response = CLIENT.newCall(request).execute();
|
||||
return response.body().string();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translate(String string) throws TranslationException {
|
||||
if (settings.getAuthenticationKey() == null || settings.getAuthenticationKey().isEmpty()) {
|
||||
throw new TranslationException("Bing Translator has not been configured, authentication key needs to be specified");
|
||||
}
|
||||
String toTranslate = string.trim();
|
||||
//Translates some text into English, without specifying the source langauge.
|
||||
|
||||
// HTML files were producing lots of white space at the end
|
||||
//Google Translate required us to replace (\r\n|\n) with <br />
|
||||
//but Bing Translator doesn not have that requirement.
|
||||
//The free account has a maximum file size. If you have a paid account,
|
||||
//you probably still want to limit file size to prevent accidentally
|
||||
//translating very large documents.
|
||||
if (toTranslate.length() > MAX_STRING_LENGTH) {
|
||||
toTranslate = toTranslate.substring(0, MAX_STRING_LENGTH);
|
||||
}
|
||||
|
||||
try {
|
||||
String response = postTranslationRequest(toTranslate);
|
||||
return parseJSONResponse(response);
|
||||
} catch (IOException | TranslationException ex) {
|
||||
throw new TranslationException("Exception while attempting to translate using BingTranslator", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Messages({"BingTranslator.name.text=Bing Translator"})
|
||||
@Override
|
||||
public String getName() {
|
||||
return Bundle.BingTranslator_name_text();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent() {
|
||||
return settingsPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
settings.setAuthenticationKey(settingsPanel.getAuthenticationKey());
|
||||
settings.setTargetLanguageCode(settingsPanel.getTargetLanguageCode());
|
||||
settings.saveSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the response to get the translated text
|
||||
*
|
||||
* @param json_text the json which was received as a response to a
|
||||
* translation request
|
||||
*
|
||||
* @return the translated text
|
||||
*
|
||||
* @throws TranslationException
|
||||
*/
|
||||
private String parseJSONResponse(String json_text) throws TranslationException {
|
||||
/*
|
||||
* Here is an example of the text we get from Bing when input is "gato",
|
||||
* the Spanish word for cat: [ { "detectedLanguage": { "language": "es",
|
||||
* "score": 1.0 }, "translations": [ { "text": "cat", "to": "en" } ] } ]
|
||||
*/
|
||||
JsonParser parser = new JsonParser();
|
||||
try {
|
||||
JsonArray responses = parser.parse(json_text).getAsJsonArray();
|
||||
//As far as I know, there's always exactly one item in the array.
|
||||
JsonObject response0 = responses.get(0).getAsJsonObject();
|
||||
JsonArray translations = response0.getAsJsonArray("translations");
|
||||
JsonObject translation0 = translations.get(0).getAsJsonObject();
|
||||
return translation0.get("text").getAsString();
|
||||
} catch (IllegalStateException | ClassCastException | NullPointerException | IndexOutOfBoundsException e) {
|
||||
throw new TranslationException("JSON text does not match Bing Translator scheme: " + e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Autopsy
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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 org.sleuthkit.autopsy.texttranslation.translators;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
/**
|
||||
* Class to handle the settings associated with the BingTranslator
|
||||
*/
|
||||
public final class BingTranslatorSettings {
|
||||
|
||||
private static final String AUTHENTICATION_KEY = "Credentials";
|
||||
private static final String BING_TRANSLATE_NAME = "BingTranslate";
|
||||
private static final String DEFAULT_AUTHENTICATION = "";
|
||||
private static final String DEFAULT_TARGET_LANGUAGE = "en";
|
||||
private static final String TARGET_LANGUAGE_CODE_KEY = "TargetLanguageCode";
|
||||
private String authenticationKey;
|
||||
private String targetLanguageCode;
|
||||
|
||||
/**
|
||||
* Construct a new BingTranslatorSettings object
|
||||
*/
|
||||
BingTranslatorSettings() {
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Authentication key to be used for the Microsoft translation
|
||||
* service
|
||||
*
|
||||
* @return the Authentication key for the service
|
||||
*/
|
||||
String getAuthenticationKey() {
|
||||
return authenticationKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Authentication key to be used for the Microsoft translation
|
||||
* service
|
||||
*
|
||||
* @param authKey the Authentication key for the service
|
||||
*/
|
||||
void setAuthenticationKey(String authKey) {
|
||||
authenticationKey = authKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings into memory from their on disk storage
|
||||
*/
|
||||
void loadSettings() {
|
||||
if (!ModuleSettings.configExists(BING_TRANSLATE_NAME)) {
|
||||
ModuleSettings.makeConfigFile(BING_TRANSLATE_NAME);
|
||||
}
|
||||
if (ModuleSettings.settingExists(BING_TRANSLATE_NAME, AUTHENTICATION_KEY)) {
|
||||
authenticationKey = ModuleSettings.getConfigSetting(BING_TRANSLATE_NAME, AUTHENTICATION_KEY);
|
||||
}
|
||||
if (authenticationKey == null || StringUtils.isBlank(authenticationKey)) {
|
||||
authenticationKey = DEFAULT_AUTHENTICATION;
|
||||
}
|
||||
if (ModuleSettings.settingExists(BING_TRANSLATE_NAME, TARGET_LANGUAGE_CODE_KEY)) {
|
||||
targetLanguageCode = ModuleSettings.getConfigSetting(BING_TRANSLATE_NAME, TARGET_LANGUAGE_CODE_KEY);
|
||||
}
|
||||
if (targetLanguageCode == null || StringUtils.isBlank(targetLanguageCode)) {
|
||||
targetLanguageCode = DEFAULT_TARGET_LANGUAGE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target language code
|
||||
*
|
||||
* @return the code used to identify the target language
|
||||
*/
|
||||
String getTargetLanguageCode() {
|
||||
return targetLanguageCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target language code. If a blank code is specified it sets the
|
||||
* default code instead.
|
||||
*
|
||||
* @param code the target language code to set
|
||||
*/
|
||||
void setTargetLanguageCode(String code) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
targetLanguageCode = DEFAULT_TARGET_LANGUAGE;
|
||||
} else {
|
||||
targetLanguageCode = code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the setting from memory to their location on disk
|
||||
*/
|
||||
void saveSettings() {
|
||||
ModuleSettings.setConfigSetting(BING_TRANSLATE_NAME, AUTHENTICATION_KEY, authenticationKey);
|
||||
ModuleSettings.setConfigSetting(BING_TRANSLATE_NAME, TARGET_LANGUAGE_CODE_KEY, targetLanguageCode);
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="warningLabel" min="-2" pref="551" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="targetLanguageLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="targetLanguageComboBox" min="-2" pref="192" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="authenticationKeyLabel" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="authenticationKeyField" min="-2" pref="486" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="20" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="testButton" min="-2" pref="79" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="25" max="-2" attributes="0"/>
|
||||
<Component id="untranslatedLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testUntranslatedTextField" min="-2" pref="140" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="resultLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testResultValueLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="authenticationKeyField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="authenticationKeyLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="targetLanguageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="targetLanguageComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="testButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="testUntranslatedTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="untranslatedLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="resultLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="testResultValueLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="warningLabel" min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextField" name="authenticationKeyField">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.authenticationKeyField.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="warningLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="GoogleTranslatorSettingsPanel.warningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="testButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.testButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="testButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="targetLanguageLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.targetLanguageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="targetLanguageComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="0"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="targetLanguageComboBoxSelected"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<LanguageWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="testUntranslatedTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="DEFUALT_TEST_STRING" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="untranslatedLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.untranslatedLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="resultLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.resultLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="testResultValueLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.testResultValueLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="authenticationKeyLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="BingTranslatorSettingsPanel.authenticationKeyLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Autopsy
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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 org.sleuthkit.autopsy.texttranslation.translators;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/**
|
||||
* Settings panel for the BingTranslator
|
||||
*/
|
||||
public class BingTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(BingTranslatorSettingsPanel.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String GET_TARGET_LANGUAGES_URL = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation";
|
||||
private static final String DEFUALT_TEST_STRING = "traducción exitoso"; //spanish which should translate to something along the lines of "successful translation"
|
||||
private String targetLanguageCode = "";
|
||||
|
||||
/**
|
||||
* Creates new form BingTranslatorSettingsPanel
|
||||
*/
|
||||
public BingTranslatorSettingsPanel(String authenticationKey, String code) {
|
||||
initComponents();
|
||||
authenticationKeyField.setText(authenticationKey);
|
||||
authenticationKeyField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
firePropertyChange("SettingChanged", true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
firePropertyChange("SettingChanged", true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
firePropertyChange("SettingChanged", true, false);
|
||||
}
|
||||
|
||||
});
|
||||
populateComboBox();
|
||||
selectLanguageByCode(code);
|
||||
targetLanguageCode = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the target language combo box with available target languages
|
||||
*/
|
||||
@Messages({"BingTranslatorSettingsPanel.warning.targetLanguageFailure=Unable to get list of target languages or parse the result that was received"})
|
||||
private void populateComboBox() {
|
||||
Request get_request = new Request.Builder()
|
||||
.url(GET_TARGET_LANGUAGES_URL).build();
|
||||
try {
|
||||
Response response = new OkHttpClient().newCall(get_request).execute();
|
||||
JsonParser parser = new JsonParser();
|
||||
String responseBody = response.body().string();
|
||||
JsonElement elementBody = parser.parse(responseBody);
|
||||
JsonObject asObject = elementBody.getAsJsonObject();
|
||||
JsonElement translationElement = asObject.get("translation");
|
||||
JsonObject responses = translationElement.getAsJsonObject();
|
||||
responses.entrySet().forEach((entry) -> {
|
||||
targetLanguageComboBox.addItem(new LanguageWrapper(entry.getKey(), entry.getValue().getAsJsonObject().get("name").getAsString()));
|
||||
});
|
||||
targetLanguageComboBox.setEnabled(true);
|
||||
} catch (IOException | IllegalStateException | ClassCastException | NullPointerException | IndexOutOfBoundsException ex) {
|
||||
logger.log(Level.SEVERE, Bundle.BingTranslatorSettingsPanel_warning_targetLanguageFailure(), ex);
|
||||
warningLabel.setText(Bundle.BingTranslatorSettingsPanel_warning_targetLanguageFailure());
|
||||
targetLanguageComboBox.setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a language code select the corresponding language in the combo box
|
||||
* if it is present
|
||||
*
|
||||
* @param code language code such as "en" for English
|
||||
*/
|
||||
private void selectLanguageByCode(String code) {
|
||||
for (int i = 0; i < targetLanguageComboBox.getModel().getSize(); i++) {
|
||||
if (targetLanguageComboBox.getModel().getElementAt(i).getLanguageCode().equals(code)) {
|
||||
targetLanguageComboBox.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
authenticationKeyField = new javax.swing.JTextField();
|
||||
warningLabel = new javax.swing.JLabel();
|
||||
testButton = new javax.swing.JButton();
|
||||
targetLanguageLabel = new javax.swing.JLabel();
|
||||
targetLanguageComboBox = new javax.swing.JComboBox<>();
|
||||
testUntranslatedTextField = new javax.swing.JTextField();
|
||||
untranslatedLabel = new javax.swing.JLabel();
|
||||
resultLabel = new javax.swing.JLabel();
|
||||
testResultValueLabel = new javax.swing.JLabel();
|
||||
authenticationKeyLabel = new javax.swing.JLabel();
|
||||
|
||||
authenticationKeyField.setToolTipText(org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.authenticationKeyField.toolTipText")); // NOI18N
|
||||
|
||||
warningLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.warningLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(testButton, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.testButton.text")); // NOI18N
|
||||
testButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
testButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(targetLanguageLabel, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.targetLanguageLabel.text")); // NOI18N
|
||||
|
||||
targetLanguageComboBox.setEnabled(false);
|
||||
targetLanguageComboBox.addItemListener(new java.awt.event.ItemListener() {
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
targetLanguageComboBoxSelected(evt);
|
||||
}
|
||||
});
|
||||
|
||||
testUntranslatedTextField.setText(DEFUALT_TEST_STRING);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(untranslatedLabel, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.untranslatedLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(resultLabel, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.resultLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(testResultValueLabel, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.testResultValueLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(authenticationKeyLabel, org.openide.util.NbBundle.getMessage(BingTranslatorSettingsPanel.class, "BingTranslatorSettingsPanel.authenticationKeyLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(warningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 551, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(targetLanguageLabel)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(targetLanguageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 192, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(authenticationKeyLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(authenticationKeyField, javax.swing.GroupLayout.PREFERRED_SIZE, 486, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 20, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(testButton, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(25, 25, 25)
|
||||
.addComponent(untranslatedLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(testUntranslatedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(resultLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(testResultValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addContainerGap())))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(authenticationKeyField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(authenticationKeyLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(targetLanguageLabel)
|
||||
.addComponent(targetLanguageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(testButton)
|
||||
.addComponent(testUntranslatedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(untranslatedLabel)
|
||||
.addComponent(resultLabel)
|
||||
.addComponent(testResultValueLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(warningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@Messages({"BingTranslatorSettingsPanel.warning.invalidKey=Invalid translation authentication key"})
|
||||
private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testButtonActionPerformed
|
||||
if (testTranslationSetup()) {
|
||||
warningLabel.setText("");
|
||||
} else {
|
||||
warningLabel.setText(Bundle.BingTranslatorSettingsPanel_warning_invalidKey());
|
||||
}
|
||||
}//GEN-LAST:event_testButtonActionPerformed
|
||||
|
||||
private void targetLanguageComboBoxSelected(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_targetLanguageComboBoxSelected
|
||||
String selectedCode = ((LanguageWrapper) targetLanguageComboBox.getSelectedItem()).getLanguageCode();
|
||||
if (!StringUtils.isBlank(selectedCode) && !selectedCode.equals(targetLanguageCode)) {
|
||||
targetLanguageCode = selectedCode;
|
||||
firePropertyChange("SettingChanged", true, false);
|
||||
}
|
||||
}//GEN-LAST:event_targetLanguageComboBoxSelected
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTextField authenticationKeyField;
|
||||
private javax.swing.JLabel authenticationKeyLabel;
|
||||
private javax.swing.JLabel resultLabel;
|
||||
private javax.swing.JComboBox<LanguageWrapper> targetLanguageComboBox;
|
||||
private javax.swing.JLabel targetLanguageLabel;
|
||||
private javax.swing.JButton testButton;
|
||||
private javax.swing.JLabel testResultValueLabel;
|
||||
private javax.swing.JTextField testUntranslatedTextField;
|
||||
private javax.swing.JLabel untranslatedLabel;
|
||||
private javax.swing.JLabel warningLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Attempts to translate the text specified in the Untranslated field using
|
||||
* the settings currently specified but not necessarily saved
|
||||
*
|
||||
* @return true if the translation was able to be performed, false otherwise
|
||||
*
|
||||
*/
|
||||
private boolean testTranslationSetup() {
|
||||
testResultValueLabel.setText("");
|
||||
MediaType mediaType = MediaType.parse("application/json");
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("Text", testUntranslatedTextField.getText());
|
||||
jsonArray.add(jsonObject);
|
||||
String bodyString = jsonArray.toString();
|
||||
|
||||
RequestBody body = RequestBody.create(mediaType,
|
||||
bodyString);
|
||||
Request request = new Request.Builder()
|
||||
.url(BingTranslator.getTranlatorUrl(targetLanguageCode)).post(body)
|
||||
.addHeader("Ocp-Apim-Subscription-Key", authenticationKeyField.getText())
|
||||
.addHeader("Content-type", "application/json").build();
|
||||
try {
|
||||
Response response = new OkHttpClient().newCall(request).execute();
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonArray responses = parser.parse(response.body().string()).getAsJsonArray();
|
||||
//As far as I know, there's always exactly one item in the array.
|
||||
JsonObject response0 = responses.get(0).getAsJsonObject();
|
||||
JsonArray translations = response0.getAsJsonArray("translations");
|
||||
JsonObject translation0 = translations.get(0).getAsJsonObject();
|
||||
testResultValueLabel.setText(translation0.get("text").getAsString());
|
||||
return true;
|
||||
} catch (IOException | IllegalStateException | ClassCastException | NullPointerException | IndexOutOfBoundsException e) {
|
||||
logger.log(Level.WARNING, "Test of Bing Translator failed due to exception", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently set authentication key to be used for the Microsoft
|
||||
* translation service
|
||||
*
|
||||
* @return the authentication key specified in the textarea
|
||||
*/
|
||||
String getAuthenticationKey() {
|
||||
return authenticationKeyField.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently selected target language code
|
||||
*
|
||||
* @return the target language code of the language selected in the combobox
|
||||
*/
|
||||
String getTargetLanguageCode() {
|
||||
return targetLanguageCode;
|
||||
}
|
||||
}
|
@ -1,4 +1,15 @@
|
||||
GoogleTranslatorSettingsPanel.browseButton.text=Browse
|
||||
GoogleTranslatorSettingsPanel.credentialsLabel.text=Credentials:
|
||||
GoogleTranslatorSettingsPanel.credentialsLabel.text=Credentials Path:
|
||||
GoogleTranslatorSettingsPanel.warningLabel.text=
|
||||
GoogleTranslatorSettingsPanel.targetLanguageLabel.text=Target Language:
|
||||
BingTranslatorSettingsPanel.testButton.text=Test
|
||||
BingTranslatorSettingsPanel.testResultValueLabel.text=
|
||||
BingTranslatorSettingsPanel.resultLabel.text=Result:
|
||||
BingTranslatorSettingsPanel.untranslatedLabel.text=Untranslated:
|
||||
BingTranslatorSettingsPanel.targetLanguageLabel.text=Target Language:
|
||||
BingTranslatorSettingsPanel.authenticationKeyField.toolTipText=Enter the hash for the
|
||||
GoogleTranslatorSettingsPanel.testButton.text=Test
|
||||
GoogleTranslatorSettingsPanel.untranslatedLabel.text=Untranslated:
|
||||
GoogleTranslatorSettingsPanel.resultLabel.text=Result:
|
||||
GoogleTranslatorSettingsPanel.testResultValueLabel.text=
|
||||
BingTranslatorSettingsPanel.authenticationKeyLabel.text=Authentication Key:
|
||||
|
@ -1,8 +1,12 @@
|
||||
BingTranslator.name.text=Bing Translator
|
||||
BingTranslatorSettingsPanel.warning.invalidKey=Invalid translation authentication key
|
||||
BingTranslatorSettingsPanel.warning.targetLanguageFailure=Unable to get list of target languages or parse the result that was received
|
||||
GoogleTranslator.name.text=Google Translate
|
||||
GoogleTranslatorSettingsPanel.browseButton.text=Browse
|
||||
GoogleTranslatorSettingsPanel.credentialsLabel.text=Credentials:
|
||||
GoogleTranslatorSettingsPanel.credentialsLabel.text=Credentials Path:
|
||||
GoogleTranslatorSettingsPanel.errorMessage.fileNotFound=Credentials file not found, please set the location to be a valid JSON credentials file.
|
||||
GoogleTranslatorSettingsPanel.errorMessage.noFileSelected=A JSON file must be selected to provide your credentials for Google Translate.
|
||||
GoogleTranslatorSettingsPanel.errorMessage.translationFailure=Translation failure with specified credentials
|
||||
GoogleTranslatorSettingsPanel.errorMessage.unableToMakeCredentials=Unable to construct credentials object from credentials file, please set the location to be a valid JSON credentials file.
|
||||
GoogleTranslatorSettingsPanel.errorMessage.unableToReadCredentials=Unable to read credentials from credentials file, please set the location to be a valid JSON credentials file.
|
||||
GoogleTranslatorSettingsPanel.errorMessage.unknownFailureGetting=Failure getting list of supported languages with current credentials file.
|
||||
@ -11,3 +15,14 @@ GoogleTranslatorSettingsPanel.fileChooser.confirmButton=Select
|
||||
GoogleTranslatorSettingsPanel.json.description=JSON Files
|
||||
GoogleTranslatorSettingsPanel.warningLabel.text=
|
||||
GoogleTranslatorSettingsPanel.targetLanguageLabel.text=Target Language:
|
||||
BingTranslatorSettingsPanel.testButton.text=Test
|
||||
BingTranslatorSettingsPanel.testResultValueLabel.text=
|
||||
BingTranslatorSettingsPanel.resultLabel.text=Result:
|
||||
BingTranslatorSettingsPanel.untranslatedLabel.text=Untranslated:
|
||||
BingTranslatorSettingsPanel.targetLanguageLabel.text=Target Language:
|
||||
BingTranslatorSettingsPanel.authenticationKeyField.toolTipText=Enter the hash for the
|
||||
GoogleTranslatorSettingsPanel.testButton.text=Test
|
||||
GoogleTranslatorSettingsPanel.untranslatedLabel.text=Untranslated:
|
||||
GoogleTranslatorSettingsPanel.resultLabel.text=Result:
|
||||
GoogleTranslatorSettingsPanel.testResultValueLabel.text=
|
||||
BingTranslatorSettingsPanel.authenticationKeyLabel.text=Authentication Key:
|
||||
|
@ -32,8 +32,10 @@ import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||
import org.sleuthkit.autopsy.texttranslation.TextTranslator;
|
||||
import org.sleuthkit.autopsy.texttranslation.TranslationException;
|
||||
|
||||
@ -58,26 +60,33 @@ public final class GoogleTranslator implements TextTranslator {
|
||||
settingsPanel = new GoogleTranslatorSettingsPanel(settings.getCredentialPath(), settings.getTargetLanguageCode());
|
||||
loadTranslator();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if google is able to be reached
|
||||
*
|
||||
* @return true if it can be, false otherwise
|
||||
*/
|
||||
private static boolean googleIsReachable() {
|
||||
String host = "www.google.com";
|
||||
InetAddress address;
|
||||
try {
|
||||
address = InetAddress.getByName(host);
|
||||
return address.isReachable(1500);
|
||||
}catch (UnknownHostException ex) {
|
||||
} catch (UnknownHostException ex) {
|
||||
logger.log(Level.WARNING, "Unable to reach google.com due to unknown host", ex);
|
||||
return false;
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Unable to reach google.com due IOException", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String translate(String string) throws TranslationException {
|
||||
if (!googleIsReachable()) {
|
||||
throw new TranslationException("Failure translating using GoogleTranslator: Cannot connect to Google");
|
||||
}
|
||||
|
||||
|
||||
if (googleTranslate != null) {
|
||||
try {
|
||||
// Translates some text into English, without specifying the source language.
|
||||
@ -88,7 +97,7 @@ public final class GoogleTranslator implements TextTranslator {
|
||||
// We can't currently set parameters, so we are using the default behavior of
|
||||
// assuming the input is HTML. We need to replace newlines with <br> for Google to preserve them
|
||||
substring = substring.replaceAll("(\r\n|\n)", "<br />");
|
||||
|
||||
|
||||
// The API complains if the "Payload" is over 204800 bytes. I'm assuming that
|
||||
// deals with the full request. At some point, we get different errors about too
|
||||
// much text. Officially, Google says they will googleTranslate only 5k chars,
|
||||
@ -100,11 +109,15 @@ public final class GoogleTranslator implements TextTranslator {
|
||||
Translation translation
|
||||
= googleTranslate.translate(substring);
|
||||
String translatedString = translation.getTranslatedText();
|
||||
|
||||
|
||||
// put back the newlines
|
||||
translatedString = translatedString.replaceAll("<br />", "\n");
|
||||
|
||||
// With our current settings, Google Translate outputs HTML
|
||||
// so we need to undo the escape characters.
|
||||
translatedString = EscapeUtil.unEscapeHtml(translatedString);
|
||||
return translatedString;
|
||||
} catch (Throwable ex) {
|
||||
} catch (Throwable ex) {
|
||||
//Catching throwables because some of this Google Translate code throws throwables
|
||||
throw new TranslationException("Failure translating using GoogleTranslator", ex);
|
||||
}
|
||||
@ -112,7 +125,7 @@ public final class GoogleTranslator implements TextTranslator {
|
||||
throw new TranslationException("Google Translator has not been configured, credentials need to be specified");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Messages({"GoogleTranslator.name.text=Google Translate"})
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -125,16 +138,20 @@ public final class GoogleTranslator implements TextTranslator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the Google Cloud Translation service give the currently saved
|
||||
* Load the Google Cloud Translation service given the currently saved
|
||||
* settings
|
||||
*/
|
||||
private void loadTranslator() {
|
||||
InputStream credentialStream = null;
|
||||
Credentials creds = null;
|
||||
try {
|
||||
credentialStream = new FileInputStream(settings.getCredentialPath());
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.WARNING, "JSON file for GoogleTranslator credentials not found", ex);
|
||||
if (StringUtils.isBlank(settings.getCredentialPath())) {
|
||||
logger.log(Level.INFO, "No credentials file has been provided for Google Translator");
|
||||
} else {
|
||||
try {
|
||||
credentialStream = new FileInputStream(settings.getCredentialPath());
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.WARNING, "JSON file for GoogleTranslator credentials not found", ex);
|
||||
}
|
||||
}
|
||||
if (credentialStream != null) {
|
||||
try {
|
||||
|
@ -92,12 +92,14 @@ public final class GoogleTranslatorSettings {
|
||||
}
|
||||
if (ModuleSettings.settingExists(GOOGLE_TRANSLATE_NAME, TARGET_LANGUAGE_CODE_KEY)) {
|
||||
targetLanguageCode = ModuleSettings.getConfigSetting(GOOGLE_TRANSLATE_NAME, TARGET_LANGUAGE_CODE_KEY);
|
||||
} else {
|
||||
}
|
||||
if (targetLanguageCode == null || StringUtils.isBlank(targetLanguageCode)) {
|
||||
targetLanguageCode = DEFAULT_TARGET_LANGUAGE;
|
||||
}
|
||||
if (ModuleSettings.settingExists(GOOGLE_TRANSLATE_NAME, CREDENTIAL_PATH_KEY)) {
|
||||
credentialPath = ModuleSettings.getConfigSetting(GOOGLE_TRANSLATE_NAME, CREDENTIAL_PATH_KEY);
|
||||
} else {
|
||||
}
|
||||
if (credentialPath == null) {
|
||||
credentialPath = DEFAULT_CREDENTIAL_PATH;
|
||||
}
|
||||
}
|
||||
|
@ -16,13 +16,9 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="warningLabel" min="-2" pref="551" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="credentialsLabel" max="32767" attributes="0"/>
|
||||
@ -31,7 +27,7 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="credentialsPathField" pref="443" max="32767" attributes="0"/>
|
||||
<Component id="credentialsPathField" pref="451" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
|
||||
@ -42,6 +38,18 @@
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="warningLabel" min="-2" pref="551" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="testButton" min="-2" pref="83" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="untranslatedLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testUntranslatedTextField" min="-2" pref="140" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="resultLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testResultValueLabel" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -60,9 +68,16 @@
|
||||
<Component id="targetLanguageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="targetLanguageComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace pref="15" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="testButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="testUntranslatedTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="untranslatedLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="resultLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="testResultValueLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="warningLabel" min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="23" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -98,7 +113,7 @@
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<org.sleuthkit.autopsy.texttranslation.translators.GoogleLanguageWrapper>"/>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<org.sleuthkit.autopsy.texttranslation.translators.LanguageWrapper>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="targetLanguageLabel">
|
||||
@ -118,5 +133,47 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="testResultValueLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="GoogleTranslatorSettingsPanel.testResultValueLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="resultLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="GoogleTranslatorSettingsPanel.resultLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="untranslatedLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="GoogleTranslatorSettingsPanel.untranslatedLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="testUntranslatedTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="DEFUALT_TEST_STRING" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="testButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/texttranslation/translators/Bundle.properties" key="GoogleTranslatorSettingsPanel.testButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="testButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.texttranslation.translators;
|
||||
import com.google.auth.Credentials;
|
||||
import com.google.auth.oauth2.ServiceAccountCredentials;
|
||||
import com.google.cloud.translate.Language;
|
||||
import com.google.cloud.translate.Translate;
|
||||
import com.google.cloud.translate.TranslateOptions;
|
||||
import com.google.cloud.translate.Translation;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -44,6 +46,7 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(GoogleTranslatorSettingsPanel.class.getName());
|
||||
private static final String JSON_EXTENSION = "json";
|
||||
private static final String DEFUALT_TEST_STRING = "traducción exitoso"; //spanish which should translate to something along the lines of "successful translation"
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final ItemListener listener = new ComboBoxSelectionListener();
|
||||
private String targetLanguageCode = "";
|
||||
@ -60,16 +63,15 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
|
||||
/**
|
||||
* Private method to make a temporary translation service given the current
|
||||
* settings and use it to retrieve the available target languages for
|
||||
* population of combobox with target language with unsaved settings.
|
||||
* settings with unsaved settings.
|
||||
*
|
||||
* @return A list of Languages
|
||||
* @return A Translate object which is the translation service
|
||||
*/
|
||||
@Messages({"GoogleTranslatorSettingsPanel.errorMessage.fileNotFound=Credentials file not found, please set the location to be a valid JSON credentials file.",
|
||||
"GoogleTranslatorSettingsPanel.errorMessage.unableToReadCredentials=Unable to read credentials from credentials file, please set the location to be a valid JSON credentials file.",
|
||||
"GoogleTranslatorSettingsPanel.errorMessage.unableToMakeCredentials=Unable to construct credentials object from credentials file, please set the location to be a valid JSON credentials file.",
|
||||
"GoogleTranslatorSettingsPanel.errorMessage.unknownFailureGetting=Failure getting list of supported languages with current credentials file.",})
|
||||
private List<Language> getListOfTargetLanguages() {
|
||||
private Translate getTemporaryTranslationService() {
|
||||
//This method also has the side effect of more or less validating the JSON file which was selected as it is necessary to get the list of target languages
|
||||
try {
|
||||
InputStream credentialStream;
|
||||
@ -77,31 +79,31 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
credentialStream = new FileInputStream(credentialsPathField.getText());
|
||||
} catch (FileNotFoundException ignored) {
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_fileNotFound());
|
||||
return new ArrayList<>();
|
||||
return null;
|
||||
}
|
||||
Credentials creds;
|
||||
try {
|
||||
creds = ServiceAccountCredentials.fromStream(credentialStream);
|
||||
} catch (IOException ignored) {
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_unableToMakeCredentials());
|
||||
return new ArrayList<>();
|
||||
return null;
|
||||
}
|
||||
if (creds == null) {
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_unableToReadCredentials());
|
||||
logger.log(Level.WARNING, "Credentials were not successfully made, no translations will be available from the GoogleTranslator");
|
||||
return new ArrayList<>();
|
||||
return null;
|
||||
} else {
|
||||
TranslateOptions.Builder builder = TranslateOptions.newBuilder();
|
||||
builder.setCredentials(creds);
|
||||
builder.setTargetLanguage(targetLanguageCode); //localize the list to the currently selected target language
|
||||
warningLabel.setText(""); //clear any previous warning text
|
||||
return builder.build().getService().listSupportedLanguages();
|
||||
return builder.build().getService();
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
//Catching throwables because some of this Google Translate code throws throwables
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_unknownFailureGetting());
|
||||
logger.log(Level.WARNING, "Throwable caught while getting list of supported languages", throwable);
|
||||
return new ArrayList<>();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,29 +116,51 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
targetLanguageComboBox.removeItemListener(listener);
|
||||
try {
|
||||
if (!StringUtils.isBlank(credentialsPathField.getText())) {
|
||||
List<Language> listSupportedLanguages = getListOfTargetLanguages();
|
||||
List<Language> listSupportedLanguages;
|
||||
Translate tempService = getTemporaryTranslationService();
|
||||
if (tempService != null) {
|
||||
listSupportedLanguages = tempService.listSupportedLanguages();
|
||||
} else {
|
||||
listSupportedLanguages = new ArrayList<>();
|
||||
}
|
||||
targetLanguageComboBox.removeAllItems();
|
||||
if (!listSupportedLanguages.isEmpty()) {
|
||||
listSupportedLanguages.forEach((lang) -> {
|
||||
targetLanguageComboBox.addItem(new GoogleLanguageWrapper(lang));
|
||||
targetLanguageComboBox.addItem(new LanguageWrapper(lang));
|
||||
});
|
||||
selectLanguageByCode(targetLanguageCode);
|
||||
targetLanguageComboBox.addItemListener(listener);
|
||||
targetLanguageComboBox.setEnabled(true);
|
||||
enableControls(true);
|
||||
|
||||
} else {
|
||||
targetLanguageComboBox.setEnabled(false);
|
||||
enableControls(false);
|
||||
}
|
||||
} else {
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_noFileSelected());
|
||||
targetLanguageComboBox.setEnabled(false);
|
||||
enableControls(false);
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_unknownFailurePopulating());
|
||||
logger.log(Level.WARNING, "Throwable caught while populating list of supported languages", throwable);
|
||||
targetLanguageComboBox.setEnabled(false);
|
||||
enableControls(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to enable/disable all controls which are dependent on valid
|
||||
* credentials having been provided
|
||||
*
|
||||
* @param enabled true to enable the controls, false to disable them
|
||||
*/
|
||||
private void enableControls(boolean enabled) {
|
||||
targetLanguageComboBox.setEnabled(enabled);
|
||||
testButton.setEnabled(enabled);
|
||||
testResultValueLabel.setEnabled(enabled);
|
||||
testUntranslatedTextField.setEnabled(enabled);
|
||||
untranslatedLabel.setEnabled(enabled);
|
||||
resultLabel.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a language code select the corresponding language in the combo box
|
||||
* if it is present
|
||||
@ -145,7 +169,7 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
*/
|
||||
private void selectLanguageByCode(String code) {
|
||||
for (int i = 0; i < targetLanguageComboBox.getModel().getSize(); i++) {
|
||||
if (targetLanguageComboBox.getItemAt(i).getLanguage().getCode().equals(code)) {
|
||||
if (targetLanguageComboBox.getItemAt(i).getLanguageCode().equals(code)) {
|
||||
targetLanguageComboBox.setSelectedIndex(i);
|
||||
return;
|
||||
}
|
||||
@ -167,6 +191,11 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
targetLanguageComboBox = new javax.swing.JComboBox<>();
|
||||
targetLanguageLabel = new javax.swing.JLabel();
|
||||
warningLabel = new javax.swing.JLabel();
|
||||
testResultValueLabel = new javax.swing.JLabel();
|
||||
resultLabel = new javax.swing.JLabel();
|
||||
untranslatedLabel = new javax.swing.JLabel();
|
||||
testUntranslatedTextField = new javax.swing.JTextField();
|
||||
testButton = new javax.swing.JButton();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(credentialsLabel, org.openide.util.NbBundle.getMessage(GoogleTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.credentialsLabel.text")); // NOI18N
|
||||
|
||||
@ -186,6 +215,25 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
warningLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(GoogleTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.warningLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(testResultValueLabel, org.openide.util.NbBundle.getMessage(GoogleTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.testResultValueLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(resultLabel, org.openide.util.NbBundle.getMessage(GoogleTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.resultLabel.text")); // NOI18N
|
||||
resultLabel.setEnabled(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(untranslatedLabel, org.openide.util.NbBundle.getMessage(GoogleTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.untranslatedLabel.text")); // NOI18N
|
||||
untranslatedLabel.setEnabled(false);
|
||||
|
||||
testUntranslatedTextField.setText(DEFUALT_TEST_STRING);
|
||||
testUntranslatedTextField.setEnabled(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(testButton, org.openide.util.NbBundle.getMessage(GoogleTranslatorSettingsPanel.class, "GoogleTranslatorSettingsPanel.testButton.text")); // NOI18N
|
||||
testButton.setEnabled(false);
|
||||
testButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
testButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -193,9 +241,6 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(warningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 551, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(credentialsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
@ -203,13 +248,24 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(credentialsPathField, javax.swing.GroupLayout.DEFAULT_SIZE, 443, Short.MAX_VALUE)
|
||||
.addComponent(credentialsPathField, javax.swing.GroupLayout.DEFAULT_SIZE, 451, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(browseButton)
|
||||
.addGap(14, 14, 14))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(targetLanguageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 317, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))))))
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
.addComponent(warningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 551, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(testButton, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(untranslatedLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(testUntranslatedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(resultLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(testResultValueLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -223,9 +279,15 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(targetLanguageLabel)
|
||||
.addComponent(targetLanguageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(warningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(23, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(testButton)
|
||||
.addComponent(testUntranslatedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(untranslatedLabel)
|
||||
.addComponent(resultLabel)
|
||||
.addComponent(testResultValueLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(warningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -249,12 +311,33 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}//GEN-LAST:event_browseButtonActionPerformed
|
||||
|
||||
@Messages({"GoogleTranslatorSettingsPanel.errorMessage.translationFailure=Translation failure with specified credentials"})
|
||||
private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testButtonActionPerformed
|
||||
testResultValueLabel.setText("");
|
||||
Translate tempTranslate = getTemporaryTranslationService();
|
||||
if (tempTranslate != null) {
|
||||
try {
|
||||
Translation translation = tempTranslate.translate(testUntranslatedTextField.getText());
|
||||
testResultValueLabel.setText(translation.getTranslatedText());
|
||||
warningLabel.setText("");
|
||||
} catch (Exception ex) {
|
||||
warningLabel.setText(Bundle.GoogleTranslatorSettingsPanel_errorMessage_translationFailure());
|
||||
logger.log(Level.WARNING, Bundle.GoogleTranslatorSettingsPanel_errorMessage_translationFailure(), ex);
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_testButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.JLabel credentialsLabel;
|
||||
private javax.swing.JTextField credentialsPathField;
|
||||
private javax.swing.JComboBox<org.sleuthkit.autopsy.texttranslation.translators.GoogleLanguageWrapper> targetLanguageComboBox;
|
||||
private javax.swing.JLabel resultLabel;
|
||||
private javax.swing.JComboBox<org.sleuthkit.autopsy.texttranslation.translators.LanguageWrapper> targetLanguageComboBox;
|
||||
private javax.swing.JLabel targetLanguageLabel;
|
||||
private javax.swing.JButton testButton;
|
||||
private javax.swing.JLabel testResultValueLabel;
|
||||
private javax.swing.JTextField testUntranslatedTextField;
|
||||
private javax.swing.JLabel untranslatedLabel;
|
||||
private javax.swing.JLabel warningLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
@ -284,7 +367,7 @@ public class GoogleTranslatorSettingsPanel extends javax.swing.JPanel {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
String selectedCode = ((GoogleLanguageWrapper) targetLanguageComboBox.getSelectedItem()).getLanguage().getCode();
|
||||
String selectedCode = ((LanguageWrapper) targetLanguageComboBox.getSelectedItem()).getLanguageCode();
|
||||
if (!StringUtils.isBlank(selectedCode) && !selectedCode.equals(targetLanguageCode)) {
|
||||
targetLanguageCode = selectedCode;
|
||||
populateTargetLanguageComboBox();
|
||||
|
@ -21,19 +21,33 @@ package org.sleuthkit.autopsy.texttranslation.translators;
|
||||
import com.google.cloud.translate.Language;
|
||||
|
||||
/**
|
||||
* Wrapper for the Language class
|
||||
* Wrapper for Language definitions used by translators
|
||||
*/
|
||||
class GoogleLanguageWrapper {
|
||||
class LanguageWrapper {
|
||||
|
||||
private final Language language;
|
||||
private final String languageCode;
|
||||
private final String languageDisplayName;
|
||||
|
||||
/**
|
||||
* Create a new GoogleLanguageWrapper
|
||||
* Create a new LanguageWrapper to wrap the google language object
|
||||
*
|
||||
* @param lang the Language object to wrap
|
||||
*/
|
||||
GoogleLanguageWrapper(Language lang) {
|
||||
language = lang;
|
||||
LanguageWrapper(Language language) {
|
||||
languageCode = language.getCode();
|
||||
languageDisplayName = language.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new LanguageWrapper to wrap json elements that identify a
|
||||
* language for microsofts translation service
|
||||
*
|
||||
* @param code the code which uniquely identifies a language
|
||||
* @param name the name of the language
|
||||
*/
|
||||
LanguageWrapper(String code, String name) {
|
||||
languageCode = code;
|
||||
languageDisplayName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,14 +55,14 @@ class GoogleLanguageWrapper {
|
||||
*
|
||||
* @return the wrapped Language
|
||||
*/
|
||||
Language getLanguage() {
|
||||
return language;
|
||||
String getLanguageCode() {
|
||||
return languageCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
//toString overridden so that the jComboBox in the GoogleTranslatorSettingsPanel will display the name of the language
|
||||
return language.getName();
|
||||
//toString overridden so that the jComboBox in the TranslatorSettingsPanels will display the name of the language
|
||||
return languageDisplayName;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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 org.sleuthkit.autopsy.texttranslation.translators;
|
||||
|
||||
//import java.io.IOException;
|
||||
//import org.junit.After;
|
||||
//import org.junit.AfterClass;
|
||||
//import org.junit.Before;
|
||||
//import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
//import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests for the BingTranslator translation service, these tests have been
|
||||
* commented out because they require credentials to perform
|
||||
*/
|
||||
public class BingTranslatorTest {
|
||||
|
||||
@Test
|
||||
public void testTranslate() {
|
||||
// BingTranslator translator = new BingTranslator();
|
||||
// String input = "gato";
|
||||
// String expectedTranslation = "cat";
|
||||
// runTest(translator, input, expectedTranslation);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testQuickStartSentence() throws Exception {
|
||||
// BingTranslator translator = new BingTranslator();
|
||||
// String input = "Willkommen bei Microsoft Translator. Raten Sie mal, wie viele Sprachen ich spreche.";
|
||||
// String expectedTranslation = "Welcome to Microsoft Translator. Guess how many languages I speak.";
|
||||
// runTest(translator, input, expectedTranslation);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testCharacterEscapes() throws Exception {
|
||||
// BingTranslator translator = new BingTranslator();
|
||||
// String input = "\"gato\"";;
|
||||
// String expectedTranslation = "Cat";
|
||||
// runTest(translator, input, expectedTranslation);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testLineBreaks() throws Exception {
|
||||
// BingTranslator translator = new BingTranslator();
|
||||
// String input = "gato\nperro";;
|
||||
// String expectedTranslation = "cat\nDog";
|
||||
// runTest(translator, input, expectedTranslation);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test whether translator throws an error. This should not be part of our
|
||||
// * regular testing, because we are limited to only 2MB of free translations
|
||||
// * ever.
|
||||
// * @param translator A BingTranslator
|
||||
// * @param input Text to translate
|
||||
// * @param expectedTranslation Not used unless you uncomment those lines.
|
||||
// */
|
||||
// public void runTest(BingTranslator translator, String input, String expectedTranslation) {
|
||||
// String translation;
|
||||
// try {
|
||||
// translation = translator.translate(input);
|
||||
// }
|
||||
// catch (Throwable e) {
|
||||
// fail("Bing translation produced an exception: " + e.getMessage());
|
||||
// return;
|
||||
// };
|
||||
//
|
||||
// /*
|
||||
// //It's unrealistic to expect the same answer every time, but sometimes
|
||||
// //it's helpful to have this in your debug process.
|
||||
// System.out.println(translation);
|
||||
// assertEquals(expectedTranslation, translation);
|
||||
// */
|
||||
// }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user