Skip to content

Commit

Permalink
Prepared fix for issue #980.
Browse files Browse the repository at this point in the history
  • Loading branch information
nilsschmidt1337 committed Sep 7, 2023
1 parent b52b752 commit dc9e2e4
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,7 @@ public void mouseDown(MouseEvent e) {
int toLine = s2 > -1 ? st.getLineAtOffset(s2) : s2 * -1;
fromLine++;
toLine++;
DataMetacommandExporter.export(fromLine, toLine, df);
DataMetacommandExporter.export(fromLine, toLine, df, tabState.window[0].getShell());
});

widgetUtil(mntmDrawSelectionPtr[0]).addSelectionListener(e -> {
Expand Down
78 changes: 76 additions & 2 deletions src/org/nschmidt/ldparteditor/data/GDataBinary.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
*/
public final class GDataBinary extends GData {

/** 4 chars = 3 bytes => 64.000 chars = 48.000 bytes */
private static final int MAX_LENGTH_OF_BASE64_STRING = 64_000;

private final DatFile df;

public GDataBinary(String text, DatFile df, GData1 parent) {
Expand All @@ -43,7 +46,7 @@ public byte[] loadBinary() {
final StringBuilder base64Sb = new StringBuilder();

GData gd = this.next;
while (gd != null) {
while (gd != null && base64Sb.length() <= MAX_LENGTH_OF_BASE64_STRING) {
final String line = whitespace.matcher(gd.toString()).replaceAll(" ").trim(); //$NON-NLS-1$
if (line.startsWith("0 !: ")) { //$NON-NLS-1$
final String encodedSubstring = line.substring(5);
Expand All @@ -58,13 +61,84 @@ public byte[] loadBinary() {
final String encodedString = base64Sb.toString();

try {
return Base64.getDecoder().decode(encodedString);
// Don't allow more than a constant amount of chars
if (encodedString.length() <= MAX_LENGTH_OF_BASE64_STRING) {
final byte[] preFilteredData = Base64.getDecoder().decode(encodedString);
return filterMaliciousContent(preFilteredData);
}
} catch (IllegalArgumentException iae) {
NLogger.debug(GDataBinary.class, iae);
}

return new byte[0];
}

/**
* Malicious content can be attached to the end of the file after the IEND tag which typically marks the
* end of the image file. We don't want to read or store this!
* @param data the byte array to filter
* @return the filtered array
*/
private byte[] filterMaliciousContent(byte[] data) {
int state = 0;
int length = 0;
int dataLength = 0;
for (byte b : data) {
if (dataLength > 0) {
break;
}

// Encoders and decoders must treat the codes as fixed binary values,
// not character strings.
switch (b) {
case 73: { // I
if (state == 0) {
state = 1;
} else {
state = 0;
}

break;
}
case 69: { // E
if (state == 1) {
state = 2;
} else {
state = 0;
}

break;
}
case 78: { // N
if (state == 2) {
state = 3;
} else {
state = 0;
}

break;
}
case 68: { // D
if (state == 3) {
// + 4 Byte CRC for IEND
dataLength = Math.min(length + 5, data.length);
} else {
state = 0;
}

break;
}
default:
// Do nothing.
}

length++;
}

final byte[] resultData = new byte[dataLength];
System.arraycopy(data, 0, resultData, 0, dataLength);
return resultData;
}

@Override
public void drawGL20(Composite3D c3d) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package org.nschmidt.ldparteditor.helper.compositetext;

/* MIT - License
Copyright (c) 2012 - this year, Nils Schmidt
Expand All @@ -15,11 +13,31 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
package org.nschmidt.ldparteditor.helper.compositetext;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

import org.nschmidt.ldparteditor.data.DatFile;
import org.nschmidt.ldparteditor.data.GData;
import org.nschmidt.ldparteditor.data.GDataBinary;
import org.nschmidt.ldparteditor.helper.math.HashBiMap;
import org.nschmidt.ldparteditor.i18n.I18n;
import org.nschmidt.ldparteditor.logger.NLogger;
import org.nschmidt.ldparteditor.project.Project;

import de.matthiasmann.twl.util.PNGDecoder;
import de.matthiasmann.twl.util.PNGDecoder.Format;

/**
* Exports !DATA meta-commands to a file (PNG only)
Expand All @@ -36,15 +54,73 @@ public enum DataMetacommandExporter {
* end line number to export
* @param datFile
*/
public static void export(int lineStart, int lineEnd, DatFile datFile) {
public static void export(int lineStart, int lineEnd, DatFile datFile, Shell shell) {
HashBiMap<Integer, GData> dpl = datFile.getDrawPerLineNoClone();
lineEnd++;

boolean noSelection = true;
for (int line = lineStart; line < lineEnd; line++) {
final GData data = dpl.getValue(line);
if (data instanceof GDataBinary gd) {
// TODO Needs implementation!
System.out.println(data);
if (data instanceof GDataBinary dataMetaTag) {
final byte[] binary = dataMetaTag.loadBinary();
if (binary.length > 0) {
try (InputStream in = new ByteArrayInputStream(binary)) {
// Link the PNG decoder to this stream
final PNGDecoder decoder = new PNGDecoder(in);

// Get the width and height of the texture
int width = decoder.getWidth();
int height = decoder.getHeight();

// Decode the PNG file in a ByteBuffer
ByteBuffer buf = ByteBuffer.allocateDirect(4 * width * height);
decoder.decode(buf, width * 4, Format.RGBA);

// Now try to save the image
FileDialog fd = new FileDialog(shell, SWT.SAVE);
fd.setText(I18n.E3D_SAVE_AS);
fd.setOverwrite(true);

File f = new File(datFile.getNewName()).getParentFile();
if (f != null && f.exists()) {
fd.setFilterPath(f.getAbsolutePath());
} else {
fd.setFilterPath(Project.getLastVisitedPath());
}

final String filename = dataMetaTag.toString().substring(8);
fd.setFileName(filename);

String[] filterExt = { "*.png", "*.*" }; //$NON-NLS-1$ //$NON-NLS-2$
fd.setFilterExtensions(filterExt);
String[] filterNames = {I18n.E3D_PORTABLE_NETWORK_GRAPHICS, I18n.E3D_ALL_FILES};
fd.setFilterNames(filterNames);

String selected = fd.open();

if (selected != null) {
try (OutputStream fos = new FileOutputStream(selected)) {
fos.write(binary);
}
}

noSelection = false;
} catch (IOException e) {
NLogger.debug(DataMetacommandExporter.class, e);
MessageBox messageBoxError = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
messageBoxError.setText(I18n.DIALOG_ERROR);
messageBoxError.setMessage(I18n.EDITORTEXT_DATA_ERROR_EXPORT);
messageBoxError.open();
}
}
}
}

if (noSelection) {
MessageBox messageBoxError = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK);
messageBoxError.setText(I18n.DIALOG_WARNING);
messageBoxError.setMessage(I18n.EDITORTEXT_DATA_NO_SELECTION);
messageBoxError.open();
}
}
}
3 changes: 2 additions & 1 deletion src/org/nschmidt/ldparteditor/i18n/I18n.java
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,8 @@ private static void adjust() { // Calculate line offset
public static final String EDITORTEXT_COMMENT = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_COMPILE = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_COMPILE_CSG = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_DATA_ERROR = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_DATA_ERROR_EXPORT = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_DATA_ERROR_IMPORT = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_DATA_EXPORT = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_DATA_IMPORT = EDITORTEXT.getString(getProperty());
public static final String EDITORTEXT_DATA_NO_SELECTION = EDITORTEXT.getString(getProperty());
Expand Down
5 changes: 3 additions & 2 deletions src/org/nschmidt/ldparteditor/i18n/TextEditor.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ COLOUR_2 = Colour [{0}]
COMMENT = Toggle Comment
COMPILE = Update/Compile linked Subfile Data
COMPILE_CSG = Optimize CSG Triangulation...\n(you can skip this)
DATA_ERROR = The file was not a valid PNG image.
DATA_ERROR_EXPORT = A valid PNG image could not be created.
DATA_ERROR_IMPORT = A valid !DATA tag could not be created.
DATA_EXPORT = Export !DATA as PNG-Image (secure)
DATA_IMPORT = Import PNG-Image as !DATA
DATA_NO_SELECTION = No single !DATA line was selected. Nothing to export.
DATA_NO_SELECTION = No single valid !DATA line was selected or the selected data size was too big (limit: 45KB). Nothing to export.
DRAW_SELECTION = Draw Selection
DRAW_UNTIL_SELECTION = Draw Until Selection
DUPLICATE = duplicate
Expand Down

0 comments on commit dc9e2e4

Please sign in to comment.