From 95d56fa3a781e7b4bb24a72638131e8e5b0526f7 Mon Sep 17 00:00:00 2001 From: Meet Boghani Date: Wed, 2 Oct 2024 22:25:26 -0400 Subject: [PATCH 01/17] Fix: Refactored the code to merge two if conditions into a single condition using an '&&' operator --- .../src/main/java/com/jme3/app/AndroidHarness.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java index 66d5abc0a..c738ad6c9 100644 --- a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java +++ b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java @@ -579,11 +579,9 @@ public void loseFocus() { //pause the sensors (aka joysticks) if (app.getContext() != null) { JoyInput joyInput = app.getContext().getJoyInput(); - if (joyInput != null) { - if (joyInput instanceof AndroidSensorJoyInput) { - AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; - androidJoyInput.pauseSensors(); - } + if (joyInput != null && joyInput instanceof AndroidSensorJoyInput) { + AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; + androidJoyInput.pauseSensors(); } } } From d3c4e1dcb46c5a7b023691ae72e8b7ba83b4bf90 Mon Sep 17 00:00:00 2001 From: MariyaBosy Date: Wed, 9 Oct 2024 01:47:22 -0400 Subject: [PATCH 02/17] =?UTF-8?q?Defined=20a=20constant=20instead=20of=20d?= =?UTF-8?q?uplicating=20this=20literal=20=E2=80=9CFailed=20to=20asset?= =?UTF-8?q?=E2=80=9D=204=20times.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/jme3/asset/plugins/AndroidLocator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/asset/plugins/AndroidLocator.java b/jme3-android/src/main/java/com/jme3/asset/plugins/AndroidLocator.java index d0ffda860..c0e6815eb 100644 --- a/jme3-android/src/main/java/com/jme3/asset/plugins/AndroidLocator.java +++ b/jme3-android/src/main/java/com/jme3/asset/plugins/AndroidLocator.java @@ -91,7 +91,7 @@ public class AndroidAssetInfo extends AssetInfo { private InputStream in; private final String assetPath; private int resourceId; - + private static final String AssetOpenError="Failed to open asset"; AndroidAssetInfo(AssetManager assetManager, AssetKey key, String assetPath, InputStream in, int resourceId) { super(assetManager, key); this.assetPath = assetPath; @@ -113,13 +113,13 @@ public InputStream openStream() { try { return androidResources.getAssets().open(assetPath); } catch (IOException ex) { - throw new AssetLoadException("Failed to open asset " + assetPath, ex); + throw new AssetLoadException(AssetOpenError + assetPath, ex); } } else { try { return androidResources.openRawResource(resourceId); } catch (Resources.NotFoundException ex) { - throw new AssetLoadException("Failed to open asset " + assetPath, ex); + throw new AssetLoadException(AssetOpenError + assetPath, ex); } } } @@ -131,13 +131,13 @@ public AssetFileDescriptor openFileDescriptor() { try { return androidResources.getAssets().openFd(assetPath); } catch (IOException ex) { - throw new AssetLoadException("Failed to open asset " + assetPath, ex); + throw new AssetLoadException(AssetOpenError + assetPath, ex); } } else { try { return androidResources.openRawResourceFd(resourceId); } catch (Resources.NotFoundException ex) { - throw new AssetLoadException("Failed to open asset " + assetPath, ex); + throw new AssetLoadException(AssetOpenError + assetPath, ex); } } } From 44949e3ac1b5823bc9bc07438a8b1fcf47fad6f5 Mon Sep 17 00:00:00 2001 From: kawsarahmedbhuiyan Date: Fri, 11 Oct 2024 23:19:27 -0400 Subject: [PATCH 03/17] Refactored onTouch method to replace anonymous inner class with a lambda expression --- .../src/main/java/com/jme3/app/AndroidHarness.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java index c738ad6c9..d4fcc0a59 100644 --- a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java +++ b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java @@ -345,13 +345,10 @@ public void handleError(final String errorMsg, final Throwable t) { logger.log(Level.SEVERE, finalMsg); - runOnUiThread(new Runnable() { - @Override - public void run() { - AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon) - .setTitle(finalTitle).setPositiveButton("Kill", AndroidHarness.this).setMessage(finalMsg).create(); - dialog.show(); - } + runOnUiThread(() -> { + AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon) + .setTitle(finalTitle).setPositiveButton("Kill", AndroidHarness.this).setMessage(finalMsg).create(); + dialog.show(); }); } From e71e5f7383374d2a304764ed9d97a06c9ba75da0 Mon Sep 17 00:00:00 2001 From: rajbhensdadiya Date: Sat, 12 Oct 2024 17:19:23 -0400 Subject: [PATCH 04/17] Merge if statement with the enclosing one --- .../src/main/java/com/jme3/app/AndroidHarness.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java index d4fcc0a59..64682da92 100644 --- a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java +++ b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java @@ -540,11 +540,9 @@ public void gainFocus() { //resume the sensors (aka joysticks) if (app.getContext() != null) { JoyInput joyInput = app.getContext().getJoyInput(); - if (joyInput != null) { - if (joyInput instanceof AndroidSensorJoyInput) { - AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; - androidJoyInput.resumeSensors(); - } + if (joyInput instanceof AndroidSensorJoyInput) { + AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; + androidJoyInput.resumeSensors(); } } } From 70eb9314b313fdc0de1f133b86b07847025e3895 Mon Sep 17 00:00:00 2001 From: SahebChandok Date: Mon, 14 Oct 2024 13:56:12 -0400 Subject: [PATCH 05/17] Refactored the code to remove usage of multiple deprecated methods. --- .../src/main/java/com/jme3/app/AndroidHarness.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java index 64682da92..81bf5a455 100644 --- a/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java +++ b/jme3-android/src/main/java/com/jme3/app/AndroidHarness.java @@ -31,6 +31,7 @@ import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; +import android.graphics.Point; /** * AndroidHarness wraps a jme application object and runs it on @@ -200,7 +201,7 @@ public void onCreate(Bundle savedInstanceState) { if (screenFullScreen) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); + WindowManager.LayoutParams.FLAG_FULLSCREEN); } else { if (!screenShowTitle) { requestWindowFeature(Window.FEATURE_NO_TITLE); @@ -216,7 +217,11 @@ public void onCreate(Bundle savedInstanceState) { //TODO try to find a better way to get a hand on the resolution WindowManager wind = this.getWindowManager(); Display disp = wind.getDefaultDisplay(); - Log.d("AndroidHarness", "Resolution from Window, width:" + disp.getWidth() + ", height: " + disp.getHeight()); + Point size = new Point(); + disp.getSize(size); // Replaces the deprecated methods + int width = size.x; + int height = size.y; + Log.d("AndroidHarness", "Resolution from Window, width:" + width + ", height: " + height); // Create Settings logger.log(Level.FINE, "Creating settings"); @@ -232,7 +237,7 @@ public void onCreate(Bundle savedInstanceState) { settings.setSamples(eglSamples); settings.setStencilBits(eglStencilBits); - settings.setResolution(disp.getWidth(), disp.getHeight()); + settings.setResolution(width, height); settings.setAudioRenderer(audioRendererType); settings.setFrameRate(frameRate); @@ -409,7 +414,7 @@ public void layoutDisplay() { Drawable drawable = this.getResources().getDrawable(splashPicID); if (drawable instanceof NinePatchDrawable) { - splashImageView.setBackgroundDrawable(drawable); + splashImageView.setBackground(drawable); } else { splashImageView.setImageResource(splashPicID); } From bcf64989dc9c508af1a92ab20af02a1838ae2540 Mon Sep 17 00:00:00 2001 From: rajbhensdadiya Date: Wed, 6 Nov 2024 22:47:35 -0500 Subject: [PATCH 06/17] Refactor: Remove duplicate onTouch method logic in AndroidInputHandler and AndroidInputHandler14 --- .../input/android/AndroidInputHandler.java | 13 +++++------- .../input/android/AndroidInputHandler14.java | 20 +------------------ 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java index dba0c7141..6a04256d3 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java @@ -184,21 +184,14 @@ public JoyInput getJoyInput() { * */ - - @Override - public boolean onTouch(View view, MotionEvent event) { + protected boolean processTouchEvent(View view, MotionEvent event) { if (view != getView()) { return false; } boolean consumed = false; - int source = event.getSource(); -// logger.log(Level.INFO, "onTouch source: {0}", source); - boolean isTouch = ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN); -// logger.log(Level.INFO, "onTouch source: {0}, isTouch: {1}", -// new Object[]{source, isTouch}); if (isTouch && touchInput != null) { // send the event to the touch processor @@ -206,7 +199,11 @@ public boolean onTouch(View view, MotionEvent event) { } return consumed; + } + @Override + public boolean onTouch(View view, MotionEvent event) { + return processTouchEvent(view, event); } @Override diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java index 5ee0f757b..67e091b41 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java @@ -73,25 +73,7 @@ protected void addListeners(GLSurfaceView view) { @Override public boolean onHover(View view, MotionEvent event) { - if (view != getView()) { - return false; - } - - boolean consumed = false; - - int source = event.getSource(); -// logger.log(Level.INFO, "onTouch source: {0}", source); - - boolean isTouch = ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN); -// logger.log(Level.INFO, "onTouch source: {0}, isTouch: {1}", -// new Object[]{source, isTouch}); - - if (isTouch && touchInput != null) { - // send the event to the touch processor - consumed = ((AndroidTouchInput14)touchInput).onHover(event); - } - - return consumed; + return processTouchEvent(view, event); } @Override From 10a3a547e4bddce385c9d751eb826a7a55e3cad0 Mon Sep 17 00:00:00 2001 From: Meet Boghani Date: Thu, 7 Nov 2024 00:20:09 -0500 Subject: [PATCH 07/17] Fix: Refactor TouchEvent setup to remove duplicate code in onShowPress and onLongPress --- .../jme3/input/android/AndroidGestureProcessor.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java index bb582ec3d..c680302fb 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java @@ -86,20 +86,19 @@ public boolean onSingleTapUp(MotionEvent event) { public void onShowPress(MotionEvent event) { float jmeX = touchInput.getJmeX(event.getX()); float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY())); - TouchEvent touchEvent = touchInput.getFreeTouchEvent(); - touchEvent.set(TouchEvent.Type.SHOWPRESS, jmeX, jmeY, 0, 0); - touchEvent.setPointerId(touchInput.getPointerId(event)); - touchEvent.setTime(event.getEventTime()); - touchEvent.setPressure(event.getPressure()); - touchInput.addEvent(touchEvent); + prepareTouchEvent(TouchEvent.Type.SHOWPRESS, event, jmeX, jmeY); } @Override public void onLongPress(MotionEvent event) { float jmeX = touchInput.getJmeX(event.getX()); float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY())); + prepareTouchEvent(TouchEvent.Type.LONGPRESSED, event, jmeX, jmeY); + } + + private void prepareTouchEvent(TouchEvent.Type eventType, MotionEvent event, float x, float y) { TouchEvent touchEvent = touchInput.getFreeTouchEvent(); - touchEvent.set(TouchEvent.Type.LONGPRESSED, jmeX, jmeY, 0, 0); + touchEvent.set(eventType, x, y, 0, 0); touchEvent.setPointerId(touchInput.getPointerId(event)); touchEvent.setTime(event.getEventTime()); touchEvent.setPressure(event.getPressure()); From d23dedfb02cf818085c505a3edc3affa00c09813 Mon Sep 17 00:00:00 2001 From: MariyaBosy Date: Sat, 9 Nov 2024 00:02:59 -0500 Subject: [PATCH 08/17] Refactor: Remove duplicate onKey method. Refactor: Remove duplicate onKey method logic in AndroidInputHandler and AndroidInputHandler14 Issue: rilling#64 --- .../input/android/AndroidInputHandler.java | 36 +++++++++++------ .../input/android/AndroidInputHandler14.java | 39 +++---------------- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java index dba0c7141..d944abe8b 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java @@ -53,7 +53,7 @@ * @author iwgeric */ public class AndroidInputHandler implements View.OnTouchListener, - View.OnKeyListener { + View.OnKeyListener { private static final Logger logger = Logger.getLogger(AndroidInputHandler.class.getName()); @@ -208,24 +208,38 @@ public boolean onTouch(View view, MotionEvent event) { return consumed; } + protected boolean consumeEvent(KeyEvent event, Object touchInput, Object joyInput) { + int source = event.getSource(); - @Override - public boolean onKey(View view, int keyCode, KeyEvent event) { - if (view != getView()) { - return false; - } + boolean isTouch = ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) || + ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD); + + boolean isJoystick = ((source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || + ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK); + + boolean isUnknown = (source & InputDevice.SOURCE_UNKNOWN) == InputDevice.SOURCE_UNKNOWN; boolean consumed = false; - int source = event.getSource(); -// logger.log(Level.INFO, "onKey source: {0}", source); + // Check if touchInput should consume the event + if (touchInput != null && (isTouch || (isUnknown && ((TouchInput)touchInput).isSimulateKeyboard()))) { + consumed = true; + } - if (touchInput != null) { - consumed = touchInput.onKey(event); + // Check if joyInput should consume the event + if (isJoystick && joyInput != null) { + consumed |= ((AndroidJoyInput14)joyInput).onKey(event); } return consumed; + } + @Override + public boolean onKey(View view, int keyCode, KeyEvent event) { + if (view != getView()) { + return false; + } + return consumeEvent(event, touchInput, null); } -} +} \ No newline at end of file diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java index 5ee0f757b..1b6c46b23 100644 --- a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java +++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java @@ -48,7 +48,7 @@ * @author iwgeric */ public class AndroidInputHandler14 extends AndroidInputHandler implements View.OnHoverListener, - View.OnGenericMotionListener { + View.OnGenericMotionListener { private static final Logger logger = Logger.getLogger(AndroidInputHandler14.class.getName()); @@ -107,7 +107,7 @@ public boolean onGenericMotion(View view, MotionEvent event) { boolean isJoystick = ((source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || - ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK); + ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK); if (isJoystick && joyInput != null) { // logger.log(Level.INFO, "onGenericMotion source: {0}, isJoystick: {1}", @@ -124,37 +124,8 @@ public boolean onKey(View view, int keyCode, KeyEvent event) { if (view != getView()) { return false; } - - boolean consumed = false; - -// logger.log(Level.INFO, "onKey keyCode: {0}, action: {1}, event: {2}", -// new Object[]{KeyEvent.keyCodeToString(keyCode), event.getAction(), event}); - int source = event.getSource(); -// logger.log(Level.INFO, "onKey source: {0}", source); - - boolean isTouch = - ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) || - ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD); - boolean isJoystick = - ((source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || - ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK); - boolean isUnknown = - (source & android.view.InputDevice.SOURCE_UNKNOWN) == android.view.InputDevice.SOURCE_UNKNOWN; - - if (touchInput != null && (isTouch || (isUnknown && this.touchInput.isSimulateKeyboard()))) { -// logger.log(Level.INFO, "onKey source: {0}, isTouch: {1}", -// new Object[]{source, isTouch}); - consumed = touchInput.onKey(event); - } - if (isJoystick && joyInput != null) { -// logger.log(Level.INFO, "onKey source: {0}, isJoystick: {1}", -// new Object[]{source, isJoystick}); - // use inclusive OR to make sure the onKey method is called. - consumed = consumed | ((AndroidJoyInput14)joyInput).onKey(event); - } - - return consumed; - + return consumeEvent(event, touchInput, joyInput); } -} + +} \ No newline at end of file From 1c8ffdc522ab4f10c10f29760fc9f18d6c41c67c Mon Sep 17 00:00:00 2001 From: kawsarahmedbhuiyan Date: Sat, 9 Nov 2024 21:15:14 -0500 Subject: [PATCH 09/17] Refactored duplicated file descriptor handling in loadBuffer and loadStream methods of NativeVorbisLoader.java into helper methods to eliminate redundancy --- .../audio/plugins/NativeVorbisLoader.java | 85 +++++++++++-------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java index 63517cd3d..aecf07d6e 100644 --- a/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java +++ b/jme3-android/src/main/java/com/jme3/audio/plugins/NativeVorbisLoader.java @@ -46,32 +46,32 @@ import java.nio.ByteBuffer; public class NativeVorbisLoader implements AssetLoader { - + private static class VorbisInputStream extends InputStream implements SeekableStream { private final AssetFileDescriptor afd; private final NativeVorbisFile file; - + public VorbisInputStream(AssetFileDescriptor afd, NativeVorbisFile file) { this.afd = afd; this.file = file; } - + @Override public int read() throws IOException { return 0; } - + @Override public int read(byte[] buf) throws IOException { return file.readIntoArray(buf, 0, buf.length); } - + @Override public int read(byte[] buf, int off, int len) throws IOException { return file.readIntoArray(buf, off, len); } - + @Override public long skip(long n) throws IOException { throw new IOException("Not supported for audio streams"); @@ -85,22 +85,22 @@ public void setTime(float time) { throw new RuntimeException(ex); } } - + @Override public void close() throws IOException { file.clearResources(); afd.close(); } } - + private static AudioBuffer loadBuffer(AssetInfo assetInfo) throws IOException { AndroidAssetInfo aai = (AndroidAssetInfo) assetInfo; AssetFileDescriptor afd = null; NativeVorbisFile file = null; try { - afd = aai.openFileDescriptor(); - int fd = afd.getParcelFileDescriptor().getFd(); - file = new NativeVorbisFile(fd, afd.getStartOffset(), afd.getLength()); + afd = openFileDescriptor(aai); + file = createNativeVorbisFile(afd); + ByteBuffer data = BufferUtils.createByteBuffer(file.totalBytes); file.readIntoBuffer(data); AudioBuffer ab = new AudioBuffer(); @@ -108,54 +108,67 @@ private static AudioBuffer loadBuffer(AssetInfo assetInfo) throws IOException { ab.updateData(data); return ab; } finally { - if (file != null) { - file.clearResources(); - } - if (afd != null) { - afd.close(); - } + closeResources(afd, file); } } - + private static AudioStream loadStream(AssetInfo assetInfo) throws IOException { AndroidAssetInfo aai = (AndroidAssetInfo) assetInfo; AssetFileDescriptor afd = null; NativeVorbisFile file = null; boolean success = false; - + try { - afd = aai.openFileDescriptor(); - int fd = afd.getParcelFileDescriptor().getFd(); - file = new NativeVorbisFile(fd, afd.getStartOffset(), afd.getLength()); - + afd = openFileDescriptor(aai); + file = createNativeVorbisFile(afd); + AudioStream stream = new AudioStream(); stream.setupFormat(file.channels, 16, file.sampleRate); stream.updateData(new VorbisInputStream(afd, file), file.duration); - + success = true; - return stream; } finally { if (!success) { - if (file != null) { - file.clearResources(); - } - if (afd != null) { - afd.close(); - } + closeResources(afd, file); } } } - + + // Helper method to open file descriptor + private static AssetFileDescriptor openFileDescriptor(AndroidAssetInfo aai) throws IOException { + return aai.openFileDescriptor(); + } + + // Helper method to create a NativeVorbisFile + private static NativeVorbisFile createNativeVorbisFile(AssetFileDescriptor afd) throws IOException { + int fd = afd.getParcelFileDescriptor().getFd(); + return new NativeVorbisFile(fd, afd.getStartOffset(), afd.getLength()); + } + + // Helper method to close resources + private static void closeResources(AssetFileDescriptor afd, NativeVorbisFile file) { + if (file != null) { + file.clearResources(); + } + if (afd != null) { + try { + afd.close(); + } catch (IOException e) { + e.printStackTrace(); // handle or log exception appropriately + } + } + } + @Override public Object load(AssetInfo assetInfo) throws IOException { AudioKey key = (AudioKey) assetInfo.getKey(); if (!(assetInfo instanceof AndroidLocator.AndroidAssetInfo)) { - throw new UnsupportedOperationException("Cannot load audio files from classpath." + - "Place your audio files in " + - "Android's assets directory"); + throw new UnsupportedOperationException("Cannot load audio files from classpath." + + "Place your audio files in " + + "Android's assets directory"); } - + if (key.isStream()) { return loadStream(assetInfo); } else { From 85fabc4d41786e2f7540aa42ad3cf52d10c75029 Mon Sep 17 00:00:00 2001 From: SahebChandok Date: Mon, 11 Nov 2024 15:42:34 -0500 Subject: [PATCH 10/17] Refactor OpenGL error handling to remove code duplication --- .../com/jme3/renderer/android/RendererUtil.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/renderer/android/RendererUtil.java b/jme3-android/src/main/java/com/jme3/renderer/android/RendererUtil.java index b4d824b94..678b808a3 100644 --- a/jme3-android/src/main/java/com/jme3/renderer/android/RendererUtil.java +++ b/jme3-android/src/main/java/com/jme3/renderer/android/RendererUtil.java @@ -63,6 +63,10 @@ private RendererUtil() { * {@link RendererUtil#ENABLE_ERROR_CHECKING}. */ public static void checkGLErrorForced() { + checkAndThrowGLError(); + } + + private static void checkAndThrowGLError() { int error = GLES20.glGetError(); if (error != 0) { String message = GLU.gluErrorString(error); @@ -153,14 +157,6 @@ public static void checkGLError() { if (!ENABLE_ERROR_CHECKING) { return; } - int error = GLES20.glGetError(); - if (error != 0) { - String message = GLU.gluErrorString(error); - if (message == null) { - throw new RendererException("An unknown OpenGL error has occurred."); - } else { - throw new RendererException("An OpenGL error has occurred: " + message); - } - } + checkAndThrowGLError(); } } From 7922ef508fc5ffbaec0806e011ebec26afd078ed Mon Sep 17 00:00:00 2001 From: Meet Boghani Date: Mon, 25 Nov 2024 19:01:08 -0500 Subject: [PATCH 11/17] Fix: removed the Cleartext Transmission of Sensitive Information vulnerability by adding SSLSocket for inpustream --- .../network/kernel/tcp/SocketConnector.java | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/jme3-networking/src/main/java/com/jme3/network/kernel/tcp/SocketConnector.java b/jme3-networking/src/main/java/com/jme3/network/kernel/tcp/SocketConnector.java index be4682bd9..8c6ec0b23 100644 --- a/jme3-networking/src/main/java/com/jme3/network/kernel/tcp/SocketConnector.java +++ b/jme3-networking/src/main/java/com/jme3/network/kernel/tcp/SocketConnector.java @@ -40,7 +40,8 @@ import java.net.Socket; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.util.concurrent.atomic.AtomicBoolean; +import javax.net.ssl.*; +import java.security.SecureRandom; /** @@ -53,26 +54,40 @@ */ public class SocketConnector implements Connector { - private Socket sock; + private SSLSocket sock; private InputStream in; private OutputStream out; private SocketAddress remoteAddress; private byte[] buffer = new byte[65535]; - private AtomicBoolean connected = new AtomicBoolean(false); + private boolean connected = false; public SocketConnector( InetAddress address, int port ) throws IOException { - this.sock = new Socket(address, port); - remoteAddress = sock.getRemoteSocketAddress(); // for info purposes - - // Disable Nagle's buffering so data goes out when we - // put it there. - sock.setTcpNoDelay(true); - - in = sock.getInputStream(); - out = sock.getOutputStream(); - - connected.set(true); + try { + // Initialize SSLContext with the default key and trust managers + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, null, new SecureRandom()); + + // Create an SSLSocketFactory + SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + + // SSLSocket connected to the provided address and port + this.sock = (SSLSocket) sslSocketFactory.createSocket(address, port); + this.remoteAddress = sock.getRemoteSocketAddress(); // For informational purposes + + // Desired SSL protocols + sock.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.3"}); + + sock.setTcpNoDelay(true); + + // Initialize input and output streams securely + this.in = sock.getInputStream(); + this.out = sock.getOutputStream(); + + this.connected = true; // Connected + } catch (Exception e) { + throw new IOException("Failed to establish SSL connection", e); + } } protected void checkClosed() @@ -96,7 +111,7 @@ public void close() try { Socket temp = sock; sock = null; - connected.set(false); + connected = false; temp.close(); } catch( IOException e ) { throw new ConnectorException( "Error closing socket for:" + remoteAddress, e ); @@ -131,7 +146,7 @@ public ByteBuffer read() // Wrap it in a ByteBuffer for the caller return ByteBuffer.wrap( buffer, 0, count ); } catch( IOException e ) { - if( !connected.get() ) { + if( !connected) { // Nothing to see here... just move along return null; } From 0f5e82cfe455604acf7f3c56d946a70dcc17a911 Mon Sep 17 00:00:00 2001 From: SahebChandok Date: Thu, 28 Nov 2024 15:11:08 -0500 Subject: [PATCH 12/17] Fixed Path Traversal Vulnerability --- .../com/jme3/system/ExtractNativeLibraries.java | 7 ++++++- .../java/com/jme3/system/NativeLibraryLoader.java | 14 +++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java b/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java index fa63dedb1..65cd6923f 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java +++ b/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java @@ -68,6 +68,11 @@ public static void main(String[] args) { String path = args[1].replace('/', File.separatorChar); File folder = new File(path); try { + File canonicalFolder = folder.getCanonicalFile(); + if (!canonicalFolder.getPath().startsWith(folder.getAbsolutePath())) { + System.err.println("Invalid extraction path: Path traversal attempt detected."); + System.exit(2); + } if ("Windows32".equals(args[0])) { NativeLibraryLoader.extractNativeLibraries(Platform.Windows32, folder); } else if ("Windows64".equals(args[0])) { @@ -77,7 +82,7 @@ public static void main(String[] args) { } else if ("Linux64".equals(args[0])) { NativeLibraryLoader.extractNativeLibraries(Platform.Linux64, folder); } else if ("MacOSX32".equals(args[0])) { - NativeLibraryLoader.extractNativeLibraries(Platform.MacOSX32, folder); + NativeLibraryLoader.extractNativeLibraries(Platform.MacOSX32, canonicalFolder); } else if ("MacOSX64".equals(args[0])) { NativeLibraryLoader.extractNativeLibraries(Platform.MacOSX64, folder); } else { diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java index e315a3c8f..636f5ec03 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java +++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java @@ -43,6 +43,7 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import java.nio.file.Path; import com.jme3.util.res.Resources; @@ -319,11 +320,18 @@ public static File[] getJarsWithNatives() { } public static void extractNativeLibraries(Platform platform, File targetDir) throws IOException { + Path trustedBaseDir = Paths.get("/trusted/extraction/directory"); + Path targetDirPath = targetDir.toPath().normalize(); + + if (!targetDirPath.startsWith(trustedBaseDir)) { + throw new SecurityException("Unauthorized extraction attempt to directory: " + targetDir.getAbsolutePath()); + } + if (!targetDir.exists()) { + targetDir.mkdirs(); + } + for (Map.Entry lib : nativeLibraryMap.entrySet()) { if (lib.getValue().getPlatform() == platform) { - if (!targetDir.exists()) { - targetDir.mkdirs(); - } extractNativeLibrary(platform, lib.getValue().getName(), targetDir); } } From 5a6fde8324c011389ee510fac989b00393bc1735 Mon Sep 17 00:00:00 2001 From: kawsarahmedbhuiyan Date: Fri, 29 Nov 2024 00:32:17 -0500 Subject: [PATCH 13/17] Fixed Improper Restriction of XML External Entity Reference Vulnerability in XMLImporter.java --- .../xml/java/com/jme3/export/xml/XMLImporter.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/jme3-plugins/src/xml/java/com/jme3/export/xml/XMLImporter.java b/jme3-plugins/src/xml/java/com/jme3/export/xml/XMLImporter.java index 7cf2a98cb..4a9d98f19 100644 --- a/jme3-plugins/src/xml/java/com/jme3/export/xml/XMLImporter.java +++ b/jme3-plugins/src/xml/java/com/jme3/export/xml/XMLImporter.java @@ -41,8 +41,10 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.w3c.dom.Document; import org.xml.sax.SAXException; /** @@ -98,7 +100,18 @@ public Savable load(File f) throws IOException { public Savable load(InputStream f) throws IOException { try { - domIn = new DOMInputCapsule(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f), this); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + factory.setXIncludeAware(false); + factory.setExpandEntityReferences(false); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(f); + + domIn = new DOMInputCapsule(doc, this); return domIn.readSavable(null, null); } catch (SAXException | ParserConfigurationException e) { IOException ex = new IOException(); From a4cec01e8e4d77ae21ee69e2502a73faa0c1b246 Mon Sep 17 00:00:00 2001 From: SahebChandok Date: Fri, 29 Nov 2024 14:03:03 -0500 Subject: [PATCH 14/17] Revert "Fixed Path Traversal Vulnerability" This reverts commit 0f5e82cfe455604acf7f3c56d946a70dcc17a911. --- .../com/jme3/system/ExtractNativeLibraries.java | 7 +------ .../java/com/jme3/system/NativeLibraryLoader.java | 14 +++----------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java b/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java index 65cd6923f..fa63dedb1 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java +++ b/jme3-desktop/src/main/java/com/jme3/system/ExtractNativeLibraries.java @@ -68,11 +68,6 @@ public static void main(String[] args) { String path = args[1].replace('/', File.separatorChar); File folder = new File(path); try { - File canonicalFolder = folder.getCanonicalFile(); - if (!canonicalFolder.getPath().startsWith(folder.getAbsolutePath())) { - System.err.println("Invalid extraction path: Path traversal attempt detected."); - System.exit(2); - } if ("Windows32".equals(args[0])) { NativeLibraryLoader.extractNativeLibraries(Platform.Windows32, folder); } else if ("Windows64".equals(args[0])) { @@ -82,7 +77,7 @@ public static void main(String[] args) { } else if ("Linux64".equals(args[0])) { NativeLibraryLoader.extractNativeLibraries(Platform.Linux64, folder); } else if ("MacOSX32".equals(args[0])) { - NativeLibraryLoader.extractNativeLibraries(Platform.MacOSX32, canonicalFolder); + NativeLibraryLoader.extractNativeLibraries(Platform.MacOSX32, folder); } else if ("MacOSX64".equals(args[0])) { NativeLibraryLoader.extractNativeLibraries(Platform.MacOSX64, folder); } else { diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java index 636f5ec03..e315a3c8f 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java +++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java @@ -43,7 +43,6 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import java.nio.file.Path; import com.jme3.util.res.Resources; @@ -320,18 +319,11 @@ public static File[] getJarsWithNatives() { } public static void extractNativeLibraries(Platform platform, File targetDir) throws IOException { - Path trustedBaseDir = Paths.get("/trusted/extraction/directory"); - Path targetDirPath = targetDir.toPath().normalize(); - - if (!targetDirPath.startsWith(trustedBaseDir)) { - throw new SecurityException("Unauthorized extraction attempt to directory: " + targetDir.getAbsolutePath()); - } - if (!targetDir.exists()) { - targetDir.mkdirs(); - } - for (Map.Entry lib : nativeLibraryMap.entrySet()) { if (lib.getValue().getPlatform() == platform) { + if (!targetDir.exists()) { + targetDir.mkdirs(); + } extractNativeLibrary(platform, lib.getValue().getName(), targetDir); } } From e89072e1bfab1ce219fb21af9e828713e3b4f087 Mon Sep 17 00:00:00 2001 From: SahebChandok Date: Fri, 29 Nov 2024 14:46:01 -0500 Subject: [PATCH 15/17] Optimize regex to prevent ReDoS vulnerability by reducing backtracking --- .../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 60e6b3026..472baac7c 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -86,7 +86,7 @@ public final class GLRenderer implements Renderer { private static final Logger logger = Logger.getLogger(GLRenderer.class.getName()); private static final boolean VALIDATE_SHADER = false; - private static final Pattern GLVERSION_PATTERN = Pattern.compile(".*?(\\d+)\\.(\\d+).*"); + private static final Pattern GLVERSION_PATTERN = Pattern.compile("\\b(\\d+)\\.(\\d+)\\b"); private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); private final FloatBuffer floatBuf16 = BufferUtils.createFloatBuffer(16); From dd598d7add66480d3d3b83d25fce98aeecec3f08 Mon Sep 17 00:00:00 2001 From: rajbhensdadiya Date: Sun, 1 Dec 2024 14:43:24 -0500 Subject: [PATCH 16/17] fix: secure FileOutputStream with encryption in MjpegFileWriter --- .../com/jme3/app/state/MjpegFileWriter.java | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/state/MjpegFileWriter.java b/jme3-android/src/main/java/com/jme3/app/state/MjpegFileWriter.java index 616daeee3..b178271ca 100644 --- a/jme3-android/src/main/java/com/jme3/app/state/MjpegFileWriter.java +++ b/jme3-android/src/main/java/com/jme3/app/state/MjpegFileWriter.java @@ -31,7 +31,6 @@ */ package com.jme3.app.state; -import android.graphics.Bitmap; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -43,19 +42,28 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.crypto.Cipher; +import javax.crypto.CipherOutputStream; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import android.graphics.Bitmap; + /** * Released under BSD License * @author monceaux, normenhansen, entrusC */ public class MjpegFileWriter { private static final Logger logger = Logger.getLogger(MjpegFileWriter.class.getName()); + private static final String ENCRYPTION_ALGORITHM = "AES"; + private static final byte[] KEY = "YourSecretKey123".getBytes(); int width = 0; int height = 0; double framerate = 0; int numFrames = 0; File aviFile = null; - FileOutputStream aviOutput = null; + CipherOutputStream encryptedOutput = null; FileChannel aviChannel = null; long riffOffset = 0; long aviMovieOffset = 0; @@ -71,18 +79,29 @@ public MjpegFileWriter(File aviFile, int width, int height, double framerate, in this.height = height; this.framerate = framerate; this.numFrames = numFrames; - aviOutput = new FileOutputStream(aviFile); - aviChannel = aviOutput.getChannel(); + + SecretKey secretKey = new SecretKeySpec(KEY, ENCRYPTION_ALGORITHM); + Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + + FileOutputStream fileOut = new FileOutputStream(aviFile) { + @Override + public FileChannel getChannel() { + return super.getChannel(); + } + }; + encryptedOutput = new CipherOutputStream(fileOut, cipher); + aviChannel = fileOut.getChannel(); RIFFHeader rh = new RIFFHeader(); - aviOutput.write(rh.toBytes()); - aviOutput.write(new AVIMainHeader().toBytes()); - aviOutput.write(new AVIStreamList().toBytes()); - aviOutput.write(new AVIStreamHeader().toBytes()); - aviOutput.write(new AVIStreamFormat().toBytes()); - aviOutput.write(new AVIJunk().toBytes()); + encryptedOutput.write(rh.toBytes()); + encryptedOutput.write(new AVIMainHeader().toBytes()); + encryptedOutput.write(new AVIStreamList().toBytes()); + encryptedOutput.write(new AVIStreamHeader().toBytes()); + encryptedOutput.write(new AVIStreamFormat().toBytes()); + encryptedOutput.write(new AVIJunk().toBytes()); aviMovieOffset = aviChannel.position(); - aviOutput.write(new AVIMovieList().toBytes()); + encryptedOutput.write(new AVIMovieList().toBytes()); indexlist = new AVIIndexList(); } @@ -105,12 +124,12 @@ public void addImage(byte[] imagedata) throws Exception { indexlist.addAVIIndex((int) position, useLength); - aviOutput.write(fcc); - aviOutput.write(intBytes(swapInt(useLength))); - aviOutput.write(imagedata); + encryptedOutput.write(fcc); + encryptedOutput.write(intBytes(swapInt(useLength))); + encryptedOutput.write(imagedata); if (extra > 0) { for (int i = 0; i < extra; i++) { - aviOutput.write(0); + encryptedOutput.write(0); } } @@ -120,8 +139,13 @@ public void addImage(byte[] imagedata) throws Exception { public void finishAVI() throws Exception { logger.log(Level.INFO, "finishAVI"); byte[] indexlistBytes = indexlist.toBytes(); - aviOutput.write(indexlistBytes); - aviOutput.close(); + encryptedOutput.write(indexlistBytes); + encryptedOutput.close(); + + SecretKey secretKey = new SecretKeySpec(KEY, ENCRYPTION_ALGORITHM); + Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + int fileSize = (int)aviFile.length(); logger.log(Level.INFO, "fileSize: {0}", fileSize); int listSize = (int) (fileSize - 8 - aviMovieOffset - indexlistBytes.length); @@ -133,17 +157,19 @@ public void finishAVI() throws Exception { } RandomAccessFile raf = new RandomAccessFile(aviFile, "rw"); + CipherOutputStream headerUpdate = new CipherOutputStream(new FileOutputStream(raf.getFD()), cipher); //add header and length by writing the headers again //with the now available information - raf.write(new RIFFHeader(fileSize).toBytes()); - raf.write(new AVIMainHeader().toBytes()); - raf.write(new AVIStreamList().toBytes()); - raf.write(new AVIStreamHeader().toBytes()); - raf.write(new AVIStreamFormat().toBytes()); - raf.write(new AVIJunk().toBytes()); - raf.write(new AVIMovieList(listSize).toBytes()); - + headerUpdate.write(new RIFFHeader(fileSize).toBytes()); + headerUpdate.write(new AVIMainHeader().toBytes()); + headerUpdate.write(new AVIStreamList().toBytes()); + headerUpdate.write(new AVIStreamHeader().toBytes()); + headerUpdate.write(new AVIStreamFormat().toBytes()); + headerUpdate.write(new AVIJunk().toBytes()); + headerUpdate.write(new AVIMovieList(listSize).toBytes()); + + headerUpdate.close(); raf.close(); } From 6a564db6b0425198faf503a4c596f4fa880daa5a Mon Sep 17 00:00:00 2001 From: MariyaBosy Date: Mon, 2 Dec 2024 00:33:08 -0500 Subject: [PATCH 17/17] Fix vulnerability in executeAnalyzer to enhance security and handle files - Specified a secure directory for temporary file creation using System.getProperty("java.io.tmpdir"). - Validated file permissions using setReadable, setWritable, and setExecutable; logged warnings for failures. - Implemented try-with-resources for FileWriter and Scanner to ensure proper resource closure. - Handled temporary file deletion failures with appropriate logging. - Restored interrupted thread status after catching InterruptedException. --- .../shadercheck/GpuAnalyzerValidator.java | 98 +++++++++++-------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/jme3-core/src/tools/java/jme3tools/shadercheck/GpuAnalyzerValidator.java b/jme3-core/src/tools/java/jme3tools/shadercheck/GpuAnalyzerValidator.java index 2064c5ced..11e3aab3e 100644 --- a/jme3-core/src/tools/java/jme3tools/shadercheck/GpuAnalyzerValidator.java +++ b/jme3-core/src/tools/java/jme3tools/shadercheck/GpuAnalyzerValidator.java @@ -54,59 +54,73 @@ public String getInstalledVersion() { } return version; } - private static void executeAnalyzer(String sourceCode, String language, String defines, String asic, StringBuilder results){ + private static void executeAnalyzer(String sourceCode, String language, String defines, String asic, StringBuilder results) { try { - // Export sourcecode to temporary file - File tempFile = File.createTempFile("test_shader", ".glsl"); - FileWriter writer = new FileWriter(tempFile); - - String glslVer = language.substring(4); - writer.append("#version ").append(glslVer).append('\n'); - writer.append("#extension all : warn").append('\n'); - writer.append(defines).append('\n'); - writer.write(sourceCode); - writer.close(); - - ProcessBuilder pb = new ProcessBuilder("GPUShaderAnalyzer", - tempFile.getAbsolutePath(), - "-I", - "-ASIC", asic); - - Process p = pb.start(); - - Scanner scan = new Scanner(p.getInputStream()); - - if (!scan.hasNextLine()){ - String x = scan.next(); - System.out.println(x); + // Export source code to a secure temporary file + File tempFile = File.createTempFile("test_shader", ".glsl", new File(System.getProperty("java.io.tmpdir"))); + + // Set secure file permissions and validate results + if (!tempFile.setReadable(false, false)) { + logger.log(Level.WARNING, "Failed to set temp file as non-readable for others: {0}", tempFile.getAbsolutePath()); } - - String ln = scan.nextLine(); - - if (ln.startsWith(";")){ - results.append(" - Success!").append('\n'); - }else{ - results.append(" - Failure!").append('\n'); - results.append(ln).append('\n'); - while (scan.hasNextLine()){ - results.append(scan.nextLine()).append('\n'); - } + if (!tempFile.setWritable(true, true)) { + logger.log(Level.WARNING, "Failed to set temp file as writable for the owner: {0}", tempFile.getAbsolutePath()); + } + if (!tempFile.setExecutable(false, false)) { + logger.log(Level.WARNING, "Failed to disable execute permissions on temp file: {0}", tempFile.getAbsolutePath()); } - scan.close(); + try (FileWriter writer = new FileWriter(tempFile)) { + String glslVer = language.substring(4); + writer.append("#version ").append(glslVer).append('\n'); + writer.append("#extension all : warn").append('\n'); + writer.append(defines).append('\n'); + writer.write(sourceCode); + } + + ProcessBuilder pb = new ProcessBuilder("GPUShaderAnalyzer", + tempFile.getAbsolutePath(), + "-I", + "-ASIC", asic); + + Process p = pb.start(); + + try (Scanner scan = new Scanner(p.getInputStream())) { + if (!scan.hasNextLine()) { + String x = scan.next(); + System.out.println(x); + } + + String ln = scan.nextLine(); + + if (ln.startsWith(";")) { + results.append(" - Success!").append('\n'); + } else { + results.append(" - Failure!").append('\n'); + results.append(ln).append('\n'); + while (scan.hasNextLine()) { + results.append(scan.nextLine()).append('\n'); + } + } + } + p.getOutputStream().close(); p.getErrorStream().close(); - + p.waitFor(); p.destroy(); - - tempFile.delete(); + + // Delete the temporary file securely + if (!tempFile.delete()) { + logger.log(Level.WARNING, "Temporary file could not be deleted: {0}", tempFile.getAbsolutePath()); + } } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); // Restore the interrupted status } catch (IOException ex) { - logger.log(Level.SEVERE, "IOEx", ex); + logger.log(Level.SEVERE, "IOException occurred", ex); } } - + @Override public void validate(Shader shader, StringBuilder results) { for (ShaderSource source : shader.getSources()){ @@ -121,5 +135,5 @@ public void validate(Shader shader, StringBuilder results) { } } } - + }