mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 13:42:06 +00:00
Merge remote-tracking branch 'origin/GT-3648-dragonmacher-csv-escape-quotes'
This commit is contained in:
commit
e135e77f1f
@ -35,18 +35,25 @@ public final class GTableToCSV {
|
||||
final static String TITLE = "Export to CSV";
|
||||
|
||||
public final static void writeCSV(File file, GTable table) {
|
||||
ConvertTask task = new ConvertTask(file, table, table.getModel());
|
||||
ConvertTask task = new ConvertTask(file, table);
|
||||
new TaskLauncher(task, table, 0);
|
||||
}
|
||||
|
||||
public final static void writeCSVUsingColunns(File file, GTable table,
|
||||
List<Integer> selectedColumns) {
|
||||
ConvertTask task = new ConvertTask(file, table, table.getModel(), selectedColumns);
|
||||
ConvertTask task = new ConvertTask(file, table, selectedColumns);
|
||||
new TaskLauncher(task, table, 0);
|
||||
}
|
||||
|
||||
private final static void writeCSV(File file, GTable table, GTableColumnModel columnModel,
|
||||
TableModel model, List<Integer> columns, TaskMonitor monitor) throws IOException {
|
||||
final static void writeCSV(File file, GTable table,
|
||||
List<Integer> columns, TaskMonitor monitor) throws IOException {
|
||||
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
writeCSV(writer, table, columns, monitor);
|
||||
}
|
||||
|
||||
final static void writeCSV(PrintWriter writer, GTable table,
|
||||
List<Integer> columns, TaskMonitor monitor) {
|
||||
|
||||
List<TableColumn> tableColumns = null;
|
||||
if (columns.isEmpty()) {
|
||||
@ -56,7 +63,7 @@ public final class GTableToCSV {
|
||||
tableColumns = getTableColumnsByIndex(table, columns);
|
||||
}
|
||||
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
TableModel model = table.getModel();
|
||||
try {
|
||||
writeColumnNames(writer, tableColumns, model, monitor);
|
||||
writeNewLine(writer);
|
||||
@ -142,7 +149,8 @@ public final class GTableToCSV {
|
||||
final int column) {
|
||||
final String[] result = new String[1];
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(() -> result[0] = getTableCellValue(table, model, row, column));
|
||||
SwingUtilities
|
||||
.invokeAndWait(() -> result[0] = getTableCellValue(table, model, row, column));
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
return null;
|
||||
@ -301,14 +309,19 @@ public final class GTableToCSV {
|
||||
* <p>
|
||||
* Note: when importing into Excel, the quotes are stripped off.
|
||||
*/
|
||||
private final static void writeField(PrintWriter writer, String fieldValue, TaskMonitor monitor) {
|
||||
private final static void writeField(PrintWriter writer, String fieldValue,
|
||||
TaskMonitor monitor) {
|
||||
writer.print("\"");
|
||||
for (int i = 0; i < fieldValue.length(); ++i) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (fieldValue.charAt(i) == '"') {//embedded separator
|
||||
writer.print("\"");
|
||||
writer.print("\\\"");
|
||||
}
|
||||
else if (fieldValue.charAt(i) == ',') {
|
||||
writer.print("\\,");
|
||||
}
|
||||
else {
|
||||
writer.print(fieldValue.charAt(i));
|
||||
@ -319,36 +332,30 @@ public final class GTableToCSV {
|
||||
|
||||
private static class ConvertTask extends Task {
|
||||
private final GTable table;
|
||||
private TableModel model;
|
||||
private GTableColumnModel columnModel;
|
||||
|
||||
private File file;
|
||||
private List<Integer> columns = new ArrayList<Integer>();
|
||||
|
||||
ConvertTask(File file, GTable table, TableModel model) {
|
||||
ConvertTask(File file, GTable table) {
|
||||
super(GTableToCSV.TITLE, true, true, true);
|
||||
this.file = file;
|
||||
this.table = table;
|
||||
this.columnModel = (GTableColumnModel) table.getColumnModel();
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
ConvertTask(File file, GTable table, TableModel model, List<Integer> columns) {
|
||||
ConvertTask(File file, GTable table, List<Integer> columns) {
|
||||
super(GTableToCSV.TITLE, true, true, true);
|
||||
this.file = file;
|
||||
this.table = table;
|
||||
this.columns = columns;
|
||||
this.columnModel = (GTableColumnModel) table.getColumnModel();
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) {
|
||||
try {
|
||||
GTableToCSV.writeCSV(file, table, columnModel, model, columns, monitor);
|
||||
GTableToCSV.writeCSV(file, table, columns, monitor);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(GTable.class.getName(), e.getMessage());
|
||||
Msg.error(GTableToCSV.class.getName(), e.getMessage());
|
||||
}
|
||||
|
||||
DockingWindowManager manager = DockingWindowManager.getInstance(table);
|
||||
|
@ -0,0 +1,145 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package docking.widgets.table;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class GTableCSVTest {
|
||||
|
||||
@Test
|
||||
public void testCSV_QuotesGetEscaped() {
|
||||
|
||||
AnyObjectTableModel<CSVRowObject> model =
|
||||
new AnyObjectTableModel<>("MyModel", CSVRowObject.class,
|
||||
"getName", "getDescription", "getNumber");
|
||||
|
||||
//@formatter:off
|
||||
List<CSVRowObject> data = Arrays.asList(
|
||||
new CSVRowObject("Bob", "Bobby", 11),
|
||||
new CSVRowObject("Joan", "Joan has \"quoted\" text", 0),
|
||||
new CSVRowObject("Sam", "\"Sam has a single quote text", 23),
|
||||
new CSVRowObject("Time", "Tim is last", 33)
|
||||
);
|
||||
//@formatter:on
|
||||
model.setModelData(data);
|
||||
|
||||
GTable table = new GTable(model);
|
||||
List<Integer> columns = new ArrayList<>();
|
||||
|
||||
PrintWriterSpy writer = new PrintWriterSpy();
|
||||
GTableToCSV.writeCSV(writer, table, columns, TaskMonitor.DUMMY);
|
||||
|
||||
assertRowValues(data, writer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCSV_CommasGetEscaped() {
|
||||
|
||||
AnyObjectTableModel<CSVRowObject> model =
|
||||
new AnyObjectTableModel<>("MyModel", CSVRowObject.class,
|
||||
"getName", "getDescription", "getNumber");
|
||||
|
||||
//@formatter:off
|
||||
List<CSVRowObject> data = Arrays.asList(
|
||||
new CSVRowObject("Bob", "Bobby", 11),
|
||||
new CSVRowObject("Joan", "Joan has a comma, in her text", 0),
|
||||
new CSVRowObject("Sam", ",Sam has a leading comma", 23),
|
||||
new CSVRowObject("Time", "Tim is last", 33)
|
||||
);
|
||||
//@formatter:on
|
||||
model.setModelData(data);
|
||||
|
||||
GTable table = new GTable(model);
|
||||
List<Integer> columns = new ArrayList<>();
|
||||
|
||||
PrintWriterSpy writer = new PrintWriterSpy();
|
||||
GTableToCSV.writeCSV(writer, table, columns, TaskMonitor.DUMMY);
|
||||
|
||||
assertRowValues(data, writer);
|
||||
}
|
||||
|
||||
private void assertRowValues(List<CSVRowObject> data, PrintWriterSpy writer) {
|
||||
|
||||
String results = writer.toString();
|
||||
String[] lines = results.split("\n");
|
||||
for (int i = 1; i < lines.length; i++) {
|
||||
int index = i - 1; // the first line is the header
|
||||
CSVRowObject row = data.get(index);
|
||||
String line = lines[i];
|
||||
String[] columns = line.split("(?<!\\\\),");
|
||||
|
||||
String name = columns[0].replaceAll("\\\\,", ",");
|
||||
name = name.replaceAll("\\\\\"", "\"");
|
||||
assertEquals("\"" + row.getName() + "\"", name);
|
||||
|
||||
String description = columns[1].replaceAll("\\\\,", ",");
|
||||
description = description.replaceAll("\\\\\"", "\"");
|
||||
assertEquals("\"" + row.getDescription() + "\"", description);
|
||||
|
||||
String number = columns[2].replaceAll("\\\\,", ",");
|
||||
number = number.replaceAll("\\\\\"", "\"");
|
||||
assertEquals("\"" + row.getNumber() + "\"", number);
|
||||
}
|
||||
}
|
||||
|
||||
class CSVRowObject {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private int number;
|
||||
|
||||
CSVRowObject(String name, String description, int number) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
private class PrintWriterSpy extends PrintWriter {
|
||||
|
||||
private StringWriter stringWriter;
|
||||
|
||||
PrintWriterSpy() {
|
||||
super(new StringWriter(), true);
|
||||
stringWriter = ((StringWriter) out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringWriter.toString();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user