From 449f96942e4bfd086fbae4ccd351fbd2e2c6aa6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 2 Aug 2024 17:05:30 +0200 Subject: [PATCH] Removed: Proxy feature. It was not working since today almost every page uses HTTPS. Also Flash is limited in browsers. --- CHANGELOG.md | 3 + README.md | 2 - lib/jpproxy.jar | Bin 86928 -> 0 bytes lib/jpproxy.muffin.license.txt | 16 - libsrc/jpproxy/build.xml | 158 -- libsrc/jpproxy/buildconfig.xml | 23 - libsrc/jpproxy/jpproxy.iml | 14 - libsrc/jpproxy/manifest.mf | 3 - libsrc/jpproxy/nbbuild.xml | 73 - libsrc/jpproxy/nbproject/build-impl.xml | 1402 ----------------- libsrc/jpproxy/nbproject/genfiles.properties | 8 - libsrc/jpproxy/nbproject/project.properties | 74 - libsrc/jpproxy/nbproject/project.xml | 13 - .../src/com/jpexs/proxy/ByteArray.java | 130 -- .../src/com/jpexs/proxy/CatchedListener.java | 21 - .../src/com/jpexs/proxy/Cleanable.java | 6 - .../jpproxy/src/com/jpexs/proxy/Client.java | 45 - .../src/com/jpexs/proxy/Connection.java | 154 -- libsrc/jpproxy/src/com/jpexs/proxy/Copy.java | 33 - .../jpproxy/src/com/jpexs/proxy/Handler.java | 665 -------- libsrc/jpproxy/src/com/jpexs/proxy/Http.java | 284 ---- .../src/com/jpexs/proxy/HttpConnection.java | 49 - .../src/com/jpexs/proxy/HttpError.java | 62 - .../src/com/jpexs/proxy/HttpRelay.java | 14 - libsrc/jpproxy/src/com/jpexs/proxy/Https.java | 127 -- .../src/com/jpexs/proxy/HttpsThrough.java | 39 - .../jpproxy/src/com/jpexs/proxy/Janitor.java | 34 - libsrc/jpproxy/src/com/jpexs/proxy/Key.java | 35 - libsrc/jpproxy/src/com/jpexs/proxy/Main.java | 65 - .../jpproxy/src/com/jpexs/proxy/Message.java | 242 --- .../src/com/jpexs/proxy/ProxyConfig.java | 43 - .../src/com/jpexs/proxy/ReplacedListener.java | 6 - .../src/com/jpexs/proxy/Replacement.java | 80 - libsrc/jpproxy/src/com/jpexs/proxy/Reply.java | 202 --- .../jpproxy/src/com/jpexs/proxy/Request.java | 223 --- .../jpexs/proxy/RetryRequestException.java | 12 - .../src/com/jpexs/proxy/ReusableThread.java | 57 - .../jpproxy/src/com/jpexs/proxy/Server.java | 139 -- .../src/com/jpexs/proxy/ThreadPool.java | 45 - .../src/com/jpexs/proxy/WorkerThread.java | 134 -- .../console/CommandLineArgumentParser.java | 13 +- src/com/jpexs/decompiler/flash/gui/Main.java | 107 -- .../decompiler/flash/gui/MainFrameMenu.java | 15 +- .../jpexs/decompiler/flash/gui/ModeFrame.java | 88 -- .../flash/gui/helpers/CheckResources.java | 5 - .../flash/gui/proxy/ProxyFrame.java | 741 --------- .../flash/gui/proxy/SWFListModel.java | 179 --- 47 files changed, 6 insertions(+), 5877 deletions(-) delete mode 100644 lib/jpproxy.jar delete mode 100644 lib/jpproxy.muffin.license.txt delete mode 100644 libsrc/jpproxy/build.xml delete mode 100644 libsrc/jpproxy/buildconfig.xml delete mode 100644 libsrc/jpproxy/jpproxy.iml delete mode 100644 libsrc/jpproxy/manifest.mf delete mode 100644 libsrc/jpproxy/nbbuild.xml delete mode 100644 libsrc/jpproxy/nbproject/build-impl.xml delete mode 100644 libsrc/jpproxy/nbproject/genfiles.properties delete mode 100644 libsrc/jpproxy/nbproject/project.properties delete mode 100644 libsrc/jpproxy/nbproject/project.xml delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/ByteArray.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/CatchedListener.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Cleanable.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Client.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Connection.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Copy.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Handler.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Http.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/HttpConnection.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/HttpError.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/HttpRelay.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Https.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/HttpsThrough.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Janitor.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Key.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Main.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Message.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/ProxyConfig.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/ReplacedListener.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Replacement.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Reply.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Request.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/RetryRequestException.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/ReusableThread.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/Server.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/ThreadPool.java delete mode 100644 libsrc/jpproxy/src/com/jpexs/proxy/WorkerThread.java delete mode 100644 src/com/jpexs/decompiler/flash/gui/ModeFrame.java delete mode 100644 src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java delete mode 100644 src/com/jpexs/decompiler/flash/gui/proxy/SWFListModel.java diff --git a/CHANGELOG.md b/CHANGELOG.md index caddddfef..e22f765f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -99,6 +99,9 @@ All notable changes to this project will be documented in this file. - Run/Debug command - executed SWF temp files (`~ffdec_run...swf` etc.) are now generated in the directory where original SWF resides to allow loading relative assets - [#2228] AS1/2/3 bitwise operations use hexadecimal operands + +### Removed +- Proxy feature. It was not working since today almost every page uses HTTPS. Also Flash is limited in browsers. ## [20.1.0] - 2023-12-30 ### Added diff --git a/README.md b/README.md index f79cdaaeb..518280717 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,6 @@ FFDec Application is licensed under the GNU GPL v3 (GPL-3.0-or-later) licence, s It uses modified code of these libraries: * [JSyntaxPane] (Code editor) - Apache License 2.0 -* [Muffin] (Proxy) - GPL And links also these libraries: @@ -169,7 +168,6 @@ See [library README](libsrc/ffdec_lib/README.md) for more info about FFDec libra [launch4j]: http://launch4j.sourceforge.net/ [NSIS]: http://nsis.sourceforge.net/ [JSyntaxPane]: https://code.google.com/p/jsyntaxpane/ -[Muffin]: https://web.archive.org/web/20171025082558/http://muffin.doit.org/ (original: http://muffin.doit.org/) [Java Native Access - JNA]: https://github.com/twall/jna [Insubstantial]: http://shemnon.com/speling/2011/04/insubstantial-62-release.html [javactivex]:https://github.com/jindrapetrik/javactivex diff --git a/lib/jpproxy.jar b/lib/jpproxy.jar deleted file mode 100644 index dc386eea57e1f84095d8d8dc49c0b7a135a56695..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86928 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�E 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≤xZE$l@PC>FL$oh~2>^&q?cX6+{DJFdBnxCmb0Y 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ðIi%NTS~SF|OpII#GA+6#A#b&7^pZ2!$}I}t zeXZ}YmS!XMjP&r0a^t3miys!pizC(({w1Fv&&&8k=6IQX1FUIE=DgoFIp-6MrcPIR zZzu22Z0j#0JS~hw-;ft0z|D#NB>oQcIU=FbP>TNiUJSg?`oc9#kf)G49~xRo#7&Eh5Sbhz5I0MhZA3s}-rf8XXu(bNc0kDQ0|J_)X6F#N*yf5Y2`HN-5F1PS z+JFtSA4Io-Zydiop)li|B$!9RXX5B7Fk_laUNGhCoIh{c?cE9~LAVzbXYSnZqu!~| z3Ij_O$ds4t#`kj6Z9$oj!S`1R@{qiIgK9$EYy00h8r6PH(IS6kjtPNPz?^% zUpM1osCZXwe!)y&b%viEBK_45Lo$Ge2ZriwJ{k(sD!Zil%;BL?->dOov)Q~Y=RGUQD|kD;c+Wo*7Du6R*cN2}jve`O#M=@n z*cc;jrJSFIXG5dGy$ZhvT(?J_+ z)WT|dsI2~9KoRxHZ4s}1Jer~vGDowwD)ZZ49iXA>lS}Mh9*!oqJ=5PaLh)aD>6UYc zsD6EfMEHNlj(qWvXktUrTy0Jao;?*eMxSXu6^_S_bbVz6LfRwXAt0LGFOP1R|0_lz zeRA8y70(sY^VAihNj+7y@`+_MQ+7hRnJ%uO{s0oFFySs`O+ts5~9I^o@gm8jHYyQ=@r{hT$J)+UXveuC7Mz+od=(p zT=BpJhAck0rM;S|CVy=3{1-%%%8#y=E$#TP3rXRyEr#-Wnwn>RlqGf3 - -Muffin is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -Muffin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Muffin; see the file COPYING. If not, write to the -Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. \ No newline at end of file diff --git a/libsrc/jpproxy/build.xml b/libsrc/jpproxy/build.xml deleted file mode 100644 index ae7c00dcd..000000000 --- a/libsrc/jpproxy/build.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - Builds project JPProxy. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libsrc/jpproxy/buildconfig.xml b/libsrc/jpproxy/buildconfig.xml deleted file mode 100644 index 30a889982..000000000 --- a/libsrc/jpproxy/buildconfig.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libsrc/jpproxy/jpproxy.iml b/libsrc/jpproxy/jpproxy.iml deleted file mode 100644 index ab79c9a38..000000000 --- a/libsrc/jpproxy/jpproxy.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/libsrc/jpproxy/manifest.mf b/libsrc/jpproxy/manifest.mf deleted file mode 100644 index 328e8e5bc..000000000 --- a/libsrc/jpproxy/manifest.mf +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - diff --git a/libsrc/jpproxy/nbbuild.xml b/libsrc/jpproxy/nbbuild.xml deleted file mode 100644 index 7369c29a9..000000000 --- a/libsrc/jpproxy/nbbuild.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - Builds, tests, and runs the project JPProxy. - - - diff --git a/libsrc/jpproxy/nbproject/build-impl.xml b/libsrc/jpproxy/nbproject/build-impl.xml deleted file mode 100644 index ec2302d65..000000000 --- a/libsrc/jpproxy/nbproject/build-impl.xml +++ /dev/null @@ -1,1402 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set build.dir - Must set dist.dir - Must set build.classes.dir - Must set dist.javadoc.dir - Must set build.test.classes.dir - Must set build.test.results.dir - Must set build.classes.excludes - Must set dist.jar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set javac.includes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No tests executed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set JVM to use for profiling in profiler.info.jvm - Must set profiler agent JVM arguments in profiler.info.jvmargs.agent - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select some files in the IDE or set javac.includes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To run this application from the command line without Ant, try: - - java -jar "${dist.jar.resolved}" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set run.class - - - - Must select one file in the IDE or set run.class - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set debug.class - - - - - Must select one file in the IDE or set debug.class - - - - - Must set fix.includes - - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - Must select one file in the IDE or set profile.class - This target only works when run from inside the NetBeans IDE. - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set run.class - - - - - - Must select some files in the IDE or set test.includes - - - - - Must select one file in the IDE or set run.class - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select some files in the IDE or set javac.includes - - - - - - - - - - - - - - - - - - Some tests failed; see details above. - - - - - - - - - Must select some files in the IDE or set test.includes - - - - Some tests failed; see details above. - - - - Must select some files in the IDE or set test.class - Must select some method in the IDE or set test.method - - - - Some tests failed; see details above. - - - - - Must select one file in the IDE or set test.class - - - - Must select one file in the IDE or set test.class - Must select some method in the IDE or set test.method - - - - - - - - - - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libsrc/jpproxy/nbproject/genfiles.properties b/libsrc/jpproxy/nbproject/genfiles.properties deleted file mode 100644 index c37be34a0..000000000 --- a/libsrc/jpproxy/nbproject/genfiles.properties +++ /dev/null @@ -1,8 +0,0 @@ -nbbuild.xml.data.CRC32=0a5363c8 -nbbuild.xml.script.CRC32=2eebe506 -nbbuild.xml.stylesheet.CRC32=8064a381@1.74.2.48 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=0a5363c8 -nbproject/build-impl.xml.script.CRC32=6f75ce45 -nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48 diff --git a/libsrc/jpproxy/nbproject/project.properties b/libsrc/jpproxy/nbproject/project.properties deleted file mode 100644 index e41c2ecde..000000000 --- a/libsrc/jpproxy/nbproject/project.properties +++ /dev/null @@ -1,74 +0,0 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -application.title=JPProxy -application.vendor=JPEXS -build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=build -build.generated.dir=${build.dir}/generated -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -buildfile=nbbuild.xml -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=${dist.dir}/JPProxy.jar -dist.javadoc.dir=${dist.dir}/javadoc -endorsed.classpath= -excludes= -file.reference.jpproxy-src=src -includes=** -jar.compress=false -javac.classpath= -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=false -javac.processorpath=\ - ${javac.classpath} -javac.source=1.5 -javac.target=1.5 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.junit.classpath}:\ - ${libs.junit_4.classpath} -javac.test.processorpath=\ - ${javac.test.classpath} -javadoc.additionalparam= -javadoc.author=false -javadoc.encoding=${source.encoding} -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=false -javadoc.windowtitle= -main.class=com.jpexs.proxy.Main -manifest.file=manifest.mf -meta.inf.dir=${src.dir}/META-INF -platform.active=default_platform -run.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -# Space-separated list of JVM arguments used when running the project -# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value -# or test-sys-prop.name=value to set system properties for unit tests): -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=${file.reference.jpproxy-src} diff --git a/libsrc/jpproxy/nbproject/project.xml b/libsrc/jpproxy/nbproject/project.xml deleted file mode 100644 index 0c1291edb..000000000 --- a/libsrc/jpproxy/nbproject/project.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - org.netbeans.modules.java.j2seproject - - - JPProxy - - - - - - - diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/ByteArray.java b/libsrc/jpproxy/src/com/jpexs/proxy/ByteArray.java deleted file mode 100644 index 7164a5f4b..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/ByteArray.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.jpexs.proxy; - -import java.io.IOException; -import java.io.OutputStream; - -public class ByteArray { - - public byte[] bytes; - public int offset = 0; - - /** - * Create a ByteArray with the default size. - */ - public ByteArray() { - this(512); - } - - /** - * Create a ByteArray with a specific default size. - */ - public ByteArray(int size) { - bytes = new byte[size]; - } - - /** - * Create a ByteArray from a String. - */ - public ByteArray(String s) { - this(s.length()); - append(s); - } - - /** - * Create a ByteArray from an array of bytes. - */ - public ByteArray(byte[] b) { - this(b.length); - append(b); - } - - /** - * Append a byte. - */ - public void append(byte ch) { - if (offset == bytes.length) { - byte[] tmpbytes = bytes; - bytes = new byte[tmpbytes.length * 2]; - System.arraycopy(tmpbytes, 0, bytes, 0, offset); - } - bytes[offset++] = ch; - } - - /** - * Append a ByteArray. - */ - public void append(ByteArray b) { - if (bytes.length - offset < b.length()) { - byte[] tmpbytes = bytes; - bytes = new byte[tmpbytes.length + b.length()]; - System.arraycopy(tmpbytes, 0, bytes, 0, offset); - } - System.arraycopy(b.bytes, 0, bytes, offset, b.length()); - offset += b.length(); - } - - /** - * Append an array of bytes. - */ - public void append(byte[] b) { - if (bytes.length - offset < b.length) { - byte[] tmpbytes = bytes; - bytes = new byte[tmpbytes.length + b.length]; - System.arraycopy(tmpbytes, 0, bytes, 0, offset); - } - System.arraycopy(b, 0, bytes, offset, b.length); - offset += b.length; - } - - /** - * Append a String. - */ - public void append(String s) { - append(s.getBytes()); - } - - /** - * Convert to String. - */ - public String toString() { - return new String(bytes, 0, offset); - } - - /** - * Return the bytes. - */ - public byte[] getBytes() { - return bytes; - } - - public void writeTo(OutputStream out) - throws IOException { - out.write(bytes, 0, offset); - } - - public byte get(int i) { - return bytes[i]; - } - - /** - * Return the number of bytes. - */ - public int length() { - return offset; - } - - public void erase() { - offset = 0; - } - - public void chop() { - chop(1); - } - - public void chop(int i) { - offset -= i; - if (offset < 0) { - offset = 0; - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/CatchedListener.java b/libsrc/jpproxy/src/com/jpexs/proxy/CatchedListener.java deleted file mode 100644 index 3c8500248..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/CatchedListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.jpexs.proxy; - -import java.io.InputStream; - -/** - * Interface to catch contentTypes - * - * @author JPEXS - */ -public interface CatchedListener { - - /** - * Method called when specified contentType is received - * - * @param contentType Content type - * @param url URL of the method - * @param data Data stream - * @return replacement data - */ - public byte[] catched(String contentType, String url, InputStream data); -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Cleanable.java b/libsrc/jpproxy/src/com/jpexs/proxy/Cleanable.java deleted file mode 100644 index 3ca64b958..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Cleanable.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.jpexs.proxy; - -public interface Cleanable { - - public void clean(); -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Client.java b/libsrc/jpproxy/src/com/jpexs/proxy/Client.java deleted file mode 100644 index 9324456b4..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Client.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jpexs.proxy; - -import java.io.*; -import java.net.Socket; - -public class Client extends Connection { - - @Override - public void promoteToServerSSL() { - super.promoteToServerSSL(); - in = new BufferedInputStream(in); - out = new BufferedOutputStream(out); - } - - /** - * Create a Client from a Socket. - */ - Client(Socket s) throws IOException { - super(s); - in = new BufferedInputStream(in); - //out = new DebugOutputStream(new BufferedOutputStream(out)); - out = new BufferedOutputStream(out); - } - - /** - * Read a Request. - * - * @returns a Request. - * @see Request - */ - Request read() throws IOException { - Request request = new Request(this); - request.read(getInputStream()); - return request; - } - - /** - * Write a Reply - * - * @see Reply - */ - void write(Reply reply) throws IOException { - reply.write(getOutputStream()); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Connection.java b/libsrc/jpproxy/src/com/jpexs/proxy/Connection.java deleted file mode 100644 index 3a4d107f1..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Connection.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.jpexs.proxy; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.Socket; -import java.net.SocketException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; - -class Connection { - - Socket socket = null; - InputStream in = null; - OutputStream out = null; - static SSLSocketFactory sf; - - static { - String ksName = ProxyConfig.httpsKeyStoreFile; - if (ksName != null) { - char[] ksPass = ProxyConfig.httpsKeyStorePass.toCharArray(); - char[] ctPass = ProxyConfig.httpsKeyPass.toCharArray(); - try { - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(ksName), ksPass); - KeyManagerFactory kmf - = KeyManagerFactory.getInstance("SunX509"); - kmf.init(ks, ctPass); - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(kmf.getKeyManagers(), null, null); - sf = sc.getSocketFactory(); - } catch (Exception ex) { - - } - } - } - - public void promoteToClientSSL() { - SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault(); - try { - socket = (SSLSocket) f.createSocket(socket, null, socket.getPort(), false); - in = socket.getInputStream(); - out = socket.getOutputStream(); - } catch (IOException ex) { - - } - - } - - public void promoteToServerSSL() { - try { - socket = sf.createSocket(socket, null, socket.getPort(), false); - ((SSLSocket) socket).setUseClientMode(false); - } catch (Exception ex) { - ex.printStackTrace(); - } - try { - in = socket.getInputStream(); - out = socket.getOutputStream(); - } catch (IOException ex) { - - } - - } - - /** - * Create a Connection from a Socket. - * - * @param socket a socket - */ - Connection(Socket socket) throws IOException { - this.socket = socket; - in = socket.getInputStream(); - out = socket.getOutputStream(); - } - - /** - * Create a Connection from a hostname and port. - * - * @param host remote hostname - * @param port remote port - */ - Connection(String host, int port) throws IOException { - this(new Socket(InetAddress.getByName(host), port)); - } - - Connection() { - } - - /** - * Return the input stream. - */ - InputStream getInputStream() { - return in; - } - - /** - * Return the output stream. - */ - OutputStream getOutputStream() { - return out; - } - - void setInputStream(InputStream in) { - this.in = in; - } - - void setOutputStream(OutputStream out) { - this.out = out; - } - - /** - * Close the connection. - */ - void close() { - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - - } - } - } - - public Socket getSocket() { - return socket; - } - - public InetAddress getInetAddress() { - return socket.getInetAddress(); - } - - public int getPort() { - return socket.getPort(); - } - - public String toString() { - return getInetAddress().getHostAddress() + ":" + getPort(); - } - - public void setTimeout(int timeout) - throws SocketException { - socket.setSoTimeout(timeout); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Copy.java b/libsrc/jpproxy/src/com/jpexs/proxy/Copy.java deleted file mode 100644 index 6a54f405b..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Copy.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.jpexs.proxy; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; -import java.net.SocketException; - -class Copy implements Runnable { - - InputStream in = null; - OutputStream out = null; - - Copy(InputStream in, OutputStream out) { - this.in = in; - this.out = out; - } - - public void run() { - int n; - byte[] buffer = new byte[8192]; - - try { - while ((n = in.read(buffer, 0, buffer.length)) > 0) { - out.write(buffer, 0, n); - out.flush(); - } - out.flush(); - } catch (SocketException e) { - } catch (IOException e) { - //Ignore errors - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Handler.java b/libsrc/jpproxy/src/com/jpexs/proxy/Handler.java deleted file mode 100644 index 2b8b20e35..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Handler.java +++ /dev/null @@ -1,665 +0,0 @@ -package com.jpexs.proxy; - -import java.io.*; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.*; -import java.net.Socket; -import java.net.SocketTimeoutException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; -import javax.net.ssl.SSLHandshakeException; - -class Handler implements Runnable { - - static final boolean DEBUG = false; - - Client client = null; - Socket socket = null; - Request request = null; - Reply reply = null; - HttpRelay http = null; - int currentLength = -1; - int contentLength = -1; - long idle = 0; - double bytesPerSecond = 0; - - List replacements; - CatchedListener catchedListener; - List catchedContentTypes; - ReplacedListener replacedListener; - - static int curId = 0; - int id; - - /** - * Create a Handler. - */ - Handler(Socket socket, List replacements, List catchedContentTypes, CatchedListener catchedListener, ReplacedListener replacedListener) { - curId++; - id = curId; - this.socket = socket; - this.replacements = replacements; - this.catchedListener = catchedListener; - this.catchedContentTypes = catchedContentTypes; - this.replacedListener = replacedListener; - } - - /** - * Close all connections associated with this handler. - */ - synchronized void close() { - if (client != null) { - client.close(); - client = null; - } - if (http != null) { - http.close(); - http = null; - } - } - - /** - * Flush all data to the client. - */ - void flush() { - if (client != null) { - try { - client.getOutputStream().flush(); - } catch (IOException e) { - - } - } - } - - public void run() { - boolean keepAlive = false; - Exception reason = null; - - Thread.currentThread().setName("Handler(" - + socket.getInetAddress().getHostAddress() - + ")"); - - try { - client = new Client(socket); - client.setTimeout(ProxyConfig.readTimeout); - } catch (IOException e) { - - return; - } - - try { - boolean secure = false; - int securePort = 443; - String secureServer = ""; - do { - request = null; - reply = null; - idle = System.currentTimeMillis(); - - try { - request = client.read(); - if (secure) { - request.addSecureHostToURL(secureServer); - } - } catch (SSLHandshakeException she) { - she.printStackTrace(); - break; - } catch (IOException e) { - - break; - } - - if (request.getCommand().equals("CONNECT")) { - secureServer = request.getHost(); - securePort = request.getPort(); - if ((ProxyConfig.httpsMode == ProxyConfig.HTTPS_FILTER) || ((ProxyConfig.httpsMode == ProxyConfig.HTTPS_FILTERLIST) && (ProxyConfig.enabledHttpsServers.contains(secureServer)))) { - secure = true; - reply = new Reply(); - reply.statusLine = "HTTP/1.0 200 Connection established"; - reply.setHeaderField("Proxy-agent", ProxyConfig.appName); - try { - client.write(reply); - } catch (IOException ex) { - - } - client.promoteToServerSSL(); - keepAlive = true; - continue; - } - } - - idle = 0; - - try { - keepAlive = processRequest(secure, secureServer, securePort); - } catch (IOException ioe) { - reason = ioe; - keepAlive = false; - } - - if (request != null && reply != null) { - // XXX insert the number of bytes read into the - // reply content-length for logging. - if (reply != null && currentLength > 0) { - reply.setHeaderField("Content-length", currentLength); - } - - } - } while (keepAlive); - } finally { - - } - - if (reason != null && reason.getMessage().indexOf("Broken pipe") == -1) { - if (client != null && request != null) { - error(client.getOutputStream(), reason, request); - } - - } - - close(); - } - - boolean processRequest(boolean secure, String secureHost, int securePort) throws IOException { - boolean keepAlive = false; - - while (reply == null) { - //boolean secure = false; - boolean uncompress = false; - - if (request.getCommand().equals("CONNECT")) { - secure = true; - } else if (request.getURL().startsWith("/")) { - - } else if (request.getURL().startsWith("https://") && (secure)) { - - } else if (!request.getURL().startsWith("http://")) { - - return false; - } - - /* Client wants Keep-Alive */ - if (ProxyConfig.proxyKeepAlive) { - keepAlive = (request.containsHeaderField("Proxy-Connection") - && request.getHeaderField("Proxy-Connection").equals("Keep-Alive")); - } - - /* Filter the request. */ - //deleted - - /* None found. Use http or https relay. */ - if (secure) { - http = createHttpsRelay(secureHost, securePort); - } else { - http = createHttpRelay(); - } - try { - http.sendRequest(request); - if (http instanceof Http) { - ((Http) http).setTimeout(ProxyConfig.readTimeout); - } - reply = http.recvReply(request); - } catch (RetryRequestException e) { - http.close(); - http = null; - continue; /* XXX */ - - } - - /* Guess content-type if there aren't any headers. - Probably an upgraded HTTP/0.9 reply. */ - if (reply.headerCount() == 0) { - String url = request.getURL(); - if (url.endsWith("/") - || url.endsWith(".html") || url.endsWith(".htm")) { - reply.setHeaderField("Content-type", "text/html"); - } - } - - /* Filter the reply. */ - if (false) { - /* uncompress gzip encoded html so it can be filtered */ - if (!ProxyConfig.dontUncompress - && "text/html".equals(reply.getHeaderField("Content-type"))) { - String encoding = reply.getHeaderField("Content-Encoding"); - if (encoding != null && encoding.indexOf("gzip") != -1) { - reply.removeHeaderField("Content-Encoding"); - reply.removeHeaderField("Content-length"); - uncompress = true; - } - } - - //filter(reply); - } - - if (request.containsHeaderField("Connection") && (request.getHeaderField("Connection").toLowerCase().equals("keep-alive")) && reply.containsHeaderField("Connection") - && reply.getHeaderField("Connection").equals("Keep-Alive")) { - keepAlive = true; - } - reply.removeHeaderField("Proxy-Connection"); - if (keepAlive && reply.containsHeaderField("Content-length")) { - reply.setHeaderField("Proxy-Connection", "Keep-Alive"); - } else { - keepAlive = false; - } - - currentLength = -1; - contentLength = -1; - try { - contentLength = Integer.parseInt(reply.getHeaderField("Content-length")); - } catch (NumberFormatException e) { - } - - if (http instanceof HttpsThrough) { - HttpsThrough https = (HttpsThrough) http; - int timeout = ProxyConfig.readTimeout; - - client.write(reply); - - try { - client.setTimeout(timeout); - https.setTimeout(timeout); - - Copy cp = new Copy(client.getInputStream(), https.getOutputStream()); - ReusableThread thread = Server.getThread(); - thread.setRunnable(cp); - flushCopy(https.getInputStream(), client.getOutputStream(), -1, true); - client.close(); - } catch (InterruptedIOException iioe) { - // ignore socket timeout exceptions - } - } else if (reply.hasContent()) { - try { - processContent(uncompress); - } catch (IOException e) { - if (http instanceof Http) { - ((Http) http).reallyClose(); - } else { - http.close(); - } - http = null; - - client.close(); - client = null; - - throw e; - //return false; /* XXX */ - } - /* Document contains no data. */ - if (contentLength == 0) { - client.close(); - } - } else { - client.write(reply); - } - - http.close(); - } - - return keepAlive; - } - - HttpRelay createHttpsRelay(String secureHost, int securePort) throws IOException { - HttpRelay http; - - if ((ProxyConfig.httpsMode == ProxyConfig.HTTPS_FILTER) || ((ProxyConfig.httpsMode == ProxyConfig.HTTPS_FILTERLIST) && (ProxyConfig.enabledHttpsServers.contains(secureHost)))) { - if (ProxyConfig.useHTTPSProxy) { - http = Https.open(ProxyConfig.httpsProxyHost, ProxyConfig.httpsProxyPort, true); - Request connectReq = new Request(null); - connectReq.setStatusLine("CONNECT " + secureHost + ":" + securePort + " HTTP/1.1"); - connectReq.setCommand("CONNECT"); - connectReq.setURL(secureHost + ":" + securePort); - connectReq.setProtocol("HTTP/1.1"); - try { - http.sendRequest(connectReq); - Reply rep = http.recvReply(connectReq); - } catch (RetryRequestException ex) { - - } - ((Https) http).promoteToClientSSL(); - } else { - http = Https.open(secureHost, securePort, false); - ((Https) http).promoteToClientSSL(); - } - /*http = new Http(request.getHost(),request.getPort(),ProxyConfig.useHTTPSProxy); - if(ProxyConfig.useHTTPSProxy){ - Request connectReq=new Request(client); - connectReq.setCommand("CONNECT"); - connectReq.setURL(secureHost+":"+securePort); - connectReq.setProtocol("HTTP/1.1"); - try { - http.sendRequest(connectReq); - http.recvReply(connectReq); - } catch (RetryRequestException ex) { - - } - } - ((Http)http).promoteToClientSSL();*/ - } else { - if (ProxyConfig.useHTTPSProxy) { - http = new HttpsThrough(ProxyConfig.httpsProxyHost, - ProxyConfig.httpsProxyPort, - true); - } else { - http = new HttpsThrough(secureHost, securePort); - } - } - - return http; - } - - HttpRelay createHttpRelay() throws IOException { - HttpRelay http; - - if (ProxyConfig.useHTTPProxy) { - http = Http.open(ProxyConfig.httpProxyHost, - ProxyConfig.httpProxyPort, - true); - } else { - http = Http.open(request.getHost(), request.getPort()); - } - - return http; - } - - InputStream readChunkedTransfer(InputStream in) throws IOException { - ByteArrayOutputStream chunks = new ByteArrayOutputStream(8192); - int size = 0; - - contentLength = 0; - while ((size = reply.getChunkSize(in)) > 0) { - contentLength += size; - copy(in, chunks, size, true); - reply.readLine(in); - } - reply.getChunkedFooter(in); - - reply.removeHeaderField("Transfer-Encoding"); - reply.setHeaderField("Content-length", contentLength); - - return new ByteArrayInputStream(chunks.toByteArray()); - } - - private static DateFormat httpDateFormat() { - DateFormat httpDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); - httpDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - return httpDateFormat; - } - - void disableReplyCaching() { - reply.removeHeaderField("Cache-Control"); - reply.removeHeaderField("Last-Modified"); - reply.removeHeaderField("Expires"); - reply.removeHeaderField("Date"); - reply.removeHeaderField("ETag"); - reply.removeHeaderField("Pragma"); - - reply.setHeaderField("Pragma", "no-cache"); - reply.setHeaderField("Cache-Control", "no-cache, must-revalidate"); - Calendar now = Calendar.getInstance(); - reply.setHeaderField("Expires", httpDateFormat().format(now.getTime()));//"Sat, 26 Jul 1997 05:00:00 GMT"); - reply.setHeaderField("Last-Modified", "Sat, 26 Jul 1997 05:00:00 GMT"); - } - - void processContent(boolean uncompress) throws IOException { - InputStream in; - boolean chunked = false; - - if (reply.containsHeaderField("Transfer-Encoding") - && reply.getTransferEncoding().equals("chunked")) { - in = readChunkedTransfer(reply.getContent()); - chunked = true; - } else { - in = reply.getContent(); - } - - if (in == null) { - - return; - } else if (uncompress) { - in = new GZIPInputStream(in); - } - - String url = request.getURL(); - boolean replaced = false; - for (Replacement r : replacements) { - if (r.matches(url)) { - r.lastAccess = Calendar.getInstance(); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - try { - FileInputStream fis = new FileInputStream(r.targetFile); - byte[] buf = new byte[4096]; - int pos = 0; - while ((pos = fis.read(buf)) > 0) { - buffer.write(buf, 0, pos); - } - fis.close(); - buffer.close(); - } catch (IOException ex) { - - } - byte[] bytes = buffer.toByteArray(); - contentLength = bytes.length; - reply.setHeaderField("Content-length", contentLength); - disableReplyCaching(); - client.write(reply); - copy(new ByteArrayInputStream(bytes), - client.getOutputStream(), contentLength, false); - replaced = true; - if (replacedListener != null) { - replacedListener.replaced(r, request.getURL(), reply.getContentType()); - } - break; - } - } - - if (!replaced) { - - String contentType = reply.getHeaderField("Content-type"); - if (reply.getStatusCode() == 200) { - if (contentType != null) { - for (String ct : catchedContentTypes) { - String convContentType = contentType; - if (convContentType.contains(";")) { - convContentType = convContentType.substring(0, convContentType.indexOf(";")); - } - - if (ct.toLowerCase().equals(convContentType.toLowerCase())) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - copy(in, baos, contentLength, true); - byte[] data = baos.toByteArray(); - if (catchedListener != null) { - byte[] newData = catchedListener.catched(ct, request.getURL(), new ByteArrayInputStream(data)); - if (newData != null) { - data = newData; - contentLength = data.length; - reply.setHeaderField("Content-length", contentLength); - } - } - in = new ByteArrayInputStream(data); - disableReplyCaching(); - break; - } - } - } - } - client.write(reply); - copy(in, client.getOutputStream(), contentLength, true); - } - } - - /** - * Return the content length. - */ - int getTotalBytes() { - return contentLength > 0 ? contentLength : 0; - } - - /** - * Return the number of bytes read so far. - */ - int getCurrentBytes() { - return currentLength > 0 ? currentLength : 0; - } - - /** - * Send a error message to the client. - * - * @param out client - * @param e exception that occurred - * @param r request - */ - void error(OutputStream out, Exception e, Request r) { - StringBuffer buf = new StringBuffer(); - buf.append("While trying to retrieve the URL: " + r.getURL() + "\r\n"); - buf.append("

\r\nThe following error was encountered:\r\n

\r\n"); - buf.append("

  • " + e.toString() + "
\r\n"); - String s = new HttpError(400, buf.toString()).toString(); - try { - out.write(s.getBytes(), 0, s.length()); - out.flush(); - } catch (Exception ex) { - } - } - - /** - * Copy in to out. - * - * @param in InputStream - * @param out OutputStream - * @param monitored Update the Monitor - */ - void copy(InputStream in, OutputStream out, int length, boolean monitored) - throws IOException { - if (length == 0) { - return; - } - - int n; - byte[] buffer = new byte[8192]; - long start = System.currentTimeMillis(); - long now = 0, then = start; - - bytesPerSecond = 0; - - if (monitored) { - currentLength = 0; - } - - for (;;) { - n = (length > 0) ? Math.min(length, buffer.length) : buffer.length; - n = in.read(buffer, 0, n); - if (n < 0) { - break; - } - - out.write(buffer, 0, n); - - if (monitored) { - currentLength += n; - - } - - now = System.currentTimeMillis(); - bytesPerSecond = currentLength / ((now - start) / 1000.0); - - // flush after 1 second - if (now - then > 1000) { - out.flush(); - } - - if (length != -1) { - length -= n; - if (length == 0) { - break; - } - } - - then = now; - } - - out.flush(); - - } - - /** - * Copy in to out. - * - * @param in InputStream - * @param out OutputStream - * @param monitored Update the Monitor - */ - void flushCopy(InputStream in, OutputStream out, int length, boolean monitored) - throws IOException { - if (length == 0) { - return; - } - - int n; - byte[] buffer = new byte[8192]; - long start = System.currentTimeMillis(); - bytesPerSecond = 0; - - if (monitored) { - currentLength = 0; - } - - for (;;) { - n = (length > 0) ? Math.min(length, buffer.length) : buffer.length; - n = in.read(buffer, 0, n); - if (n < 0) { - break; - } - - out.write(buffer, 0, n); - out.flush(); - if (monitored) { - currentLength += n; - - } - bytesPerSecond = currentLength / ((System.currentTimeMillis() - start) / 1000.0); - if (length != -1) { - length -= n; - if (length == 0) { - break; - } - } - } - out.flush(); - - } - - /** - * Return a string represenation of the hander's state. - */ - public String toString() { - StringBuffer str = new StringBuffer(); - str.append("CLIENT "); - str.append(socket.getInetAddress().getHostAddress()); - str.append(":"); - str.append(socket.getPort()); - str.append(" - "); - if (request == null) { - str.append("idle " + ((System.currentTimeMillis() - idle) / 1000.0) + " sec"); - } else { - if (reply != null && currentLength > 0) { - str.append("("); - str.append(currentLength); - if (contentLength > 0) { - str.append("/"); - str.append(contentLength); - } - str.append(" "); - str.append(((int) bytesPerSecond / 1024) + " kB/s"); - str.append(") "); - } - str.append(request.getURL()); - } - return str.toString(); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Http.java b/libsrc/jpproxy/src/com/jpexs/proxy/Http.java deleted file mode 100644 index cca9bc177..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Http.java +++ /dev/null @@ -1,284 +0,0 @@ -package com.jpexs.proxy; - -import java.io.IOException; -import java.net.Socket; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -class Http extends HttpConnection { - - /* XXX - more than 1 should work now. */ - static final int MAX_PENDING_REQUESTS = 1; - - static Hashtable cache = new Hashtable(33); - private static Object httpLock = new Object(); - - String host; - int port; - boolean proxy = false; - boolean persistent = false; - boolean closed = false; - long idle = 0; - Vector queue = new Vector(); - - public Http(String host, int port) throws IOException { - this(host, port, false); - } - - public Http(String host, int port, boolean isProxy) throws IOException { - super(host, port); - this.host = host; - this.port = port; - this.proxy = isProxy; - } - - public Http(String host, int port, boolean isProxy, Socket sock) throws IOException { - super(sock); - this.host = host; - this.port = port; - this.proxy = isProxy; - } - - public synchronized void sendRequest(Request request) - throws IOException, RetryRequestException { - queue.addElement(request); - - try { - send(request); - } catch (IOException e) { - if (persistent) { - persistent = false; - throw new RetryRequestException(); - } - throw e; - } - } - - public synchronized Reply recvReply(Request request) - throws IOException, RetryRequestException { - while (queue.firstElement() != request) { - try { - wait(); - } catch (InterruptedException e) { - } - } - - if (closed) { - throw new RetryRequestException(); - } - - try { - return recv(); - } catch (IOException e) { - if (persistent) { - persistent = false; - throw new RetryRequestException(); - } - throw e; - } - } - - public void reallyClose() { - persistent = false; - close(); - } - - public synchronized void close() { - if (persistent) { - idle = System.currentTimeMillis(); - } else { - cacheRemove(host, port, this); - super.close(); - closed = true; - } - - if (queue.size() > 0) { - queue.removeElementAt(0); - - notify(); - } - } - - private void send(Request request) throws IOException { - - /* Prepare HTTP/1.1 request */ - request.removeHeaderField("Proxy-Connection"); - - if (!proxy) { - if (request.containsHeaderField("Connection") && (request.getHeaderField("Connection").toLowerCase().equals("keep-alive"))) { - - } else { - request.setHeaderField("Connection", "open"); - } - if (!request.containsHeaderField("Host")) { - request.setHeaderField("Host", request.getHost()); - } - } - - if (proxy) { - request.write(getOutputStream()); - } else { - String oldStatusLine = request.statusLine; - StringBuffer head = new StringBuffer(); - head.append(request.getCommand()); - head.append(" "); - head.append(request.getPath()); - head.append(" "); - head.append("HTTP/1.0"); - request.statusLine = head.toString(); - - request.write(getOutputStream()); - - /* flush? */ - request.statusLine = oldStatusLine; - } - } - - private Reply recv() throws IOException { - Reply reply = new Reply(getInputStream()); - reply.read(); - - String conn = reply.getHeaderField("Connection"); - - if (reply.containsHeaderField("Connection") - && reply.getHeaderField("Connection").equals("close")) { - persistent = false; - } else if (reply.getProtocol().equals("HTTP/1.1")) { - persistent = true; - } else { - persistent = false; - } - - /* Received HTTP/1.1 "Continue". Read another Reply. */ - if (reply.getStatusCode() == 100) { - reply = recv(); - } - - return reply; - } - - protected boolean isBusy() { - return queue.size() >= MAX_PENDING_REQUESTS; - } - - protected boolean isPersistent() { - return persistent; - } - - private static String cacheKey(String host, int port) { - return host.toLowerCase() + ":" + port; - } - - private static Vector cacheLookup(String host, int port) { - Vector v = (Vector) cache.get(cacheKey(host, port)); - return v; - } - - private static boolean cacheContains(Http http) { - Vector v = (Vector) cache.get(cacheKey(http.host, http.port)); - return v != null ? v.contains(http) : false; - } - - private static void cacheInsert(String host, int port, Http http) { - String key = cacheKey(host, port); - Vector v = (Vector) cache.get(key); - if (v == null) { - v = new Vector(); - } - v.addElement(http); - cache.put(key, v); - } - - private static void cacheRemove(String host, int port, Http http) { - Vector v = (Vector) cache.get(cacheKey(host, port)); - if (v != null) { - v.removeElement(http); - if (v.isEmpty()) { - cache.remove(cacheKey(host, port)); - } - } - } - - private static void cacheClean() { - long now = System.currentTimeMillis(); - Enumeration e = cache.keys(); - while (e.hasMoreElements()) { - Vector v = (Vector) cache.get(e.nextElement()); - for (int i = 0; i < v.size(); i++) { - Http http = (Http) v.elementAt(i); - if (http.idle > 0 && now - http.idle > 30000) /* 30 seconds */ { - http.persistent = false; - http.close(); - } - } - } - } - - static Http open(String host, int port, boolean isProxy) - throws IOException { - Http http = null; - - synchronized (httpLock) { - Vector v = cacheLookup(host, port); - if (v != null) { - for (int i = 0; i < v.size(); i++) { - Http pick = (Http) v.elementAt(i); - - /* find an http connection that isn't busy */ - if (pick.isPersistent() && !pick.isBusy()) { - http = pick; - break; - } - } - - if (http != null) { - http.idle = 0; - } - } - } - - if (http == null) { - http = new Http(host, port, isProxy); - cacheInsert(host, port, http); - } - - return http; - } - - static Http open(String host, int port) throws IOException { - return open(host, port, false); - } - - static Enumeration enumerate() { - Vector list = new Vector(); - Enumeration e = cache.keys(); - while (e.hasMoreElements()) { - Vector v = (Vector) cache.get(e.nextElement()); - for (int i = 0; i < v.size(); i++) { - list.addElement(v.elementAt(i)); - } - } - return list.elements(); - } - - static synchronized void clean() { - cacheClean(); - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("SERVER "); - buf.append(super.toString()); - if (isPersistent()) { - buf.append(" - "); - if (queue.size() > 0) { - buf.append(queue.size()); - buf.append(" pending"); - } else { - buf.append("idle " + ((System.currentTimeMillis() - idle) / 1000.0) + " sec"); - } - } - return buf.toString(); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/HttpConnection.java b/libsrc/jpproxy/src/com/jpexs/proxy/HttpConnection.java deleted file mode 100644 index 14e944fd5..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/HttpConnection.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.jpexs.proxy; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; -import java.net.Socket; - -abstract class HttpConnection extends Connection implements HttpRelay { - - HttpConnection(String host, int port) throws IOException { - super(host, port); - } - - HttpConnection(Socket s) throws IOException { - super(s); - } - - public void sendRequest(Request request) - throws IOException, RetryRequestException { - request.write(getOutputStream()); - } - - public Reply recvReply(Request request) - throws IOException, RetryRequestException { - Reply reply = new Reply(getInputStream()); - reply.read(); - return reply; - } - - public void setInputStream(InputStream in) { - super.setInputStream(in); - } - - public void setOutputStream(OutputStream out) { - super.setOutputStream(out); - } - - public InputStream getInputStream() { - return super.getInputStream(); - } - - public OutputStream getOutputStream() { - return super.getOutputStream(); - } - - public void close() { - super.close(); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/HttpError.java b/libsrc/jpproxy/src/com/jpexs/proxy/HttpError.java deleted file mode 100644 index f136473d6..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/HttpError.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.jpexs.proxy; - -class HttpError { - - StringBuffer content = null; - Reply reply = null; - - HttpError(int code, String message) { - String error; - switch (code) { - case 400: - error = "Bad Request"; - break; - - case 403: - error = "Forbidden"; - break; - - case 404: - error = "Not found"; - break; - - case 503: - error = "Service Unavailable"; - break; - - default: - error = "Error"; - break; - } - - reply = new Reply(); - reply.statusLine = "HTTP/1.0 " + code + " " + error; - reply.setHeaderField("Content-type", "text/html"); - reply.setHeaderField("Server", ProxyConfig.appName + "/" + ProxyConfig.appVersion); - - content = new StringBuffer(); - content.append(message); - } - - Reply getReply() { - return reply; - } - - String getContent() { - if (content == null) { - return null; - } - return content.toString(); - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - if (reply != null) { - buf.append(reply.toString()); - } - if (content != null) { - buf.append(content.toString()); - } - return buf.toString(); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/HttpRelay.java b/libsrc/jpproxy/src/com/jpexs/proxy/HttpRelay.java deleted file mode 100644 index aed61531c..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/HttpRelay.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.jpexs.proxy; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -public interface HttpRelay { - - void sendRequest(Request request) throws IOException, RetryRequestException; - - Reply recvReply(Request request) throws IOException, RetryRequestException; - - void close(); -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Https.java b/libsrc/jpproxy/src/com/jpexs/proxy/Https.java deleted file mode 100644 index 27da62bd8..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Https.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.jpexs.proxy; - -import java.io.IOException; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -/** - * - * @author JPEXS - */ -public class Https extends Http { - /* XXX - more than 1 should work now. */ - - static final int MAX_PENDING_REQUESTS = 1; - - static Hashtable cache = new Hashtable(33); - private static Object httpLock = new Object(); - - public Https(String host, int port) throws IOException { - this(host, port, false); - } - - public Https(String host, int port, boolean isProxy) throws IOException { - super(host, port, isProxy); - } - - private static String cacheKey(String host, int port) { - return host.toLowerCase() + ":" + port; - } - - private static Vector cacheLookup(String host, int port) { - Vector v = (Vector) cache.get(cacheKey(host, port)); - return v; - } - - private static boolean cacheContains(Https http) { - Vector v = (Vector) cache.get(cacheKey(http.host, http.port)); - return v != null ? v.contains(http) : false; - } - - private static void cacheInsert(String host, int port, Https http) { - String key = cacheKey(host, port); - Vector v = (Vector) cache.get(key); - if (v == null) { - v = new Vector(); - } - v.addElement(http); - cache.put(key, v); - } - - private static void cacheRemove(String host, int port, Https http) { - Vector v = (Vector) cache.get(cacheKey(host, port)); - if (v != null) { - v.removeElement(http); - if (v.isEmpty()) { - cache.remove(cacheKey(host, port)); - } - } - } - - private static void cacheClean() { - long now = System.currentTimeMillis(); - Enumeration e = cache.keys(); - while (e.hasMoreElements()) { - Vector v = (Vector) cache.get(e.nextElement()); - for (int i = 0; i < v.size(); i++) { - Https http = (Https) v.elementAt(i); - if (http.idle > 0 && now - http.idle > 30000) /* 30 seconds */ { - http.persistent = false; - http.close(); - } - } - } - } - - static Https open(String host, int port, boolean isProxy) - throws IOException { - Https http = null; - - synchronized (httpLock) { - Vector v = cacheLookup(host, port); - if (v != null) { - for (int i = 0; i < v.size(); i++) { - Https pick = (Https) v.elementAt(i); - - /* find an http connection that isn't busy */ - if (pick.isPersistent() && !pick.isBusy()) { - http = pick; - break; - } - } - - if (http != null) { - http.idle = 0; - } - } - } - - if (http == null) { - http = new Https(host, port, isProxy); - cacheInsert(host, port, http); - } - - return http; - } - - static Https open(String host, int port) throws IOException { - return open(host, port, false); - } - - static Enumeration enumerate() { - Vector list = new Vector(); - Enumeration e = cache.keys(); - while (e.hasMoreElements()) { - Vector v = (Vector) cache.get(e.nextElement()); - for (int i = 0; i < v.size(); i++) { - list.addElement(v.elementAt(i)); - } - } - return list.elements(); - } - - static synchronized void clean() { - cacheClean(); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/HttpsThrough.java b/libsrc/jpproxy/src/com/jpexs/proxy/HttpsThrough.java deleted file mode 100644 index ebf3fa6ef..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/HttpsThrough.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.jpexs.proxy; - -import java.io.IOException; - -class HttpsThrough extends HttpConnection { - - boolean proxy = false; - - HttpsThrough(String host, int port) throws IOException { - super(host, port); - } - - HttpsThrough(String host, int port, boolean isProxy) throws IOException { - this(host, port); - proxy = isProxy; - } - - public void sendRequest(Request request) - throws IOException, RetryRequestException { - if (proxy) { - super.sendRequest(request); - } else { - /* nothing */ - } - } - - public Reply recvReply(Request request) - throws java.io.IOException, RetryRequestException { - Reply reply = new Reply(getInputStream()); - if (proxy) { - reply.read(); - } else { - reply.statusLine = "HTTP/1.0 200 Connection established"; - reply.setHeaderField("Proxy-agent", ProxyConfig.appName); - } - - return reply; - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Janitor.java b/libsrc/jpproxy/src/com/jpexs/proxy/Janitor.java deleted file mode 100644 index 53b2382bb..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Janitor.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.jpexs.proxy; - -import java.util.Enumeration; -import java.util.Vector; - -class Janitor implements Runnable { - - private Vector cleanable = new Vector(); - - public void add(Cleanable c) { - cleanable.addElement(c); - } - - public void run() { - Thread.currentThread().setName("Janitor"); - - for (;;) { - try { - Thread.sleep(30 * 1000); /* 30 seconds */ - - } catch (Exception e) { - - } - - for (Enumeration e = cleanable.elements(); - e.hasMoreElements();) { - ((Cleanable) e.nextElement()).clean(); - } - - Http.clean(); - - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Key.java b/libsrc/jpproxy/src/com/jpexs/proxy/Key.java deleted file mode 100644 index 18fca5321..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Key.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.jpexs.proxy; - -class Key { - - private String name = null; - - /** - * Create a Key. - */ - Key(String name) { - this.name = name; - } - - /** - * Return a lowercase hashCode. - */ - public int hashCode() { - String s = name.toLowerCase(); - return s.hashCode(); - } - - /** - * Return a lowercase equals. - */ - public boolean equals(Object obj) { - return name.equalsIgnoreCase(obj.toString()); - } - - /** - * Return the key. - */ - public String toString() { - return name; - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Main.java b/libsrc/jpproxy/src/com/jpexs/proxy/Main.java deleted file mode 100644 index f690e36b6..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Main.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.jpexs.proxy; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -public class Main { - - public static final String REPLACEMENTSFILE = "." + File.separator + "config" + File.separator + "replacements.ini"; - public static boolean DEBUG_MODE = false; - - public static void main(String[] argv) { - List replacements = new ArrayList(); - if ((new File(REPLACEMENTSFILE)).exists()) { - try { - BufferedReader br = new BufferedReader(new FileReader(REPLACEMENTSFILE)); - String s = ""; - while ((s = br.readLine()) != null) { - String fileName = br.readLine(); - if (fileName == null) { - break; - } - fileName = fileName.replaceAll("[\\\\/]", File.separator); - Replacement r = new Replacement(s, fileName); - if (DEBUG_MODE) { - System.out.println("Added Replacement: " + r.urlPattern + " => " + r.targetFile); - } - replacements.add(r); - } - br.close(); - } catch (IOException e) { - - } - } else { - if (DEBUG_MODE) { - System.out.println("WARNING:REPLACEMENTS FILE NOT FOUND."); - } - } - Server.startServer(ProxyConfig.port, replacements, new ArrayList(), new CatchedListener() { - - /** - * Method called when specified contentType is received - * - * @param contentType Content type - * @param url URL of the method - * @param data Data stream - */ - public byte[] catched(String contentType, String url, InputStream data) { - return null; - } - }, new ReplacedListener() { - - public void replaced(Replacement replacement, String url, String contentType) { - if (DEBUG_MODE) { - System.out.println("REPLACED:" + url + " (Content-type:" + contentType + ") WITH FILE " + replacement.targetFile); - } - } - }); - - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Message.java b/libsrc/jpproxy/src/com/jpexs/proxy/Message.java deleted file mode 100644 index 42c34aabb..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Message.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.jpexs.proxy; - -import java.util.Hashtable; -import java.util.Enumeration; -import java.util.Vector; -import java.io.*; - -public abstract class Message { - - /** - * Hashtable used to store message headers. - */ - private Hashtable headers = new Hashtable(33); - - /** - * - */ - String statusLine = null; - - public String readLine(InputStream in) throws IOException { - char[] buf = new char[128]; - int offset = 0; - int ch; - - for (;;) { - ch = in.read(); - if (ch == -1 || ch == '\n') { - break; - } else if (ch == '\r') { - int tmpch = in.read(); - if (tmpch != '\n') { - if (!(in instanceof PushbackInputStream)) { - in = new PushbackInputStream(in); - } - ((PushbackInputStream) in).unread(tmpch); - } - break; - } else { - if (offset == buf.length) { - char[] tmpbuf = buf; - buf = new char[tmpbuf.length * 2]; - System.arraycopy(tmpbuf, 0, buf, 0, offset); - } - buf[offset++] = (char) ch; - } - } - return String.copyValueOf(buf, 0, offset); - } - - /** - * Read headers and store them in the hashtable. - */ - void readHeaders(InputStream in) throws IOException { - int i; - Key key = null; - - for (;;) { - String s = readLine(in); - if (s == null) { - break; - } - i = s.indexOf(':'); - if (i == -1) { - /* end of header */ - if (s.length() == 0) { - break; - } /* multi-line headers */ else if (key != null - && (s.startsWith(" ") || s.startsWith("\t"))) { - int index = getHeaderValueCount(key.toString()); - index--; - Vector v = (Vector) headers.get(key); - v.setElementAt(v.elementAt(index) + "\n" + s, index); - } - } else { - key = new Key(s.substring(0, i)); - Vector v; - if (headers.containsKey(key)) { - v = (Vector) headers.get(key); - } else { - v = new Vector(); - } - v.addElement(s.substring(i + 1).trim()); - headers.put(key, v); - } - } - } - - public int headerCount() { - return headers.size(); - } - - /** - * Set the Status line. - */ - public void setStatusLine(String l) { - statusLine = l; - } - - public int getHeaderValueCount(String name) { - Vector v = (Vector) headers.get(new Key(name)); - return v.size(); - } - - public String getHeaderField(String name) { - return getHeaderField(name, 0); - } - - public String getHeaderField(String name, int index) { - Vector v = (Vector) headers.get(new Key(name)); - if (v == null) { - return null; - } - return (String) v.elementAt(index); - } - - public void setHeaderField(String name, String value) { - setHeaderField(name, value, 0); - } - - public void setHeaderField(String name, String value, int index) { - Vector v; - Key key = new Key(name); - - if (headers.containsKey(key)) { - v = (Vector) headers.get(key); - } else { - v = new Vector(); - if (index == 0) { - v.addElement(""); - } - headers.put(key, v); - } - v.setElementAt(value, index); - } - - public void setHeaderField(String name, int value) { - setHeaderField(name, value, 0); - } - - public void setHeaderField(String name, int value, int index) { - setHeaderField(name, new Integer(value).toString(), index); - } - - /** - * Set all header fields with the give name to the specified value. - */ - public void setHeaderFields(String name, String value) { - Vector v; - Key key = new Key(name); - - v = (Vector) headers.get(key); - if (v != null) { - for (int i = 0; i < v.size(); i++) { - v.setElementAt(value, i); - } - } - } - - public void appendHeaderField(String name, String value) { - appendHeaderField(name, value, 0); - } - - public void appendHeaderField(String name, String value, int index) { - setHeaderField(name, getHeaderField(name, index) + value, index); - } - - public void removeHeaderField(String name) { - headers.remove(new Key(name)); - } - - /** - * Return whether or not a header exists. - * - * @param name header name - */ - public boolean containsHeaderField(String name) { - return headers.containsKey(new Key(name)); - } - - /** - * @return an Enumeration of Strings - */ - public Enumeration getHeaders() { - Vector v = new Vector(); - - for (Enumeration e = headers.keys(); e.hasMoreElements();) { - v.addElement(e.nextElement().toString()); - } - - return v.elements(); - } - - private final static byte[] COLON_SPACE = ": ".getBytes(); - private final static byte[] CRLF = "\r\n".getBytes(); - - private ByteArray toByteArray(byte[] sep) { - ByteArray buf = new ByteArray(); - Key key; - String value; - Vector v; - int i = 0; - - buf.append(statusLine); - buf.append(sep); - - for (Enumeration e = headers.keys(); e.hasMoreElements();) { - key = (Key) e.nextElement(); - v = (Vector) headers.get(key); - for (i = 0; i < v.size(); i++) { - buf.append(key.toString()); - buf.append(COLON_SPACE); - buf.append(v.elementAt(i).toString()); - buf.append(sep); - } - } - buf.append(sep); - - return buf; - } - - private ByteArray toByteArray() { - return toByteArray(CRLF); - } - - private ByteArray toByteArray(String sep) { - return toByteArray(sep.getBytes()); - } - - public String toString() { - return toByteArray().toString(); - } - - public String toString(String sep) { - return toByteArray(sep).toString(); - } - - public void write(OutputStream out) - throws IOException { - toByteArray().writeTo(out); - out.flush(); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/ProxyConfig.java b/libsrc/jpproxy/src/com/jpexs/proxy/ProxyConfig.java deleted file mode 100644 index 4b3ac637d..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/ProxyConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.jpexs.proxy; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ProxyConfig { - - public static boolean dontLogFilters = false; - - public static String appVersion = "1.1"; - public static String appName = "JPProxy"; - public static int port = 55555; - public static String bindAddress; - - public static int readTimeout = 50000; - public static boolean proxyKeepAlive = false; - public static boolean dontUncompress = false; - - public static final int HTTPS_PASSTHRU = 0; - public static final int HTTPS_FILTER = 1; - public static final int HTTPS_FILTERLIST = 2; - - public static int httpsMode = HTTPS_PASSTHRU; - - public static List enabledHttpsServers = new ArrayList(); - - public static boolean useHTTPSProxy = false; - public static String httpsProxyHost = ""; - public static int httpsProxyPort = 0; - - public static boolean useHTTPProxy = false; - public static String httpProxyHost = ""; - public static int httpProxyPort = 0; - - public static String httpsKeyStoreFile = null; - public static String httpsKeyStorePass = null; - public static String httpsKeyPass = null; - -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/ReplacedListener.java b/libsrc/jpproxy/src/com/jpexs/proxy/ReplacedListener.java deleted file mode 100644 index 3304e76e4..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/ReplacedListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.jpexs.proxy; - -public interface ReplacedListener { - - public void replaced(Replacement replacement, String url, String contentType); -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Replacement.java b/libsrc/jpproxy/src/com/jpexs/proxy/Replacement.java deleted file mode 100644 index c09b6030a..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Replacement.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.jpexs.proxy; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.regex.Pattern; - -/** - * Replacement of URL with local file - */ -public class Replacement { - - /** - * URL pattern, can contain * wild-cards - */ - public String urlPattern; - /** - * Filename to replace content with - */ - public String targetFile; - /** - * Date of last accesing this url - */ - public Calendar lastAccess; - - /** - * Constructor - * - * @param urlPattern URL pattern, can contain * wild-cards - * @param targetFile Filename to replace content with - */ - public Replacement(String urlPattern, String targetFile) { - this.urlPattern = urlPattern; - this.targetFile = targetFile; - } - - /** - * Returns true when urlPattern matches specified url - * - * @param url Url to test match - * @return True when matches - */ - public boolean matches(String url) { - String pat = Pattern.quote(urlPattern); - pat = pat.replace("*", "\\E.*\\Q"); - return Pattern.matches(pat, url); - } - - private static String byteCountStr(long bytes, boolean si) { - int unit = si ? 1000 : 1024; - if (bytes < unit) { - return bytes + " B"; - } - int exp = (int) (Math.log(bytes) / Math.log(unit)); - String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); - return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); - } - - /** - * Returns a string representation of the object. - * - * @return a string representation of the object. - */ - @Override - public String toString() { - SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); - - long size = new File(targetFile).length(); - String sizeS = byteCountStr(size, false); - while (sizeS.length() < 12) { - sizeS = " " + sizeS; - } - - if (lastAccess == null) { - return " " + " | " + sizeS + " | " + urlPattern; - } else { - return format.format(lastAccess.getTime()) + " | " + sizeS + " | " + urlPattern; - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Reply.java b/libsrc/jpproxy/src/com/jpexs/proxy/Reply.java deleted file mode 100644 index ce1f6b8d8..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Reply.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.jpexs.proxy; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; -import java.io.StringBufferInputStream; -import java.io.SequenceInputStream; -import java.util.Hashtable; -import java.util.StringTokenizer; - -public class Reply extends Message { - - InputStream in = null; - int statusCode = -1; - - public Reply() { - } - - public Reply(InputStream in) { - setContent(in); - } - - public void setContent(InputStream in) { - this.in = in; - } - - public InputStream getContent() { - return in; - } - - void read() throws IOException { - if (in != null) { - read(in); - } - } - - void read(InputStream in) throws IOException { - statusLine = readLine(in); - if (statusLine == null || statusLine.length() == 0) { - throw new IOException("Missing HTTP status line"); - } - - /* Look for HTTP/0.9 */ - if (!statusLine.startsWith("HTTP")) { - /* Put back the line */ - if (this.in != null) { - String putback = new String(statusLine + "\n"); - this.in = new SequenceInputStream(new StringBufferInputStream(putback), in); - } - /* Fake a status line and upgrade to HTTP/1.0 */ - statusLine = "HTTP/1.0 200 OK"; - return; - } - - readHeaders(in); - int code = getStatusCode(); - - /* RFC 2068: 204 and 304 MUST NOT contain a message body. */ - switch (code) { - case 204: /* No Content */ - - case 304: /* Not Modified */ - /* Ignore the message body if it exists */ - - if (containsHeaderField("Content-length")) { - int contentLength = 0; - try { - contentLength = Integer.parseInt(getHeaderField("Content-length")); - } catch (NumberFormatException e) { - } - int n; - byte[] buffer = new byte[8192]; - while ((n = in.read(buffer, 0, buffer.length)) > 0) { - /* ignore */ - } - removeHeaderField("Content-length"); - } - break; - } - } - - public boolean hasContent() { - switch (getStatusCode()) { - case 204: - case 304: - return false; - - default: - return true; - } - } - - public String getProtocol() { - StringTokenizer st = new StringTokenizer(statusLine); - String protocol = (String) st.nextToken(); - return protocol; - } - - public int getStatusCode() { - if (statusCode == -1) { - StringTokenizer st = new StringTokenizer(statusLine); - String protocol = (String) st.nextToken(); - String status = (String) st.nextToken(); - - try { - statusCode = Integer.parseInt(status); - } catch (NumberFormatException e) { - System.out.println("Malformed or missing status code"); - statusCode = 0; - } - } - - return statusCode; - } - - private Hashtable headerParser(String header) { - Hashtable table = new Hashtable(); - String type = getHeaderField(header); - if (type == null) { - return table; - } - - StringTokenizer st = new StringTokenizer(type, ";"); - int count = 0; - while (st.hasMoreTokens()) { - String token = st.nextToken(); - token = token.trim(); - String name; - String value; - int i = token.indexOf('='); - if (i != -1) { - name = token.substring(0, i); - value = token.substring(i + 1); - } else { - name = token; - value = ""; - } - - if (count == 0) { - table.put(header, name); - } else { - table.put(name, value); - } - - count++; - } - - return table; - } - - public String getContentType() { - Hashtable table = headerParser("Content-type"); - return (String) table.get("Content-type"); - } - - public String getBoundary() { - Hashtable table = headerParser("Content-type"); - return (String) table.get("boundary"); - } - - public String getTransferEncoding() { - Hashtable table = headerParser("Transfer-Encoding"); - return (String) table.get("Transfer-Encoding"); - } - - public int getChunkSize(InputStream in) throws IOException { - String line = readLine(in); - line = line.trim(); /* apache can have trailing spaces */ - - int size = -1; - try { - size = Integer.valueOf(line, 16).intValue(); - } catch (NumberFormatException e) { - System.out.println(e); - } - return size; - } - - public void getChunkedFooter(InputStream in) throws IOException { - for (;;) { - String line = readLine(in); - if (line == null) { - break; - } - int i = line.indexOf(':'); - if (i == -1) { - break; - } - } - } - - public void setStatusLine(String line) { - this.statusLine = line; - } - - public static Reply createRedirect(String url) { - Reply r = new Reply(); - r.setStatusLine("HTTP/1.0 302 Moved Temporarily"); - r.setHeaderField("Location", url); - return r; - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Request.java b/libsrc/jpproxy/src/com/jpexs/proxy/Request.java deleted file mode 100644 index b7630e106..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Request.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.jpexs.proxy; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; -import java.util.StringTokenizer; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -public class Request extends Message { - - private String command = null; - private String url = null; - private String protocol = null; - private byte[] data = null; - private Client client = null; - private Hashtable log; - private Vector logHeaders; - public boolean hadKeepalive = false; - - Request(Client c) { - client = c; - } - - void read(InputStream in) throws IOException { - statusLine = readLine(in); - if (statusLine == null || statusLine.length() == 0) { - throw new IOException("Empty request"); - } - - StringTokenizer st = new StringTokenizer(statusLine); - command = (String) st.nextToken(); - url = (String) st.nextToken(); - protocol = (String) st.nextToken(); - - if (!url.startsWith("http")) { - //TODO do something here - } - - readHeaders(in); - - if ("POST".equals(command) || "PUT".equals(command)) { - try { - int n = Integer.parseInt(getHeaderField("Content-length")); - data = new byte[n]; - int offset = 0; - while (offset < data.length) { - n = in.read(data, offset, data.length - offset); - if (n < 0) { - throw new IOException("Not enough " + command + " data"); - } - offset += n; - } - } catch (NumberFormatException e) { - - } - } - } - - public void write(OutputStream out) - throws IOException { - super.write(out); - if (data != null) { - out.write(data); - out.flush(); - } - } - - public String getRequest() { - return statusLine; - } - - public String getCommand() { - return command; - } - - public void setCommand(String command) { - this.command = command; - } - - public String getURL() { - return url; - } - - public void setURL(String url) { - this.url = url; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public void addSecureHostToURL(String host) { - url = "https://" + host + url; - } - - public String getHost() { - String url = getURL(); - String s; - - if (url.startsWith("http://")) { - s = url.substring(7, url.indexOf('/', 7)); - } else if (url.startsWith("https://")) { - s = url.substring(8, url.indexOf('/', 8)); - } else { - s = url; - } - - int at = s.indexOf('@'); - if (at != -1) { - s = s.substring(at + 1); - } - - if (s.indexOf(':') != -1) { - return s.substring(0, s.indexOf(':')); - } - - return s; - } - - public int getPort() { - int port = 80; - String url = getURL(); - String s; - - if (url.startsWith("http://")) { - s = url.substring(7, url.indexOf('/', 7)); - } else if (url.startsWith("https://")) { - s = url.substring(8, url.indexOf('/', 8)); - port = 443; - } else { - s = url; - } - - int at = s.indexOf('@'); - if (at != -1) { - s = s.substring(at + 1); - } - - if (s.indexOf(':') != -1) { - try { - port = Integer.parseInt(s.substring(s.indexOf(':') + 1)); - } catch (NumberFormatException e) { - - } - } - return port; - } - - public String getData() { - if (data == null) { - return null; - } - return new String(data); - } - - public String getPath() { - String str = getURL(); - int pos = 0; - for (int i = 0; i < 3; i++) { - pos = str.indexOf('/', pos); - pos++; - } - pos--; - return str.substring(pos); - } - - public String getDocument() { - String path = getPath(); - int n = path.lastIndexOf('/'); - if (n == path.length() - 1) { - n = path.lastIndexOf('/', n - 1); - } - if (n < 0) { - return "/"; - } else { - return path.substring(n + 1); - } - } - - public Client getClient() { - return client; - } - - public String getQueryString() { - String path = getPath(); - int n = path.indexOf('?'); - if (n < 0) { - return null; - } - return path.substring(n + 1); - } - - public synchronized void addLogEntry(String header, - String message) { - if (log == null) { - log = new Hashtable(); - logHeaders = new Vector(); - } - - Vector v = (Vector) log.get(header); - if (log.get(header) == null) { - v = new Vector(); - log.put(header, v); - logHeaders.addElement(header); - } - v.addElement(message); - } - - public Enumeration getLogHeaders() { - return logHeaders != null ? logHeaders.elements() : null; - } - - public Enumeration getLogEntries(String header) { - return log != null ? ((Vector) log.get(header)).elements() : null; - } - -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/RetryRequestException.java b/libsrc/jpproxy/src/com/jpexs/proxy/RetryRequestException.java deleted file mode 100644 index 873b5eb7e..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/RetryRequestException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.jpexs.proxy; - -class RetryRequestException extends Exception { - - RetryRequestException() { - super(); - } - - RetryRequestException(String message) { - super(message); - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/ReusableThread.java b/libsrc/jpproxy/src/com/jpexs/proxy/ReusableThread.java deleted file mode 100644 index 090ec7888..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/ReusableThread.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.jpexs.proxy; - -public class ReusableThread extends Thread { - - private ThreadPool pool = null; - private Runnable runnable = null; - private boolean alive = true; - private long lastrun = 0; - private int used = 0; - - public ReusableThread(ThreadPool pool) { - this.pool = pool; - } - - public synchronized void setRunnable(Runnable runnable) { - this.runnable = runnable; - notify(); - } - - public synchronized void terminate() { - alive = false; - notify(); - } - - public long getLastRunTime() { - return lastrun; - } - - public int useCount() { - return used; - } - - public void run() { - while (alive) { - setName("ReusableThread: idle"); - - while (runnable == null && alive) { - synchronized (this) { - try { - wait(); - } catch (InterruptedException ie) { - } - } - } - - if (alive) { - setName("ReusableThread: busy"); - setPriority(Thread.NORM_PRIORITY); - lastrun = System.currentTimeMillis(); - used++; - runnable.run(); - runnable = null; - pool.put(this); - } - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/Server.java b/libsrc/jpproxy/src/com/jpexs/proxy/Server.java deleted file mode 100644 index 3f0654f3a..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/Server.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.jpexs.proxy; - -import java.net.InetAddress; -import java.net.Socket; -import java.net.ServerSocket; -import java.io.IOException; -import java.io.DataOutputStream; -import java.util.List; - -public class Server implements Runnable { - - ServerSocket server = null; - boolean running = false; - - private List catchedContentTypes; - private CatchedListener catchedListener; - private ReplacedListener replacedListener; - private List replacements; - - static ThreadPool pool; - - static Server myServer; - static boolean serverRunning = false; - - static boolean stopping = false; - - public static ReusableThread getThread() { - return pool.get(); - } - - /** - * Starts proxy server - * - * @param port Listening port - * @param replacements List of replacements - * @param catchedContentTypes Content types to sniff - * @param catchedListener Catched listener - */ - public static boolean startServer(int port, List replacements, List catchedContentTypes, CatchedListener catchedListener, ReplacedListener replacedListener) { - stopServer(); - stopping = false; - try { - myServer = new Server(port, replacements, catchedContentTypes, catchedListener, replacedListener); - } catch (IOException ex) { - return false; - } - pool = new ThreadPool(ProxyConfig.appName + " Threads"); - /* Startup the Janitor */ - Janitor j = new Janitor(); - j.add(pool); - getThread().setRunnable(j); - serverRunning = true; - getThread().setRunnable(myServer); - return true; - } - - public static void stopServer() { - if (serverRunning) { - stopping = true; - serverRunning = false; - try { - myServer.server.close(); - } catch (IOException ex) { - - } - pool.clean(); - } - } - - Server(int port, List replacements, List catchedContentTypes, CatchedListener catchedListener, ReplacedListener replacedListener) throws IOException { - - this.replacements = replacements; - this.catchedContentTypes = catchedContentTypes; - this.catchedListener = catchedListener; - this.replacedListener = replacedListener; - - try { - String bindaddr = ProxyConfig.bindAddress; - if (bindaddr != null && bindaddr.length() > 0) { - server = new ServerSocket(port, 512, - InetAddress.getByName(bindaddr)); - } else { - server = new ServerSocket(port, 512); - } - } catch (IOException e) { - throw e; - } - - /* Initialize internal Httpd */ - } - - synchronized void suspend() { - running = false; - } - - synchronized void resume() { - running = true; - } - - public void run() { - Thread.currentThread().setName(ProxyConfig.appName + " Server"); - running = true; - for (;;) { - Socket socket; - - try { - socket = server.accept(); - } catch (IOException e) { - if (stopping) { - break; - } - continue; - } - - if (stopping) { - break; - } - - if (running) { - Handler h = new Handler(socket, replacements, catchedContentTypes, catchedListener, replacedListener); - ReusableThread rt = getThread(); - rt.setRunnable(h); - } else { - error(socket, 503, ProxyConfig.appName + " proxy service is suspended."); - } - } - } - - void error(Socket socket, int code, String message) { - try { - DataOutputStream out = new DataOutputStream(socket.getOutputStream()); - out.writeBytes((new HttpError(code, message)).toString()); - out.close(); - socket.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/ThreadPool.java b/libsrc/jpproxy/src/com/jpexs/proxy/ThreadPool.java deleted file mode 100644 index 86409ddcb..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/ThreadPool.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jpexs.proxy; - -import java.util.*; - -public class ThreadPool implements Cleanable { - - private String name; - private Vector pool = new Vector(); - - public ThreadPool(String name) { - this.name = name; - } - - public synchronized ReusableThread get() { - ReusableThread rt = null; - - if (pool.size() > 0) { - rt = (ReusableThread) pool.firstElement(); - pool.removeElement(rt); - } - - if (rt == null) { - rt = new ReusableThread(this); - rt.start(); - } - - return rt; - } - - public synchronized void put(ReusableThread rt) { - pool.addElement(rt); - } - - public synchronized void clean() { - long now = System.currentTimeMillis(); - - for (Enumeration e = pool.elements(); e.hasMoreElements();) { - ReusableThread rt = (ReusableThread) e.nextElement(); - if (now - rt.getLastRunTime() >= 30000) { - rt.terminate(); - pool.removeElement(rt); - } - } - } -} diff --git a/libsrc/jpproxy/src/com/jpexs/proxy/WorkerThread.java b/libsrc/jpproxy/src/com/jpexs/proxy/WorkerThread.java deleted file mode 100644 index ddc2d4075..000000000 --- a/libsrc/jpproxy/src/com/jpexs/proxy/WorkerThread.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.jpexs.proxy; - -import java.util.*; - -public class WorkerThread extends Thread { - - private Runnable task; - private String name; - - private static int nactive = 0; - private static Vector list = new Vector(); - private static int max = 10; - private static long lifetime = 900 * 1000; /* 15 minute default */ - - - private - WorkerThread() { - setDaemon(true); - } - - /** - * Sets the lifetime of an idle WorkerThread (in ms). A WorkerThread will - * remain on the idle list for this much time before exiting. This does not - * affect WorkerThreads currently idling. - */ - synchronized static void - setLifetime(long time) { - lifetime = time; - } - - /** - * Sets the maximum number of WorkerThreads that can exist at any given - * time. If this value is decreased below the current number of - * WorkerThreads, this will not take effect immediately. - */ - synchronized static void - setMaxThreads(int maxThreads) { - max = maxThreads; - } - - /** - * Obtains a WorkerThread to which a task can be assigned. If an idle - * WorkerThread is present, it is removed from the idle list and returned. - * If not, and the maximum number of WorkerThreads has not been reached, a - * new WorkerThread is created. If the maximum number has been reached, this - * blocks until a WorkerThread is free. - */ - static WorkerThread - getThread() { - WorkerThread t; - synchronized (list) { - if (list.size() > 0) { - t = (WorkerThread) list.firstElement(); - list.removeElement(t); - } else if (nactive >= max) { - while (true) { - try { - list.wait(); - } catch (InterruptedException e) { - } - if (list.size() == 0) { - continue; - } - t = (WorkerThread) list.firstElement(); - list.removeElement(t); - break; - } - } else { - t = new WorkerThread(); - } - nactive++; - } - return t; - } - - /** - * Assigns a task to a WorkerThread - * - * @param task The task to be run - * @param name The name of the task - */ - public static void - assignThread(Runnable task, String name) { - while (true) { - try { - WorkerThread t = getThread(); - synchronized (t) { - t.task = task; - t.name = name; - if (!t.isAlive()) { - t.start(); - } else { - t.notify(); - } - } - return; - } catch (IllegalThreadStateException e) { - } - } - } - - /** - * Performs the task - */ - synchronized public void - run() { - while (true) { - setName(name); - try { - task.run(); - } catch (Throwable t) { - System.err.println(t); - } - setName("idle thread"); - synchronized (list) { - list.addElement(this); - if (nactive >= max) { - list.notify(); - } - nactive--; - } - task = null; - try { - wait(lifetime); - } catch (InterruptedException e) { - } - if (task == null) { - list.removeElement(this); - return; - } - } - } - -} diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 99288cf89..bfd1d9658 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -1914,17 +1914,8 @@ public class CommandLineArgumentParser { } private static void parseProxy(Stack args) { - int port = 55555; - String portStr = args.peek(); - if (portStr != null && portStr.startsWith("-P")) { - args.pop(); - try { - port = Integer.parseInt(portStr.substring(2)); - } catch (NumberFormatException nex) { - System.err.println("Bad port number"); - } - } - Main.startProxy(port); + System.err.println("Proxy functionalit was REMOVED"); + System.exit(1); } private static List parseSelectClass(Stack args) { diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 5c73e8326..880de86f6 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -49,7 +49,6 @@ import com.jpexs.decompiler.flash.gfx.GfxConvertor; import com.jpexs.decompiler.flash.gui.debugger.DebugAdapter; import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; import com.jpexs.decompiler.flash.gui.pipes.FirstInstance; -import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; @@ -78,19 +77,12 @@ import com.sun.jna.Platform; import com.sun.jna.platform.win32.Advapi32Util; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinReg; -import java.awt.AWTException; import java.awt.Component; -import java.awt.Frame; import java.awt.GraphicsEnvironment; import java.awt.MenuItem; -import java.awt.PopupMenu; import java.awt.SystemTray; import java.awt.TrayIcon; import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; @@ -143,7 +135,6 @@ import java.util.logging.SimpleFormatter; import java.util.regex.Pattern; import javax.swing.JFileChooser; import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; @@ -159,8 +150,6 @@ public class Main { public static final String IMPORT_ASSETS_SEPARATOR = "{*sep*}"; - protected static ProxyFrame proxyFrame; - private static List sourceInfos = new ArrayList<>(); public static LoadingDialog loadingDialog; @@ -842,24 +831,6 @@ public class Main { return working; } - public static void startProxy(int port) { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } - - proxyFrame.setPort(port); - addTrayIcon(); - switchProxy(); - } - - public static void showProxy() { - if (proxyFrame == null) { - proxyFrame = new ProxyFrame(mainFrame); - } - proxyFrame.setVisible(true); - proxyFrame.setState(Frame.NORMAL); - } - public static void continueWork(String name) { continueWork(name, -1); } @@ -1762,11 +1733,6 @@ public class Main { } } } - if (proxyFrame != null) { - proxyFrame.setVisible(false); - proxyFrame.dispose(); - proxyFrame = null; - } if (loadFromMemoryFrame != null) { loadFromMemoryFrame.setVisible(false); loadFromMemoryFrame.dispose(); @@ -2938,79 +2904,6 @@ public class Main { } } - public static void switchProxy() { - proxyFrame.switchState(); - if (stopMenuItem != null) { - if (proxyFrame.isRunning()) { - stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); - } else { - stopMenuItem.setLabel(AppStrings.translate("proxy.start")); - } - } - } - - public static void addTrayIcon() { - if (trayIcon != null) { - return; - } - if (SystemTray.isSupported()) { - SystemTray tray = SystemTray.getSystemTray(); - trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy")); - trayIcon.setImageAutoSize(true); - PopupMenu trayPopup = new PopupMenu(); - - ActionListener trayListener = new ActionListener() { - /** - * Invoked when an action occurs. - */ - @Override - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("EXIT")) { - Main.exit(); - } - if (e.getActionCommand().equals("SHOW")) { - Main.showProxy(); - } - if (e.getActionCommand().equals("SWITCH")) { - Main.switchProxy(); - } - } - }; - - MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); - showMenuItem.setActionCommand("SHOW"); - showMenuItem.addActionListener(trayListener); - trayPopup.add(showMenuItem); - stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); - stopMenuItem.setActionCommand("SWITCH"); - stopMenuItem.addActionListener(trayListener); - trayPopup.add(stopMenuItem); - trayPopup.addSeparator(); - MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); - exitMenuItem.setActionCommand("EXIT"); - exitMenuItem.addActionListener(trayListener); - trayPopup.add(exitMenuItem); - - trayIcon.setPopupMenu(trayPopup); - trayIcon.addMouseListener(new MouseAdapter() { - /** - * {@inheritDoc} - */ - @Override - public void mouseClicked(MouseEvent e) { - if (SwingUtilities.isLeftMouseButton(e)) { - Main.showProxy(); - } - } - }); - try { - tray.add(trayIcon); - } catch (AWTException ex) { - //ignored - } - } - } - public static List namesToSwfs(List names) { List ret = new ArrayList<>(); Map swfs = new LinkedHashMap<>(); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index d24490f24..05e159839 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -547,18 +547,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return false; } - - protected void showProxyActionPerformed(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - if (mainFrame.getPanel().checkEdited()) { - return; - } - - Main.showProxy(); - } - + protected boolean clearLog(ActionEvent evt) { ErrorLogFrame.getInstance().clearLog(); return true; @@ -1083,7 +1072,6 @@ public abstract class MainFrameMenu implements MenuBuilder { setMenuEnabled("/tools/replace", swfSelected); setMenuEnabled("/tools/timeline", swfSelected); setMenuEnabled("/tools/abcExplorer", isAs3); - setMenuEnabled("/tools/showProxy", !isWorking); setMenuEnabled("/tools/gotoDocumentClass", hasAbc); /*setMenuEnabled("/tools/debugger/debuggerSwitch", hasAbc); @@ -1277,7 +1265,6 @@ public abstract class MainFrameMenu implements MenuBuilder { addToggleMenuItem("/tools/timeline", translate("menu.tools.timeline"), null, "timeline32", this::timelineActionPerformed, PRIORITY_TOP, null); addMenuItem("/tools/abcExplorer", translate("menu.tools.abcexplorer"), "abcexplorer32", this::abcExplorerActionPerformed, PRIORITY_TOP, null, true, null, false); - addMenuItem("/tools/showProxy", translate("menu.tools.proxy"), "proxy16", this::showProxyActionPerformed, PRIORITY_MEDIUM, null, true, null, false); if (Platform.isWindows()) { addMenuItem("/tools/searchMemory", translate("menu.tools.searchMemory"), "loadmemory16", this::searchMemoryActionPerformed, PRIORITY_MEDIUM, null, true, null, false); } diff --git a/src/com/jpexs/decompiler/flash/gui/ModeFrame.java b/src/com/jpexs/decompiler/flash/gui/ModeFrame.java deleted file mode 100644 index 9eb51909e..000000000 --- a/src/com/jpexs/decompiler/flash/gui/ModeFrame.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010-2024 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.ApplicationInfo; -import java.awt.Container; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import javax.swing.JButton; -import javax.swing.JLabel; - -/** - * Frame with selection on application startServer - * - * @author JPEXS - */ -public class ModeFrame extends AppFrame { - - private final JButton openButton = new JButton(translate("button.open")); - - private final JButton proxyButton = new JButton(translate("button.proxy")); - - private final JButton exitButton = new JButton(translate("button.exit")); - - /** - * Constructor - */ - public ModeFrame() { - setSize(350, 200); - openButton.addActionListener(this::openButtonActionPerformed); - openButton.setIcon(View.getIcon("open32")); - proxyButton.addActionListener(this::proxyButtonActionPerformed); - proxyButton.setIcon(View.getIcon("proxy32")); - exitButton.addActionListener(this::exitButtonActionPerformed); - exitButton.setIcon(View.getIcon("exit32")); - setResizable(false); - Container cont = getContentPane(); - cont.setLayout(new GridLayout(4, 1)); - JLabel logoLabel = new JLabel(); - logoLabel.setIcon(View.getIcon("logo")); - cont.add(logoLabel); - cont.add(openButton); - cont.add(proxyButton); - cont.add(exitButton); - View.centerScreen(this); - View.setWindowIcon(this); - setTitle(ApplicationInfo.shortApplicationVerName); - this.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - Main.exit(); - } - }); - } - - private void openButtonActionPerformed(ActionEvent evt) { - setVisible(false); - if (!Main.openFileDialog()) { - setVisible(true); - } - } - - private void proxyButtonActionPerformed(ActionEvent evt) { - setVisible(false); - Main.showProxy(); - } - - private void exitButtonActionPerformed(ActionEvent evt) { - setVisible(false); - Main.exit(); - } -} diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java index 87180e03b..b16a59380 100644 --- a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java +++ b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java @@ -28,7 +28,6 @@ import com.jpexs.decompiler.flash.gui.GraphDialog; import com.jpexs.decompiler.flash.gui.LoadFromMemoryFrame; import com.jpexs.decompiler.flash.gui.LoadingDialog; import com.jpexs.decompiler.flash.gui.MainFrame; -import com.jpexs.decompiler.flash.gui.ModeFrame; import com.jpexs.decompiler.flash.gui.NewVersionDialog; import com.jpexs.decompiler.flash.gui.RenameDialog; import com.jpexs.decompiler.flash.gui.ReplaceCharacterDialog; @@ -39,7 +38,6 @@ import com.jpexs.decompiler.flash.gui.SelectLanguageDialog; import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog; import com.jpexs.decompiler.flash.gui.abc.NewTraitDialog; import com.jpexs.decompiler.flash.gui.abc.UsageFrame; -import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; import com.jpexs.helpers.Helper; import java.io.BufferedReader; import java.io.FileNotFoundException; @@ -253,7 +251,6 @@ public class CheckResources { LoadFromMemoryFrame.class, LoadingDialog.class, MainFrame.class, - ModeFrame.class, NewVersionDialog.class, RenameDialog.class, ReplaceCharacterDialog.class, @@ -265,8 +262,6 @@ public class CheckResources { DeobfuscationDialog.class, NewTraitDialog.class, UsageFrame.class, - // Proxy - ProxyFrame.class }; return classes; } diff --git a/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java b/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java deleted file mode 100644 index b817b8fbe..000000000 --- a/src/com/jpexs/decompiler/flash/gui/proxy/ProxyFrame.java +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Copyright (C) 2010-2024 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.proxy; - -import com.jpexs.decompiler.flash.RetryTask; -import com.jpexs.decompiler.flash.RunnableIOEx; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.gui.AppFrame; -import com.jpexs.decompiler.flash.gui.AppStrings; -import com.jpexs.decompiler.flash.gui.FasterScrollPane; -import com.jpexs.decompiler.flash.gui.GuiAbortRetryIgnoreHandler; -import com.jpexs.decompiler.flash.gui.Main; -import com.jpexs.decompiler.flash.gui.MainFrame; -import com.jpexs.decompiler.flash.gui.View; -import com.jpexs.decompiler.flash.gui.ViewMessages; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.utf8.Utf8InputStreamReader; -import com.jpexs.helpers.utf8.Utf8OutputStreamWriter; -import com.jpexs.proxy.CatchedListener; -import com.jpexs.proxy.ReplacedListener; -import com.jpexs.proxy.Replacement; -import com.jpexs.proxy.Server; -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.Image; -import java.awt.Toolkit; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.StringSelection; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.SwingConstants; -import javax.swing.filechooser.FileFilter; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.DefaultTableColumnModel; -import javax.swing.table.DefaultTableModel; - -/** - * Frame with Proxy - * - * @author JPEXS - */ -public class ProxyFrame extends AppFrame implements CatchedListener, MouseListener, ReplacedListener { - - private static final String REPLACEMENTS_NAME = "replacements.cfg"; - - private JTable replacementsTable; - - private JButton switchButton = new JButton(translate("proxy.start")); - - private boolean started = false; - - private JTextField portField = new JTextField("55555"); - - private JCheckBox sniffSWFCheckBox = new JCheckBox("SWF", false); - - private JCheckBox sniffOSCheckBox = new JCheckBox("OctetStream", false); - - private JCheckBox sniffJSCheckBox = new JCheckBox("JS", false); - - private JCheckBox sniffXMLCheckBox = new JCheckBox("XML", false); - - /** - * Is server running - * - * @return True when running - */ - public boolean isRunning() { - return started; - } - - /** - * Sets port for the proxy - * - * @param port Port number - */ - public void setPort(int port) { - portField.setText(Integer.toString(port)); - } - - private static class SizeItem implements Comparable { - - String file; - - public SizeItem(String file) { - this.file = file; - } - - @Override - public String toString() { - return Helper.byteCountStr(new File(file).length(), false); - } - - @Override - public int compareTo(SizeItem o) { - return (int) (new File(file).length() - new File(o.file).length()); - } - } - - DefaultTableModel tableModel; - - private SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); - - /** - * List of replacements - */ - private static List replacements = new ArrayList<>(); - - /** - * Saves replacements to file for future use - */ - private static void saveReplacements() { - String replacementsFile = getReplacementsFile(); - if (replacements.isEmpty()) { - File rf = new File(replacementsFile); - if (rf.exists()) { - if (!rf.delete()) { - Logger.getLogger(ProxyFrame.class.getName()).log(Level.SEVERE, "Cannot delete replacements file"); - } - } - } else { - try (PrintWriter pw = new PrintWriter(new Utf8OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(replacementsFile))))) { - for (Replacement r : replacements) { - pw.println(r.urlPattern); - pw.println(r.targetFile); - } - } catch (IOException ex) { - Logger.getLogger(ProxyFrame.class.getName()).log(Level.SEVERE, "Exception during saving replacements", ex); - } - } - } - - /** - * Load replacements from file - */ - private static void loadReplacements() { - String replacementsFile = getReplacementsFile(); - if (!(new File(replacementsFile)).exists()) { - return; - } - replacements = new ArrayList<>(); - try (BufferedReader br = new BufferedReader(new Utf8InputStreamReader(new FileInputStream(replacementsFile)))) { - String s; - while ((s = br.readLine()) != null) { - Replacement r = new Replacement(s, br.readLine()); - replacements.add(r); - } - } catch (IOException e) { - //ignore - } - } - - private static String getReplacementsFile() { - return Configuration.getFFDecHome() + REPLACEMENTS_NAME; - } - - /** - * Constructor - * - * @param mainFrame Main frame - */ - public ProxyFrame(final MainFrame mainFrame) { - - final String[] columnNames = new String[]{ - translate("column.accessed"), - translate("column.size"), - translate("column.url")}; - - loadReplacements(); - - Object[][] data = new Object[replacements.size()][3]; - - for (int i = 0; i < replacements.size(); i++) { - Replacement r = replacements.get(i); - data[i][0] = r.lastAccess == null ? "" : format.format(r.lastAccess.getTime()); - data[i][1] = new SizeItem(r.targetFile); - data[i][2] = r.urlPattern; - } - - tableModel = new DefaultTableModel(data, columnNames) { - @Override - public Class getColumnClass(int columnIndex) { - Class[] classes = new Class[]{String.class, SizeItem.class, String.class}; - return classes[columnIndex]; - } - - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - replacementsTable = new JTable(tableModel); - - DefaultTableCellRenderer tcr = new DefaultTableCellRenderer(); - tcr.setHorizontalAlignment(SwingConstants.RIGHT); - - replacementsTable.setDefaultRenderer(String.class, new DefaultTableCellRenderer()); - replacementsTable.setDefaultRenderer(SizeItem.class, tcr); - - replacementsTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); - - replacementsTable.setRowSelectionAllowed(true); - - DefaultTableColumnModel colModel = (DefaultTableColumnModel) replacementsTable.getColumnModel(); - colModel.getColumn(0).setMaxWidth(100); - - colModel.getColumn(1).setMaxWidth(200); - - replacementsTable.setAutoCreateRowSorter(true); - - replacementsTable.setAutoCreateRowSorter(false); - - replacementsTable.addMouseListener(this); - replacementsTable.setFont(new Font("Monospaced", Font.PLAIN, 12)); - switchButton.addActionListener(this::switchStateButtonActionPerformed); - Container cnt = getContentPane(); - cnt.setLayout(new BorderLayout()); - cnt.add(new FasterScrollPane(replacementsTable), BorderLayout.CENTER); - - portField.setPreferredSize(new Dimension(80, portField.getPreferredSize().height)); - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout(new FlowLayout()); - buttonsPanel.add(new JLabel(translate("port"))); - buttonsPanel.add(portField); - buttonsPanel.add(switchButton); - cnt.add(buttonsPanel, BorderLayout.NORTH); - - JPanel buttonsPanel23 = new JPanel(); - buttonsPanel23.setLayout(new BoxLayout(buttonsPanel23, BoxLayout.Y_AXIS)); - - JPanel buttonsPanel21 = new JPanel(new FlowLayout()); - JButton openButton = new JButton(translate("open")); - openButton.addActionListener(this::openButtonActionPerformed); - buttonsPanel21.add(openButton); - JButton clearButton = new JButton(translate("clear")); - clearButton.addActionListener(this::clearButtonActionPerformed); - buttonsPanel21.add(clearButton); - JButton renameButton = new JButton(translate("rename")); - renameButton.addActionListener(this::renameButtonActionPerformed); - buttonsPanel21.add(renameButton); - JButton removeButton = new JButton(translate("remove")); - removeButton.addActionListener(this::removeButtonActionPerformed); - buttonsPanel21.add(removeButton); - - //JPanel buttonsPanel22 = new JPanel(new FlowLayout()); - JButton copyUrlButton = new JButton(translate("copy.url")); - copyUrlButton.addActionListener(this::copyUrlButtonActionPerformed); - buttonsPanel21.add(copyUrlButton); - - JButton saveAsButton = new JButton(translate("save.as")); - saveAsButton.addActionListener(this::saveAsButtonActionPerformed); - buttonsPanel21.add(saveAsButton); - - JButton replaceButton = new JButton(translate("replace")); - replaceButton.addActionListener(this::replaceButtonActionPerformed); - buttonsPanel21.add(replaceButton); - - JPanel buttonsPanel3 = new JPanel(); - buttonsPanel3.setLayout(new FlowLayout()); - buttonsPanel3.add(new JLabel(translate("sniff"))); - buttonsPanel3.add(sniffSWFCheckBox); - buttonsPanel3.add(sniffOSCheckBox); - //buttonsPanel3.add(sniffJSCheckBox); - //buttonsPanel3.add(sniffXMLCheckBox); - - buttonsPanel23.add(buttonsPanel21); - //buttonsPanel23.add(buttonsPanel22); - buttonsPanel23.add(buttonsPanel3); - - cnt.add(buttonsPanel23, BorderLayout.SOUTH); - setSize(800, 500); - View.centerScreen(this); - View.setWindowIcon(this); - setTitle(translate("dialog.title")); - this.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - setVisible(false); - Main.removeTrayIcon(); - if (mainFrame != null) { - if (mainFrame.isVisible()) { - return; - } - } - Main.showModeFrame(); - } - - /** - * Invoked when a window is iconified. - */ - @Override - public void windowIconified(WindowEvent e) { - setVisible(false); - } - }); - List images = new ArrayList<>(); - images.add(View.loadImage("proxy16")); - images.add(View.loadImage("proxy32")); - setIconImages(images); - } - - private void open() { - View.checkAccess(); - - if (replacementsTable.getSelectedRow() > -1) { - Replacement r = replacements.get(replacementsTable.getRowSorter().convertRowIndexToModel(replacementsTable.getSelectedRow())); - Main.openFile(r.targetFile, r.urlPattern); - } - } - - private String selectExportDir() { - JFileChooser chooser = new JFileChooser(); - chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); - chooser.setDialogTitle(translate("export.select.directory")); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setAcceptAllFileFilterUsed(false); - if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - final String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); - Configuration.lastExportDir.set(Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath()); - return selFile; - } - return null; - } - - private int[] getSelectedRows() { - int[] sel = replacementsTable.getSelectedRows(); - for (int i = 0; i < sel.length; i++) { - sel[i] = replacementsTable.getRowSorter().convertRowIndexToModel(sel[i]); - } - - return sel; - } - - private void openButtonActionPerformed(ActionEvent evt) { - open(); - } - - private void saveAsButtonActionPerformed(ActionEvent evt) { - int[] sel = getSelectedRows(); - if (sel.length == 1) { - Replacement r = replacements.get(sel[0]); - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get())); - String n = r.urlPattern; - if (n.contains("?")) { - n = n.substring(0, n.indexOf('?')); - } - if (n.contains("/")) { - n = n.substring(n.lastIndexOf('/')); - } - n = Helper.makeFileName(n); - fc.setSelectedFile(new File(Configuration.lastSaveDir.get(), n)); - String ext = ".swf"; - final String extension = ext; - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(extension)) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter" + extension); - } - }; - fc.setFileFilter(swfFilter); - fc.setAcceptAllFileFilterUsed(true); - if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { - File file = Helper.fixDialogFile(fc.getSelectedFile()); - try { - Files.copy(new File(r.targetFile).toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException ex) { - ViewMessages.showMessageDialog(this, translate("error.save.as") + "\r\n" + ex.getLocalizedMessage(), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - } - } - } else { - GuiAbortRetryIgnoreHandler handler = new GuiAbortRetryIgnoreHandler(); - File exportDir = new File(selectExportDir()); - for (int s : sel) { - final Replacement r = replacements.get(s); - String n = r.urlPattern; - if (n.contains("?")) { - n = n.substring(0, n.indexOf('?')); - } - if (n.contains("/")) { - n = n.substring(n.lastIndexOf('/')); - } - n = Helper.makeFileName(n); - int c = 2; - String n2 = n; - while (new File(exportDir, n2).exists()) { - if (n.contains(".")) { - n2 = n.substring(0, n.lastIndexOf('.')) + c + n.substring(n.lastIndexOf('.')); - c++; - } else { - n2 = n + c + ".swf"; - c++; - } - } - - final File outfile = new File(exportDir, n2); - try { - new RetryTask(new RunnableIOEx() { - @Override - public void run() throws IOException { - Files.copy(new File(r.targetFile).toPath(), outfile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - }, handler).run(); - } catch (IOException | InterruptedException ex) { - break; - } - } - } - } - - private void replaceButtonActionPerformed(ActionEvent evt) { - int[] sel = getSelectedRows(); - if (sel.length > 0) { - Replacement r = replacements.get(sel[0]); - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - String ext = ".swf"; - final String extension = ext; - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(extension)) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter" + extension); - } - }; - fc.setFileFilter(swfFilter); - fc.setAcceptAllFileFilterUsed(true); - if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - File file = Helper.fixDialogFile(fc.getSelectedFile()); - try { - Files.copy(file.toPath(), new File(r.targetFile).toPath(), StandardCopyOption.REPLACE_EXISTING); - tableModel.fireTableCellUpdated(sel[0], 1/*size*/); - } catch (IOException ex) { - ViewMessages.showMessageDialog(this, translate("error.replace") + "\r\n" + ex.getLocalizedMessage(), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - } - } - } - } - - private void copyUrlButtonActionPerformed(ActionEvent evt) { - int[] sel = getSelectedRows(); - StringBuilder copyText = new StringBuilder(); - for (int sc : sel) { - Replacement r = replacements.get(sc); - if (copyText.length() > 0) { - copyText.append(System.lineSeparator()); - } - copyText.append(r.urlPattern); - } - - if (copyText.length() > 0) { - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - StringSelection stringSelection = new StringSelection(copyText.toString()); - clipboard.setContents(stringSelection, null); - } - } - - private void renameButtonActionPerformed(ActionEvent evt) { - int[] sel = getSelectedRows(); - if (sel.length > 0) { - Replacement r = replacements.get(sel[0]); - String s = ViewMessages.showInputDialog(this, "URL", r.urlPattern); - if (s != null) { - r.urlPattern = s; - tableModel.setValueAt(s, sel[0], 2/*url*/); - } - } - } - - private void clearButtonActionPerformed(ActionEvent evt) { - for (Replacement r : replacements) { - File f; - try { - f = (new File(Main.tempFile(r.targetFile))); - if (f.exists()) { - f.delete(); - } - } catch (IOException ex) { - Logger.getLogger(ProxyFrame.class.getName()).log(Level.SEVERE, null, ex); - } - } - tableModel.setRowCount(0); - replacements.clear(); - saveReplacements(); - } - - private void removeButtonActionPerformed(ActionEvent evt) { - int[] sel = getSelectedRows(); - Arrays.sort(sel); - for (int i = sel.length - 1; i >= 0; i--) { - tableModel.removeRow(sel[i]); - Replacement r = replacements.remove(sel[i]); - saveReplacements(); - File f = (new File(r.targetFile)); - if (f.exists()) { - f.delete(); - } - } - } - - private void switchStateButtonActionPerformed(ActionEvent evt) { - Main.switchProxy(); - } - - /** - * Switch proxy state - */ - public void switchState() { - started = !started; - if (started) { - int port = 0; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException nfe) { - //ignored - } - if ((port <= 0) || (port > 65535)) { - ViewMessages.showMessageDialog(this, translate("error.port"), translate("error"), JOptionPane.ERROR_MESSAGE); - started = false; - return; - } - List catchedContentTypes = new ArrayList<>(); - catchedContentTypes.add("application/x-shockwave-flash"); - catchedContentTypes.add("application/x-javascript"); - catchedContentTypes.add("application/javascript"); - catchedContentTypes.add("text/javascript"); - catchedContentTypes.add("application/json"); - catchedContentTypes.add("text/xml"); - catchedContentTypes.add("application/xml"); - catchedContentTypes.add("application/octet-stream"); - if (!Server.startServer(port, replacements, catchedContentTypes, this, this)) { - JOptionPane.showMessageDialog(this, translate("error.start.server").replace("%port%", "" + port), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - started = false; - return; - } - switchButton.setText(translate("proxy.stop")); - portField.setEditable(false); - } else { - Server.stopServer(); - switchButton.setText(translate("proxy.start")); - portField.setEditable(true); - } - } - - /** - * Mouse clicked event - * - * @param e event - */ - @Override - public void mouseClicked(MouseEvent e) { - if (e.getSource() == replacementsTable) { - if (e.getClickCount() == 2) { - open(); - } - } - } - - /** - * Mouse pressed event - * - * @param e event - */ - @Override - public void mousePressed(MouseEvent e) { - } - - /** - * Mouse released event - * - * @param e event - */ - @Override - public void mouseReleased(MouseEvent e) { - } - - /** - * Mouse entered event - * - * @param e event - */ - @Override - public void mouseEntered(MouseEvent e) { - } - - /** - * Mouse exited event - * - * @param e event - */ - @Override - public void mouseExited(MouseEvent e) { - } - - /** - * Method called when specified contentType is received - * - * @param contentType Content type - * @param url URL of the method - * @param data Data stream - * @return replacement data - */ - @Override - public byte[] catched(String contentType, String url, InputStream data) { - boolean swfOnly = false; - if (contentType.contains(";")) { - contentType = contentType.substring(0, contentType.indexOf(';')); - } - if ((!sniffSWFCheckBox.isSelected()) && (contentType.equals("application/x-shockwave-flash"))) { - return null; - } - if ((!sniffJSCheckBox.isSelected()) && (contentType.equals("application/javascript") || contentType.equals("application/x-javascript") || contentType.equals("text/javascript") || contentType.equals("application/json"))) { - return null; - } - if ((!sniffXMLCheckBox.isSelected()) && (contentType.equals("application/xml") || contentType.equals("text/xml"))) { - return null; - } - if ((!sniffOSCheckBox.isSelected()) && (contentType.equals("application/octet-stream"))) { - return null; - } - - byte[] result = null; - - boolean cont = false; - for (Replacement r : replacements) { - if (r.matches(url)) { - cont = true; - break; - } - } - if (!cont) { - try { - byte[] hdr = new byte[3]; - if (data.read(hdr) != 3) { - throw new IOException(); - } - - String shdr = new String(hdr); - if (swfOnly && ((!shdr.equals("FWS")) && (!shdr.equals("CWS")) && (!shdr.equals("ZWS")))) { - return null; //NOT SWF - } - - String tempFilePath = Main.tempFile(url); - data.reset(); - byte[] dataArray = Helper.readStream(data); - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File(tempFilePath)))) { - fos.write(dataArray); - } - - result = SWFDecompilerPlugin.fireProxyFileCatched(dataArray); - - Replacement r = new Replacement(url, tempFilePath); - r.lastAccess = Calendar.getInstance(); - replacements.add(r); - saveReplacements(); - tableModel.addRow(new Object[]{ - r.lastAccess == null ? "" : format.format(r.lastAccess.getTime()), - new SizeItem(r.targetFile), - r.urlPattern - }); - } catch (IOException e) { - //ignored - } - } - - return result; - } - - @Override - public void setVisible(boolean b) { - if (b == true) { - Main.addTrayIcon(); - } - super.setVisible(b); - } - - @Override - public void replaced(Replacement replacement, String url, String contentType) { - int index = replacements.indexOf(replacement); - tableModel.setValueAt(replacement.lastAccess == null ? "" : format.format(replacement.lastAccess.getTime()), index, 0); - tableModel.setValueAt(new SizeItem(replacement.targetFile), index, 1); - tableModel.setValueAt(replacement.urlPattern, index, 2); - } -} diff --git a/src/com/jpexs/decompiler/flash/gui/proxy/SWFListModel.java b/src/com/jpexs/decompiler/flash/gui/proxy/SWFListModel.java deleted file mode 100644 index e79cc25cc..000000000 --- a/src/com/jpexs/decompiler/flash/gui/proxy/SWFListModel.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2010-2024 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui.proxy; - -import com.jpexs.proxy.Replacement; -import java.util.ArrayList; -import java.util.List; -import javax.swing.ListModel; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; - -/** - * List mode for list with SWF urls - * - * @author JPEXS - */ -public class SWFListModel implements ListModel { - - private final List listeners = new ArrayList<>(); - - private final List replacements; - - /** - * Constructor - * - * @param replacements List of replacements - */ - public SWFListModel(List replacements) { - this.replacements = replacements; - } - - /** - * Removes replacement with specified index from the list - * - * @param index Index of replacement to remove - * @return Removed replacement - */ - public Replacement removeURL(int index) { - if (index == -1) { - return null; - } - if (index < replacements.size()) { - Replacement r = replacements.remove(index); - for (ListDataListener l : listeners) { - l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index)); - } - return r; - } - return null; - } - - /** - * Called when data in a replacement changed - * - * @param index Index of which SWF changed - */ - public void dataChanged(int index) { - if (index == -1) { - return; - } - for (ListDataListener l : listeners) { - l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index)); - } - } - - /** - * Returns index of specified replacement - * - * @param replacement Replacement - * @return Index of -1 if not found - */ - public int indexOf(Replacement replacement) { - for (int i = 0; i < replacements.size(); i++) { - if (replacements.get(i) == replacement) { - return i; - } - } - return -1; - } - - /** - * Clears url list - */ - public void clear() { - int size = replacements.size(); - if (size == 0) { - return; - } - replacements.clear(); - for (ListDataListener l : listeners) { - l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, 0, size - 1)); - } - } - - /** - * Test whether the list contains url - * - * @param url URL to test - * @return True when contains - */ - public boolean contains(String url) { - for (Replacement r : replacements) { - if (r.matches(url)) { - return true; - } - } - return false; - } - - /** - * Adds url to the list - * - * @param replacement URL to add - */ - public void addURL(Replacement replacement) { - int sizeBefore = replacements.size(); - replacements.add(replacement); - for (ListDataListener l : listeners) { - l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, sizeBefore, sizeBefore)); - } - } - - /** - * Returns size of the list - * - * @return Size of the list - */ - @Override - public int getSize() { - return replacements.size(); - } - - /** - * Returns element on specified index - * - * @param index Index of element - * @return Element on index - */ - @Override - public Replacement getElementAt(int index) { - return replacements.get(index); - } - - /** - * Adds add list data listener - * - * @param l list data listener - */ - @Override - public void addListDataListener(ListDataListener l) { - listeners.add(l); - } - - /** - * Adds remove list data listener - * - * @param l list data listener - */ - @Override - public void removeListDataListener(ListDataListener l) { - if (listeners.contains(l)) { - listeners.remove(l); - } - } -}