diff --git a/.gitattributes b/.gitattributes index 81c042e5c..8e560a161 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,16 +1,47 @@ -# Set the default behavior, in case people don't have core.autocrlf set. -#* text=auto +# Text files +*.txt text +*.xml text +*.md text -# Explicitly declare text files you want to always be normalized and converted -# to native line endings on checkout. -*.c text -*.h text -*.java text eol=crlf -*.sh binary +# Installers: +*.iss text +*.nsi text +*.nsh text -# Declare files that will always have CRLF line endings on checkout. -*.sln text eol=crlf +# Java +*.java text +*.mf text +*.properties text -# Denote all files that are truly binary and should not be modified. +# Graphics: +*.svg text *.png binary -*.jpg binary \ No newline at end of file +*.jpg binary +*.bmp binary +*.ico binary +*.icns binary +*.xcf binary +*.gif binary + +# Findbugs: +*.fbp text + +# Batch files +*.sh text eol=lf +*.bat text eol=crlf + +# Delphi sources +*.dpr text eol=crlf +*.dfm text eol=crlf +*.pas text eol=crlf +*.dof text eol=crlf + +# Executables +*.dll binary +*.exe binary +*.jar binary +*.res binary + +# Fonts +*.otf binary +*.ttf binary diff --git a/.idea/ant.xml b/.idea/ant.xml index 6ddee46ae..4674eeac9 100644 --- a/.idea/ant.xml +++ b/.idea/ant.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/.idea/compiler.xml b/.idea/compiler.xml index c33f99162..48642b4fc 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,28 +1,28 @@ - - - - - - - - + + + + + + + + diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml index b385f01fd..3572571ad 100644 --- a/.idea/copyright/profiles_settings.xml +++ b/.idea/copyright/profiles_settings.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 7c62b52a1..e206d70d8 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,5 +1,5 @@ - - - - - + + + + + diff --git a/.idea/libraries/lib.xml b/.idea/libraries/lib.xml index d062ade52..bfe7b7ba7 100644 --- a/.idea/libraries/lib.xml +++ b/.idea/libraries/lib.xml @@ -1,10 +1,10 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/testlib.xml b/.idea/libraries/testlib.xml index 24bd8f60a..c5ea87068 100644 --- a/.idea/libraries/testlib.xml +++ b/.idea/libraries/testlib.xml @@ -1,11 +1,11 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 13ec7fbc5..dde57ed46 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml index b6f26e5ea..8aa827526 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -1,11 +1,11 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml index 1e7cce4b8..3b0002030 100644 --- a/.idea/uiDesigner.xml +++ b/.idea/uiDesigner.xml @@ -1,125 +1,125 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 6d89e2bf8..f6a23c130 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2f6ddde58..4a622bba7 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,553 +1,553 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - localhost - 5050 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.6 - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + localhost + 5050 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.6 + + + + + + + + + + + + + + diff --git a/lib/avi.montemedia.license.txt b/lib/avi.montemedia.license.txt index 80ba1df4b..b10d67604 100644 --- a/lib/avi.montemedia.license.txt +++ b/lib/avi.montemedia.license.txt @@ -1,8 +1,8 @@ -Monte Media Library © 2012 -Werner Randelshofer, Hausmatt 10, CH-6405 Goldau Switzerland -werner.randelshofer@bluewin.ch -All Rights Reserved. - -The Monte Media Library can be licensed under the terms of the Creative Commons BY 3.0 license, and/or under the terms of the Lesser General Public License LGPL Version 3. - +Monte Media Library © 2012 +Werner Randelshofer, Hausmatt 10, CH-6405 Goldau Switzerland +werner.randelshofer@bluewin.ch +All Rights Reserved. + +The Monte Media Library can be licensed under the terms of the Creative Commons BY 3.0 license, and/or under the terms of the Lesser General Public License LGPL Version 3. + The license is free for commercial and non-commercial use. \ No newline at end of file diff --git a/lib/flamingo.license.txt b/lib/flamingo.license.txt index 69d06bfe0..d84664dad 100644 --- a/lib/flamingo.license.txt +++ b/lib/flamingo.license.txt @@ -1,27 +1,27 @@ -Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - o Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - o Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - o Neither the name of Flamingo Kirill Grouchnikov nor the names of - its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + o Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + o Neither the name of Flamingo Kirill Grouchnikov nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/gif.license.txt b/lib/gif.license.txt index ea041f71e..1febc60c3 100644 --- a/lib/gif.license.txt +++ b/lib/gif.license.txt @@ -1,6 +1,6 @@ -Created by Elliot Kroo on 2009-04-25. - -This work is licensed under the Creative Commons Attribution 3.0 Unported -License. To view a copy of this license, visit -http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative +Created by Elliot Kroo on 2009-04-25. + +This work is licensed under the Creative Commons Attribution 3.0 Unported +License. To view a copy of this license, visit +http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. \ No newline at end of file diff --git a/lib/jl.license.txt b/lib/jl.license.txt index 247851325..ef8de92a6 100644 --- a/lib/jl.license.txt +++ b/lib/jl.license.txt @@ -1,17 +1,17 @@ -Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) -Berlin University of Technology ------------------------------------------------------------------------ -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Library General Public License as published -by the Free Software Foundation; either version 2 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 Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) +Berlin University of Technology +----------------------------------------------------------------------- +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published +by the Free Software Foundation; either version 2 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 Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ---------------------------------------------------------------------- \ No newline at end of file diff --git a/lib/jna.license.txt b/lib/jna.license.txt index 687212f5a..0eb865e1b 100644 --- a/lib/jna.license.txt +++ b/lib/jna.license.txt @@ -1,11 +1,11 @@ -Copyright (c) 2007 Timothy Wall, All Rights Reserved - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. +Copyright (c) 2007 Timothy Wall, All Rights Reserved + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. diff --git a/lib/jpacker.license.txt b/lib/jpacker.license.txt index f8f9604f5..a08669cf8 100644 --- a/lib/jpacker.license.txt +++ b/lib/jpacker.license.txt @@ -1,10 +1,10 @@ -Packer version 3.0 (final) -Copyright 2004-2007, Dean Edwards -Web: http://dean.edwards.name/ - -This software is licensed under the MIT license -Web: http://www.opensource.org/licenses/mit-license - -Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, -Web: http://jpacker.googlecode.com/ -Email: pablo.santiago@gmail.com +Packer version 3.0 (final) +Copyright 2004-2007, Dean Edwards +Web: http://dean.edwards.name/ + +This software is licensed under the MIT license +Web: http://www.opensource.org/licenses/mit-license + +Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, +Web: http://jpacker.googlecode.com/ +Email: pablo.santiago@gmail.com diff --git a/lib/jpproxy.muffin.license.txt b/lib/jpproxy.muffin.license.txt index 6bf59f369..90f94a078 100644 --- a/lib/jpproxy.muffin.license.txt +++ b/lib/jpproxy.muffin.license.txt @@ -1,16 +1,16 @@ -Copyright (C) 1996-2003 Mark R. Boyns - -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., +Copyright (C) 1996-2003 Mark R. Boyns + +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/lib/jsyntaxpane.license.txt b/lib/jsyntaxpane.license.txt index ad68c7d70..1d2910d6c 100644 --- a/lib/jsyntaxpane.license.txt +++ b/lib/jsyntaxpane.license.txt @@ -1,11 +1,11 @@ -Copyright 2008 Ayman Al-Sairafi ayman.alsairafi@gmail.com - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License - at http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and +Copyright 2008 Ayman Al-Sairafi ayman.alsairafi@gmail.com + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License + at http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file diff --git a/lib/nellymoser.license.txt b/lib/nellymoser.license.txt index 5fabd50e4..3ec3f1729 100644 --- a/lib/nellymoser.license.txt +++ b/lib/nellymoser.license.txt @@ -1,17 +1,17 @@ -NellyMoser ASAO codec -Copyright (C) 2007-2008 UAB "DKD" -Copyright (C) 2007-2008 Joseph Artsimovich - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with FFmpeg; if not, write to the Free Software +NellyMoser ASAO codec +Copyright (C) 2007-2008 UAB "DKD" +Copyright (C) 2007-2008 Joseph Artsimovich + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with FFmpeg; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA \ No newline at end of file diff --git a/lib/sfntly.license.txt b/lib/sfntly.license.txt index 6363a8ed5..762937be3 100644 --- a/lib/sfntly.license.txt +++ b/lib/sfntly.license.txt @@ -1,13 +1,13 @@ -Copyright 2010 Google Inc. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and +Copyright 2010 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file diff --git a/lib/substance-flamingo.license.txt b/lib/substance-flamingo.license.txt index 4918b1889..f1b0b1d61 100644 --- a/lib/substance-flamingo.license.txt +++ b/lib/substance-flamingo.license.txt @@ -1,27 +1,27 @@ -Copyright (c) 2005-2010 Flamingo / Substance Kirill Grouchnikov. All Rights Reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - o Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - o Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - o Neither the name of Flamingo Kirill Grouchnikov nor the names of - its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +Copyright (c) 2005-2010 Flamingo / Substance Kirill Grouchnikov. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + o Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + o Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + o Neither the name of Flamingo Kirill Grouchnikov nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/trident.license.txt b/lib/trident.license.txt index 8b508f15a..f78d981e6 100644 --- a/lib/trident.license.txt +++ b/lib/trident.license.txt @@ -1,27 +1,27 @@ -Copyright (c) 2005-2010 Trident Kirill Grouchnikov. All Rights Reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -o Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -o Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -o Neither the name of Trident Kirill Grouchnikov nor the names of -its contributors may be used to endorse or promote products derived -from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +Copyright (c) 2005-2010 Trident Kirill Grouchnikov. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +o Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +o Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +o Neither the name of Trident Kirill Grouchnikov nor the names of +its contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/ttf.doubletype.license.txt b/lib/ttf.doubletype.license.txt index 1405e83c5..126b8a2b2 100644 --- a/lib/ttf.doubletype.license.txt +++ b/lib/ttf.doubletype.license.txt @@ -1,24 +1,24 @@ -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 2 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, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -In addition, as a special exception, e.e d3si9n gives permission to -link the code of this program with any Java Platform that is available -to public with free of charge, including but not limited to -Sun Microsystem's JAVA(TM) 2 RUNTIME ENVIRONMENT (J2RE), -and distribute linked combinations including the two. -You must obey the GNU General Public License in all respects for all -of the code used other than Java Platform. If you modify this file, -you may extend this exception to your version of the file, but you are not -obligated to do so. If you do not wish to do so, delete this exception +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 2 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, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +In addition, as a special exception, e.e d3si9n gives permission to +link the code of this program with any Java Platform that is available +to public with free of charge, including but not limited to +Sun Microsystem's JAVA(TM) 2 RUNTIME ENVIRONMENT (J2RE), +and distribute linked combinations including the two. +You must obey the GNU General Public License in all respects for all +of the code used other than Java Platform. If you modify this file, +you may extend this exception to your version of the file, but you are not +obligated to do so. If you do not wish to do so, delete this exception statement from your version. \ No newline at end of file diff --git a/lib/ttf.fontastic.license.txt b/lib/ttf.fontastic.license.txt index 3554af743..79e0b766a 100644 --- a/lib/ttf.fontastic.license.txt +++ b/lib/ttf.fontastic.license.txt @@ -1,20 +1,20 @@ -Fontastic -A font file writer to create TTF and WOFF (Webfonts). -http://code.andreaskoller.com/libraries/fontastic - -Copyright (C) 2013 Andreas Koller http://andreaskoller.com - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General -Public License along with this library; if not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, +Fontastic +A font file writer to create TTF and WOFF (Webfonts). +http://code.andreaskoller.com/libraries/fontastic + +Copyright (C) 2013 Andreas Koller http://andreaskoller.com + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General +Public License along with this library; 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/FlashPlayer/FlashPlayer.dof b/libsrc/FlashPlayer/FlashPlayer.dof index 6a3c75bbb..20eb0ba86 100644 --- a/libsrc/FlashPlayer/FlashPlayer.dof +++ b/libsrc/FlashPlayer/FlashPlayer.dof @@ -1,138 +1,138 @@ -[FileVersion] -Version=7.0 -[Compiler] -A=8 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=0 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -NamespacePrefix= -SymbolDeprecated=1 -SymbolLibrary=1 -SymbolPlatform=1 -UnitLibrary=1 -UnitPlatform=1 -UnitDeprecated=1 -HResultCompat=1 -HidingMember=1 -HiddenVirtual=1 -Garbage=1 -BoundsError=1 -ZeroNilCompat=1 -StringConstTruncated=1 -ForLoopVarVarPar=1 -TypedConstVarPar=1 -AsgToTypedConst=1 -CaseLabelRange=1 -ForVariable=1 -ConstructingAbstract=1 -ComparisonFalse=1 -ComparisonTrue=1 -ComparingSignedUnsigned=1 -CombiningSignedUnsigned=1 -UnsupportedConstruct=1 -FileOpen=1 -FileOpenUnitSrc=1 -BadGlobalSymbol=1 -DuplicateConstructorDestructor=1 -InvalidDirective=1 -PackageNoLink=1 -PackageThreadVar=1 -ImplicitImport=1 -HPPEMITIgnored=1 -NoRetVal=1 -UseBeforeDef=1 -ForLoopVarUndef=1 -UnitNameMismatch=1 -NoCFGFileFound=1 -MessageDirective=1 -ImplicitVariants=1 -UnicodeToLocale=1 -LocaleToUnicode=1 -ImagebaseMultiple=1 -SuspiciousTypecast=1 -PrivatePropAccessor=1 -UnsafeType=0 -UnsafeCode=0 -UnsafeCast=0 -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=..\..\lib\ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=vcl;rtl;vclx;VclSmp;vclshlctrls -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -Launcher= -UseLauncher=0 -DebugCWD= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1029 -CodePage=1250 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=1 -Item0=..\..\lib\ +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=..\..\lib\ +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=vcl;rtl;vclx;VclSmp;vclshlctrls +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1029 +CodePage=1250 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlOutputDirectorry] +Count=1 +Item0=..\..\lib\ diff --git a/libsrc/FlashPlayer/FlashPlayer.dpr b/libsrc/FlashPlayer/FlashPlayer.dpr index cb89a93ba..ba8eee704 100644 --- a/libsrc/FlashPlayer/FlashPlayer.dpr +++ b/libsrc/FlashPlayer/FlashPlayer.dpr @@ -1,24 +1,24 @@ -program FlashPlayer; - -uses - Forms, - Windows, - Dialogs, - uMain in 'uMain.pas' {frmMain}; - -{$R *.res} - -begin - Application.Initialize; - Application.Title := 'FFDec Flash Player'; - if(ParamCount<2) then - begin - ShowMessage('Wrong parameter count. This EXE is for FFDec internal use only.'); - Application.Terminate; - end - else - begin - Application.CreateForm(TfrmMain, frmMain); - end; - Application.Run; -end. +program FlashPlayer; + +uses + Forms, + Windows, + Dialogs, + uMain in 'uMain.pas' {frmMain}; + +{$R *.res} + +begin + Application.Initialize; + Application.Title := 'FFDec Flash Player'; + if(ParamCount<2) then + begin + ShowMessage('Wrong parameter count. This EXE is for FFDec internal use only.'); + Application.Terminate; + end + else + begin + Application.CreateForm(TfrmMain, frmMain); + end; + Application.Run; +end. diff --git a/libsrc/LZMA/build.xml b/libsrc/LZMA/build.xml index 39c801a28..28af043d3 100644 --- a/libsrc/LZMA/build.xml +++ b/libsrc/LZMA/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project LZMA. - - - + + + + + + + + + + + Builds, tests, and runs the project LZMA. + + + diff --git a/libsrc/LZMA/manifest.mf b/libsrc/LZMA/manifest.mf index 1574df4a2..328e8e5bc 100644 --- a/libsrc/LZMA/manifest.mf +++ b/libsrc/LZMA/manifest.mf @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/libsrc/LZMA/nbproject/build-impl.xml b/libsrc/LZMA/nbproject/build-impl.xml index 951bf989a..6b452785c 100644 --- a/libsrc/LZMA/nbproject/build-impl.xml +++ b/libsrc/LZMA/nbproject/build-impl.xml @@ -1,1413 +1,1413 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.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/LZMA/nbproject/genfiles.properties b/libsrc/LZMA/nbproject/genfiles.properties index ebce23e4c..d3abacb89 100644 --- a/libsrc/LZMA/nbproject/genfiles.properties +++ b/libsrc/LZMA/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=cf8fb9e4 -build.xml.script.CRC32=0d82b5ac -build.xml.stylesheet.CRC32=8064a381@1.68.1.46 -# 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=cf8fb9e4 -nbproject/build-impl.xml.script.CRC32=fd6704e6 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 +build.xml.data.CRC32=cf8fb9e4 +build.xml.script.CRC32=0d82b5ac +build.xml.stylesheet.CRC32=8064a381@1.68.1.46 +# 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=cf8fb9e4 +nbproject/build-impl.xml.script.CRC32=fd6704e6 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 diff --git a/libsrc/LZMA/nbproject/project.properties b/libsrc/LZMA/nbproject/project.properties index 01fd54dea..26a929b88 100644 --- a/libsrc/LZMA/nbproject/project.properties +++ b/libsrc/LZMA/nbproject/project.properties @@ -1,71 +1,71 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -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 -# 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=../../lib/LZMA.jar -dist.javadoc.dir=${dist.dir}/javadoc -excludes= -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.6 -javac.target=1.6 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -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= -manifest.file=manifest.mf -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=false -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=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processor.options= +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +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 +# 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=../../lib/LZMA.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +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.6 +javac.target=1.6 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +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= +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +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=src +test.src.dir=test diff --git a/libsrc/LZMA/nbproject/project.xml b/libsrc/LZMA/nbproject/project.xml index d34c5fea1..ca4d9c5d4 100644 --- a/libsrc/LZMA/nbproject/project.xml +++ b/libsrc/LZMA/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - LZMA - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + LZMA + + + + + + + + + diff --git a/libsrc/Swf2Exe/Swf2Exe.dof b/libsrc/Swf2Exe/Swf2Exe.dof index 0955e8a7e..d2fdac623 100644 --- a/libsrc/Swf2Exe/Swf2Exe.dof +++ b/libsrc/Swf2Exe/Swf2Exe.dof @@ -1,138 +1,138 @@ -[FileVersion] -Version=7.0 -[Compiler] -A=8 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=0 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -NamespacePrefix= -SymbolDeprecated=1 -SymbolLibrary=1 -SymbolPlatform=1 -UnitLibrary=1 -UnitPlatform=1 -UnitDeprecated=1 -HResultCompat=1 -HidingMember=1 -HiddenVirtual=1 -Garbage=1 -BoundsError=1 -ZeroNilCompat=1 -StringConstTruncated=1 -ForLoopVarVarPar=1 -TypedConstVarPar=1 -AsgToTypedConst=1 -CaseLabelRange=1 -ForVariable=1 -ConstructingAbstract=1 -ComparisonFalse=1 -ComparisonTrue=1 -ComparingSignedUnsigned=1 -CombiningSignedUnsigned=1 -UnsupportedConstruct=1 -FileOpen=1 -FileOpenUnitSrc=1 -BadGlobalSymbol=1 -DuplicateConstructorDestructor=1 -InvalidDirective=1 -PackageNoLink=1 -PackageThreadVar=1 -ImplicitImport=1 -HPPEMITIgnored=1 -NoRetVal=1 -UseBeforeDef=1 -ForLoopVarUndef=1 -UnitNameMismatch=1 -NoCFGFileFound=1 -MessageDirective=1 -ImplicitVariants=1 -UnicodeToLocale=1 -LocaleToUnicode=1 -ImagebaseMultiple=1 -SuspiciousTypecast=1 -PrivatePropAccessor=1 -UnsafeType=0 -UnsafeCode=0 -UnsafeCast=0 -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=. -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=vcl;rtl;vclx;VclSmp;vclshlctrls -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -Launcher= -UseLauncher=0 -DebugCWD= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1029 -CodePage=1250 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=1 -Item0=. +[FileVersion] +Version=7.0 +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=0 +K=0 +L=1 +M=0 +N=1 +O=1 +P=1 +Q=0 +R=0 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=1 +SymbolLibrary=1 +SymbolPlatform=1 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription= +[Directories] +OutputDir=. +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages=vcl;rtl;vclx;VclSmp;vclshlctrls +Conditionals= +DebugSourceDirs= +UsePackages=0 +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1029 +CodePage=1250 +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +[HistoryLists\hlOutputDirectorry] +Count=1 +Item0=. diff --git a/libsrc/Swf2Exe/Swf2Exe.dpr b/libsrc/Swf2Exe/Swf2Exe.dpr index d5aeb1d5b..b7f87ceb7 100644 --- a/libsrc/Swf2Exe/Swf2Exe.dpr +++ b/libsrc/Swf2Exe/Swf2Exe.dpr @@ -1,16 +1,16 @@ -program Swf2Exe; - -uses - Forms, - Windows, - Dialogs, - uMain in 'uMain.pas' {frmMain}; - -{$R *.res} - -begin - Application.Initialize; - Application.Title := 'FFDec Flash Player'; - Application.CreateForm(TfrmMain, frmMain); - Application.Run; -end. +program Swf2Exe; + +uses + Forms, + Windows, + Dialogs, + uMain in 'uMain.pas' {frmMain}; + +{$R *.res} + +begin + Application.Initialize; + Application.Title := 'FFDec Flash Player'; + Application.CreateForm(TfrmMain, frmMain); + Application.Run; +end. diff --git a/libsrc/Swf2Exe/uMain.dfm b/libsrc/Swf2Exe/uMain.dfm index 28a944670..225dfff95 100644 --- a/libsrc/Swf2Exe/uMain.dfm +++ b/libsrc/Swf2Exe/uMain.dfm @@ -1,651 +1,651 @@ -object frmMain: TfrmMain - Left = 323 - Top = 163 - Width = 1007 - Height = 661 - Caption = 'FFDec Flash Player' - Color = clWhite - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'MS Sans Serif' - Font.Style = [] - Icon.Data = { - 0000010004000000000001000800EC310000460000003030000001000800A80E - 0000323200002020000001000800A8080000DA40000010100000010008006805 - 00008249000089504E470D0A1A0A0000000D4948445200000100000001000806 - 0000005C72A866000031B34944415478DAED9D0B7C14D5F5C70F8F3C8090F008 - 041523521031451E159AF8A041FEB4F28F88429428A08912B51A54A80F94FEED - 940AA258F081CADFA841010D1A10458A1695482B49E15F40298280881435BC02 - 84040328F33FBF95B50177E6DED99DDD99D9BDDFCF673EBBB0B39BBBB373CE3D - E7DC73CE6D448AA8E4FD8913F5FA8307E9686DADEF38C2CF8F1C3A4447F9F03D - E2FFF911C4B76C49F149499480473EF0989092E2FB3F1C89FC7CE0E4C98D9CFE - 4E0AFB513FAA078170EFFDEC33DAC7C7DE2D5BE8787DBD23E3689C9848A95DBB - 52DB6EDD28950FA524BC87FAC15CCC5B85853F0A7ADDAE5D4E0FC7122DD2D27E - 540C571417ABFBCCA5A81FC645BC326488BE7DF9729F791E8DC09DE83460005D - B778B1BAEF5C82FA211CA474D8307D7B7939D557573B3D1447486CD3863A6567 - 53DEC285EA3E740875E123C8EB7979BE19DE6BE67CA480DB000BE1EAD252755F - 460875A1C3CCCB8306E9DB962D737A189EA4F3A04174FDB265EA1E0D23EAE286 - 8137F2F3F58D656551EBCB471AC40EBAE7E6D255B367ABFBD566D405B5092CCD - 7D3C670ED5ECD8E1D8185A356942CD1B35A284C68D299E1F7124F21177E27933 - FEFF383E2F911F134E3C07C7F83872FC38D5F381E7DFF2E3515DA7637CD4F371 - F4C481730EF3E381EFBF77EC3B26A7A753CFD1A3D592A34DA88B1822C59999FA - 57959511FB7BCD5890539B36F51D6D59E053F9687BE27924D9C74A60DF77DFD1 - 5E3CF2B117CFF9F8961544A4382333930A2B2BD53D1C02EAE20501D6E7D7CD9E - 4DC78F1D0BDBDFC0ACDD312E8E4E83B043D04F083D667437038BC1AF0CA01CBE - E1C79D7C9D8E85513134E6EBD42B3F5FE51B0481BA601658306A94BE61FEFCB0 - 083E04BE030BF8D9F1F1D4858F347E1EE77261B7C2177CCDBE3C7A94BEE0A38A - 95423814021441C68811347CEEDCE8B97061465D2809E6E7E6FA827A767326DF - B0387E9690401DA34CE0CD80F0EF6425F0F99123B49D15C2D7FCDC6E10341C51 - 56161B173404D40532615E4E8EBE65C912DB3E0FFEFBCF1313A90B0B7C2716FC - 581178115008DBD942D8CA0AE15FF5F5B6C611BAE6E4D0C8254BD48536405D98 - 00CC1E30C097B0630710F27359E07B356B4667C7C585FE813100DC8575DF7E4B - 9B5821D8E52A20C1287FF97275BF9F82BA200D783E2B4BDF595161CB67C197EF - C1829FC133BE9AE98303C2BF812D82F5AC08103BB0838E595934A6A242FD2027 - 501782595450A0AF2B2909F973DAB31FDF8305BE271F498D1B3BFDB5A28ADAE3 - C7E96328033E76DB1033E8555040579694C4FCFD1FF317606A9B367A28C53898 - DD7BB1C0F766131F517C45F8C12AC25A7611D6B13208C5454031D284EAEA9896 - 8198FDF2CFF5EBA77FBD6A55D0EF87E0F765A1CF6CDE5CCDF60E01ABA0F2F061 - 5ACDCA201445707ABF7E74F3AA5531290B31F7A5971415E9AB67CE0CFAFD88E4 - F765A187E0BB3D29275640F2914F11F011CA0A42DFA222CA993933A67ED498FA - B2D3D2D2F4604B7121F817B568E19BF55550CF9DC00A8035F0515D5DD08AA045 - 870E744F5555CCFCC031F1454BB2B3F52FCBCB837A2F0A6CFAF36CAFA2F9DE01 - 8A00F1810AB608822D5C3A2B3B9B0ACACBA3FE078FFA2F382931510FA669A65F - F0B17EAFF02EC8275811A42240D3D307EBEBA35A46A2F6CB059BBE8B593E8B05 - FF223ED48C1F1DC022F88895002C82608285D19C561C955FEA892E5DF4FD5BB7 - 5A7E1F9277FEBB65CB8897D62A2203CA96FF72E850504945ADBB74A13BB76E8D - 3A7989BA2F34292E4EB75AAD87001F041F7EBE22FA4176211481D54021AA0D1F - 3C762CAA64266ABE0C3AEC6E5AB8D0F2FB10D51F80DD6F94B91F53C01578AFB6 - D6B76A609573870D8B9A4EC651F1251EEFDC593FB06D9BA5F7A00C7730CFFA2A - 7B2FB64156E1DB3535964B925B75EE4C776DDBE679F9F1FC17B06AF223B03798 - 677C15DD573404AB054BD922B012248C0697C0B3830F26CA7F3ACFF6D7A4A450 - B20AF2290250F3FDF7F4DAC18396AD012FAF127872D0C1D4EBC3D787C9AF5088 - 587AE890E5D88057FB0D786EC0B37AF7D6ABD6AE953E1F11FEA1C9C9744E4282 - D343577888CD478ED09B353596560A3AF4EE4DB7AE5DEB2999F2D460ADAEEF2B - 935F110AC1B8045ECB17F0CC40A775E8A0D75555499F7F61F3E6F45F49494E0F - 5B110560B970E5E1C3D2E77BA9A0C813839C9294A4CB6EB3A54C7E4538B0EA12 - 603BB3076A6B5D2F5FAE1FA095621EB4E41AD5AA956AD0A138097F1BF24DFCB8 - 95CDFAADFCFCE77CAF145A5C0A864BF00ABB04B22DC9BC504CE4EAC15959E347 - 1EFFD5ECEFAB8CBED8E4C0F1E3B48D8FCF5948716CE763CB89E7DFF071EA5D74 - 330BFFAC205685A04C4A5909C8D613B83D57C0B503D388A4C3AFDDD9DC87F02B - 6283AF58D03F64015C81F6E13C1B6346AFB698D7FF5B56004F07B92C0C25B088 - DD818DEC16C8A2B954D65C3928CD82F0ABF5FDE807FB047CC8B378F909A1DF6E - C3EEC4C15A000DB19A2FA0B950DE5C37202B667F768B16D49F0F4574B19167F4 - 0F21F438B09720CFF876138A05D09015757554CE870C6E74075C35182B01BF2B - F8C753F9FCD10384FE25FEED4BD9ACDE61C30C2FC20E0BC00FEA08DE626B4006 - B705065D3310D9A53E14F3E4B2BFDF353EDEE9212B42640FCFEC10F812F4F80F - C306A166D86501F8C132E1829A1AA96222372D11BA6210B2493E58E3BFB6552B - EAA8F6D8F32C68E1BD98CDFAB93CDBBF83BDFF1C1A879D16809F9DECB2BC7AE0 - 8054AE805B92851C1F806C7A2F847F74EBD6AA7EDFA354B070C0C47F958F4336 - EEFEDB90389E183A75EAE43BBA76ED4AEBD6ADA3952B57063CD76E0BC00FFA0B - CCD9BF5F4A09B8216DD8D13F2E5BD803B37FB49AF93DC7376CE2CF62F37E0E0B - BD1D91FB86B464E1CDCCCCA45FFDEA57949595455D5898CE3CF34C6AD4200F64 - C28409F4C8238F047C7F382C003FB004E6B02520E30E385D40E4D81FB652D29B - C73EBF4AEDF50E58A79F525747B359F043D9A9A721EDDAB5F3097A7676365D7C - F1C5D4B3674F8A17C481CC1440B82C003F880920614806274B891DF9A3569A79 - A868BF77B053F021F003070EA44B2EB9C427F4DDBB773F697697C1290BC08F95 - D501A79A8A38A20034C9441FB5CEEF0DFC82FF3C36E90CE173E0C30F1932846E - B8E106BAECB2CB8433BC08272D003F56F2043407E431E27F5036D14765F8B91F - 44F435BEB96760C38D103EA75FBF7E3EA1CFCBCBA3366DDAD8363EA72D003FB2 - 19834EE40844F48FC976EF55B9FDEE6711FBB877D5D6069DB4939E9E4E23478E - A4FCFC7C3AE79C73C232463758007E5E3F7850AA7620D2DD8623F68764FBF6A3 - AA0F413FB52D973B415E7E11CFFA4B83D85D0791FB2BAFBCD227F403060CB0EC - D35BC52D16801FAC0CC854114672DF8188499926E1F7A39EFFA6D6AD95F0BB10 - 98FBD3D9D49FCC87D5001F027877DF7DB7CFC46FDEBC79C4C6EC260B00E01ACE - DEBF5FAA9F801621D98CC81F91F1FB91E8730BFB7FAA7F9FFB409EFE556CC26E - B668EE43F0274E9C48D75D775DD867FB40B8CD0200682AF2BFD5D542251AA9C2 - A1B0FF01D94C3FA4F8AAFC7EF7F14A7D3D155ADC47CF69C1F7E3360BC0CF1676 - 0390322C2212998261FD70D9F57ED5C0D37D208B6D6C6D2D3D67A1DEFDB4D34E - A369D3A6392EF87EDC6801F8916D341AEEFC80B0FE4A9A84DF8F3DFA0AD8EF57 - B80704FA86F3AC2F5BA187F5FB5B6FBD951E7AE8214A4E4E767AF83FE2560BC0 - CFF3EC0AC8B41CD7C228A761FB6099DA7EE5F7BB0F2CEFDD5053235DB08335FC - 679F7D96FAF4E9E3F4D07F829B2D00201D0F08637E40583EB4243B5BFFB2BC5C - 789ECAF17717C8E6FBBD64D65A6BB6DA205C63C68C7185B91F08B75B0040B666 - E0ACEC6C2A282FB7FD4287E597D3244C7FE5F7BB8B89EC933E2CB9F945FFFEFD - A9B4B4D4E7F3BB19B75B007E64E3015A18E4D5F60F9C9696A6D7EDDA657A0EB6 - EC1A6363CAA722347EC737E00C49E1BFEFBEFBE8E1871F76EDACDF102F58007E - 64E2012DD2D2E89E5DBB6CBDF0B67ED892A2227DF5CC99A6E720C9E776E5F7BB - 863B0F1DA2A72422FD30F9E7CD9B4783070F767AC8D278C5020088073CCD4A40 - D443A06F5111E5CC9C699BDCDAAA003409D35F95F7BA87DB59F89F95107E04FA - 5E7FFD755FFEBE97F092050064CB87351BE5D6B60F7AAE5F3FFDEB55AB4CCF51 - A6BF7BB8956F349935FEC2C2429AC9565DA8A5B94EE0250BC04FC9FEFDF46F41 - D6ECE9AC906F5EB5CA16D9B54D016812B3FFCD2CFCAAA79FF3C8CEFCE3C68DA3 - E9D3A73B3DDCA0F19A0500D053F0397605446836C9AE2D1F32B54D1BBD5E3068 - 55DFEF0ED09F0FEBFC22EEBFFF7E9A32658AD3C30D092F5A0040A67F40224FA6 - 13AAAB4396DF903F60514181BEAEA4C4F41C24FCDC959AAAAAFC1C660DCF2E97 - 4874AC45461F72F9BD8E172D008040E0E37BF70A7FA75E050574654949484215 - B2446A12A6FFF0E464CA484CB4FB3A292C80DD73FBB0F08BBAF3C2E487E91F0D - 78D502009B8E1CA1D7241284B4106538A4373F9F95A5EFACA8303D070D3ED0D2 - 5BE12C39070E089B783CF1C41374C71D77383D54DBF0AA05E047A68148C7AC2C - 1A535111B41C87A40034C1EC0F931F81BFB66ACDDF51FE5057477F12A4F8DE76 - DB6DF4F4D34F3B3D545BF1B20500F6B3B5364B2237400B418E837EA34C5F7F74 - F4CD565D7D1DE56D3625AF109892175E78212DE7DFD28B4B7D6678DD0200E828 - BC42A0BC43D957206805A00966FF563CEBFF96677F15F8730EF8FDDD7806D963 - B2BD36F2F9FFF9CF7FBA3EAF3F18BC6E0100CCFECFF26F784010BBD18294E5A0 - DE342F2747DFB26489E9392AE3CF794439FEA8E3FFF0C30F7D3BEE4423D16001 - 00990CC1AE39393472C912CBF21C9402D02466FF3BDAB68DE435529C02FAF85D - 2058F283CF0FDF3F1A387AF428FDFDEF7FA7F2F272DAB06103AD5FBF9EB66CD9 - 6278BE572C003F4FEEDB17162BC0F21B64DA7C21E1A7AF9AFD1D4514F52F2828 - A0175F7CD1E96186C461B66EDE7BEF3D5AB46891EFD8CF0A4F162F5900008941 - 4B05564030EDC32C2B004D30FB23E9E79E76ED9CB8468A132C63C1FF8D49D349 - F8FB5BB76E8D688B6EBBD0D9A259BC7831BDF4D24BB46CD9323A24B9F7DEA978 - CD0200D3F6EC112607691665DAD2C90B468DD2D7CF9D6B7A0E9A7C5CE8C11B2B - 9AF87975357D6A525B3E977F43ECCAE32520F8A848449622CCFB50F19A0500D0 - 3404CD43CCE8316A140D9F3B575AAE2D2900517F7F95F2EB3CA8EDBFD36456C4 - 921F7C652F34F40010FC3973E6D0D4A95369E3C68DB67DAE172D00991461ABFB - 09489FF85661A1BEA6B8D8F41CB5EEEF2C58F6EBB26F1F551BDC20717C7CB46A - 15F5EDDBD7E9A14AF1C1071FF8BA0D9B05F382C58B160090C90BE85358485714 - 174BC9B6B40210CDFE98F5C7F1EC9FE89199251A1165FC7925F0575353E3AB46 - 7CE6996742FE2C28BDB39B34A1F39B36A55E7C9CC74737FE77778F96A5637BB1 - 196C051CB3C90A9096564D10FC534D3E9DA713CFFE46BBF562634E04FEDAB76F - EFF4304DF9EB5FFF4AB7DC720B6DDFBE3DA8F7A7B3700F8D8FA70B58083220F0 - FCEF689B94649A886A92B22D75527166A6FE5565A5E1EB98FDC7B66D4B498D1B - 3B7D6D62162CF9E59844FE911073EFBDF73A3D4C43E0EB1715150535EB63561F - 9E904043F9E8E3D199DD0A3256C019999954585929946F2905A009667FD5ECC3 - 79AE397890CA0CF69FC7ECBF73E74E57EDDAD31098FCB9B9B9BE653D5960DA8F - 4A4CA4BBD9F2F4AA391F0A324D433409F9169EF0FEC489FADF264F363D47B5FA - 7216E4FA77C48C60F0BA9B7DFF6DDBB6D1E5975F2E1DE187E08FE109E76E16FE - B3E3E29C1EBE63C8B40EBB64E2441A3879B2A98C0B15C0F4F474BD66C70EC3D7 - DBB3E0DFAA1A7D3ACA34F607EF33591F5EB972A52BF3FD57AF5E4D393939B467 - CF1EA9F30B58E8272525D119CAD5F48152E1DD26F91EC9E9E9347EC78ED01480 - 2630FF07F20F72914AFC719473F7EDA3CD06C1BF1E3D7AD0279F7CE2F4107F02 - 847FE0C08152997C1D58E05F60F7657094952B878A4C6290269071D317DFC8CF - D73F9E3DDBF40F8C4F4D55C13F07A938768C2E32C9817763971F28A4ECEC6CA9 - DC7DCCFA7FE649A695BAC77E422DBB7ED3D9F533A3677E3E5D357BB6A19C9B2A - 80294949FA51130DA3DA7D39CF4D35355462B00B7333F69511FC6BE322170D3E - FFC5175F4CDF7CF38DE979C82A9DCDB3FED56AF35853446DC3E259793E505B1B - 9C02D004E6BFAAF9779E54F69F8D32FFF2F2F2E8D5575F757A883F02A1472AB2 - 688DBF1DCFF66FA7A450DF180EF2C922D32B40339173C3175E1E3448DF66B22C - 83B5FFBB55DEBFA3A0E63FC32412FCFEFBEFD3A5975EEAF4307D609D1F3EFF72 - 411BB99F376D4A4BD9AA54813E39900BF0982027A0F3A04174FDB2650105D550 - 7A35C1ECDF837DB3AB5CBAAE1C2B14B3F6BFC540FBB76BD78E76EFDEEDF4107F - 64C68C19347EFC78D37390D0F321CFFCAA89AC35DE603770BD811BE8473390F5 - A015C0B5ACA5BBAAA8ACA398F9FF575C7105BDF9E69B4E0FD107827E175C7001 - 1D33A925410A6F45EBD6749A9AF92DF3055FD7398280AA664501BC9E97A76F28 - 2D35FC30D5F4C31D982DFFB925F517ADBA20FC6635FCF0F92B79E68FE5C49E50 - 11350BC9C8CBA3AB4B4B7F22EF0115C0B4B434BD6ED72EC30F53A9BFCE83D2DF - 36264B4068F6D9BF7F7FA787E933FB61FE1B81C6A4157C2FC5420E7F38111508 - B5E8D081EEA9AA9253009AC0FC1FCDA69AD2D6CE6256FC03A13AC0AF39DDF20B - F5FC08FC998135FE712A912C64B6F0FDF0AA493118D002C87B500AE07E36FF55 - F4DF59CC6AFFFBF4E9E3EBF5EF24D5D5D5D4BB776FDA6192463E283E9EDE5579 - 24B620B31AA0C92880D261C3F44D0B171A7EC8993CBB14B005A0709681ACED97 - 1B24808C1D3B969E7CF24947C777EDB5D752A9491C097EFFBA366D54D0CF464A - F6EFA77F9B045ACF1D368CF2162E3C49E67FA200A6B669A3D79BAC2DABC61FEE - A08549D0C7E9A69F6BD6ACA15FFCE217A6E7CC4F4951597E36236A1796C80A77 - 4275B5B902D094FFEF7A4409405F7EF925A5A7A73B36BEA14387D25B6FBD65F8 - 3AF2FB5F503924B613CC72A02505A0B2FFDCC12BF5F534AAA626E06BE8F9FFF5 - D75F3B3636ACF9F7ECD9D3F0F54E4D9AD0273C89A80232FB09260E70D23F5E19 - 3244DFBC78B1E19B95FFEF0E26D4D6D2A3064B3EC3D8CF5BB0608163631B3E7C - 382D3489217DC8F7CF25CA820C1BA238C0394386D0758B17FF28F727290051F5 - 9F6AFBED0ECC0280D83863E2C4898E8CEBD34F3FA58C8C0CC3D755D43FFC88E2 - 00A756079EA4003481FF7F236BEF8E4A7B3B8E5905E05FFEF2171A3C78B023E3 - 1245FED5EC1F7EACC601A41580F2FFDD017EE09F99FCC0F0FF1107883498FD7B - F5EA6598EF0FC1FF50B98F11E1619E2064E3003F3E11EDFCA39A7FB88345478E - D0B0830703BEE66405E0F5D75FEFDBC2CB88F7F9DE19A08AC72282A84948C39D - 837E54002FF6EFAFEF58B1C2F04D6AFDDF1D986500C2F4870B1069D0D63B95AD - 43A3D93F8B67FF8FD4EC1F31447180F4FEFDE9C6152B4E5600D33A74D0EBAAAA - 0CDFA4BAFFB803E4FF2F35D0EED84E6BCA9429111F135A8EDF74D34D86AF2FE1 - D95F35F48C1CA22E412DD2D2E89E5DBB4E56009A0A007A82D3F7EEA5AAE3C703 - BE367FFE7CBAE69A6B223E26741D32EAF483FDF8D6B8A827612C20B367807642 - F6A515C0BDEC5F46DB1E6B5E031B80A49994007FFEF9E7D4B973E7888E09C53E - 679D7596E1EB4FB0E53856598E11055B873D2AD86B41B3A20054031077605602 - 8CEDBF0E1E3C488D22ACA41F7DF451BAEFBEFB02BE067B717B6AAA2AF8710051 - 8310ADA102106DFFA53200DDC1D4C38791C411F03534FF4013904873FEF9E71B - 76FB51893FCE21CA08F46F1BE65300F37373F58D65658627F766136E88EA00E4 - 38B93CC32F34D80074DCB871347DFAF4888E4794F9F7627232E5272646744C8A - 1F587CE810AD35D93CB47B6E2E8D282BFB41013CD3A387BEDBA4671B96FF2E54 - 5D5B1CA7F3BE7DB4DDA007E04B2FBDE45B8B8F24D8CAFBF6DB6F0FF81ADCC65D - 6ACB78C7106D1BD6BE470FBA6DFDFA1F14C0A4C444FDB8495B61D501D879443D - 003FFEF8639F391E49468C1841AFBDF65AC0D786252450594A4A44C7A3F80FA2 - 16618DD9327BB0BEFE0705A00956006E674DAE7AB53BCBDFD89FFB95410A30B6 - 00430FC0F8082BE9D34F3FDD708BAF67D865BCD562F41FD1EB437CF8B31C603B - A0552882895881C21DA852D1E5D8C796E2D36C319AA111C9298007DBB777FAFB - C43C33D8A4FB9D8149E7440FC0CD9B3753B76EDD0C5F47F61F76F769CEB7D861 - 16EA3A3E0EF081C834FE5DC3079C995A7EFC8E8F63F27F9AFCD9284DF9B3FD2A - 269E9FE380D2883FF1EFF1ECB6C6720C6292202D5C935100AD78E6BF832D0085 - B3E4D7D4D0CB066E5A6161213DF7DC73111D4F717131DD7CF3CD4E5F1653A624 - 25D184188E5D3DC916C001839811D06414C0E94D9BD21895C9E5384800DA6390 - 01F8F4D34FD36DB7DD16D1F1888A7FDC40AC2B80E7ABABE9EBEFBE337C5D9351 - 00AA0AD0792AD8FFBFC8A40418E63FDC804872F6D9670B77F9759A585700A2AA - 400D0A409404D42D218146A868AEA34C64DFFF618316604EF40044E00F0140B7 - 13EB0A60FEC183F49941DE08403250A3254545FAEA99330D4F524940CE733E9B - 72FF3230E59CF0FFE7CD9B47A3468D72FAB20889750520DA35B86F5111357A23 - 3F5FFF78F66CE393D43E808E22EA00841D80B113702441F20F9280DC4EAC2B80 - A5870ED16A936CC09EF9F9D4489406AC1A813ACB53FC03DE6950DB8D02A0AAAA - AA88EF01880620C83BA8E7D9A596DD131C757575F42D8F15C7617657F088D771 - 24262652120B63C303FF87FC85047631F11CDFA5499326BED7F0FF286AC2CEC2 - DFB1E5E33F8EB0398BA623FE7FE3B3274C98404B972E0D38CE585700A20D4391 - 0EDCE8E54183F46DCB96199E04E1EFAF148063987500C6CC0F0B2096316B441A - EB0AE02316FEF74DD2813B0F1A448D9ECFCAD2775654189E04F3BFAFAAE77684 - 0327EAFF8D92645E78E105BAF1C61B9D1EA6A398A523C7BA0280F9BFD4A433D0 - 199999D4E8E98C0C7DCF860D8627A95660CE61B6031070AA03B09B501680311B - F8FE596072FFB4CBC8A046D3D3D3F51A932D9CAF4949A173D5268E8E702DFF78 - F30DA2B8FDFAF5A37FFCE31F4E0FD17194023066D39123F49A410769909C9E4E - 8D44BB01ABCD409D017DDD53D9FC3F64D0D5C5C91D80DC845200C6883609C16E - C18D26C5C5E9C74D3A87DCCC277568DAD4E9EF127320F037D0A49CD389F25F37 - A21480313B59AE5F3451008D7962172A00D50DD819B0F4F794C11A6EA74E9DE8 - 8B2FBE707A88AE4029006344DD817D0A40B900EEC4ACFBCFD8B163E9C9279F74 - 7A88AE40AD021823E502A820A0FB40DAEFF9264AF9DD77DFA55FFFFAD74E0FD3 - 15280BC018A920A068197078723265C47053052740E38F1906195CC898DBBB77 - 6FC4BBFFB815A5008C11ED10E45B062CCECCD4BFAAAC343C4925024516B4C54A - 3389FE63E71FEC00A4F801A5008C914A0412A5020FE48B78510C5FC44853CC3F - DA2D263F1A36FFC426A08A1F50310063A4528145C5406A57E0C8D2877DFF7506 - A5BF88FE6FDBB62DE2BBFFB81965011823550CA4CA81DD83A8F3CF238F3C42F7 - DE7BAFD3C374154A011823550EAC1A82B887913535F4AA41EA6F5C5C9CAFF4B7 - 8DEACF78124A011823D51044B50473071BD9ECEFC5E6BF514AD6E8D1A3E9E597 - 5F767A98AE43C5008C916A0986279A6A0AEA3866B33F58B97225656565393D4C - D7A12C0063A49A829E78A2DA823B8868F67762E30FAFA0148031B6B405571B83 - 841FD1EC8F757FACFF2B7E8A5200C6D8B23108505B83850FCCFE192669BF3D7A - F4F055FEA9A5BFC0280560CCC37BF6F8CACA8DD0641580DA1C347CE4B09FB6D4 - C44F5BB060010D1B36CCE961BA16A5000263697350D1F6E0792929748E2A08B2 - 9D45478ED03093620DE5FB8B510A20309BF9DE2A35B9B74EDA1EFC991E3DF4DD - EBD71B9E8C4CC00B63F442860BE4FC9FCBA6FF0E131FCD899EFF5E432980C020 - 03F03D9334E0F6EC5ADEB67EFD0F0A40940EAC9281EC6702FF388F9AA469AA9E - 7F7228051098C5870ED15A932C40A4018F282BFB4101889281CE8C8BA382D6AD - 9DFE4E518368D90F38B1E1A717510A203025FBF7D3BF4D3A7D210968E0E4C9FF - 092D6B2681C0667CDA3DEDDA39FD9DA20244652F3970805699FC38D8EA1B5B7E - 2BC4A84CC0C04CDBB387BE15AC00E0514A01807B590124AAA5A890316BF601D0 - E77FD3A64D949C9CECF4503D81B2007E0AE24B8FB2023043B3AA005477E0D079 - FBC811BAC224320BE6CE9D4B23478E74749C2B56ACF0EDBBF7FDF7DFFBF6EB6B - F8084EFDBF501EC1A99FDFF06F3424D0FB27B3EB8AF10622561580A81B30D04E - 5500D3D2D2F4BA5DBB0CDFA076080A8DAF8E1FA79EFBF651B589593660C000FA - E0830F1C1D2736FE4C4D4DF56DC2E975625501885A81B5484BA37B76ED3A5901 - BCD8BFBFBEC3409302B54B70F0608FBF4BD9EF5F6792978D5E7FEBD6ADA3CE9D - 3B3B3A56F8D3F0ABA381585500E57575B4820F23D2FBF7A71B57AC385901BC55 - 58A8AF292E367C93AA0A0C8E5A16FEFE02E1076EC9F7C766A32525254E0FC316 - 62550188AA00FB1416D215C5C5272B00A099C401E21A35A2FBD54A802520FCFF - C53EFF2A81395DC83FC873CF3DE7F4707DB46FDF9EF60802485E211615005699 - 1EC38ED2122B00405A0100B54B903C88C4FE8635F1DF04C28F629FCACA4A6AEE - 821B75F5EAD5BE04A468211615809500203849018876095271003920FC393CF3 - 2F3731C300FC7E08FF79E79DE7F4907D4C9A3489FEF0873F383D0CDB88450520 - F2FFB11BD084EAEAC00AE0952143F4CD8B171BBE5965048A81E975250BFF5281 - F0376BD68CDE79E71DEADFBFBFD343FE915FFEF297B46AD5AA80AFB5611730B5 - 7163A7876889DFB1F017C6D8CA952803F09C2143E8BAC58B032B00A009E20077 - A7A6FA1E153F05C29F5B53438B4DFAB00108FFDB6FBF4D975E7AA9D343FE91DD - BB7753C78E1D0D97FFE6A7A4D0D5AA22D4D558F5FF81250500D466A181C152DF - 0D870E4909FFA2458B5CB7B71F1A8EDE70C30D015FC3AFBD8B157F2B8F5900B1 - 86683350A08914808A035807FDFCAFE599DFACB417A0B5775959992B4B7CCD52 - 6A07C4C7D3FB6A09D8F588360239D5FF073F5100A5C386E99B162E34FC101507 - 3899297575F4473E447973107E08981BBBFB1CE69B06E6FF7E83D9E391A424BA - 27C682695E44E4FF9FCBF75EDEC285E60A0068023700F900B11E07406AEFF53C - EB8B22FD00C28F1C7F3724FA04E2C9279FA43BEFBCD3F0F50D3C7374577520AE - 067EFFC39205400D094A015CCBE660D718DE9E1A453D37B1BFBF87958008083F - 32EB9C2EF031E2282BB06EDDBAD1F6EDDB03BEDEA94913DAA6BA42BB9E60FC7F - 1050014CEBD041AFABAA32FCA058DD3014EBFBF7B19FF59449A7958640F867CD - 9AE54BAF752B66C13FF03F2D5AD01F55CCC7F588F6016C5800D490800AE0F5BC - 3C7D83414008C46283106CDBFD07F6F5AB24667D809D7C5F79E51557EFE6A3B3 - 42CBC8C8A08D1B37067C1DBFF30E36FF554768F723DA0320232F8FAE2E2D9553 - 004053CB813ED0B917FDFB360B22FC0D81AF5F5C5CECFAA61E6FBDF5160D1D3A - D4F0F5716CE9FD39062D3DAF11ACF90F0C15C0A4B838FDB84944B14762225DE5 - F21B3C1490C30FC1AFB050178F35FE993367BADAE46F8859E61F54FBB6D4543A - 43ADFDBB1ED12EC040B3AA005E1E3448DFB66C99E107466B56E0BFBEFBCEE7E7 - 8B52794F05453D58E6734B5EBF08341E193870A0E1EB05ACE05F8862051F2DC8 - 64FF751E3488AE5FB6CC9A02009AC00D88A62E4130A3FEC87E3EF6E8B3DA0B67 - ECD8B1F4D8638F51BC47564610F9EFD5AB97A1EF0FD4D29F371075FF019A899C - 9B2A80294949FA5193CD05A2A14908D6F11FE78B284AE10D44EBD6AD69F6ECD9 - AECCEC33E381071EA0871F7ED8F0F5DC84047A2D25C5E9612A241035FF884F4A - A2076A6B8353006FE4E7EB1FF30D6EC6787603923CE62762396F0ECFF458CEFB - 97A0534F20B0BC57545444BFFFFDEFA98DC7B64E5FB3660D6566669AF6FCFB3F - FE4E7DD4ECEF7AD070663A9BFF66F42A28A02B4B4A8253004013B8015EDA360C - D97B4F1D3E4C252CFC32493CA702C1CFCBCB234DD31CEFDD170C30FD2FB8E002 - 5A6FB20DDC109EFDDF54B3BF27106DFF0534818C0B15C0F4F474BD66C70EC3D7 - DBF34C71ABCB674144F2D18BFF4D36F383ED753B78F0609A3A752A9D7FFEF94E - 7F9DA079F0C107E94F7FFA93E1EB2D1B35A24D6DDBD2691EB3E8629559D5D5B4 - DBC4824D4E4FA7F13B7684A60044DB8601B7EE198035FC497575C2869C66A045 - 16FC6537D5EE07838CE9FF627232E527263A3D548504557C4F3F6752B50BFCDB - 7F999D23B586A709DC80BECD9AD160176E1E3AF4E0C1A0827BA06BD7AEBE19DF - 8DD57B5641B51F84DFCCF41F141F4FEF7A3CA01B4B88527F812621DF520AA038 - 3353FFAAB2D2F075E4028C4B4D75DDD661B9AC00165A540068D185CAB8ABAEBA - 8A1AB9ECFB0403D27D73727268E9D2A586E7C0F4FF944D7F95F4E30D10C49E21 - 58FB3F83157E6165A53D0A0068022BC08D0542B2160032F810DCBBEBAEBB3CED - E307E28E3BEEA0A79E7ACAF49C67D87ABB354AF239620151E30FA049CAB6B402 - 989498A81F37493774A315205200D888F3F6DB6FF7F5E5473FFC6863C68C1934 - 7EFC78D37354B71F6F2133FB378E8BA3078F1DB3570188760E026815D6DF45A5 - A3660A005B704340BC92BD671551A10F80E9BF8E853F168ABAA205B4FC2E3769 - FB0D1AEEFC23C2D2742D2A1042F9E85D2EAA0F3053004F3CF184CF3C8E4610F1 - CFCECEA6432629A210F97758F80744A9028C4630EB3FCEB3FFB736CDFEC092A4 - 2E18354A5F3F77AEE9396E4A0C325300D3A74FA771E3C6393D44DBD9BC79B34F - F8BFF9E61BD3F3D4929FF79049FCE9316A140D9F3B373C0A00C858016E691662 - B60A108D0A0033FF65975D26DCDB4F75F9F126D3F877359BFD816651A62D2B80 - F9B9B9FAC6B232D373DC5225184B2EC08A152BE8F2CB2F3735FBC1F53CEBCF56 - 65BE9E036BFE4B05BF6DF7DC5C1A5156165E050034C19260AB264DE80E173492 - 8C150580801F9631BF1524865CC2FEE17BECF7BB2546A39047D4F20B6841C873 - 5077C2BC9C1C7DCB9225A6E7B8C10A888518C0BC79F3A8A0A0C034C5179CC34A - B9B2756BB5BB8F0791A9F93F75CF3F59829E0A34092BE0B76DDA383ADB44BB02 - 78F4D147E9BEFBEE139E87D6DEEFB3D9AF96FBBC0722FFCF56578765F607414B - E7EC0103F4EDCB979B9EE3F43662D1EA02D4D4D4F866FD85263B38F939AF6953 - 5F8EBF4AF3F526A2EDBE41A70103287FF9F2C82A00A009AC00CCFEBF6DDBD631 - B3D36C15C0AB0AE0934F3EA1DCDC5CDAB2658BF0DC7E3CE3BF9392A2CC7E8FB2 - 8F677D54FC1DB339F2DF909014C0F35959FACE8A0AD3739C6C1B166D2EC08B2F - BEE8EB44240AF60124F8BCC966BFD7BA3529FE83A8DD17E8989545632A2A9C51 - 00401358016038DF88190E249D448B0B80725E083EB61893015D7DCAF89AAB68 - BF77D9505F4F0BD8D513A18528C321DF218B0A0AF475821B130141340D8974A1 - 503458009F7EFAA96F89CFAC96BF21AA9DB7F79149F905A27E7F32D8229153DB - B4D1EB05DD499C2817F6B20580FE7D0F3DF490AF298968890F20BEFF47BEBE13 - 5C9286AD081E9972DF449E50275457872CBFB64DC99A842B10E9D6615EB5002A - 2A2AE8A69B6E32EDDBDF900EECE7CF4F49F125FA28BC8D4CAB2FA0D924BBB629 - 0051D7207026DFA005AD5BDBF5278578AD1600CB7B68352E6AE0D11004FB4AD9 - E46FA7827D5141C9FEFDF46F81C527DBED47065B9D7251A110886486A0975C00 - A4F36287A11D261D984F4515F5441732197F40B3516E6D55004B8A8AF4D53367 - 9A9E83C8F4EDEC0A244760CB692FB800AB57AFF665F32D1724553504B33D0A7A - 06AB5AFEA8A1E6FBEFE9698935FFBE4545943373A63B1500989696A6D7EDDA65 - 7A4EA45C01375B00DBB66DA3FBEFBF9F5E7BED354BEF43F75ED4F2ABCCBEE8E2 - 7916FEAF05EDEB5BA4A5D13DBB76D92AB3615997D3240282915815709B024087 - DEFDECE36167A159B3664945F7FD60D67F8CAFD768D5C423EA9089FA032D0CF2 - 1A160550929DAD7F595E2E3CEFDA56ADA86B18CD5837B900E8D083E0DE4C7691 - 4435FB3FB94E2CF48FB3F0AB405FF4B199EFCF52BE4F458492EF6F46D8327344 - 5D8441B313B502E14A5775C32A0072F7B175786969A9A5191FA4376942CFB66C - A97CFD28057EFFFFB2E92F4AF869CC13C083F5F56191D5B0A6E66912AEC0E94D - 9BD29830ED2DE8940B0053FF9D77DEA169D3A6590AEEF9C16AFE9866CDE8CF3C - EBBBA9CDBAC25E64FC7EA085514EC37A77C9B40F03E18A07445A0120671F0D3A - D06E5C3689E75490C73FB5450BEAEEC2BD1615F621EBF767E4E5D1D5A5A5DE54 - 00E0892E5DF4FD5BB70ACF0B473C20523180DDBB77FB7C7B04F6440D398DE8C5 - 02FF049BFB2A9B2FFAD972F428BD7AE080F0BCD65DBAD09D5BB786554623625F - CAC6036EB1393F20DC0A00FEFDE38F3FEEF3EF654A7403816E3D0FF18C7F9D8A - EEC704D27EBFC5FEFEC112310753938807B4E759F0A6D6AD6D2B630D870B80F5 - FB575F7D95E6CF9F2F5DA11708E4EF8F63D7E72EF6F555D96E6C80249F17F6EF - A7DD0EFBFD0D89D89D573A6C98BE49A285959D0D44ECEA088425BC3973E6D082 - 050B68D5AA55218DE9E7ACE4C6B3E08F645F5F097EEC00E1C7729FA8C1073877 - D830CA5BB830BA140078BC7367FD00CFA022BAB3705C9D9212F2DF0BC50580D0 - BFF1C61BBEA0DECA952B431E0B32F8EE66C11FA496F46292D7F95EDC28B15375 - ABCE9DE9AE6DDB222697119F8264E201A02F9BC6835BB60CE96F59550028C479 - F7DD777D267E30CB77A782705E017F8F3BF95051FDD8051B7AAC9688118573BD - DF08476C504D221E0042DD6D58140340A79DF2F2727AEFBDF768D9B265B47DFB - 765BBE1F32F66E65A12FE24365EFC53632BBF9FAD11C90474714C0EB7979FA86 - D252A97343291F365300AD5BB7F6E5E5DB095A7063B647BEBE4AE051C896F782 - 70AFF71BE1D85D2AB3AF809FBC94143A2721C1F2DF3053007681E5CB1CF6EB61 - EAAB945D851FD91C7F10AE3C7F191C9DA666F5EEAD57AD5D2B3C0FD172AC0C74 - B49824132E0580515CC60A69041F57B0D0ABD6DB8A86EC3C76CCD7D25B54DB0F - 3AF4EE4DB7AE5DEB981C3A6EA7CA660A62A61DCD66BB959E82762A0008FDC52C - EC7958A1E0436DB6A108047AFACD61D75294E8032291E927C2710500A675E8A0 - D7555509CF8312B8D68225609607200B76D719C93E3D045F05F4146660E6478A - AF8CF0B7E8D081EEA9AA725CFE1C1F809F294949FAD1DA5AE1797007B0D1884C - 4C20180BA0257F7E36CFF4D92CF8D7B0E0ABCE3B0A1990DF5FC6F79B8CD96F57 - 4B6F3B70C520FCC8E6080099D5011905005B229385FD372CF4E8B09BA58A7114 - 16B112ED7762ADDF0CD70CC48F4C67613FA23C01230580CABB5FB3B00FE403D5 - 776AC94E112C56D6F92355E06305570DC68F26992804CC3206FD3100E4DF0FE0 - 8B3FE08469AF02780A3B90CDF0F3A3B950DE5C37203F9A052560543BB0E6BBEF - E84C167615BC53D88D6C6EBF1FCDA5B2E6CA41F9B1E20EA08A100943AAC24E11 - 4EEA75DD27FC32557DC08D667F435C3B303F560283E827701D2B81486C3AA288 - 3D6A8F1FA7B9070E48D5F303B705FC02E1EAC1F991D97DD80F7205AE642510CE - 76E38AD803A9BD6FD6D448ADF103372DF599E1FA01FA914D16F2E3C476E48AE8 - 44B681A71FB724F9C8E08941FA914D1BF6832DC89034A45C024530A07FDF029E - F545BBF536C40DE9BD56F0CC40FDC81610F9814B3054327350A1F083CCBE4507 - 0F4A9BFCC0E9C29E60F0D460FD582925F663478721456C60D5E4074E96F48682 - E706ECC74A53113F7009AE4A495189408A80C0E47F8D677D99DD7A1AE254330F - 3BF0E4A01B62255700204F60705252D05D8614D109F2F997F2CC2F53CCE3C7ED - 6BFC32787AF07E64BB0D3704D6005C022BFD0514D107EAF791D26B25D00722DD - BD375C78FE0BF891DD77E054101BC072A1CA208C2D30D3C3D7B792CBEF27927D - FBC34D547C898658750900560AFE9BAD810CB53D574CB0A1BE9EFEC2B3BE9508 - 3FF042669F55A2EACBF8B19A2FE007F5044392935590304AD9F7FDF7BE59FFB3 - 20BA44796D7D5F96A8FB427E64B7263F15B80259CD9BD3457C28B7203A80B9FF - D1E1C354C18795209F9FEEB9B934A2AC2C2A6F86A8FC520DB1524CD490564D9A - D0C0162D945BE07110DD5FC1827F80677FAB44A3C97F2A51FDE5FC946467EB5F - 969707F55E280258047DD5B2A1A74070AF2248C1075E4DECB14AD47FC1864C4B - 4BD3EB76ED0AEABD500417B012E8ABB6F3762D30EF21F8FFC747B082EFA5421E - 3B88992FEA67495191BE7AE6CCA0DF8F1583BE6C1164F2A17A09BA0334E958C5 - B3FD3FF8B01AD96F48DFA222CA993933A67ED498FAB20D29CECCD4BFAAAC0CFA - FDB002600D5CDCA28552040E01C1FF7B5D9D6FD60F26B8E7E7F47EFDE8E655AB - 62F2478CC92FDD102BCD46020145D02B31917AB3325059859101D97B6B59E8D7 - D5D78724F85E69DA114E62FACBFB595450A0AF2B2909F973D092EC7C560638D4 - 7E81F682765C9FB0C0E3906DC96546AF8202BAB2A424E6EFFF98BF000D793E2B - 4BDF595161CB6721A9A84742826F1951050D8303B33B5A71AD61A1976DC229A2 - 6356168DA9A8503FC809D485084030FD068C80F09FCB8A00D58767AB5D87A440 - 338E7FB1D06F62E10FC5C46F48AC2CEB59455D10135E193244DFBC78B16D9F87 - 1504C40ACE62EBA0132B036519FC00847CFBB163B495051EC21FEC125E20BAE6 - E4D0C8254BD48536405D18099056FCD99B6F92D52223112849C6F133B6103A36 - 6D1A330A0102BF93FDF8CF59E0B7B3C0EF6181B76BA607A8D3EF367468D4A6EF - DA89BA401658306A94BE61FE7CDB150180F0631501B1832E7CA4459942F882AF - D9972CECF0E511C5B753E0FD40F033468CA0E173E746CF850B33EA4205C15B85 - 85FABA397328981A035920FC1DF9863E8D15018E56AC14DAF2FFB93DE7006BF3 - 30E1AB58E0F7F2E3372CEC3BF9793804DE0F04BF577E3E5D515CECEE8BE342D4 - 050B9150138AAC8238422A2B041C6D9B34A176FC8823D225CC28ADDDC7C20D21 - C7F3BD78CE4728997856392333930A2B2BD53D1C02EAE2D9C4FB1327EA1FB355 - 50B36387237F1F16430B5602CDF931811FE3F9B1393F363DF15AB313FF877588 - 447E8E73A04CBE6381854373E4F871AAE703CF8FF2FF7D8BE7FC8815F7C3FC1C - FF87730E9F98E19D22393D9D7A8E1E4D03274F56F7AE0DA88B1806DEC8CFF7F5 - 22385A5BEBF450A282F8A4243AEFEAAB55E24E18501734CCBC3C6890BEBDBC3C - 2C81C368067E7DA7EC6CBA7ED932758F861175712308F6328032B0B2C7612C81 - 525C08BD577BEC7B1175A11D04F9055F7CF00185528CE465508C03818F960EBB - 5E445D781781CCC31D1F7D14B50A01029F7ED14574DDE2C5EABE7309EA877031 - C837D8B7650BEDDDB4C9736E438BB4344AEDDE9DDA76EDAAD6E75D8CFA613C08 - 961CF77EF619EDE3632F2B887026249981A699A92CE06DBB75A3543ED4D29CF7 - 503F58940225517FF0201DABABA323870ED1117E8E65C9233535BE7FE3F9517E - 04F12D5BFA96DA12F8312139F987E72929BE7FC7A1E3113F57C21D9DFC3FB05B - 459D4B95757A0000000049454E44AE4260822800000030000000600000000100 - 0800000000000000000000000000000000000000000000000000000000000202 - 04000505070004040B0003030E0004040D0008080B000A0A0E000C0C0E000404 - 1200050514000C0C100006061A0006061D001111160015151A00060621000707 - 280007072C001B1B20001D1D22000808350008083B0022222800242429002828 - 2E002E2E2F0036363A0039393D003C3C3C000808470008084B0008084D000707 - 50000808530008085A0008085F003E3E42000909660009096A000A0A71000A0A - 76000B0B79000B0B7D004343470044444700464649004A4A4C00535354005757 - 57005B5B5D00666667007171710077777700787878007D7D7D00000080000606 - 83000B0B8100090984000C0C85000404890005058F000C0C890016168B001717 - 8C00070790000D0D91000D0D96000606990006069D000D0D9900222291003434 - 9A003E3E9E000707A3000E0EA0000E0EA6000707A9000909B1000F0FB2000909 - B5001010B4001010BA005050A7005757AB007272B8000E0ECE001111C2001111 - C9001212D1001212D6001010DA001010DE001313E1001414E3001212E6001414 - E7001414E9001515EE001414F3001515F5001616FA001515FE00808080008A8A - 8A008D8D8D00929292009A9A9A009E9E9E00A1A1A100A7A7A700AAAAAA00B0B0 - B000BDBDBD00C9C9C900D0D0D000D7D7D700D9D9D900DDDDDD00E2E2E200E5E5 - E500EBEBEB00EDEDED00F1F1F100F5F5F500F9F9F900FEFEFE00000000002F26 - 000050410000705B000090740000B08E0000CFA90000F0C30000FFD21100FFD8 - 3100FFDD5100FFE47100FFEA9100FFF0B100FFF6D100FFFFFF00000000002F14 - 00005022000070300000903E0000B04D0000CF5B0000F0690000FF791100FF8A - 3100FF9D5100FFAF7100FFC19100FFD2B100FFE5D100FFFFFF00000000002F03 - 0000500400007006000090090000B00A0000CF0C0000F00E0000FF201200FF3E - 3100FF5C5100FF7A7100FF979100FFB6B100FFD4D100FFFFFF00000000002F00 - 0E00500017007000210090002B00B0003600CF004000F0004900FF115A00FF31 - 7000FF518600FF719C00FF91B200FFB1C800FFD1DF00FFFFFF00000000002F00 - 20005000360070004C0090006200B0007800CF008E00F000A400FF11B300FF31 - BE00FF51C700FF71D100FF91DC00FFB1E500FFD1F000FFFFFF00000000002C00 - 2F004B0050006900700087009000A500B000C400CF00E100F000F011FF00F231 - FF00F451FF00F671FF00F791FF00F9B1FF00FBD1FF00FFFFFF00000000001B00 - 2F002D0050003F007000520090006300B0007600CF008800F0009911FF00A631 - FF00B451FF00C271FF00CF91FF00DCB1FF00EBD1FF00FFFFFF00000000000800 - 2F000E005000150070001B0090002100B0002600CF002C00F0003E11FF005831 - FF007151FF008C71FF00A691FF00BFB1FF00DAD1FF00FFFFFF00000000000000 - 0000000000000000000000000056554A483B3B484A5556000000000000000000 - 0000000000000000000000000000000000000000000000000000543B383D4246 - 4F52534E4B4339383B5400000000000000000000000000000000000000000000 - 00000000000000003B393D505E676666666666666667665E513D383C00000000 - 0000000000000000000000000000000000000000000040384B5E676766666666 - 666666666666666666665F4D3841000000000000000000000000000000000000 - 000000004938475F66666666666666666666666666666666666667675E453849 - 0000000000000000000000000000000000000041395767676767666666666666 - 66666666666666666666666666665A3941000000000000000000000000000000 - 0000394261676767676767676666666666666666666666666666666666676761 - 423B0000000000000000000000000000003846652923475F6767676767676766 - 6666666666666666666666666666666666463800000000000000000000000000 - 394C6667240807011F5266676767676666666666666666666666666666666667 - 6766463900000000000000000000004142656767242E7E6F25000C2B63676767 - 6766666666666666666666666666666666666642410000000000000000004939 - 62666767242E8F8F8F77360E0A47666766666666666666666666666666666666 - 6667676139490000000000000000385767676666262E8F8F8F8F8F7C34011662 - 67676766666666666666666666666666666666665A3800000000000000414766 - 66666767242E8F8F8F8F8F8F8F7414105B676666666666666666666666666666 - 66666667674541000000000000385D6767666666262E8F8F8F8F8F8F8F8F7A1C - 055B676767666666666666666666666666666666665F3800000000003B4D6666 - 66666667241A7B8F8F8F8F8F8F8F8F7E1B126567676767666666666666666666 - 6666666767674B3C00000000385E6767666666664D0C08347A7F8F8F8F8F8F8F - 790B26676767676767676766666666666666666666665F380000005442666666 - 666666666666430C026D8F8F8F8F8F8F8F70005E676767676767676766666666 - 666666666767673D5400003B4F67676666666666666666663C02688F8F8F8F8F - 8F7F0F2A67676767676767676767676666666666666666503B0000385E666666 - 6666666666666666674C01327F8F8F8F8F8F360C44444444444444475B666666 - 666666666667675C38005638676767666666666666666666666658026D8F8F8F - 8F8F75080B0707080B0808004467676666666666666666673956554366666666 - 6666666666666666666767270F7D8F8F8F8F8F8F8F8F8F8F8F8F8F0B47666666 - 666666666666676742554A466767666666666666666666666666666306688F8F - 8F8F8F8F8F8F8F8F8F8F8F0B446767666666666666666667464A484E67666666 - 6666666666666666666667673C06798F8F8F8F8F8F8F8F8F8F8F8F0B47666666 - 66666666666767674E483B5167676766666666666666666666666666660B698F - 8F8F8F8F8F8F8F8F8F8F8F08446767666666666666666666533B3B5366666666 - 66666666666666666666666767222F8F8F8F8F8F8F8F8F8F8F8F8F0847666666 - 6666666666666767513B484E6767676666666666666666666666666666440B8F - 8F8F8F8F712D2C2D2D2E2E024467666666666666666666674E484A4667676666 - 666666666666666666666667675A00748F8F8F8F730022262627272759666666 - 6666666666676767464A5542676767666666666666666666666666666667076B - 8F8F8F8F7F0E2A67676766666666666666666666666666674355563966676666 - 666666666666666666666667676720308F8F8F8F8F370A656766666666666666 - 6666666666676767385600385C6767676766666666666666666666666666400E - 8F8F8F8F8F79023F6767676766666666666666666666675B3800003B4F676767 - 66666666666666666666666666675A00738F8F8F8F8F69015267676666666666 - 666666666767674F3B0000543D67676767666666666666666666666666666610 - 687F8F8F8F8F8F330359676767676666666666666667663D54000000385E6767 - 66666666666666666666666666676727198F8F8F8F8F8F7F2E01285F67666666 - 6666666767675D38000000003C4B67676767666666666666666666666666665A - 026E8F8F8F8F8F8F7F6C0E000C3C66666666666667674B3C0000000000385E67 - 67666666666666666666666666666767280B798F8F8F8F8F8F8F7E721D1F6666 - 66676767675D3800000000000040456767676767666666666666666666666666 - 66111D7C8F8F8F8F8F8F8F8F331E67666667676767454100000000000000385A - 67676766666666666666666666666666675B0D18778F8F8F8F8F8F8F331E6767 - 6767676757380000000000000000493861676767676766666666666666666666 - 666663150E6A7E8F8F8F8F8F331E676767676761384900000000000000000041 - 3E656767676666666666666666666666666667662A021469768F8F8F331E6767 - 6767643E41000000000000000000000039466767676767676666666666666666 - 666666666661260C02183672311E676767674639000000000000000000000000 - 00384665676767676766666666666666666666666666666658281100001E6767 - 644638000000000000000000000000000000393E606767676767676767666666 - 6666666666666666666667635958676142390000000000000000000000000000 - 0000004138576767676767676767676767676767676767676767676767675738 - 41000000000000000000000000000000000000004938455D6767676767676767 - 6767676767676767676767675D45384900000000000000000000000000000000 - 00000000000040384B5D676767676767676767676767676767675D4B38400000 - 0000000000000000000000000000000000000000000000003B383D4F5C676767 - 676767676767675C4F3D383B0000000000000000000000000000000000000000 - 00000000000000000000543B38383E464E51514E464238383B54000000000000 - 000000000000000000000000000000000000000000000000000000000056554A - 483B3B484A555600000000000000000000000000000000000000FFFFE007FFFF - 0000FFFF0000FFFF0000FFFC00003FFF0000FFF000000FFF0000FFC0000003FF - 0000FF80000001FF0000FF00000000FF0000FE000000007F0000FC000000003F - 0000F8000000001F0000F0000000000F0000F0000000000F0000E00000000007 - 0000E000000000070000C000000000030000C000000000030000800000000001 - 0000800000000001000080000000000100000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000800000000001000080000000000100008000000000010000C00000000003 - 0000C000000000030000E000000000070000E000000000070000F0000000000F - 0000F0000000000F0000F8000000001F0000FC000000003F0000FE000000007F - 0000FF00000000FF0000FF80000001FF0000FFC0000003FF0000FFF000000FFF - 0000FFFC00003FFF0000FFFF0000FFFF0000FFFFE007FFFF0000280000002000 - 0000400000000100080000000000000000000000000000000000000000000000 - 000000000000030305000B0B14000C0C16000E0E1D0012121F000F0F22001313 - 220017172300101024001919270012122D0014142F00191928001D1D29001E1E - 2F001313340014143A0012123C0015153F00222231002A2A3A002C2C39003131 - 3D001212450010104B001616480012124E0013135200323243003A3A46001717 - 660012126A001414690012126E000F0F7D001111700013137E00454554004B4B - 570050505E005E5E6A0063636F00676772006D6D77007373780078787F000606 - 8400090987000A0A88000E0E8E0012128E0015158E000D0D95000E0E9D001010 - 92001919910010109A0010109C002E2E9B0031319F000E0EA8001010A3001010 - A6000F0FB7001010BA001010BF006262B4007A7ABE000D0DC2001212CE000F0F - D0001212D1001010DA001212E7001414E7001414E9001313EE001414EC001414 - F1001414F5001616FB001616FE00808085008C8C8F00969699009E9E9F00A0A0 - A100AEAEAE00B7B7B700BEBEBE00D6D6D600DADADA00E2E2E200E4E4E400E9E9 - E900EEEEEE00F0F0F000F6F6F600F8F8F800FEFEFE004CB0000059CF000067F0 - 000078FF11008AFF31009CFF5100AEFF7100C0FF9100D2FFB100E4FFD100FFFF - FF0000000000262F0000405000005A700000749000008EB00000A9CF0000C2F0 - 0000D1FF1100D8FF3100DEFF5100E3FF7100E9FF9100EFFFB100F6FFD100FFFF - FF00000000002F26000050410000705B000090740000B08E0000CFA90000F0C3 - 0000FFD21100FFD83100FFDD5100FFE47100FFEA9100FFF0B100FFF6D100FFFF - FF00000000002F1400005022000070300000903E0000B04D0000CF5B0000F069 - 0000FF791100FF8A3100FF9D5100FFAF7100FFC19100FFD2B100FFE5D100FFFF - FF00000000002F030000500400007006000090090000B00A0000CF0C0000F00E - 0000FF201200FF3E3100FF5C5100FF7A7100FF979100FFB6B100FFD4D100FFFF - FF00000000002F000E00500017007000210090002B00B0003600CF004000F000 - 4900FF115A00FF317000FF518600FF719C00FF91B200FFB1C800FFD1DF00FFFF - FF00000000002F0020005000360070004C0090006200B0007800CF008E00F000 - A400FF11B300FF31BE00FF51C700FF71D100FF91DC00FFB1E500FFD1F000FFFF - FF00000000002C002F004B0050006900700087009000A500B000C400CF00E100 - F000F011FF00F231FF00F451FF00F671FF00F791FF00F9B1FF00FBD1FF00FFFF - FF00000000001B002F002D0050003F007000520090006300B0007600CF008800 - F0009911FF00A631FF00B451FF00C271FF00CF91FF00DCB1FF00EBD1FF00FFFF - FF000000000008002F000E005000150070001B0090002100B0002600CF002C00 - F0003E11FF005831FF007151FF008C71FF00A691FF00BFB1FF00DAD1FF00FFFF - FF00000000000000000000000000433C382F2F383C4300000000000000000000 - 000000000000000000000043313945494A50504A494539314300000000000000 - 0000000000000000004431404F525252525252525252524F4031440000000000 - 00000000000000003B3F4F52525252525252525252525252524D3F3B00000000 - 0000000000000034414952525252525252525252525252525252524234000000 - 00000000000034474B0110324B52525252525252525252525252525247340000 - 00000000003B42524B0F5C2E0A1A485252525252525252525252525252423B00 - 00000000443F52524B0F6F6F6F5A0A3352525252525252525252525252523F44 - 00000000314D52524B0F6F6F6F6F6127184B5252525252525252525252524D31 - 00000043405252524B08626F6F6F6F6F55125252525252525252525252525240 - 430000314F52525250220553636F6F6F6F2B255252525252525252525252524F - 300000395252525252524E2017606F6F6F610451525252525252525252525252 - 390043455252525252525252370E616F6F6F281B1F1F1F1F2452525252525252 - 45433C49525252525252525252232C6F6F6F5E59595959590352525252525252 - 493C384A52525252525252525250065D6F6F6F6F6F6F6F6F0352525252525252 - 4A382F505252525252525252525236296F6F6F6F6F6F6F6F0352525252525252 - 502F2F50525252525252525252524E0D6F6F6F615B5C5B5B0352525252525252 - 502F384A52525252525252525252520B5F6F6F5B011313131952525252525252 - 4A383C49525252525252525252525221586F6F6F144952525252525252525252 - 493C434552525252525252525252523D2A6F6F6F542452525252525252525252 - 4543003952525252525252525252524E0D6F6F6F63163E525252525252525252 - 390000304F5252525252525252525252115C6F6F6F5F0E21465252525252524F - 300000434052525252525252525252523E266F6F6F6F6257151C525252525240 - 43000000314D52525252525252525252521B53646F6F6F6F610C525252524D31 - 00000000443F52525252525252525252524E1C1E5F6F6F6F610C525252523F44 - 00000000003B425252525252525252525252523A0756616F610C525252423B00 - 00000000000034475252525252525252525252524922091D2D0C525247340000 - 0000000000000034425252525252525252525252525252483532524234000000 - 00000000000000003B3F4D52525252525252525252525252524D3F3B00000000 - 0000000000000000004431404F525252525252525252524F4031440000000000 - 000000000000000000000043303945494A50504A494539304300000000000000 - 0000000000000000000000000000433C382F2F383C4300000000000000000000 - 0000FFF00FFFFF8001FFFE00007FFC00003FF800001FF000000FE0000007C000 - 0003C00000038000000180000001800000010000000000000000000000000000 - 000000000000000000000000000000000000800000018000000180000001C000 - 0003C0000003E0000007F000000FF800001FFC00003FFE00007FFF8001FFFFF0 - 0FFF280000001000000020000000010008000000000000000000000000000000 - 00000000000000000000000000003F3F69002A2A720044447700272784002323 - 8F002C2C8F003535870033338C0035358E002A2A91002D2D910023239A001F1F - A1001F1FB1001C1CBF002323A0002525A4003333BE0040408700515181005555 - 86005F5F80006363870062628E0066668E00696989004747B4004A4ABC001515 - C3001515D4001919D6002828C5001717E5001515F3001515FA001616FE006969 - C1007E7EC8009797AA00AFAFBB00BABAC700C2C2C800CDCDD400D1D1D300D5D5 - D800DDDDE000E4E4E500F1F1F100F9F9F900FFFFFF0000704C000090630000B0 - 790000CF8F0000F0A60011FFB40031FFBE0051FFC80071FFD30091FFDC00B1FF - E500D1FFF000FFFFFF0000000000002F0E00005018000070220000902C0000B0 - 360000CF400000F04A0011FF5B0031FF710051FF870071FF9D0091FFB200B1FF - C900D1FFDF00FFFFFF0000000000022F00000450000006700000089000000AB0 - 00000BCF00000EF0000020FF12003DFF31005BFF510079FF710098FF9100B5FF - B100D4FFD100FFFFFF0000000000142F000022500000307000003D9000004CB0 - 000059CF000067F0000078FF11008AFF31009CFF5100AEFF7100C0FF9100D2FF - B100E4FFD100FFFFFF0000000000262F0000405000005A700000749000008EB0 - 0000A9CF0000C2F00000D1FF1100D8FF3100DEFF5100E3FF7100E9FF9100EFFF - B100F6FFD100FFFFFF00000000002F26000050410000705B000090740000B08E - 0000CFA90000F0C30000FFD21100FFD83100FFDD5100FFE47100FFEA9100FFF0 - B100FFF6D100FFFFFF00000000002F1400005022000070300000903E0000B04D - 0000CF5B0000F0690000FF791100FF8A3100FF9D5100FFAF7100FFC19100FFD2 - B100FFE5D100FFFFFF00000000002F030000500400007006000090090000B00A - 0000CF0C0000F00E0000FF201200FF3E3100FF5C5100FF7A7100FF979100FFB6 - B100FFD4D100FFFFFF00000000002F000E00500017007000210090002B00B000 - 3600CF004000F0004900FF115A00FF317000FF518600FF719C00FF91B200FFB1 - C800FFD1DF00FFFFFF00000000002F0020005000360070004C0090006200B000 - 7800CF008E00F000A400FF11B300FF31BE00FF51C700FF71D100FF91DC00FFB1 - E500FFD1F000FFFFFF00000000002C002F004B0050006900700087009000A500 - B000C400CF00E100F000F011FF00F231FF00F451FF00F671FF00F791FF00F9B1 - FF00FBD1FF00FFFFFF00000000001B002F002D0050003F007000520090006300 - B0007600CF008800F0009911FF00A631FF00B451FF00C271FF00CF91FF00DCB1 - FF00EBD1FF00FFFFFF000000000008002F000E005000150070001B0090002100 - B0002600CF002C00F0003E11FF005831FF007151FF008C71FF00A691FF00BFB1 - FF00DAD1FF00FFFFFF000000000000251C12121C250000000000000000262023 - 2424242423202600000000001B0D0E23242424242424211B0000002621092C17 - 112424242424242126000020240832322B0724242424242420002523241F032E - 32280F242424242423251C24242424042D321A1515102424241C122424242424 - 143232323206242424121224242424240B313016180C242424121C2424242424 - 1D2A321324242424241C25232424242424153229052224242325002024242424 - 240C2E322F012424200000262124242424240A2731192421260000001B212424 - 2424241E0A02211B000000000026202324242424232026000000000000000025 - 1C12121C250000000000F81F0000E0070000C003000080010000800100000000 - 000000000000000000000000000000000000000000008001000080010000C003 - 0000E0070000F81F0000} - OldCreateOrder = False - OnCreate = FormCreate - OnResize = FormResize - PixelsPerInch = 96 - TextHeight = 13 -end +object frmMain: TfrmMain + Left = 323 + Top = 163 + Width = 1007 + Height = 661 + Caption = 'FFDec Flash Player' + Color = clWhite + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + Icon.Data = { + 0000010004000000000001000800EC310000460000003030000001000800A80E + 0000323200002020000001000800A8080000DA40000010100000010008006805 + 00008249000089504E470D0A1A0A0000000D4948445200000100000001000806 + 0000005C72A866000031B34944415478DAED9D0B7C14D5F5C70F8F3C8090F008 + 041523521031451E159AF8A041FEB4F28F88429428A08912B51A54A80F94FEED + 940AA258F081CADFA841010D1A10458A1695482B49E15F40298280881435BC02 + 84040328F33FBF95B50177E6DED99DDD99D9BDDFCF673EBBB0B39BBBB373CE3D + E7DC73CE6D448AA8E4FD8913F5FA8307E9686DADEF38C2CF8F1C3A4447F9F03D + E2FFF911C4B76C49F149499480473EF0989092E2FB3F1C89FC7CE0E4C98D9CFE + 4E0AFB513FAA078170EFFDEC33DAC7C7DE2D5BE8787DBD23E3689C9848A95DBB + 52DB6EDD28950FA524BC87FAC15CCC5B85853F0A7ADDAE5D4E0FC7122DD2D27E + 540C571417ABFBCCA5A81FC645BC326488BE7DF9729F791E8DC09DE83460005D + B778B1BAEF5C82FA211CA474D8307D7B7939D557573B3D1447486CD3863A6567 + 53DEC285EA3E740875E123C8EB7979BE19DE6BE67CA480DB000BE1EAD252755F + 460875A1C3CCCB8306E9DB962D737A189EA4F3A04174FDB265EA1E0D23EAE286 + 8137F2F3F58D656551EBCB471AC40EBAE7E6D255B367ABFBD566D405B5092CCD + 7D3C670ED5ECD8E1D8185A356942CD1B35A284C68D299E1F7124F21177E27933 + FEFF383E2F911F134E3C07C7F83872FC38D5F381E7DFF2E3515DA7637CD4F371 + F4C481730EF3E381EFBF77EC3B26A7A753CFD1A3D592A34DA88B1822C59999FA + 57959511FB7BCD5890539B36F51D6D59E053F9687BE27924D9C74A60DF77DFD1 + 5E3CF2B117CFF9F8961544A4382333930A2B2BD53D1C02EAE20501D6E7D7CD9E + 4DC78F1D0BDBDFC0ACDD312E8E4E83B043D04F083D667437038BC1AF0CA01CBE + E1C79D7C9D8E85513134E6EBD42B3F5FE51B0481BA601658306A94BE61FEFCB0 + 083E04BE030BF8D9F1F1D4858F347E1EE77261B7C2177CCDBE3C7A94BEE0A38A + 95423814021441C68811347CEEDCE8B97061465D2809E6E7E6FA827A767326DF + B0387E9690401DA34CE0CD80F0EF6425F0F99123B49D15C2D7FCDC6E10341C51 + 56161B173404D40532615E4E8EBE65C912DB3E0FFEFBCF1313A90B0B7C2716FC + 581178115008DBD942D8CA0AE15FF5F5B6C611BAE6E4D0C8254BD48536405D98 + 00CC1E30C097B0630710F27359E07B356B4667C7C585FE813100DC8575DF7E4B + 9B5821D8E52A20C1287FF97275BF9F82BA200D783E2B4BDF595161CB67C197EF + C1829FC133BE9AE98303C2BF812D82F5AC08103BB0838E595934A6A242FD2027 + 501782595450A0AF2B2909F973DAB31FDF8305BE271F498D1B3BFDB5A28ADAE3 + C7E96328033E76DB1033E8555040579694C4FCFD1FF317606A9B367A28C53898 + DD7BB1C0F766131F517C45F8C12AC25A7611D6B13208C5454031D284EAEA9896 + 8198FDF2CFF5EBA77FBD6A55D0EF87E0F765A1CF6CDE5CCDF60E01ABA0F2F061 + 5ACDCA201445707ABF7E74F3AA5531290B31F7A5971415E9AB67CE0CFAFD88E4 + F765A187E0BB3D29275640F2914F11F011CA0A42DFA222CA993933A67ED498FA + B2D3D2D2F4604B7121F817B568E19BF55550CF9DC00A8035F0515D5DD08AA045 + 870E744F5555CCFCC031F1454BB2B3F52FCBCB837A2F0A6CFAF36CAFA2F9DE01 + 8A00F1810AB608822D5C3A2B3B9B0ACACBA3FE078FFA2F382931510FA669A65F + F0B17EAFF02EC8275811A42240D3D307EBEBA35A46A2F6CB059BBE8B593E8B05 + FF223ED48C1F1DC022F88895002C82608285D19C561C955FEA892E5DF4FD5BB7 + 5A7E1F9277FEBB65CB8897D62A2203CA96FF72E850504945ADBB74A13BB76E8D + 3A7989BA2F34292E4EB75AAD87001F041F7EBE22FA4176211481D54021AA0D1F + 3C762CAA64266ABE0C3AEC6E5AB8D0F2FB10D51F80DD6F94B91F53C01578AFB6 + D6B76A609573870D8B9A4EC651F1251EEFDC593FB06D9BA5F7A00C7730CFFA2A + 7B2FB64156E1DB3535964B925B75EE4C776DDBE679F9F1FC17B06AF223B03798 + 677C15DD573404AB054BD922B012248C0697C0B3830F26CA7F3ACFF6D7A4A450 + B20AF2290250F3FDF7F4DAC18396AD012FAF127872D0C1D4EBC3D787C9AF5088 + 587AE890E5D88057FB0D786EC0B37AF7D6ABD6AE953E1F11FEA1C9C9744E4282 + D343577888CD478ED09B353596560A3AF4EE4DB7AE5DEB2999F2D460ADAEEF2B + 935F110AC1B8045ECB17F0CC40A775E8A0D75555499F7F61F3E6F45F49494E0F + 5B110560B970E5E1C3D2E77BA9A0C813839C9294A4CB6EB3A54C7E4538B0EA12 + 603BB3076A6B5D2F5FAE1FA095621EB4E41AD5AA956AD0A138097F1BF24DFCB8 + 95CDFAADFCFCE77CAF145A5C0A864BF00ABB04B22DC9BC504CE4EAC15959E347 + 1EFFD5ECEFAB8CBED8E4C0F1E3B48D8FCF5948716CE763CB89E7DFF071EA5D74 + 330BFFAC205685A04C4A5909C8D613B83D57C0B503D388A4C3AFDDD9DC87F02B + 6283AF58D03F64015C81F6E13C1B6346AFB698D7FF5B56004F07B92C0C25B088 + DD818DEC16C8A2B954D65C3928CD82F0ABF5FDE807FB047CC8B378F909A1DF6E + C3EEC4C15A000DB19A2FA0B950DE5C37202B667F768B16D49F0F4574B19167F4 + 0F21F438B09720CFF876138A05D09015757554CE870C6E74075C35182B01BF2B + F8C753F9FCD10384FE25FEED4BD9ACDE61C30C2FC20E0BC00FEA08DE626B4006 + B705065D3310D9A53E14F3E4B2BFDF353EDEE9212B42640FCFEC10F812F4F80F + C306A166D86501F8C132E1829A1AA96222372D11BA6210B2493E58E3BFB6552B + EAA8F6D8F32C68E1BD98CDFAB93CDBBF83BDFF1C1A879D16809F9DECB2BC7AE0 + 8054AE805B92851C1F806C7A2F847F74EBD6AA7EDFA354B070C0C47F958F4336 + EEFEDB90389E183A75EAE43BBA76ED4AEBD6ADA3952B57063CD76E0BC00FFA0B + CCD9BF5F4A09B8216DD8D13F2E5BD803B37FB49AF93DC7376CE2CF62F37E0E0B + BD1D91FB86B464E1CDCCCCA45FFDEA57949595455D5898CE3CF34C6AD4200F64 + C28409F4C8238F047C7F382C003FB004E6B02520E30E385D40E4D81FB652D29B + C73EBF4AEDF50E58A79F525747B359F043D9A9A721EDDAB5F3097A7676365D7C + F1C5D4B3674F8A17C481CC1440B82C003F880920614806274B891DF9A3569A79 + A868BF77B053F021F003070EA44B2EB9C427F4DDBB773F697697C1290BC08F95 + D501A79A8A38A20034C9441FB5CEEF0DFC82FF3C36E90CE173E0C30F1932846E + B8E106BAECB2CB8433BC08272D003F56F2043407E431E27F5036D14765F8B91F + 44F435BEB96760C38D103EA75FBF7E3EA1CFCBCBA3366DDAD8363EA72D003FB2 + 19834EE40844F48FC976EF55B9FDEE6711FBB877D5D6069DB4939E9E4E23478E + A4FCFC7C3AE79C73C232463758007E5E3F7850AA7620D2DD8623F68764FBF6A3 + AA0F413FB52D973B415E7E11CFFA4B83D85D0791FB2BAFBCD227F403060CB0EC + D35BC52D16801FAC0CC854114672DF8188499926E1F7A39EFFA6D6AD95F0BB10 + 98FBD3D9D49FCC87D5001F027877DF7DB7CFC46FDEBC79C4C6EC260B00E01ACE + DEBF5FAA9F801621D98CC81F91F1FB91E8730BFB7FAA7F9FFB409EFE556CC26E + B668EE43F0274E9C48D75D775DD867FB40B8CD0200682AF2BFD5D542251AA9C2 + A1B0FF01D94C3FA4F8AAFC7EF7F14A7D3D155ADC47CF69C1F7E3360BC0CF1676 + 0390322C2212998261FD70D9F57ED5C0D37D208B6D6C6D2D3D67A1DEFDB4D34E + A369D3A6392EF87EDC6801F8916D341AEEFC80B0FE4A9A84DF8F3DFA0AD8EF57 + B80704FA86F3AC2F5BA187F5FB5B6FBD951E7AE8214A4E4E767AF83FE2560BC0 + CFF3EC0AC8B41CD7C228A761FB6099DA7EE5F7BB0F2CEFDD5053235DB08335FC + 679F7D96FAF4E9E3F4D07F829B2D00201D0F08637E40583EB4243B5BFFB2BC5C + 789ECAF17717C8E6FBBD64D65A6BB6DA205C63C68C7185B91F08B75B0040B666 + E0ACEC6C2A282FB7FD4287E597D3244C7FE5F7BB8B89EC933E2CB9F945FFFEFD + A9B4B4D4E7F3BB19B75B007E64E3015A18E4D5F60F9C9696A6D7EDDA657A0EB6 + EC1A6363CAA722347EC737E00C49E1BFEFBEFBE8E1871F76EDACDF102F58007E + 64E2012DD2D2E89E5DBB6CBDF0B67ED892A2227DF5CC99A6E720C9E776E5F7BB + 863B0F1DA2A72422FD30F9E7CD9B4783070F767AC8D278C5020088073CCD4A40 + D443A06F5111E5CC9C699BDCDAAA003409D35F95F7BA87DB59F89F95107E04FA + 5E7FFD755FFEBE97F092050064CB87351BE5D6B60F7AAE5F3FFDEB55AB4CCF51 + A6BF7BB8956F349935FEC2C2429AC9565DA8A5B94EE0250BC04FC9FEFDF46F41 + D6ECE9AC906F5EB5CA16D9B54D016812B3FFCD2CFCAAA79FF3C8CEFCE3C68DA3 + E9D3A73B3DDCA0F19A0500D053F0397605446836C9AE2D1F32B54D1BBD5E3068 + 55DFEF0ED09F0FEBFC22EEBFFF7E9A32658AD3C30D092F5A0040A67F40224FA6 + 13AAAB4396DF903F60514181BEAEA4C4F41C24FCDC959AAAAAFC1C660DCF2E97 + 4874AC45461F72F9BD8E172D008040E0E37BF70A7FA75E050574654949484215 + B2446A12A6FFF0E464CA484CB4FB3A292C80DD73FBB0F08BBAF3C2E487E91F0D + 78D502009B8E1CA1D7241284B4106538A4373F9F95A5EFACA8303D070D3ED0D2 + 5BE12C39070E089B783CF1C41374C71D77383D54DBF0AA05E047A68148C7AC2C + 1A535111B41C87A40034C1EC0F931F81BFB66ACDDF51FE5057477F12A4F8DE76 + DB6DF4F4D34F3B3D545BF1B20500F6B3B5364B2237400B418E837EA34C5F7F74 + F4CD565D7D1DE56D3625AF109892175E78212DE7DFD28B4B7D6678DD0200E828 + BC42A0BC43D957206805A00966FF563CEBFF96677F15F8730EF8FDDD7806D963 + B2BD36F2F9FFF9CF7FBA3EAF3F18BC6E0100CCFECFF26F784010BBD18294E5A0 + DE342F2747DFB26489E9392AE3CF794439FEA8E3FFF0C30F7D3BEE4423D16001 + 00990CC1AE39393472C912CBF21C9402D02466FF3BDAB68DE435529C02FAF85D + 2058F283CF0FDF3F1A387AF428FDFDEF7FA7F2F272DAB06103AD5FBF9EB66CD9 + 6278BE572C003F4FEEDB17162BC0F21B64DA7C21E1A7AF9AFD1D4514F52F2828 + A0175F7CD1E96186C461B66EDE7BEF3D5AB46891EFD8CF0A4F162F5900008941 + 4B05564030EDC32C2B004D30FB23E9E79E76ED9CB8468A132C63C1FF8D49D349 + F8FB5BB76E8D688B6EBBD0D9A259BC7831BDF4D24BB46CD9323A24B9F7DEA978 + CD0200D3F6EC112607691665DAD2C90B468DD2D7CF9D6B7A0E9A7C5CE8C11B2B + 9AF87975357D6A525B3E977F43ECCAE32520F8A848449622CCFB50F19A0500D0 + 3404CD43CCE8316A140D9F3B575AAE2D2900517F7F95F2EB3CA8EDBFD36456C4 + 921F7C652F34F40010FC3973E6D0D4A95369E3C68DB67DAE172D00991461ABFB + 09489FF85661A1BEA6B8D8F41CB5EEEF2C58F6EBB26F1F551BDC20717C7CB46A + 15F5EDDBD7E9A14AF1C1071FF8BA0D9B05F382C58B160090C90BE85358485714 + 174BC9B6B40210CDFE98F5C7F1EC9FE89199251A1165FC7925F0575353E3AB46 + 7CE6996742FE2C28BDB39B34A1F39B36A55E7C9CC74737FE77778F96A5637BB1 + 196C051CB3C90A9096564D10FC534D3E9DA713CFFE46BBF562634E04FEDAB76F + EFF4304DF9EB5FFF4AB7DC720B6DDFBE3DA8F7A7B3700F8D8FA70B58083220F0 + FCEF689B94649A886A92B22D75527166A6FE5565A5E1EB98FDC7B66D4B498D1B + 3B7D6D62162CF9E59844FE911073EFBDF73A3D4C43E0EB1715150535EB63561F + 9E904043F9E8E3D199DD0A3256C019999954585929946F2905A009667FD5ECC3 + 79AE397890CA0CF69FC7ECBF73E74E57EDDAD31098FCB9B9B9BE653D5960DA8F + 4A4CA4BBD9F2F4AA391F0A324D433409F9169EF0FEC489FADF264F363D47B5FA + 7216E4FA77C48C60F0BA9B7DFF6DDBB6D1E5975F2E1DE187E08FE109E76E16FE + B3E3E29C1EBE63C8B40EBB64E2441A3879B2A98C0B15C0F4F474BD66C70EC3D7 + DBB3E0DFAA1A7D3ACA34F607EF33591F5EB972A52BF3FD57AF5E4D393939B467 + CF1EA9F30B58E8272525D119CAD5F48152E1DD26F91EC9E9E9347EC78ED01480 + 2630FF07F20F72914AFC719473F7EDA3CD06C1BF1E3D7AD0279F7CE2F4107F02 + 847FE0C08152997C1D58E05F60F7657094952B878A4C6290269071D317DFC8CF + D73F9E3DDBF40F8C4F4D55C13F07A938768C2E32C9817763971F28A4ECEC6CA9 + DC7DCCFA7FE649A695BAC77E422DBB7ED3D9F533A3677E3E5D357BB6A19C9B2A + 80294949FA51130DA3DA7D39CF4D35355462B00B7333F69511FC6BE322170D3E + FFC5175F4CDF7CF38DE979C82A9DCDB3FED56AF35853446DC3E259793E505B1B + 9C02D004E6BFAAF9779E54F69F8D32FFF2F2F2E8D5575F757A883F02A1472AB2 + 688DBF1DCFF66FA7A450DF180EF2C922D32B40339173C3175E1E3448DF66B22C + 83B5FFBB55DEBFA3A0E63FC32412FCFEFBEFD3A5975EEAF4307D609D1F3EFF72 + 411BB99F376D4A4BD9AA54813E39900BF0982027A0F3A04174FDB2650105D550 + 7A35C1ECDF837DB3AB5CBAAE1C2B14B3F6BFC540FBB76BD78E76EFDEEDF4107F + 64C68C19347EFC78D37390D0F321CFFCAA89AC35DE603770BD811BE8473390F5 + A015C0B5ACA5BBAAA8ACA398F9FF575C7105BDF9E69B4E0FD107827E175C7001 + 1D33A925410A6F45EBD6749A9AF92DF3055FD7398280AA664501BC9E97A76F28 + 2D35FC30D5F4C31D982DFFB925F517ADBA20FC6635FCF0F92B79E68FE5C49E50 + 11350BC9C8CBA3AB4B4B7F22EF0115C0B4B434BD6ED72EC30F53A9BFCE83D2DF + 36264B4068F6D9BF7F7FA787E933FB61FE1B81C6A4157C2FC5420E7F38111508 + B5E8D081EEA9AA9253009AC0FC1FCDA69AD2D6CE6256FC03A13AC0AF39DDF20B + F5FC08FC998135FE712A912C64B6F0FDF0AA493118D002C87B500AE07E36FF55 + F4DF59CC6AFFFBF4E9E3EBF5EF24D5D5D5D4BB776FDA6192463E283E9EDE5579 + 24B620B31AA0C92880D261C3F44D0B171A7EC8993CBB14B005A0709681ACED97 + 1B24808C1D3B969E7CF24947C777EDB5D752A9491C097EFFBA366D54D0CF464A + F6EFA77F9B045ACF1D368CF2162E3C49E67FA200A6B669A3D79BAC2DABC61FEE + A08549D0C7E9A69F6BD6ACA15FFCE217A6E7CC4F4951597E36236A1796C80A77 + 4275B5B902D094FFEF7A4409405F7EF925A5A7A73B36BEA14387D25B6FBD65F8 + 3AF2FB5F503924B613CC72A02505A0B2FFDCC12BF5F534AAA626E06BE8F9FFF5 + D75F3B3636ACF9F7ECD9D3F0F54E4D9AD0273C89A80232FB09260E70D23F5E19 + 3244DFBC78B1E19B95FFEF0E26D4D6D2A3064B3EC3D8CF5BB0608163631B3E7C + 382D3489217DC8F7CF25CA820C1BA238C0394386D0758B17FF28F727290051F5 + 9F6AFBED0ECC0280D83863E2C4898E8CEBD34F3FA58C8C0CC3D755D43FFC88E2 + 00A756079EA4003481FF7F236BEF8E4A7B3B8E5905E05FFEF2171A3C78B023E3 + 1245FED5EC1F7EACC601A41580F2FFDD017EE09F99FCC0F0FF1107883498FD7B + F5EA6598EF0FC1FF50B98F11E1619E2064E3003F3E11EDFCA39A7FB88345478E + D0B0830703BEE66405E0F5D75FEFDBC2CB88F7F9DE19A08AC72282A84948C39D + 837E54002FF6EFAFEF58B1C2F04D6AFDDF1D986500C2F4870B1069D0D63B95AD + 43A3D93F8B67FF8FD4EC1F31447180F4FEFDE9C6152B4E5600D33A74D0EBAAAA + 0CDFA4BAFFB803E4FF2F35D0EED84E6BCA9429111F135A8EDF74D34D86AF2FE1 + D95F35F48C1CA22E412DD2D2E89E5DBB4E56009A0A007A82D3F7EEA5AAE3C703 + BE367FFE7CBAE69A6B223E26741D32EAF483FDF8D6B8A827612C20B367807642 + F6A515C0BDEC5F46DB1E6B5E031B80A49994007FFEF9E7D4B973E7888E09C53E + 679D7596E1EB4FB0E53856598E11055B873D2AD86B41B3A20054031077605602 + 8CEDBF0E1E3C488D22ACA41F7DF451BAEFBEFB02BE067B717B6AAA2AF8710051 + 8310ADA102106DFFA53200DDC1D4C38791C411F03534FF4013904873FEF9E71B + 76FB51893FCE21CA08F46F1BE65300F37373F58D65658627F766136E88EA00E4 + 38B93CC32F34D80074DCB871347DFAF4888E4794F9F7627232E5272646744C8A + 1F587CE810AD35D93CB47B6E2E8D282BFB41013CD3A387BEDBA4671B96FF2E54 + 5D5B1CA7F3BE7DB4DDA007E04B2FBDE45B8B8F24D8CAFBF6DB6F0FF81ADCC65D + 6ACB78C7106D1BD6BE470FBA6DFDFA1F14C0A4C444FDB8495B61D501D879443D + 003FFEF8639F391E49468C1841AFBDF65AC0D786252450594A4A44C7A3F80FA2 + 16618DD9327BB0BEFE0705A00956006E674DAE7AB53BCBDFD89FFB95410A30B6 + 00430FC0F8082BE9D34F3FDD708BAF67D865BCD562F41FD1EB437CF8B31C603B + A0552882895881C21DA852D1E5D8C796E2D36C319AA111C9298007DBB777FAFB + C43C33D8A4FB9D8149E7440FC0CD9B3753B76EDD0C5F47F61F76F769CEB7D861 + 16EA3A3E0EF081C834FE5DC3079C995A7EFC8E8F63F27F9AFCD9284DF9B3FD2A + 269E9FE380D2883FF1EFF1ECB6C6720C6292202D5C935100AD78E6BF832D0085 + B3E4D7D4D0CB066E5A6161213DF7DC73111D4F717131DD7CF3CD4E5F1653A624 + 25D184188E5D3DC916C001839811D06414C0E94D9BD21895C9E5384800DA6390 + 01F8F4D34FD36DB7DD16D1F1888A7FDC40AC2B80E7ABABE9EBEFBE337C5D9351 + 00AA0AD0792AD8FFBFC8A40418E63FDC804872F6D9670B77F9759A585700A2AA + 400D0A409404D42D218146A868AEA34C64DFFF618316604EF40044E00F0140B7 + 13EB0A60FEC183F49941DE08403250A3254545FAEA99330D4F524940CE733E9B + 72FF3230E59CF0FFE7CD9B47A3468D72FAB20889750520DA35B86F5111357A23 + 3F5FFF78F66CE393D43E808E22EA00841D80B113702441F20F9280DC4EAC2B80 + A5870ED16A936CC09EF9F9D4489406AC1A813ACB53FC03DE6950DB8D02A0AAAA + AA88EF01880620C83BA8E7D9A596DD131C757575F42D8F15C7617657F088D771 + 24262652120B63C303FF87FC85047631F11CDFA5499326BED7F0FF286AC2CEC2 + DFB1E5E33F8EB0398BA623FE7FE3B3274C98404B972E0D38CE585700A20D4391 + 0EDCE8E54183F46DCB96199E04E1EFAF148063987500C6CC0F0B2096316B441A + EB0AE02316FEF74DD2813B0F1A448D9ECFCAD2775654189E04F3BFAFAAE77684 + 0327EAFF8D92645E78E105BAF1C61B9D1EA6A398A523C7BA0280F9BFD4A433D0 + 199999D4E8E98C0C7DCF860D8627A95660CE61B6031070AA03B09B501680311B + F8FE596072FFB4CBC8A046D3D3D3F51A932D9CAF4949A173D5268E8E702DFF78 + F30DA2B8FDFAF5A37FFCE31F4E0FD17194023066D39123F49A410769909C9E4E + 8D44BB01ABCD409D017DDD53D9FC3F64D0D5C5C91D80DC845200C6883609C16E + C18D26C5C5E9C74D3A87DCCC277568DAD4E9EF127320F037D0A49CD389F25F37 + A21480313B59AE5F3451008D7962172A00D50DD819B0F4F794C11A6EA74E9DE8 + 8B2FBE707A88AE4029006344DD817D0A40B900EEC4ACFBCFD8B163E9C9279F74 + 7A88AE40AD021823E502A820A0FB40DAEFF9264AF9DD77DFA55FFFFAD74E0FD3 + 15280BC018A920A068197078723265C47053052740E38F1906195CC898DBBB77 + 6FC4BBFFB815A5008C11ED10E45B062CCECCD4BFAAAC343C4925024516B4C54A + 3389FE63E71FEC00A4F801A5008C914A0412A5020FE48B78510C5FC44853CC3F + DA2D263F1A36FFC426A08A1F50310063A4528145C5406A57E0C8D2877DFF7506 + A5BF88FE6FDBB62DE2BBFFB81965011823550CA4CA81DD83A8F3CF238F3C42F7 + DE7BAFD3C374154A011823550EAC1A82B887913535F4AA41EA6F5C5C9CAFF4B7 + 8DEACF78124A011823D51044B50473071BD9ECEFC5E6BF514AD6E8D1A3E9E597 + 5F767A98AE43C5008C916A0986279A6A0AEA3866B33F58B97225656565393D4C + D7A12C0063A49A829E78A2DA823B8868F67762E30FAFA0148031B6B405571B83 + 841FD1EC8F757FACFF2B7E8A5200C6D8B23108505B83850FCCFE192669BF3D7A + F4F055FEA9A5BFC0280560CCC37BF6F8CACA8DD0641580DA1C347CE4B09FB6D4 + C44F5BB060010D1B36CCE961BA16A5000263697350D1F6E0792929748E2A08B2 + 9D45478ED03093620DE5FB8B510A20309BF9DE2A35B9B74EDA1EFC991E3DF4DD + EBD71B9E8C4CC00B63F442860BE4FC9FCBA6FF0E131FCD899EFF5E432980C020 + 03F03D9334E0F6EC5ADEB67EFD0F0A40940EAC9281EC6702FF388F9AA469AA9E + 7F7228051098C5870ED15A932C40A4018F282BFB4101889281CE8C8BA382D6AD + 9DFE4E518368D90F38B1E1A717510A203025FBF7D3BF4D3A7D210968E0E4C9FF + 092D6B2681C0667CDA3DEDDA39FD9DA20244652F3970805699FC38D8EA1B5B7E + 2BC4A84CC0C04CDBB387BE15AC00E0514A01807B590124AAA5A890316BF601D0 + E77FD3A64D949C9CECF4503D81B2007E0AE24B8FB2023043B3AA005477E0D079 + FBC811BAC224320BE6CE9D4B23478E74749C2B56ACF0EDBBF7FDF7DFFBF6EB6B + F8084EFDBF501EC1A99FDFF06F3424D0FB27B3EB8AF10622561580A81B30D04E + 5500D3D2D2F4BA5DBB0CDFA076080A8DAF8E1FA79EFBF651B589593660C000FA + E0830F1C1D2736FE4C4D4DF56DC2E975625501885A81B5484BA37B76ED3A5901 + BCD8BFBFBEC3409302B54B70F0608FBF4BD9EF5F6792978D5E7FEBD6ADA3CE9D + 3B3B3A56F8D3F0ABA381585500E57575B4820F23D2FBF7A71B57AC385901BC55 + 58A8AF292E367C93AA0A0C8E5A16FEFE02E1076EC9F7C766A32525254E0FC316 + 62550188AA00FB1416D215C5C5272B00A099C401E21A35A2FBD54A802520FCFF + C53EFF2A81395DC83FC873CF3DE7F4707DB46FDF9EF60802485E211615005699 + 1EC38ED2122B00405A0100B54B903C88C4FE8635F1DF04C28F629FCACA4A6AEE + 821B75F5EAD5BE04A468211615809500203849018876095271003920FC393CF3 + 2F3731C300FC7E08FF79E79DE7F4907D4C9A3489FEF0873F383D0CDB88450520 + F2FFB11BD084EAEAC00AE0952143F4CD8B171BBE5965048A81E975250BFF5281 + F0376BD68CDE79E71DEADFBFBFD343FE915FFEF297B46AD5AA80AFB5611730B5 + 7163A7876889DFB1F017C6D8CA952803F09C2143E8BAC58B032B00A009E20077 + A7A6FA1E153F05C29F5B53438B4DFAB00108FFDB6FBF4D975E7AA9D343FE91DD + BB7753C78E1D0D97FFE6A7A4D0D5AA22D4D558F5FF81250500D466A181C152DF + 0D870E4909FFA2458B5CB7B71F1A8EDE70C30D015FC3AFBD8B157F2B8F5900B1 + 86683350A08914808A035807FDFCAFE599DFACB417A0B5775959992B4B7CCD52 + 6A07C4C7D3FB6A09D8F588360239D5FF073F5100A5C386E99B162E34FC101507 + 3899297575F4473E447973107E08981BBBFB1CE69B06E6FF7E83D9E391A424BA + 27C682695E44E4FF9FCBF75EDEC285E60A0068023700F900B11E07406AEFF53C + EB8B22FD00C28F1C7F3724FA04E2C9279FA43BEFBCD3F0F50D3C7374577520AE + 067EFFC39205400D094A015CCBE660D718DE9E1A453D37B1BFBF87958008083F + 32EB9C2EF031E2282BB06EDDBAD1F6EDDB03BEDEA94913DAA6BA42BB9E60FC7F + 1050014CEBD041AFABAA32FCA058DD3014EBFBF7B19FF59449A7958640F867CD + 9AE54BAF752B66C13FF03F2D5AD01F55CCC7F588F6016C5800D490800AE0F5BC + 3C7D83414008C46283106CDBFD07F6F5AB24667D809D7C5F79E51557EFE6A3B3 + 42CBC8C8A08D1B37067C1DBFF30E36FF554768F723DA0320232F8FAE2E2D9553 + 004053CB813ED0B917FDFB360B22FC0D81AF5F5C5CECFAA61E6FBDF5160D1D3A + D4F0F5716CE9FD39062D3DAF11ACF90F0C15C0A4B838FDB84944B14762225DE5 + F21B3C1490C30FC1AFB050178F35FE993367BADAE46F8859E61F54FBB6D4543A + 43ADFDBB1ED12EC040B3AA005E1E3448DFB66C99E107466B56E0BFBEFBCEE7E7 + 8B52794F05453D58E6734B5EBF08341E193870A0E1EB05ACE05F8862051F2DC8 + 64FF751E3488AE5FB6CC9A02009AC00D88A62E4130A3FEC87E3EF6E8B3DA0B67 + ECD8B1F4D8638F51BC47564610F9EFD5AB97A1EF0FD4D29F371075FF019A899C + 9B2A80294949FA5193CD05A2A14908D6F11FE78B284AE10D44EBD6AD69F6ECD9 + AECCEC33E381071EA0871F7ED8F0F5DC84047A2D25C5E9612A241035FF884F4A + A2076A6B8353006FE4E7EB1FF30D6EC6787603923CE62762396F0ECFF458CEFB + 97A0534F20B0BC57545444BFFFFDEFA98DC7B64E5FB3660D6566669AF6FCFB3F + FE4E7DD4ECEF7AD070663A9BFF66F42A28A02B4B4A8253004013B8015EDA360C + D97B4F1D3E4C252CFC32493CA702C1CFCBCB234DD31CEFDD170C30FD2FB8E002 + 5A6FB20DDC109EFDDF54B3BF27106DFF0534818C0B15C0F4F474BD66C70EC3D7 + DBF34C71ABCB674144F2D18BFF4D36F383ED753B78F0609A3A752A9D7FFEF94E + 7F9DA079F0C107E94F7FFA93E1EB2D1B35A24D6DDBD2691EB3E8629559D5D5B4 + DBC4824D4E4FA7F13B7684A60044DB8601B7EE198035FC497575C2869C66A045 + 16FC6537D5EE07838CE9FF627232E527263A3D548504557C4F3F6752B50BFCDB + 7F999D23B586A709DC80BECD9AD160176E1E3AF4E0C1A0827BA06BD7AEBE19DF + 8DD57B5641B51F84DFCCF41F141F4FEF7A3CA01B4B88527F812621DF520AA038 + 3353FFAAB2D2F075E4028C4B4D75DDD661B9AC00165A540068D185CAB8ABAEBA + 8A1AB9ECFB0403D27D73727268E9D2A586E7C0F4FF944D7F95F4E30D10C49E21 + 58FB3F83157E6165A53D0A0068022BC08D0542B2160032F810DCBBEBAEBB3CED + E307E28E3BEEA0A79E7ACAF49C67D87ABB354AF239620151E30FA049CAB6B402 + 989498A81F37493774A315205200D888F3F6DB6FF7F5E5473FFC6863C68C1934 + 7EFC78D37354B71F6F2133FB378E8BA3078F1DB3570188760E026815D6DF45A5 + A3660A005B704340BC92BD671551A10F80E9BF8E853F168ABAA205B4FC2E3769 + FB0D1AEEFC23C2D2742D2A1042F9E85D2EAA0F3053004F3CF184CF3C8E4610F1 + CFCECEA6432629A210F97758F80744A9028C4630EB3FCEB3FFB736CDFEC092A4 + 2E18354A5F3F77AEE9396E4A0C325300D3A74FA771E3C6393D44DBD9BC79B34F + F8BFF9E61BD3F3D4929FF79049FCE9316A140D9F3B373C0A00C858016E691662 + B60A108D0A0033FF65975D26DCDB4F75F9F126D3F877359BFD816651A62D2B80 + F9B9B9FAC6B232D373DC5225184B2EC08A152BE8F2CB2F3735FBC1F53CEBCF56 + 65BE9E036BFE4B05BF6DF7DC5C1A5156165E050034C19260AB264DE80E173492 + 8C150580801F9631BF1524865CC2FEE17BECF7BB2546A39047D4F20B6841C873 + 5077C2BC9C1C7DCB9225A6E7B8C10A888518C0BC79F3A8A0A0C034C5179CC34A + B9B2756BB5BB8F0791A9F93F75CF3F59829E0A34092BE0B76DDA383ADB44BB02 + 78F4D147E9BEFBEE139E87D6DEEFB3D9AF96FBBC0722FFCF56578765F607414B + E7EC0103F4EDCB979B9EE3F43662D1EA02D4D4D4F866FD85263B38F939AF6953 + 5F8EBF4AF3F526A2EDBE41A70103287FF9F2C82A00A009AC00CCFEBF6DDBD631 + B3D36C15C0AB0AE0934F3EA1DCDC5CDAB2658BF0DC7E3CE3BF9392A2CC7E8FB2 + 8F677D54FC1DB339F2DF909014C0F35959FACE8A0AD3739C6C1B166D2EC08B2F + BEE8EB44240AF60124F8BCC966BFD7BA3529FE83A8DD17E8989545632A2A9C51 + 00401358016038DF88190E249D448B0B80725E083EB61893015D7DCAF89AAB68 + BF77D9505F4F0BD8D513A18528C321DF218B0A0AF475821B130141340D8974A1 + 503458009F7EFAA96F89CFAC96BF21AA9DB7F79149F905A27E7F32D8229153DB + B4D1EB05DD499C2817F6B20580FE7D0F3DF490AF298968890F20BEFF47BEBE13 + 5C9286AD081E9972DF449E50275457872CBFB64DC99A842B10E9D6615EB5002A + 2A2AE8A69B6E32EDDBDF900EECE7CF4F49F125FA28BC8D4CAB2FA0D924BBB629 + 0051D7207026DFA005AD5BDBF5278578AD1600CB7B68352E6AE0D11004FB4AD9 + E46FA7827D5141C9FEFDF46F81C527DBED47065B9D7251A110886486A0975C00 + A4F36287A11D261D984F4515F5441732197F40B3516E6D55004B8A8AF4D53367 + 9A9E83C8F4EDEC0A244760CB692FB800AB57AFF665F32D1724553504B33D0A7A + 06AB5AFEA8A1E6FBEFE9698935FFBE4545943373A63B1500989696A6D7EDDA65 + 7A4EA45C01375B00DBB66DA3FBEFBF9F5E7BED354BEF43F75ED4F2ABCCBEE8E2 + 7916FEAF05EDEB5BA4A5D13DBB76D92AB3615997D3240282915815709B024087 + DEFDECE36167A159B3664945F7FD60D67F8CAFD768D5C423EA9089FA032D0CF2 + 1A160550929DAD7F595E2E3CEFDA56ADA86B18CD5837B900E8D083E0DE4C7691 + 4435FB3FB94E2CF48FB3F0AB405FF4B199EFCF52BE4F458492EF6F46D8327344 + 5D8441B313B502E14A5775C32A0072F7B175786969A9A5191FA4376942CFB66C + A97CFD28057EFFFFB2E92F4AF869CC13C083F5F56191D5B0A6E66912AEC0E94D + 9BD29830ED2DE8940B0053FF9D77DEA169D3A6590AEEF9C16AFE9866CDE8CF3C + EBBBA9CDBAC25E64FC7EA085514EC37A77C9B40F03E18A07445A0120671F0D3A + D06E5C3689E75490C73FB5450BEAEEC2BD1615F621EBF767E4E5D1D5A5A5DE54 + 00E0892E5DF4FD5BB70ACF0B473C20523180DDBB77FB7C7B04F6440D398DE8C5 + 02FF049BFB2A9B2FFAD972F428BD7AE080F0BCD65DBAD09D5BB786554623625F + CAC6036EB1393F20DC0A00FEFDE38F3FEEF3EF654A7403816E3D0FF18C7F9D8A + EEC704D27EBFC5FEFEC112310753938807B4E759F0A6D6AD6D2B630D870B80F5 + FB575F7D95E6CF9F2F5DA11708E4EF8F63D7E72EF6F555D96E6C80249F17F6EF + A7DD0EFBFD0D89D89D573A6C98BE49A285959D0D44ECEA088425BC3973E6D082 + 050B68D5AA55218DE9E7ACE4C6B3E08F645F5F097EEC00E1C7729FA8C1073877 + D830CA5BB830BA140078BC7367FD00CFA022BAB3705C9D9212F2DF0BC50580D0 + BFF1C61BBEA0DECA952B431E0B32F8EE66C11FA496F46292D7F95EDC28B15375 + ABCE9DE9AE6DDB222697119F8264E201A02F9BC6835BB60CE96F59550028C479 + F7DD777D267E30CB77A782705E017F8F3BF95051FDD8051B7AAC9688118573BD + DF08476C504D221E0042DD6D58140340A79DF2F2727AEFBDF768D9B265B47DFB + 765BBE1F32F66E65A12FE24365EFC53632BBF9FAD11C90474714C0EB7979FA86 + D252A97343291F365300AD5BB7F6E5E5DB095A7063B647BEBE4AE051C896F782 + 70AFF71BE1D85D2AB3AF809FBC94143A2721C1F2DF3053007681E5CB1CF6EB61 + EAAB945D851FD91C7F10AE3C7F191C9DA666F5EEAD57AD5D2B3C0FD172AC0C74 + B49824132E0580515CC60A69041F57B0D0ABD6DB8A86EC3C76CCD7D25B54DB0F + 3AF4EE4DB7AE5DEB981C3A6EA7CA660A62A61DCD66BB959E82762A0008FDC52C + EC7958A1E0436DB6A108047AFACD61D75294E8032291E927C2710500A675E8A0 + D7555509CF8312B8D68225609607200B76D719C93E3D045F05F4146660E6478A + AF8CF0B7E8D081EEA9AA725CFE1C1F809F294949FAD1DA5AE1797007B0D1884C + 4C20180BA0257F7E36CFF4D92CF8D7B0E0ABCE3B0A1990DF5FC6F79B8CD96F57 + 4B6F3B70C520FCC8E6080099D5011905005B229385FD372CF4E8B09BA58A7114 + 16B112ED7762ADDF0CD70CC48F4C67613FA23C01230580CABB5FB3B00FE403D5 + 776AC94E112C56D6F92355E06305570DC68F26992804CC3206FD3100E4DF0FE0 + 8B3FE08469AF02780A3B90CDF0F3A3B950DE5C37203F9A052560543BB0E6BBEF + E84C167615BC53D88D6C6EBF1FCDA5B2E6CA41F9B1E20EA08A100943AAC24E11 + 4EEA75DD27FC32557DC08D667F435C3B303F560283E827701D2B81486C3AA288 + 3D6A8F1FA7B9070E48D5F303B705FC02E1EAC1F991D97DD80F7205AE642510CE + 76E38AD803A9BD6FD6D448ADF103372DF599E1FA01FA914D16F2E3C476E48AE8 + 44B681A71FB724F9C8E08941FA914D1BF6832DC89034A45C024530A07FDF029E + F545BBF536C40DE9BD56F0CC40FDC81610F9814B3054327350A1F083CCBE4507 + 0F4A9BFCC0E9C29E60F0D460FD582925F663478721456C60D5E4074E96F48682 + E706ECC74A53113F7009AE4A495189408A80C0E47F8D677D99DD7A1AE254330F + 3BF0E4A01B62255700204F60705252D05D8614D109F2F997F2CC2F53CCE3C7ED + 6BFC32787AF07E64BB0D3704D6005C022BFD0514D107EAF791D26B25D00722DD + BD375C78FE0BF891DD77E054101BC072A1CA208C2D30D3C3D7B792CBEF27927D + FBC34D547C898658750900560AFE9BAD810CB53D574CB0A1BE9EFEC2B3BE9508 + 3FF042669F55A2EACBF8B19A2FE007F5044392935590304AD9F7FDF7BE59FFB3 + 20BA44796D7D5F96A8FB427E64B7263F15B80259CD9BD3457C28B7203A80B9FF + D1E1C354C18795209F9FEEB9B934A2AC2C2A6F86A8FC520DB1524CD490564D9A + D0C0162D945BE07110DD5FC1827F80677FAB44A3C97F2A51FDE5FC946467EB5F + 969707F55E280258047DD5B2A1A74070AF2248C1075E4DECB14AD47FC1864C4B + 4BD3EB76ED0AEABD500417B012E8ABB6F3762D30EF21F8FFC747B082EFA5421E + 3B88992FEA67495191BE7AE6CCA0DF8F1583BE6C1164F2A17A09BA0334E958C5 + B3FD3FF8B01AD96F48DFA222CA993933A67ED498FAB20D29CECCD4BFAAAC0CFA + FDB002600D5CDCA28552040E01C1FF7B5D9D6FD60F26B8E7E7F47EFDE8E655AB + 62F2478CC92FDD102BCD46020145D02B31917AB3325059859101D97B6B59E8D7 + D5D78724F85E69DA114E62FACBFB595450A0AF2B2909F973D092EC7C560638D4 + 7E81F682765C9FB0C0E3906DC96546AF8202BAB2A424E6EFFF98BF000D793E2B + 4BDF595161CB6721A9A84742826F1951050D8303B33B5A71AD61A1976DC229A2 + 6356168DA9A8503FC809D485084030FD068C80F09FCB8A00D58767AB5D87A440 + 338E7FB1D06F62E10FC5C46F48AC2CEB59455D10135E193244DFBC78B16D9F87 + 1504C40ACE62EBA0132B036519FC00847CFBB163B495051EC21FEC125E20BAE6 + E4D0C8254BD48536405D18099056FCD99B6F92D52223112849C6F133B6103A36 + 6D1A330A0102BF93FDF8CF59E0B7B3C0EF6181B76BA607A8D3EF367468D4A6EF + DA89BA401658306A94BE61FE7CDB150180F0631501B1832E7CA4459942F882AF + D9972CECF0E511C5B753E0FD40F033468CA0E173E746CF850B33EA4205C15B85 + 85FABA397328981A035920FC1DF9863E8D15018E56AC14DAF2FFB93DE7006BF3 + 30E1AB58E0F7F2E3372CEC3BF9793804DE0F04BF577E3E5D515CECEE8BE342D4 + 050B9150138AAC8238422A2B041C6D9B34A176FC8823D225CC28ADDDC7C20D21 + C7F3BD78CE4728997856392333930A2B2BD53D1C02EAE2D9C4FB1327EA1FB355 + 50B36387237F1F16430B5602CDF931811FE3F9B1393F363DF15AB313FF877588 + 447E8E73A04CBE6381854373E4F871AAE703CF8FF2FF7D8BE7FC8815F7C3FC1C + FF87730E9F98E19D22393D9D7A8E1E4D03274F56F7AE0DA88B1806DEC8CFF7F5 + 22385A5BEBF450A282F8A4243AEFEAAB55E24E18501734CCBC3C6890BEBDBC3C + 2C81C368067E7DA7EC6CBA7ED932758F861175712308F6328032B0B2C7612C81 + 525C08BD577BEC7B1175A11D04F9055F7CF00185528CE465508C03818F960EBB + 5E445D781781CCC31D1F7D14B50A01029F7ED14574DDE2C5EABE7309EA877031 + C837D8B7650BEDDDB4C9736E438BB4344AEDDE9DDA76EDAAD6E75D8CFA613C08 + 961CF77EF619EDE3632F2B887026249981A699A92CE06DBB75A3543ED4D29CF7 + 503F58940225517FF0201DABABA323870ED1117E8E65C9233535BE7FE3F9517E + 04F12D5BFA96DA12F8312139F987E72929BE7FC7A1E3113F57C21D9DFC3FB05B + 459D4B95757A0000000049454E44AE4260822800000030000000600000000100 + 0800000000000000000000000000000000000000000000000000000000000202 + 04000505070004040B0003030E0004040D0008080B000A0A0E000C0C0E000404 + 1200050514000C0C100006061A0006061D001111160015151A00060621000707 + 280007072C001B1B20001D1D22000808350008083B0022222800242429002828 + 2E002E2E2F0036363A0039393D003C3C3C000808470008084B0008084D000707 + 50000808530008085A0008085F003E3E42000909660009096A000A0A71000A0A + 76000B0B79000B0B7D004343470044444700464649004A4A4C00535354005757 + 57005B5B5D00666667007171710077777700787878007D7D7D00000080000606 + 83000B0B8100090984000C0C85000404890005058F000C0C890016168B001717 + 8C00070790000D0D91000D0D96000606990006069D000D0D9900222291003434 + 9A003E3E9E000707A3000E0EA0000E0EA6000707A9000909B1000F0FB2000909 + B5001010B4001010BA005050A7005757AB007272B8000E0ECE001111C2001111 + C9001212D1001212D6001010DA001010DE001313E1001414E3001212E6001414 + E7001414E9001515EE001414F3001515F5001616FA001515FE00808080008A8A + 8A008D8D8D00929292009A9A9A009E9E9E00A1A1A100A7A7A700AAAAAA00B0B0 + B000BDBDBD00C9C9C900D0D0D000D7D7D700D9D9D900DDDDDD00E2E2E200E5E5 + E500EBEBEB00EDEDED00F1F1F100F5F5F500F9F9F900FEFEFE00000000002F26 + 000050410000705B000090740000B08E0000CFA90000F0C30000FFD21100FFD8 + 3100FFDD5100FFE47100FFEA9100FFF0B100FFF6D100FFFFFF00000000002F14 + 00005022000070300000903E0000B04D0000CF5B0000F0690000FF791100FF8A + 3100FF9D5100FFAF7100FFC19100FFD2B100FFE5D100FFFFFF00000000002F03 + 0000500400007006000090090000B00A0000CF0C0000F00E0000FF201200FF3E + 3100FF5C5100FF7A7100FF979100FFB6B100FFD4D100FFFFFF00000000002F00 + 0E00500017007000210090002B00B0003600CF004000F0004900FF115A00FF31 + 7000FF518600FF719C00FF91B200FFB1C800FFD1DF00FFFFFF00000000002F00 + 20005000360070004C0090006200B0007800CF008E00F000A400FF11B300FF31 + BE00FF51C700FF71D100FF91DC00FFB1E500FFD1F000FFFFFF00000000002C00 + 2F004B0050006900700087009000A500B000C400CF00E100F000F011FF00F231 + FF00F451FF00F671FF00F791FF00F9B1FF00FBD1FF00FFFFFF00000000001B00 + 2F002D0050003F007000520090006300B0007600CF008800F0009911FF00A631 + FF00B451FF00C271FF00CF91FF00DCB1FF00EBD1FF00FFFFFF00000000000800 + 2F000E005000150070001B0090002100B0002600CF002C00F0003E11FF005831 + FF007151FF008C71FF00A691FF00BFB1FF00DAD1FF00FFFFFF00000000000000 + 0000000000000000000000000056554A483B3B484A5556000000000000000000 + 0000000000000000000000000000000000000000000000000000543B383D4246 + 4F52534E4B4339383B5400000000000000000000000000000000000000000000 + 00000000000000003B393D505E676666666666666667665E513D383C00000000 + 0000000000000000000000000000000000000000000040384B5E676766666666 + 666666666666666666665F4D3841000000000000000000000000000000000000 + 000000004938475F66666666666666666666666666666666666667675E453849 + 0000000000000000000000000000000000000041395767676767666666666666 + 66666666666666666666666666665A3941000000000000000000000000000000 + 0000394261676767676767676666666666666666666666666666666666676761 + 423B0000000000000000000000000000003846652923475F6767676767676766 + 6666666666666666666666666666666666463800000000000000000000000000 + 394C6667240807011F5266676767676666666666666666666666666666666667 + 6766463900000000000000000000004142656767242E7E6F25000C2B63676767 + 6766666666666666666666666666666666666642410000000000000000004939 + 62666767242E8F8F8F77360E0A47666766666666666666666666666666666666 + 6667676139490000000000000000385767676666262E8F8F8F8F8F7C34011662 + 67676766666666666666666666666666666666665A3800000000000000414766 + 66666767242E8F8F8F8F8F8F8F7414105B676666666666666666666666666666 + 66666667674541000000000000385D6767666666262E8F8F8F8F8F8F8F8F7A1C + 055B676767666666666666666666666666666666665F3800000000003B4D6666 + 66666667241A7B8F8F8F8F8F8F8F8F7E1B126567676767666666666666666666 + 6666666767674B3C00000000385E6767666666664D0C08347A7F8F8F8F8F8F8F + 790B26676767676767676766666666666666666666665F380000005442666666 + 666666666666430C026D8F8F8F8F8F8F8F70005E676767676767676766666666 + 666666666767673D5400003B4F67676666666666666666663C02688F8F8F8F8F + 8F7F0F2A67676767676767676767676666666666666666503B0000385E666666 + 6666666666666666674C01327F8F8F8F8F8F360C44444444444444475B666666 + 666666666667675C38005638676767666666666666666666666658026D8F8F8F + 8F8F75080B0707080B0808004467676666666666666666673956554366666666 + 6666666666666666666767270F7D8F8F8F8F8F8F8F8F8F8F8F8F8F0B47666666 + 666666666666676742554A466767666666666666666666666666666306688F8F + 8F8F8F8F8F8F8F8F8F8F8F0B446767666666666666666667464A484E67666666 + 6666666666666666666667673C06798F8F8F8F8F8F8F8F8F8F8F8F0B47666666 + 66666666666767674E483B5167676766666666666666666666666666660B698F + 8F8F8F8F8F8F8F8F8F8F8F08446767666666666666666666533B3B5366666666 + 66666666666666666666666767222F8F8F8F8F8F8F8F8F8F8F8F8F0847666666 + 6666666666666767513B484E6767676666666666666666666666666666440B8F + 8F8F8F8F712D2C2D2D2E2E024467666666666666666666674E484A4667676666 + 666666666666666666666667675A00748F8F8F8F730022262627272759666666 + 6666666666676767464A5542676767666666666666666666666666666667076B + 8F8F8F8F7F0E2A67676766666666666666666666666666674355563966676666 + 666666666666666666666667676720308F8F8F8F8F370A656766666666666666 + 6666666666676767385600385C6767676766666666666666666666666666400E + 8F8F8F8F8F79023F6767676766666666666666666666675B3800003B4F676767 + 66666666666666666666666666675A00738F8F8F8F8F69015267676666666666 + 666666666767674F3B0000543D67676767666666666666666666666666666610 + 687F8F8F8F8F8F330359676767676666666666666667663D54000000385E6767 + 66666666666666666666666666676727198F8F8F8F8F8F7F2E01285F67666666 + 6666666767675D38000000003C4B67676767666666666666666666666666665A + 026E8F8F8F8F8F8F7F6C0E000C3C66666666666667674B3C0000000000385E67 + 67666666666666666666666666666767280B798F8F8F8F8F8F8F7E721D1F6666 + 66676767675D3800000000000040456767676767666666666666666666666666 + 66111D7C8F8F8F8F8F8F8F8F331E67666667676767454100000000000000385A + 67676766666666666666666666666666675B0D18778F8F8F8F8F8F8F331E6767 + 6767676757380000000000000000493861676767676766666666666666666666 + 666663150E6A7E8F8F8F8F8F331E676767676761384900000000000000000041 + 3E656767676666666666666666666666666667662A021469768F8F8F331E6767 + 6767643E41000000000000000000000039466767676767676666666666666666 + 666666666661260C02183672311E676767674639000000000000000000000000 + 00384665676767676766666666666666666666666666666658281100001E6767 + 644638000000000000000000000000000000393E606767676767676767666666 + 6666666666666666666667635958676142390000000000000000000000000000 + 0000004138576767676767676767676767676767676767676767676767675738 + 41000000000000000000000000000000000000004938455D6767676767676767 + 6767676767676767676767675D45384900000000000000000000000000000000 + 00000000000040384B5D676767676767676767676767676767675D4B38400000 + 0000000000000000000000000000000000000000000000003B383D4F5C676767 + 676767676767675C4F3D383B0000000000000000000000000000000000000000 + 00000000000000000000543B38383E464E51514E464238383B54000000000000 + 000000000000000000000000000000000000000000000000000000000056554A + 483B3B484A555600000000000000000000000000000000000000FFFFE007FFFF + 0000FFFF0000FFFF0000FFFC00003FFF0000FFF000000FFF0000FFC0000003FF + 0000FF80000001FF0000FF00000000FF0000FE000000007F0000FC000000003F + 0000F8000000001F0000F0000000000F0000F0000000000F0000E00000000007 + 0000E000000000070000C000000000030000C000000000030000800000000001 + 0000800000000001000080000000000100000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000800000000001000080000000000100008000000000010000C00000000003 + 0000C000000000030000E000000000070000E000000000070000F0000000000F + 0000F0000000000F0000F8000000001F0000FC000000003F0000FE000000007F + 0000FF00000000FF0000FF80000001FF0000FFC0000003FF0000FFF000000FFF + 0000FFFC00003FFF0000FFFF0000FFFF0000FFFFE007FFFF0000280000002000 + 0000400000000100080000000000000000000000000000000000000000000000 + 000000000000030305000B0B14000C0C16000E0E1D0012121F000F0F22001313 + 220017172300101024001919270012122D0014142F00191928001D1D29001E1E + 2F001313340014143A0012123C0015153F00222231002A2A3A002C2C39003131 + 3D001212450010104B001616480012124E0013135200323243003A3A46001717 + 660012126A001414690012126E000F0F7D001111700013137E00454554004B4B + 570050505E005E5E6A0063636F00676772006D6D77007373780078787F000606 + 8400090987000A0A88000E0E8E0012128E0015158E000D0D95000E0E9D001010 + 92001919910010109A0010109C002E2E9B0031319F000E0EA8001010A3001010 + A6000F0FB7001010BA001010BF006262B4007A7ABE000D0DC2001212CE000F0F + D0001212D1001010DA001212E7001414E7001414E9001313EE001414EC001414 + F1001414F5001616FB001616FE00808085008C8C8F00969699009E9E9F00A0A0 + A100AEAEAE00B7B7B700BEBEBE00D6D6D600DADADA00E2E2E200E4E4E400E9E9 + E900EEEEEE00F0F0F000F6F6F600F8F8F800FEFEFE004CB0000059CF000067F0 + 000078FF11008AFF31009CFF5100AEFF7100C0FF9100D2FFB100E4FFD100FFFF + FF0000000000262F0000405000005A700000749000008EB00000A9CF0000C2F0 + 0000D1FF1100D8FF3100DEFF5100E3FF7100E9FF9100EFFFB100F6FFD100FFFF + FF00000000002F26000050410000705B000090740000B08E0000CFA90000F0C3 + 0000FFD21100FFD83100FFDD5100FFE47100FFEA9100FFF0B100FFF6D100FFFF + FF00000000002F1400005022000070300000903E0000B04D0000CF5B0000F069 + 0000FF791100FF8A3100FF9D5100FFAF7100FFC19100FFD2B100FFE5D100FFFF + FF00000000002F030000500400007006000090090000B00A0000CF0C0000F00E + 0000FF201200FF3E3100FF5C5100FF7A7100FF979100FFB6B100FFD4D100FFFF + FF00000000002F000E00500017007000210090002B00B0003600CF004000F000 + 4900FF115A00FF317000FF518600FF719C00FF91B200FFB1C800FFD1DF00FFFF + FF00000000002F0020005000360070004C0090006200B0007800CF008E00F000 + A400FF11B300FF31BE00FF51C700FF71D100FF91DC00FFB1E500FFD1F000FFFF + FF00000000002C002F004B0050006900700087009000A500B000C400CF00E100 + F000F011FF00F231FF00F451FF00F671FF00F791FF00F9B1FF00FBD1FF00FFFF + FF00000000001B002F002D0050003F007000520090006300B0007600CF008800 + F0009911FF00A631FF00B451FF00C271FF00CF91FF00DCB1FF00EBD1FF00FFFF + FF000000000008002F000E005000150070001B0090002100B0002600CF002C00 + F0003E11FF005831FF007151FF008C71FF00A691FF00BFB1FF00DAD1FF00FFFF + FF00000000000000000000000000433C382F2F383C4300000000000000000000 + 000000000000000000000043313945494A50504A494539314300000000000000 + 0000000000000000004431404F525252525252525252524F4031440000000000 + 00000000000000003B3F4F52525252525252525252525252524D3F3B00000000 + 0000000000000034414952525252525252525252525252525252524234000000 + 00000000000034474B0110324B52525252525252525252525252525247340000 + 00000000003B42524B0F5C2E0A1A485252525252525252525252525252423B00 + 00000000443F52524B0F6F6F6F5A0A3352525252525252525252525252523F44 + 00000000314D52524B0F6F6F6F6F6127184B5252525252525252525252524D31 + 00000043405252524B08626F6F6F6F6F55125252525252525252525252525240 + 430000314F52525250220553636F6F6F6F2B255252525252525252525252524F + 300000395252525252524E2017606F6F6F610451525252525252525252525252 + 390043455252525252525252370E616F6F6F281B1F1F1F1F2452525252525252 + 45433C49525252525252525252232C6F6F6F5E59595959590352525252525252 + 493C384A52525252525252525250065D6F6F6F6F6F6F6F6F0352525252525252 + 4A382F505252525252525252525236296F6F6F6F6F6F6F6F0352525252525252 + 502F2F50525252525252525252524E0D6F6F6F615B5C5B5B0352525252525252 + 502F384A52525252525252525252520B5F6F6F5B011313131952525252525252 + 4A383C49525252525252525252525221586F6F6F144952525252525252525252 + 493C434552525252525252525252523D2A6F6F6F542452525252525252525252 + 4543003952525252525252525252524E0D6F6F6F63163E525252525252525252 + 390000304F5252525252525252525252115C6F6F6F5F0E21465252525252524F + 300000434052525252525252525252523E266F6F6F6F6257151C525252525240 + 43000000314D52525252525252525252521B53646F6F6F6F610C525252524D31 + 00000000443F52525252525252525252524E1C1E5F6F6F6F610C525252523F44 + 00000000003B425252525252525252525252523A0756616F610C525252423B00 + 00000000000034475252525252525252525252524922091D2D0C525247340000 + 0000000000000034425252525252525252525252525252483532524234000000 + 00000000000000003B3F4D52525252525252525252525252524D3F3B00000000 + 0000000000000000004431404F525252525252525252524F4031440000000000 + 000000000000000000000043303945494A50504A494539304300000000000000 + 0000000000000000000000000000433C382F2F383C4300000000000000000000 + 0000FFF00FFFFF8001FFFE00007FFC00003FF800001FF000000FE0000007C000 + 0003C00000038000000180000001800000010000000000000000000000000000 + 000000000000000000000000000000000000800000018000000180000001C000 + 0003C0000003E0000007F000000FF800001FFC00003FFE00007FFF8001FFFFF0 + 0FFF280000001000000020000000010008000000000000000000000000000000 + 00000000000000000000000000003F3F69002A2A720044447700272784002323 + 8F002C2C8F003535870033338C0035358E002A2A91002D2D910023239A001F1F + A1001F1FB1001C1CBF002323A0002525A4003333BE0040408700515181005555 + 86005F5F80006363870062628E0066668E00696989004747B4004A4ABC001515 + C3001515D4001919D6002828C5001717E5001515F3001515FA001616FE006969 + C1007E7EC8009797AA00AFAFBB00BABAC700C2C2C800CDCDD400D1D1D300D5D5 + D800DDDDE000E4E4E500F1F1F100F9F9F900FFFFFF0000704C000090630000B0 + 790000CF8F0000F0A60011FFB40031FFBE0051FFC80071FFD30091FFDC00B1FF + E500D1FFF000FFFFFF0000000000002F0E00005018000070220000902C0000B0 + 360000CF400000F04A0011FF5B0031FF710051FF870071FF9D0091FFB200B1FF + C900D1FFDF00FFFFFF0000000000022F00000450000006700000089000000AB0 + 00000BCF00000EF0000020FF12003DFF31005BFF510079FF710098FF9100B5FF + B100D4FFD100FFFFFF0000000000142F000022500000307000003D9000004CB0 + 000059CF000067F0000078FF11008AFF31009CFF5100AEFF7100C0FF9100D2FF + B100E4FFD100FFFFFF0000000000262F0000405000005A700000749000008EB0 + 0000A9CF0000C2F00000D1FF1100D8FF3100DEFF5100E3FF7100E9FF9100EFFF + B100F6FFD100FFFFFF00000000002F26000050410000705B000090740000B08E + 0000CFA90000F0C30000FFD21100FFD83100FFDD5100FFE47100FFEA9100FFF0 + B100FFF6D100FFFFFF00000000002F1400005022000070300000903E0000B04D + 0000CF5B0000F0690000FF791100FF8A3100FF9D5100FFAF7100FFC19100FFD2 + B100FFE5D100FFFFFF00000000002F030000500400007006000090090000B00A + 0000CF0C0000F00E0000FF201200FF3E3100FF5C5100FF7A7100FF979100FFB6 + B100FFD4D100FFFFFF00000000002F000E00500017007000210090002B00B000 + 3600CF004000F0004900FF115A00FF317000FF518600FF719C00FF91B200FFB1 + C800FFD1DF00FFFFFF00000000002F0020005000360070004C0090006200B000 + 7800CF008E00F000A400FF11B300FF31BE00FF51C700FF71D100FF91DC00FFB1 + E500FFD1F000FFFFFF00000000002C002F004B0050006900700087009000A500 + B000C400CF00E100F000F011FF00F231FF00F451FF00F671FF00F791FF00F9B1 + FF00FBD1FF00FFFFFF00000000001B002F002D0050003F007000520090006300 + B0007600CF008800F0009911FF00A631FF00B451FF00C271FF00CF91FF00DCB1 + FF00EBD1FF00FFFFFF000000000008002F000E005000150070001B0090002100 + B0002600CF002C00F0003E11FF005831FF007151FF008C71FF00A691FF00BFB1 + FF00DAD1FF00FFFFFF000000000000251C12121C250000000000000000262023 + 2424242423202600000000001B0D0E23242424242424211B0000002621092C17 + 112424242424242126000020240832322B0724242424242420002523241F032E + 32280F242424242423251C24242424042D321A1515102424241C122424242424 + 143232323206242424121224242424240B313016180C242424121C2424242424 + 1D2A321324242424241C25232424242424153229052224242325002024242424 + 240C2E322F012424200000262124242424240A2731192421260000001B212424 + 2424241E0A02211B000000000026202324242424232026000000000000000025 + 1C12121C250000000000F81F0000E0070000C003000080010000800100000000 + 000000000000000000000000000000000000000000008001000080010000C003 + 0000E0070000F81F0000} + OldCreateOrder = False + OnCreate = FormCreate + OnResize = FormResize + PixelsPerInch = 96 + TextHeight = 13 +end diff --git a/libsrc/Swf2Exe/uMain.pas b/libsrc/Swf2Exe/uMain.pas index 178fbec17..eba13dc1d 100644 --- a/libsrc/Swf2Exe/uMain.pas +++ b/libsrc/Swf2Exe/uMain.pas @@ -1,94 +1,94 @@ -unit uMain; - -interface - -uses - Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, - Dialogs, OleCtrls, ShockwaveFlashObjects_TLB, StdCtrls, ExtCtrls; - -type - TfrmMain = class(TForm) - - procedure FormCreate(Sender: TObject); - procedure FormResize(Sender: TObject); - private - { Private declarations } - public - { Public declarations } - end; - -type - TMySWF = class(TShockwaveFlash) - public - procedure CreateWnd; override; - end; - -var - frmMain: TfrmMain; - flaPreview: TMySWF; - -implementation - -{$R *.dfm} - -procedure TMySWF.CreateWnd; -begin - inherited; -end; - -procedure TfrmMain.FormCreate(Sender: TObject); -const - exeSize = 470016; -var - stream: TFileStream; - buffer: array of byte; - tempFile: array[0..MAX_PATH - 1] of char; - tempPath: array[0..MAX_PATH - 1] of char; - flashVarData: TVarData; - Width: integer; - Height: integer; - scaleMode: byte; -begin - flaPreview := TMySWF.Create(frmMain); - flaPreview.Parent := frmMain; - flaPreview.Anchors := [akLeft, akRight, akTop, akBottom]; - flaPreview.Align := alClient; - GetTempPath(MAX_PATH, TempPath); - if GetTempFileName(TempPath, PAnsiChar('ffd'), 0, TempFile) = 0 then - raise Exception.Create('GetTempFileName API failed. ' + - SysErrorMessage(GetLastError)); - try - stream := TFileStream.Create(ParamStr(0), fmOpenRead); - stream.Seek(exeSize, soBeginning); - stream.Read(Width, 4); - stream.Read(Height, 4); - stream.Read(scaleMode, 1); - SetLength(buffer, stream.Size - exeSize); - try - stream.Read(buffer[0], Length(buffer)); - finally - stream.Free; - end; - except - Width := 12800; - Height := 9600; - scaleMode := 3; - end; - ClientWidth := Width div 20; - ClientHeight := Height div 20; - stream := TFileStream.Create(tempFile, fmOpenWrite); - try - stream.Write(buffer[0], Length(buffer)); - finally - stream.Free; - end; - flaPreview.Movie := tempFile; - flaPreview.ScaleMode := scaleMode; -end; - -procedure TfrmMain.FormResize(Sender: TObject); -begin - flaPreview.CreateWnd; -end; - -end. +unit uMain; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, OleCtrls, ShockwaveFlashObjects_TLB, StdCtrls, ExtCtrls; + +type + TfrmMain = class(TForm) + + procedure FormCreate(Sender: TObject); + procedure FormResize(Sender: TObject); + private + { Private declarations } + public + { Public declarations } + end; + +type + TMySWF = class(TShockwaveFlash) + public + procedure CreateWnd; override; + end; + +var + frmMain: TfrmMain; + flaPreview: TMySWF; + +implementation + +{$R *.dfm} + +procedure TMySWF.CreateWnd; +begin + inherited; +end; + +procedure TfrmMain.FormCreate(Sender: TObject); +const + exeSize = 470016; +var + stream: TFileStream; + buffer: array of byte; + tempFile: array[0..MAX_PATH - 1] of char; + tempPath: array[0..MAX_PATH - 1] of char; + flashVarData: TVarData; + Width: integer; + Height: integer; + scaleMode: byte; +begin + flaPreview := TMySWF.Create(frmMain); + flaPreview.Parent := frmMain; + flaPreview.Anchors := [akLeft, akRight, akTop, akBottom]; + flaPreview.Align := alClient; + GetTempPath(MAX_PATH, TempPath); + if GetTempFileName(TempPath, PAnsiChar('ffd'), 0, TempFile) = 0 then + raise Exception.Create('GetTempFileName API failed. ' + + SysErrorMessage(GetLastError)); + try + stream := TFileStream.Create(ParamStr(0), fmOpenRead); + stream.Seek(exeSize, soBeginning); + stream.Read(Width, 4); + stream.Read(Height, 4); + stream.Read(scaleMode, 1); + SetLength(buffer, stream.Size - exeSize); + try + stream.Read(buffer[0], Length(buffer)); + finally + stream.Free; + end; + except + Width := 12800; + Height := 9600; + scaleMode := 3; + end; + ClientWidth := Width div 20; + ClientHeight := Height div 20; + stream := TFileStream.Create(tempFile, fmOpenWrite); + try + stream.Write(buffer[0], Length(buffer)); + finally + stream.Free; + end; + flaPreview.Movie := tempFile; + flaPreview.ScaleMode := scaleMode; +end; + +procedure TfrmMain.FormResize(Sender: TObject); +begin + flaPreview.CreateWnd; +end; + +end. diff --git a/libsrc/avi/build.xml b/libsrc/avi/build.xml index f35d65806..e133552c6 100644 --- a/libsrc/avi/build.xml +++ b/libsrc/avi/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project avi. - - - + + + + + + + + + + + Builds, tests, and runs the project avi. + + + diff --git a/libsrc/avi/nbproject/build-impl.xml b/libsrc/avi/nbproject/build-impl.xml index d2730e2c3..e108c2960 100644 --- a/libsrc/avi/nbproject/build-impl.xml +++ b/libsrc/avi/nbproject/build-impl.xml @@ -1,1413 +1,1413 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.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/avi/nbproject/genfiles.properties b/libsrc/avi/nbproject/genfiles.properties index adc983466..3bbefa247 100644 --- a/libsrc/avi/nbproject/genfiles.properties +++ b/libsrc/avi/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=505ab359 -build.xml.script.CRC32=fa68b8cb -build.xml.stylesheet.CRC32=8064a381@1.68.1.46 -# 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=505ab359 -nbproject/build-impl.xml.script.CRC32=3d5c3ae5 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 +build.xml.data.CRC32=505ab359 +build.xml.script.CRC32=fa68b8cb +build.xml.stylesheet.CRC32=8064a381@1.68.1.46 +# 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=505ab359 +nbproject/build-impl.xml.script.CRC32=3d5c3ae5 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 diff --git a/libsrc/avi/nbproject/project.properties b/libsrc/avi/nbproject/project.properties index 10af1866e..fcd82c1b0 100644 --- a/libsrc/avi/nbproject/project.properties +++ b/libsrc/avi/nbproject/project.properties @@ -1,72 +1,72 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -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 -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# Files in build.classes.dir which should be excluded from distribution jar -dist.archive.excludes= -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=../../lib/avi.jar -dist.javadoc.dir=${dist.dir}/javadoc -excludes= -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.7 -javac.target=1.7 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -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=org.monte.media.math.IntMath -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=true -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. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processor.options= +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +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 +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=../../lib/avi.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +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.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +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=org.monte.media.math.IntMath +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=true +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. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/libsrc/avi/nbproject/project.xml b/libsrc/avi/nbproject/project.xml index 53a131c45..272f02a51 100644 --- a/libsrc/avi/nbproject/project.xml +++ b/libsrc/avi/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - avi - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + avi + + + + + + + + + diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java index 14282fe9a..37d49f865 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java @@ -1,111 +1,111 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Properties; - -/** - * - * @author JPEXS - */ -public class ApplicationInfo { - - public static final String APPLICATION_NAME = "JPEXS Free Flash Decompiler"; - - public static final String SHORT_APPLICATION_NAME = "FFDec"; - - public static final String VENDOR = "JPEXS"; - - public static String version = ""; - - public static String revision = ""; - - public static int version_major = 4; - - public static int version_minor = 0; - - public static int version_release = 0; - - public static int version_build = 0; - - public static boolean nightly = false; - - public static String applicationVerName; - - public static String shortApplicationVerName; - - public static final String PROJECT_PAGE = "https://www.free-decompiler.com/flash"; - - /** - * URL for checking new updates - */ - public static String updateCheckUrl = "https://www.free-decompiler.com/flash/update/check/?currentVersion=¤tRevision=¤tVersionMajor=¤tVersionMinor=¤tVersionRelease=¤tVersionBuild=¤tNightly="; - - /** - * URL for doing update - */ - public static String updateUrl = "https://www.free-decompiler.com/flash/update/update/?currentVersion=¤tRevision=¤tVersionMajor=¤tVersionMinor=¤tVersionRelease=¤tVersionBuild=¤tNightly="; - - static { - loadProperties(); - } - - private static void loadProperties() { - Properties prop = new Properties(); - try { - prop.load(ApplicationInfo.class.getResourceAsStream("/project.properties")); - version = prop.getProperty("version"); - revision = prop.getProperty("build"); - version_major = Integer.parseInt(prop.getProperty("version.major")); - version_minor = Integer.parseInt(prop.getProperty("version.minor")); - version_release = Integer.parseInt(prop.getProperty("version.release")); - version_build = Integer.parseInt(prop.getProperty("version.build")); - nightly = prop.getProperty("nightly").equals("true"); - if (nightly) { - version = version + " nightly build " + version_build; - } - } catch (IOException | NullPointerException | NumberFormatException ex) { - // ignore - version = "unknown"; - } - try { - updateCheckUrl = updateCheckUrl - .replace("", URLEncoder.encode(revision, "UTF-8")) - .replace("", URLEncoder.encode(version, "UTF-8")) - .replace("", "" + version_major) - .replace("", "" + version_minor) - .replace("", "" + version_release) - .replace("", "" + version_build) - .replace("", nightly ? "1" : "0"); - updateUrl = updateUrl - .replace("", URLEncoder.encode(revision, "UTF-8")) - .replace("", URLEncoder.encode(version, "UTF-8")) - .replace("", "" + version_major) - .replace("", "" + version_minor) - .replace("", "" + version_release) - .replace("", "" + version_build) - .replace("", nightly ? "1" : "0"); - } catch (UnsupportedEncodingException e) { - - } - applicationVerName = APPLICATION_NAME + " v." + version; - shortApplicationVerName = SHORT_APPLICATION_NAME + " v." + version; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Properties; + +/** + * + * @author JPEXS + */ +public class ApplicationInfo { + + public static final String APPLICATION_NAME = "JPEXS Free Flash Decompiler"; + + public static final String SHORT_APPLICATION_NAME = "FFDec"; + + public static final String VENDOR = "JPEXS"; + + public static String version = ""; + + public static String revision = ""; + + public static int version_major = 4; + + public static int version_minor = 0; + + public static int version_release = 0; + + public static int version_build = 0; + + public static boolean nightly = false; + + public static String applicationVerName; + + public static String shortApplicationVerName; + + public static final String PROJECT_PAGE = "https://www.free-decompiler.com/flash"; + + /** + * URL for checking new updates + */ + public static String updateCheckUrl = "https://www.free-decompiler.com/flash/update/check/?currentVersion=¤tRevision=¤tVersionMajor=¤tVersionMinor=¤tVersionRelease=¤tVersionBuild=¤tNightly="; + + /** + * URL for doing update + */ + public static String updateUrl = "https://www.free-decompiler.com/flash/update/update/?currentVersion=¤tRevision=¤tVersionMajor=¤tVersionMinor=¤tVersionRelease=¤tVersionBuild=¤tNightly="; + + static { + loadProperties(); + } + + private static void loadProperties() { + Properties prop = new Properties(); + try { + prop.load(ApplicationInfo.class.getResourceAsStream("/project.properties")); + version = prop.getProperty("version"); + revision = prop.getProperty("build"); + version_major = Integer.parseInt(prop.getProperty("version.major")); + version_minor = Integer.parseInt(prop.getProperty("version.minor")); + version_release = Integer.parseInt(prop.getProperty("version.release")); + version_build = Integer.parseInt(prop.getProperty("version.build")); + nightly = prop.getProperty("nightly").equals("true"); + if (nightly) { + version = version + " nightly build " + version_build; + } + } catch (IOException | NullPointerException | NumberFormatException ex) { + // ignore + version = "unknown"; + } + try { + updateCheckUrl = updateCheckUrl + .replace("", URLEncoder.encode(revision, "UTF-8")) + .replace("", URLEncoder.encode(version, "UTF-8")) + .replace("", "" + version_major) + .replace("", "" + version_minor) + .replace("", "" + version_release) + .replace("", "" + version_build) + .replace("", nightly ? "1" : "0"); + updateUrl = updateUrl + .replace("", URLEncoder.encode(revision, "UTF-8")) + .replace("", URLEncoder.encode(version, "UTF-8")) + .replace("", "" + version_major) + .replace("", "" + version_minor) + .replace("", "" + version_release) + .replace("", "" + version_build) + .replace("", nightly ? "1" : "0"); + } catch (UnsupportedEncodingException e) { + + } + applicationVerName = APPLICATION_NAME + " v." + version; + shortApplicationVerName = SHORT_APPLICATION_NAME + " v." + version; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java index 7edda7b65..faf327b5c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java @@ -1,62 +1,62 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.tags.Tag; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ReadOnlyTagList implements Iterable { - - public static final ReadOnlyTagList EMPTY = new ReadOnlyTagList(new ArrayList<>()); - - private final List list; - - public ReadOnlyTagList(List list) { - this.list = list; - } - - @Override - public Iterator iterator() { - return list.iterator(); - } - - public int size() { - return list.size(); - } - - public boolean isEmpty() { - return list.isEmpty(); - } - - public Tag get(int index) { - return list.get(index); - } - - public int indexOf(Tag tag) { - return list.indexOf(tag); - } - - public ArrayList toArrayList() { - return new ArrayList<>(list); - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.tags.Tag; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ReadOnlyTagList implements Iterable { + + public static final ReadOnlyTagList EMPTY = new ReadOnlyTagList(new ArrayList<>()); + + private final List list; + + public ReadOnlyTagList(List list) { + this.list = list; + } + + @Override + public Iterator iterator() { + return list.iterator(); + } + + public int size() { + return list.size(); + } + + public boolean isEmpty() { + return list.isEmpty(); + } + + public Tag get(int index) { + return list.get(index); + } + + public int indexOf(Tag tag) { + return list.indexOf(tag); + } + + public ArrayList toArrayList() { + return new ArrayList<>(list); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 9fc2a1482..7ade5e28f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -1,3651 +1,3651 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash; - -import SevenZip.Compression.LZMA.Decoder; -import SevenZip.Compression.LZMA.Encoder; -import com.jpexs.debugger.flash.SWD; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.CachedDecompilation; -import com.jpexs.decompiler.flash.abc.ClassPath; -import com.jpexs.decompiler.flash.abc.RenameType; -import com.jpexs.decompiler.flash.abc.ScriptPack; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; -import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair; -import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; -import com.jpexs.decompiler.flash.abc.types.ConvertData; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.ScriptInfo; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.ActionGraphSource; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.ActionListReader; -import com.jpexs.decompiler.flash.action.ActionLocalData; -import com.jpexs.decompiler.flash.action.CachedScript; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.dumpview.DumpInfo; -import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter; -import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter; -import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; -import com.jpexs.decompiler.flash.exporters.shape.ShapeExportData; -import com.jpexs.decompiler.flash.helpers.HighlightedText; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.flash.helpers.collections.MyEntry; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.flash.tags.DebugIDTag; -import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; -import com.jpexs.decompiler.flash.tags.DefineSoundTag; -import com.jpexs.decompiler.flash.tags.DefineSpriteTag; -import com.jpexs.decompiler.flash.tags.DoInitActionTag; -import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag; -import com.jpexs.decompiler.flash.tags.EnableDebuggerTag; -import com.jpexs.decompiler.flash.tags.EnableTelemetryTag; -import com.jpexs.decompiler.flash.tags.EndTag; -import com.jpexs.decompiler.flash.tags.ExportAssetsTag; -import com.jpexs.decompiler.flash.tags.FileAttributesTag; -import com.jpexs.decompiler.flash.tags.JPEGTablesTag; -import com.jpexs.decompiler.flash.tags.MetadataTag; -import com.jpexs.decompiler.flash.tags.ProtectTag; -import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; -import com.jpexs.decompiler.flash.tags.ShowFrameTag; -import com.jpexs.decompiler.flash.tags.SymbolClassTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.TagStub; -import com.jpexs.decompiler.flash.tags.VideoFrameTag; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; -import com.jpexs.decompiler.flash.tags.base.ButtonTag; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.tags.base.DrawableTag; -import com.jpexs.decompiler.flash.tags.base.Exportable; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.tags.base.ImportTag; -import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; -import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; -import com.jpexs.decompiler.flash.tags.base.RemoveTag; -import com.jpexs.decompiler.flash.tags.base.RenderContext; -import com.jpexs.decompiler.flash.tags.base.ShapeTag; -import com.jpexs.decompiler.flash.tags.base.SoundTag; -import com.jpexs.decompiler.flash.tags.base.TextTag; -import com.jpexs.decompiler.flash.tags.enums.ImageFormat; -import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; -import com.jpexs.decompiler.flash.timeline.AS2Package; -import com.jpexs.decompiler.flash.timeline.Frame; -import com.jpexs.decompiler.flash.timeline.FrameScript; -import com.jpexs.decompiler.flash.timeline.TagScript; -import com.jpexs.decompiler.flash.timeline.Timeline; -import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.treeitems.SWFList; -import com.jpexs.decompiler.flash.treeitems.TreeItem; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFField; -import com.jpexs.decompiler.flash.xfl.FLAVersion; -import com.jpexs.decompiler.flash.xfl.XFLConverter; -import com.jpexs.decompiler.flash.xfl.XFLExportSettings; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.Cache; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.NulStream; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.SerializableImage; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.EmptyStackException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.DeflaterOutputStream; -import java.util.zip.InflaterInputStream; - -/** - * Class representing SWF file - * - * @author JPEXS - */ -public final class SWF implements SWFContainerItem, Timelined { - - // big object for testing cleanup - //BigObject bigObj = new BigObject(); - /** - * Default version of SWF file format - */ - public static final int DEFAULT_VERSION = 10; - - /** - * Maximum SWF file format version Needs to be fixed when SWF versions - * reaches this value - */ - public static final int MAX_VERSION = 32; - - /** - * Tags inside of file - */ - @SWFField - private List tags = new ArrayList<>(); - - @Internal - public ReadOnlyTagList readOnlyTags; - - public boolean hasEndTag = true; - - /** - * ExportRectangle for the display - */ - public RECT displayRect; - - /** - * Movie frame rate - */ - public float frameRate; - - /** - * Number of frames in movie - */ - public int frameCount; - - /** - * Version of SWF - */ - public int version; - - /** - * Uncompressed size of the file - */ - @Internal - public long fileSize; - - /** - * Used compression mode - */ - public SWFCompression compression = SWFCompression.NONE; - - /** - * Compressed size of the file (LZMA) - */ - @Internal - public long compressedSize; - - /** - * LZMA Properties - */ - public byte[] lzmaProperties; - - @Internal - public byte[] uncompressedData; - - @Internal - public byte[] originalUncompressedData; - - /** - * ScaleForm GFx - */ - public boolean gfx = false; - - @Internal - public SWFList swfList; - - @Internal - private String file; - - @Internal - private String fileTitle; - - @Internal - private volatile Map characters; - - @Internal - private volatile Map> characterIdTags; - - @Internal - private volatile Map> dependentCharacters; - - @Internal - private volatile List abcList; - - @Internal - private volatile JPEGTablesTag jtt; - - @Internal - public Map sourceFontNamesMap = new HashMap<>(); - - public static final double unitDivisor = 20; - - private static final Logger logger = Logger.getLogger(SWF.class.getName()); - - @Internal - private boolean isModified; - - @Internal - private Timeline timeline; - - @Internal - public DumpInfoSwfNode dumpInfo; - - @Internal - public DefineBinaryDataTag binaryData; - - @Internal - private final HashMap deobfuscated = new HashMap<>(); - - @Internal - private final IdentifiersDeobfuscation deobfuscation = new IdentifiersDeobfuscation(); - - @Internal - private final Cache frameCache = Cache.getInstance(false, false, "frame"); - - @Internal - private final Cache rectCache = Cache.getInstance(true, true, "rect"); - - @Internal - private final Cache shapeExportDataCache = Cache.getInstance(true, true, "shapeExportData"); - - @Internal - private final Cache soundCache = Cache.getInstance(false, false, "sound"); - - @Internal - private final Cache as2PcodeCache = Cache.getInstance(true, true, "as2pcode"); - - @Internal - private final Cache as2Cache = Cache.getInstance(true, false, "as2"); - - @Internal - private final Cache as3Cache = Cache.getInstance(true, false, "as3"); - - public static List swfSignatures = Arrays.asList( - "FWS", // Uncompressed Flash - "CWS", // ZLib compressed Flash - "ZWS", // LZMA compressed Flash - "GFX", // Uncompressed ScaleForm GFx - "CFX", // Compressed ScaleForm GFx - "ABC" // Non-standard LZMA compressed Flash - ); - - public void updateCharacters() { - characters = null; - characterIdTags = null; - } - - public void clearTagSwfs() { - resetTimelines(this); - updateCharacters(); - - for (Tag tag : getTags()) { - if (tag instanceof DefineSpriteTag) { - DefineSpriteTag spriteTag = (DefineSpriteTag) tag; - for (Tag tag1 : spriteTag.getTags()) { - tag1.setSwf(null); - } - - for (int i = spriteTag.getTags().size() - 1; i >= 0; i--) { - spriteTag.removeTag(i); - } - } - - if (tag instanceof DefineBinaryDataTag) { - DefineBinaryDataTag binaryTag = (DefineBinaryDataTag) tag; - if (binaryTag.innerSwf != null) { - binaryTag.innerSwf.clearTagSwfs(); - } - } - - tag.setSwf(null); - } - - tags.clear(); - if (abcList != null) { - abcList.clear(); - } - - if (swfList != null) { - swfList.swfs.clear(); - } - - as2PcodeCache.clear(); - as2Cache.clear(); - as3Cache.clear(); - frameCache.clear(); - soundCache.clear(); - - timeline = null; - clearDumpInfo(dumpInfo); - dumpInfo = null; - jtt = null; - binaryData = null; - } - - private void clearDumpInfo(DumpInfo di) { - for (DumpInfo childInfo : di.getChildInfos()) { - clearDumpInfo(childInfo); - } - - di.getChildInfos().clear(); - } - - public Map getCharacters() { - if (characters == null) { - synchronized (this) { - if (characters == null) { - Map chars = new HashMap<>(); - Map> charIdtags = new HashMap<>(); - parseCharacters(getTags(), chars, charIdtags); - characters = Collections.unmodifiableMap(chars); - characterIdTags = Collections.unmodifiableMap(charIdtags); - } - } - } - - return characters; - } - - public List getCharacterIdTags(int characterId) { - if (characterIdTags == null) { - getCharacters(); - } - - return characterIdTags.get(characterId); - } - - public CharacterIdTag getCharacterIdTag(int characterId, int tagId) { - List characterIdTags = getCharacterIdTags(characterId); - if (characterIdTags != null) { - for (CharacterIdTag t : characterIdTags) { - if (((Tag) t).getId() == tagId) { - if (t.getCharacterId() == characterId) { - return t; - } - } - } - } - - return null; - } - - public Map> getDependentCharacters() { - if (dependentCharacters == null) { - synchronized (this) { - if (dependentCharacters == null) { - Map> dep = new HashMap<>(); - for (Tag tag : getTags()) { - if (tag instanceof CharacterTag) { - int characterId = ((CharacterTag) tag).getCharacterId(); - Set needed = new HashSet<>(); - tag.getNeededCharacters(needed); - for (Integer needed1 : needed) { - Set s = dep.get(needed1); - if (s == null) { - s = new HashSet<>(); - dep.put(needed1, s); - } - - s.add(characterId); - } - } - } - - dependentCharacters = dep; - } - } - } - - return dependentCharacters; - } - - public Set getDependentCharacters(int characterId) { - Set visited = new HashSet<>(); - - Set dependents2 = new LinkedHashSet<>(); - Set deps = getDependentCharacters().get(characterId); - if (deps != null) { - dependents2.addAll(deps); - } - - while (visited.size() != dependents2.size()) { - for (int chId : dependents2) { - if (!visited.contains(chId)) { - visited.add(chId); - if (getCharacters().containsKey(chId)) { - deps = getDependentCharacters().get(chId); - if (deps != null) { - dependents2.addAll(deps); - } - - break; - } - } - } - } - - Set dependents = new LinkedHashSet<>(); - for (Integer chId : dependents2) { - if (getCharacters().containsKey(chId)) { - dependents.add(chId); - } - } - - return dependents; - } - - public CharacterTag getCharacter(int characterId) { - return getCharacters().get(characterId); - } - - public String getExportName(int characterId) { - CharacterTag characterTag = getCharacters().get(characterId); - String exportName = characterTag != null ? characterTag.getExportName() : null; - return exportName; - } - - public FontTag getFontByClass(String fontClass) { - if (fontClass == null) { - return null; - } - for (Tag t : getTags()) { - if (t instanceof FontTag) { - if (fontClass.equals(((FontTag) t).getClassName())) { - return (FontTag) t; - } - } - } - return null; - } - - public FontTag getFont(int fontId) { - CharacterTag characterTag = getCharacters().get(fontId); - if (characterTag instanceof FontTag) { - return (FontTag) characterTag; - } - - if (characterTag != null) { - logger.log(Level.SEVERE, "CharacterTag should be a FontTag. characterId: {0}", fontId); - } - - return null; - } - - public ImageTag getImage(int imageId) { - CharacterTag characterTag = getCharacters().get(imageId); - if (characterTag instanceof ImageTag) { - return (ImageTag) characterTag; - } - - if (characterTag != null) { - logger.log(Level.SEVERE, "CharacterTag should be an ImageTag. characterId: {0}", imageId); - } - - return null; - } - - public DefineSoundTag getSound(int soundId) { - CharacterTag characterTag = getCharacters().get(soundId); - if (characterTag instanceof DefineSoundTag) { - return (DefineSoundTag) characterTag; - } - - if (characterTag != null) { - logger.log(Level.SEVERE, "CharacterTag should be a DefineSoundTag. characterId: {0}", soundId); - } - - return null; - } - - public TextTag getText(int textId) { - CharacterTag characterTag = getCharacters().get(textId); - if (characterTag instanceof TextTag) { - return (TextTag) characterTag; - } - - if (characterTag != null) { - logger.log(Level.SEVERE, "CharacterTag should be a TextTag. characterId: {0}", textId); - } - - return null; - } - - public List getAbcList() { - if (abcList == null) { - synchronized (this) { - if (abcList == null) { - ArrayList newAbcList = new ArrayList<>(); - getAbcTags(getTags(), newAbcList); - abcList = newAbcList; - } - } - } - - return abcList; - } - - public boolean isAS3() { - FileAttributesTag fileAttributes = getFileAttributes(); - return (fileAttributes != null && fileAttributes.actionScript3) || (fileAttributes == null && !getAbcList().isEmpty()); - } - - public MetadataTag getMetadata() { - for (Tag t : getTags()) { - if (t instanceof MetadataTag) { - return (MetadataTag) t; - } - } - - return null; - } - - public FileAttributesTag getFileAttributes() { - for (Tag t : getTags()) { - if (t instanceof FileAttributesTag) { - return (FileAttributesTag) t; - } - } - - return null; - } - - public SetBackgroundColorTag getBackgroundColor() { - for (Tag t : getTags()) { - if (t instanceof SetBackgroundColorTag) { - return (SetBackgroundColorTag) t; - } - } - - return null; - } - - public EnableTelemetryTag getEnableTelemetry() { - for (Tag t : getTags()) { - if (t instanceof EnableTelemetryTag) { - return (EnableTelemetryTag) t; - } - } - return null; - } - - public int getNextCharacterId() { - int max = 0; - Set ids = new HashSet<>(getCharacters().keySet()); - for (Tag t : tags) { - if (t instanceof ImportTag) { - ids.addAll(((ImportTag) t).getAssets().keySet()); - } - } - for (int characterId : ids) { - if (characterId > max) { - max = characterId; - } - } - - return max + 1; - } - - public synchronized JPEGTablesTag getJtt() { - if (jtt == null) { - synchronized (this) { - if (jtt == null) { - for (Tag t : getTags()) { - if (t instanceof JPEGTablesTag) { - jtt = (JPEGTablesTag) t; - break; - } - } - } - } - } - - return jtt; - } - - public String getDocumentClass() { - for (Tag t : getTags()) { - if (t instanceof SymbolClassTag) { - SymbolClassTag sc = (SymbolClassTag) t; - for (int i = 0; i < sc.tags.size(); i++) { - if (sc.tags.get(i) == 0) { - return sc.names.get(i); - } - } - } - } - - return null; - } - - public void fixCharactersOrder(boolean checkAll) { - Set addedCharacterIds = new HashSet<>(); - Set movedTags = new HashSet<>(); - for (int i = 0; i < tags.size(); i++) { - Tag tag = tags.get(i); - if (checkAll || tag.isModified()) { - Set needed = new HashSet<>(); - tag.getNeededCharacters(needed); - if (tag instanceof CharacterTag) { - CharacterTag characterTag = (CharacterTag) tag; - needed.remove(characterTag.getCharacterId()); - } - boolean moved = false; - for (Integer id : needed) { - if (!addedCharacterIds.contains(id)) { - CharacterTag neededCharacter = getCharacter(id); - if (neededCharacter == null) { - continue; - } - - if (movedTags.contains(neededCharacter)) { - logger.log(Level.SEVERE, "Fixing characters order failed, recursion detected."); - return; - } - - // move the needed character to the current position - tags.remove(neededCharacter); - tags.add(i, neededCharacter); - movedTags.add(neededCharacter); - moved = true; - } - } - - if (moved) { - i--; - continue; - } - } - if (tag instanceof CharacterTag) { - addedCharacterIds.add(((CharacterTag) tag).getCharacterId()); - } - } - } - - public void resetTimelines(Timelined timelined) { - timelined.resetTimeline(); - if (timelined instanceof SWF) { - for (Tag t : ((SWF) timelined).getTags()) { - if (t instanceof Timelined) { - resetTimelines((Timelined) t); - } - } - } - } - - private void parseCharacters(Iterable list, Map characters, Map> characterIdTags) { - for (Tag t : list) { - if (t instanceof CharacterIdTag) { - int characterId = ((CharacterIdTag) t).getCharacterId(); - if (t instanceof CharacterTag) { - if (characters.containsKey(characterId)) { - logger.log(Level.SEVERE, "SWF already contains characterId={0}", characterId); - } - - if (characterId != 0) { - characters.put(characterId, (CharacterTag) t); - characterIdTags.put(characterId, new ArrayList<>()); - } - } else if (characterIdTags.containsKey(characterId)) { - characterIdTags.get(characterId).add((CharacterIdTag) t); - } - } - - if (t instanceof DefineSpriteTag) { - parseCharacters(((DefineSpriteTag) t).getTags(), characters, characterIdTags); - } - } - } - - /** - * Unresolve recursive sprites - */ - private void checkInvalidSprites() { - for (int i = 0; i < tags.size(); i++) { - Tag t = tags.get(i); - if (t instanceof DefineSpriteTag) { - if (!isSpriteValid((DefineSpriteTag) t, new ArrayList<>())) { - tags.set(i, new TagStub(this, t.getId(), "InvalidSprite", t.getOriginalRange(), null)); - } - } - } - } - - private boolean isSpriteValid(DefineSpriteTag sprite, List path) { - if (path.contains(sprite.spriteId)) { - return false; - } - path.add(sprite.spriteId); - for (Tag t : sprite.getTags()) { - if (t instanceof DefineSpriteTag) { - if (!isSpriteValid((DefineSpriteTag) t, path)) { - return false; - } - } - } - path.remove((Integer) sprite.spriteId); - return true; - } - - @Override - public Timeline getTimeline() { - if (timeline == null) { - timeline = new Timeline(this); - } - return timeline; - } - - @Override - public void resetTimeline() { - if (timeline != null) { - timeline.reset(this); - } - } - - /** - * Gets all tags with specified id - * - * @param tagId Identificator of tag type - * @return List of tags - */ - public List getTagData(int tagId) { - List ret = new ArrayList<>(); - for (Tag tag : getTags()) { - if (tag.getId() == tagId) { - ret.add(tag); - } - } - return ret; - } - - /** - * Saves this SWF into new file - * - * @param os OutputStream to save SWF in - * @throws IOException - */ - public void saveTo(OutputStream os) throws IOException { - byte[] uncompressedData = saveToByteArray(); - compress(new ByteArrayInputStream(uncompressedData), os, compression, lzmaProperties); - } - - public byte[] getHeaderBytes() { - return getHeaderBytes(compression, gfx); - } - - private static byte[] getHeaderBytes(SWFCompression compression, boolean gfx) { - if (compression == SWFCompression.LZMA_ABC) { - return new byte[]{'A', 'B', 'C'}; - } - - byte[] ret = new byte[3]; - - if (compression == SWFCompression.LZMA) { - ret[0] = 'Z'; - } else if (compression == SWFCompression.ZLIB) { - ret[0] = 'C'; - } else if (gfx) { - ret[0] = 'G'; - } else { - ret[0] = 'F'; - } - - if (gfx) { - ret[1] = 'F'; - ret[2] = 'X'; - } else { - ret[1] = 'W'; - ret[2] = 'S'; - } - - return ret; - } - - private byte[] saveToByteArray() throws IOException { - fixCharactersOrder(false); - - byte[] data; - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, version)) { - sos.write(getHeaderBytes(SWFCompression.NONE, gfx)); - sos.writeUI8(version); - sos.writeUI32(0); // placeholder for file length - sos.writeRECT(displayRect); - sos.writeFIXED8(frameRate); - sos.writeUI16(frameCount); - - sos.writeTags(getLocalTags()); - if (hasEndTag) { - sos.writeUI16(0); - } - - data = baos.toByteArray(); - } - - // update file size - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, version)) { - sos.writeUI32(data.length); - byte[] lengthData = baos.toByteArray(); - System.arraycopy(lengthData, 0, data, 4, lengthData.length); - } - - return data; - } - - /** - * Compress SWF file - * - * @param is InputStream - * @param os OutputStream to save SWF in - * @param compression - * @param lzmaProperties - * @throws IOException - */ - private static void compress(InputStream is, OutputStream os, SWFCompression compression, byte[] lzmaProperties) throws IOException { - byte[] hdr = new byte[8]; - - is.mark(8); - - // SWFheader: signature, version and fileSize - if (is.read(hdr) != 8) { - throw new SwfOpenException("SWF header is too short"); - } - - boolean uncompressed = hdr[0] == 'F' || hdr[0] == 'G'; // FWS or GFX - if (!uncompressed) { - // fisrt decompress, then compress to the given format - is.reset(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - decompress(is, baos, false); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - compress(bais, os, compression, lzmaProperties); - return; - } - - boolean gfx = hdr[1] == 'F' && hdr[2] == 'X'; - int version = hdr[3]; - long fileSize; - try (SWFInputStream sis = new SWFInputStream(null, Arrays.copyOfRange(hdr, 4, 8), 4, 4)) { - fileSize = sis.readUI32("fileSize"); - } - - SWFOutputStream sos = new SWFOutputStream(os, version); - sos.write(getHeaderBytes(compression, gfx)); - sos.writeUI8(version); - sos.writeUI32(fileSize); - - if (compression == SWFCompression.LZMA || compression == SWFCompression.LZMA_ABC) { - long uncompressedLength = fileSize - 8; - Encoder enc = new Encoder(); - if (lzmaProperties == null) { - // todo: the bytes are from a sample swf - lzmaProperties = new byte[]{93, 0, 0, 32, 0}; - } - - int val = lzmaProperties[0] & 0xFF; - int lc = val % 9; - int remainder = val / 9; - int lp = remainder % 5; - int pb = remainder / 5; - int dictionarySize = 0; - for (int i = 0; i < 4; i++) { - dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8); - } - if (Configuration.lzmaFastBytes.get() > 0) { - enc.SetNumFastBytes(Configuration.lzmaFastBytes.get()); - } - enc.SetDictionarySize(dictionarySize); - enc.SetLcLpPb(lc, lp, pb); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - enc.SetEndMarkerMode(true); - enc.Code(is, baos, -1, -1, null); - byte[] data = baos.toByteArray(); - if (compression == SWFCompression.LZMA) { - byte[] udata = new byte[4]; - udata[0] = (byte) (data.length & 0xFF); - udata[1] = (byte) ((data.length >> 8) & 0xFF); - udata[2] = (byte) ((data.length >> 16) & 0xFF); - udata[3] = (byte) ((data.length >> 24) & 0xFF); - os.write(udata); - } - enc.WriteCoderProperties(os); - if (compression == SWFCompression.LZMA_ABC) { - byte[] udata = new byte[8]; - udata[0] = (byte) (uncompressedLength & 0xFF); - udata[1] = (byte) ((uncompressedLength >> 8) & 0xFF); - udata[2] = (byte) ((uncompressedLength >> 16) & 0xFF); - udata[3] = (byte) ((uncompressedLength >> 24) & 0xFF); - udata[4] = (byte) ((uncompressedLength >> 32) & 0xFF); - udata[5] = (byte) ((uncompressedLength >> 40) & 0xFF); - udata[6] = (byte) ((uncompressedLength >> 48) & 0xFF); - udata[7] = (byte) ((uncompressedLength >> 56) & 0xFF); - os.write(udata); - } - os.write(data); - } else if (compression == SWFCompression.ZLIB) { - DeflaterOutputStream dos = new DeflaterOutputStream(os); - try { - Helper.copyStream(is, dos); - } finally { - dos.finish(); - } - } else { - Helper.copyStream(is, os); - } - } - - @Override - public boolean isModified() { - if (isModified) { - return true; - } - - for (Tag tag : getTags()) { - if (tag.isModified()) { - return true; - } - } - return false; - } - - @Override - public void setModified(boolean value) { - isModified = value; - } - - public void clearModified() { - for (Tag tag : getTags()) { - if (tag.isModified()) { - tag.createOriginalData(); - tag.setModified(false); - } - } - - isModified = false; - - try { - uncompressedData = saveToByteArray(); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Cannot save SWF", ex); - } - } - - /** - * Constructs an empty SWF - */ - public SWF() { - version = SWF.DEFAULT_VERSION; - displayRect = new RECT(0, 1, 0, 1); - } - - /** - * Construct SWF from stream - * - * @param is Stream to read SWF from - * @param parallelRead Use parallel threads? - * @throws IOException - * @throws java.lang.InterruptedException - */ - public SWF(InputStream is, boolean parallelRead) throws IOException, InterruptedException { - this(is, null, null, null, parallelRead, false, true); - } - - /** - * Construct SWF from stream - * - * @param is Stream to read SWF from - * @param parallelRead Use parallel threads? - * @param lazy - * @throws IOException - * @throws java.lang.InterruptedException - */ - public SWF(InputStream is, boolean parallelRead, boolean lazy) throws IOException, InterruptedException { - this(is, null, null, null, parallelRead, false, lazy); - } - - /** - * Construct SWF from stream - * - * @param is Stream to read SWF from - * @param file Path to the file - * @param fileTitle Title of the SWF - * @param parallelRead Use parallel threads? - * @throws IOException - * @throws java.lang.InterruptedException - */ - public SWF(InputStream is, String file, String fileTitle, boolean parallelRead) throws IOException, InterruptedException { - this(is, file, fileTitle, null, parallelRead, false, true); - } - - /** - * Construct SWF from stream - * - * @param is Stream to read SWF from - * @param listener - * @param parallelRead Use parallel threads? - * @throws IOException - * @throws java.lang.InterruptedException - */ - public SWF(InputStream is, ProgressListener listener, boolean parallelRead) throws IOException, InterruptedException { - this(is, null, null, listener, parallelRead, false, true); - } - - /** - * Construct SWF from stream - * - * @param is Stream to read SWF from - * @param file Path to the file - * @param fileTitle Title of the SWF - * @param listener - * @param parallelRead Use parallel threads? - * @throws IOException - * @throws java.lang.InterruptedException - */ - public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead) throws IOException, InterruptedException { - this(is, file, fileTitle, listener, parallelRead, false, true); - } - - /** - * Faster constructor to check SWF only - * - * @param is - * @throws java.io.IOException - */ - public SWF(InputStream is) throws IOException { - decompress(is, new NulStream(), true); - } - - public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy) throws IOException, InterruptedException { - this(is, file, fileTitle, listener, parallelRead, checkOnly, lazy, null); - } - - /** - * Construct SWF from stream - * - * @param is Stream to read SWF from - * @param file Path to the file - * @param fileTitle Title of the SWF - * @param listener - * @param parallelRead Use parallel threads? - * @param checkOnly Check only file validity - * @param lazy - * @param resolver Resolver for imported tags - * @throws IOException - * @throws java.lang.InterruptedException - */ - public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy, UrlResolver resolver) throws IOException, InterruptedException { - this.file = file; - this.fileTitle = fileTitle; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFHeader header = decompress(is, baos, true); - gfx = header.gfx; - compression = header.compression; - lzmaProperties = header.lzmaProperties; - uncompressedData = baos.toByteArray(); - originalUncompressedData = uncompressedData; - - SWFInputStream sis = new SWFInputStream(this, uncompressedData); - dumpInfo = new DumpInfoSwfNode(this, "rootswf", "", null, 0, 0); - sis.dumpInfo = dumpInfo; - sis.skipBytesEx(3, "signature"); // skip siganture - version = sis.readUI8("version"); - fileSize = sis.readUI32("fileSize"); - dumpInfo.lengthBytes = fileSize; - if (listener != null) { - sis.addPercentListener(listener); - } - sis.setPercentMax(fileSize); - displayRect = sis.readRECT("displayRect"); - frameRate = sis.readFIXED8("frameRate"); - frameCount = sis.readUI16("frameCount"); - List tags = sis.readTagList(this, 0, parallelRead, true, !checkOnly, lazy); - if (tags.size() > 0 && tags.get(tags.size() - 1).getId() == EndTag.ID) { - tags.remove(tags.size() - 1); - } else { - hasEndTag = false; - } - this.tags = tags; - readOnlyTags = null; - if (!checkOnly) { - checkInvalidSprites(); - updateCharacters(); - assignExportNamesToSymbols(); - assignClassesToSymbols(); - if (resolver != null) { - resolveImported(resolver); - } - SWFDecompilerPlugin.fireSwfParsed(this); - } else { - boolean hasNonUnknownTag = false; - for (Tag tag : tags) { - if (tag.getOriginalDataLength() > 0 && Tag.getRequiredTags().contains(tag.getId())) { - hasNonUnknownTag = true; - } - } - if (!hasNonUnknownTag) { - throw new IOException("Invalid SWF file. No known tag found."); - } - } - - if (Configuration.autoRenameIdentifiers.get()) { - deobfuscateIdentifiers(RenameType.TYPENUMBER); - assignClassesToSymbols(); - clearScriptCache(); - } - - getASMs(true); // Add scriptNames to ASMs - } - - private void resolveImported(UrlResolver resolver) { - for (int p = 0; p < tags.size(); p++) { - Tag t = tags.get(p); - if (t instanceof ImportTag) { - ImportTag importTag = (ImportTag) t; - - SWF iSwf = resolver.resolveUrl(importTag.getUrl()); - if (iSwf != null) { - Map exportedMap1 = new HashMap<>(); - Map classesMap1 = new HashMap<>(); - - for (Tag t2 : iSwf.tags) { - if (t2 instanceof ExportAssetsTag) { - ExportAssetsTag sc = (ExportAssetsTag) t2; - Map m2 = sc.getTagToNameMap(); - for (int key : m2.keySet()) { - if (!exportedMap1.containsKey(key)) { - exportedMap1.put(key, m2.get(key)); - } - } - } - if (t2 instanceof SymbolClassTag) { - SymbolClassTag sc = (SymbolClassTag) t2; - Map m2 = sc.getTagToNameMap(); - for (int key : m2.keySet()) { - if (!classesMap1.containsKey(key)) { - classesMap1.put(key, m2.get(key)); - } - } - } - } - Map exportedMap2 = new HashMap<>(); - for (int k : exportedMap1.keySet()) { - exportedMap2.put(exportedMap1.get(k), k); - } - - Map classesMap2 = new HashMap<>(); - for (int k : classesMap1.keySet()) { - classesMap2.put(classesMap1.get(k), k); - } - - Map importedMap1 = importTag.getAssets(); - Map importedMap2 = new HashMap<>(); - for (int k : importedMap1.keySet()) { - importedMap2.put(importedMap1.get(k), k); - } - - int pos = 0; - for (String key : importedMap2.keySet()) { - if (!exportedMap2.containsKey(key)) { - continue; //? - } - int exportedId = exportedMap2.get(key); - int importedId = importedMap2.get(key); - for (Tag cht : iSwf.tags) { - if ((cht instanceof CharacterIdTag) && (((CharacterIdTag) cht).getCharacterId() == exportedId) && !(cht instanceof PlaceObjectTypeTag) && !(cht instanceof RemoveTag)) { - CharacterIdTag ch = (CharacterIdTag) cht; - cht.setSwf(this); - ch.setCharacterId(importedId); - cht.setImported(true); - tags.add(p + 1 + pos, cht); - pos++; - } - } - } - - int newId = getNextCharacterId(); - pos = 0; - for (String key : classesMap2.keySet()) { - int exportedId = classesMap2.get(key); - int importedId = newId++; - for (Tag cht : iSwf.tags) { - if ((cht instanceof CharacterIdTag) && (((CharacterIdTag) cht).getCharacterId() == exportedId) && !(cht instanceof PlaceObjectTypeTag) && !(cht instanceof RemoveTag)) { - CharacterIdTag ch = (CharacterIdTag) cht; - cht.setSwf(this); - ch.setCharacterId(importedId); - cht.setImported(true); - tags.add(p + 1 + pos, cht); - pos++; - } - } - } - updateCharacters(); - } - } - } - } - - @Override - public SWF getSwf() { - return this; - } - - public SWF getRootSwf() { - SWF result = this; - while (result.binaryData != null) { - result = result.binaryData.getSwf(); - } - - return result; - } - - public String getFile() { - return file; - } - - /** - * Get title of the file - * - * @return file title - */ - public String getFileTitle() { - if (fileTitle != null) { - return fileTitle; - } - return file; - } - - public String getShortFileName() { - String title = getFileTitle(); - if (title == null) { - return ""; - } - return new File(title).getName(); - } - - public void setFile(String file) { - this.file = file; - fileTitle = null; - } - - public Date getFileModificationDate() { - try { - if (swfList != null && swfList.sourceInfo != null) { - String fileName = swfList.sourceInfo.getFile(); - if (fileName != null) { - long lastModified = new File(fileName).lastModified(); - if (lastModified > 0) { - return new Date(lastModified); - } - } - } - } catch (SecurityException sex) { - } - - return new Date(); - } - - private static void getAbcTags(Iterable list, List actionScripts) { - for (Tag t : list) { - if (t instanceof DefineSpriteTag) { - getAbcTags(((DefineSpriteTag) t).getTags(), actionScripts); - } - if (t instanceof ABCContainerTag) { - actionScripts.add((ABCContainerTag) t); - } - } - } - - public void assignExportNamesToSymbols() { - HashMap exportNames = new HashMap<>(); - for (Tag t : getTags()) { - if (t instanceof ExportAssetsTag) { - ExportAssetsTag eat = (ExportAssetsTag) t; - for (int i = 0; i < eat.tags.size(); i++) { - Integer tagId = eat.tags.get(i); - String name = eat.names.get(i); - if ((!exportNames.containsKey(tagId)) && (!exportNames.containsValue(name))) { - exportNames.put(tagId, name); - } - } - } - } - for (Tag t : getTags()) { - if (t instanceof CharacterTag) { - CharacterTag ct = (CharacterTag) t; - if (exportNames.containsKey(ct.getCharacterId())) { - ct.setExportName(exportNames.get(ct.getCharacterId())); - } - } - } - } - - public void assignClassesToSymbols() { - HashMap classes = new HashMap<>(); - for (Tag t : getTags()) { - if (t instanceof SymbolClassTag) { - SymbolClassTag sct = (SymbolClassTag) t; - for (int i = 0; i < sct.tags.size(); i++) { - if ((!classes.containsKey(sct.tags.get(i))) && (!classes.containsValue(sct.names.get(i)))) { - classes.put(sct.tags.get(i), sct.names.get(i)); - } - } - } - } - for (Tag t : getTags()) { - if (t instanceof CharacterTag) { - CharacterTag ct = (CharacterTag) t; - if (classes.containsKey(ct.getCharacterId())) { - ct.setClassName(classes.get(ct.getCharacterId())); - } - } - } - } - - /** - * Compress SWF file - * - * @param fis Input stream - * @param fos Output stream - * @param compression - * @return True on success - */ - public static boolean compress(InputStream fis, OutputStream fos, SWFCompression compression) { - try { - compress(fis, fos, compression, null); - } catch (IOException ex) { - return false; - } - return true; - } - - public static boolean decompress(InputStream fis, OutputStream fos) { - try { - decompress(fis, fos, false); - return true; - } catch (IOException ex) { - return false; - } - } - - private static void decodeLZMAStream(InputStream is, OutputStream os, byte[] lzmaProperties, long fileSize) throws IOException { - Decoder decoder = new Decoder(); - if (!decoder.SetDecoderProperties(lzmaProperties)) { - throw new IOException("LZMA:Incorrect stream properties"); - } - if (!decoder.Code(is, os, fileSize - 8)) { - throw new IOException("LZMA:Error in data stream"); - } - } - - private static SWFHeader decompress(InputStream is, OutputStream os, boolean allowUncompressed) throws IOException { - byte[] hdr = new byte[8]; - - // SWFheader: signature, version and fileSize - if (is.read(hdr) != 8) { - throw new SwfOpenException("SWF header is too short"); - } - - String signature = new String(hdr, 0, 3, Utf8Helper.charset); - if (!swfSignatures.contains(signature)) { - throw new SwfOpenException("Invalid SWF file, wrong signature."); - } - - int version = hdr[3]; - long fileSize; - try (SWFInputStream sis = new SWFInputStream(null, Arrays.copyOfRange(hdr, 4, 8), 4, 4)) { - fileSize = sis.readUI32("fileSize"); - } - - SWFHeader header = new SWFHeader(); - header.version = version; - header.fileSize = fileSize; - header.gfx = hdr[1] == 'F' && hdr[2] == 'X'; - - try (SWFOutputStream sos = new SWFOutputStream(os, version)) { - sos.write(getHeaderBytes(SWFCompression.NONE, header.gfx)); - sos.writeUI8(version); - sos.writeUI32(fileSize); - - switch (hdr[0]) { - case 'C': { // CWS, CFX - Helper.copyStream(new InflaterInputStream(is), os, fileSize - 8); - header.compression = SWFCompression.ZLIB; - break; - } - case 'Z': { // ZWS - byte[] lzmaprop = new byte[9]; - is.read(lzmaprop); - try (SWFInputStream sis = new SWFInputStream(null, lzmaprop)) { - sis.readUI32("LZMAsize"); // compressed LZMA data size = compressed SWF - 17 byte, - // where 17 = 8 byte header + this 4 byte + 5 bytes decoder properties - - int propertiesSize = 5; - byte[] lzmaProperties = sis.readBytes(propertiesSize, "lzmaproperties"); - if (lzmaProperties.length != propertiesSize) { - throw new IOException("LZMA:input .lzma file is too short"); - } - - decodeLZMAStream(is, os, lzmaProperties, fileSize); - - header.compression = SWFCompression.LZMA; - header.lzmaProperties = lzmaProperties; - } - break; - } - case 'A': { // ABC - byte[] lzmaProperties = new byte[5]; - is.read(lzmaProperties); - byte[] uncompressedLength = new byte[8]; - is.read(uncompressedLength); - - decodeLZMAStream(is, os, lzmaProperties, fileSize); - - header.compression = SWFCompression.LZMA_ABC; - header.lzmaProperties = lzmaProperties; - break; - } - default: { // FWS, GFX - if (allowUncompressed) { - Helper.copyStream(is, os, fileSize - 8); - } else { - throw new IOException("SWF is not compressed"); - } - } - } - - return header; - } - } - - public static boolean renameInvalidIdentifiers(RenameType renameType, InputStream fis, OutputStream fos) { - try { - SWF swf = new SWF(fis, Configuration.parallelSpeedUp.get()); - int cnt = swf.deobfuscateIdentifiers(renameType); - swf.assignClassesToSymbols(); - System.out.println(cnt + " identifiers renamed."); - swf.saveTo(fos); - } catch (InterruptedException | IOException ex) { - return false; - } - return true; - } - - public List getScriptPacksByClassNames(List classNames) throws Exception { - Set resultSet = new HashSet<>(); - - List abcList = getAbcList(); - List allAbcList = new ArrayList<>(); - for (int i = 0; i < abcList.size(); i++) { - allAbcList.add(abcList.get(i).getABC()); - } - - for (String className : classNames) { - for (int i = 0; i < abcList.size(); i++) { - ABC abc = abcList.get(i).getABC(); - List scrs = abc.findScriptPacksByPath(className, allAbcList); - for (int j = 0; j < scrs.size(); j++) { - ScriptPack scr = scrs.get(j); - resultSet.add(scr); - } - } - } - - return new ArrayList<>(resultSet); - } - - private List uniqueAS3Packs(List packs) { - List ret = new ArrayList<>(); - Set classPaths = new HashSet<>(); - for (ScriptPack item : packs) { - ClassPath key = item.getClassPath(); - if (classPaths.contains(key)) { - logger.log(Level.SEVERE, "Duplicate pack path found (" + key + ")!"); - } else { - classPaths.add(key); - ret.add(item); - } - } - return ret; - } - - public List getAS3Packs() { - List packs = new ArrayList<>(); - - List abcList = getAbcList(); - List allAbcList = new ArrayList<>(); - for (int i = 0; i < abcList.size(); i++) { - allAbcList.add(abcList.get(i).getABC()); - } - - for (ABCContainerTag abcTag : abcList) { - packs.addAll(abcTag.getABC().getScriptPacks(null, allAbcList)); - } - return uniqueAS3Packs(packs); - } - - @Override - public RECT getRect() { - return displayRect; - } - - @Override - public RECT getRect(Set added) { - return displayRect; - } - - public EventListener getExportEventListener() { - EventListener evl = new EventListener() { - @Override - public void handleExportingEvent(String type, int index, int count, Object data) { - for (EventListener listener : listeners) { - listener.handleExportingEvent(type, index, count, data); - } - } - - @Override - public void handleExportedEvent(String type, int index, int count, Object data) { - for (EventListener listener : listeners) { - listener.handleExportedEvent(type, index, count, data); - } - } - - @Override - public void handleEvent(String event, Object data) { - informListeners(event, data); - } - }; - - return evl; - } - - public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException { - return exportActionScript(handler, outdir, null, exportSettings, parallel, evl, true, true); - } - - public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, List as3scripts, ScriptExportSettings exportSettings, boolean parallel, EventListener evl, boolean as2, boolean as3) throws IOException { - List ret = new ArrayList<>(); - - if (isAS3()) { - if (as3) { - ret.addAll(new AS3ScriptExporter().exportActionScript3(this, handler, outdir, as3scripts, exportSettings, parallel, evl)); - } - } else if (as2) { - ret.addAll(new AS2ScriptExporter().exportAS2Scripts(handler, outdir, getASMs(true), exportSettings, parallel, evl)); - } - return ret; - } - - public Map getASMs(boolean exportFileNames) { - return getASMs(exportFileNames, new ArrayList<>(), true); - } - - public Map getASMs(boolean exportFileNames, List nodesToExport, boolean exportAll) { - Map asmsToExport = new HashMap<>(); - for (TreeItem treeItem : getFirstLevelASMNodes(null)) { - getASMs(exportFileNames, treeItem, nodesToExport, exportAll, asmsToExport, File.separator + getASMPath(exportFileNames, treeItem)); - } - - return asmsToExport; - } - - private void getASMs(boolean exportFileNames, TreeItem treeItem, List nodesToExport, boolean exportAll, Map asmsToExport, String path) { - boolean exportNode = nodesToExport.contains(treeItem); - TreeItem realItem = treeItem instanceof TagScript ? ((TagScript) treeItem).getTag() : treeItem; - if (realItem instanceof ASMSource && (exportAll || exportNode)) { - String npath = path; - String exPath = path; - int ppos = 1; - while (asmsToExport.containsKey(npath)) { - ppos++; - npath = path + (exportFileNames ? "[" + ppos + "]" : "_" + ppos); - exPath = path + "[" + ppos + "]"; - } - ((ASMSource) realItem).setScriptName(exPath); - asmsToExport.put(npath, (ASMSource) realItem); - } - - if (treeItem instanceof TagScript) { - TagScript tagScript = (TagScript) treeItem; - for (TreeItem subItem : tagScript.getFrames()) { - getASMs(exportFileNames, subItem, nodesToExport, exportAll, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); - } - } else if (treeItem instanceof FrameScript) { - FrameScript frameScript = (FrameScript) treeItem; - Frame parentFrame = frameScript.getFrame(); - for (TreeItem subItem : parentFrame.actionContainers) { - getASMs(exportFileNames, getASMWrapToTagScript(subItem), nodesToExport, exportAll || exportNode, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); - } - for (TreeItem subItem : parentFrame.actions) { - getASMs(exportFileNames, getASMWrapToTagScript(subItem), nodesToExport, exportAll || exportNode, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); - } - } else if (treeItem instanceof AS2Package) { - AS2Package as2Package = (AS2Package) treeItem; - for (TreeItem subItem : as2Package.subPackages.values()) { - getASMs(exportFileNames, subItem, nodesToExport, exportAll, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); - } - for (TreeItem subItem : as2Package.scripts.values()) { - getASMs(exportFileNames, subItem, nodesToExport, exportAll, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); - } - } - } - - private String getASMPath(boolean exportFileName, TreeItem treeItem) { - if (!exportFileName) { - return treeItem.toString(); - } - - String result; - if (treeItem instanceof Exportable) { - result = ((Exportable) treeItem).getExportFileName(); - } else { - result = treeItem.toString(); - } - - return Helper.makeFileName(result); - } - - private TreeItem getASMWrapToTagScript(TreeItem treeItem) { - if (treeItem instanceof Tag) { - Tag resultTag = (Tag) treeItem; - List subNodes = new ArrayList<>(); - if (treeItem instanceof ASMSourceContainer) { - for (ASMSource item : ((ASMSourceContainer) treeItem).getSubItems()) { - subNodes.add(item); - } - } - - TagScript tagScript = new TagScript(treeItem.getSwf(), resultTag, subNodes); - return tagScript; - } - - return treeItem; - } - - public List getFirstLevelASMNodes(Map tagScriptCache) { - Timeline timeline = getTimeline(); - List subNodes = new ArrayList<>(); - List subFrames = new ArrayList<>(); - subNodes.addAll(timeline.getAS2RootPackage().subPackages.values()); - subNodes.addAll(timeline.getAS2RootPackage().scripts.values()); - - for (Tag tag : timeline.otherTags) { - boolean hasInnerFrames = false; - List tagSubNodes = new ArrayList<>(); - if (tag instanceof Timelined) { - Timeline timeline2 = ((Timelined) tag).getTimeline(); - for (Frame frame : timeline2.getFrames()) { - if (!frame.actions.isEmpty() || !frame.actionContainers.isEmpty()) { - FrameScript frameScript = new FrameScript(this, frame); - tagSubNodes.add(frameScript); - hasInnerFrames = true; - } - } - } - - if (tag instanceof ASMSourceContainer) { - for (ASMSource asm : ((ASMSourceContainer) tag).getSubItems()) { - tagSubNodes.add(asm); - } - } - - if (!tagSubNodes.isEmpty()) { - TagScript ts = new TagScript(this, tag, tagSubNodes); - if (tagScriptCache != null) { - tagScriptCache.put(tag, ts); - } - if (hasInnerFrames) { - subFrames.add(ts); - } else { - subNodes.add(ts); - } - } - } - - subNodes.addAll(subFrames); - for (Frame frame : timeline.getFrames()) { - if (!frame.actions.isEmpty() || !frame.actionContainers.isEmpty()) { - FrameScript frameScript = new FrameScript(this, frame); - subNodes.add(frameScript); - } - } - - return subNodes; - } - - private final HashSet listeners = new HashSet<>(); - - public final void addEventListener(EventListener listener) { - listeners.add(listener); - for (Tag t : getTags()) { - if (t instanceof ABCContainerTag) { - (((ABCContainerTag) t).getABC()).addEventListener(listener); - } - } - } - - public final void removeEventListener(EventListener listener) { - listeners.remove(listener); - for (Tag t : getTags()) { - if (t instanceof ABCContainerTag) { - (((ABCContainerTag) t).getABC()).removeEventListener(listener); - } - } - } - - protected void informListeners(String event, Object data) { - for (EventListener listener : listeners) { - listener.handleEvent(event, data); - } - } - - public static void populateVideoFrames(int streamId, Iterable tags, HashMap output) { - for (Tag t : tags) { - if (t instanceof VideoFrameTag) { - VideoFrameTag videoFrameTag = (VideoFrameTag) t; - if (videoFrameTag.streamID == streamId) { - output.put(videoFrameTag.frameNum, (VideoFrameTag) t); - } - } - if (t instanceof DefineSpriteTag) { - populateVideoFrames(streamId, ((DefineSpriteTag) t).getTags(), output); - } - } - } - - private static void writeLE(OutputStream os, long val, int size) throws IOException { - for (int i = 0; i < size; i++) { - os.write((int) (val & 0xff)); - val >>= 8; - } - } - - public static void createWavFromPcmData(OutputStream fos, int soundRateHz, boolean soundSize, boolean soundType, byte[] data) throws IOException { - ByteArrayOutputStream subChunk1Data = new ByteArrayOutputStream(); - int audioFormat = 1; // PCM - writeLE(subChunk1Data, audioFormat, 2); - int numChannels = soundType ? 2 : 1; - writeLE(subChunk1Data, numChannels, 2); - int[] rateMap = {5512, 11025, 22050, 44100}; - int sampleRate = soundRateHz; // rateMap[soundRate]; - writeLE(subChunk1Data, sampleRate, 4); - int bitsPerSample = soundSize ? 16 : 8; - int byteRate = sampleRate * numChannels * bitsPerSample / 8; - writeLE(subChunk1Data, byteRate, 4); - int blockAlign = numChannels * bitsPerSample / 8; - writeLE(subChunk1Data, blockAlign, 2); - writeLE(subChunk1Data, bitsPerSample, 2); - - ByteArrayOutputStream chunks = new ByteArrayOutputStream(); - chunks.write(Utf8Helper.getBytes("fmt ")); - byte[] subChunk1DataBytes = subChunk1Data.toByteArray(); - writeLE(chunks, subChunk1DataBytes.length, 4); - chunks.write(subChunk1DataBytes); - - chunks.write(Utf8Helper.getBytes("data")); - writeLE(chunks, data.length, 4); - chunks.write(data); - - fos.write(Utf8Helper.getBytes("RIFF")); - byte[] chunkBytes = chunks.toByteArray(); - writeLE(fos, 4 + chunkBytes.length, 4); - fos.write(Utf8Helper.getBytes("WAVE")); - fos.write(chunkBytes); - } - - public static String getTypePrefix(CharacterTag c) { - if (c instanceof ShapeTag) { - return "shape"; - } - if (c instanceof MorphShapeTag) { - return "morphshape"; - } - if (c instanceof DefineSpriteTag) { - return "sprite"; - } - if (c instanceof TextTag) { - return "text"; - } - if (c instanceof ButtonTag) { - return "button"; - } - if (c instanceof FontTag) { - return "font"; - } - if (c instanceof ImageTag) { - return "image"; - } - return "character"; - } - - public static void writeLibrary(SWF fswf, Set library, OutputStream fos) throws IOException { - for (int c : library) { - CharacterTag ch = fswf.getCharacter(c); - if (ch instanceof FontTag) { - StringBuilder sb = new StringBuilder(); - sb.append("function ").append(getTypePrefix(ch)).append(c).append("(ctx,ch,textColor){\r\n"); - ((FontTag) ch).toHtmlCanvas(sb, 1); - sb.append("}\r\n\r\n"); - fos.write(Utf8Helper.getBytes(sb.toString())); - } else { - if (ch instanceof ImageTag) { - ImageTag image = (ImageTag) ch; - ImageFormat format = image.getImageFormat(); - byte[] imageData = Helper.readStream(image.getImageData()); - String base64ImgData = Helper.byteArrayToBase64String(imageData); - fos.write(Utf8Helper.getBytes("var imageObj" + c + " = document.createElement(\"img\");\r\nimageObj" + c + ".src=\"data:image/" + format + ";base64," + base64ImgData + "\";\r\n")); - } - fos.write(Utf8Helper.getBytes("function " + getTypePrefix(ch) + c + "(ctx,ctrans,frame,ratio,time){\r\n")); - if (ch instanceof DrawableTag) { - StringBuilder sb = new StringBuilder(); - ((DrawableTag) ch).toHtmlCanvas(sb, 1); - fos.write(Utf8Helper.getBytes(sb.toString())); - } - fos.write(Utf8Helper.getBytes("}\r\n\r\n")); - } - } - } - - private static void getVariables(ConstantPool constantPool, BaseLocalData localData, TranslateStack stack, List output, ActionGraphSource code, int ip, List> variables, List functions, HashMap strings, List visited, HashMap usageTypes, String path) throws InterruptedException { - boolean debugMode = false; - while ((ip > -1) && ip < code.size()) { - if (visited.contains(ip)) { - break; - } - GraphSourceItem ins = code.get(ip); - - if (debugMode) { - System.err.println("Visit " + ip + ": ofs" + Helper.formatAddress(((Action) ins).getAddress()) + ":" + ((Action) ins).getASMSource(new ActionList(), new HashSet<>(), ScriptExportMode.PCODE) + " stack:" + Helper.stackToString(stack, LocalData.create(new ConstantPool()))); - } - if (ins.isExit()) { - break; - } - if (ins.isIgnored()) { - ip++; - continue; - } - - String usageType = "name"; - GraphTargetItem name = null; - if ((ins instanceof ActionGetVariable) - || (ins instanceof ActionGetMember) - || (ins instanceof ActionDefineLocal2) - || (ins instanceof ActionNewMethod) - || (ins instanceof ActionNewObject) - || (ins instanceof ActionCallMethod) - || (ins instanceof ActionCallFunction)) { - if (stack.isEmpty()) { - break; - } - name = stack.peek(); - } - - if ((ins instanceof ActionGetVariable) || (ins instanceof ActionDefineLocal2)) { - usageType = "variable"; - } - if (ins instanceof ActionGetMember) { - usageType = "member"; - } - if ((ins instanceof ActionNewMethod) || (ins instanceof ActionNewObject)) { - usageType = "class"; - } - if (ins instanceof ActionCallMethod) { - usageType = "function"; // can there be method? - } - if (ins instanceof ActionCallFunction) { - usageType = "function"; - } - - if ((ins instanceof ActionDefineFunction) || (ins instanceof ActionDefineFunction2)) { - functions.add(ins); - } - - if (ins instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) ins; - List cntSizes = cnt.getContainerSizes(); - long addr = code.pos2adr(ip + 1); - ip = code.adr2pos(addr); - String cntName = cnt.getName(); - for (Long size : cntSizes) { - if (size == 0) { - continue; - } - ip = code.adr2pos(addr); - addr += size; - int nextip = code.adr2pos(addr); - getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path + (cntName == null ? "" : "/" + cntName)); - ip = nextip; - } - List> r = new ArrayList<>(); - r.add(new ArrayList<>()); - r.add(new ArrayList<>()); - r.add(new ArrayList<>()); - ((GraphSourceItemContainer) ins).translateContainer(r, ins, stack, output, new HashMap<>(), new HashMap<>(), new HashMap<>()); - continue; - } - - if ((ins instanceof ActionSetVariable) || (ins instanceof ActionSetMember) || (ins instanceof ActionDefineLocal)) { - if (stack.size() < 2) { - break; - } - name = stack.get(stack.size() - 2); - } - - if ((ins instanceof ActionSetVariable) || (ins instanceof ActionDefineLocal)) { - usageType = "variable"; - } - - if (ins instanceof ActionSetMember) { - usageType = "member"; - } - - if (name instanceof DirectValueActionItem) { - variables.add(new MyEntry<>((DirectValueActionItem) name, constantPool)); - usageTypes.put((DirectValueActionItem) name, usageType); - } - - // for..in return - if (((ins instanceof ActionEquals) || (ins instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { - stack.push(new DirectValueActionItem(null, null, 0, Null.INSTANCE, new ArrayList<>())); - } - - if (ins instanceof ActionConstantPool) { - constantPool = new ConstantPool(((ActionConstantPool) ins).constantPool); - } - int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; - - int requiredStackSize = ins.getStackPopCount(localData, stack); - if (stack.size() < requiredStackSize) { - // probably obfucated code, never executed branch - break; - } - - ins.translate(localData, stack, output, staticOperation, path); - if (ins.isExit()) { - break; - } - - if (ins instanceof ActionPush) { - if (!stack.isEmpty()) { - GraphTargetItem top = stack.peek(); - if (top instanceof DirectValueActionItem) { - DirectValueActionItem dvt = (DirectValueActionItem) top; - if ((dvt.value instanceof String) || (dvt.value instanceof ConstantIndex)) { - if (constantPool == null) { - constantPool = new ConstantPool(dvt.constants); - } - strings.put(dvt, constantPool); - } - } - } - } - - if (ins.isBranch() || ins.isJump()) { - if (ins instanceof ActionIf) { - if (stack.isEmpty()) { - break; - } - stack.pop(); - } - visited.add(ip); - List branches = ins.getBranches(code); - for (int b : branches) { - TranslateStack brStack = (TranslateStack) stack.clone(); - if (b >= 0) { - getVariables(constantPool, localData, brStack, output, code, b, variables, functions, strings, visited, usageTypes, path); - } else if (debugMode) { - System.out.println("Negative branch:" + b); - } - } - // } - break; - } - ip++; - } - } - - private static void getVariables(List> variables, List functions, HashMap strings, HashMap usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException { - ActionLocalData localData = new ActionLocalData(); - getVariables(null, localData, new TranslateStack(path), new ArrayList<>(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList<>(), usageTypes, path); - } - - private List> getVariables(List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes, ASMSource src, String path) throws InterruptedException { - List> ret = new ArrayList<>(); - ActionList actions = src.getActions(); - actionsMap.put(src, actions); - getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(actions, version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path); - return ret; - } - - private void getVariables(Iterable tags, String path, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes) throws InterruptedException { - List processed = new ArrayList<>(); - for (Tag t : tags) { - String subPath = path + "/" + t.toString(); - if (t instanceof ASMSource) { - addVariable((ASMSource) t, subPath, processed, variables, actionsMap, functions, strings, usageTypes); - } - if (t instanceof ASMSourceContainer) { - List processed2 = new ArrayList<>(); - for (ASMSource asm : ((ASMSourceContainer) t).getSubItems()) { - addVariable(asm, subPath + "/" + asm.toString(), processed2, variables, actionsMap, functions, strings, usageTypes); - } - } - if (t instanceof DefineSpriteTag) { - getVariables(((DefineSpriteTag) t).getTags(), path + "/" + t.toString(), variables, actionsMap, functions, strings, usageTypes); - } - } - } - - private void addVariable(ASMSource asm, String path, List processed, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes) throws InterruptedException { - int pos = 1; - String infPath2 = path; - while (processed.contains(infPath2)) { - pos++; - infPath2 = path + "[" + pos + "]"; - } - processed.add(infPath2); - informListeners("getVariables", infPath2); - getVariables(variables, actionsMap, functions, strings, usageTypes, asm, path); - } - - public boolean as3StringConstantExists(String str) { - for (ABCContainerTag abcTag : getAbcList()) { - ABC abc = abcTag.getABC(); - for (int i = 1; i < abc.constants.getStringCount(); i++) { - if (abc.constants.getString(i).equals(str)) { - return true; - } - } - } - - return false; - } - - public void fixAS3Code() { - for (ABCContainerTag abcTag : getAbcList()) { - ABC abc = abcTag.getABC(); - for (MethodBody body : abc.bodies) { - AVM2Code code = body.getCode(); - body.setCodeBytes(code.getBytes()); - } - - ((Tag) abcTag).setModified(true); - } - } - - public int deobfuscateAS3Identifiers(RenameType renameType) { - for (Tag tag : getTags()) { - if (tag instanceof ABCContainerTag) { - ((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, true); - tag.setModified(true); - } - } - for (Tag tag : getTags()) { - if (tag instanceof ABCContainerTag) { - ((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, false); - tag.setModified(true); - } - } - for (Tag tag : getTags()) { - if (tag instanceof SymbolClassTag) { - SymbolClassTag sc = (SymbolClassTag) tag; - for (int i = 0; i < sc.names.size(); i++) { - String newname = deobfuscation.deobfuscateNameWithPackage(true, sc.names.get(i), deobfuscated, renameType, deobfuscated); - if (newname != null) { - sc.names.set(i, newname); - } - } - sc.setModified(true); - } - } - deobfuscation.deobfuscateInstanceNames(true, deobfuscated, renameType, getTags(), new HashMap<>()); - return deobfuscated.size(); - } - - public int deobfuscateIdentifiers(RenameType renameType) throws InterruptedException { - FileAttributesTag fileAttributes = getFileAttributes(); - if (fileAttributes == null) { - int cnt = 0; - cnt += deobfuscateAS2Identifiers(renameType); - cnt += deobfuscateAS3Identifiers(renameType); - return cnt; - } else if (fileAttributes.actionScript3) { - return deobfuscateAS3Identifiers(renameType); - } else { - return deobfuscateAS2Identifiers(renameType); - } - } - - public void renameAS2Identifier(String identifier, String newname) throws InterruptedException { - Map selected = new HashMap<>(); - selected.put(DottedChain.parse(identifier), DottedChain.parse(newname)); - renameAS2Identifiers(null, selected); - } - - private int deobfuscateAS2Identifiers(RenameType renameType) throws InterruptedException { - return renameAS2Identifiers(renameType, null); - } - - private int renameAS2Identifiers(RenameType renameType, Map selected) throws InterruptedException { - HashMap actionsMap = new HashMap<>(); - List allFunctions = new ArrayList<>(); - List> allVariableNames = new ArrayList<>(); - HashMap allStrings = new HashMap<>(); - HashMap usageTypes = new HashMap<>(); - - int ret = 0; - getVariables(getTags(), "", allVariableNames, actionsMap, allFunctions, allStrings, usageTypes); - informListeners("rename", ""); - int fc = 0; - for (MyEntry it : allVariableNames) { - String name = it.getKey().toStringNoH(it.getValue()); - deobfuscation.allVariableNamesStr.add(name); - } - - informListeners("rename", "classes"); - int classCount = 0; - for (Tag t : getTags()) { - if (t instanceof DoInitActionTag) { - classCount++; - } - } - int cnt = 0; - for (Tag t : getTags()) { - if (t instanceof DoInitActionTag) { - cnt++; - informListeners("rename", "class " + cnt + "/" + classCount); - DoInitActionTag dia = (DoInitActionTag) t; - String exportName = getExportName(dia.spriteId); - exportName = exportName != null ? exportName : "_unk_"; - final String pkgPrefix = "__Packages."; - String[] classNameParts = null; - if (exportName.startsWith(pkgPrefix)) { - String className = exportName.substring(pkgPrefix.length()); - if (className.contains(".")) { - classNameParts = className.split("\\."); - } else { - classNameParts = new String[]{className}; - } - } - int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; - List dec; - try { - dec = Action.actionsToTree(dia.getActions(), version, staticOperation, ""/*FIXME*/); - } catch (EmptyStackException ex) { - continue; - } - GraphTargetItem name = null; - for (GraphTargetItem it : dec) { - if (it instanceof ClassActionItem) { - ClassActionItem cti = (ClassActionItem) it; - List methods = new ArrayList<>(); - methods.addAll(cti.functions); - methods.addAll(cti.staticFunctions); - - for (GraphTargetItem gti : methods) { - if (gti instanceof FunctionActionItem) { - FunctionActionItem fun = (FunctionActionItem) gti; - if (fun.calculatedFunctionName instanceof DirectValueActionItem) { - DirectValueActionItem dvf = (DirectValueActionItem) fun.calculatedFunctionName; - String fname = dvf.toStringNoH(null); - String changed = deobfuscation.deobfuscateName(false, fname, false, "method", deobfuscated, renameType, selected); - if (changed != null) { - deobfuscated.put(DottedChain.parse(fname), DottedChain.parse(changed)); - } - } - } - } - - List vars = new ArrayList<>(); - for (MyEntry item : cti.vars) { - vars.add(item.getKey()); - } - for (MyEntry item : cti.staticVars) { - vars.add(item.getKey()); - } - for (GraphTargetItem gti : vars) { - if (gti instanceof DirectValueActionItem) { - DirectValueActionItem dvf = (DirectValueActionItem) gti; - String vname = dvf.toStringNoH(null); - String changed = deobfuscation.deobfuscateName(false, vname, false, "attribute", deobfuscated, renameType, selected); - if (changed != null) { - deobfuscated.put(DottedChain.parse(vname), DottedChain.parse(changed)); - } - } - } - - name = cti.className; - break; - } - if (it instanceof InterfaceActionItem) { - InterfaceActionItem ift = (InterfaceActionItem) it; - name = ift.name; - } - } - - if (name != null) { - int pos = 0; - while (name instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) name; - GraphTargetItem memberName = mem.memberName; - if (memberName instanceof DirectValueActionItem) { - DirectValueActionItem dvt = (DirectValueActionItem) memberName; - String nameStr = dvt.toStringNoH(null); - if (classNameParts != null) { - if (classNameParts.length - 1 - pos < 0) { - break; - } - } - String changedNameStr = nameStr; - if (classNameParts != null) { - changedNameStr = classNameParts[classNameParts.length - 1 - pos]; - } - String changedNameStr2 = deobfuscation.deobfuscateName(false, changedNameStr, pos == 0, pos == 0 ? "class" : "package", deobfuscated, renameType, selected); - if (changedNameStr2 != null) { - changedNameStr = changedNameStr2; - } - ret++; - deobfuscated.put(DottedChain.parse(nameStr), DottedChain.parse(changedNameStr)); - pos++; - } - name = mem.object; - } - if (name instanceof GetVariableActionItem) { - GetVariableActionItem var = (GetVariableActionItem) name; - if (var.name instanceof DirectValueActionItem) { - DirectValueActionItem dvt = (DirectValueActionItem) var.name; - String nameStr = dvt.toStringNoH(null); - if (classNameParts != null) { - if (classNameParts.length - 1 - pos < 0) { - break; - } - } - String changedNameStr = nameStr; - if (classNameParts != null) { - changedNameStr = classNameParts[classNameParts.length - 1 - pos]; - } - String changedNameStr2 = deobfuscation.deobfuscateName(false, changedNameStr, pos == 0, pos == 0 ? "class" : "package", deobfuscated, renameType, selected); - if (changedNameStr2 != null) { - changedNameStr = changedNameStr2; - } - ret++; - deobfuscated.put(DottedChain.parse(nameStr), DottedChain.parse(changedNameStr)); - pos++; - } - } - } - t.setModified(true); - } - } - - for (GraphSourceItem fun : allFunctions) { - fc++; - informListeners("rename", "function " + fc + "/" + allFunctions.size()); - if (fun instanceof ActionDefineFunction) { - ActionDefineFunction f = (ActionDefineFunction) fun; - if (f.functionName.isEmpty()) { // anonymous function, leave as is - continue; - } - String changed = deobfuscation.deobfuscateName(false, f.functionName, false, "function", deobfuscated, renameType, selected); - if (changed != null) { - f.replacedFunctionName = changed; - ret++; - } - } - if (fun instanceof ActionDefineFunction2) { - ActionDefineFunction2 f = (ActionDefineFunction2) fun; - if (f.functionName.isEmpty()) { // anonymous function, leave as is - continue; - } - String changed = deobfuscation.deobfuscateName(false, f.functionName, false, "function", deobfuscated, renameType, selected); - if (changed != null) { - f.replacedFunctionName = changed; - ret++; - } - } - } - - HashSet stringsNoVarH = new HashSet<>(); - List allVariableNamesDv = new ArrayList<>(); - for (MyEntry it : allVariableNames) { - allVariableNamesDv.add(it.getKey()); - } - for (DirectValueActionItem ti : allStrings.keySet()) { - if (!allVariableNamesDv.contains(ti)) { - stringsNoVarH.add(System.identityHashCode(allStrings.get(ti)) + "_" + ti.toStringNoH(allStrings.get(ti))); - } - } - - int vc = 0; - for (MyEntry it : allVariableNames) { - vc++; - String name = it.getKey().toStringNoH(it.getValue()); - String changed = deobfuscation.deobfuscateName(false, name, false, usageTypes.get(it.getKey()), deobfuscated, renameType, selected); - if (changed != null) { - boolean addNew = false; - String h = System.identityHashCode(it.getKey()) + "_" + name; - if (stringsNoVarH.contains(h)) { - addNew = true; - } - ActionPush pu = (ActionPush) it.getKey().getSrc(); - if (pu.replacement == null) { - pu.replacement = new ArrayList<>(); - pu.replacement.addAll(pu.values); - } - if (pu.replacement.get(it.getKey().pos) instanceof ConstantIndex) { - ConstantIndex ci = (ConstantIndex) pu.replacement.get(it.getKey().pos); - ConstantPool pool = it.getValue(); - if (pool == null) { - continue; - } - if (pool.constants == null) { - continue; - } - if (addNew) { - pool.constants.add(changed); - ci.index = pool.constants.size() - 1; - } else { - pool.constants.set(ci.index, changed); - } - } else { - pu.replacement.set(it.getKey().pos, changed); - } - ret++; - } - } - - for (ASMSource src : actionsMap.keySet()) { - actionsMap.get(src).removeNops(); - src.setActions(actionsMap.get(src)); - src.setModified(); - } - - deobfuscation.deobfuscateInstanceNames(false, deobfuscated, renameType, getTags(), selected); - return ret; - } - - public IdentifiersDeobfuscation getDeobfuscation() { - return deobfuscation; - } - - public void exportFla(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion version) throws IOException, InterruptedException { - XFLExportSettings settings = new XFLExportSettings(); - settings.compressed = true; - exportXfl(handler, outfile, swfName, generator, generatorVerName, generatorVersion, parallel, version, settings); - } - - public void exportXfl(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion version) throws IOException, InterruptedException { - XFLExportSettings settings = new XFLExportSettings(); - settings.compressed = false; - exportXfl(handler, outfile, swfName, generator, generatorVerName, generatorVersion, parallel, version, settings); - } - - public void exportXfl(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion version, XFLExportSettings settings) throws IOException, InterruptedException { - new XFLConverter().convertSWF(handler, this, swfName, outfile, settings, generator, generatorVerName, generatorVersion, parallel, version); - clearAllCache(); - } - - public static AffineTransform matrixToTransform(MATRIX mat) { - return new AffineTransform(mat.getScaleXFloat(), mat.getRotateSkew0Float(), - mat.getRotateSkew1Float(), mat.getScaleYFloat(), - mat.translateX, mat.translateY); - } - - public SerializableImage getFromCache(String key) { - if (frameCache.contains(key)) { - return frameCache.get(key); - } - return null; - } - - public byte[] getFromCache(SoundTag soundTag) { - if (soundCache.contains(soundTag)) { - return soundCache.get(soundTag); - } - return null; - } - - public void putToCache(String key, SerializableImage img) { - if (Configuration.useFrameCache.get()) { - frameCache.put(key, img); - } - } - - public void putToCache(SoundTag soundTag, byte[] data) { - soundCache.put(soundTag, data); - } - - public void clearImageCache() { - frameCache.clear(); - rectCache.clear(); - for (Tag tag : getTags()) { - if (tag instanceof ImageTag) { - ((ImageTag) tag).clearCache(); - } - else if (tag instanceof DefineCompactedFont) { - ((DefineCompactedFont) tag).rebuildShapeCache(); - } - } - } - - public void clearScriptCache() { - as2PcodeCache.clear(); - as2Cache.clear(); - as3Cache.clear(); - IdentifiersDeobfuscation.clearCache(); - } - - public void clearReadOnlyListCache() { - readOnlyTags = null; - for (Tag tag : tags) { - if (tag instanceof DefineSpriteTag) { - ((DefineSpriteTag) tag).clearReadOnlyListCache(); - } - } - } - - public static void clearAllStaticCache() { - Cache.clearAll(); - Helper.clearShapeCache(); - System.gc(); - } - - public void clearAllCache() { - characters = null; - characterIdTags = null; - abcList = null; - timeline = null; - clearReadOnlyListCache(); - clearImageCache(); - clearScriptCache(); - clearAllStaticCache(); - } - - public static void uncache(ASMSource src) { - if (src != null) { - SWF swf = src.getSwf(); - swf.as2Cache.remove(src); - swf.as2PcodeCache.remove(src); - } - } - - public static void uncache(ScriptPack pack) { - if (pack != null) { - pack.getSwf().as3Cache.remove(pack); - } - } - - public static boolean isCached(ASMSource src) { - return src.getSwf().as2Cache.contains(src); - } - - public static boolean isCached(ScriptPack pack) { - return pack.getSwf().as3Cache.contains(pack); - } - - public static ActionList getCachedActionList(ASMSource src, final List listeners) throws InterruptedException { - synchronized (src) { - SWF swf = src.getSwf(); - int deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0; - if (swf != null && swf.as2PcodeCache.contains(src)) { - ActionList result = swf.as2PcodeCache.get(src); - if (result.deobfuscationMode == deobfuscationMode) { - return result; - } - } - - try { - ByteArrayRange actionBytes = src.getActionBytes(); - int prevLength = actionBytes.getPos(); - SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray()); - if (prevLength != 0) { - rri.seek(prevLength); - } - - int version = swf == null ? SWF.DEFAULT_VERSION : swf.version; - ActionList list = ActionListReader.readActionListTimeout(listeners, rri, version, prevLength, prevLength + actionBytes.getLength(), src.toString()/*FIXME?*/, deobfuscationMode); - list.fileData = actionBytes.getArray(); - list.deobfuscationMode = deobfuscationMode; - if (swf != null) { - swf.as2PcodeCache.put(src, list); - } - - return list; - } catch (InterruptedException ex) { - throw ex; - } catch (Exception ex) { - logger.log(Level.SEVERE, null, ex); - return new ActionList(); - } - } - } - - public static CachedScript getFromCache(ASMSource src) { - SWF swf = src.getSwf(); - if (swf.as2Cache.contains(src)) { - return swf.as2Cache.get(src); - } - - return null; - } - - public static CachedScript getCached(ASMSource src, ActionList actions) throws InterruptedException { - SWF swf = src.getSwf(); - if (swf.as2Cache.contains(src)) { - return swf.as2Cache.get(src); - } - - if (actions == null) { - actions = src.getActions(); - } - - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); - writer.startFunction("!script"); - Action.actionsToSource(src, actions, src.toString()/*FIXME?*/, writer); - writer.endFunction(); - List hilights = writer.instructionHilights; - List methodHilights = writer.methodHilights; - List classHilights = writer.classHilights; - List specialHilights = writer.specialHilights; - - String srcNoHex = writer.toString(); - CachedScript res = new CachedScript(srcNoHex, hilights, methodHilights, classHilights, specialHilights); - swf.as2Cache.put(src, res); - return res; - } - - public static CachedDecompilation getCached(ScriptPack pack) throws InterruptedException { - SWF swf = pack.getSwf(); - if (swf.as3Cache.contains(pack)) { - return swf.as3Cache.get(pack); - } - - int scriptIndex = pack.scriptIndex; - ScriptInfo script = null; - if (scriptIndex > -1) { - script = pack.abc.script_info.get(scriptIndex); - } - boolean parallel = Configuration.parallelSpeedUp.get(); - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); - pack.toSource(writer, script == null ? null : script.traits.traits, new ConvertData(), ScriptExportMode.AS, parallel); - HighlightedText hilightedCode = new HighlightedText(writer); - CachedDecompilation res = new CachedDecompilation(hilightedCode); - swf.as3Cache.put(pack, res); - - return res; - } - - public Cache getRectCache() { - return rectCache; - } - - public Cache getShapeExportDataCache() { - return shapeExportDataCache; - } - - public static RECT fixRect(RECT rect) { - RECT ret = new RECT(); - ret.Xmin = rect.Xmin; - ret.Xmax = rect.Xmax; - ret.Ymin = rect.Ymin; - ret.Ymax = rect.Ymax; - - if (ret.Xmax <= 0) { - ret.Xmax = ret.getWidth(); - ret.Xmin = 0; - } - if (ret.Ymax <= 0) { - ret.Ymax = ret.getHeight(); - ret.Ymin = 0; - } - if (ret.Xmin < 0) { - ret.Xmax += (-ret.Xmin); - ret.Xmin = 0; - } - if (ret.Ymin < 0) { - ret.Ymax += (-ret.Ymin); - ret.Ymin = 0; - } - - if (ret.getWidth() < 1 || ret.getHeight() < 1) { - ret.Xmin = 0; - ret.Ymin = 0; - ret.Xmax = 20; - ret.Ymax = 20; - } - return ret; - } - - public static SerializableImage frameToImageGet(Timeline timeline, int frame, int time, Point cursorPosition, int mouseButton, RECT displayRect, Matrix transformation, ColorTransform colorTransform, Color backGroundColor, double zoom) { - if (timeline.getFrameCount() == 0) { - return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB_PRE); - } - - RECT rect = displayRect; - SerializableImage image = new SerializableImage((int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1, - (int) (rect.getHeight() * zoom / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB_PRE); - if (backGroundColor == null) { - image.fillTransparent(); - } else { - Graphics2D g = (Graphics2D) image.getBufferedImage().getGraphics(); - g.setComposite(AlphaComposite.Src); - g.setColor(backGroundColor); - g.fill(new Rectangle(image.getWidth(), image.getHeight())); - } - - Matrix m = transformation.clone(); - m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); - m.scale(zoom); - RenderContext renderContext = new RenderContext(); - renderContext.cursorPosition = cursorPosition; - renderContext.mouseButton = mouseButton; - timeline.toImage(frame, time, renderContext, image, false, m, transformation, m, colorTransform); - - return image; - } - - private void removeTagWithDependenciesFromTimeline(Tag toRemove, Timeline timeline) { - Map stage = new HashMap<>(); - Set dependingChars = new HashSet<>(); - Timelined timelined = timeline.timelined; - ReadOnlyTagList tags = timelined.getTags(); - if (toRemove instanceof CharacterTag) { - int characterId = ((CharacterTag) toRemove).getCharacterId(); - - if (characterId != 0) { - dependingChars.add(characterId); - for (int i = 0; i < tags.size(); i++) { - Tag t = tags.get(i); - if (t instanceof CharacterIdTag) { - CharacterIdTag c = (CharacterIdTag) t; - Set needed = new HashSet<>(); - t.getNeededCharacters(needed); - if (needed.contains(characterId)) { - dependingChars.add(c.getCharacterId()); - } - } - } - } - } - - for (int i = 0; i < tags.size(); i++) { - Tag t = tags.get(i); - if (t instanceof RemoveTag) { - RemoveTag rt = (RemoveTag) t; - int depth = rt.getDepth(); - if (stage.containsKey(depth)) { - int currentCharId = stage.get(depth); - stage.remove(depth); - if (dependingChars.contains(currentCharId)) { - timelined.removeTag(i); - i--; - continue; - } - } - } - if (t instanceof PlaceObjectTypeTag) { - PlaceObjectTypeTag po = (PlaceObjectTypeTag) t; - int placeCharId = po.getCharacterId(); - int depth = po.getDepth(); - if (placeCharId != 0) { - stage.put(depth, placeCharId); - if (dependingChars.contains(placeCharId)) { - timelined.removeTag(i); - i--; - continue; - } - } - } - if (t instanceof CharacterIdTag) { - CharacterIdTag c = (CharacterIdTag) t; - if (dependingChars.contains(c.getCharacterId())) { - timelined.removeTag(i); - i--; - continue; - } - } - Set needed = new HashSet<>(); - t.getNeededCharacters(needed); - for (int dep : dependingChars) { - if (needed.contains(dep)) { - timelined.removeTag(i); - i--; - //continue; - } - } - if (t == toRemove) { - timelined.removeTag(i); - i--; - continue; - } - if (t instanceof Timelined) { - removeTagWithDependenciesFromTimeline(toRemove, ((Timelined) t).getTimeline()); - } - } - } - - private boolean removeTagFromTimeline(Tag toRemove, Timeline timeline) { - boolean modified = false; - int characterId = -1; - if (toRemove instanceof CharacterTag) { - characterId = ((CharacterTag) toRemove).getCharacterId(); - modified = timeline.removeCharacter(characterId); - } - Timelined timelined = timeline.timelined; - ReadOnlyTagList tags = timelined.getTags(); - for (int i = 0; i < tags.size(); i++) { - Tag t = tags.get(i); - if (t == toRemove) { - timelined.removeTag(t); - i--; - continue; - } - - if (toRemove instanceof CharacterTag) { - if (t.removeCharacter(characterId)) { - modified = true; - i = -1; - continue; - } - } - - if (t instanceof DefineSpriteTag) { - DefineSpriteTag spr = (DefineSpriteTag) t; - boolean sprModified = removeTagFromTimeline(toRemove, spr.getTimeline()); - if (sprModified) { - spr.setModified(true); - } - modified |= sprModified; - } - } - return modified; - } - - public void removeTags(Collection tags, boolean removeDependencies) { - Set timelineds = new HashSet<>(); - for (Tag tag : tags) { - Timelined timelined = tag.getTimelined(); - timelineds.add(timelined); - removeTagInternal(timelined, tag, removeDependencies); - } - - for (Timelined timelined : timelineds) { - resetTimelines(timelined); - } - - updateCharacters(); - clearImageCache(); - } - - @Override - public void removeTag(int index) { - setModified(true); - tags.remove(index); - updateCharacters(); - } - - @Override - public void removeTag(Tag tag) { - setModified(true); - tags.remove(tag); - updateCharacters(); - } - - public void removeTag(Tag tag, boolean removeDependencies) { - Timelined timelined = tag.getTimelined(); - removeTagInternal(timelined, tag, removeDependencies); - resetTimelines(timelined); - updateCharacters(); - clearImageCache(); - } - - private void removeTagInternal(Timelined timelined, Tag tag, boolean removeDependencies) { - if (tag instanceof ShowFrameTag || ShowFrameTag.isNestedTagType(tag.getId())) { - timelined.removeTag(tag); - timelined.setModified(true); - timelined.resetTimeline(); - } else // timeline should be always the swf here - if (removeDependencies) { - removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline()); - timelined.setModified(true); - } else { - boolean modified = removeTagFromTimeline(tag, timelined.getTimeline()); - if (modified) { - timelined.setModified(true); - } - } - } - - @Override - public ReadOnlyTagList getTags() { - if (readOnlyTags == null) { - readOnlyTags = new ReadOnlyTagList(tags); - } - - return readOnlyTags; - } - - public ReadOnlyTagList getLocalTags() { - List localTags = new ArrayList<>(); - for (Tag t : tags) { - if (!t.isImported()) { - localTags.add(t); - } - } - return new ReadOnlyTagList(localTags); - } - - /** - * Adds a tag to the SWF - * - * @param tag - */ - @Override - public void addTag(Tag tag) { - setModified(true); - tags.add(tag); - updateCharacters(); - } - - /** - * Adds a tag to the SWF - * - * @param index - * @param tag - */ - @Override - public void addTag(int index, Tag tag) { - setModified(true); - tags.add(index, tag); - updateCharacters(); - } - - /** - * Replaces a tag in the SWF - * - * @param oldTag - * @param newTag - */ - public void replaceTag(Tag oldTag, Tag newTag) { - setModified(true); - int index = tags.indexOf(oldTag); - if (index != -1) { - tags.set(index, newTag); - updateCharacters(); - } - } - - /** - * Adds a tag to the SWF If targetTreeItem is: - Frame: adds the tag to the - * Frame. Frame can be a frame of the main timeline or a DefineSprite frame - * - DefineSprite: adds the tag to the end of the DefineSprite's tag list - - * Any other tag in the SWF: adds the new tag exactly before the specified - * tag - Other: adds the tag to the end of the SWF's tag list - * - * @param tag - * @param targetTreeItem - */ - public void addTag(Tag tag, TreeItem targetTreeItem) { - SWF swf = tag.getSwf(); - Frame frame = targetTreeItem instanceof Frame ? (Frame) targetTreeItem : null; - Timelined timelined; - if (frame != null) { - timelined = frame.timeline.timelined; - } else { - timelined = swf.getTimelined(targetTreeItem); - } - - tag.setTimelined(timelined); - - ReadOnlyTagList tags = timelined.getTags(); - - int index; - if (frame != null) { - if (frame.showFrameTag != null) { - index = tags.indexOf(frame.showFrameTag); - } else { - index = -1; - } - } else if (timelined instanceof DefineSpriteTag) { - index = -1; - } else if (targetTreeItem instanceof Tag) { - if (tag instanceof CharacterIdTag && !(tag instanceof CharacterTag) && targetTreeItem instanceof CharacterTag) { - ((CharacterIdTag) tag).setCharacterId(((CharacterTag) targetTreeItem).getCharacterId()); - } - - index = tags.indexOf((Tag) targetTreeItem); // todo: honfika: why not index + 1? - } else { - index = -1; - if (tag instanceof CharacterTag) { - // add before the last ShowFrame tag - for (int i = tags.size() - 1; i >= 0; i--) { - if (tags.get(i) instanceof ShowFrameTag) { - index = i; - break; - } - } - } - } - - if (index > -1) { - timelined.addTag(index, tag); - } else { - timelined.addTag(tag); - } - - timelined.resetTimeline(); - - if (timelined instanceof DefineSpriteTag) { - DefineSpriteTag sprite = (DefineSpriteTag) timelined; - sprite.frameCount = timelined.getTimeline().getFrameCount(); - } - } - - public Timelined getTimelined(TreeItem treeItem) { - if (treeItem instanceof Frame) { - return ((Frame) treeItem).timeline.timelined; - } - - if (treeItem instanceof DefineSpriteTag) { - return (DefineSpriteTag) treeItem; - } - - return treeItem.getSwf(); - } - - public void packCharacterIds() { - int maxId = getNextCharacterId(); - int id = 1; - for (int i = 1; i < maxId; i++) { - CharacterTag charactertag = getCharacter(i); - if (charactertag != null) { - if (i != id) { - replaceCharacter(i, id); - } - id++; - } else { - // make sure that the id is not referenced in the tags - replaceCharacter(i, 0); - } - } - } - - public void sortCharacterIds() { - int maxId = Math.max(tags.size(), getNextCharacterId()); - int id = maxId; - // first set the chatacter ids to surely not used ids - for (Tag tag : getTags()) { - if (tag instanceof CharacterTag) { - CharacterTag characterTag = (CharacterTag) tag; - replaceCharacter(characterTag.getCharacterId(), id++); - } - } - // then set them to 1,2,3... - id = 1; - for (Tag tag : getTags()) { - if (tag instanceof CharacterTag) { - CharacterTag characterTag = (CharacterTag) tag; - replaceCharacter(characterTag.getCharacterId(), id++); - } - } - } - - public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { - boolean modified = false; - for (Tag tag : getTags()) { - boolean modified2 = false; - if (tag instanceof CharacterIdTag) { - CharacterIdTag characterIdTag = (CharacterIdTag) tag; - if (characterIdTag.getCharacterId() == oldCharacterId) { - characterIdTag.setCharacterId(newCharacterId); - modified2 = true; - } - } - modified2 |= tag.replaceCharacter(oldCharacterId, newCharacterId); - if (modified2) { - tag.setModified(true); - } - modified |= modified2; - } - return modified; - } - - public void replaceCharacterTags(CharacterTag characterTag, int newCharacterId) { - int characterId = characterTag.getCharacterId(); - CharacterTag newCharacter = getCharacter(newCharacterId); - newCharacter.setCharacterId(characterId); - characterTag.setCharacterId(newCharacterId); - newCharacter.setModified(true); - characterTag.setModified(true); - - assignExportNamesToSymbols(); - assignClassesToSymbols(); - clearImageCache(); - updateCharacters(); - } - - @Override - public String toString() { - return getShortFileName(); - } - - public void deobfuscate(DeobfuscationLevel level) throws InterruptedException { - List atags = getAbcList(); - - for (ABCContainerTag tag : atags) { - if (level == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE) { - tag.getABC().removeDeadCode(); - } else if (level == DeobfuscationLevel.LEVEL_REMOVE_TRAPS) { - tag.getABC().removeTraps(); - } else if (level == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW) { - tag.getABC().removeTraps(); - } - - ((Tag) tag).setModified(true); - } - } - - /** - * Enables debugging. Adds tags to enable debugging and optinally injects - * debugline and debugfile instructions to AS3 code by decompiling it first - * - * @param injectAS3Code Modify AS3 code with debugfile / debugline ? - * @param decompileDir Directory to virtual decompile (will affect - * debugfile) - */ - public void enableDebugging(boolean injectAS3Code, File decompileDir) { - enableDebugging(injectAS3Code, decompileDir, false); - } - - /** - * Enables debugging. Adds tags to enable debugging. - */ - public void enableDebugging() { - enableDebugging(false, null, false); - } - - /** - * Enables debugging. Adds tags to enable debugging and injects debugline - * and debugfile instructions to AS3 code. Optionally enables Telemetry - * - * @param injectAS3Code Modify AS3 code with debugfile / debugline ? - * @param decompileDir Directory to virtual decompile (will affect - * debugfile) - * @param telemetry Enable telemetry info? - */ - public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry) { - enableDebugging(injectAS3Code, decompileDir, telemetry, false); - } - - /** - * Injects debugline and debugfile instructions to AS3 P-code (lines of - * P-code) - */ - public void injectAS3PcodeDebugInfo() { - List packs = getAS3Packs(); - for (ScriptPack s : packs) { - int abcIndex = s.allABCs.indexOf(s.abc); - if (s.isSimple) { - s.injectPCodeDebugInfo(abcIndex); - } - } - } - - /** - * Injects debugline and debugfile instructions to AS3 code - * - * @param decompileDir Directory to set file information paths - */ - public void injectAS3DebugInfo(File decompileDir) { - List packs = getAS3Packs(); - for (ScriptPack s : packs) { - if (s.isSimple) { - s.injectDebugInfo(decompileDir); - } - } - } - - /** - * Enables debugging. Adds tags to enable debugging and injects debugline - * and debugfile instructions to AS3 code. Optionally enables Telemetry - * - * @param injectAS3Code Modify AS3 code with debugfile / debugline ? - * @param decompileDir Directory to virtual decompile (will affect - * debugfile) - * @param telemetry Enable telemetry info? - * @param pcodeLevel inject Pcode lines instead of decompiled lines - */ - public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry, boolean pcodeLevel) { - - if (injectAS3Code) { - if (pcodeLevel) { - injectAS3PcodeDebugInfo(); - } else { - injectAS3DebugInfo(decompileDir); - } - } - - int pos = 0; - - boolean hasEnabled = false; - - for (int i = 0; i < tags.size(); i++) { - Tag t = tags.get(i); - if (t instanceof MetadataTag) { - pos = i + 1; - } - if (t instanceof FileAttributesTag) { - pos = i + 1; - } - if (version >= 6 && (t instanceof EnableDebugger2Tag)) { - hasEnabled = true; - break; - } - if (version == 5 && (t instanceof EnableDebuggerTag)) { - hasEnabled = true; - break; - } - if (version < 5 && (t instanceof ProtectTag)) { - hasEnabled = true; - break; - } - } - - if (!hasEnabled) { - if (version >= 6) { - tags.add(pos, new EnableDebugger2Tag(this)); - } else if (version == 5) { - tags.add(pos, new EnableDebuggerTag(this)); - } else { - tags.add(pos, new ProtectTag(this)); - } - } - - getOrAddDebugId(); - } - - /** - * Finds DebugID tag - * - * @return the tag or null if not found - */ - public DebugIDTag getDebugId() { - for (Tag t : getTags()) { - if (t instanceof DebugIDTag) { - return (DebugIDTag) t; - } - } - return null; - } - - /** - * Finds DebugID tag and generates new one if none exists - * - * @return the tag or null if there is not debugging enabled in the swf file - */ - public DebugIDTag getOrAddDebugId() { - DebugIDTag r = getDebugId(); - if (r == null) { - for (int i = 0; i < tags.size(); i++) { - Tag t = tags.get(i); - if ((t instanceof EnableDebuggerTag) || (t instanceof EnableDebugger2Tag)) { - r = new DebugIDTag(this); - tags.add(i + 1, r); - new Random().nextBytes(r.debugId); - break; - } - } - } - return r; - } - - public boolean generatePCodeSwdFile(File file, Map> breakpoints) throws IOException { - DebugIDTag dit = getDebugId(); - if (dit == null) { - return false; - } - List items = new ArrayList<>(); - Map asms = getASMs(true); - - try { - items.add(new SWD.DebugId(dit.debugId)); - - } catch (Throwable t) { - logger.log(Level.SEVERE, "message", t); - return false; - } - - int moduleId = 0; - List names = new ArrayList<>(asms.keySet()); - Collections.sort(names); - for (String name : names) { - moduleId++; - String sname = "#PCODE " + name; - int bitmap = SWD.bitmapAction; - items.add(new SWD.DebugScript(moduleId, bitmap, sname, "")); - - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); - try { - asms.get(name).getASMSource(ScriptExportMode.PCODE, writer, asms.get(name).getActions()); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - List hls = writer.instructionHilights; - - Map offsetToLine = new TreeMap<>(); - String txt = writer.toString(); - txt = txt.replace("\r", ""); - int line = 1; - for (int i = 0; i < txt.length(); i++) { - Highlighting h = Highlighting.searchPos(hls, i); - if (h != null) { - int of = (int) h.getProperties().fileOffset; - if (of > -1 && !offsetToLine.containsKey(of) && !offsetToLine.containsValue(line)) { - offsetToLine.put(of, line); - } - } - if (txt.charAt(i) == '\n') { - line++; - } - } - - for (int ofs : offsetToLine.keySet()) { - items.add(new SWD.DebugOffset(moduleId, offsetToLine.get(ofs), ofs)); - } - - if (breakpoints.containsKey(sname)) { - Set bplines = breakpoints.get(sname); - for (int bpline : bplines) { - if (offsetToLine.containsValue(bpline)) { - try { - SWD.DebugBreakpoint dbp = new SWD.DebugBreakpoint(moduleId, bpline); - items.add(dbp); - } catch (IllegalArgumentException iex) { - logger.log(Level.WARNING, "Cannot generate breakpoint to SWD: {0}", iex.getMessage()); - } - } - } - } - } - - SWD swd = new SWD(7, items); - try (FileOutputStream fis = new FileOutputStream(file)) { - swd.saveTo(fis); - } - return true; - } - - public boolean generateSwdFile(File file, Map> breakpoints) throws IOException { - DebugIDTag dit = getDebugId(); - if (dit == null) { - return false; - } - List items = new ArrayList<>(); - Map asms = getASMs(true); - - try { - items.add(new SWD.DebugId(dit.debugId)); - - int moduleId = 0; - List names = new ArrayList<>(asms.keySet()); - Collections.sort(names); - for (String name : names) { - List regitems = new ArrayList<>(); - moduleId++; - CachedScript cs; - try { - cs = SWF.getCached(asms.get(name), asms.get(name).getActions()); - } catch (InterruptedException ex) { - return false; - } - String txt = cs.text.replace("\r", ""); - int line = 1; - Map lineToOffset = new HashMap<>(); - Map regNames = new HashMap<>(); - - for (int pos = 0; pos < txt.length(); pos++) { - Highlighting h = Highlighting.searchPos(cs.hilights, pos); - if (h != null) { - - int firstLineOffset = (int) h.getProperties().firstLineOffset; - if (firstLineOffset > -1 && h.getProperties().declaration && h.getProperties().regIndex > -1 && (!regNames.containsKey(h.getProperties().regIndex) || !regNames.get(h.getProperties().regIndex).equals(h.getProperties().localName))) { - regNames.put(h.getProperties().regIndex, h.getProperties().localName); - - List curRegIndexes = new ArrayList<>(regNames.keySet()); - List curRegNames = new ArrayList<>(); - for (int i = 0; i < curRegIndexes.size(); i++) { - curRegNames.add(regNames.get(curRegIndexes.get(i))); - } - regitems.add(new SWD.DebugRegisters((int) h.getProperties().firstLineOffset, curRegIndexes, curRegNames)); - } - - if (firstLineOffset != -1 && !lineToOffset.containsKey(line)) { - lineToOffset.put(line, firstLineOffset); - } - } - if (txt.charAt(pos) == '\n') { - line++; - } - } - - Map offSetToLine = new TreeMap<>(); - for (Map.Entry en : lineToOffset.entrySet()) { - offSetToLine.put(en.getValue(), en.getKey()); - } - - //final String NONAME = "[No instance name assigned]"; - String sname = name; - int bitmap = SWD.bitmapAction; - /* Matcher m; - int bitmap = SWD.bitmapAction; - m = Pattern.compile("^\\\\frame_([0-9]+)\\\\DoAction$").matcher(sname); - if (m.matches()) { - //TODO: scenes?, layers? - sname = "Actions for Scene 1: Frame " + m.group(1) + " of Layer Name Layer 1"; - } else if ((m = Pattern.compile("^\\\\__Packages\\\\(.*)$").matcher(sname)).matches()) { - sname = m.group(1).replace("\\", ".") + ": .\\" + m.group(1) + ".as"; - } else { - continue; //FIXME! - } - m = Pattern.compile("^\\\\DefineSprite_([0-9])+\\\\frame_([0-9]+)\\\\DoAction$").matcher(sname); - if (m.matches()) { - //TODO: layers? - //sname = "Actions for Symbol " + m.group(1) + ": Frame " + m.group(2) + " of Layer Name Layer 1"; - continue; //FIXME! - } - - //TODO: handle onxxx together ? - m = Pattern.compile("^\\\\DefineButton2?_([0-9]+)\\\\on\\(.*$").matcher(sname); - if (m.matches()) { - //bitmap = SWD.bitmapOnAction; - //sname = "Actions for " + NONAME + " (Symbol " + m.group(1) + ")"; - continue; //FIXME! - } - - //TODO: handle onClipEvent together ? - m = Pattern.compile("^\\\\frame_([0-9]+)\\\\PlaceObject[2-3]?_([0-9]+)_[^\\\\]*\\\\onClipEvent\\(.*$").matcher(sname); - if (m.matches()) { - //bitmap = SWD.bitmapOnClipAction; - //sname = "Actions for " + NONAME + " (Symbol " + m.group(2) + ")"; - continue; //FIXME! - }//*/ - - items.add(new SWD.DebugScript(moduleId, bitmap, sname, txt)); - for (int ofs : offSetToLine.keySet()) { - items.add(new SWD.DebugOffset(moduleId, offSetToLine.get(ofs), ofs)); - } - if (breakpoints.containsKey(name)) { - Set bplines = breakpoints.get(name); - for (int bpline : bplines) { - if (lineToOffset.containsKey(bpline)) { - try { - SWD.DebugBreakpoint dbp = new SWD.DebugBreakpoint(moduleId, bpline); - items.add(dbp); - } catch (IllegalArgumentException iex) { - logger.log(Level.WARNING, "Cannot generate breakpoint to SWD: {0}", iex.getMessage()); - } - } - } - } - items.addAll(regitems); - //moduleId++; - } - //items.addAll(swdOffsets); - //items.addAll(swfBps); - - } catch (Throwable t) { - logger.log(Level.SEVERE, "message", t); - return false; - } - SWD swd = new SWD(7, items); - try (FileOutputStream fis = new FileOutputStream(file)) { - swd.saveTo(fis); - } - return true; - } - - public boolean enableTelemetry(String password) { - - EnableTelemetryTag et = getEnableTelemetry(); - - if (et == null) { - FileAttributesTag fat = getFileAttributes(); - if (fat == null) { - return false; - } - int insertTo = tags.indexOf(fat) + 1; - MetadataTag mt = getMetadata(); - if (mt != null) { - insertTo = tags.indexOf(mt) + 1; - } - - et = new EnableTelemetryTag(this); - tags.add(insertTo, et); - } - et.setPassword(password); - //TODO: SWFs with tag 92 (signed) are unsupported - return true; - } - - public String getFlexMainClass(List ignoredClasses, List ignoredNs) { - String documentClass = getDocumentClass(); - - ScriptPack documentPack = null; - for (ScriptPack item : getAS3Packs()) { - if (item.getClassPath().toString().equals(documentClass)) { - documentPack = item; - break; - } - } - - if (documentPack != null) { - if (!documentPack.traitIndices.isEmpty()) { - Trait firstTrait = documentPack.abc.script_info.get(documentPack.scriptIndex).traits.traits.get(documentPack.traitIndices.get(0)); - if (firstTrait instanceof TraitClass) { - int cindex = ((TraitClass) firstTrait).class_info; - Multiname superName = documentPack.abc.constants.getMultiname(documentPack.abc.instance_info.get(cindex).super_index); - String parentClass = superName.getNameWithNamespace(documentPack.abc.constants).toRawString(); - if ("mx.managers.SystemManager".equals(parentClass)) { - for (Trait t : documentPack.abc.instance_info.get(cindex).instance_traits.traits) { - if ((t instanceof TraitMethodGetterSetter) && "info".equals(t.getName(documentPack.abc).getName(documentPack.abc.constants, new ArrayList<>(), true))) { - - int mi = ((TraitMethodGetterSetter) t).method_info; - try { - documentPack.abc.findBody(mi).convert(new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); - List infos = documentPack.abc.findBody(mi).convertedItems; - if (!infos.isEmpty()) { - if (infos.get(0) instanceof IfItem) { - IfItem ift = ((IfItem) infos.get(0)); - if (!ift.onTrue.isEmpty()) { - if (ift.onTrue.get(0) instanceof InitPropertyAVM2Item) { - if (ift.onTrue.get(0).value instanceof NewObjectAVM2Item) { - NewObjectAVM2Item no = (NewObjectAVM2Item) ift.onTrue.get(0).value; - List compiledLocales = new ArrayList<>(); - List compiledResourceBundleNames = new ArrayList<>(); - List mixins = new ArrayList<>(); - String mainClassName = null; - //currentDomain,preloader - /*double width = 0; - double height = 0; - */ - for (NameValuePair nvp : no.pairs) { - if (nvp.name instanceof StringAVM2Item) { - String n = ((StringAVM2Item) nvp.name).getValue(); - switch (n) { - case "compiledLocales": - if (nvp.value instanceof NewArrayAVM2Item) { - NewArrayAVM2Item na = (NewArrayAVM2Item) nvp.value; - for (GraphTargetItem tv : na.values) { - compiledLocales.add("" + tv.getResult()); - } - } - break; - case "compiledResourceBundleNames": - if (nvp.value instanceof NewArrayAVM2Item) { - NewArrayAVM2Item na = (NewArrayAVM2Item) nvp.value; - for (GraphTargetItem tv : na.values) { - compiledResourceBundleNames.add("" + tv.getResult()); - } - } - break; - case "mixins": - if (nvp.value instanceof NewArrayAVM2Item) { - NewArrayAVM2Item na = (NewArrayAVM2Item) nvp.value; - for (GraphTargetItem tv : na.values) { - mixins.add("" + tv.getResult()); - } - } - break; - /*case "width": - width = Double.parseDouble("" + nvp.value.getResult()); - break; - case "height": - height = Double.parseDouble("" + nvp.value.getResult()); - break;*/ - case "mainClassName": - mainClassName = "" + nvp.value.getResult(); - break; - } - } - } - - ignoredClasses.add(documentClass); - for (String loc : compiledLocales) { - ignoredClasses.add(loc + "$" + "controls" + "_properties"); - for (String res : compiledResourceBundleNames) { - ignoredClasses.add(loc + "$" + res + "_properties"); - } - } - ignoredClasses.addAll(mixins); - - //find internal classes used in mixins - for (ScriptPack p : getAS3Packs()) { - for (String m : mixins) { - if (m.equals(p.getClassPath().toRawString())) { - for (int ti : p.traitIndices) { - Trait tr = p.abc.script_info.get(p.scriptIndex).traits.traits.get(ti); - if (tr instanceof TraitClass) { - int ci = ((TraitClass) tr).class_info; - int cinit = p.abc.class_info.get(ci).cinit_index; - p.abc.findBody(cinit).convert(new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); - List cinitBody = p.abc.findBody(cinit).convertedItems; - for (GraphTargetItem cit : cinitBody) { - if (cit instanceof SetPropertyAVM2Item) { - if (cit.value instanceof GetLexAVM2Item) { - GetLexAVM2Item gl = (GetLexAVM2Item) cit.value; - ignoredClasses.add(gl.propertyName.getNameWithNamespace(p.abc.constants).toRawString()); - } - } - } - } - } - } - } - } - ignoredNs.add("mx"); - ignoredNs.add("spark"); - ignoredNs.add("flashx"); - return mainClassName; - } - } - } - } - } - } catch (InterruptedException e) { - //ignore - } - } - } - } - } - } - } - return null; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import SevenZip.Compression.LZMA.Decoder; +import SevenZip.Compression.LZMA.Encoder; +import com.jpexs.debugger.flash.SWD; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.CachedDecompilation; +import com.jpexs.decompiler.flash.abc.ClassPath; +import com.jpexs.decompiler.flash.abc.RenameType; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; +import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair; +import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; +import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; +import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionGraphSource; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.action.ActionLocalData; +import com.jpexs.decompiler.flash.action.CachedScript; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; +import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.dumpview.DumpInfo; +import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter; +import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter; +import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; +import com.jpexs.decompiler.flash.exporters.shape.ShapeExportData; +import com.jpexs.decompiler.flash.helpers.HighlightedText; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.DebugIDTag; +import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; +import com.jpexs.decompiler.flash.tags.DefineSoundTag; +import com.jpexs.decompiler.flash.tags.DefineSpriteTag; +import com.jpexs.decompiler.flash.tags.DoInitActionTag; +import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag; +import com.jpexs.decompiler.flash.tags.EnableDebuggerTag; +import com.jpexs.decompiler.flash.tags.EnableTelemetryTag; +import com.jpexs.decompiler.flash.tags.EndTag; +import com.jpexs.decompiler.flash.tags.ExportAssetsTag; +import com.jpexs.decompiler.flash.tags.FileAttributesTag; +import com.jpexs.decompiler.flash.tags.JPEGTablesTag; +import com.jpexs.decompiler.flash.tags.MetadataTag; +import com.jpexs.decompiler.flash.tags.ProtectTag; +import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; +import com.jpexs.decompiler.flash.tags.ShowFrameTag; +import com.jpexs.decompiler.flash.tags.SymbolClassTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagStub; +import com.jpexs.decompiler.flash.tags.VideoFrameTag; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.ButtonTag; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.tags.base.Exportable; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.tags.base.ImportTag; +import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; +import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; +import com.jpexs.decompiler.flash.tags.base.RemoveTag; +import com.jpexs.decompiler.flash.tags.base.RenderContext; +import com.jpexs.decompiler.flash.tags.base.ShapeTag; +import com.jpexs.decompiler.flash.tags.base.SoundTag; +import com.jpexs.decompiler.flash.tags.base.TextTag; +import com.jpexs.decompiler.flash.tags.enums.ImageFormat; +import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; +import com.jpexs.decompiler.flash.timeline.AS2Package; +import com.jpexs.decompiler.flash.timeline.Frame; +import com.jpexs.decompiler.flash.timeline.FrameScript; +import com.jpexs.decompiler.flash.timeline.TagScript; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.TreeItem; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFField; +import com.jpexs.decompiler.flash.xfl.FLAVersion; +import com.jpexs.decompiler.flash.xfl.XFLConverter; +import com.jpexs.decompiler.flash.xfl.XFLExportSettings; +import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.Cache; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.NulStream; +import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.SerializableImage; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; + +/** + * Class representing SWF file + * + * @author JPEXS + */ +public final class SWF implements SWFContainerItem, Timelined { + + // big object for testing cleanup + //BigObject bigObj = new BigObject(); + /** + * Default version of SWF file format + */ + public static final int DEFAULT_VERSION = 10; + + /** + * Maximum SWF file format version Needs to be fixed when SWF versions + * reaches this value + */ + public static final int MAX_VERSION = 32; + + /** + * Tags inside of file + */ + @SWFField + private List tags = new ArrayList<>(); + + @Internal + public ReadOnlyTagList readOnlyTags; + + public boolean hasEndTag = true; + + /** + * ExportRectangle for the display + */ + public RECT displayRect; + + /** + * Movie frame rate + */ + public float frameRate; + + /** + * Number of frames in movie + */ + public int frameCount; + + /** + * Version of SWF + */ + public int version; + + /** + * Uncompressed size of the file + */ + @Internal + public long fileSize; + + /** + * Used compression mode + */ + public SWFCompression compression = SWFCompression.NONE; + + /** + * Compressed size of the file (LZMA) + */ + @Internal + public long compressedSize; + + /** + * LZMA Properties + */ + public byte[] lzmaProperties; + + @Internal + public byte[] uncompressedData; + + @Internal + public byte[] originalUncompressedData; + + /** + * ScaleForm GFx + */ + public boolean gfx = false; + + @Internal + public SWFList swfList; + + @Internal + private String file; + + @Internal + private String fileTitle; + + @Internal + private volatile Map characters; + + @Internal + private volatile Map> characterIdTags; + + @Internal + private volatile Map> dependentCharacters; + + @Internal + private volatile List abcList; + + @Internal + private volatile JPEGTablesTag jtt; + + @Internal + public Map sourceFontNamesMap = new HashMap<>(); + + public static final double unitDivisor = 20; + + private static final Logger logger = Logger.getLogger(SWF.class.getName()); + + @Internal + private boolean isModified; + + @Internal + private Timeline timeline; + + @Internal + public DumpInfoSwfNode dumpInfo; + + @Internal + public DefineBinaryDataTag binaryData; + + @Internal + private final HashMap deobfuscated = new HashMap<>(); + + @Internal + private final IdentifiersDeobfuscation deobfuscation = new IdentifiersDeobfuscation(); + + @Internal + private final Cache frameCache = Cache.getInstance(false, false, "frame"); + + @Internal + private final Cache rectCache = Cache.getInstance(true, true, "rect"); + + @Internal + private final Cache shapeExportDataCache = Cache.getInstance(true, true, "shapeExportData"); + + @Internal + private final Cache soundCache = Cache.getInstance(false, false, "sound"); + + @Internal + private final Cache as2PcodeCache = Cache.getInstance(true, true, "as2pcode"); + + @Internal + private final Cache as2Cache = Cache.getInstance(true, false, "as2"); + + @Internal + private final Cache as3Cache = Cache.getInstance(true, false, "as3"); + + public static List swfSignatures = Arrays.asList( + "FWS", // Uncompressed Flash + "CWS", // ZLib compressed Flash + "ZWS", // LZMA compressed Flash + "GFX", // Uncompressed ScaleForm GFx + "CFX", // Compressed ScaleForm GFx + "ABC" // Non-standard LZMA compressed Flash + ); + + public void updateCharacters() { + characters = null; + characterIdTags = null; + } + + public void clearTagSwfs() { + resetTimelines(this); + updateCharacters(); + + for (Tag tag : getTags()) { + if (tag instanceof DefineSpriteTag) { + DefineSpriteTag spriteTag = (DefineSpriteTag) tag; + for (Tag tag1 : spriteTag.getTags()) { + tag1.setSwf(null); + } + + for (int i = spriteTag.getTags().size() - 1; i >= 0; i--) { + spriteTag.removeTag(i); + } + } + + if (tag instanceof DefineBinaryDataTag) { + DefineBinaryDataTag binaryTag = (DefineBinaryDataTag) tag; + if (binaryTag.innerSwf != null) { + binaryTag.innerSwf.clearTagSwfs(); + } + } + + tag.setSwf(null); + } + + tags.clear(); + if (abcList != null) { + abcList.clear(); + } + + if (swfList != null) { + swfList.swfs.clear(); + } + + as2PcodeCache.clear(); + as2Cache.clear(); + as3Cache.clear(); + frameCache.clear(); + soundCache.clear(); + + timeline = null; + clearDumpInfo(dumpInfo); + dumpInfo = null; + jtt = null; + binaryData = null; + } + + private void clearDumpInfo(DumpInfo di) { + for (DumpInfo childInfo : di.getChildInfos()) { + clearDumpInfo(childInfo); + } + + di.getChildInfos().clear(); + } + + public Map getCharacters() { + if (characters == null) { + synchronized (this) { + if (characters == null) { + Map chars = new HashMap<>(); + Map> charIdtags = new HashMap<>(); + parseCharacters(getTags(), chars, charIdtags); + characters = Collections.unmodifiableMap(chars); + characterIdTags = Collections.unmodifiableMap(charIdtags); + } + } + } + + return characters; + } + + public List getCharacterIdTags(int characterId) { + if (characterIdTags == null) { + getCharacters(); + } + + return characterIdTags.get(characterId); + } + + public CharacterIdTag getCharacterIdTag(int characterId, int tagId) { + List characterIdTags = getCharacterIdTags(characterId); + if (characterIdTags != null) { + for (CharacterIdTag t : characterIdTags) { + if (((Tag) t).getId() == tagId) { + if (t.getCharacterId() == characterId) { + return t; + } + } + } + } + + return null; + } + + public Map> getDependentCharacters() { + if (dependentCharacters == null) { + synchronized (this) { + if (dependentCharacters == null) { + Map> dep = new HashMap<>(); + for (Tag tag : getTags()) { + if (tag instanceof CharacterTag) { + int characterId = ((CharacterTag) tag).getCharacterId(); + Set needed = new HashSet<>(); + tag.getNeededCharacters(needed); + for (Integer needed1 : needed) { + Set s = dep.get(needed1); + if (s == null) { + s = new HashSet<>(); + dep.put(needed1, s); + } + + s.add(characterId); + } + } + } + + dependentCharacters = dep; + } + } + } + + return dependentCharacters; + } + + public Set getDependentCharacters(int characterId) { + Set visited = new HashSet<>(); + + Set dependents2 = new LinkedHashSet<>(); + Set deps = getDependentCharacters().get(characterId); + if (deps != null) { + dependents2.addAll(deps); + } + + while (visited.size() != dependents2.size()) { + for (int chId : dependents2) { + if (!visited.contains(chId)) { + visited.add(chId); + if (getCharacters().containsKey(chId)) { + deps = getDependentCharacters().get(chId); + if (deps != null) { + dependents2.addAll(deps); + } + + break; + } + } + } + } + + Set dependents = new LinkedHashSet<>(); + for (Integer chId : dependents2) { + if (getCharacters().containsKey(chId)) { + dependents.add(chId); + } + } + + return dependents; + } + + public CharacterTag getCharacter(int characterId) { + return getCharacters().get(characterId); + } + + public String getExportName(int characterId) { + CharacterTag characterTag = getCharacters().get(characterId); + String exportName = characterTag != null ? characterTag.getExportName() : null; + return exportName; + } + + public FontTag getFontByClass(String fontClass) { + if (fontClass == null) { + return null; + } + for (Tag t : getTags()) { + if (t instanceof FontTag) { + if (fontClass.equals(((FontTag) t).getClassName())) { + return (FontTag) t; + } + } + } + return null; + } + + public FontTag getFont(int fontId) { + CharacterTag characterTag = getCharacters().get(fontId); + if (characterTag instanceof FontTag) { + return (FontTag) characterTag; + } + + if (characterTag != null) { + logger.log(Level.SEVERE, "CharacterTag should be a FontTag. characterId: {0}", fontId); + } + + return null; + } + + public ImageTag getImage(int imageId) { + CharacterTag characterTag = getCharacters().get(imageId); + if (characterTag instanceof ImageTag) { + return (ImageTag) characterTag; + } + + if (characterTag != null) { + logger.log(Level.SEVERE, "CharacterTag should be an ImageTag. characterId: {0}", imageId); + } + + return null; + } + + public DefineSoundTag getSound(int soundId) { + CharacterTag characterTag = getCharacters().get(soundId); + if (characterTag instanceof DefineSoundTag) { + return (DefineSoundTag) characterTag; + } + + if (characterTag != null) { + logger.log(Level.SEVERE, "CharacterTag should be a DefineSoundTag. characterId: {0}", soundId); + } + + return null; + } + + public TextTag getText(int textId) { + CharacterTag characterTag = getCharacters().get(textId); + if (characterTag instanceof TextTag) { + return (TextTag) characterTag; + } + + if (characterTag != null) { + logger.log(Level.SEVERE, "CharacterTag should be a TextTag. characterId: {0}", textId); + } + + return null; + } + + public List getAbcList() { + if (abcList == null) { + synchronized (this) { + if (abcList == null) { + ArrayList newAbcList = new ArrayList<>(); + getAbcTags(getTags(), newAbcList); + abcList = newAbcList; + } + } + } + + return abcList; + } + + public boolean isAS3() { + FileAttributesTag fileAttributes = getFileAttributes(); + return (fileAttributes != null && fileAttributes.actionScript3) || (fileAttributes == null && !getAbcList().isEmpty()); + } + + public MetadataTag getMetadata() { + for (Tag t : getTags()) { + if (t instanceof MetadataTag) { + return (MetadataTag) t; + } + } + + return null; + } + + public FileAttributesTag getFileAttributes() { + for (Tag t : getTags()) { + if (t instanceof FileAttributesTag) { + return (FileAttributesTag) t; + } + } + + return null; + } + + public SetBackgroundColorTag getBackgroundColor() { + for (Tag t : getTags()) { + if (t instanceof SetBackgroundColorTag) { + return (SetBackgroundColorTag) t; + } + } + + return null; + } + + public EnableTelemetryTag getEnableTelemetry() { + for (Tag t : getTags()) { + if (t instanceof EnableTelemetryTag) { + return (EnableTelemetryTag) t; + } + } + return null; + } + + public int getNextCharacterId() { + int max = 0; + Set ids = new HashSet<>(getCharacters().keySet()); + for (Tag t : tags) { + if (t instanceof ImportTag) { + ids.addAll(((ImportTag) t).getAssets().keySet()); + } + } + for (int characterId : ids) { + if (characterId > max) { + max = characterId; + } + } + + return max + 1; + } + + public synchronized JPEGTablesTag getJtt() { + if (jtt == null) { + synchronized (this) { + if (jtt == null) { + for (Tag t : getTags()) { + if (t instanceof JPEGTablesTag) { + jtt = (JPEGTablesTag) t; + break; + } + } + } + } + } + + return jtt; + } + + public String getDocumentClass() { + for (Tag t : getTags()) { + if (t instanceof SymbolClassTag) { + SymbolClassTag sc = (SymbolClassTag) t; + for (int i = 0; i < sc.tags.size(); i++) { + if (sc.tags.get(i) == 0) { + return sc.names.get(i); + } + } + } + } + + return null; + } + + public void fixCharactersOrder(boolean checkAll) { + Set addedCharacterIds = new HashSet<>(); + Set movedTags = new HashSet<>(); + for (int i = 0; i < tags.size(); i++) { + Tag tag = tags.get(i); + if (checkAll || tag.isModified()) { + Set needed = new HashSet<>(); + tag.getNeededCharacters(needed); + if (tag instanceof CharacterTag) { + CharacterTag characterTag = (CharacterTag) tag; + needed.remove(characterTag.getCharacterId()); + } + boolean moved = false; + for (Integer id : needed) { + if (!addedCharacterIds.contains(id)) { + CharacterTag neededCharacter = getCharacter(id); + if (neededCharacter == null) { + continue; + } + + if (movedTags.contains(neededCharacter)) { + logger.log(Level.SEVERE, "Fixing characters order failed, recursion detected."); + return; + } + + // move the needed character to the current position + tags.remove(neededCharacter); + tags.add(i, neededCharacter); + movedTags.add(neededCharacter); + moved = true; + } + } + + if (moved) { + i--; + continue; + } + } + if (tag instanceof CharacterTag) { + addedCharacterIds.add(((CharacterTag) tag).getCharacterId()); + } + } + } + + public void resetTimelines(Timelined timelined) { + timelined.resetTimeline(); + if (timelined instanceof SWF) { + for (Tag t : ((SWF) timelined).getTags()) { + if (t instanceof Timelined) { + resetTimelines((Timelined) t); + } + } + } + } + + private void parseCharacters(Iterable list, Map characters, Map> characterIdTags) { + for (Tag t : list) { + if (t instanceof CharacterIdTag) { + int characterId = ((CharacterIdTag) t).getCharacterId(); + if (t instanceof CharacterTag) { + if (characters.containsKey(characterId)) { + logger.log(Level.SEVERE, "SWF already contains characterId={0}", characterId); + } + + if (characterId != 0) { + characters.put(characterId, (CharacterTag) t); + characterIdTags.put(characterId, new ArrayList<>()); + } + } else if (characterIdTags.containsKey(characterId)) { + characterIdTags.get(characterId).add((CharacterIdTag) t); + } + } + + if (t instanceof DefineSpriteTag) { + parseCharacters(((DefineSpriteTag) t).getTags(), characters, characterIdTags); + } + } + } + + /** + * Unresolve recursive sprites + */ + private void checkInvalidSprites() { + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if (t instanceof DefineSpriteTag) { + if (!isSpriteValid((DefineSpriteTag) t, new ArrayList<>())) { + tags.set(i, new TagStub(this, t.getId(), "InvalidSprite", t.getOriginalRange(), null)); + } + } + } + } + + private boolean isSpriteValid(DefineSpriteTag sprite, List path) { + if (path.contains(sprite.spriteId)) { + return false; + } + path.add(sprite.spriteId); + for (Tag t : sprite.getTags()) { + if (t instanceof DefineSpriteTag) { + if (!isSpriteValid((DefineSpriteTag) t, path)) { + return false; + } + } + } + path.remove((Integer) sprite.spriteId); + return true; + } + + @Override + public Timeline getTimeline() { + if (timeline == null) { + timeline = new Timeline(this); + } + return timeline; + } + + @Override + public void resetTimeline() { + if (timeline != null) { + timeline.reset(this); + } + } + + /** + * Gets all tags with specified id + * + * @param tagId Identificator of tag type + * @return List of tags + */ + public List getTagData(int tagId) { + List ret = new ArrayList<>(); + for (Tag tag : getTags()) { + if (tag.getId() == tagId) { + ret.add(tag); + } + } + return ret; + } + + /** + * Saves this SWF into new file + * + * @param os OutputStream to save SWF in + * @throws IOException + */ + public void saveTo(OutputStream os) throws IOException { + byte[] uncompressedData = saveToByteArray(); + compress(new ByteArrayInputStream(uncompressedData), os, compression, lzmaProperties); + } + + public byte[] getHeaderBytes() { + return getHeaderBytes(compression, gfx); + } + + private static byte[] getHeaderBytes(SWFCompression compression, boolean gfx) { + if (compression == SWFCompression.LZMA_ABC) { + return new byte[]{'A', 'B', 'C'}; + } + + byte[] ret = new byte[3]; + + if (compression == SWFCompression.LZMA) { + ret[0] = 'Z'; + } else if (compression == SWFCompression.ZLIB) { + ret[0] = 'C'; + } else if (gfx) { + ret[0] = 'G'; + } else { + ret[0] = 'F'; + } + + if (gfx) { + ret[1] = 'F'; + ret[2] = 'X'; + } else { + ret[1] = 'W'; + ret[2] = 'S'; + } + + return ret; + } + + private byte[] saveToByteArray() throws IOException { + fixCharactersOrder(false); + + byte[] data; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, version)) { + sos.write(getHeaderBytes(SWFCompression.NONE, gfx)); + sos.writeUI8(version); + sos.writeUI32(0); // placeholder for file length + sos.writeRECT(displayRect); + sos.writeFIXED8(frameRate); + sos.writeUI16(frameCount); + + sos.writeTags(getLocalTags()); + if (hasEndTag) { + sos.writeUI16(0); + } + + data = baos.toByteArray(); + } + + // update file size + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, version)) { + sos.writeUI32(data.length); + byte[] lengthData = baos.toByteArray(); + System.arraycopy(lengthData, 0, data, 4, lengthData.length); + } + + return data; + } + + /** + * Compress SWF file + * + * @param is InputStream + * @param os OutputStream to save SWF in + * @param compression + * @param lzmaProperties + * @throws IOException + */ + private static void compress(InputStream is, OutputStream os, SWFCompression compression, byte[] lzmaProperties) throws IOException { + byte[] hdr = new byte[8]; + + is.mark(8); + + // SWFheader: signature, version and fileSize + if (is.read(hdr) != 8) { + throw new SwfOpenException("SWF header is too short"); + } + + boolean uncompressed = hdr[0] == 'F' || hdr[0] == 'G'; // FWS or GFX + if (!uncompressed) { + // fisrt decompress, then compress to the given format + is.reset(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + decompress(is, baos, false); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + compress(bais, os, compression, lzmaProperties); + return; + } + + boolean gfx = hdr[1] == 'F' && hdr[2] == 'X'; + int version = hdr[3]; + long fileSize; + try (SWFInputStream sis = new SWFInputStream(null, Arrays.copyOfRange(hdr, 4, 8), 4, 4)) { + fileSize = sis.readUI32("fileSize"); + } + + SWFOutputStream sos = new SWFOutputStream(os, version); + sos.write(getHeaderBytes(compression, gfx)); + sos.writeUI8(version); + sos.writeUI32(fileSize); + + if (compression == SWFCompression.LZMA || compression == SWFCompression.LZMA_ABC) { + long uncompressedLength = fileSize - 8; + Encoder enc = new Encoder(); + if (lzmaProperties == null) { + // todo: the bytes are from a sample swf + lzmaProperties = new byte[]{93, 0, 0, 32, 0}; + } + + int val = lzmaProperties[0] & 0xFF; + int lc = val % 9; + int remainder = val / 9; + int lp = remainder % 5; + int pb = remainder / 5; + int dictionarySize = 0; + for (int i = 0; i < 4; i++) { + dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8); + } + if (Configuration.lzmaFastBytes.get() > 0) { + enc.SetNumFastBytes(Configuration.lzmaFastBytes.get()); + } + enc.SetDictionarySize(dictionarySize); + enc.SetLcLpPb(lc, lp, pb); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + enc.SetEndMarkerMode(true); + enc.Code(is, baos, -1, -1, null); + byte[] data = baos.toByteArray(); + if (compression == SWFCompression.LZMA) { + byte[] udata = new byte[4]; + udata[0] = (byte) (data.length & 0xFF); + udata[1] = (byte) ((data.length >> 8) & 0xFF); + udata[2] = (byte) ((data.length >> 16) & 0xFF); + udata[3] = (byte) ((data.length >> 24) & 0xFF); + os.write(udata); + } + enc.WriteCoderProperties(os); + if (compression == SWFCompression.LZMA_ABC) { + byte[] udata = new byte[8]; + udata[0] = (byte) (uncompressedLength & 0xFF); + udata[1] = (byte) ((uncompressedLength >> 8) & 0xFF); + udata[2] = (byte) ((uncompressedLength >> 16) & 0xFF); + udata[3] = (byte) ((uncompressedLength >> 24) & 0xFF); + udata[4] = (byte) ((uncompressedLength >> 32) & 0xFF); + udata[5] = (byte) ((uncompressedLength >> 40) & 0xFF); + udata[6] = (byte) ((uncompressedLength >> 48) & 0xFF); + udata[7] = (byte) ((uncompressedLength >> 56) & 0xFF); + os.write(udata); + } + os.write(data); + } else if (compression == SWFCompression.ZLIB) { + DeflaterOutputStream dos = new DeflaterOutputStream(os); + try { + Helper.copyStream(is, dos); + } finally { + dos.finish(); + } + } else { + Helper.copyStream(is, os); + } + } + + @Override + public boolean isModified() { + if (isModified) { + return true; + } + + for (Tag tag : getTags()) { + if (tag.isModified()) { + return true; + } + } + return false; + } + + @Override + public void setModified(boolean value) { + isModified = value; + } + + public void clearModified() { + for (Tag tag : getTags()) { + if (tag.isModified()) { + tag.createOriginalData(); + tag.setModified(false); + } + } + + isModified = false; + + try { + uncompressedData = saveToByteArray(); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Cannot save SWF", ex); + } + } + + /** + * Constructs an empty SWF + */ + public SWF() { + version = SWF.DEFAULT_VERSION; + displayRect = new RECT(0, 1, 0, 1); + } + + /** + * Construct SWF from stream + * + * @param is Stream to read SWF from + * @param parallelRead Use parallel threads? + * @throws IOException + * @throws java.lang.InterruptedException + */ + public SWF(InputStream is, boolean parallelRead) throws IOException, InterruptedException { + this(is, null, null, null, parallelRead, false, true); + } + + /** + * Construct SWF from stream + * + * @param is Stream to read SWF from + * @param parallelRead Use parallel threads? + * @param lazy + * @throws IOException + * @throws java.lang.InterruptedException + */ + public SWF(InputStream is, boolean parallelRead, boolean lazy) throws IOException, InterruptedException { + this(is, null, null, null, parallelRead, false, lazy); + } + + /** + * Construct SWF from stream + * + * @param is Stream to read SWF from + * @param file Path to the file + * @param fileTitle Title of the SWF + * @param parallelRead Use parallel threads? + * @throws IOException + * @throws java.lang.InterruptedException + */ + public SWF(InputStream is, String file, String fileTitle, boolean parallelRead) throws IOException, InterruptedException { + this(is, file, fileTitle, null, parallelRead, false, true); + } + + /** + * Construct SWF from stream + * + * @param is Stream to read SWF from + * @param listener + * @param parallelRead Use parallel threads? + * @throws IOException + * @throws java.lang.InterruptedException + */ + public SWF(InputStream is, ProgressListener listener, boolean parallelRead) throws IOException, InterruptedException { + this(is, null, null, listener, parallelRead, false, true); + } + + /** + * Construct SWF from stream + * + * @param is Stream to read SWF from + * @param file Path to the file + * @param fileTitle Title of the SWF + * @param listener + * @param parallelRead Use parallel threads? + * @throws IOException + * @throws java.lang.InterruptedException + */ + public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead) throws IOException, InterruptedException { + this(is, file, fileTitle, listener, parallelRead, false, true); + } + + /** + * Faster constructor to check SWF only + * + * @param is + * @throws java.io.IOException + */ + public SWF(InputStream is) throws IOException { + decompress(is, new NulStream(), true); + } + + public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy) throws IOException, InterruptedException { + this(is, file, fileTitle, listener, parallelRead, checkOnly, lazy, null); + } + + /** + * Construct SWF from stream + * + * @param is Stream to read SWF from + * @param file Path to the file + * @param fileTitle Title of the SWF + * @param listener + * @param parallelRead Use parallel threads? + * @param checkOnly Check only file validity + * @param lazy + * @param resolver Resolver for imported tags + * @throws IOException + * @throws java.lang.InterruptedException + */ + public SWF(InputStream is, String file, String fileTitle, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean lazy, UrlResolver resolver) throws IOException, InterruptedException { + this.file = file; + this.fileTitle = fileTitle; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFHeader header = decompress(is, baos, true); + gfx = header.gfx; + compression = header.compression; + lzmaProperties = header.lzmaProperties; + uncompressedData = baos.toByteArray(); + originalUncompressedData = uncompressedData; + + SWFInputStream sis = new SWFInputStream(this, uncompressedData); + dumpInfo = new DumpInfoSwfNode(this, "rootswf", "", null, 0, 0); + sis.dumpInfo = dumpInfo; + sis.skipBytesEx(3, "signature"); // skip siganture + version = sis.readUI8("version"); + fileSize = sis.readUI32("fileSize"); + dumpInfo.lengthBytes = fileSize; + if (listener != null) { + sis.addPercentListener(listener); + } + sis.setPercentMax(fileSize); + displayRect = sis.readRECT("displayRect"); + frameRate = sis.readFIXED8("frameRate"); + frameCount = sis.readUI16("frameCount"); + List tags = sis.readTagList(this, 0, parallelRead, true, !checkOnly, lazy); + if (tags.size() > 0 && tags.get(tags.size() - 1).getId() == EndTag.ID) { + tags.remove(tags.size() - 1); + } else { + hasEndTag = false; + } + this.tags = tags; + readOnlyTags = null; + if (!checkOnly) { + checkInvalidSprites(); + updateCharacters(); + assignExportNamesToSymbols(); + assignClassesToSymbols(); + if (resolver != null) { + resolveImported(resolver); + } + SWFDecompilerPlugin.fireSwfParsed(this); + } else { + boolean hasNonUnknownTag = false; + for (Tag tag : tags) { + if (tag.getOriginalDataLength() > 0 && Tag.getRequiredTags().contains(tag.getId())) { + hasNonUnknownTag = true; + } + } + if (!hasNonUnknownTag) { + throw new IOException("Invalid SWF file. No known tag found."); + } + } + + if (Configuration.autoRenameIdentifiers.get()) { + deobfuscateIdentifiers(RenameType.TYPENUMBER); + assignClassesToSymbols(); + clearScriptCache(); + } + + getASMs(true); // Add scriptNames to ASMs + } + + private void resolveImported(UrlResolver resolver) { + for (int p = 0; p < tags.size(); p++) { + Tag t = tags.get(p); + if (t instanceof ImportTag) { + ImportTag importTag = (ImportTag) t; + + SWF iSwf = resolver.resolveUrl(importTag.getUrl()); + if (iSwf != null) { + Map exportedMap1 = new HashMap<>(); + Map classesMap1 = new HashMap<>(); + + for (Tag t2 : iSwf.tags) { + if (t2 instanceof ExportAssetsTag) { + ExportAssetsTag sc = (ExportAssetsTag) t2; + Map m2 = sc.getTagToNameMap(); + for (int key : m2.keySet()) { + if (!exportedMap1.containsKey(key)) { + exportedMap1.put(key, m2.get(key)); + } + } + } + if (t2 instanceof SymbolClassTag) { + SymbolClassTag sc = (SymbolClassTag) t2; + Map m2 = sc.getTagToNameMap(); + for (int key : m2.keySet()) { + if (!classesMap1.containsKey(key)) { + classesMap1.put(key, m2.get(key)); + } + } + } + } + Map exportedMap2 = new HashMap<>(); + for (int k : exportedMap1.keySet()) { + exportedMap2.put(exportedMap1.get(k), k); + } + + Map classesMap2 = new HashMap<>(); + for (int k : classesMap1.keySet()) { + classesMap2.put(classesMap1.get(k), k); + } + + Map importedMap1 = importTag.getAssets(); + Map importedMap2 = new HashMap<>(); + for (int k : importedMap1.keySet()) { + importedMap2.put(importedMap1.get(k), k); + } + + int pos = 0; + for (String key : importedMap2.keySet()) { + if (!exportedMap2.containsKey(key)) { + continue; //? + } + int exportedId = exportedMap2.get(key); + int importedId = importedMap2.get(key); + for (Tag cht : iSwf.tags) { + if ((cht instanceof CharacterIdTag) && (((CharacterIdTag) cht).getCharacterId() == exportedId) && !(cht instanceof PlaceObjectTypeTag) && !(cht instanceof RemoveTag)) { + CharacterIdTag ch = (CharacterIdTag) cht; + cht.setSwf(this); + ch.setCharacterId(importedId); + cht.setImported(true); + tags.add(p + 1 + pos, cht); + pos++; + } + } + } + + int newId = getNextCharacterId(); + pos = 0; + for (String key : classesMap2.keySet()) { + int exportedId = classesMap2.get(key); + int importedId = newId++; + for (Tag cht : iSwf.tags) { + if ((cht instanceof CharacterIdTag) && (((CharacterIdTag) cht).getCharacterId() == exportedId) && !(cht instanceof PlaceObjectTypeTag) && !(cht instanceof RemoveTag)) { + CharacterIdTag ch = (CharacterIdTag) cht; + cht.setSwf(this); + ch.setCharacterId(importedId); + cht.setImported(true); + tags.add(p + 1 + pos, cht); + pos++; + } + } + } + updateCharacters(); + } + } + } + } + + @Override + public SWF getSwf() { + return this; + } + + public SWF getRootSwf() { + SWF result = this; + while (result.binaryData != null) { + result = result.binaryData.getSwf(); + } + + return result; + } + + public String getFile() { + return file; + } + + /** + * Get title of the file + * + * @return file title + */ + public String getFileTitle() { + if (fileTitle != null) { + return fileTitle; + } + return file; + } + + public String getShortFileName() { + String title = getFileTitle(); + if (title == null) { + return ""; + } + return new File(title).getName(); + } + + public void setFile(String file) { + this.file = file; + fileTitle = null; + } + + public Date getFileModificationDate() { + try { + if (swfList != null && swfList.sourceInfo != null) { + String fileName = swfList.sourceInfo.getFile(); + if (fileName != null) { + long lastModified = new File(fileName).lastModified(); + if (lastModified > 0) { + return new Date(lastModified); + } + } + } + } catch (SecurityException sex) { + } + + return new Date(); + } + + private static void getAbcTags(Iterable list, List actionScripts) { + for (Tag t : list) { + if (t instanceof DefineSpriteTag) { + getAbcTags(((DefineSpriteTag) t).getTags(), actionScripts); + } + if (t instanceof ABCContainerTag) { + actionScripts.add((ABCContainerTag) t); + } + } + } + + public void assignExportNamesToSymbols() { + HashMap exportNames = new HashMap<>(); + for (Tag t : getTags()) { + if (t instanceof ExportAssetsTag) { + ExportAssetsTag eat = (ExportAssetsTag) t; + for (int i = 0; i < eat.tags.size(); i++) { + Integer tagId = eat.tags.get(i); + String name = eat.names.get(i); + if ((!exportNames.containsKey(tagId)) && (!exportNames.containsValue(name))) { + exportNames.put(tagId, name); + } + } + } + } + for (Tag t : getTags()) { + if (t instanceof CharacterTag) { + CharacterTag ct = (CharacterTag) t; + if (exportNames.containsKey(ct.getCharacterId())) { + ct.setExportName(exportNames.get(ct.getCharacterId())); + } + } + } + } + + public void assignClassesToSymbols() { + HashMap classes = new HashMap<>(); + for (Tag t : getTags()) { + if (t instanceof SymbolClassTag) { + SymbolClassTag sct = (SymbolClassTag) t; + for (int i = 0; i < sct.tags.size(); i++) { + if ((!classes.containsKey(sct.tags.get(i))) && (!classes.containsValue(sct.names.get(i)))) { + classes.put(sct.tags.get(i), sct.names.get(i)); + } + } + } + } + for (Tag t : getTags()) { + if (t instanceof CharacterTag) { + CharacterTag ct = (CharacterTag) t; + if (classes.containsKey(ct.getCharacterId())) { + ct.setClassName(classes.get(ct.getCharacterId())); + } + } + } + } + + /** + * Compress SWF file + * + * @param fis Input stream + * @param fos Output stream + * @param compression + * @return True on success + */ + public static boolean compress(InputStream fis, OutputStream fos, SWFCompression compression) { + try { + compress(fis, fos, compression, null); + } catch (IOException ex) { + return false; + } + return true; + } + + public static boolean decompress(InputStream fis, OutputStream fos) { + try { + decompress(fis, fos, false); + return true; + } catch (IOException ex) { + return false; + } + } + + private static void decodeLZMAStream(InputStream is, OutputStream os, byte[] lzmaProperties, long fileSize) throws IOException { + Decoder decoder = new Decoder(); + if (!decoder.SetDecoderProperties(lzmaProperties)) { + throw new IOException("LZMA:Incorrect stream properties"); + } + if (!decoder.Code(is, os, fileSize - 8)) { + throw new IOException("LZMA:Error in data stream"); + } + } + + private static SWFHeader decompress(InputStream is, OutputStream os, boolean allowUncompressed) throws IOException { + byte[] hdr = new byte[8]; + + // SWFheader: signature, version and fileSize + if (is.read(hdr) != 8) { + throw new SwfOpenException("SWF header is too short"); + } + + String signature = new String(hdr, 0, 3, Utf8Helper.charset); + if (!swfSignatures.contains(signature)) { + throw new SwfOpenException("Invalid SWF file, wrong signature."); + } + + int version = hdr[3]; + long fileSize; + try (SWFInputStream sis = new SWFInputStream(null, Arrays.copyOfRange(hdr, 4, 8), 4, 4)) { + fileSize = sis.readUI32("fileSize"); + } + + SWFHeader header = new SWFHeader(); + header.version = version; + header.fileSize = fileSize; + header.gfx = hdr[1] == 'F' && hdr[2] == 'X'; + + try (SWFOutputStream sos = new SWFOutputStream(os, version)) { + sos.write(getHeaderBytes(SWFCompression.NONE, header.gfx)); + sos.writeUI8(version); + sos.writeUI32(fileSize); + + switch (hdr[0]) { + case 'C': { // CWS, CFX + Helper.copyStream(new InflaterInputStream(is), os, fileSize - 8); + header.compression = SWFCompression.ZLIB; + break; + } + case 'Z': { // ZWS + byte[] lzmaprop = new byte[9]; + is.read(lzmaprop); + try (SWFInputStream sis = new SWFInputStream(null, lzmaprop)) { + sis.readUI32("LZMAsize"); // compressed LZMA data size = compressed SWF - 17 byte, + // where 17 = 8 byte header + this 4 byte + 5 bytes decoder properties + + int propertiesSize = 5; + byte[] lzmaProperties = sis.readBytes(propertiesSize, "lzmaproperties"); + if (lzmaProperties.length != propertiesSize) { + throw new IOException("LZMA:input .lzma file is too short"); + } + + decodeLZMAStream(is, os, lzmaProperties, fileSize); + + header.compression = SWFCompression.LZMA; + header.lzmaProperties = lzmaProperties; + } + break; + } + case 'A': { // ABC + byte[] lzmaProperties = new byte[5]; + is.read(lzmaProperties); + byte[] uncompressedLength = new byte[8]; + is.read(uncompressedLength); + + decodeLZMAStream(is, os, lzmaProperties, fileSize); + + header.compression = SWFCompression.LZMA_ABC; + header.lzmaProperties = lzmaProperties; + break; + } + default: { // FWS, GFX + if (allowUncompressed) { + Helper.copyStream(is, os, fileSize - 8); + } else { + throw new IOException("SWF is not compressed"); + } + } + } + + return header; + } + } + + public static boolean renameInvalidIdentifiers(RenameType renameType, InputStream fis, OutputStream fos) { + try { + SWF swf = new SWF(fis, Configuration.parallelSpeedUp.get()); + int cnt = swf.deobfuscateIdentifiers(renameType); + swf.assignClassesToSymbols(); + System.out.println(cnt + " identifiers renamed."); + swf.saveTo(fos); + } catch (InterruptedException | IOException ex) { + return false; + } + return true; + } + + public List getScriptPacksByClassNames(List classNames) throws Exception { + Set resultSet = new HashSet<>(); + + List abcList = getAbcList(); + List allAbcList = new ArrayList<>(); + for (int i = 0; i < abcList.size(); i++) { + allAbcList.add(abcList.get(i).getABC()); + } + + for (String className : classNames) { + for (int i = 0; i < abcList.size(); i++) { + ABC abc = abcList.get(i).getABC(); + List scrs = abc.findScriptPacksByPath(className, allAbcList); + for (int j = 0; j < scrs.size(); j++) { + ScriptPack scr = scrs.get(j); + resultSet.add(scr); + } + } + } + + return new ArrayList<>(resultSet); + } + + private List uniqueAS3Packs(List packs) { + List ret = new ArrayList<>(); + Set classPaths = new HashSet<>(); + for (ScriptPack item : packs) { + ClassPath key = item.getClassPath(); + if (classPaths.contains(key)) { + logger.log(Level.SEVERE, "Duplicate pack path found (" + key + ")!"); + } else { + classPaths.add(key); + ret.add(item); + } + } + return ret; + } + + public List getAS3Packs() { + List packs = new ArrayList<>(); + + List abcList = getAbcList(); + List allAbcList = new ArrayList<>(); + for (int i = 0; i < abcList.size(); i++) { + allAbcList.add(abcList.get(i).getABC()); + } + + for (ABCContainerTag abcTag : abcList) { + packs.addAll(abcTag.getABC().getScriptPacks(null, allAbcList)); + } + return uniqueAS3Packs(packs); + } + + @Override + public RECT getRect() { + return displayRect; + } + + @Override + public RECT getRect(Set added) { + return displayRect; + } + + public EventListener getExportEventListener() { + EventListener evl = new EventListener() { + @Override + public void handleExportingEvent(String type, int index, int count, Object data) { + for (EventListener listener : listeners) { + listener.handleExportingEvent(type, index, count, data); + } + } + + @Override + public void handleExportedEvent(String type, int index, int count, Object data) { + for (EventListener listener : listeners) { + listener.handleExportedEvent(type, index, count, data); + } + } + + @Override + public void handleEvent(String event, Object data) { + informListeners(event, data); + } + }; + + return evl; + } + + public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException { + return exportActionScript(handler, outdir, null, exportSettings, parallel, evl, true, true); + } + + public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, List as3scripts, ScriptExportSettings exportSettings, boolean parallel, EventListener evl, boolean as2, boolean as3) throws IOException { + List ret = new ArrayList<>(); + + if (isAS3()) { + if (as3) { + ret.addAll(new AS3ScriptExporter().exportActionScript3(this, handler, outdir, as3scripts, exportSettings, parallel, evl)); + } + } else if (as2) { + ret.addAll(new AS2ScriptExporter().exportAS2Scripts(handler, outdir, getASMs(true), exportSettings, parallel, evl)); + } + return ret; + } + + public Map getASMs(boolean exportFileNames) { + return getASMs(exportFileNames, new ArrayList<>(), true); + } + + public Map getASMs(boolean exportFileNames, List nodesToExport, boolean exportAll) { + Map asmsToExport = new HashMap<>(); + for (TreeItem treeItem : getFirstLevelASMNodes(null)) { + getASMs(exportFileNames, treeItem, nodesToExport, exportAll, asmsToExport, File.separator + getASMPath(exportFileNames, treeItem)); + } + + return asmsToExport; + } + + private void getASMs(boolean exportFileNames, TreeItem treeItem, List nodesToExport, boolean exportAll, Map asmsToExport, String path) { + boolean exportNode = nodesToExport.contains(treeItem); + TreeItem realItem = treeItem instanceof TagScript ? ((TagScript) treeItem).getTag() : treeItem; + if (realItem instanceof ASMSource && (exportAll || exportNode)) { + String npath = path; + String exPath = path; + int ppos = 1; + while (asmsToExport.containsKey(npath)) { + ppos++; + npath = path + (exportFileNames ? "[" + ppos + "]" : "_" + ppos); + exPath = path + "[" + ppos + "]"; + } + ((ASMSource) realItem).setScriptName(exPath); + asmsToExport.put(npath, (ASMSource) realItem); + } + + if (treeItem instanceof TagScript) { + TagScript tagScript = (TagScript) treeItem; + for (TreeItem subItem : tagScript.getFrames()) { + getASMs(exportFileNames, subItem, nodesToExport, exportAll, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); + } + } else if (treeItem instanceof FrameScript) { + FrameScript frameScript = (FrameScript) treeItem; + Frame parentFrame = frameScript.getFrame(); + for (TreeItem subItem : parentFrame.actionContainers) { + getASMs(exportFileNames, getASMWrapToTagScript(subItem), nodesToExport, exportAll || exportNode, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); + } + for (TreeItem subItem : parentFrame.actions) { + getASMs(exportFileNames, getASMWrapToTagScript(subItem), nodesToExport, exportAll || exportNode, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); + } + } else if (treeItem instanceof AS2Package) { + AS2Package as2Package = (AS2Package) treeItem; + for (TreeItem subItem : as2Package.subPackages.values()) { + getASMs(exportFileNames, subItem, nodesToExport, exportAll, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); + } + for (TreeItem subItem : as2Package.scripts.values()) { + getASMs(exportFileNames, subItem, nodesToExport, exportAll, asmsToExport, path + File.separator + getASMPath(exportFileNames, subItem)); + } + } + } + + private String getASMPath(boolean exportFileName, TreeItem treeItem) { + if (!exportFileName) { + return treeItem.toString(); + } + + String result; + if (treeItem instanceof Exportable) { + result = ((Exportable) treeItem).getExportFileName(); + } else { + result = treeItem.toString(); + } + + return Helper.makeFileName(result); + } + + private TreeItem getASMWrapToTagScript(TreeItem treeItem) { + if (treeItem instanceof Tag) { + Tag resultTag = (Tag) treeItem; + List subNodes = new ArrayList<>(); + if (treeItem instanceof ASMSourceContainer) { + for (ASMSource item : ((ASMSourceContainer) treeItem).getSubItems()) { + subNodes.add(item); + } + } + + TagScript tagScript = new TagScript(treeItem.getSwf(), resultTag, subNodes); + return tagScript; + } + + return treeItem; + } + + public List getFirstLevelASMNodes(Map tagScriptCache) { + Timeline timeline = getTimeline(); + List subNodes = new ArrayList<>(); + List subFrames = new ArrayList<>(); + subNodes.addAll(timeline.getAS2RootPackage().subPackages.values()); + subNodes.addAll(timeline.getAS2RootPackage().scripts.values()); + + for (Tag tag : timeline.otherTags) { + boolean hasInnerFrames = false; + List tagSubNodes = new ArrayList<>(); + if (tag instanceof Timelined) { + Timeline timeline2 = ((Timelined) tag).getTimeline(); + for (Frame frame : timeline2.getFrames()) { + if (!frame.actions.isEmpty() || !frame.actionContainers.isEmpty()) { + FrameScript frameScript = new FrameScript(this, frame); + tagSubNodes.add(frameScript); + hasInnerFrames = true; + } + } + } + + if (tag instanceof ASMSourceContainer) { + for (ASMSource asm : ((ASMSourceContainer) tag).getSubItems()) { + tagSubNodes.add(asm); + } + } + + if (!tagSubNodes.isEmpty()) { + TagScript ts = new TagScript(this, tag, tagSubNodes); + if (tagScriptCache != null) { + tagScriptCache.put(tag, ts); + } + if (hasInnerFrames) { + subFrames.add(ts); + } else { + subNodes.add(ts); + } + } + } + + subNodes.addAll(subFrames); + for (Frame frame : timeline.getFrames()) { + if (!frame.actions.isEmpty() || !frame.actionContainers.isEmpty()) { + FrameScript frameScript = new FrameScript(this, frame); + subNodes.add(frameScript); + } + } + + return subNodes; + } + + private final HashSet listeners = new HashSet<>(); + + public final void addEventListener(EventListener listener) { + listeners.add(listener); + for (Tag t : getTags()) { + if (t instanceof ABCContainerTag) { + (((ABCContainerTag) t).getABC()).addEventListener(listener); + } + } + } + + public final void removeEventListener(EventListener listener) { + listeners.remove(listener); + for (Tag t : getTags()) { + if (t instanceof ABCContainerTag) { + (((ABCContainerTag) t).getABC()).removeEventListener(listener); + } + } + } + + protected void informListeners(String event, Object data) { + for (EventListener listener : listeners) { + listener.handleEvent(event, data); + } + } + + public static void populateVideoFrames(int streamId, Iterable tags, HashMap output) { + for (Tag t : tags) { + if (t instanceof VideoFrameTag) { + VideoFrameTag videoFrameTag = (VideoFrameTag) t; + if (videoFrameTag.streamID == streamId) { + output.put(videoFrameTag.frameNum, (VideoFrameTag) t); + } + } + if (t instanceof DefineSpriteTag) { + populateVideoFrames(streamId, ((DefineSpriteTag) t).getTags(), output); + } + } + } + + private static void writeLE(OutputStream os, long val, int size) throws IOException { + for (int i = 0; i < size; i++) { + os.write((int) (val & 0xff)); + val >>= 8; + } + } + + public static void createWavFromPcmData(OutputStream fos, int soundRateHz, boolean soundSize, boolean soundType, byte[] data) throws IOException { + ByteArrayOutputStream subChunk1Data = new ByteArrayOutputStream(); + int audioFormat = 1; // PCM + writeLE(subChunk1Data, audioFormat, 2); + int numChannels = soundType ? 2 : 1; + writeLE(subChunk1Data, numChannels, 2); + int[] rateMap = {5512, 11025, 22050, 44100}; + int sampleRate = soundRateHz; // rateMap[soundRate]; + writeLE(subChunk1Data, sampleRate, 4); + int bitsPerSample = soundSize ? 16 : 8; + int byteRate = sampleRate * numChannels * bitsPerSample / 8; + writeLE(subChunk1Data, byteRate, 4); + int blockAlign = numChannels * bitsPerSample / 8; + writeLE(subChunk1Data, blockAlign, 2); + writeLE(subChunk1Data, bitsPerSample, 2); + + ByteArrayOutputStream chunks = new ByteArrayOutputStream(); + chunks.write(Utf8Helper.getBytes("fmt ")); + byte[] subChunk1DataBytes = subChunk1Data.toByteArray(); + writeLE(chunks, subChunk1DataBytes.length, 4); + chunks.write(subChunk1DataBytes); + + chunks.write(Utf8Helper.getBytes("data")); + writeLE(chunks, data.length, 4); + chunks.write(data); + + fos.write(Utf8Helper.getBytes("RIFF")); + byte[] chunkBytes = chunks.toByteArray(); + writeLE(fos, 4 + chunkBytes.length, 4); + fos.write(Utf8Helper.getBytes("WAVE")); + fos.write(chunkBytes); + } + + public static String getTypePrefix(CharacterTag c) { + if (c instanceof ShapeTag) { + return "shape"; + } + if (c instanceof MorphShapeTag) { + return "morphshape"; + } + if (c instanceof DefineSpriteTag) { + return "sprite"; + } + if (c instanceof TextTag) { + return "text"; + } + if (c instanceof ButtonTag) { + return "button"; + } + if (c instanceof FontTag) { + return "font"; + } + if (c instanceof ImageTag) { + return "image"; + } + return "character"; + } + + public static void writeLibrary(SWF fswf, Set library, OutputStream fos) throws IOException { + for (int c : library) { + CharacterTag ch = fswf.getCharacter(c); + if (ch instanceof FontTag) { + StringBuilder sb = new StringBuilder(); + sb.append("function ").append(getTypePrefix(ch)).append(c).append("(ctx,ch,textColor){\r\n"); + ((FontTag) ch).toHtmlCanvas(sb, 1); + sb.append("}\r\n\r\n"); + fos.write(Utf8Helper.getBytes(sb.toString())); + } else { + if (ch instanceof ImageTag) { + ImageTag image = (ImageTag) ch; + ImageFormat format = image.getImageFormat(); + byte[] imageData = Helper.readStream(image.getImageData()); + String base64ImgData = Helper.byteArrayToBase64String(imageData); + fos.write(Utf8Helper.getBytes("var imageObj" + c + " = document.createElement(\"img\");\r\nimageObj" + c + ".src=\"data:image/" + format + ";base64," + base64ImgData + "\";\r\n")); + } + fos.write(Utf8Helper.getBytes("function " + getTypePrefix(ch) + c + "(ctx,ctrans,frame,ratio,time){\r\n")); + if (ch instanceof DrawableTag) { + StringBuilder sb = new StringBuilder(); + ((DrawableTag) ch).toHtmlCanvas(sb, 1); + fos.write(Utf8Helper.getBytes(sb.toString())); + } + fos.write(Utf8Helper.getBytes("}\r\n\r\n")); + } + } + } + + private static void getVariables(ConstantPool constantPool, BaseLocalData localData, TranslateStack stack, List output, ActionGraphSource code, int ip, List> variables, List functions, HashMap strings, List visited, HashMap usageTypes, String path) throws InterruptedException { + boolean debugMode = false; + while ((ip > -1) && ip < code.size()) { + if (visited.contains(ip)) { + break; + } + GraphSourceItem ins = code.get(ip); + + if (debugMode) { + System.err.println("Visit " + ip + ": ofs" + Helper.formatAddress(((Action) ins).getAddress()) + ":" + ((Action) ins).getASMSource(new ActionList(), new HashSet<>(), ScriptExportMode.PCODE) + " stack:" + Helper.stackToString(stack, LocalData.create(new ConstantPool()))); + } + if (ins.isExit()) { + break; + } + if (ins.isIgnored()) { + ip++; + continue; + } + + String usageType = "name"; + GraphTargetItem name = null; + if ((ins instanceof ActionGetVariable) + || (ins instanceof ActionGetMember) + || (ins instanceof ActionDefineLocal2) + || (ins instanceof ActionNewMethod) + || (ins instanceof ActionNewObject) + || (ins instanceof ActionCallMethod) + || (ins instanceof ActionCallFunction)) { + if (stack.isEmpty()) { + break; + } + name = stack.peek(); + } + + if ((ins instanceof ActionGetVariable) || (ins instanceof ActionDefineLocal2)) { + usageType = "variable"; + } + if (ins instanceof ActionGetMember) { + usageType = "member"; + } + if ((ins instanceof ActionNewMethod) || (ins instanceof ActionNewObject)) { + usageType = "class"; + } + if (ins instanceof ActionCallMethod) { + usageType = "function"; // can there be method? + } + if (ins instanceof ActionCallFunction) { + usageType = "function"; + } + + if ((ins instanceof ActionDefineFunction) || (ins instanceof ActionDefineFunction2)) { + functions.add(ins); + } + + if (ins instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) ins; + List cntSizes = cnt.getContainerSizes(); + long addr = code.pos2adr(ip + 1); + ip = code.adr2pos(addr); + String cntName = cnt.getName(); + for (Long size : cntSizes) { + if (size == 0) { + continue; + } + ip = code.adr2pos(addr); + addr += size; + int nextip = code.adr2pos(addr); + getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path + (cntName == null ? "" : "/" + cntName)); + ip = nextip; + } + List> r = new ArrayList<>(); + r.add(new ArrayList<>()); + r.add(new ArrayList<>()); + r.add(new ArrayList<>()); + ((GraphSourceItemContainer) ins).translateContainer(r, ins, stack, output, new HashMap<>(), new HashMap<>(), new HashMap<>()); + continue; + } + + if ((ins instanceof ActionSetVariable) || (ins instanceof ActionSetMember) || (ins instanceof ActionDefineLocal)) { + if (stack.size() < 2) { + break; + } + name = stack.get(stack.size() - 2); + } + + if ((ins instanceof ActionSetVariable) || (ins instanceof ActionDefineLocal)) { + usageType = "variable"; + } + + if (ins instanceof ActionSetMember) { + usageType = "member"; + } + + if (name instanceof DirectValueActionItem) { + variables.add(new MyEntry<>((DirectValueActionItem) name, constantPool)); + usageTypes.put((DirectValueActionItem) name, usageType); + } + + // for..in return + if (((ins instanceof ActionEquals) || (ins instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { + stack.push(new DirectValueActionItem(null, null, 0, Null.INSTANCE, new ArrayList<>())); + } + + if (ins instanceof ActionConstantPool) { + constantPool = new ConstantPool(((ActionConstantPool) ins).constantPool); + } + int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; + + int requiredStackSize = ins.getStackPopCount(localData, stack); + if (stack.size() < requiredStackSize) { + // probably obfucated code, never executed branch + break; + } + + ins.translate(localData, stack, output, staticOperation, path); + if (ins.isExit()) { + break; + } + + if (ins instanceof ActionPush) { + if (!stack.isEmpty()) { + GraphTargetItem top = stack.peek(); + if (top instanceof DirectValueActionItem) { + DirectValueActionItem dvt = (DirectValueActionItem) top; + if ((dvt.value instanceof String) || (dvt.value instanceof ConstantIndex)) { + if (constantPool == null) { + constantPool = new ConstantPool(dvt.constants); + } + strings.put(dvt, constantPool); + } + } + } + } + + if (ins.isBranch() || ins.isJump()) { + if (ins instanceof ActionIf) { + if (stack.isEmpty()) { + break; + } + stack.pop(); + } + visited.add(ip); + List branches = ins.getBranches(code); + for (int b : branches) { + TranslateStack brStack = (TranslateStack) stack.clone(); + if (b >= 0) { + getVariables(constantPool, localData, brStack, output, code, b, variables, functions, strings, visited, usageTypes, path); + } else if (debugMode) { + System.out.println("Negative branch:" + b); + } + } + // } + break; + } + ip++; + } + } + + private static void getVariables(List> variables, List functions, HashMap strings, HashMap usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException { + ActionLocalData localData = new ActionLocalData(); + getVariables(null, localData, new TranslateStack(path), new ArrayList<>(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList<>(), usageTypes, path); + } + + private List> getVariables(List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes, ASMSource src, String path) throws InterruptedException { + List> ret = new ArrayList<>(); + ActionList actions = src.getActions(); + actionsMap.put(src, actions); + getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(actions, version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path); + return ret; + } + + private void getVariables(Iterable tags, String path, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes) throws InterruptedException { + List processed = new ArrayList<>(); + for (Tag t : tags) { + String subPath = path + "/" + t.toString(); + if (t instanceof ASMSource) { + addVariable((ASMSource) t, subPath, processed, variables, actionsMap, functions, strings, usageTypes); + } + if (t instanceof ASMSourceContainer) { + List processed2 = new ArrayList<>(); + for (ASMSource asm : ((ASMSourceContainer) t).getSubItems()) { + addVariable(asm, subPath + "/" + asm.toString(), processed2, variables, actionsMap, functions, strings, usageTypes); + } + } + if (t instanceof DefineSpriteTag) { + getVariables(((DefineSpriteTag) t).getTags(), path + "/" + t.toString(), variables, actionsMap, functions, strings, usageTypes); + } + } + } + + private void addVariable(ASMSource asm, String path, List processed, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes) throws InterruptedException { + int pos = 1; + String infPath2 = path; + while (processed.contains(infPath2)) { + pos++; + infPath2 = path + "[" + pos + "]"; + } + processed.add(infPath2); + informListeners("getVariables", infPath2); + getVariables(variables, actionsMap, functions, strings, usageTypes, asm, path); + } + + public boolean as3StringConstantExists(String str) { + for (ABCContainerTag abcTag : getAbcList()) { + ABC abc = abcTag.getABC(); + for (int i = 1; i < abc.constants.getStringCount(); i++) { + if (abc.constants.getString(i).equals(str)) { + return true; + } + } + } + + return false; + } + + public void fixAS3Code() { + for (ABCContainerTag abcTag : getAbcList()) { + ABC abc = abcTag.getABC(); + for (MethodBody body : abc.bodies) { + AVM2Code code = body.getCode(); + body.setCodeBytes(code.getBytes()); + } + + ((Tag) abcTag).setModified(true); + } + } + + public int deobfuscateAS3Identifiers(RenameType renameType) { + for (Tag tag : getTags()) { + if (tag instanceof ABCContainerTag) { + ((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, true); + tag.setModified(true); + } + } + for (Tag tag : getTags()) { + if (tag instanceof ABCContainerTag) { + ((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, false); + tag.setModified(true); + } + } + for (Tag tag : getTags()) { + if (tag instanceof SymbolClassTag) { + SymbolClassTag sc = (SymbolClassTag) tag; + for (int i = 0; i < sc.names.size(); i++) { + String newname = deobfuscation.deobfuscateNameWithPackage(true, sc.names.get(i), deobfuscated, renameType, deobfuscated); + if (newname != null) { + sc.names.set(i, newname); + } + } + sc.setModified(true); + } + } + deobfuscation.deobfuscateInstanceNames(true, deobfuscated, renameType, getTags(), new HashMap<>()); + return deobfuscated.size(); + } + + public int deobfuscateIdentifiers(RenameType renameType) throws InterruptedException { + FileAttributesTag fileAttributes = getFileAttributes(); + if (fileAttributes == null) { + int cnt = 0; + cnt += deobfuscateAS2Identifiers(renameType); + cnt += deobfuscateAS3Identifiers(renameType); + return cnt; + } else if (fileAttributes.actionScript3) { + return deobfuscateAS3Identifiers(renameType); + } else { + return deobfuscateAS2Identifiers(renameType); + } + } + + public void renameAS2Identifier(String identifier, String newname) throws InterruptedException { + Map selected = new HashMap<>(); + selected.put(DottedChain.parse(identifier), DottedChain.parse(newname)); + renameAS2Identifiers(null, selected); + } + + private int deobfuscateAS2Identifiers(RenameType renameType) throws InterruptedException { + return renameAS2Identifiers(renameType, null); + } + + private int renameAS2Identifiers(RenameType renameType, Map selected) throws InterruptedException { + HashMap actionsMap = new HashMap<>(); + List allFunctions = new ArrayList<>(); + List> allVariableNames = new ArrayList<>(); + HashMap allStrings = new HashMap<>(); + HashMap usageTypes = new HashMap<>(); + + int ret = 0; + getVariables(getTags(), "", allVariableNames, actionsMap, allFunctions, allStrings, usageTypes); + informListeners("rename", ""); + int fc = 0; + for (MyEntry it : allVariableNames) { + String name = it.getKey().toStringNoH(it.getValue()); + deobfuscation.allVariableNamesStr.add(name); + } + + informListeners("rename", "classes"); + int classCount = 0; + for (Tag t : getTags()) { + if (t instanceof DoInitActionTag) { + classCount++; + } + } + int cnt = 0; + for (Tag t : getTags()) { + if (t instanceof DoInitActionTag) { + cnt++; + informListeners("rename", "class " + cnt + "/" + classCount); + DoInitActionTag dia = (DoInitActionTag) t; + String exportName = getExportName(dia.spriteId); + exportName = exportName != null ? exportName : "_unk_"; + final String pkgPrefix = "__Packages."; + String[] classNameParts = null; + if (exportName.startsWith(pkgPrefix)) { + String className = exportName.substring(pkgPrefix.length()); + if (className.contains(".")) { + classNameParts = className.split("\\."); + } else { + classNameParts = new String[]{className}; + } + } + int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; + List dec; + try { + dec = Action.actionsToTree(dia.getActions(), version, staticOperation, ""/*FIXME*/); + } catch (EmptyStackException ex) { + continue; + } + GraphTargetItem name = null; + for (GraphTargetItem it : dec) { + if (it instanceof ClassActionItem) { + ClassActionItem cti = (ClassActionItem) it; + List methods = new ArrayList<>(); + methods.addAll(cti.functions); + methods.addAll(cti.staticFunctions); + + for (GraphTargetItem gti : methods) { + if (gti instanceof FunctionActionItem) { + FunctionActionItem fun = (FunctionActionItem) gti; + if (fun.calculatedFunctionName instanceof DirectValueActionItem) { + DirectValueActionItem dvf = (DirectValueActionItem) fun.calculatedFunctionName; + String fname = dvf.toStringNoH(null); + String changed = deobfuscation.deobfuscateName(false, fname, false, "method", deobfuscated, renameType, selected); + if (changed != null) { + deobfuscated.put(DottedChain.parse(fname), DottedChain.parse(changed)); + } + } + } + } + + List vars = new ArrayList<>(); + for (MyEntry item : cti.vars) { + vars.add(item.getKey()); + } + for (MyEntry item : cti.staticVars) { + vars.add(item.getKey()); + } + for (GraphTargetItem gti : vars) { + if (gti instanceof DirectValueActionItem) { + DirectValueActionItem dvf = (DirectValueActionItem) gti; + String vname = dvf.toStringNoH(null); + String changed = deobfuscation.deobfuscateName(false, vname, false, "attribute", deobfuscated, renameType, selected); + if (changed != null) { + deobfuscated.put(DottedChain.parse(vname), DottedChain.parse(changed)); + } + } + } + + name = cti.className; + break; + } + if (it instanceof InterfaceActionItem) { + InterfaceActionItem ift = (InterfaceActionItem) it; + name = ift.name; + } + } + + if (name != null) { + int pos = 0; + while (name instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) name; + GraphTargetItem memberName = mem.memberName; + if (memberName instanceof DirectValueActionItem) { + DirectValueActionItem dvt = (DirectValueActionItem) memberName; + String nameStr = dvt.toStringNoH(null); + if (classNameParts != null) { + if (classNameParts.length - 1 - pos < 0) { + break; + } + } + String changedNameStr = nameStr; + if (classNameParts != null) { + changedNameStr = classNameParts[classNameParts.length - 1 - pos]; + } + String changedNameStr2 = deobfuscation.deobfuscateName(false, changedNameStr, pos == 0, pos == 0 ? "class" : "package", deobfuscated, renameType, selected); + if (changedNameStr2 != null) { + changedNameStr = changedNameStr2; + } + ret++; + deobfuscated.put(DottedChain.parse(nameStr), DottedChain.parse(changedNameStr)); + pos++; + } + name = mem.object; + } + if (name instanceof GetVariableActionItem) { + GetVariableActionItem var = (GetVariableActionItem) name; + if (var.name instanceof DirectValueActionItem) { + DirectValueActionItem dvt = (DirectValueActionItem) var.name; + String nameStr = dvt.toStringNoH(null); + if (classNameParts != null) { + if (classNameParts.length - 1 - pos < 0) { + break; + } + } + String changedNameStr = nameStr; + if (classNameParts != null) { + changedNameStr = classNameParts[classNameParts.length - 1 - pos]; + } + String changedNameStr2 = deobfuscation.deobfuscateName(false, changedNameStr, pos == 0, pos == 0 ? "class" : "package", deobfuscated, renameType, selected); + if (changedNameStr2 != null) { + changedNameStr = changedNameStr2; + } + ret++; + deobfuscated.put(DottedChain.parse(nameStr), DottedChain.parse(changedNameStr)); + pos++; + } + } + } + t.setModified(true); + } + } + + for (GraphSourceItem fun : allFunctions) { + fc++; + informListeners("rename", "function " + fc + "/" + allFunctions.size()); + if (fun instanceof ActionDefineFunction) { + ActionDefineFunction f = (ActionDefineFunction) fun; + if (f.functionName.isEmpty()) { // anonymous function, leave as is + continue; + } + String changed = deobfuscation.deobfuscateName(false, f.functionName, false, "function", deobfuscated, renameType, selected); + if (changed != null) { + f.replacedFunctionName = changed; + ret++; + } + } + if (fun instanceof ActionDefineFunction2) { + ActionDefineFunction2 f = (ActionDefineFunction2) fun; + if (f.functionName.isEmpty()) { // anonymous function, leave as is + continue; + } + String changed = deobfuscation.deobfuscateName(false, f.functionName, false, "function", deobfuscated, renameType, selected); + if (changed != null) { + f.replacedFunctionName = changed; + ret++; + } + } + } + + HashSet stringsNoVarH = new HashSet<>(); + List allVariableNamesDv = new ArrayList<>(); + for (MyEntry it : allVariableNames) { + allVariableNamesDv.add(it.getKey()); + } + for (DirectValueActionItem ti : allStrings.keySet()) { + if (!allVariableNamesDv.contains(ti)) { + stringsNoVarH.add(System.identityHashCode(allStrings.get(ti)) + "_" + ti.toStringNoH(allStrings.get(ti))); + } + } + + int vc = 0; + for (MyEntry it : allVariableNames) { + vc++; + String name = it.getKey().toStringNoH(it.getValue()); + String changed = deobfuscation.deobfuscateName(false, name, false, usageTypes.get(it.getKey()), deobfuscated, renameType, selected); + if (changed != null) { + boolean addNew = false; + String h = System.identityHashCode(it.getKey()) + "_" + name; + if (stringsNoVarH.contains(h)) { + addNew = true; + } + ActionPush pu = (ActionPush) it.getKey().getSrc(); + if (pu.replacement == null) { + pu.replacement = new ArrayList<>(); + pu.replacement.addAll(pu.values); + } + if (pu.replacement.get(it.getKey().pos) instanceof ConstantIndex) { + ConstantIndex ci = (ConstantIndex) pu.replacement.get(it.getKey().pos); + ConstantPool pool = it.getValue(); + if (pool == null) { + continue; + } + if (pool.constants == null) { + continue; + } + if (addNew) { + pool.constants.add(changed); + ci.index = pool.constants.size() - 1; + } else { + pool.constants.set(ci.index, changed); + } + } else { + pu.replacement.set(it.getKey().pos, changed); + } + ret++; + } + } + + for (ASMSource src : actionsMap.keySet()) { + actionsMap.get(src).removeNops(); + src.setActions(actionsMap.get(src)); + src.setModified(); + } + + deobfuscation.deobfuscateInstanceNames(false, deobfuscated, renameType, getTags(), selected); + return ret; + } + + public IdentifiersDeobfuscation getDeobfuscation() { + return deobfuscation; + } + + public void exportFla(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion version) throws IOException, InterruptedException { + XFLExportSettings settings = new XFLExportSettings(); + settings.compressed = true; + exportXfl(handler, outfile, swfName, generator, generatorVerName, generatorVersion, parallel, version, settings); + } + + public void exportXfl(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion version) throws IOException, InterruptedException { + XFLExportSettings settings = new XFLExportSettings(); + settings.compressed = false; + exportXfl(handler, outfile, swfName, generator, generatorVerName, generatorVersion, parallel, version, settings); + } + + public void exportXfl(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion version, XFLExportSettings settings) throws IOException, InterruptedException { + new XFLConverter().convertSWF(handler, this, swfName, outfile, settings, generator, generatorVerName, generatorVersion, parallel, version); + clearAllCache(); + } + + public static AffineTransform matrixToTransform(MATRIX mat) { + return new AffineTransform(mat.getScaleXFloat(), mat.getRotateSkew0Float(), + mat.getRotateSkew1Float(), mat.getScaleYFloat(), + mat.translateX, mat.translateY); + } + + public SerializableImage getFromCache(String key) { + if (frameCache.contains(key)) { + return frameCache.get(key); + } + return null; + } + + public byte[] getFromCache(SoundTag soundTag) { + if (soundCache.contains(soundTag)) { + return soundCache.get(soundTag); + } + return null; + } + + public void putToCache(String key, SerializableImage img) { + if (Configuration.useFrameCache.get()) { + frameCache.put(key, img); + } + } + + public void putToCache(SoundTag soundTag, byte[] data) { + soundCache.put(soundTag, data); + } + + public void clearImageCache() { + frameCache.clear(); + rectCache.clear(); + for (Tag tag : getTags()) { + if (tag instanceof ImageTag) { + ((ImageTag) tag).clearCache(); + } + else if (tag instanceof DefineCompactedFont) { + ((DefineCompactedFont) tag).rebuildShapeCache(); + } + } + } + + public void clearScriptCache() { + as2PcodeCache.clear(); + as2Cache.clear(); + as3Cache.clear(); + IdentifiersDeobfuscation.clearCache(); + } + + public void clearReadOnlyListCache() { + readOnlyTags = null; + for (Tag tag : tags) { + if (tag instanceof DefineSpriteTag) { + ((DefineSpriteTag) tag).clearReadOnlyListCache(); + } + } + } + + public static void clearAllStaticCache() { + Cache.clearAll(); + Helper.clearShapeCache(); + System.gc(); + } + + public void clearAllCache() { + characters = null; + characterIdTags = null; + abcList = null; + timeline = null; + clearReadOnlyListCache(); + clearImageCache(); + clearScriptCache(); + clearAllStaticCache(); + } + + public static void uncache(ASMSource src) { + if (src != null) { + SWF swf = src.getSwf(); + swf.as2Cache.remove(src); + swf.as2PcodeCache.remove(src); + } + } + + public static void uncache(ScriptPack pack) { + if (pack != null) { + pack.getSwf().as3Cache.remove(pack); + } + } + + public static boolean isCached(ASMSource src) { + return src.getSwf().as2Cache.contains(src); + } + + public static boolean isCached(ScriptPack pack) { + return pack.getSwf().as3Cache.contains(pack); + } + + public static ActionList getCachedActionList(ASMSource src, final List listeners) throws InterruptedException { + synchronized (src) { + SWF swf = src.getSwf(); + int deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0; + if (swf != null && swf.as2PcodeCache.contains(src)) { + ActionList result = swf.as2PcodeCache.get(src); + if (result.deobfuscationMode == deobfuscationMode) { + return result; + } + } + + try { + ByteArrayRange actionBytes = src.getActionBytes(); + int prevLength = actionBytes.getPos(); + SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray()); + if (prevLength != 0) { + rri.seek(prevLength); + } + + int version = swf == null ? SWF.DEFAULT_VERSION : swf.version; + ActionList list = ActionListReader.readActionListTimeout(listeners, rri, version, prevLength, prevLength + actionBytes.getLength(), src.toString()/*FIXME?*/, deobfuscationMode); + list.fileData = actionBytes.getArray(); + list.deobfuscationMode = deobfuscationMode; + if (swf != null) { + swf.as2PcodeCache.put(src, list); + } + + return list; + } catch (InterruptedException ex) { + throw ex; + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + return new ActionList(); + } + } + } + + public static CachedScript getFromCache(ASMSource src) { + SWF swf = src.getSwf(); + if (swf.as2Cache.contains(src)) { + return swf.as2Cache.get(src); + } + + return null; + } + + public static CachedScript getCached(ASMSource src, ActionList actions) throws InterruptedException { + SWF swf = src.getSwf(); + if (swf.as2Cache.contains(src)) { + return swf.as2Cache.get(src); + } + + if (actions == null) { + actions = src.getActions(); + } + + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); + writer.startFunction("!script"); + Action.actionsToSource(src, actions, src.toString()/*FIXME?*/, writer); + writer.endFunction(); + List hilights = writer.instructionHilights; + List methodHilights = writer.methodHilights; + List classHilights = writer.classHilights; + List specialHilights = writer.specialHilights; + + String srcNoHex = writer.toString(); + CachedScript res = new CachedScript(srcNoHex, hilights, methodHilights, classHilights, specialHilights); + swf.as2Cache.put(src, res); + return res; + } + + public static CachedDecompilation getCached(ScriptPack pack) throws InterruptedException { + SWF swf = pack.getSwf(); + if (swf.as3Cache.contains(pack)) { + return swf.as3Cache.get(pack); + } + + int scriptIndex = pack.scriptIndex; + ScriptInfo script = null; + if (scriptIndex > -1) { + script = pack.abc.script_info.get(scriptIndex); + } + boolean parallel = Configuration.parallelSpeedUp.get(); + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); + pack.toSource(writer, script == null ? null : script.traits.traits, new ConvertData(), ScriptExportMode.AS, parallel); + HighlightedText hilightedCode = new HighlightedText(writer); + CachedDecompilation res = new CachedDecompilation(hilightedCode); + swf.as3Cache.put(pack, res); + + return res; + } + + public Cache getRectCache() { + return rectCache; + } + + public Cache getShapeExportDataCache() { + return shapeExportDataCache; + } + + public static RECT fixRect(RECT rect) { + RECT ret = new RECT(); + ret.Xmin = rect.Xmin; + ret.Xmax = rect.Xmax; + ret.Ymin = rect.Ymin; + ret.Ymax = rect.Ymax; + + if (ret.Xmax <= 0) { + ret.Xmax = ret.getWidth(); + ret.Xmin = 0; + } + if (ret.Ymax <= 0) { + ret.Ymax = ret.getHeight(); + ret.Ymin = 0; + } + if (ret.Xmin < 0) { + ret.Xmax += (-ret.Xmin); + ret.Xmin = 0; + } + if (ret.Ymin < 0) { + ret.Ymax += (-ret.Ymin); + ret.Ymin = 0; + } + + if (ret.getWidth() < 1 || ret.getHeight() < 1) { + ret.Xmin = 0; + ret.Ymin = 0; + ret.Xmax = 20; + ret.Ymax = 20; + } + return ret; + } + + public static SerializableImage frameToImageGet(Timeline timeline, int frame, int time, Point cursorPosition, int mouseButton, RECT displayRect, Matrix transformation, ColorTransform colorTransform, Color backGroundColor, double zoom) { + if (timeline.getFrameCount() == 0) { + return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB_PRE); + } + + RECT rect = displayRect; + SerializableImage image = new SerializableImage((int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1, + (int) (rect.getHeight() * zoom / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB_PRE); + if (backGroundColor == null) { + image.fillTransparent(); + } else { + Graphics2D g = (Graphics2D) image.getBufferedImage().getGraphics(); + g.setComposite(AlphaComposite.Src); + g.setColor(backGroundColor); + g.fill(new Rectangle(image.getWidth(), image.getHeight())); + } + + Matrix m = transformation.clone(); + m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); + m.scale(zoom); + RenderContext renderContext = new RenderContext(); + renderContext.cursorPosition = cursorPosition; + renderContext.mouseButton = mouseButton; + timeline.toImage(frame, time, renderContext, image, false, m, transformation, m, colorTransform); + + return image; + } + + private void removeTagWithDependenciesFromTimeline(Tag toRemove, Timeline timeline) { + Map stage = new HashMap<>(); + Set dependingChars = new HashSet<>(); + Timelined timelined = timeline.timelined; + ReadOnlyTagList tags = timelined.getTags(); + if (toRemove instanceof CharacterTag) { + int characterId = ((CharacterTag) toRemove).getCharacterId(); + + if (characterId != 0) { + dependingChars.add(characterId); + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if (t instanceof CharacterIdTag) { + CharacterIdTag c = (CharacterIdTag) t; + Set needed = new HashSet<>(); + t.getNeededCharacters(needed); + if (needed.contains(characterId)) { + dependingChars.add(c.getCharacterId()); + } + } + } + } + } + + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if (t instanceof RemoveTag) { + RemoveTag rt = (RemoveTag) t; + int depth = rt.getDepth(); + if (stage.containsKey(depth)) { + int currentCharId = stage.get(depth); + stage.remove(depth); + if (dependingChars.contains(currentCharId)) { + timelined.removeTag(i); + i--; + continue; + } + } + } + if (t instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag po = (PlaceObjectTypeTag) t; + int placeCharId = po.getCharacterId(); + int depth = po.getDepth(); + if (placeCharId != 0) { + stage.put(depth, placeCharId); + if (dependingChars.contains(placeCharId)) { + timelined.removeTag(i); + i--; + continue; + } + } + } + if (t instanceof CharacterIdTag) { + CharacterIdTag c = (CharacterIdTag) t; + if (dependingChars.contains(c.getCharacterId())) { + timelined.removeTag(i); + i--; + continue; + } + } + Set needed = new HashSet<>(); + t.getNeededCharacters(needed); + for (int dep : dependingChars) { + if (needed.contains(dep)) { + timelined.removeTag(i); + i--; + //continue; + } + } + if (t == toRemove) { + timelined.removeTag(i); + i--; + continue; + } + if (t instanceof Timelined) { + removeTagWithDependenciesFromTimeline(toRemove, ((Timelined) t).getTimeline()); + } + } + } + + private boolean removeTagFromTimeline(Tag toRemove, Timeline timeline) { + boolean modified = false; + int characterId = -1; + if (toRemove instanceof CharacterTag) { + characterId = ((CharacterTag) toRemove).getCharacterId(); + modified = timeline.removeCharacter(characterId); + } + Timelined timelined = timeline.timelined; + ReadOnlyTagList tags = timelined.getTags(); + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if (t == toRemove) { + timelined.removeTag(t); + i--; + continue; + } + + if (toRemove instanceof CharacterTag) { + if (t.removeCharacter(characterId)) { + modified = true; + i = -1; + continue; + } + } + + if (t instanceof DefineSpriteTag) { + DefineSpriteTag spr = (DefineSpriteTag) t; + boolean sprModified = removeTagFromTimeline(toRemove, spr.getTimeline()); + if (sprModified) { + spr.setModified(true); + } + modified |= sprModified; + } + } + return modified; + } + + public void removeTags(Collection tags, boolean removeDependencies) { + Set timelineds = new HashSet<>(); + for (Tag tag : tags) { + Timelined timelined = tag.getTimelined(); + timelineds.add(timelined); + removeTagInternal(timelined, tag, removeDependencies); + } + + for (Timelined timelined : timelineds) { + resetTimelines(timelined); + } + + updateCharacters(); + clearImageCache(); + } + + @Override + public void removeTag(int index) { + setModified(true); + tags.remove(index); + updateCharacters(); + } + + @Override + public void removeTag(Tag tag) { + setModified(true); + tags.remove(tag); + updateCharacters(); + } + + public void removeTag(Tag tag, boolean removeDependencies) { + Timelined timelined = tag.getTimelined(); + removeTagInternal(timelined, tag, removeDependencies); + resetTimelines(timelined); + updateCharacters(); + clearImageCache(); + } + + private void removeTagInternal(Timelined timelined, Tag tag, boolean removeDependencies) { + if (tag instanceof ShowFrameTag || ShowFrameTag.isNestedTagType(tag.getId())) { + timelined.removeTag(tag); + timelined.setModified(true); + timelined.resetTimeline(); + } else // timeline should be always the swf here + if (removeDependencies) { + removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline()); + timelined.setModified(true); + } else { + boolean modified = removeTagFromTimeline(tag, timelined.getTimeline()); + if (modified) { + timelined.setModified(true); + } + } + } + + @Override + public ReadOnlyTagList getTags() { + if (readOnlyTags == null) { + readOnlyTags = new ReadOnlyTagList(tags); + } + + return readOnlyTags; + } + + public ReadOnlyTagList getLocalTags() { + List localTags = new ArrayList<>(); + for (Tag t : tags) { + if (!t.isImported()) { + localTags.add(t); + } + } + return new ReadOnlyTagList(localTags); + } + + /** + * Adds a tag to the SWF + * + * @param tag + */ + @Override + public void addTag(Tag tag) { + setModified(true); + tags.add(tag); + updateCharacters(); + } + + /** + * Adds a tag to the SWF + * + * @param index + * @param tag + */ + @Override + public void addTag(int index, Tag tag) { + setModified(true); + tags.add(index, tag); + updateCharacters(); + } + + /** + * Replaces a tag in the SWF + * + * @param oldTag + * @param newTag + */ + public void replaceTag(Tag oldTag, Tag newTag) { + setModified(true); + int index = tags.indexOf(oldTag); + if (index != -1) { + tags.set(index, newTag); + updateCharacters(); + } + } + + /** + * Adds a tag to the SWF If targetTreeItem is: - Frame: adds the tag to the + * Frame. Frame can be a frame of the main timeline or a DefineSprite frame + * - DefineSprite: adds the tag to the end of the DefineSprite's tag list - + * Any other tag in the SWF: adds the new tag exactly before the specified + * tag - Other: adds the tag to the end of the SWF's tag list + * + * @param tag + * @param targetTreeItem + */ + public void addTag(Tag tag, TreeItem targetTreeItem) { + SWF swf = tag.getSwf(); + Frame frame = targetTreeItem instanceof Frame ? (Frame) targetTreeItem : null; + Timelined timelined; + if (frame != null) { + timelined = frame.timeline.timelined; + } else { + timelined = swf.getTimelined(targetTreeItem); + } + + tag.setTimelined(timelined); + + ReadOnlyTagList tags = timelined.getTags(); + + int index; + if (frame != null) { + if (frame.showFrameTag != null) { + index = tags.indexOf(frame.showFrameTag); + } else { + index = -1; + } + } else if (timelined instanceof DefineSpriteTag) { + index = -1; + } else if (targetTreeItem instanceof Tag) { + if (tag instanceof CharacterIdTag && !(tag instanceof CharacterTag) && targetTreeItem instanceof CharacterTag) { + ((CharacterIdTag) tag).setCharacterId(((CharacterTag) targetTreeItem).getCharacterId()); + } + + index = tags.indexOf((Tag) targetTreeItem); // todo: honfika: why not index + 1? + } else { + index = -1; + if (tag instanceof CharacterTag) { + // add before the last ShowFrame tag + for (int i = tags.size() - 1; i >= 0; i--) { + if (tags.get(i) instanceof ShowFrameTag) { + index = i; + break; + } + } + } + } + + if (index > -1) { + timelined.addTag(index, tag); + } else { + timelined.addTag(tag); + } + + timelined.resetTimeline(); + + if (timelined instanceof DefineSpriteTag) { + DefineSpriteTag sprite = (DefineSpriteTag) timelined; + sprite.frameCount = timelined.getTimeline().getFrameCount(); + } + } + + public Timelined getTimelined(TreeItem treeItem) { + if (treeItem instanceof Frame) { + return ((Frame) treeItem).timeline.timelined; + } + + if (treeItem instanceof DefineSpriteTag) { + return (DefineSpriteTag) treeItem; + } + + return treeItem.getSwf(); + } + + public void packCharacterIds() { + int maxId = getNextCharacterId(); + int id = 1; + for (int i = 1; i < maxId; i++) { + CharacterTag charactertag = getCharacter(i); + if (charactertag != null) { + if (i != id) { + replaceCharacter(i, id); + } + id++; + } else { + // make sure that the id is not referenced in the tags + replaceCharacter(i, 0); + } + } + } + + public void sortCharacterIds() { + int maxId = Math.max(tags.size(), getNextCharacterId()); + int id = maxId; + // first set the chatacter ids to surely not used ids + for (Tag tag : getTags()) { + if (tag instanceof CharacterTag) { + CharacterTag characterTag = (CharacterTag) tag; + replaceCharacter(characterTag.getCharacterId(), id++); + } + } + // then set them to 1,2,3... + id = 1; + for (Tag tag : getTags()) { + if (tag instanceof CharacterTag) { + CharacterTag characterTag = (CharacterTag) tag; + replaceCharacter(characterTag.getCharacterId(), id++); + } + } + } + + public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { + boolean modified = false; + for (Tag tag : getTags()) { + boolean modified2 = false; + if (tag instanceof CharacterIdTag) { + CharacterIdTag characterIdTag = (CharacterIdTag) tag; + if (characterIdTag.getCharacterId() == oldCharacterId) { + characterIdTag.setCharacterId(newCharacterId); + modified2 = true; + } + } + modified2 |= tag.replaceCharacter(oldCharacterId, newCharacterId); + if (modified2) { + tag.setModified(true); + } + modified |= modified2; + } + return modified; + } + + public void replaceCharacterTags(CharacterTag characterTag, int newCharacterId) { + int characterId = characterTag.getCharacterId(); + CharacterTag newCharacter = getCharacter(newCharacterId); + newCharacter.setCharacterId(characterId); + characterTag.setCharacterId(newCharacterId); + newCharacter.setModified(true); + characterTag.setModified(true); + + assignExportNamesToSymbols(); + assignClassesToSymbols(); + clearImageCache(); + updateCharacters(); + } + + @Override + public String toString() { + return getShortFileName(); + } + + public void deobfuscate(DeobfuscationLevel level) throws InterruptedException { + List atags = getAbcList(); + + for (ABCContainerTag tag : atags) { + if (level == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE) { + tag.getABC().removeDeadCode(); + } else if (level == DeobfuscationLevel.LEVEL_REMOVE_TRAPS) { + tag.getABC().removeTraps(); + } else if (level == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW) { + tag.getABC().removeTraps(); + } + + ((Tag) tag).setModified(true); + } + } + + /** + * Enables debugging. Adds tags to enable debugging and optinally injects + * debugline and debugfile instructions to AS3 code by decompiling it first + * + * @param injectAS3Code Modify AS3 code with debugfile / debugline ? + * @param decompileDir Directory to virtual decompile (will affect + * debugfile) + */ + public void enableDebugging(boolean injectAS3Code, File decompileDir) { + enableDebugging(injectAS3Code, decompileDir, false); + } + + /** + * Enables debugging. Adds tags to enable debugging. + */ + public void enableDebugging() { + enableDebugging(false, null, false); + } + + /** + * Enables debugging. Adds tags to enable debugging and injects debugline + * and debugfile instructions to AS3 code. Optionally enables Telemetry + * + * @param injectAS3Code Modify AS3 code with debugfile / debugline ? + * @param decompileDir Directory to virtual decompile (will affect + * debugfile) + * @param telemetry Enable telemetry info? + */ + public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry) { + enableDebugging(injectAS3Code, decompileDir, telemetry, false); + } + + /** + * Injects debugline and debugfile instructions to AS3 P-code (lines of + * P-code) + */ + public void injectAS3PcodeDebugInfo() { + List packs = getAS3Packs(); + for (ScriptPack s : packs) { + int abcIndex = s.allABCs.indexOf(s.abc); + if (s.isSimple) { + s.injectPCodeDebugInfo(abcIndex); + } + } + } + + /** + * Injects debugline and debugfile instructions to AS3 code + * + * @param decompileDir Directory to set file information paths + */ + public void injectAS3DebugInfo(File decompileDir) { + List packs = getAS3Packs(); + for (ScriptPack s : packs) { + if (s.isSimple) { + s.injectDebugInfo(decompileDir); + } + } + } + + /** + * Enables debugging. Adds tags to enable debugging and injects debugline + * and debugfile instructions to AS3 code. Optionally enables Telemetry + * + * @param injectAS3Code Modify AS3 code with debugfile / debugline ? + * @param decompileDir Directory to virtual decompile (will affect + * debugfile) + * @param telemetry Enable telemetry info? + * @param pcodeLevel inject Pcode lines instead of decompiled lines + */ + public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry, boolean pcodeLevel) { + + if (injectAS3Code) { + if (pcodeLevel) { + injectAS3PcodeDebugInfo(); + } else { + injectAS3DebugInfo(decompileDir); + } + } + + int pos = 0; + + boolean hasEnabled = false; + + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if (t instanceof MetadataTag) { + pos = i + 1; + } + if (t instanceof FileAttributesTag) { + pos = i + 1; + } + if (version >= 6 && (t instanceof EnableDebugger2Tag)) { + hasEnabled = true; + break; + } + if (version == 5 && (t instanceof EnableDebuggerTag)) { + hasEnabled = true; + break; + } + if (version < 5 && (t instanceof ProtectTag)) { + hasEnabled = true; + break; + } + } + + if (!hasEnabled) { + if (version >= 6) { + tags.add(pos, new EnableDebugger2Tag(this)); + } else if (version == 5) { + tags.add(pos, new EnableDebuggerTag(this)); + } else { + tags.add(pos, new ProtectTag(this)); + } + } + + getOrAddDebugId(); + } + + /** + * Finds DebugID tag + * + * @return the tag or null if not found + */ + public DebugIDTag getDebugId() { + for (Tag t : getTags()) { + if (t instanceof DebugIDTag) { + return (DebugIDTag) t; + } + } + return null; + } + + /** + * Finds DebugID tag and generates new one if none exists + * + * @return the tag or null if there is not debugging enabled in the swf file + */ + public DebugIDTag getOrAddDebugId() { + DebugIDTag r = getDebugId(); + if (r == null) { + for (int i = 0; i < tags.size(); i++) { + Tag t = tags.get(i); + if ((t instanceof EnableDebuggerTag) || (t instanceof EnableDebugger2Tag)) { + r = new DebugIDTag(this); + tags.add(i + 1, r); + new Random().nextBytes(r.debugId); + break; + } + } + } + return r; + } + + public boolean generatePCodeSwdFile(File file, Map> breakpoints) throws IOException { + DebugIDTag dit = getDebugId(); + if (dit == null) { + return false; + } + List items = new ArrayList<>(); + Map asms = getASMs(true); + + try { + items.add(new SWD.DebugId(dit.debugId)); + + } catch (Throwable t) { + logger.log(Level.SEVERE, "message", t); + return false; + } + + int moduleId = 0; + List names = new ArrayList<>(asms.keySet()); + Collections.sort(names); + for (String name : names) { + moduleId++; + String sname = "#PCODE " + name; + int bitmap = SWD.bitmapAction; + items.add(new SWD.DebugScript(moduleId, bitmap, sname, "")); + + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); + try { + asms.get(name).getASMSource(ScriptExportMode.PCODE, writer, asms.get(name).getActions()); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + List hls = writer.instructionHilights; + + Map offsetToLine = new TreeMap<>(); + String txt = writer.toString(); + txt = txt.replace("\r", ""); + int line = 1; + for (int i = 0; i < txt.length(); i++) { + Highlighting h = Highlighting.searchPos(hls, i); + if (h != null) { + int of = (int) h.getProperties().fileOffset; + if (of > -1 && !offsetToLine.containsKey(of) && !offsetToLine.containsValue(line)) { + offsetToLine.put(of, line); + } + } + if (txt.charAt(i) == '\n') { + line++; + } + } + + for (int ofs : offsetToLine.keySet()) { + items.add(new SWD.DebugOffset(moduleId, offsetToLine.get(ofs), ofs)); + } + + if (breakpoints.containsKey(sname)) { + Set bplines = breakpoints.get(sname); + for (int bpline : bplines) { + if (offsetToLine.containsValue(bpline)) { + try { + SWD.DebugBreakpoint dbp = new SWD.DebugBreakpoint(moduleId, bpline); + items.add(dbp); + } catch (IllegalArgumentException iex) { + logger.log(Level.WARNING, "Cannot generate breakpoint to SWD: {0}", iex.getMessage()); + } + } + } + } + } + + SWD swd = new SWD(7, items); + try (FileOutputStream fis = new FileOutputStream(file)) { + swd.saveTo(fis); + } + return true; + } + + public boolean generateSwdFile(File file, Map> breakpoints) throws IOException { + DebugIDTag dit = getDebugId(); + if (dit == null) { + return false; + } + List items = new ArrayList<>(); + Map asms = getASMs(true); + + try { + items.add(new SWD.DebugId(dit.debugId)); + + int moduleId = 0; + List names = new ArrayList<>(asms.keySet()); + Collections.sort(names); + for (String name : names) { + List regitems = new ArrayList<>(); + moduleId++; + CachedScript cs; + try { + cs = SWF.getCached(asms.get(name), asms.get(name).getActions()); + } catch (InterruptedException ex) { + return false; + } + String txt = cs.text.replace("\r", ""); + int line = 1; + Map lineToOffset = new HashMap<>(); + Map regNames = new HashMap<>(); + + for (int pos = 0; pos < txt.length(); pos++) { + Highlighting h = Highlighting.searchPos(cs.hilights, pos); + if (h != null) { + + int firstLineOffset = (int) h.getProperties().firstLineOffset; + if (firstLineOffset > -1 && h.getProperties().declaration && h.getProperties().regIndex > -1 && (!regNames.containsKey(h.getProperties().regIndex) || !regNames.get(h.getProperties().regIndex).equals(h.getProperties().localName))) { + regNames.put(h.getProperties().regIndex, h.getProperties().localName); + + List curRegIndexes = new ArrayList<>(regNames.keySet()); + List curRegNames = new ArrayList<>(); + for (int i = 0; i < curRegIndexes.size(); i++) { + curRegNames.add(regNames.get(curRegIndexes.get(i))); + } + regitems.add(new SWD.DebugRegisters((int) h.getProperties().firstLineOffset, curRegIndexes, curRegNames)); + } + + if (firstLineOffset != -1 && !lineToOffset.containsKey(line)) { + lineToOffset.put(line, firstLineOffset); + } + } + if (txt.charAt(pos) == '\n') { + line++; + } + } + + Map offSetToLine = new TreeMap<>(); + for (Map.Entry en : lineToOffset.entrySet()) { + offSetToLine.put(en.getValue(), en.getKey()); + } + + //final String NONAME = "[No instance name assigned]"; + String sname = name; + int bitmap = SWD.bitmapAction; + /* Matcher m; + int bitmap = SWD.bitmapAction; + m = Pattern.compile("^\\\\frame_([0-9]+)\\\\DoAction$").matcher(sname); + if (m.matches()) { + //TODO: scenes?, layers? + sname = "Actions for Scene 1: Frame " + m.group(1) + " of Layer Name Layer 1"; + } else if ((m = Pattern.compile("^\\\\__Packages\\\\(.*)$").matcher(sname)).matches()) { + sname = m.group(1).replace("\\", ".") + ": .\\" + m.group(1) + ".as"; + } else { + continue; //FIXME! + } + m = Pattern.compile("^\\\\DefineSprite_([0-9])+\\\\frame_([0-9]+)\\\\DoAction$").matcher(sname); + if (m.matches()) { + //TODO: layers? + //sname = "Actions for Symbol " + m.group(1) + ": Frame " + m.group(2) + " of Layer Name Layer 1"; + continue; //FIXME! + } + + //TODO: handle onxxx together ? + m = Pattern.compile("^\\\\DefineButton2?_([0-9]+)\\\\on\\(.*$").matcher(sname); + if (m.matches()) { + //bitmap = SWD.bitmapOnAction; + //sname = "Actions for " + NONAME + " (Symbol " + m.group(1) + ")"; + continue; //FIXME! + } + + //TODO: handle onClipEvent together ? + m = Pattern.compile("^\\\\frame_([0-9]+)\\\\PlaceObject[2-3]?_([0-9]+)_[^\\\\]*\\\\onClipEvent\\(.*$").matcher(sname); + if (m.matches()) { + //bitmap = SWD.bitmapOnClipAction; + //sname = "Actions for " + NONAME + " (Symbol " + m.group(2) + ")"; + continue; //FIXME! + }//*/ + + items.add(new SWD.DebugScript(moduleId, bitmap, sname, txt)); + for (int ofs : offSetToLine.keySet()) { + items.add(new SWD.DebugOffset(moduleId, offSetToLine.get(ofs), ofs)); + } + if (breakpoints.containsKey(name)) { + Set bplines = breakpoints.get(name); + for (int bpline : bplines) { + if (lineToOffset.containsKey(bpline)) { + try { + SWD.DebugBreakpoint dbp = new SWD.DebugBreakpoint(moduleId, bpline); + items.add(dbp); + } catch (IllegalArgumentException iex) { + logger.log(Level.WARNING, "Cannot generate breakpoint to SWD: {0}", iex.getMessage()); + } + } + } + } + items.addAll(regitems); + //moduleId++; + } + //items.addAll(swdOffsets); + //items.addAll(swfBps); + + } catch (Throwable t) { + logger.log(Level.SEVERE, "message", t); + return false; + } + SWD swd = new SWD(7, items); + try (FileOutputStream fis = new FileOutputStream(file)) { + swd.saveTo(fis); + } + return true; + } + + public boolean enableTelemetry(String password) { + + EnableTelemetryTag et = getEnableTelemetry(); + + if (et == null) { + FileAttributesTag fat = getFileAttributes(); + if (fat == null) { + return false; + } + int insertTo = tags.indexOf(fat) + 1; + MetadataTag mt = getMetadata(); + if (mt != null) { + insertTo = tags.indexOf(mt) + 1; + } + + et = new EnableTelemetryTag(this); + tags.add(insertTo, et); + } + et.setPassword(password); + //TODO: SWFs with tag 92 (signed) are unsupported + return true; + } + + public String getFlexMainClass(List ignoredClasses, List ignoredNs) { + String documentClass = getDocumentClass(); + + ScriptPack documentPack = null; + for (ScriptPack item : getAS3Packs()) { + if (item.getClassPath().toString().equals(documentClass)) { + documentPack = item; + break; + } + } + + if (documentPack != null) { + if (!documentPack.traitIndices.isEmpty()) { + Trait firstTrait = documentPack.abc.script_info.get(documentPack.scriptIndex).traits.traits.get(documentPack.traitIndices.get(0)); + if (firstTrait instanceof TraitClass) { + int cindex = ((TraitClass) firstTrait).class_info; + Multiname superName = documentPack.abc.constants.getMultiname(documentPack.abc.instance_info.get(cindex).super_index); + String parentClass = superName.getNameWithNamespace(documentPack.abc.constants).toRawString(); + if ("mx.managers.SystemManager".equals(parentClass)) { + for (Trait t : documentPack.abc.instance_info.get(cindex).instance_traits.traits) { + if ((t instanceof TraitMethodGetterSetter) && "info".equals(t.getName(documentPack.abc).getName(documentPack.abc.constants, new ArrayList<>(), true))) { + + int mi = ((TraitMethodGetterSetter) t).method_info; + try { + documentPack.abc.findBody(mi).convert(new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); + List infos = documentPack.abc.findBody(mi).convertedItems; + if (!infos.isEmpty()) { + if (infos.get(0) instanceof IfItem) { + IfItem ift = ((IfItem) infos.get(0)); + if (!ift.onTrue.isEmpty()) { + if (ift.onTrue.get(0) instanceof InitPropertyAVM2Item) { + if (ift.onTrue.get(0).value instanceof NewObjectAVM2Item) { + NewObjectAVM2Item no = (NewObjectAVM2Item) ift.onTrue.get(0).value; + List compiledLocales = new ArrayList<>(); + List compiledResourceBundleNames = new ArrayList<>(); + List mixins = new ArrayList<>(); + String mainClassName = null; + //currentDomain,preloader + /*double width = 0; + double height = 0; + */ + for (NameValuePair nvp : no.pairs) { + if (nvp.name instanceof StringAVM2Item) { + String n = ((StringAVM2Item) nvp.name).getValue(); + switch (n) { + case "compiledLocales": + if (nvp.value instanceof NewArrayAVM2Item) { + NewArrayAVM2Item na = (NewArrayAVM2Item) nvp.value; + for (GraphTargetItem tv : na.values) { + compiledLocales.add("" + tv.getResult()); + } + } + break; + case "compiledResourceBundleNames": + if (nvp.value instanceof NewArrayAVM2Item) { + NewArrayAVM2Item na = (NewArrayAVM2Item) nvp.value; + for (GraphTargetItem tv : na.values) { + compiledResourceBundleNames.add("" + tv.getResult()); + } + } + break; + case "mixins": + if (nvp.value instanceof NewArrayAVM2Item) { + NewArrayAVM2Item na = (NewArrayAVM2Item) nvp.value; + for (GraphTargetItem tv : na.values) { + mixins.add("" + tv.getResult()); + } + } + break; + /*case "width": + width = Double.parseDouble("" + nvp.value.getResult()); + break; + case "height": + height = Double.parseDouble("" + nvp.value.getResult()); + break;*/ + case "mainClassName": + mainClassName = "" + nvp.value.getResult(); + break; + } + } + } + + ignoredClasses.add(documentClass); + for (String loc : compiledLocales) { + ignoredClasses.add(loc + "$" + "controls" + "_properties"); + for (String res : compiledResourceBundleNames) { + ignoredClasses.add(loc + "$" + res + "_properties"); + } + } + ignoredClasses.addAll(mixins); + + //find internal classes used in mixins + for (ScriptPack p : getAS3Packs()) { + for (String m : mixins) { + if (m.equals(p.getClassPath().toRawString())) { + for (int ti : p.traitIndices) { + Trait tr = p.abc.script_info.get(p.scriptIndex).traits.traits.get(ti); + if (tr instanceof TraitClass) { + int ci = ((TraitClass) tr).class_info; + int cinit = p.abc.class_info.get(ci).cinit_index; + p.abc.findBody(cinit).convert(new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); + List cinitBody = p.abc.findBody(cinit).convertedItems; + for (GraphTargetItem cit : cinitBody) { + if (cit instanceof SetPropertyAVM2Item) { + if (cit.value instanceof GetLexAVM2Item) { + GetLexAVM2Item gl = (GetLexAVM2Item) cit.value; + ignoredClasses.add(gl.propertyName.getNameWithNamespace(p.abc.constants).toRawString()); + } + } + } + } + } + } + } + } + ignoredNs.add("mx"); + ignoredNs.add("spark"); + ignoredNs.add("flashx"); + return mainClassName; + } + } + } + } + } + } catch (InterruptedException e) { + //ignore + } + } + } + } + } + } + } + return null; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java index f2baed8e0..67584ea52 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java @@ -1,157 +1,157 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.MemoryInputStream; -import com.jpexs.helpers.PosMarkedInputStream; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.Searchable; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public class SWFSearch { - - protected Searchable s; - - private final boolean noCheck; - - private final SearchMode searchMode; - - private boolean processed = false; - - private final Set listeners = new HashSet<>(); - - private final Map swfStreams = new HashMap<>(); - - public SWFSearch(Searchable s, boolean noCheck, SearchMode searchMode) { - this.s = s; - this.noCheck = noCheck; - this.searchMode = searchMode; - } - - public void addProgressListener(ProgressListener l) { - listeners.add(l); - } - - public void removeProgressListener(ProgressListener l) { - listeners.remove(l); - } - - private void setProgress(int p) { - for (ProgressListener l : listeners) { - l.progress(p); - } - } - - public void process() { - Map ret; - ret = s.search(new ProgressListener() { - @Override - public void progress(int p) { - setProgress(p); - } - }, - "FWS".getBytes(), // Uncompressed Flash - "CWS".getBytes(), // ZLib compressed Flash - "ZWS".getBytes(), // LZMA compressed Flash - "GFX".getBytes(), // Uncompressed ScaleForm GFx - "CFX".getBytes()); // Compressed ScaleForm GFx - int pos = 0; - long biggestSize = 0; - long smallestSize = Long.MAX_VALUE; - addressLoop: - for (Long addr : ret.keySet()) { - setProgress(pos * 100 / ret.size()); - pos++; - try { - MemoryInputStream mis = (MemoryInputStream) ret.get(addr); - mis.reset(); - PosMarkedInputStream pmi = new PosMarkedInputStream(mis); - SWF swf = noCheck ? new SWF(pmi) : new SWF(pmi, null, null, null, false, true, true); - boolean valid = swf.fileSize > 0 - && swf.version > 0 - && (!swf.getTags().isEmpty() || noCheck) - && swf.version <= SWF.MAX_VERSION; - if (valid) { - long limit = pmi.getPos(); - MemoryInputStream is = new MemoryInputStream(mis.getAllRead(), (int) (long) addr, (int) limit); - switch (searchMode) { - case ALL: - swfStreams.put(addr, is); - break; - case BIGGEST: - if (limit > biggestSize) { - biggestSize = limit; - swfStreams.clear(); - swfStreams.put(addr, is); - } - break; - case SMALLEST: - if (limit < smallestSize) { - smallestSize = limit; - swfStreams.clear(); - swfStreams.put(addr, is); - } - break; - case FIRST: - swfStreams.put(addr, is); - break addressLoop; - case LAST: - swfStreams.clear(); - swfStreams.put(addr, is); - break; - } - } - } catch (OutOfMemoryError ome) { - Helper.freeMem(); - } catch (Exception | Error ex) { - } - } - setProgress(100); - processed = true; - } - - public MemoryInputStream get(ProgressListener listener, long address) throws IOException { - if (!processed) { - return null; - } - if (!swfStreams.containsKey(address)) { - return null; - } - return swfStreams.get(address); - } - - public Set getAddresses() { - return swfStreams.keySet(); - } - - public int length() { - if (!processed) { - return 0; - } - return swfStreams.size(); - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.MemoryInputStream; +import com.jpexs.helpers.PosMarkedInputStream; +import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.Searchable; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * + * @author JPEXS + */ +public class SWFSearch { + + protected Searchable s; + + private final boolean noCheck; + + private final SearchMode searchMode; + + private boolean processed = false; + + private final Set listeners = new HashSet<>(); + + private final Map swfStreams = new HashMap<>(); + + public SWFSearch(Searchable s, boolean noCheck, SearchMode searchMode) { + this.s = s; + this.noCheck = noCheck; + this.searchMode = searchMode; + } + + public void addProgressListener(ProgressListener l) { + listeners.add(l); + } + + public void removeProgressListener(ProgressListener l) { + listeners.remove(l); + } + + private void setProgress(int p) { + for (ProgressListener l : listeners) { + l.progress(p); + } + } + + public void process() { + Map ret; + ret = s.search(new ProgressListener() { + @Override + public void progress(int p) { + setProgress(p); + } + }, + "FWS".getBytes(), // Uncompressed Flash + "CWS".getBytes(), // ZLib compressed Flash + "ZWS".getBytes(), // LZMA compressed Flash + "GFX".getBytes(), // Uncompressed ScaleForm GFx + "CFX".getBytes()); // Compressed ScaleForm GFx + int pos = 0; + long biggestSize = 0; + long smallestSize = Long.MAX_VALUE; + addressLoop: + for (Long addr : ret.keySet()) { + setProgress(pos * 100 / ret.size()); + pos++; + try { + MemoryInputStream mis = (MemoryInputStream) ret.get(addr); + mis.reset(); + PosMarkedInputStream pmi = new PosMarkedInputStream(mis); + SWF swf = noCheck ? new SWF(pmi) : new SWF(pmi, null, null, null, false, true, true); + boolean valid = swf.fileSize > 0 + && swf.version > 0 + && (!swf.getTags().isEmpty() || noCheck) + && swf.version <= SWF.MAX_VERSION; + if (valid) { + long limit = pmi.getPos(); + MemoryInputStream is = new MemoryInputStream(mis.getAllRead(), (int) (long) addr, (int) limit); + switch (searchMode) { + case ALL: + swfStreams.put(addr, is); + break; + case BIGGEST: + if (limit > biggestSize) { + biggestSize = limit; + swfStreams.clear(); + swfStreams.put(addr, is); + } + break; + case SMALLEST: + if (limit < smallestSize) { + smallestSize = limit; + swfStreams.clear(); + swfStreams.put(addr, is); + } + break; + case FIRST: + swfStreams.put(addr, is); + break addressLoop; + case LAST: + swfStreams.clear(); + swfStreams.put(addr, is); + break; + } + } + } catch (OutOfMemoryError ome) { + Helper.freeMem(); + } catch (Exception | Error ex) { + } + } + setProgress(100); + processed = true; + } + + public MemoryInputStream get(ProgressListener listener, long address) throws IOException { + if (!processed) { + return null; + } + if (!swfStreams.containsKey(address)) { + return null; + } + return swfStreams.get(address); + } + + public Set getAddresses() { + return swfStreams.keySet(); + } + + public int length() { + if (!processed) { + return 0; + } + return swfStreams.size(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 3dca8d4e0..e4189d543 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1,2911 +1,2911 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2; - -import com.jpexs.decompiler.flash.EndOfStreamException; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ABCInputStream; -import com.jpexs.decompiler.flash.abc.CopyOutputStream; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorGetSet; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorRegistersOld; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorSimpleOld; -import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException; -import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2VerifyErrorException; -import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph; -import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphSource; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2InstructionFlag; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.UnknownInstruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf64Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li16Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li8Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf64Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si16Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si8Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi16Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi1Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi8Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DivideIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitNotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewActivationIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewArrayIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewClassIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewObjectIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugFileIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallMethodIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropLexIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallStaticIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfEqIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfGeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfGtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfLeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfLtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNGeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNGtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNLeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNLtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal0Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal1Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal2Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal3Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal0Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal1Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal2Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal3Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.DeletePropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindDefIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetDescendantsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNextIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InitPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextNameIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextValueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetGlobalSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AbsJumpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AddDIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AddPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AllocIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.BkptIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.BkptLineIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CallInterfaceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CallSuperIdIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CodeGenOpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceBIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceDIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceOIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceUIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConcatIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertF4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertFIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertMIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertMPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecLocalPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecodeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecrementPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DelDescendantsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DeletePropertyLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DividePIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DoubleToAtomIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.FindPropGlobalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.GetOuterScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncLocalPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncrementPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.InvalidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.Lf32x4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.MarkIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ModuloPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.MultiplyPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.NegatePIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PrologueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushConstantIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushDNanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushDecimalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushFloat4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushFloatIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SendEnterIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SetPropertyLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.Sf32x4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SubtractPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SweepIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.TimestampIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.UnPlusIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.VerifyOpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.VerifyPassIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.WbIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNamespaceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ApplyTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertBIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertDIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertOIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertUIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.InstanceOfIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.TypeOfIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.CheckFilterIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXAttrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXElemIns; -import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; -import com.jpexs.decompiler.flash.abc.types.ABCException; -import com.jpexs.decompiler.flash.abc.types.AssignedValue; -import com.jpexs.decompiler.flash.abc.types.ConvertData; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.ValueKind; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.dumpview.DumpInfo; -import com.jpexs.decompiler.flash.ecma.Undefined; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import com.jpexs.decompiler.graph.Block; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.SimpleValue; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.TypeItem; -import com.jpexs.decompiler.graph.model.BinaryOpItem; -import com.jpexs.decompiler.graph.model.ExitItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.ScriptEndItem; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.ReflectionTools; -import com.jpexs.helpers.stat.Statistics; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public class AVM2Code implements Cloneable { - - private static final Logger logger = Logger.getLogger(AVM2Code.class.getName()); - - private static final boolean DEBUG_MODE = false; - - public static int toSourceLimit = -1; - - public List code; - - public static boolean DEBUG_REWRITE = false; - - public static final int OPT_U30 = 0x100; - - public static final int OPT_U8 = 0x200; - - public static final int OPT_S24 = 0x300; - - public static final int OPT_CASE_OFFSETS = 0x400; - - public static final int OPT_S8 = 0x500; - - public static final int OPT_S16 = 0x600; - - public static final int DAT_MULTINAME_INDEX = OPT_U30 + 0x01; - - public static final int DAT_ARG_COUNT = OPT_U30 + 0x02; - - public static final int DAT_METHOD_INDEX = OPT_U30 + 0x03; - - public static final int DAT_STRING_INDEX = OPT_U30 + 0x04; - - public static final int DAT_DEBUG_TYPE = OPT_U8 + 0x05; - - public static final int DAT_REGISTER_INDEX = OPT_U8 + 0x06; - - public static final int DAT_LINENUM = OPT_U30 + 0x07; - - public static final int DAT_LOCAL_REG_INDEX = OPT_U30 + 0x08; - - public static final int DAT_SLOT_INDEX = OPT_U30 + 0x09; - - public static final int DAT_SCOPE_INDEX = OPT_U30 + 0x0A; - - public static final int DAT_OFFSET = OPT_S24 + 0x0B; - - public static final int DAT_EXCEPTION_INDEX = OPT_U30 + 0x0C; - - public static final int DAT_CLASS_INDEX = OPT_U30 + 0x0D; - - public static final int DAT_INT_INDEX = OPT_U30 + 0x0E; - - public static final int DAT_UINT_INDEX = OPT_U30 + 0x0F; - - public static final int DAT_DOUBLE_INDEX = OPT_U30 + 0x10; - - public static final int DAT_DECIMAL_INDEX = OPT_U30 + 0x11; - - public static final int DAT_CASE_BASEOFFSET = OPT_S24 + 0x12; - - public static final int DAT_NUMBER_CONTEXT = OPT_U30 + 0x13; - - public static final int DAT_DISPATCH_ID = OPT_U30 + 0x14; - - public static final int DAT_FLOAT_INDEX = OPT_U30 + 0x15; - - public static final int DAT_FLOAT4_INDEX = OPT_U30 + 0x16; - - public static final int DAT_NAMESPACE_INDEX = OPT_U30 + 0x17; - - public static String operandTypeSizeToString(int ot) { - int sizeType = ot & 0xff00; - switch (sizeType) { - case OPT_U30: - return "U30"; - case OPT_S16: - return "S16"; - case OPT_U8: - return "U8"; - case OPT_S8: - return "S8"; - case OPT_S24: - return "S24"; - case OPT_CASE_OFFSETS: - return "S24(=n), S24[n]"; - } - return ""; - } - - private static Map operandDataTypeIdentifiers = ReflectionTools.getConstNamesMap(AVM2Code.class, Integer.class, "^DAT_(.*)$"); - - public static String operandTypeToString(int ot, boolean withTypeSize) { - String typeSize = operandTypeSizeToString(ot); - if (ot == OPT_CASE_OFFSETS) { - return "number" + (withTypeSize ? "(U30)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", ..."; - } - if (operandDataTypeIdentifiers.containsKey(ot)) { - String dataType = operandDataTypeIdentifiers.get(ot); - return dataType + (withTypeSize ? "(" + typeSize + ")" : ""); - } else { - return typeSize; - } - - } - - public static final InstructionDefinition[] instructionSet = new InstructionDefinition[256]; - - public static final InstructionDefinition[] allInstructionSet = new InstructionDefinition[]{ - /*0x00*/null, - /*0x01*/ new BkptIns(), - /*0x02*/ new NopIns(), - /*0x03*/ new ThrowIns(), - /*0x04*/ new GetSuperIns(), - /*0x05*/ new SetSuperIns(), - /*0x06*/ new DXNSIns(), - /*0x07*/ new DXNSLateIns(), - /*0x08*/ new KillIns(), - /*0x09*/ new LabelIns(), - /*0x0A*/ new Lf32x4Ins(), - /*0x0B*/ new Sf32x4Ins(), - /*0x0C*/ new IfNLtIns(), - /*0x0D*/ new IfNLeIns(), - /*0x0E*/ new IfNGtIns(), - /*0x0F*/ new IfNGeIns(), - /*0x10*/ new JumpIns(), - /*0x11*/ new IfTrueIns(), - /*0x12*/ new IfFalseIns(), - /*0x13*/ new IfEqIns(), - /*0x14*/ new IfNeIns(), - /*0x15*/ new IfLtIns(), - /*0x16*/ new IfLeIns(), - /*0x17*/ new IfGtIns(), - /*0x18*/ new IfGeIns(), - /*0x19*/ new IfStrictEqIns(), - /*0x1A*/ new IfStrictNeIns(), - /*0x1B*/ new LookupSwitchIns(), - /*0x1C*/ new PushWithIns(), - /*0x1D*/ new PopScopeIns(), - /*0x1E*/ new NextNameIns(), - /*0x1F*/ new HasNextIns(), - /*0x20*/ new PushNullIns(), - /*0x21*/ new PushUndefinedIns(), - /*0x22*/ new PushFloatIns(), //major 47+ - /*0x22*/ new PushConstantIns(), //before major 47 - /*0x23*/ new NextValueIns(), - /*0x24*/ new PushByteIns(), - /*0x25*/ new PushShortIns(), - /*0x26*/ new PushTrueIns(), - /*0x27*/ new PushFalseIns(), - /*0x28*/ new PushNanIns(), - /*0x29*/ new PopIns(), - /*0x2A*/ new DupIns(), - /*0x2B*/ new SwapIns(), - /*0x2C*/ new PushStringIns(), - /*0x2D*/ new PushIntIns(), - /*0x2E*/ new PushUIntIns(), - /*0x2F*/ new PushDoubleIns(), - /*0x30*/ new PushScopeIns(), - /*0x31*/ new PushNamespaceIns(), - /*0x32*/ new HasNext2Ins(), - /*0x33*/ new PushDecimalIns(), //pushdecimal(minor 17), lix8 (internal-only) according to Tamarin - /*0x34*/ new PushDNanIns(), //pushdnan according to Flex SDK, lix16 (internal-only) according to Tamarin - /*0x35*/ new Li8Ins(), - /*0x36*/ new Li16Ins(), - /*0x37*/ new Li32Ins(), - /*0x38*/ new Lf32Ins(), - /*0x39*/ new Lf64Ins(), - /*0x3A*/ new Si8Ins(), - /*0x3B*/ new Si16Ins(), - /*0x3C*/ new Si32Ins(), - /*0x3D*/ new Sf32Ins(), - /*0x3E*/ new Sf64Ins(), - /*0x3F*/ null, - /*0x40*/ new NewFunctionIns(), - /*0x41*/ new CallIns(), - /*0x42*/ new ConstructIns(), - /*0x43*/ new CallMethodIns(), - /*0x44*/ new CallStaticIns(), - /*0x45*/ new CallSuperIns(), - /*0x46*/ new CallPropertyIns(), - /*0x47*/ new ReturnVoidIns(), - /*0x48*/ new ReturnValueIns(), - /*0x49*/ new ConstructSuperIns(), - /*0x4A*/ new ConstructPropIns(), - /*0x4B*/ new CallSuperIdIns(), - /*0x4C*/ new CallPropLexIns(), - /*0x4D*/ new CallInterfaceIns(), - /*0x4E*/ new CallSuperVoidIns(), - /*0x4F*/ new CallPropVoidIns(), - /*0x50*/ new Sxi1Ins(), - /*0x51*/ new Sxi8Ins(), - /*0x52*/ new Sxi16Ins(), - /*0x53*/ new ApplyTypeIns(), - /*0x54*/ new PushFloat4Ins(), //major 47+ - /*0x55*/ new NewObjectIns(), - /*0x56*/ new NewArrayIns(), - /*0x57*/ new NewActivationIns(), - /*0x58*/ new NewClassIns(), - /*0x59*/ new GetDescendantsIns(), - /*0x5A*/ new NewCatchIns(), - /*0x5B*/ new DelDescendantsIns(), //deldescendants according to Flex, findpropglobalstrict(internal-only) according to Tamarin - /*0x5C*/ new FindPropGlobalIns(), //Tamarin (internal-only) - /*0x5D*/ new FindPropertyStrictIns(), - /*0x5E*/ new FindPropertyIns(), - /*0x5F*/ new FindDefIns(), - /*0x60*/ new GetLexIns(), - /*0x61*/ new SetPropertyIns(), - /*0x62*/ new GetLocalIns(), - /*0x63*/ new SetLocalIns(), - /*0x64*/ new GetGlobalScopeIns(), - /*0x65*/ new GetScopeObjectIns(), - /*0x66*/ new GetPropertyIns(), - /*0x67*/ new GetOuterScopeIns(), // new GetPropertyLateIns() - /*0x68*/ new InitPropertyIns(), - /*0x69*/ new SetPropertyLateIns(), - /*0x6A*/ new DeletePropertyIns(), - /*0x6B*/ new DeletePropertyLateIns(), - /*0x6C*/ new GetSlotIns(), - /*0x6D*/ new SetSlotIns(), - /*0x6E*/ new GetGlobalSlotIns(), - /*0x6F*/ new SetGlobalSlotIns(), - /*0x70*/ new ConvertSIns(), - /*0x71*/ new EscXElemIns(), - /*0x72*/ new EscXAttrIns(), - /*0x73*/ new ConvertIIns(), - /*0x74*/ new ConvertUIns(), - /*0x75*/ new ConvertDIns(), - /*0x76*/ new ConvertBIns(), - /*0x77*/ new ConvertOIns(), - /*0x78*/ new CheckFilterIns(), - /*0x79*/ new ConvertMIns(), //minor 17 (Flex) - /*0x79*/ new ConvertFIns(), //major 47+, SWF 15+ - /*0x7A*/ new ConvertMPIns(), //minor 17 (Flex) - /*0x7A*/ new UnPlusIns(), //major 47+, SWF 15+ - /*0x7B*/ new ConvertF4Ins(), //major 47+, SWF 15+ - /*0x7C*/ null, - /*0x7D*/ null, - /*0x7E*/ null, - /*0x7F*/ null, - /*0x80*/ new CoerceIns(), - /*0x81*/ new CoerceBIns(), - /*0x82*/ new CoerceAIns(), - /*0x83*/ new CoerceIIns(), - /*0x84*/ new CoerceDIns(), - /*0x85*/ new CoerceSIns(), - /*0x86*/ new AsTypeIns(), - /*0x87*/ new AsTypeLateIns(), - /*0x88*/ new CoerceUIns(), - /*0x89*/ new CoerceOIns(), - /*0x8A*/ null, - /*0x8B*/ null, - /*0x8C*/ null, - /*0x8D*/ null, - /*0x8E*/ null, - /*0x8F*/ new NegatePIns(), - /*0x90*/ new NegateIns(), - /*0x91*/ new IncrementIns(), - /*0x92*/ new IncLocalIns(), - /*0x93*/ new DecrementIns(), - /*0x94*/ new DecLocalIns(), - /*0x95*/ new TypeOfIns(), - /*0x96*/ new NotIns(), - /*0x97*/ new BitNotIns(), - /*0x98*/ null, - /*0x99*/ null, - /*0x9A*/ new ConcatIns(), - /*0x9B*/ new AddDIns(), - /*0x9C*/ new IncrementPIns(), - /*0x9D*/ new IncLocalPIns(), - /*0x9E*/ new DecrementPIns(), - /*0x9F*/ new DecLocalPIns(), - /*0xA0*/ new AddIns(), - /*0xA1*/ new SubtractIns(), - /*0xA2*/ new MultiplyIns(), - /*0xA3*/ new DivideIns(), - /*0xA4*/ new ModuloIns(), - /*0xA5*/ new LShiftIns(), - /*0xA6*/ new RShiftIns(), - /*0xA7*/ new URShiftIns(), - /*0xA8*/ new BitAndIns(), - /*0xA9*/ new BitOrIns(), - /*0xAA*/ new BitXorIns(), - /*0xAB*/ new EqualsIns(), - /*0xAC*/ new StrictEqualsIns(), - /*0xAD*/ new LessThanIns(), - /*0xAE*/ new LessEqualsIns(), - /*0xAF*/ new GreaterThanIns(), - /*0xB0*/ new GreaterEqualsIns(), - /*0xB1*/ new InstanceOfIns(), - /*0xB2*/ new IsTypeIns(), - /*0xB3*/ new IsTypeLateIns(), - /*0xB4*/ new InIns(), - /*0xB5*/ new AddPIns(), - /*0xB6*/ new SubtractPIns(), - /*0xB7*/ new MultiplyPIns(), - /*0xB8*/ new DividePIns(), - /*0xB9*/ new ModuloPIns(), - /*0xBA*/ null, - /*0xBB*/ null, - /*0xBC*/ null, - /*0xBD*/ null, - /*0xBE*/ null, - /*0xBF*/ null, - /*0xC0*/ new IncrementIIns(), - /*0xC1*/ new DecrementIIns(), - /*0xC2*/ new IncLocalIIns(), - /*0xC3*/ new DecLocalIIns(), - /*0xC4*/ new NegateIIns(), - /*0xC5*/ new AddIIns(), - /*0xC6*/ new SubtractIIns(), - /*0xC7*/ new MultiplyIIns(), - /*0xC8*/ null, - /*0xC9*/ null, - /*0xCA*/ null, - /*0xCB*/ null, - /*0xCC*/ null, - /*0xCD*/ null, - /*0xCE*/ null, - /*0xCF*/ null, - /*0xD0*/ new GetLocal0Ins(), - /*0xD1*/ new GetLocal1Ins(), - /*0xD2*/ new GetLocal2Ins(), - /*0xD3*/ new GetLocal3Ins(), - /*0xD4*/ new SetLocal0Ins(), - /*0xD5*/ new SetLocal1Ins(), - /*0xD6*/ new SetLocal2Ins(), - /*0xD7*/ new SetLocal3Ins(), - /*0xD8*/ null, - /*0xD9*/ null, - /*0xDA*/ null, - /*0xDB*/ null, - /*0xDC*/ null, - /*0xDD*/ null, - /*0xDE*/ null, - /*0xDF*/ null, - /*0xE0*/ null, - /*0xE1*/ null, - /*0xE2*/ null, - /*0xE3*/ null, - /*0xE4*/ null, - /*0xE5*/ null, - /*0xE6*/ null, - /*0xE7*/ null, - /*0xE8*/ null, - /*0xE9*/ null, - /*0xEA*/ null, - /*0xEB*/ null, - /*0xEC*/ null, - /*0xED*/ new InvalidIns(), - /*0xEE*/ new AbsJumpIns(), - /*0xEF*/ new DebugIns(), - /*0xF0*/ new DebugLineIns(), - /*0xF1*/ new DebugFileIns(), - /*0xF2*/ new BkptLineIns(), - /*0xF3*/ new TimestampIns(), - /*0xF4*/ null, - /*0xF5*/ new VerifyPassIns(), - /*0xF6*/ new AllocIns(), - /*0xF7*/ new MarkIns(), - /*0xF8*/ new WbIns(), - /*0xF9*/ new PrologueIns(), - /*0xFA*/ new SendEnterIns(), - /*0xFB*/ new DoubleToAtomIns(), - /*0xFC*/ new SweepIns(), - /*0xFD*/ new CodeGenOpIns(), - /*0xFE*/ new VerifyOpIns(), - /*0xFF*/ new DecodeIns(),}; - // endoflist - - static { - - for (int i = 0; i < allInstructionSet.length; i++) { - if (allInstructionSet[i] != null) { - int opCode = allInstructionSet[i].instructionCode; - if (instructionSet[opCode] == null) { - instructionSet[opCode] = allInstructionSet[i]; - } else if (instructionSet[opCode].hasFlag(AVM2InstructionFlag.NO_FLASH_PLAYER) && !allInstructionSet[i].hasFlag(AVM2InstructionFlag.NO_FLASH_PLAYER)) { - instructionSet[opCode] = allInstructionSet[i]; - } //Prefer without decimal: - else if (instructionSet[opCode].hasFlag(AVM2InstructionFlag.ES4_NUMERICS_MINOR) && !allInstructionSet[i].hasFlag(AVM2InstructionFlag.ES4_NUMERICS_MINOR)) { - instructionSet[opCode] = allInstructionSet[i]; - } //Prefer without float: - else if (instructionSet[opCode].hasFlag(AVM2InstructionFlag.FLOAT_MAJOR) && !allInstructionSet[i].hasFlag(AVM2InstructionFlag.FLOAT_MAJOR)) { - instructionSet[opCode] = allInstructionSet[i]; - } - } - } - - for (int i = 0; - i < instructionSet.length; - i++) { - if (instructionSet[i] == null) { - instructionSet[i] = new UnknownInstruction(i); - } - } - - } - - public static final String IDENTOPEN = "/*IDENTOPEN*/"; - - public static final String IDENTCLOSE = "/*IDENTCLOSE*/"; - - public AVM2Code() { - code = new ArrayList<>(); - } - - public AVM2Code(int capacity) { - code = new ArrayList<>(capacity); - } - - public AVM2Code(ArrayList instructions) { - code = instructions; - } - - public Object execute(HashMap arguments, AVM2ConstantPool constants) throws AVM2ExecutionException { - return execute(arguments, constants, null); - } - - public Object execute(HashMap arguments, AVM2ConstantPool constants, AVM2RuntimeInfo runtimeInfo) throws AVM2ExecutionException { - int pos = 0; - LocalDataArea lda = new LocalDataArea(); - lda.methodName = "methodName"; // todo: needed for VerifyError exception message - lda.localRegisters = arguments; - lda.runtimeInfo = runtimeInfo; - - for (AVM2Instruction ins : code) { - ins.definition.verify(lda, constants, ins); - } - - while (pos < code.size()) { - AVM2Instruction ins = code.get(pos); - if (!ins.definition.execute(lda, constants, ins)) { - return null; - } - - if (lda.jump != null) { - try { - pos = adr2pos(lda.jump); - } catch (ConvertException ex) { - throw new AVM2VerifyErrorException(AVM2VerifyErrorException.BRANCH_TARGET_INVALID_INSTRUCTION, lda.isDebug()); - } - lda.jump = null; - } else { - pos++; - } - - if (lda.returnValue != null) { - return lda.returnValue; - } - } - - return Undefined.INSTANCE; - } - - public void calculateDebugFileLine(ABC abc) { - calculateDebugFileLine(null, 0, 0, abc, new HashSet<>()); - } - - private boolean calculateDebugFileLine(String debugFile, int debugLine, int pos, ABC abc, Set seen) { - while (pos < code.size()) { - AVM2Instruction ins = code.get(pos); - if (seen.contains(pos)) { - return true; - } - - seen.add(pos); - - if (ins.definition instanceof DebugFileIns) { - debugFile = abc.constants.getString(ins.operands[0]); - } - - if (ins.definition instanceof DebugLineIns) { - debugLine = ins.operands[0]; - } - - ins.setFileLine(debugFile, debugLine); - - if (ins.definition instanceof NewFunctionIns) { - //Only analyze NewFunction objects that are not immediately discarded by Pop. - //This avoids bogus functions used in obfuscation or special compilers that can lead to infinite recursion. - if ((pos + 1 < code.size()) && !(code.get(pos + 1).definition instanceof PopIns)) { - MethodBody innerBody = abc.findBody(ins.operands[0]); - if (innerBody != null) { //Ignore functions without body - innerBody.getCode().calculateDebugFileLine(debugFile, debugLine, 0, abc, new HashSet<>()); - } - } - } - - if (ins.definition instanceof ReturnValueIns) { - return true; - } - if (ins.definition instanceof ReturnVoidIns) { - return true; - } - if (ins.definition instanceof JumpIns) { - try { - pos = adr2pos(ins.getTargetAddress()); - continue; - } catch (ConvertException ex) { - return false; - } - } else if (ins.definition instanceof IfTypeIns) { - try { - int newpos = adr2pos(ins.getTargetAddress()); - calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen); - } catch (ConvertException ex) { - return false; - } - } - if (ins.definition instanceof LookupSwitchIns) { - for (int i = 0; i < ins.operands.length; i++) { - if (i == 1) { - continue; - } - try { - int newpos = adr2pos(pos2adr(pos) + ins.operands[i]); - if (!calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen)) { - return false; - } - } catch (ConvertException ex) { - return false; - } - } - } - pos++; - } - return true; - } - - /** - * Removes nonexistent indices to constants from instruction operands. - * - * @param constants - */ - public void removeWrongIndices(AVM2ConstantPool constants) { - for (AVM2Instruction ins : code) { - for (int i = 0; i < ins.definition.operands.length; i++) { - if (ins.definition.operands[i] == DAT_MULTINAME_INDEX && ins.operands[i] >= constants.getMultinameCount()) { - ins.operands[i] = 0; - } - if (ins.definition.operands[i] == DAT_DOUBLE_INDEX && ins.operands[i] >= constants.getDoubleCount()) { - ins.operands[i] = 0; - } - if (ins.definition.operands[i] == DAT_INT_INDEX && ins.operands[i] >= constants.getIntCount()) { - ins.operands[i] = 0; - } - if (ins.definition.operands[i] == DAT_UINT_INDEX && ins.operands[i] >= constants.getUIntCount()) { - ins.operands[i] = 0; - } - if (ins.definition.operands[i] == DAT_STRING_INDEX && ins.operands[i] >= constants.getStringCount()) { - ins.operands[i] = 0; - } - } - } - } - - public AVM2Code(ABCInputStream ais, MethodBody body) throws IOException { - Map codeMap = new HashMap<>(); - DumpInfo diParent = ais.dumpInfo; - List addresses = new ArrayList<>(); - //Do not add new jumps when processing these addresses (unreachable code,etc.) - List unAdresses = new ArrayList<>(); - //Handle lookupswitches at the end - they can be invalid. Handle other instruction first so we can decide lookupswitch to be invalid based on other instructions inside it - //Flashplayer does not check casecount in lookupswitch instruction so the instruction can "be" long and over other instructions - List switchAddresses = new ArrayList<>(); - int availableBytes = ais.available(); - for (int i = 0; i < availableBytes; i++) { - codeMap.put((long) i, new AVM2Instruction(i, AVM2Instructions.Nop, null)); - } - - long startPos = ais.getPosition(); - addresses.add(startPos); - if (body != null) { - for (ABCException e : body.exceptions) { - addresses.add((long) e.start); - addresses.add((long) e.end); - addresses.add((long) e.target); - } - } - - loopaddr: - while (!addresses.isEmpty() || !switchAddresses.isEmpty() || !unAdresses.isEmpty()) { - long address; - boolean isSwitch = false; - boolean handleJumps = true; - if (!addresses.isEmpty()) { - address = addresses.remove(0); - } else if (!switchAddresses.isEmpty()) { - address = switchAddresses.remove(0); - isSwitch = true; - } else { - address = unAdresses.remove(0); - handleJumps = false; - } - if (address < startPos) // no jump outside block - { - continue; - } - try { - ais.seek(address); - while (ais.available() > 0) { - long startOffset = ais.getPosition(); - - if (codeMap.containsKey(startOffset) && !(codeMap.get(startOffset).definition instanceof NopIns)) { - continue loopaddr; - } - - DumpInfo di = ais.newDumpLevel("instruction", "instruction"); - InstructionDefinition instr = null; - try { - int instructionCode = ais.read("instructionCode"); - instr = instructionSet[instructionCode]; - if (instructionCode == AVM2Instructions.LookupSwitch) { - if (!isSwitch) { - switchAddresses.add(startOffset); - continue loopaddr; - } else { - isSwitch = false; - } - } - if (di != null) { - di.name = instr.instructionName; - } - if (instr != null) { - int[] actualOperands = null; - - if (instructionCode == AVM2Instructions.LookupSwitch) { // switch - int firstOperand = ais.readS24("default_offset"); - int case_count = ais.readU30("case_count"); - long afterCasePos = ais.getPosition() + 3 * (case_count + 1); - - boolean invalidSwitch = false; - //If there are already some instructions in the lookupswitch bytes, the lookupswitch is invalid (obfuscation) - for (long a = startOffset; a < afterCasePos; a++) { - if (codeMap.containsKey(a) && (!(codeMap.get(a).definition instanceof NopIns))) { - invalidSwitch = true; - break; - } - } - - long totalBytes = ais.getPosition() + ais.available(); - - //If the lookupswitch case_count are larger than available bytes, the lookupswitch is invalid (obfuscation) - if (afterCasePos > totalBytes) { - invalidSwitch = true; - } - if (invalidSwitch) { - continue loopaddr; - } else { - actualOperands = new int[case_count + 3]; - actualOperands[0] = firstOperand; - actualOperands[1] = case_count; - for (int c = 0; c < case_count + 1; c++) { - actualOperands[2 + c] = ais.readS24("actualOperand"); - } - } - } else if (instr.operands.length > 0) { - actualOperands = new int[instr.operands.length]; - for (int op = 0; op < instr.operands.length; op++) { - switch (instr.operands[op] & 0xff00) { - case OPT_U30: - actualOperands[op] = ais.readU30("operand"); - break; - case OPT_S16: - actualOperands[op] = (short) ais.readU30("operand"); - break; - case OPT_U8: - actualOperands[op] = ais.read("operand"); - break; - case OPT_S8: - actualOperands[op] = (byte) ais.read("operand"); - break; - case OPT_S24: - actualOperands[op] = ais.readS24("operand"); - break; - } - } - } - - AVM2Instruction ai = new AVM2Instruction(startOffset, instr, actualOperands); - long endOffset = ais.getPosition(); - - boolean hasRoom = true; - for (long p = startOffset; p < endOffset; p++) { - if (codeMap.containsKey(p) && !(codeMap.get(p).definition instanceof NopIns)) { - hasRoom = false; - } - } - - //There is no room for this instruction (it is invalid?) - if (!hasRoom) { - continue loopaddr; - } - for (long p = startOffset; p < endOffset; p++) { - codeMap.put(p, ai); - } - - if ((instr instanceof IfTypeIns)) { - if (handleJumps) { - long target = ais.getPosition() + actualOperands[0]; - addresses.add(target); - } else { - actualOperands[0] = 0; - } - } - - if (instr instanceof JumpIns) { - if (handleJumps) { - long target = ais.getPosition() + actualOperands[0]; - addresses.add(target); - unAdresses.add(ais.getPosition()); - continue loopaddr; - } else { - actualOperands[0] = 0; - } - } - - if (instr.isExitInstruction()) { //do not process jumps if there is return/throw instruction - if (handleJumps) { - unAdresses.add(ais.getPosition()); - continue loopaddr; - } - } - if ((instr instanceof LookupSwitchIns) && actualOperands != null) { - if (handleJumps) { - addresses.add(startOffset + actualOperands[0]); - - for (int c = 2; c < actualOperands.length; c++) { - addresses.add(startOffset + actualOperands[c]); - } - unAdresses.add(ais.getPosition()); - continue loopaddr; - } else { - int swlen = (int) (endOffset - startOffset); - actualOperands[0] = swlen; - for (int c = 2; c < actualOperands.length; c++) { - actualOperands[c] = swlen; - } - } - } - - } else { - break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions) - //throw new UnknownInstructionCode(instructionCode); - } - } finally { - if (instr == null) { - ais.endDumpLevel(); - } else { - ais.endDumpLevel(instr.instructionCode); - } - } - } - } catch (EndOfStreamException ex) { - // lookupswitch obfuscation, ignore - ais.endDumpLevelUntil(diParent); - } - } - - if (diParent != null) { - diParent.sortChildren(); - } - - code = new ArrayList<>(codeMap.size()); - AVM2Instruction prev = null; - for (int i = 0; i < availableBytes; i++) { - AVM2Instruction ins = codeMap.get((long) i); - if (prev != ins) { - code.add(ins); - } - prev = ins; - } - } - - public void compact() { - if (code instanceof ArrayList) { - ((ArrayList) code).trimToSize(); - } - } - - public byte[] getBytes() { - return getBytes(null); - } - - public byte[] getBytes(byte[] origBytes) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - - OutputStream cos; - if ((origBytes != null) && (DEBUG_REWRITE)) { - ByteArrayInputStream origis = new ByteArrayInputStream(origBytes); - cos = new CopyOutputStream(bos, origis); - } else { - cos = bos; - } - try { - for (AVM2Instruction instruction : code) { - cos.write(instruction.getBytes()); - } - } catch (IOException ex) { - } - return bos.toByteArray(); - } - - public void markOffsets() { - long address = 0; - for (int i = 0; i < code.size(); i++) { - code.get(i).setAddress(address); - address += code.get(i).getBytesLength(); - } - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - for (AVM2Instruction instruction : code) { - s.append(instruction.toString()); - s.append(Helper.newLine); - } - return s.toString(); - } - - public String toASMSource() { - return toASMSource(new AVM2ConstantPool()); - } - - public String toASMSource(AVM2ConstantPool constants) { - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - toASMSource(constants, null, null, null, new ArrayList<>(), ScriptExportMode.PCODE, writer); - return writer.toString(); - } - - public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, ScriptExportMode exportMode, GraphTextWriter writer) { - return toASMSource(constants, trait, info, body, new ArrayList<>(), exportMode, writer); - } - - public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List outputMap, ScriptExportMode exportMode, GraphTextWriter writer) { - if (trait != null) { - if (trait instanceof TraitFunction) { - TraitFunction tf = (TraitFunction) trait; - writer.appendNoHilight("trait "); - writer.hilightSpecial("function ", HighlightSpecialType.TRAIT_TYPE); - writer.hilightSpecial(constants.multinameToString(tf.name_index), HighlightSpecialType.TRAIT_NAME); - writer.appendNoHilight(" slotid "); - writer.hilightSpecial("" + tf.slot_id, HighlightSpecialType.SLOT_ID); - writer.newLine(); - } - if (trait instanceof TraitMethodGetterSetter) { - TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait; - writer.appendNoHilight("trait "); - switch (tm.kindType) { - case Trait.TRAIT_METHOD: - writer.hilightSpecial("method ", HighlightSpecialType.TRAIT_TYPE); - break; - case Trait.TRAIT_GETTER: - writer.hilightSpecial("getter ", HighlightSpecialType.TRAIT_TYPE); - break; - case Trait.TRAIT_SETTER: - writer.hilightSpecial("setter ", HighlightSpecialType.TRAIT_TYPE); - break; - } - writer.hilightSpecial(constants.multinameToString(tm.name_index), HighlightSpecialType.TRAIT_NAME); - writer.appendNoHilight(" dispid "); - writer.hilightSpecial("" + tm.disp_id, HighlightSpecialType.DISP_ID); - writer.newLine(); - } - } - - if (info != null) { - writer.appendNoHilight("method").newLine(); - writer.appendNoHilight("name "); - writer.hilightSpecial(info.name_index == 0 ? "null" : "\"" + Helper.escapeActionScriptString(info.getName(constants)) + "\"", HighlightSpecialType.METHOD_NAME); - writer.newLine(); - if (info.flagExplicit()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("EXPLICIT", HighlightSpecialType.FLAG_EXPLICIT); - writer.newLine(); - } - if (info.flagHas_optional()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("HAS_OPTIONAL", HighlightSpecialType.FLAG_HAS_OPTIONAL); - writer.newLine(); - writer.appendNoHilight("flag HAS_OPTIONAL").newLine(); - } - if (info.flagHas_paramnames()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("HAS_PARAM_NAMES", HighlightSpecialType.FLAG_HAS_PARAM_NAMES); - writer.newLine(); - } - if (info.flagIgnore_rest()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("EXPLICIT", HighlightSpecialType.FLAG_IGNORE_REST); - writer.newLine(); - } - if (info.flagNeed_activation()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("NEED_ACTIVATION", HighlightSpecialType.FLAG_NEED_ACTIVATION); - writer.newLine(); - } - if (info.flagNeed_arguments()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("NEED_ARGUMENTS", HighlightSpecialType.FLAG_NEED_ARGUMENTS); - writer.newLine(); - } - if (info.flagNeed_rest()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("NEED_REST", HighlightSpecialType.FLAG_NEED_REST); - writer.newLine(); - } - if (info.flagSetsdxns()) { - writer.appendNoHilight("flag "); - writer.hilightSpecial("SET_DXNS", HighlightSpecialType.FLAG_SET_DXNS); - writer.newLine(); - } - for (int p = 0; p < info.param_types.length; p++) { - writer.appendNoHilight("param "); - writer.hilightSpecial(constants.multinameToString(info.param_types[p]), HighlightSpecialType.PARAM, p); - writer.newLine(); - } - if (info.flagHas_paramnames()) { - for (int n : info.paramNames) { - writer.appendNoHilight("paramname "); - if (n == 0) { - writer.appendNoHilight("null"); - } else { - writer.appendNoHilight("\""); - writer.appendNoHilight(constants.getString(n)); - writer.appendNoHilight("\""); - } - writer.newLine(); - } - } - if (info.flagHas_optional()) { - for (int i = 0; i < info.optional.length; i++) { - ValueKind vk = info.optional[i]; - writer.appendNoHilight("optional "); - writer.hilightSpecial(vk.toString(constants), HighlightSpecialType.OPTIONAL, i); - writer.newLine(); - } - } - writer.appendNoHilight("returns "); - writer.hilightSpecial(constants.multinameToString(info.ret_type), HighlightSpecialType.RETURNS); - writer.newLine(); - } - writer.newLine(); - - Set importantOffsets = getImportantOffsets(body, true); - if (body != null) { - writer.appendNoHilight("body").newLine(); - - writer.appendNoHilight("maxstack "); - writer.appendNoHilight(body.max_stack); - writer.newLine(); - - writer.appendNoHilight("localcount "); - writer.appendNoHilight(body.max_regs); - writer.newLine(); - - writer.appendNoHilight("initscopedepth "); - writer.appendNoHilight(body.init_scope_depth); - writer.newLine(); - - writer.appendNoHilight("maxscopedepth "); - writer.appendNoHilight(body.max_scope_depth); - writer.newLine(); - - for (int e = 0; e < body.exceptions.length; e++) { - ABCException exception = body.exceptions[e]; - writer.appendNoHilight("try"); - - writer.appendNoHilight(" from "); - writer.appendNoHilight("ofs"); - writer.appendNoHilight(Helper.formatAddress(exception.start)); - - writer.appendNoHilight(" to "); - writer.appendNoHilight("ofs"); - writer.appendNoHilight(Helper.formatAddress(exception.end)); - - writer.appendNoHilight(" target "); - writer.appendNoHilight("ofs"); - writer.appendNoHilight(Helper.formatAddress(exception.target)); - - writer.appendNoHilight(" type "); - writer.hilightSpecial(exception.type_index == 0 ? "null" : constants.getMultiname(exception.type_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_TYPE, e); - - writer.appendNoHilight(" name "); - writer.hilightSpecial(exception.name_index == 0 ? "null" : constants.getMultiname(exception.name_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_NAME, e); - writer.newLine(); - } - } - - writer.newLine(); - writer.appendNoHilight("code").newLine(); - - int ip = 0; - int largeLimit = 20000; - boolean markOffsets = code.size() <= largeLimit; - - if (exportMode == ScriptExportMode.HEX) { - Helper.byteArrayToHexWithHeader(writer, getBytes()); - } else if (exportMode == ScriptExportMode.PCODE || exportMode == ScriptExportMode.PCODE_HEX) { - for (AVM2Instruction ins : code) { - long addr = ins.getAddress(); - if (exportMode == ScriptExportMode.PCODE_HEX) { - writer.appendNoHilight("; "); - writer.appendNoHilight(Helper.bytesToHexString(ins.getBytes())); - writer.newLine(); - } - if (Configuration.showAllAddresses.get() || importantOffsets.contains(addr)) { - writer.appendNoHilight("ofs" + Helper.formatAddress(addr) + ":"); - } - /*for (int e = 0; e < body.exceptions.length; e++) { - if (body.exceptions[e].start == ofs) { - ret.append("exceptionstart " + e + ":"); - } - if (body.exceptions[e].end == ofs) { - ret.append("exceptionend " + e + ":"); - } - if (body.exceptions[e].target == ofs) { - ret.append("exceptiontarget " + e + ":"); - } - }*/ - - if (!ins.isIgnored()) { - if (markOffsets) { - writer.append("", addr, ins.getFileOffset()); - } - - writer.appendNoHilight(ins.toStringNoAddress(constants, new ArrayList<>())); - writer.newLine(); - outputMap.add(ip); - } - - ip++; - } - } else if (exportMode == ScriptExportMode.CONSTANTS) { - writer.appendNoHilight("Constant export mode is not supported.").newLine(); - } - - return writer; - } - - public Set getImportantOffsets(MethodBody body, boolean tryEnds) { - Set ret = new HashSet<>(); - if (body != null) { - for (ABCException exception : body.exceptions) { - ret.add((long) exception.start); - if (tryEnds) { - ret.add((long) exception.end); - } - ret.add((long) exception.target); - } - } - - for (AVM2Instruction ins : code) { - ret.addAll(ins.getOffsets()); - } - - return ret; - } - - public AVM2Instruction adr2ins(long address) throws ConvertException { - int pos = adr2pos(address, false); - if (pos == code.size()) { - // end - return null; - } - - return code.get(pos); - } - - public int adr2pos(long address) throws ConvertException { - return adr2pos(address, false); - } - - public int adr2pos(long address, boolean nearest) throws ConvertException { - int ret = adr2posNoEx(address); - if (ret < 0) { - if (nearest && address < getEndOffset()) { - return -ret - 1; - } - throw new ConvertException("Invalid jump to ofs" + Helper.formatAddress(address), -1); - } - return ret; - } - - private int adr2posNoEx(long address) { - int min = 0; - int max = code.size() - 1; - - while (max >= min) { - int mid = (min + max) / 2; - long midValue = code.get(mid).getAddress(); - if (midValue == address) { - return mid; - } else if (midValue < address) { - min = mid + 1; - } else { - max = mid - 1; - } - } - - if (address == getEndOffset()) { - return code.size(); - } - - return -min - 1; - } - - public long pos2adr(int pos) { - if (pos == code.size()) { - return getEndOffset(); - } - return (int) code.get(pos).getAddress(); - } - - public long getEndOffset() { - if (code.isEmpty()) { - return 0; - } - - AVM2Instruction ins = code.get(code.size() - 1); - return (int) (ins.getAddress() + ins.getBytesLength()); - } - - /** - * Test for killed register. CalcKilledStats must be called before - * - * @param regName - * @param start - * @param end - * @return - */ - public boolean isKilled(int regName, int start, int end) { - if (!killedRegs.containsKey(regName)) { - return false; - } - for (int ip : killedRegs.get(regName)) { - if (ip >= start && ip <= end) { - return true; - } - } - return false; - } - - private int toSourceCount = 0; - - public Map getLocalRegNamesFromDebug(ABC abc) { - Map localRegNames = new HashMap<>(); - - for (AVM2Instruction ins : code) { - if (ins.definition instanceof DebugIns) { - if (ins.operands[0] == 1) { - String v = abc.constants.getString(ins.operands[1]); - // Same name already exists, it may be wrong names inserted by obfuscator - if (localRegNames.values().contains(v)) { - return new HashMap<>(); - } - localRegNames.put(ins.operands[2] + 1, v); - } - } - } - - // TODO: Make this immune to using existing multinames (?) - return localRegNames; - } - - private Map> killedRegs = new HashMap<>(); - - public void calcKilledStats(MethodBody body) throws InterruptedException { - killedRegs.clear(); - HashMap> vis = visitCode(body); - - for (int k = 0; k < code.size(); k++) { - if (vis.get(k).isEmpty()) { - continue; - } - if (code.get(k).definition instanceof KillIns) { - int regid = code.get(k).operands[0]; - if (!killedRegs.containsKey(regid)) { - killedRegs.put(regid, new HashSet<>()); - } - killedRegs.get(regid).add(k); - } - } - } - - public List clearTemporaryRegisters(List input) { - List output = new ArrayList<>(input); - for (int i = 0; i < output.size(); i++) { - if (output.get(i) instanceof SetLocalAVM2Item) { - if (isKilled(((SetLocalAVM2Item) output.get(i)).regIndex, 0, code.size() - 1)) { - SetLocalAVM2Item lsi = (SetLocalAVM2Item) output.get(i); - if (i + 1 < output.size()) { - if (output.get(i + 1) instanceof ExitItem) { - GraphTargetItem rv = output.get(i + 1); - if (rv.value instanceof LocalRegAVM2Item) { - LocalRegAVM2Item lr = (LocalRegAVM2Item) rv.value; - if (lr.regIndex == lsi.regIndex) { - rv.value = lsi.value; - } - } - } - } - output.remove(i); - i--; - } - } else if (output.get(i) instanceof WithAVM2Item) { - clearTemporaryRegisters(((WithAVM2Item) output.get(i)).items); - } - } - return output; - } - - public int fixIPAfterDebugLine(int ip) { - if (code.isEmpty()) { - return ip; - } - if (ip >= code.size()) { - return code.size() - 1; - } - while (code.get(ip).definition instanceof DebugLineIns) { - ip++; - } - return ip; - } - - public long fixAddrAfterDebugLine(long addr) throws ConvertException { - return pos2adr(fixIPAfterDebugLine(adr2pos(addr, true))); - } - - public ConvertOutput toSourceOutput(boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssigmentIps, HashMap> refs) throws ConvertException, InterruptedException { - calcKilledStats(body); - boolean debugMode = DEBUG_MODE; - if (debugMode) { - System.err.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString()); - } - if (visited == null) { - visited = new boolean[code.size()]; - } - //if(true) return ""; - toSourceCount++; - if (toSourceLimit > 0 && toSourceCount >= toSourceLimit) { - throw new ConvertException("Limit of subs(" + toSourceLimit + ") was reached", start); - } - List output = new ArrayList<>(); - int ip = start; - //try { - //int addr; - iploop: - while (ip <= end) { - - boolean processTry = processJumps; - //addr = pos2adr(ip); - //int ipfix = fixIPAfterDebugLine(ip); - //int addrfix = pos2adr(ipfix); - //int maxend = -1; - - if (ip > end) { - break; - } - - if (visited[ip]) { - //logger.warning(path + ": Code already visited, ofs:" + Helper.formatAddress(pos2adr(ip)) + ", ip:" + ip); - break; - } - - if (Configuration.simplifyExpressions.get()) { - stack.simplify(); - } - visited[ip] = true; - AVM2Instruction ins = code.get(ip); - if (stack.isEmpty()) { - lineStartItem.setVal(ins); - } - - if (debugMode) { - System.err.println("translating ip " + ip + " ins " + ins.toString() + " stack:" + stack.toString() + " scopeStack:" + scopeStack.toString()); - } - if (ins.definition instanceof NewFunctionIns) { - if (ip + 1 <= end) { - if (code.get(ip + 1).definition instanceof PopIns) { - ip += 2; - continue; - } - } - } - /*if ((ip + 8 < code.size())) { //return in finally clause - if (ins.definition instanceof SetLocalTypeIns) { - if (code.get(ip + 1).definition instanceof PushByteIns) { - AVM2Instruction jmp = code.get(ip + 2); - if (jmp.definition instanceof JumpIns) { - if (jmp.operands[0] == 0) { - if (code.get(ip + 3).definition instanceof LabelIns) { - if (code.get(ip + 4).definition instanceof PopIns) { - if (code.get(ip + 5).definition instanceof LabelIns) { - AVM2Instruction gl = code.get(ip + 6); - if (gl.definition instanceof GetLocalTypeIns) { - if (((GetLocalTypeIns) gl.definition).getRegisterId(gl) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins)) { - AVM2Instruction ki = code.get(ip + 7); - if (ki.definition instanceof KillIns) { - if (ki.operands[0] == ((SetLocalTypeIns) ins.definition).getRegisterId(ins)) { - if (code.get(ip + 8).definition instanceof ReturnValueIns) { - ip = ip + 8; - continue; - } - } - } - } - } - } - } - } - } - } - } - } - }//*/ - - /*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause - if (code.get(ip + 1).definition instanceof DupIns) { - if (code.get(ip + 2).definition instanceof SetLocalTypeIns) { - ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames, fullyQualifiedNames); - ip += 3; - continue; - } - } - }*/ - if ((ins.definition instanceof GetLocalTypeIns) && (!output.isEmpty()) && (output.get(output.size() - 1) instanceof SetLocalAVM2Item) && (((SetLocalAVM2Item) output.get(output.size() - 1)).regIndex == ((GetLocalTypeIns) ins.definition).getRegisterId(ins)) && isKilled(((SetLocalAVM2Item) output.get(output.size() - 1)).regIndex, start, end)) { - SetLocalAVM2Item slt = (SetLocalAVM2Item) output.remove(output.size() - 1); - stack.push(slt.getValue()); - ip++; - } else if ((ins.definition instanceof SetLocalTypeIns) && (ip + 1 <= end) && (isKilled(((SetLocalTypeIns) ins.definition).getRegisterId(ins), ip, end))) { // set_local_x,get_local_x..kill x - AVM2Instruction insAfter = code.get(ip + 1); - if ((insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) { - GraphTargetItem before = stack.peek(); - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - stack.push(before); - ip += 2; - continue iploop; - } else { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - ip++; - continue iploop; - } - } else if (ins.definition instanceof DupIns) { - int nextPos; - do { - AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null; - if (insAfter == null) { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - ip++; - break; - } - AVM2Instruction insBefore = ins; - if (ip - 1 >= start) { - insBefore = code.get(ip - 1); - } - if (insAfter.definition instanceof ConvertBIns) { // SWF compiled with debug contain convert_b - ip++; - //addr = pos2adr(ip); - insAfter = code.get(ip + 1); - } - - boolean isAnd; - if (processJumps && (insAfter.definition instanceof IfFalseIns)) { - //stack.add("(" + stack.pop() + ")&&"); - isAnd = true; - } else if (processJumps && (insAfter.definition instanceof IfTrueIns)) { - //stack.add("(" + stack.pop() + ")||"); - isAnd = false; - } else if (insAfter.definition instanceof SetLocalTypeIns) { - // chained assignments - int reg = (((SetLocalTypeIns) insAfter.definition).getRegisterId(insAfter)); - for (int t = ip + 1; t <= end - 1; t++) { - if (code.get(t).definition instanceof KillIns) { - if (code.get(t).operands[0] == reg) { - break; - } - } - if (code.get(t).definition instanceof GetLocalTypeIns) { - if (((GetLocalTypeIns) code.get(t).definition).getRegisterId(code.get(t)) == reg) { - if (code.get(t + 1).definition instanceof KillIns) { - if (code.get(t + 1).operands[0] == reg) { - ConvertOutput assignment = toSourceOutput(thisHasDefaultToPrimitive, lineStartItem, path, part, processJumps, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, abc, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited, localRegAssigmentIps, refs); - if (!assignment.output.isEmpty()) { - GraphTargetItem tar = assignment.output.remove(assignment.output.size() - 1); - tar.firstPart = part; - stack.push(tar); - ip = t + 2; - - continue iploop; - } - } - } - } - } - } - if (!isKilled(reg, 0, end)) { - GraphTargetItem vx = stack.pop().getThroughDuplicate(); - int dupCnt = 1; - for (int i = ip - 1; i >= start; i--) { - if (code.get(i).definition instanceof DupIns) { - if (stack.isEmpty()) { - break; // FIXME?o - } - stack.pop(); - dupCnt++; - //stack.push(v); - } else { - break; - } - } - for (int i = 0; i < dupCnt; i++) { - stack.push(new LocalRegAVM2Item(ins, (AVM2Instruction) lineStartItem.getVal(), reg, vx)); - } - stack.push(vx); - } else { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - } - ip++; - break; - //} - - } else { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - ip++; - break; - //throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString()); - } - } while (ins.definition instanceof DupIns); - } else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - //ip = end + 1; - break; - } else if (ins.definition instanceof NewFunctionIns) { - String functionName = ""; - if ((ip >= start + 2) && (ip <= end - 4)) { - AVM2Instruction prev2 = code.get(ip - 2); - if (prev2.definition instanceof NewObjectIns) { - if (prev2.operands[0] == 0) { - if (code.get(ip - 1).definition instanceof PushWithIns) { - boolean hasDup = false; - int plus = 0; - if (code.get(ip + 1).definition instanceof DupIns) { - hasDup = true; - plus = 1; - } - AVM2Instruction psco = code.get(ip + 1 + plus); - if (psco.definition instanceof GetScopeObjectIns) { - if (psco.operands[0] == scopeStack.size() - 1) { - if (code.get(ip + plus + 2).definition instanceof SwapIns) { - if (code.get(ip + plus + 4).definition instanceof PopScopeIns) { - if (code.get(ip + plus + 3).definition instanceof SetPropertyIns) { - functionName = abc.constants.getMultiname(code.get(ip + plus + 3).operands[0]).getName(abc.constants, fullyQualifiedNames, true); - scopeStack.pop();// with - output.remove(output.size() - 1); // with - ip = ip + plus + 4; // +1 below - } - } - } - } - } - } - } - } - } - // What to do when hasDup is false? - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek(); - nft.functionName = functionName; - ip++; - } else { - try { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); - } catch (RuntimeException re) { - /*String last=""; - int len=5; - for(int i=(ip-len<0?0:ip-len);i maxRegister) { - maxRegister = regId; - } - } - return maxRegister + 1; - } - - public HashMap getLocalRegTypes(AVM2ConstantPool constants, List fullyQualifiedNames) { - HashMap ret = new HashMap<>(); - AVM2Instruction prev = null; - for (AVM2Instruction ins : code) { - if (ins.definition instanceof SetLocalTypeIns) { - if (prev != null) { - if (prev.definition instanceof CoerceOrConvertTypeIns) { - ret.put(((SetLocalTypeIns) ins.definition).getRegisterId(ins), ((CoerceOrConvertTypeIns) prev.definition).getTargetType(constants, prev)); - } - } - } - prev = ins; - } - return ret; - - } - - private class Slot { - - public final GraphTargetItem scope; - - public final Multiname multiname; - - public Slot(GraphTargetItem scope, Multiname multiname) { - this.scope = scope; - this.multiname = multiname; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Slot) { - Slot slot = (Slot) obj; - return (slot.scope.getThroughRegister() == scope.getThroughRegister()) - && (slot.multiname == multiname); - } - return false; - } - - @Override - public int hashCode() { - int hash = 7; - hash = 59 * hash + (scope != null ? Objects.hashCode(scope.getThroughRegister()) : 0); - hash = 59 * hash + Objects.hashCode(multiname); - return hash; - } - } - - public void initToSource() { - toSourceCount = 0; - } - - private GraphTargetItem handleDeclareReg(int minreg, GraphTargetItem assignment, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, int reg) { - - //do not add declarations for reserved local registers like function arguments - if (reg < minreg) { - return assignment; - } - GraphTargetItem vtype = TypeItem.UNBOUNDED; - if (assignment.value instanceof ConvertAVM2Item) { - vtype = ((ConvertAVM2Item) assignment.value).type; - } - - if (vtype.equals(TypeItem.UNBOUNDED) && (assignment.value instanceof CoerceAVM2Item)) { - vtype = ((CoerceAVM2Item) assignment.value).typeObj; - } - if (vtype.equals(TypeItem.UNBOUNDED) && (assignment.value instanceof SimpleValue) && ((SimpleValue) assignment.value).isSimpleValue()) { - vtype = assignment.value.returnType(); - } - - if (declaredRegisters[reg] == null) { - declaredRegisters[reg] = new DeclarationAVM2Item(assignment, vtype); - if (assignment instanceof SetTypeAVM2Item) { - ((SetTypeAVM2Item) assignment).setDeclaration(declaredRegisters[reg]); - } - return declaredRegisters[reg]; - } - - if (declaredRegisters[reg].type == TypeItem.UNBOUNDED) { - - } else if (!declaredRegisters[reg].type.equals(vtype)) { //already declared with different type - declaredRegisters[reg].type = TypeItem.UNBOUNDED; - } - - if (assignment instanceof SetTypeAVM2Item) { - ((SetTypeAVM2Item) assignment).setDeclaration(declaredRegisters[reg]); - } - - return assignment; - } - - private GraphTargetItem injectDeclarations(int minreg, GraphTargetItem ti, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { - if (ti.value != null) { - ti.value = injectDeclarations(minreg, ti.value, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - //TODO: walk whole tree... some walker? - if (ti instanceof IfItem) { - ((IfItem) ti).expression = injectDeclarations(minreg, ((IfItem) ti).expression, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - if (ti instanceof BinaryOpItem) { - ((BinaryOpItem) ti).leftSide = injectDeclarations(minreg, ((BinaryOpItem) ti).leftSide, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - ((BinaryOpItem) ti).rightSide = injectDeclarations(minreg, ((BinaryOpItem) ti).rightSide, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - if (ti instanceof ForEachInAVM2Item) { - ForEachInAVM2Item fei = (ForEachInAVM2Item) ti; - if (fei.expression.object instanceof LocalRegAVM2Item) { - int reg = ((LocalRegAVM2Item) fei.expression.object).regIndex; - if (declaredRegisters[reg] == null) { - fei.expression.object = handleDeclareReg(minreg, fei.expression.object, declaredRegisters, declaredSlots, reg); - } - } - } - if (ti instanceof ForInAVM2Item) { - ForInAVM2Item fi = (ForInAVM2Item) ti; - if (fi.expression.object instanceof LocalRegAVM2Item) { - int reg = ((LocalRegAVM2Item) fi.expression.object).regIndex; - fi.expression.object = handleDeclareReg(minreg, fi.expression.object, declaredRegisters, declaredSlots, reg); - //nowdeclaredRegs.add(reg); - - } - } - if (ti instanceof Block) { - Block bl = (Block) ti; - for (List s : bl.getSubs()) { - injectDeclarations(minreg, s, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - } - if (ti instanceof SetLocalAVM2Item) { - int reg = ((SetLocalAVM2Item) ti).regIndex; - ti = handleDeclareReg(minreg, ti, declaredRegisters, declaredSlots, reg); - return ti; - } - if (ti instanceof SetSlotAVM2Item) { - SetSlotAVM2Item ssti = (SetSlotAVM2Item) ti; - Slot sl = new Slot(ssti.scope, ssti.slotName); - if (!declaredSlots.contains(sl)) { - GraphTargetItem type = TypeItem.UNBOUNDED; - for (int t = 0; t < body.traits.traits.size(); t++) { - if (body.traits.traits.get(t).getName(abc) == sl.multiname) { - if (body.traits.traits.get(t) instanceof TraitSlotConst) { - type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); - } - } - } - DeclarationAVM2Item d = new DeclarationAVM2Item(ti, type); - ssti.setDeclaration(d); - declaredSlotsDec.add(d); - declaredSlots.add(sl); - return d; - //nowdeclaredSlots.add(sl); - } else { - int idx = declaredSlots.indexOf(sl); - ssti.setDeclaration(declaredSlotsDec.get(idx)); - } - } - return ti; - } - - private void injectDeclarations(int minreg, List list, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { - //List nowdeclaredRegs=new ArrayList<>(); - //List nowdeclaredSlots=new ArrayList<>(); - for (int i = 0; i < list.size(); i++) { - GraphTargetItem ti = list.get(i); - GraphTargetItem ti2 = injectDeclarations(minreg, ti, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - if (ti != ti2) { - list.set(i, ti2); - } - } - - /* - //undeclare registers at the end of the block? - for(int reg:nowdeclaredRegs){ - declaredRegisters[reg] = false; - } - - for(Slot s:nowdeclaredSlots){ - declaredSlots.remove(s); - }*/ - } - - public List toGraphTargetItems(boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, List initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) throws InterruptedException { - initToSource(); - List list; - HashMap localRegs = new HashMap<>(); - - int regCount = getRegisterCount(); - for (int i = 0; i < regCount; i++) { - localRegs.put(0, new UndefinedAVM2Item(null, null)); - } - - //try { - list = AVM2Graph.translateViaGraph(path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive); - - if (initTraits != null) { - loopi: - for (int i = 0; i < list.size(); i++) { - GraphTargetItem ti = list.get(i); - if ((ti instanceof InitPropertyAVM2Item) || (ti instanceof SetPropertyAVM2Item)) { - int multinameIndex = 0; - GraphTargetItem value = null; - if (ti instanceof InitPropertyAVM2Item) { - multinameIndex = ((InitPropertyAVM2Item) ti).propertyName.multinameIndex; - value = ((InitPropertyAVM2Item) ti).value; - } - if (ti instanceof SetPropertyAVM2Item) { - multinameIndex = ((FullMultinameAVM2Item) ((SetPropertyAVM2Item) ti).propertyName).multinameIndex; - value = ((SetPropertyAVM2Item) ti).value; - } - Multiname m = abc.constants.getMultiname(multinameIndex); - for (Traits ts : initTraits) { - for (Trait t : ts.traits) { - Multiname tm = abc.constants.getMultiname(t.name_index); - if (tm != null && tm.equals(m)) { - if ((t instanceof TraitSlotConst)) { - if (((TraitSlotConst) t).isConst() || initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) { - TraitSlotConst tsc = (TraitSlotConst) t; - if (value != null && !convertData.assignedValues.containsKey(tsc)) { - - if (value instanceof NewFunctionAVM2Item) { - NewFunctionAVM2Item f = (NewFunctionAVM2Item) value; - f.functionName = tsc.getName(abc).getName(abc.constants, fullyQualifiedNames, true); - } - AssignedValue av = new AssignedValue(value, initializerType, methodIndex); - convertData.assignedValues.put(tsc, av); - list.remove(i); - i--; - continue; - } - } - break; - } - } - } - } - } else { - // In obfuscated code, SetLocal instructions comes first - //break; - } - } - } - if (initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) { - List newList = new ArrayList<>(); - for (GraphTargetItem ti : list) { - if (!(ti instanceof ReturnVoidAVM2Item)) { - if (!(ti instanceof InitPropertyAVM2Item)) { - newList.add(ti); - } - } - } - list = newList; - if (list.isEmpty()) { - return list; - } - } - // Declarations - - DeclarationAVM2Item d[] = new DeclarationAVM2Item[regCount]; - - int param_types[] = abc.method_info.get(body.method_info).param_types; - int r = 1; - for (int i = 0; i < param_types.length; i++) { - GraphTargetItem type; - if (param_types[i] == 0) { - type = TypeItem.UNBOUNDED; - } else { - type = new TypeItem(abc.constants.getMultiname(param_types[i]).getNameWithNamespace(abc.constants)); - } - if (d.length > r) { - d[r] = new DeclarationAVM2Item(new SetLocalAVM2Item(null, null, r, new NullAVM2Item(null, null)), type); - } - r++; - } - if (abc.method_info.get(body.method_info).flagNeed_arguments()) { - if (d.length > r) { - d[r] = new DeclarationAVM2Item(new SetLocalAVM2Item(null, null, r, new NullAVM2Item(null, null)), TypeItem.ARRAY /*?*/); - } - r++; - } - if (abc.method_info.get(body.method_info).flagNeed_rest()) { - if (d.length > r) { - d[r] = new DeclarationAVM2Item(new SetLocalAVM2Item(null, null, r, new NullAVM2Item(null, null)), TypeItem.ARRAY/*?*/); - } - r++; - } - // - - //int minreg = abc.method_info.get(body.method_info).getMaxReservedReg() + 1; - injectDeclarations(1, list, d, new ArrayList<>(), new ArrayList<>(), abc, body); - - int lastPos = list.size() - 1; - if (lastPos < 0) { - lastPos = 0; - } - if ((list.size() > lastPos) && (list.get(lastPos) instanceof ScriptEndItem)) { - lastPos--; - } - if (lastPos < 0) { - lastPos = 0; - } - if ((list.size() > lastPos) && (list.get(lastPos) instanceof ReturnVoidAVM2Item)) { - list.remove(lastPos); - } - - return list; - } - - public void updateOffsets(OffsetUpdater updater, MethodBody body) { - for (int i = 0; i < code.size(); i++) { - AVM2Instruction ins = code.get(i); - if (ins.definition instanceof LookupSwitchIns) { - long target = ins.getAddress() + ins.operands[0]; - ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]); - for (int k = 2; k < ins.operands.length; k++) { - target = ins.getAddress() + ins.operands[k]; - ins.operands[k] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[k]); - } - } else /*for (int j = 0; j < ins.definition.operands.length; j++) { - if (ins.definition.operands[j] == AVM2Code.DAT_OFFSET) { - long target = ins.offset + ins.getBytes().length + ins.operands[j]; - ins.operands[j] = updater.updateOperandOffset(target, ins.operands[j]); - } - }*/ //Faster, but not so universal - { - if (ins.definition instanceof IfTypeIns) { - long target = ins.getTargetAddress(); - try { - ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]); - } catch (ConvertException cex) { - throw new ConvertException("Invalid offset (" + ins + ")", i); - } - } - } - ins.setAddress(updater.updateInstructionOffset(ins.getAddress())); - } - - for (ABCException ex : body.exceptions) { - ex.start = updater.updateOperandOffset(-1, ex.start, ex.start); - ex.end = updater.updateOperandOffset(-1, ex.end, ex.end); - ex.target = updater.updateOperandOffset(-1, ex.target, ex.target); - } - } - - public void fixJumps(final String path, MethodBody body) throws InterruptedException { - if (code.isEmpty()) { - return; - } - final List insAddrToRemove = new ArrayList<>(); - final long endOffset = getEndOffset(); - updateOffsets(new OffsetUpdater() { - - @Override - public long updateInstructionOffset(long address) { - return address; - } - - @Override - public int updateOperandOffset(long insAddr, long targetAddress, int offset) { - if (targetAddress > endOffset || targetAddress < 0 || adr2posNoEx(targetAddress) < 0) { - insAddrToRemove.add(insAddr); - } - return offset; - } - - }, body); - - boolean someIgnored = false; - for (Long insAddr : insAddrToRemove) { - int pos = adr2posNoEx(insAddr); - if (pos > -1) { - code.get(pos).setIgnored(true, 0); - someIgnored = true; - } - } - if (someIgnored) { - logger.log(Level.WARNING, path + ": One or more invalid jump offsets found in the code. Those instructions were ignored."); - } - removeIgnored(body); - } - - public void checkValidOffsets(MethodBody body) { - updateOffsets(new OffsetUpdater() { - - @Override - public long updateInstructionOffset(long address) { - adr2pos(address); - return address; - } - - @Override - public int updateOperandOffset(long insAddr, long targetAddress, int offset) { - /*if (insAddr == -1) { - return offset; - }*/ - adr2pos(targetAddress); - return offset; - } - - }, body); - } - - public void removeInstruction(int pos, MethodBody body) { - if ((pos < 0) || (pos >= code.size())) { - throw new IndexOutOfBoundsException(); - } - - AVM2Instruction ins = code.get(pos); - final long remOffset = ins.getAddress(); - int bc = ins.getBytesLength(); - - final int byteCount = bc; - updateOffsets(new OffsetUpdater() { - @Override - public long updateInstructionOffset(long address) { - if (address > remOffset) { - return address - byteCount; - } - return address; - } - - @Override - public int updateOperandOffset(long jumpInsAddr, long jumpTargetAddr, int jumpOffset) { - /* - a:jump d: - b: - c:X - d: - */ - if (jumpTargetAddr > remOffset && jumpInsAddr < remOffset) { - return jumpOffset - byteCount; - } - /* - a:X1 - b:X2 - c: - d:jump a: - */ - if (jumpTargetAddr <= remOffset && jumpInsAddr > remOffset) { - return jumpOffset + byteCount; - } - - return jumpOffset; - } - }, body); - code.remove(pos); - //checkValidOffsets(body); - } - - /** - * Inserts instruction at specified point. Handles offsets properly. Note: - * If newinstruction is jump, the offset operand must be handled properly by - * caller. All old jump offsets to pos are targeted before new instruction. - * - * @param pos Position in the list - * @param instruction Instruction False means before new instruction - * @param body Method body (used for try handling) - */ - public void insertInstruction(int pos, AVM2Instruction instruction, MethodBody body) { - insertInstruction(pos, instruction, false, body); - } - - /** - * Replaces instruction by another. Properly handles offsets. Note: If - * newinstruction is jump, the offset operand must be handled properly by - * caller. - * - * @param pos - * @param instruction - * @param body - */ - public void replaceInstruction(int pos, AVM2Instruction instruction, MethodBody body) { - AVM2Instruction oldInstruction = code.get(pos); - instruction.setAddress(oldInstruction.getAddress()); - int oldByteCount = oldInstruction.getBytesLength(); - int newByteCount = instruction.getBytesLength(); - int byteDelta = newByteCount - oldByteCount; - - if (byteDelta != 0) { - updateOffsets(new OffsetUpdater() { - - @Override - public long updateInstructionOffset(long address) { - if (address > instruction.getAddress()) { - return address + byteDelta; - } - return address; - } - - @Override - public int updateOperandOffset(long insAddr, long targetAddress, int offset) { - if (targetAddress > instruction.getAddress() && insAddr <= instruction.getAddress()) { - return offset + byteDelta; - } - if (targetAddress <= instruction.getAddress() && insAddr > instruction.getAddress()) { - return offset - byteDelta; - } - return offset; - } - }, body); - } - code.set(pos, instruction); - } - - /** - * Inserts instruction at specified point. Handles offsets properly. Note: - * If newinstruction is jump, the offset operand must be handled properly by - * caller. - * - * @param pos Position in the list - * @param instruction Instruction - * @param mapOffsetsAfterIns Map all jumps to the pos after new instruction? - * False means before new instruction - * @param body Method body (used for try handling) - */ - public void insertInstruction(int pos, AVM2Instruction instruction, boolean mapOffsetsAfterIns, MethodBody body) { - //checkValidOffsets(body); - if (pos < 0) { - pos = 0; - } - if (pos > code.size()) { - pos = code.size(); - } - final int byteCount = instruction.getBytesLength(); - if (pos == code.size()) { - instruction.setAddress(code.get(pos - 1).getAddress() + code.get(pos - 1).getBytesLength()); - } else { - instruction.setAddress(code.get(pos).getAddress()); - } - final long x = instruction.getAddress(); - updateOffsets(new OffsetUpdater() { - - @Override - public long updateInstructionOffset(long offset) { - if (offset >= x) { - return offset + byteCount; - } - return offset; - } - - @Override - public int updateOperandOffset(long j, long t, int offset_jt) { - - /* - j:jump t: - n: - n: - x:# - t: - */ - if (((t > x) || (mapOffsetsAfterIns && (t == x))) && (j < x)) { - return offset_jt + byteCount; - } - /* - t: - x:# - n: - n: - j:jump t: - */ - if (((t < x) || (mapOffsetsAfterIns && (t == x))) && (j > x)) { - return offset_jt - byteCount; - } - - /* - t: - n: - n: - j:x: # jump t: - */ - if ((j == x) && (t < x)) { - return offset_jt - byteCount; - } - - return offset_jt; - } - }, body); - instruction.setAddress(x); - code.add(pos, instruction); - //checkValidOffsets(body); - } - - public int removeTraps(Trait trait, int methodInfo, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { - SWFDecompilerPlugin.fireAvm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); - try (Statistics s = new Statistics("AVM2DeobfuscatorGetSet")) { - new AVM2DeobfuscatorGetSet().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); - } - try (Statistics s = new Statistics("AVM2DeobfuscatorSimple")) { - new AVM2DeobfuscatorSimpleOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); - } - try (Statistics s = new Statistics("AVM2DeobfuscatorRegisters")) { - new AVM2DeobfuscatorRegistersOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); - } - try (Statistics s = new Statistics("AVM2DeobfuscatorJumps")) { - new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); - } - return 1; - } - - private void handleRegister(CodeStats stats, int reg) { - if (reg + 1 > stats.maxlocal) { - stats.maxlocal = reg + 1; - } - } - - private boolean walkCode(CodeStats stats, int pos, int stack, int scope, ABC abc) { - while (pos < code.size()) { - AVM2Instruction ins = code.get(pos); - if (stats.instructionStats[pos].seen) { - // check stack mismatch here - return true; - } - - if (ins.definition instanceof NewFunctionIns) { - MethodBody innerBody = abc.findBody(ins.operands[0]); - innerBody.autoFillStats(abc, stats.initscope + (stats.has_activation ? 1 : 0), false); - } - - stats.instructionStats[pos].seen = true; - stats.instructionStats[pos].stackpos = stack; - stats.instructionStats[pos].scopepos = scope; - - int stackDelta = ins.definition.getStackDelta(ins, abc); - int scopeDelta = ins.definition.getScopeStackDelta(ins, abc); - int oldStack = stack; - - //+" deltaScope:"+(scopeDelta>0?"+"+scopeDelta:scopeDelta)+" stack:"+stack+" scope:"+scope); - stack += stackDelta; - scope += scopeDelta; - - stats.instructionStats[pos].stackpos_after = stack; - stats.instructionStats[pos].scopepos_after = scope; - - if (stack > stats.maxstack) { - stats.maxstack = stack; - } - if (scope > stats.maxscope) { - stats.maxscope = scope; - } - - //System.out.println("stack "+oldStack+(stackDelta>=0?"+"+stackDelta:stackDelta)+" max:"+stats.maxstack+" "+ins); - if ((ins.definition instanceof DXNSIns) || (ins.definition instanceof DXNSLateIns)) { - stats.has_set_dxns = true; - } - if (ins.definition instanceof NewActivationIns) { - stats.has_activation = true; - } - if (ins.definition instanceof SetLocalTypeIns) { - handleRegister(stats, ((SetLocalTypeIns) ins.definition).getRegisterId(ins)); - } else if (ins.definition instanceof GetLocalTypeIns) { - handleRegister(stats, ((GetLocalTypeIns) ins.definition).getRegisterId(ins)); - } else { - for (int i = 0; i < ins.definition.operands.length; i++) { - int op = ins.definition.operands[i]; - if (op == DAT_LOCAL_REG_INDEX) { - handleRegister(stats, ins.operands[i]); - } - } - } - if (ins.definition instanceof ReturnValueIns) { - // check stack=1 - return true; - } - if (ins.definition instanceof ReturnVoidIns) { - // check stack=0 - return true; - } - if (ins.definition instanceof JumpIns) { - try { - pos = adr2pos(ins.getTargetAddress()); - continue; - } catch (ConvertException ex) { - return false; - } - } else if (ins.definition instanceof IfTypeIns) { - try { - int newpos = adr2pos(ins.getTargetAddress()); - walkCode(stats, newpos, stack, scope, abc); - } catch (ConvertException ex) { - return false; - } - } - if (ins.definition instanceof LookupSwitchIns) { - for (int i = 0; i < ins.operands.length; i++) { - if (i == 1) { - continue; - } - try { - int newpos = adr2pos(pos2adr(pos) + ins.operands[i]); - if (!walkCode(stats, newpos, stack, scope, abc)) { - return false; - } - } catch (ConvertException ex) { - return false; - } - } - } - pos++; - } - return true; - } - - public CodeStats getStats(ABC abc, MethodBody body, int initScope) { - CodeStats stats = new CodeStats(this); - stats.initscope = initScope; - if (!walkCode(stats, 0, 0, initScope, abc)) { - return null; - } - int scopePos = -1; - int prevStart = 0; - for (int e = 0; e < body.exceptions.length; e++) { - ABCException ex = body.exceptions[e]; - try { - if (scopePos == -1) { - scopePos = stats.instructionStats[adr2pos(ex.end) - 1].scopepos_after; - } - List visited = new ArrayList<>(); - for (int i = 0; i < stats.instructionStats.length; i++) { - if (stats.instructionStats[i].seen) { - visited.add(i); - } - } - if (!walkCode(stats, adr2pos(ex.target), 1 + (ex.isFinally() ? 1 : 0), scopePos, abc)) { - return null; - } - int maxIp = 0; - // searching for visited instruction in second run which has maximum position - for (int i = 0; i < stats.instructionStats.length; i++) { - if (stats.instructionStats[i].seen && !visited.contains(i)) { - maxIp = i; - } - } - scopePos = stats.instructionStats[maxIp].scopepos_after; - int stackPos = stats.instructionStats[maxIp].stackpos_after; - int nextIp = maxIp + 1; - if (code.get(maxIp).definition instanceof JumpIns) { - nextIp = adr2pos(pos2adr(nextIp) + code.get(maxIp).operands[0]); - } - if (nextIp < stats.instructionStats.length) { - InstructionStats nextIpStat = stats.instructionStats[nextIp]; - int origScopePos = nextIpStat.scopepos; - int origStackPos = nextIpStat.stackpos; - - if (prevStart == ex.start && ex.isFinally() && !code.get(nextIp).isExit() && nextIpStat.seen) { - for (int i = 0; i < stats.instructionStats.length; i++) { - stats.instructionStats[i].seen = false; - } - // Rerun rest with new scopePos, stackPos - if (!walkCode(stats, nextIp, origStackPos + 1/*magic!*/, scopePos - 1 /*magic!*/, abc)) { - return null; - } - scopePos--; - } - } - prevStart = ex.start; - } catch (ConvertException ex1) { - // ignore - } - } - //stats.maxscope+=initScope; - return stats; - } - - private void visitCode(int ip, int lastIp, HashMap> refs) throws InterruptedException { - List toVisit = new ArrayList<>(); - List toVisitLast = new ArrayList<>(); - toVisit.add(ip); - toVisitLast.add(lastIp); - while (!toVisit.isEmpty()) { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - ip = toVisit.remove(0); - lastIp = toVisitLast.remove(0); - while (ip < code.size()) { - if (!refs.containsKey(ip)) { - refs.put(ip, new ArrayList<>()); - } - refs.get(ip).add(lastIp); - lastIp = ip; - if (refs.get(ip).size() > 1) { - break; - } - AVM2Instruction ins = code.get(ip); - if (ins.definition instanceof ThrowIns) { - break; - } - if (ins.definition instanceof ReturnValueIns) { - break; - } - if (ins.definition instanceof ReturnVoidIns) { - break; - } - if (ins.definition instanceof LookupSwitchIns) { - try { - for (int i = 2; i < ins.operands.length; i++) { - toVisit.add(adr2pos(pos2adr(ip) + ins.operands[i])); - toVisitLast.add(ip); - } - ip = adr2pos(pos2adr(ip) + ins.operands[0]); - continue; - } catch (ConvertException ex) { - } - } - if (ins.definition instanceof JumpIns) { - try { - ip = adr2pos(ins.getTargetAddress()); - continue; - } catch (ConvertException ex) { - logger.log(Level.FINE, null, ex); - } - } else if (ins.definition instanceof IfTypeIns) { - try { - toVisit.add(adr2pos(ins.getTargetAddress())); - toVisitLast.add(ip); - } catch (ConvertException ex) { - logger.log(Level.FINE, null, ex); - } - } - ip++; - } - }; - } - - public HashMap> visitCode(MethodBody body) throws InterruptedException { - HashMap> refs = new HashMap<>(); - for (int i = 0; i < code.size(); i++) { - refs.put(i, new ArrayList<>()); - } - visitCode(0, 0, refs); - int pos = 0; - for (ABCException e : body.exceptions) { - pos++; - try { - visitCode(adr2pos(e.start, true), adr2pos(e.start, true) - 1, refs); - visitCode(adr2pos(e.start, true), -1, refs); - visitCode(adr2pos(e.target), adr2pos(e.end, true), refs); - visitCode(adr2pos(e.end, true), -pos, refs); - } catch (ConvertException ex) { - logger.log(Level.SEVERE, "Visitcode error", ex); - } - } - return refs; - } - - public void removeIgnored(MethodBody body) throws InterruptedException { - //System.err.println("removing ignored..."); - for (int i = 0; i < code.size(); i++) { - if (code.get(i).isIgnored()) { - removeInstruction(i, body); - i--; - } - } - //System.err.println("/ignored removed"); - } - - public int removeDeadCode(MethodBody body) throws InterruptedException { - HashMap> refs = visitCode(body); - int cnt = 0; - for (int i = code.size() - 1; i >= 0; i--) { - if (refs.get(i).isEmpty()) { - code.get(i).setIgnored(true, 0); - cnt++; - } - } - - removeIgnored(body); - - for (int i = code.size() - 1; i >= 0; i--) { - AVM2Instruction ins = code.get(i); - if (ins.definition instanceof JumpIns) { - if (ins.operands[0] == 0) { - ins.setIgnored(true, 0); - cnt++; - } - } - } - - removeIgnored(body); - - return cnt; - } - - public boolean inlineJumpExit() { - boolean modified = false; - int csize = code.size(); - for (int i = 0; i < csize; i++) { - AVM2Instruction ins = code.get(i); - int insLen = code.get(i).getBytesLength(); - long ofs = pos2adr(i); - if (ins.definition instanceof JumpIns) { - long targetOfs = ofs + insLen + ins.operands[0]; - try { - int ni = adr2pos(targetOfs); - if (ni < code.size() && ni > -1) { - AVM2Instruction ins2 = code.get(ni); - if (ins2.isExit()) { - code.set(i, new AVM2Instruction(ofs, ins2.definition, ins2.operands)); - modified = true; - } - } - } catch (ConvertException ex) { - //ignore - } - } - } - - return modified; - } - - private static int getMostCommonIp(AVM2GraphSource code, List branches) { - List> reachable = new ArrayList<>(); - for (int i = 0; i < branches.size(); i++) { - List r = new ArrayList<>(); - getReachableIps(code, branches.get(i), r); - } - - int commonLevel; - Map levelMap = new HashMap<>(); - for (List first : reachable) { - int maxclevel = 0; - Set visited = new HashSet<>(); - for (Integer p : first) { - if (visited.contains(p)) { - continue; - } - visited.add(p); - boolean common = true; - commonLevel = 1; - for (List r : reachable) { - if (r == first) { - continue; - } - if (r.contains(p)) { - commonLevel++; - } - } - if (commonLevel <= maxclevel) { - continue; - } - maxclevel = commonLevel; - if (levelMap.containsKey(p)) { - if (levelMap.get(p) > commonLevel) { - commonLevel = levelMap.get(p); - } - } - levelMap.put(p, commonLevel); - if (common) { - //return p; - } - } - } - for (int i = reachable.size() - 1; i >= 2; i--) { - for (Integer p : levelMap.keySet()) { - if (levelMap.get(p) == i) { - return p; - } - } - } - for (Integer p : levelMap.keySet()) { - if (levelMap.get(p) == branches.size()) { - return p; - } - } - return -1; - } - - public static void getReachableIps(AVM2GraphSource code, int ip, List reachable) { - do { - if (reachable.contains(ip)) { - return; - } - reachable.add(ip); - GraphSourceItem ins = code.get(ip); - if (ins.isJump() || ins.isBranch()) { - List branches = ins.getBranches(code); - for (int i = 1; i < branches.size(); i++) { - getReachableIps(code, branches.get(i), reachable); - } - ip = branches.get(0); - continue; - } - ip++; - } while (ip < code.size()); - } - - public static boolean isDirectAncestor(int currentIp, int ancestor, HashMap> refs) { - return isDirectAncestor(currentIp, ancestor, refs, new ArrayList<>()); - } - - private static boolean isDirectAncestor(int currentIp, int ancestor, HashMap> refs, List visited) { - if (currentIp == -1) { - return true; - } - do { - if (currentIp == ancestor) { - return true; - } - if (currentIp == 0) { - return false; - } - if (visited.contains(currentIp)) { - return true; - } - visited.add(currentIp); - if (refs.containsKey(currentIp)) { - List currentRefs = refs.get(currentIp); - if ((currentRefs != null) && (!currentRefs.isEmpty())) { - for (int i = 1; i < currentRefs.size(); i++) { - if (!isDirectAncestor(currentRefs.get(i), ancestor, refs, visited)) { - return false; - } - } - currentIp = currentRefs.get(0); - continue; - } - } - currentIp--; - } while (currentIp >= 0); - return false; - } - - public static boolean getPreviousReachableIps(int currentIp, HashMap> refs, Set reachable, Set visited) { - do { - if (visited.contains(currentIp)) { - return false; - } - reachable.add(currentIp); - visited.add(currentIp); - if (refs.containsKey(currentIp)) { - List currentRefs = refs.get(currentIp); - if ((currentRefs != null) && (!currentRefs.isEmpty())) { - if (currentRefs.size() == 1) { - currentIp = currentRefs.get(0); - continue; - } - boolean r = false; - for (int i = 0; i < currentRefs.size(); i++) { - Set nr = new HashSet<>(); - boolean v = getPreviousReachableIps(currentRefs.get(i), refs, nr, visited); - if ((!v) || nr.contains(0)) { - reachable.addAll(nr); - } - r = r || v; - } - return r; - } - } - currentIp--; - } while (currentIp >= 0); - return true; - } - - @Override - public AVM2Code clone() { - try { - AVM2Code ret = (AVM2Code) super.clone(); - if (code != null) { - List codeCopy = new ArrayList<>(code.size()); - for (AVM2Instruction ins : code) { - codeCopy.add(ins.clone()); - } - ret.code = codeCopy; - } - - ret.killedRegs = new HashMap<>(); - return ret; - } catch (CloneNotSupportedException ex) { - throw new RuntimeException(); - } - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2; + +import com.jpexs.decompiler.flash.EndOfStreamException; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ABCInputStream; +import com.jpexs.decompiler.flash.abc.CopyOutputStream; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorGetSet; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorRegistersOld; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorSimpleOld; +import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException; +import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2VerifyErrorException; +import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph; +import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphSource; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2InstructionFlag; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; +import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.UnknownInstruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf64Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li8Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf64Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si32Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si8Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi16Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi1Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi8Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DivideIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitNotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewActivationIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewArrayIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewClassIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewObjectIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugFileIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallMethodIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropLexIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallStaticIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfEqIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfGeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfGtIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfLeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfLtIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNGeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNGtIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNLeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNLtIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfTrueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal0Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal1Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal2Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal3Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal0Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal1Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal2Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal3Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.DeletePropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindDefIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetDescendantsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalScopeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalSlotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSlotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNextIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InitPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextNameIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextValueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NopIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetGlobalSlotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AbsJumpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AddDIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AddPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.AllocIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.BkptIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.BkptLineIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CallInterfaceIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CallSuperIdIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CodeGenOpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceBIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceDIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceOIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.CoerceUIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConcatIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertF4Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertFIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertMIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ConvertMPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecLocalPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecodeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecrementPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DelDescendantsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DeletePropertyLateIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DividePIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DoubleToAtomIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.FindPropGlobalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.GetOuterScopeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncLocalPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncrementPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.InvalidIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.Lf32x4Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.MarkIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.ModuloPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.MultiplyPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.NegatePIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PrologueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushConstantIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushDNanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushDecimalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushFloat4Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.PushFloatIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SendEnterIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SetPropertyLateIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.Sf32x4Ins; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SubtractPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.SweepIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.TimestampIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.UnPlusIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.VerifyOpIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.VerifyPassIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.WbIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNamespaceIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNanIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUIntIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ApplyTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeLateIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceSIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertBIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertDIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertOIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertSIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertUIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.InstanceOfIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeLateIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.TypeOfIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.CheckFilterIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSLateIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXAttrIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXElemIns; +import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.decompiler.flash.abc.types.ABCException; +import com.jpexs.decompiler.flash.abc.types.AssignedValue; +import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.ValueKind; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; +import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; +import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.dumpview.DumpInfo; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import com.jpexs.decompiler.graph.Block; +import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.SimpleValue; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.BinaryOpItem; +import com.jpexs.decompiler.graph.model.ExitItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.ScriptEndItem; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.ReflectionTools; +import com.jpexs.helpers.stat.Statistics; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class AVM2Code implements Cloneable { + + private static final Logger logger = Logger.getLogger(AVM2Code.class.getName()); + + private static final boolean DEBUG_MODE = false; + + public static int toSourceLimit = -1; + + public List code; + + public static boolean DEBUG_REWRITE = false; + + public static final int OPT_U30 = 0x100; + + public static final int OPT_U8 = 0x200; + + public static final int OPT_S24 = 0x300; + + public static final int OPT_CASE_OFFSETS = 0x400; + + public static final int OPT_S8 = 0x500; + + public static final int OPT_S16 = 0x600; + + public static final int DAT_MULTINAME_INDEX = OPT_U30 + 0x01; + + public static final int DAT_ARG_COUNT = OPT_U30 + 0x02; + + public static final int DAT_METHOD_INDEX = OPT_U30 + 0x03; + + public static final int DAT_STRING_INDEX = OPT_U30 + 0x04; + + public static final int DAT_DEBUG_TYPE = OPT_U8 + 0x05; + + public static final int DAT_REGISTER_INDEX = OPT_U8 + 0x06; + + public static final int DAT_LINENUM = OPT_U30 + 0x07; + + public static final int DAT_LOCAL_REG_INDEX = OPT_U30 + 0x08; + + public static final int DAT_SLOT_INDEX = OPT_U30 + 0x09; + + public static final int DAT_SCOPE_INDEX = OPT_U30 + 0x0A; + + public static final int DAT_OFFSET = OPT_S24 + 0x0B; + + public static final int DAT_EXCEPTION_INDEX = OPT_U30 + 0x0C; + + public static final int DAT_CLASS_INDEX = OPT_U30 + 0x0D; + + public static final int DAT_INT_INDEX = OPT_U30 + 0x0E; + + public static final int DAT_UINT_INDEX = OPT_U30 + 0x0F; + + public static final int DAT_DOUBLE_INDEX = OPT_U30 + 0x10; + + public static final int DAT_DECIMAL_INDEX = OPT_U30 + 0x11; + + public static final int DAT_CASE_BASEOFFSET = OPT_S24 + 0x12; + + public static final int DAT_NUMBER_CONTEXT = OPT_U30 + 0x13; + + public static final int DAT_DISPATCH_ID = OPT_U30 + 0x14; + + public static final int DAT_FLOAT_INDEX = OPT_U30 + 0x15; + + public static final int DAT_FLOAT4_INDEX = OPT_U30 + 0x16; + + public static final int DAT_NAMESPACE_INDEX = OPT_U30 + 0x17; + + public static String operandTypeSizeToString(int ot) { + int sizeType = ot & 0xff00; + switch (sizeType) { + case OPT_U30: + return "U30"; + case OPT_S16: + return "S16"; + case OPT_U8: + return "U8"; + case OPT_S8: + return "S8"; + case OPT_S24: + return "S24"; + case OPT_CASE_OFFSETS: + return "S24(=n), S24[n]"; + } + return ""; + } + + private static Map operandDataTypeIdentifiers = ReflectionTools.getConstNamesMap(AVM2Code.class, Integer.class, "^DAT_(.*)$"); + + public static String operandTypeToString(int ot, boolean withTypeSize) { + String typeSize = operandTypeSizeToString(ot); + if (ot == OPT_CASE_OFFSETS) { + return "number" + (withTypeSize ? "(U30)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", ..."; + } + if (operandDataTypeIdentifiers.containsKey(ot)) { + String dataType = operandDataTypeIdentifiers.get(ot); + return dataType + (withTypeSize ? "(" + typeSize + ")" : ""); + } else { + return typeSize; + } + + } + + public static final InstructionDefinition[] instructionSet = new InstructionDefinition[256]; + + public static final InstructionDefinition[] allInstructionSet = new InstructionDefinition[]{ + /*0x00*/null, + /*0x01*/ new BkptIns(), + /*0x02*/ new NopIns(), + /*0x03*/ new ThrowIns(), + /*0x04*/ new GetSuperIns(), + /*0x05*/ new SetSuperIns(), + /*0x06*/ new DXNSIns(), + /*0x07*/ new DXNSLateIns(), + /*0x08*/ new KillIns(), + /*0x09*/ new LabelIns(), + /*0x0A*/ new Lf32x4Ins(), + /*0x0B*/ new Sf32x4Ins(), + /*0x0C*/ new IfNLtIns(), + /*0x0D*/ new IfNLeIns(), + /*0x0E*/ new IfNGtIns(), + /*0x0F*/ new IfNGeIns(), + /*0x10*/ new JumpIns(), + /*0x11*/ new IfTrueIns(), + /*0x12*/ new IfFalseIns(), + /*0x13*/ new IfEqIns(), + /*0x14*/ new IfNeIns(), + /*0x15*/ new IfLtIns(), + /*0x16*/ new IfLeIns(), + /*0x17*/ new IfGtIns(), + /*0x18*/ new IfGeIns(), + /*0x19*/ new IfStrictEqIns(), + /*0x1A*/ new IfStrictNeIns(), + /*0x1B*/ new LookupSwitchIns(), + /*0x1C*/ new PushWithIns(), + /*0x1D*/ new PopScopeIns(), + /*0x1E*/ new NextNameIns(), + /*0x1F*/ new HasNextIns(), + /*0x20*/ new PushNullIns(), + /*0x21*/ new PushUndefinedIns(), + /*0x22*/ new PushFloatIns(), //major 47+ + /*0x22*/ new PushConstantIns(), //before major 47 + /*0x23*/ new NextValueIns(), + /*0x24*/ new PushByteIns(), + /*0x25*/ new PushShortIns(), + /*0x26*/ new PushTrueIns(), + /*0x27*/ new PushFalseIns(), + /*0x28*/ new PushNanIns(), + /*0x29*/ new PopIns(), + /*0x2A*/ new DupIns(), + /*0x2B*/ new SwapIns(), + /*0x2C*/ new PushStringIns(), + /*0x2D*/ new PushIntIns(), + /*0x2E*/ new PushUIntIns(), + /*0x2F*/ new PushDoubleIns(), + /*0x30*/ new PushScopeIns(), + /*0x31*/ new PushNamespaceIns(), + /*0x32*/ new HasNext2Ins(), + /*0x33*/ new PushDecimalIns(), //pushdecimal(minor 17), lix8 (internal-only) according to Tamarin + /*0x34*/ new PushDNanIns(), //pushdnan according to Flex SDK, lix16 (internal-only) according to Tamarin + /*0x35*/ new Li8Ins(), + /*0x36*/ new Li16Ins(), + /*0x37*/ new Li32Ins(), + /*0x38*/ new Lf32Ins(), + /*0x39*/ new Lf64Ins(), + /*0x3A*/ new Si8Ins(), + /*0x3B*/ new Si16Ins(), + /*0x3C*/ new Si32Ins(), + /*0x3D*/ new Sf32Ins(), + /*0x3E*/ new Sf64Ins(), + /*0x3F*/ null, + /*0x40*/ new NewFunctionIns(), + /*0x41*/ new CallIns(), + /*0x42*/ new ConstructIns(), + /*0x43*/ new CallMethodIns(), + /*0x44*/ new CallStaticIns(), + /*0x45*/ new CallSuperIns(), + /*0x46*/ new CallPropertyIns(), + /*0x47*/ new ReturnVoidIns(), + /*0x48*/ new ReturnValueIns(), + /*0x49*/ new ConstructSuperIns(), + /*0x4A*/ new ConstructPropIns(), + /*0x4B*/ new CallSuperIdIns(), + /*0x4C*/ new CallPropLexIns(), + /*0x4D*/ new CallInterfaceIns(), + /*0x4E*/ new CallSuperVoidIns(), + /*0x4F*/ new CallPropVoidIns(), + /*0x50*/ new Sxi1Ins(), + /*0x51*/ new Sxi8Ins(), + /*0x52*/ new Sxi16Ins(), + /*0x53*/ new ApplyTypeIns(), + /*0x54*/ new PushFloat4Ins(), //major 47+ + /*0x55*/ new NewObjectIns(), + /*0x56*/ new NewArrayIns(), + /*0x57*/ new NewActivationIns(), + /*0x58*/ new NewClassIns(), + /*0x59*/ new GetDescendantsIns(), + /*0x5A*/ new NewCatchIns(), + /*0x5B*/ new DelDescendantsIns(), //deldescendants according to Flex, findpropglobalstrict(internal-only) according to Tamarin + /*0x5C*/ new FindPropGlobalIns(), //Tamarin (internal-only) + /*0x5D*/ new FindPropertyStrictIns(), + /*0x5E*/ new FindPropertyIns(), + /*0x5F*/ new FindDefIns(), + /*0x60*/ new GetLexIns(), + /*0x61*/ new SetPropertyIns(), + /*0x62*/ new GetLocalIns(), + /*0x63*/ new SetLocalIns(), + /*0x64*/ new GetGlobalScopeIns(), + /*0x65*/ new GetScopeObjectIns(), + /*0x66*/ new GetPropertyIns(), + /*0x67*/ new GetOuterScopeIns(), // new GetPropertyLateIns() + /*0x68*/ new InitPropertyIns(), + /*0x69*/ new SetPropertyLateIns(), + /*0x6A*/ new DeletePropertyIns(), + /*0x6B*/ new DeletePropertyLateIns(), + /*0x6C*/ new GetSlotIns(), + /*0x6D*/ new SetSlotIns(), + /*0x6E*/ new GetGlobalSlotIns(), + /*0x6F*/ new SetGlobalSlotIns(), + /*0x70*/ new ConvertSIns(), + /*0x71*/ new EscXElemIns(), + /*0x72*/ new EscXAttrIns(), + /*0x73*/ new ConvertIIns(), + /*0x74*/ new ConvertUIns(), + /*0x75*/ new ConvertDIns(), + /*0x76*/ new ConvertBIns(), + /*0x77*/ new ConvertOIns(), + /*0x78*/ new CheckFilterIns(), + /*0x79*/ new ConvertMIns(), //minor 17 (Flex) + /*0x79*/ new ConvertFIns(), //major 47+, SWF 15+ + /*0x7A*/ new ConvertMPIns(), //minor 17 (Flex) + /*0x7A*/ new UnPlusIns(), //major 47+, SWF 15+ + /*0x7B*/ new ConvertF4Ins(), //major 47+, SWF 15+ + /*0x7C*/ null, + /*0x7D*/ null, + /*0x7E*/ null, + /*0x7F*/ null, + /*0x80*/ new CoerceIns(), + /*0x81*/ new CoerceBIns(), + /*0x82*/ new CoerceAIns(), + /*0x83*/ new CoerceIIns(), + /*0x84*/ new CoerceDIns(), + /*0x85*/ new CoerceSIns(), + /*0x86*/ new AsTypeIns(), + /*0x87*/ new AsTypeLateIns(), + /*0x88*/ new CoerceUIns(), + /*0x89*/ new CoerceOIns(), + /*0x8A*/ null, + /*0x8B*/ null, + /*0x8C*/ null, + /*0x8D*/ null, + /*0x8E*/ null, + /*0x8F*/ new NegatePIns(), + /*0x90*/ new NegateIns(), + /*0x91*/ new IncrementIns(), + /*0x92*/ new IncLocalIns(), + /*0x93*/ new DecrementIns(), + /*0x94*/ new DecLocalIns(), + /*0x95*/ new TypeOfIns(), + /*0x96*/ new NotIns(), + /*0x97*/ new BitNotIns(), + /*0x98*/ null, + /*0x99*/ null, + /*0x9A*/ new ConcatIns(), + /*0x9B*/ new AddDIns(), + /*0x9C*/ new IncrementPIns(), + /*0x9D*/ new IncLocalPIns(), + /*0x9E*/ new DecrementPIns(), + /*0x9F*/ new DecLocalPIns(), + /*0xA0*/ new AddIns(), + /*0xA1*/ new SubtractIns(), + /*0xA2*/ new MultiplyIns(), + /*0xA3*/ new DivideIns(), + /*0xA4*/ new ModuloIns(), + /*0xA5*/ new LShiftIns(), + /*0xA6*/ new RShiftIns(), + /*0xA7*/ new URShiftIns(), + /*0xA8*/ new BitAndIns(), + /*0xA9*/ new BitOrIns(), + /*0xAA*/ new BitXorIns(), + /*0xAB*/ new EqualsIns(), + /*0xAC*/ new StrictEqualsIns(), + /*0xAD*/ new LessThanIns(), + /*0xAE*/ new LessEqualsIns(), + /*0xAF*/ new GreaterThanIns(), + /*0xB0*/ new GreaterEqualsIns(), + /*0xB1*/ new InstanceOfIns(), + /*0xB2*/ new IsTypeIns(), + /*0xB3*/ new IsTypeLateIns(), + /*0xB4*/ new InIns(), + /*0xB5*/ new AddPIns(), + /*0xB6*/ new SubtractPIns(), + /*0xB7*/ new MultiplyPIns(), + /*0xB8*/ new DividePIns(), + /*0xB9*/ new ModuloPIns(), + /*0xBA*/ null, + /*0xBB*/ null, + /*0xBC*/ null, + /*0xBD*/ null, + /*0xBE*/ null, + /*0xBF*/ null, + /*0xC0*/ new IncrementIIns(), + /*0xC1*/ new DecrementIIns(), + /*0xC2*/ new IncLocalIIns(), + /*0xC3*/ new DecLocalIIns(), + /*0xC4*/ new NegateIIns(), + /*0xC5*/ new AddIIns(), + /*0xC6*/ new SubtractIIns(), + /*0xC7*/ new MultiplyIIns(), + /*0xC8*/ null, + /*0xC9*/ null, + /*0xCA*/ null, + /*0xCB*/ null, + /*0xCC*/ null, + /*0xCD*/ null, + /*0xCE*/ null, + /*0xCF*/ null, + /*0xD0*/ new GetLocal0Ins(), + /*0xD1*/ new GetLocal1Ins(), + /*0xD2*/ new GetLocal2Ins(), + /*0xD3*/ new GetLocal3Ins(), + /*0xD4*/ new SetLocal0Ins(), + /*0xD5*/ new SetLocal1Ins(), + /*0xD6*/ new SetLocal2Ins(), + /*0xD7*/ new SetLocal3Ins(), + /*0xD8*/ null, + /*0xD9*/ null, + /*0xDA*/ null, + /*0xDB*/ null, + /*0xDC*/ null, + /*0xDD*/ null, + /*0xDE*/ null, + /*0xDF*/ null, + /*0xE0*/ null, + /*0xE1*/ null, + /*0xE2*/ null, + /*0xE3*/ null, + /*0xE4*/ null, + /*0xE5*/ null, + /*0xE6*/ null, + /*0xE7*/ null, + /*0xE8*/ null, + /*0xE9*/ null, + /*0xEA*/ null, + /*0xEB*/ null, + /*0xEC*/ null, + /*0xED*/ new InvalidIns(), + /*0xEE*/ new AbsJumpIns(), + /*0xEF*/ new DebugIns(), + /*0xF0*/ new DebugLineIns(), + /*0xF1*/ new DebugFileIns(), + /*0xF2*/ new BkptLineIns(), + /*0xF3*/ new TimestampIns(), + /*0xF4*/ null, + /*0xF5*/ new VerifyPassIns(), + /*0xF6*/ new AllocIns(), + /*0xF7*/ new MarkIns(), + /*0xF8*/ new WbIns(), + /*0xF9*/ new PrologueIns(), + /*0xFA*/ new SendEnterIns(), + /*0xFB*/ new DoubleToAtomIns(), + /*0xFC*/ new SweepIns(), + /*0xFD*/ new CodeGenOpIns(), + /*0xFE*/ new VerifyOpIns(), + /*0xFF*/ new DecodeIns(),}; + // endoflist + + static { + + for (int i = 0; i < allInstructionSet.length; i++) { + if (allInstructionSet[i] != null) { + int opCode = allInstructionSet[i].instructionCode; + if (instructionSet[opCode] == null) { + instructionSet[opCode] = allInstructionSet[i]; + } else if (instructionSet[opCode].hasFlag(AVM2InstructionFlag.NO_FLASH_PLAYER) && !allInstructionSet[i].hasFlag(AVM2InstructionFlag.NO_FLASH_PLAYER)) { + instructionSet[opCode] = allInstructionSet[i]; + } //Prefer without decimal: + else if (instructionSet[opCode].hasFlag(AVM2InstructionFlag.ES4_NUMERICS_MINOR) && !allInstructionSet[i].hasFlag(AVM2InstructionFlag.ES4_NUMERICS_MINOR)) { + instructionSet[opCode] = allInstructionSet[i]; + } //Prefer without float: + else if (instructionSet[opCode].hasFlag(AVM2InstructionFlag.FLOAT_MAJOR) && !allInstructionSet[i].hasFlag(AVM2InstructionFlag.FLOAT_MAJOR)) { + instructionSet[opCode] = allInstructionSet[i]; + } + } + } + + for (int i = 0; + i < instructionSet.length; + i++) { + if (instructionSet[i] == null) { + instructionSet[i] = new UnknownInstruction(i); + } + } + + } + + public static final String IDENTOPEN = "/*IDENTOPEN*/"; + + public static final String IDENTCLOSE = "/*IDENTCLOSE*/"; + + public AVM2Code() { + code = new ArrayList<>(); + } + + public AVM2Code(int capacity) { + code = new ArrayList<>(capacity); + } + + public AVM2Code(ArrayList instructions) { + code = instructions; + } + + public Object execute(HashMap arguments, AVM2ConstantPool constants) throws AVM2ExecutionException { + return execute(arguments, constants, null); + } + + public Object execute(HashMap arguments, AVM2ConstantPool constants, AVM2RuntimeInfo runtimeInfo) throws AVM2ExecutionException { + int pos = 0; + LocalDataArea lda = new LocalDataArea(); + lda.methodName = "methodName"; // todo: needed for VerifyError exception message + lda.localRegisters = arguments; + lda.runtimeInfo = runtimeInfo; + + for (AVM2Instruction ins : code) { + ins.definition.verify(lda, constants, ins); + } + + while (pos < code.size()) { + AVM2Instruction ins = code.get(pos); + if (!ins.definition.execute(lda, constants, ins)) { + return null; + } + + if (lda.jump != null) { + try { + pos = adr2pos(lda.jump); + } catch (ConvertException ex) { + throw new AVM2VerifyErrorException(AVM2VerifyErrorException.BRANCH_TARGET_INVALID_INSTRUCTION, lda.isDebug()); + } + lda.jump = null; + } else { + pos++; + } + + if (lda.returnValue != null) { + return lda.returnValue; + } + } + + return Undefined.INSTANCE; + } + + public void calculateDebugFileLine(ABC abc) { + calculateDebugFileLine(null, 0, 0, abc, new HashSet<>()); + } + + private boolean calculateDebugFileLine(String debugFile, int debugLine, int pos, ABC abc, Set seen) { + while (pos < code.size()) { + AVM2Instruction ins = code.get(pos); + if (seen.contains(pos)) { + return true; + } + + seen.add(pos); + + if (ins.definition instanceof DebugFileIns) { + debugFile = abc.constants.getString(ins.operands[0]); + } + + if (ins.definition instanceof DebugLineIns) { + debugLine = ins.operands[0]; + } + + ins.setFileLine(debugFile, debugLine); + + if (ins.definition instanceof NewFunctionIns) { + //Only analyze NewFunction objects that are not immediately discarded by Pop. + //This avoids bogus functions used in obfuscation or special compilers that can lead to infinite recursion. + if ((pos + 1 < code.size()) && !(code.get(pos + 1).definition instanceof PopIns)) { + MethodBody innerBody = abc.findBody(ins.operands[0]); + if (innerBody != null) { //Ignore functions without body + innerBody.getCode().calculateDebugFileLine(debugFile, debugLine, 0, abc, new HashSet<>()); + } + } + } + + if (ins.definition instanceof ReturnValueIns) { + return true; + } + if (ins.definition instanceof ReturnVoidIns) { + return true; + } + if (ins.definition instanceof JumpIns) { + try { + pos = adr2pos(ins.getTargetAddress()); + continue; + } catch (ConvertException ex) { + return false; + } + } else if (ins.definition instanceof IfTypeIns) { + try { + int newpos = adr2pos(ins.getTargetAddress()); + calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen); + } catch (ConvertException ex) { + return false; + } + } + if (ins.definition instanceof LookupSwitchIns) { + for (int i = 0; i < ins.operands.length; i++) { + if (i == 1) { + continue; + } + try { + int newpos = adr2pos(pos2adr(pos) + ins.operands[i]); + if (!calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen)) { + return false; + } + } catch (ConvertException ex) { + return false; + } + } + } + pos++; + } + return true; + } + + /** + * Removes nonexistent indices to constants from instruction operands. + * + * @param constants + */ + public void removeWrongIndices(AVM2ConstantPool constants) { + for (AVM2Instruction ins : code) { + for (int i = 0; i < ins.definition.operands.length; i++) { + if (ins.definition.operands[i] == DAT_MULTINAME_INDEX && ins.operands[i] >= constants.getMultinameCount()) { + ins.operands[i] = 0; + } + if (ins.definition.operands[i] == DAT_DOUBLE_INDEX && ins.operands[i] >= constants.getDoubleCount()) { + ins.operands[i] = 0; + } + if (ins.definition.operands[i] == DAT_INT_INDEX && ins.operands[i] >= constants.getIntCount()) { + ins.operands[i] = 0; + } + if (ins.definition.operands[i] == DAT_UINT_INDEX && ins.operands[i] >= constants.getUIntCount()) { + ins.operands[i] = 0; + } + if (ins.definition.operands[i] == DAT_STRING_INDEX && ins.operands[i] >= constants.getStringCount()) { + ins.operands[i] = 0; + } + } + } + } + + public AVM2Code(ABCInputStream ais, MethodBody body) throws IOException { + Map codeMap = new HashMap<>(); + DumpInfo diParent = ais.dumpInfo; + List addresses = new ArrayList<>(); + //Do not add new jumps when processing these addresses (unreachable code,etc.) + List unAdresses = new ArrayList<>(); + //Handle lookupswitches at the end - they can be invalid. Handle other instruction first so we can decide lookupswitch to be invalid based on other instructions inside it + //Flashplayer does not check casecount in lookupswitch instruction so the instruction can "be" long and over other instructions + List switchAddresses = new ArrayList<>(); + int availableBytes = ais.available(); + for (int i = 0; i < availableBytes; i++) { + codeMap.put((long) i, new AVM2Instruction(i, AVM2Instructions.Nop, null)); + } + + long startPos = ais.getPosition(); + addresses.add(startPos); + if (body != null) { + for (ABCException e : body.exceptions) { + addresses.add((long) e.start); + addresses.add((long) e.end); + addresses.add((long) e.target); + } + } + + loopaddr: + while (!addresses.isEmpty() || !switchAddresses.isEmpty() || !unAdresses.isEmpty()) { + long address; + boolean isSwitch = false; + boolean handleJumps = true; + if (!addresses.isEmpty()) { + address = addresses.remove(0); + } else if (!switchAddresses.isEmpty()) { + address = switchAddresses.remove(0); + isSwitch = true; + } else { + address = unAdresses.remove(0); + handleJumps = false; + } + if (address < startPos) // no jump outside block + { + continue; + } + try { + ais.seek(address); + while (ais.available() > 0) { + long startOffset = ais.getPosition(); + + if (codeMap.containsKey(startOffset) && !(codeMap.get(startOffset).definition instanceof NopIns)) { + continue loopaddr; + } + + DumpInfo di = ais.newDumpLevel("instruction", "instruction"); + InstructionDefinition instr = null; + try { + int instructionCode = ais.read("instructionCode"); + instr = instructionSet[instructionCode]; + if (instructionCode == AVM2Instructions.LookupSwitch) { + if (!isSwitch) { + switchAddresses.add(startOffset); + continue loopaddr; + } else { + isSwitch = false; + } + } + if (di != null) { + di.name = instr.instructionName; + } + if (instr != null) { + int[] actualOperands = null; + + if (instructionCode == AVM2Instructions.LookupSwitch) { // switch + int firstOperand = ais.readS24("default_offset"); + int case_count = ais.readU30("case_count"); + long afterCasePos = ais.getPosition() + 3 * (case_count + 1); + + boolean invalidSwitch = false; + //If there are already some instructions in the lookupswitch bytes, the lookupswitch is invalid (obfuscation) + for (long a = startOffset; a < afterCasePos; a++) { + if (codeMap.containsKey(a) && (!(codeMap.get(a).definition instanceof NopIns))) { + invalidSwitch = true; + break; + } + } + + long totalBytes = ais.getPosition() + ais.available(); + + //If the lookupswitch case_count are larger than available bytes, the lookupswitch is invalid (obfuscation) + if (afterCasePos > totalBytes) { + invalidSwitch = true; + } + if (invalidSwitch) { + continue loopaddr; + } else { + actualOperands = new int[case_count + 3]; + actualOperands[0] = firstOperand; + actualOperands[1] = case_count; + for (int c = 0; c < case_count + 1; c++) { + actualOperands[2 + c] = ais.readS24("actualOperand"); + } + } + } else if (instr.operands.length > 0) { + actualOperands = new int[instr.operands.length]; + for (int op = 0; op < instr.operands.length; op++) { + switch (instr.operands[op] & 0xff00) { + case OPT_U30: + actualOperands[op] = ais.readU30("operand"); + break; + case OPT_S16: + actualOperands[op] = (short) ais.readU30("operand"); + break; + case OPT_U8: + actualOperands[op] = ais.read("operand"); + break; + case OPT_S8: + actualOperands[op] = (byte) ais.read("operand"); + break; + case OPT_S24: + actualOperands[op] = ais.readS24("operand"); + break; + } + } + } + + AVM2Instruction ai = new AVM2Instruction(startOffset, instr, actualOperands); + long endOffset = ais.getPosition(); + + boolean hasRoom = true; + for (long p = startOffset; p < endOffset; p++) { + if (codeMap.containsKey(p) && !(codeMap.get(p).definition instanceof NopIns)) { + hasRoom = false; + } + } + + //There is no room for this instruction (it is invalid?) + if (!hasRoom) { + continue loopaddr; + } + for (long p = startOffset; p < endOffset; p++) { + codeMap.put(p, ai); + } + + if ((instr instanceof IfTypeIns)) { + if (handleJumps) { + long target = ais.getPosition() + actualOperands[0]; + addresses.add(target); + } else { + actualOperands[0] = 0; + } + } + + if (instr instanceof JumpIns) { + if (handleJumps) { + long target = ais.getPosition() + actualOperands[0]; + addresses.add(target); + unAdresses.add(ais.getPosition()); + continue loopaddr; + } else { + actualOperands[0] = 0; + } + } + + if (instr.isExitInstruction()) { //do not process jumps if there is return/throw instruction + if (handleJumps) { + unAdresses.add(ais.getPosition()); + continue loopaddr; + } + } + if ((instr instanceof LookupSwitchIns) && actualOperands != null) { + if (handleJumps) { + addresses.add(startOffset + actualOperands[0]); + + for (int c = 2; c < actualOperands.length; c++) { + addresses.add(startOffset + actualOperands[c]); + } + unAdresses.add(ais.getPosition()); + continue loopaddr; + } else { + int swlen = (int) (endOffset - startOffset); + actualOperands[0] = swlen; + for (int c = 2; c < actualOperands.length; c++) { + actualOperands[c] = swlen; + } + } + } + + } else { + break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions) + //throw new UnknownInstructionCode(instructionCode); + } + } finally { + if (instr == null) { + ais.endDumpLevel(); + } else { + ais.endDumpLevel(instr.instructionCode); + } + } + } + } catch (EndOfStreamException ex) { + // lookupswitch obfuscation, ignore + ais.endDumpLevelUntil(diParent); + } + } + + if (diParent != null) { + diParent.sortChildren(); + } + + code = new ArrayList<>(codeMap.size()); + AVM2Instruction prev = null; + for (int i = 0; i < availableBytes; i++) { + AVM2Instruction ins = codeMap.get((long) i); + if (prev != ins) { + code.add(ins); + } + prev = ins; + } + } + + public void compact() { + if (code instanceof ArrayList) { + ((ArrayList) code).trimToSize(); + } + } + + public byte[] getBytes() { + return getBytes(null); + } + + public byte[] getBytes(byte[] origBytes) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + OutputStream cos; + if ((origBytes != null) && (DEBUG_REWRITE)) { + ByteArrayInputStream origis = new ByteArrayInputStream(origBytes); + cos = new CopyOutputStream(bos, origis); + } else { + cos = bos; + } + try { + for (AVM2Instruction instruction : code) { + cos.write(instruction.getBytes()); + } + } catch (IOException ex) { + } + return bos.toByteArray(); + } + + public void markOffsets() { + long address = 0; + for (int i = 0; i < code.size(); i++) { + code.get(i).setAddress(address); + address += code.get(i).getBytesLength(); + } + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + for (AVM2Instruction instruction : code) { + s.append(instruction.toString()); + s.append(Helper.newLine); + } + return s.toString(); + } + + public String toASMSource() { + return toASMSource(new AVM2ConstantPool()); + } + + public String toASMSource(AVM2ConstantPool constants) { + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + toASMSource(constants, null, null, null, new ArrayList<>(), ScriptExportMode.PCODE, writer); + return writer.toString(); + } + + public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, ScriptExportMode exportMode, GraphTextWriter writer) { + return toASMSource(constants, trait, info, body, new ArrayList<>(), exportMode, writer); + } + + public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List outputMap, ScriptExportMode exportMode, GraphTextWriter writer) { + if (trait != null) { + if (trait instanceof TraitFunction) { + TraitFunction tf = (TraitFunction) trait; + writer.appendNoHilight("trait "); + writer.hilightSpecial("function ", HighlightSpecialType.TRAIT_TYPE); + writer.hilightSpecial(constants.multinameToString(tf.name_index), HighlightSpecialType.TRAIT_NAME); + writer.appendNoHilight(" slotid "); + writer.hilightSpecial("" + tf.slot_id, HighlightSpecialType.SLOT_ID); + writer.newLine(); + } + if (trait instanceof TraitMethodGetterSetter) { + TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait; + writer.appendNoHilight("trait "); + switch (tm.kindType) { + case Trait.TRAIT_METHOD: + writer.hilightSpecial("method ", HighlightSpecialType.TRAIT_TYPE); + break; + case Trait.TRAIT_GETTER: + writer.hilightSpecial("getter ", HighlightSpecialType.TRAIT_TYPE); + break; + case Trait.TRAIT_SETTER: + writer.hilightSpecial("setter ", HighlightSpecialType.TRAIT_TYPE); + break; + } + writer.hilightSpecial(constants.multinameToString(tm.name_index), HighlightSpecialType.TRAIT_NAME); + writer.appendNoHilight(" dispid "); + writer.hilightSpecial("" + tm.disp_id, HighlightSpecialType.DISP_ID); + writer.newLine(); + } + } + + if (info != null) { + writer.appendNoHilight("method").newLine(); + writer.appendNoHilight("name "); + writer.hilightSpecial(info.name_index == 0 ? "null" : "\"" + Helper.escapeActionScriptString(info.getName(constants)) + "\"", HighlightSpecialType.METHOD_NAME); + writer.newLine(); + if (info.flagExplicit()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("EXPLICIT", HighlightSpecialType.FLAG_EXPLICIT); + writer.newLine(); + } + if (info.flagHas_optional()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("HAS_OPTIONAL", HighlightSpecialType.FLAG_HAS_OPTIONAL); + writer.newLine(); + writer.appendNoHilight("flag HAS_OPTIONAL").newLine(); + } + if (info.flagHas_paramnames()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("HAS_PARAM_NAMES", HighlightSpecialType.FLAG_HAS_PARAM_NAMES); + writer.newLine(); + } + if (info.flagIgnore_rest()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("EXPLICIT", HighlightSpecialType.FLAG_IGNORE_REST); + writer.newLine(); + } + if (info.flagNeed_activation()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("NEED_ACTIVATION", HighlightSpecialType.FLAG_NEED_ACTIVATION); + writer.newLine(); + } + if (info.flagNeed_arguments()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("NEED_ARGUMENTS", HighlightSpecialType.FLAG_NEED_ARGUMENTS); + writer.newLine(); + } + if (info.flagNeed_rest()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("NEED_REST", HighlightSpecialType.FLAG_NEED_REST); + writer.newLine(); + } + if (info.flagSetsdxns()) { + writer.appendNoHilight("flag "); + writer.hilightSpecial("SET_DXNS", HighlightSpecialType.FLAG_SET_DXNS); + writer.newLine(); + } + for (int p = 0; p < info.param_types.length; p++) { + writer.appendNoHilight("param "); + writer.hilightSpecial(constants.multinameToString(info.param_types[p]), HighlightSpecialType.PARAM, p); + writer.newLine(); + } + if (info.flagHas_paramnames()) { + for (int n : info.paramNames) { + writer.appendNoHilight("paramname "); + if (n == 0) { + writer.appendNoHilight("null"); + } else { + writer.appendNoHilight("\""); + writer.appendNoHilight(constants.getString(n)); + writer.appendNoHilight("\""); + } + writer.newLine(); + } + } + if (info.flagHas_optional()) { + for (int i = 0; i < info.optional.length; i++) { + ValueKind vk = info.optional[i]; + writer.appendNoHilight("optional "); + writer.hilightSpecial(vk.toString(constants), HighlightSpecialType.OPTIONAL, i); + writer.newLine(); + } + } + writer.appendNoHilight("returns "); + writer.hilightSpecial(constants.multinameToString(info.ret_type), HighlightSpecialType.RETURNS); + writer.newLine(); + } + writer.newLine(); + + Set importantOffsets = getImportantOffsets(body, true); + if (body != null) { + writer.appendNoHilight("body").newLine(); + + writer.appendNoHilight("maxstack "); + writer.appendNoHilight(body.max_stack); + writer.newLine(); + + writer.appendNoHilight("localcount "); + writer.appendNoHilight(body.max_regs); + writer.newLine(); + + writer.appendNoHilight("initscopedepth "); + writer.appendNoHilight(body.init_scope_depth); + writer.newLine(); + + writer.appendNoHilight("maxscopedepth "); + writer.appendNoHilight(body.max_scope_depth); + writer.newLine(); + + for (int e = 0; e < body.exceptions.length; e++) { + ABCException exception = body.exceptions[e]; + writer.appendNoHilight("try"); + + writer.appendNoHilight(" from "); + writer.appendNoHilight("ofs"); + writer.appendNoHilight(Helper.formatAddress(exception.start)); + + writer.appendNoHilight(" to "); + writer.appendNoHilight("ofs"); + writer.appendNoHilight(Helper.formatAddress(exception.end)); + + writer.appendNoHilight(" target "); + writer.appendNoHilight("ofs"); + writer.appendNoHilight(Helper.formatAddress(exception.target)); + + writer.appendNoHilight(" type "); + writer.hilightSpecial(exception.type_index == 0 ? "null" : constants.getMultiname(exception.type_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_TYPE, e); + + writer.appendNoHilight(" name "); + writer.hilightSpecial(exception.name_index == 0 ? "null" : constants.getMultiname(exception.name_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_NAME, e); + writer.newLine(); + } + } + + writer.newLine(); + writer.appendNoHilight("code").newLine(); + + int ip = 0; + int largeLimit = 20000; + boolean markOffsets = code.size() <= largeLimit; + + if (exportMode == ScriptExportMode.HEX) { + Helper.byteArrayToHexWithHeader(writer, getBytes()); + } else if (exportMode == ScriptExportMode.PCODE || exportMode == ScriptExportMode.PCODE_HEX) { + for (AVM2Instruction ins : code) { + long addr = ins.getAddress(); + if (exportMode == ScriptExportMode.PCODE_HEX) { + writer.appendNoHilight("; "); + writer.appendNoHilight(Helper.bytesToHexString(ins.getBytes())); + writer.newLine(); + } + if (Configuration.showAllAddresses.get() || importantOffsets.contains(addr)) { + writer.appendNoHilight("ofs" + Helper.formatAddress(addr) + ":"); + } + /*for (int e = 0; e < body.exceptions.length; e++) { + if (body.exceptions[e].start == ofs) { + ret.append("exceptionstart " + e + ":"); + } + if (body.exceptions[e].end == ofs) { + ret.append("exceptionend " + e + ":"); + } + if (body.exceptions[e].target == ofs) { + ret.append("exceptiontarget " + e + ":"); + } + }*/ + + if (!ins.isIgnored()) { + if (markOffsets) { + writer.append("", addr, ins.getFileOffset()); + } + + writer.appendNoHilight(ins.toStringNoAddress(constants, new ArrayList<>())); + writer.newLine(); + outputMap.add(ip); + } + + ip++; + } + } else if (exportMode == ScriptExportMode.CONSTANTS) { + writer.appendNoHilight("Constant export mode is not supported.").newLine(); + } + + return writer; + } + + public Set getImportantOffsets(MethodBody body, boolean tryEnds) { + Set ret = new HashSet<>(); + if (body != null) { + for (ABCException exception : body.exceptions) { + ret.add((long) exception.start); + if (tryEnds) { + ret.add((long) exception.end); + } + ret.add((long) exception.target); + } + } + + for (AVM2Instruction ins : code) { + ret.addAll(ins.getOffsets()); + } + + return ret; + } + + public AVM2Instruction adr2ins(long address) throws ConvertException { + int pos = adr2pos(address, false); + if (pos == code.size()) { + // end + return null; + } + + return code.get(pos); + } + + public int adr2pos(long address) throws ConvertException { + return adr2pos(address, false); + } + + public int adr2pos(long address, boolean nearest) throws ConvertException { + int ret = adr2posNoEx(address); + if (ret < 0) { + if (nearest && address < getEndOffset()) { + return -ret - 1; + } + throw new ConvertException("Invalid jump to ofs" + Helper.formatAddress(address), -1); + } + return ret; + } + + private int adr2posNoEx(long address) { + int min = 0; + int max = code.size() - 1; + + while (max >= min) { + int mid = (min + max) / 2; + long midValue = code.get(mid).getAddress(); + if (midValue == address) { + return mid; + } else if (midValue < address) { + min = mid + 1; + } else { + max = mid - 1; + } + } + + if (address == getEndOffset()) { + return code.size(); + } + + return -min - 1; + } + + public long pos2adr(int pos) { + if (pos == code.size()) { + return getEndOffset(); + } + return (int) code.get(pos).getAddress(); + } + + public long getEndOffset() { + if (code.isEmpty()) { + return 0; + } + + AVM2Instruction ins = code.get(code.size() - 1); + return (int) (ins.getAddress() + ins.getBytesLength()); + } + + /** + * Test for killed register. CalcKilledStats must be called before + * + * @param regName + * @param start + * @param end + * @return + */ + public boolean isKilled(int regName, int start, int end) { + if (!killedRegs.containsKey(regName)) { + return false; + } + for (int ip : killedRegs.get(regName)) { + if (ip >= start && ip <= end) { + return true; + } + } + return false; + } + + private int toSourceCount = 0; + + public Map getLocalRegNamesFromDebug(ABC abc) { + Map localRegNames = new HashMap<>(); + + for (AVM2Instruction ins : code) { + if (ins.definition instanceof DebugIns) { + if (ins.operands[0] == 1) { + String v = abc.constants.getString(ins.operands[1]); + // Same name already exists, it may be wrong names inserted by obfuscator + if (localRegNames.values().contains(v)) { + return new HashMap<>(); + } + localRegNames.put(ins.operands[2] + 1, v); + } + } + } + + // TODO: Make this immune to using existing multinames (?) + return localRegNames; + } + + private Map> killedRegs = new HashMap<>(); + + public void calcKilledStats(MethodBody body) throws InterruptedException { + killedRegs.clear(); + HashMap> vis = visitCode(body); + + for (int k = 0; k < code.size(); k++) { + if (vis.get(k).isEmpty()) { + continue; + } + if (code.get(k).definition instanceof KillIns) { + int regid = code.get(k).operands[0]; + if (!killedRegs.containsKey(regid)) { + killedRegs.put(regid, new HashSet<>()); + } + killedRegs.get(regid).add(k); + } + } + } + + public List clearTemporaryRegisters(List input) { + List output = new ArrayList<>(input); + for (int i = 0; i < output.size(); i++) { + if (output.get(i) instanceof SetLocalAVM2Item) { + if (isKilled(((SetLocalAVM2Item) output.get(i)).regIndex, 0, code.size() - 1)) { + SetLocalAVM2Item lsi = (SetLocalAVM2Item) output.get(i); + if (i + 1 < output.size()) { + if (output.get(i + 1) instanceof ExitItem) { + GraphTargetItem rv = output.get(i + 1); + if (rv.value instanceof LocalRegAVM2Item) { + LocalRegAVM2Item lr = (LocalRegAVM2Item) rv.value; + if (lr.regIndex == lsi.regIndex) { + rv.value = lsi.value; + } + } + } + } + output.remove(i); + i--; + } + } else if (output.get(i) instanceof WithAVM2Item) { + clearTemporaryRegisters(((WithAVM2Item) output.get(i)).items); + } + } + return output; + } + + public int fixIPAfterDebugLine(int ip) { + if (code.isEmpty()) { + return ip; + } + if (ip >= code.size()) { + return code.size() - 1; + } + while (code.get(ip).definition instanceof DebugLineIns) { + ip++; + } + return ip; + } + + public long fixAddrAfterDebugLine(long addr) throws ConvertException { + return pos2adr(fixIPAfterDebugLine(adr2pos(addr, true))); + } + + public ConvertOutput toSourceOutput(boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssigmentIps, HashMap> refs) throws ConvertException, InterruptedException { + calcKilledStats(body); + boolean debugMode = DEBUG_MODE; + if (debugMode) { + System.err.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString()); + } + if (visited == null) { + visited = new boolean[code.size()]; + } + //if(true) return ""; + toSourceCount++; + if (toSourceLimit > 0 && toSourceCount >= toSourceLimit) { + throw new ConvertException("Limit of subs(" + toSourceLimit + ") was reached", start); + } + List output = new ArrayList<>(); + int ip = start; + //try { + //int addr; + iploop: + while (ip <= end) { + + boolean processTry = processJumps; + //addr = pos2adr(ip); + //int ipfix = fixIPAfterDebugLine(ip); + //int addrfix = pos2adr(ipfix); + //int maxend = -1; + + if (ip > end) { + break; + } + + if (visited[ip]) { + //logger.warning(path + ": Code already visited, ofs:" + Helper.formatAddress(pos2adr(ip)) + ", ip:" + ip); + break; + } + + if (Configuration.simplifyExpressions.get()) { + stack.simplify(); + } + visited[ip] = true; + AVM2Instruction ins = code.get(ip); + if (stack.isEmpty()) { + lineStartItem.setVal(ins); + } + + if (debugMode) { + System.err.println("translating ip " + ip + " ins " + ins.toString() + " stack:" + stack.toString() + " scopeStack:" + scopeStack.toString()); + } + if (ins.definition instanceof NewFunctionIns) { + if (ip + 1 <= end) { + if (code.get(ip + 1).definition instanceof PopIns) { + ip += 2; + continue; + } + } + } + /*if ((ip + 8 < code.size())) { //return in finally clause + if (ins.definition instanceof SetLocalTypeIns) { + if (code.get(ip + 1).definition instanceof PushByteIns) { + AVM2Instruction jmp = code.get(ip + 2); + if (jmp.definition instanceof JumpIns) { + if (jmp.operands[0] == 0) { + if (code.get(ip + 3).definition instanceof LabelIns) { + if (code.get(ip + 4).definition instanceof PopIns) { + if (code.get(ip + 5).definition instanceof LabelIns) { + AVM2Instruction gl = code.get(ip + 6); + if (gl.definition instanceof GetLocalTypeIns) { + if (((GetLocalTypeIns) gl.definition).getRegisterId(gl) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins)) { + AVM2Instruction ki = code.get(ip + 7); + if (ki.definition instanceof KillIns) { + if (ki.operands[0] == ((SetLocalTypeIns) ins.definition).getRegisterId(ins)) { + if (code.get(ip + 8).definition instanceof ReturnValueIns) { + ip = ip + 8; + continue; + } + } + } + } + } + } + } + } + } + } + } + } + }//*/ + + /*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause + if (code.get(ip + 1).definition instanceof DupIns) { + if (code.get(ip + 2).definition instanceof SetLocalTypeIns) { + ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames, fullyQualifiedNames); + ip += 3; + continue; + } + } + }*/ + if ((ins.definition instanceof GetLocalTypeIns) && (!output.isEmpty()) && (output.get(output.size() - 1) instanceof SetLocalAVM2Item) && (((SetLocalAVM2Item) output.get(output.size() - 1)).regIndex == ((GetLocalTypeIns) ins.definition).getRegisterId(ins)) && isKilled(((SetLocalAVM2Item) output.get(output.size() - 1)).regIndex, start, end)) { + SetLocalAVM2Item slt = (SetLocalAVM2Item) output.remove(output.size() - 1); + stack.push(slt.getValue()); + ip++; + } else if ((ins.definition instanceof SetLocalTypeIns) && (ip + 1 <= end) && (isKilled(((SetLocalTypeIns) ins.definition).getRegisterId(ins), ip, end))) { // set_local_x,get_local_x..kill x + AVM2Instruction insAfter = code.get(ip + 1); + if ((insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) { + GraphTargetItem before = stack.peek(); + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + stack.push(before); + ip += 2; + continue iploop; + } else { + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ip++; + continue iploop; + } + } else if (ins.definition instanceof DupIns) { + int nextPos; + do { + AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null; + if (insAfter == null) { + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ip++; + break; + } + AVM2Instruction insBefore = ins; + if (ip - 1 >= start) { + insBefore = code.get(ip - 1); + } + if (insAfter.definition instanceof ConvertBIns) { // SWF compiled with debug contain convert_b + ip++; + //addr = pos2adr(ip); + insAfter = code.get(ip + 1); + } + + boolean isAnd; + if (processJumps && (insAfter.definition instanceof IfFalseIns)) { + //stack.add("(" + stack.pop() + ")&&"); + isAnd = true; + } else if (processJumps && (insAfter.definition instanceof IfTrueIns)) { + //stack.add("(" + stack.pop() + ")||"); + isAnd = false; + } else if (insAfter.definition instanceof SetLocalTypeIns) { + // chained assignments + int reg = (((SetLocalTypeIns) insAfter.definition).getRegisterId(insAfter)); + for (int t = ip + 1; t <= end - 1; t++) { + if (code.get(t).definition instanceof KillIns) { + if (code.get(t).operands[0] == reg) { + break; + } + } + if (code.get(t).definition instanceof GetLocalTypeIns) { + if (((GetLocalTypeIns) code.get(t).definition).getRegisterId(code.get(t)) == reg) { + if (code.get(t + 1).definition instanceof KillIns) { + if (code.get(t + 1).operands[0] == reg) { + ConvertOutput assignment = toSourceOutput(thisHasDefaultToPrimitive, lineStartItem, path, part, processJumps, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, abc, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited, localRegAssigmentIps, refs); + if (!assignment.output.isEmpty()) { + GraphTargetItem tar = assignment.output.remove(assignment.output.size() - 1); + tar.firstPart = part; + stack.push(tar); + ip = t + 2; + + continue iploop; + } + } + } + } + } + } + if (!isKilled(reg, 0, end)) { + GraphTargetItem vx = stack.pop().getThroughDuplicate(); + int dupCnt = 1; + for (int i = ip - 1; i >= start; i--) { + if (code.get(i).definition instanceof DupIns) { + if (stack.isEmpty()) { + break; // FIXME?o + } + stack.pop(); + dupCnt++; + //stack.push(v); + } else { + break; + } + } + for (int i = 0; i < dupCnt; i++) { + stack.push(new LocalRegAVM2Item(ins, (AVM2Instruction) lineStartItem.getVal(), reg, vx)); + } + stack.push(vx); + } else { + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + } + ip++; + break; + //} + + } else { + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ip++; + break; + //throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString()); + } + } while (ins.definition instanceof DupIns); + } else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) { + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + //ip = end + 1; + break; + } else if (ins.definition instanceof NewFunctionIns) { + String functionName = ""; + if ((ip >= start + 2) && (ip <= end - 4)) { + AVM2Instruction prev2 = code.get(ip - 2); + if (prev2.definition instanceof NewObjectIns) { + if (prev2.operands[0] == 0) { + if (code.get(ip - 1).definition instanceof PushWithIns) { + boolean hasDup = false; + int plus = 0; + if (code.get(ip + 1).definition instanceof DupIns) { + hasDup = true; + plus = 1; + } + AVM2Instruction psco = code.get(ip + 1 + plus); + if (psco.definition instanceof GetScopeObjectIns) { + if (psco.operands[0] == scopeStack.size() - 1) { + if (code.get(ip + plus + 2).definition instanceof SwapIns) { + if (code.get(ip + plus + 4).definition instanceof PopScopeIns) { + if (code.get(ip + plus + 3).definition instanceof SetPropertyIns) { + functionName = abc.constants.getMultiname(code.get(ip + plus + 3).operands[0]).getName(abc.constants, fullyQualifiedNames, true); + scopeStack.pop();// with + output.remove(output.size() - 1); // with + ip = ip + plus + 4; // +1 below + } + } + } + } + } + } + } + } + } + // What to do when hasDup is false? + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek(); + nft.functionName = functionName; + ip++; + } else { + try { + ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + } catch (RuntimeException re) { + /*String last=""; + int len=5; + for(int i=(ip-len<0?0:ip-len);i maxRegister) { + maxRegister = regId; + } + } + return maxRegister + 1; + } + + public HashMap getLocalRegTypes(AVM2ConstantPool constants, List fullyQualifiedNames) { + HashMap ret = new HashMap<>(); + AVM2Instruction prev = null; + for (AVM2Instruction ins : code) { + if (ins.definition instanceof SetLocalTypeIns) { + if (prev != null) { + if (prev.definition instanceof CoerceOrConvertTypeIns) { + ret.put(((SetLocalTypeIns) ins.definition).getRegisterId(ins), ((CoerceOrConvertTypeIns) prev.definition).getTargetType(constants, prev)); + } + } + } + prev = ins; + } + return ret; + + } + + private class Slot { + + public final GraphTargetItem scope; + + public final Multiname multiname; + + public Slot(GraphTargetItem scope, Multiname multiname) { + this.scope = scope; + this.multiname = multiname; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Slot) { + Slot slot = (Slot) obj; + return (slot.scope.getThroughRegister() == scope.getThroughRegister()) + && (slot.multiname == multiname); + } + return false; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 59 * hash + (scope != null ? Objects.hashCode(scope.getThroughRegister()) : 0); + hash = 59 * hash + Objects.hashCode(multiname); + return hash; + } + } + + public void initToSource() { + toSourceCount = 0; + } + + private GraphTargetItem handleDeclareReg(int minreg, GraphTargetItem assignment, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, int reg) { + + //do not add declarations for reserved local registers like function arguments + if (reg < minreg) { + return assignment; + } + GraphTargetItem vtype = TypeItem.UNBOUNDED; + if (assignment.value instanceof ConvertAVM2Item) { + vtype = ((ConvertAVM2Item) assignment.value).type; + } + + if (vtype.equals(TypeItem.UNBOUNDED) && (assignment.value instanceof CoerceAVM2Item)) { + vtype = ((CoerceAVM2Item) assignment.value).typeObj; + } + if (vtype.equals(TypeItem.UNBOUNDED) && (assignment.value instanceof SimpleValue) && ((SimpleValue) assignment.value).isSimpleValue()) { + vtype = assignment.value.returnType(); + } + + if (declaredRegisters[reg] == null) { + declaredRegisters[reg] = new DeclarationAVM2Item(assignment, vtype); + if (assignment instanceof SetTypeAVM2Item) { + ((SetTypeAVM2Item) assignment).setDeclaration(declaredRegisters[reg]); + } + return declaredRegisters[reg]; + } + + if (declaredRegisters[reg].type == TypeItem.UNBOUNDED) { + + } else if (!declaredRegisters[reg].type.equals(vtype)) { //already declared with different type + declaredRegisters[reg].type = TypeItem.UNBOUNDED; + } + + if (assignment instanceof SetTypeAVM2Item) { + ((SetTypeAVM2Item) assignment).setDeclaration(declaredRegisters[reg]); + } + + return assignment; + } + + private GraphTargetItem injectDeclarations(int minreg, GraphTargetItem ti, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { + if (ti.value != null) { + ti.value = injectDeclarations(minreg, ti.value, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + } + //TODO: walk whole tree... some walker? + if (ti instanceof IfItem) { + ((IfItem) ti).expression = injectDeclarations(minreg, ((IfItem) ti).expression, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + } + if (ti instanceof BinaryOpItem) { + ((BinaryOpItem) ti).leftSide = injectDeclarations(minreg, ((BinaryOpItem) ti).leftSide, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + ((BinaryOpItem) ti).rightSide = injectDeclarations(minreg, ((BinaryOpItem) ti).rightSide, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + } + if (ti instanceof ForEachInAVM2Item) { + ForEachInAVM2Item fei = (ForEachInAVM2Item) ti; + if (fei.expression.object instanceof LocalRegAVM2Item) { + int reg = ((LocalRegAVM2Item) fei.expression.object).regIndex; + if (declaredRegisters[reg] == null) { + fei.expression.object = handleDeclareReg(minreg, fei.expression.object, declaredRegisters, declaredSlots, reg); + } + } + } + if (ti instanceof ForInAVM2Item) { + ForInAVM2Item fi = (ForInAVM2Item) ti; + if (fi.expression.object instanceof LocalRegAVM2Item) { + int reg = ((LocalRegAVM2Item) fi.expression.object).regIndex; + fi.expression.object = handleDeclareReg(minreg, fi.expression.object, declaredRegisters, declaredSlots, reg); + //nowdeclaredRegs.add(reg); + + } + } + if (ti instanceof Block) { + Block bl = (Block) ti; + for (List s : bl.getSubs()) { + injectDeclarations(minreg, s, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + } + } + if (ti instanceof SetLocalAVM2Item) { + int reg = ((SetLocalAVM2Item) ti).regIndex; + ti = handleDeclareReg(minreg, ti, declaredRegisters, declaredSlots, reg); + return ti; + } + if (ti instanceof SetSlotAVM2Item) { + SetSlotAVM2Item ssti = (SetSlotAVM2Item) ti; + Slot sl = new Slot(ssti.scope, ssti.slotName); + if (!declaredSlots.contains(sl)) { + GraphTargetItem type = TypeItem.UNBOUNDED; + for (int t = 0; t < body.traits.traits.size(); t++) { + if (body.traits.traits.get(t).getName(abc) == sl.multiname) { + if (body.traits.traits.get(t) instanceof TraitSlotConst) { + type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + } + } + } + DeclarationAVM2Item d = new DeclarationAVM2Item(ti, type); + ssti.setDeclaration(d); + declaredSlotsDec.add(d); + declaredSlots.add(sl); + return d; + //nowdeclaredSlots.add(sl); + } else { + int idx = declaredSlots.indexOf(sl); + ssti.setDeclaration(declaredSlotsDec.get(idx)); + } + } + return ti; + } + + private void injectDeclarations(int minreg, List list, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { + //List nowdeclaredRegs=new ArrayList<>(); + //List nowdeclaredSlots=new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + GraphTargetItem ti = list.get(i); + GraphTargetItem ti2 = injectDeclarations(minreg, ti, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + if (ti != ti2) { + list.set(i, ti2); + } + } + + /* + //undeclare registers at the end of the block? + for(int reg:nowdeclaredRegs){ + declaredRegisters[reg] = false; + } + + for(Slot s:nowdeclaredSlots){ + declaredSlots.remove(s); + }*/ + } + + public List toGraphTargetItems(boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, List initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) throws InterruptedException { + initToSource(); + List list; + HashMap localRegs = new HashMap<>(); + + int regCount = getRegisterCount(); + for (int i = 0; i < regCount; i++) { + localRegs.put(0, new UndefinedAVM2Item(null, null)); + } + + //try { + list = AVM2Graph.translateViaGraph(path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive); + + if (initTraits != null) { + loopi: + for (int i = 0; i < list.size(); i++) { + GraphTargetItem ti = list.get(i); + if ((ti instanceof InitPropertyAVM2Item) || (ti instanceof SetPropertyAVM2Item)) { + int multinameIndex = 0; + GraphTargetItem value = null; + if (ti instanceof InitPropertyAVM2Item) { + multinameIndex = ((InitPropertyAVM2Item) ti).propertyName.multinameIndex; + value = ((InitPropertyAVM2Item) ti).value; + } + if (ti instanceof SetPropertyAVM2Item) { + multinameIndex = ((FullMultinameAVM2Item) ((SetPropertyAVM2Item) ti).propertyName).multinameIndex; + value = ((SetPropertyAVM2Item) ti).value; + } + Multiname m = abc.constants.getMultiname(multinameIndex); + for (Traits ts : initTraits) { + for (Trait t : ts.traits) { + Multiname tm = abc.constants.getMultiname(t.name_index); + if (tm != null && tm.equals(m)) { + if ((t instanceof TraitSlotConst)) { + if (((TraitSlotConst) t).isConst() || initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) { + TraitSlotConst tsc = (TraitSlotConst) t; + if (value != null && !convertData.assignedValues.containsKey(tsc)) { + + if (value instanceof NewFunctionAVM2Item) { + NewFunctionAVM2Item f = (NewFunctionAVM2Item) value; + f.functionName = tsc.getName(abc).getName(abc.constants, fullyQualifiedNames, true); + } + AssignedValue av = new AssignedValue(value, initializerType, methodIndex); + convertData.assignedValues.put(tsc, av); + list.remove(i); + i--; + continue; + } + } + break; + } + } + } + } + } else { + // In obfuscated code, SetLocal instructions comes first + //break; + } + } + } + if (initializerType == GraphTextWriter.TRAIT_CLASS_INITIALIZER || initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER) { + List newList = new ArrayList<>(); + for (GraphTargetItem ti : list) { + if (!(ti instanceof ReturnVoidAVM2Item)) { + if (!(ti instanceof InitPropertyAVM2Item)) { + newList.add(ti); + } + } + } + list = newList; + if (list.isEmpty()) { + return list; + } + } + // Declarations + + DeclarationAVM2Item d[] = new DeclarationAVM2Item[regCount]; + + int param_types[] = abc.method_info.get(body.method_info).param_types; + int r = 1; + for (int i = 0; i < param_types.length; i++) { + GraphTargetItem type; + if (param_types[i] == 0) { + type = TypeItem.UNBOUNDED; + } else { + type = new TypeItem(abc.constants.getMultiname(param_types[i]).getNameWithNamespace(abc.constants)); + } + if (d.length > r) { + d[r] = new DeclarationAVM2Item(new SetLocalAVM2Item(null, null, r, new NullAVM2Item(null, null)), type); + } + r++; + } + if (abc.method_info.get(body.method_info).flagNeed_arguments()) { + if (d.length > r) { + d[r] = new DeclarationAVM2Item(new SetLocalAVM2Item(null, null, r, new NullAVM2Item(null, null)), TypeItem.ARRAY /*?*/); + } + r++; + } + if (abc.method_info.get(body.method_info).flagNeed_rest()) { + if (d.length > r) { + d[r] = new DeclarationAVM2Item(new SetLocalAVM2Item(null, null, r, new NullAVM2Item(null, null)), TypeItem.ARRAY/*?*/); + } + r++; + } + // + + //int minreg = abc.method_info.get(body.method_info).getMaxReservedReg() + 1; + injectDeclarations(1, list, d, new ArrayList<>(), new ArrayList<>(), abc, body); + + int lastPos = list.size() - 1; + if (lastPos < 0) { + lastPos = 0; + } + if ((list.size() > lastPos) && (list.get(lastPos) instanceof ScriptEndItem)) { + lastPos--; + } + if (lastPos < 0) { + lastPos = 0; + } + if ((list.size() > lastPos) && (list.get(lastPos) instanceof ReturnVoidAVM2Item)) { + list.remove(lastPos); + } + + return list; + } + + public void updateOffsets(OffsetUpdater updater, MethodBody body) { + for (int i = 0; i < code.size(); i++) { + AVM2Instruction ins = code.get(i); + if (ins.definition instanceof LookupSwitchIns) { + long target = ins.getAddress() + ins.operands[0]; + ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]); + for (int k = 2; k < ins.operands.length; k++) { + target = ins.getAddress() + ins.operands[k]; + ins.operands[k] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[k]); + } + } else /*for (int j = 0; j < ins.definition.operands.length; j++) { + if (ins.definition.operands[j] == AVM2Code.DAT_OFFSET) { + long target = ins.offset + ins.getBytes().length + ins.operands[j]; + ins.operands[j] = updater.updateOperandOffset(target, ins.operands[j]); + } + }*/ //Faster, but not so universal + { + if (ins.definition instanceof IfTypeIns) { + long target = ins.getTargetAddress(); + try { + ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]); + } catch (ConvertException cex) { + throw new ConvertException("Invalid offset (" + ins + ")", i); + } + } + } + ins.setAddress(updater.updateInstructionOffset(ins.getAddress())); + } + + for (ABCException ex : body.exceptions) { + ex.start = updater.updateOperandOffset(-1, ex.start, ex.start); + ex.end = updater.updateOperandOffset(-1, ex.end, ex.end); + ex.target = updater.updateOperandOffset(-1, ex.target, ex.target); + } + } + + public void fixJumps(final String path, MethodBody body) throws InterruptedException { + if (code.isEmpty()) { + return; + } + final List insAddrToRemove = new ArrayList<>(); + final long endOffset = getEndOffset(); + updateOffsets(new OffsetUpdater() { + + @Override + public long updateInstructionOffset(long address) { + return address; + } + + @Override + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { + if (targetAddress > endOffset || targetAddress < 0 || adr2posNoEx(targetAddress) < 0) { + insAddrToRemove.add(insAddr); + } + return offset; + } + + }, body); + + boolean someIgnored = false; + for (Long insAddr : insAddrToRemove) { + int pos = adr2posNoEx(insAddr); + if (pos > -1) { + code.get(pos).setIgnored(true, 0); + someIgnored = true; + } + } + if (someIgnored) { + logger.log(Level.WARNING, path + ": One or more invalid jump offsets found in the code. Those instructions were ignored."); + } + removeIgnored(body); + } + + public void checkValidOffsets(MethodBody body) { + updateOffsets(new OffsetUpdater() { + + @Override + public long updateInstructionOffset(long address) { + adr2pos(address); + return address; + } + + @Override + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { + /*if (insAddr == -1) { + return offset; + }*/ + adr2pos(targetAddress); + return offset; + } + + }, body); + } + + public void removeInstruction(int pos, MethodBody body) { + if ((pos < 0) || (pos >= code.size())) { + throw new IndexOutOfBoundsException(); + } + + AVM2Instruction ins = code.get(pos); + final long remOffset = ins.getAddress(); + int bc = ins.getBytesLength(); + + final int byteCount = bc; + updateOffsets(new OffsetUpdater() { + @Override + public long updateInstructionOffset(long address) { + if (address > remOffset) { + return address - byteCount; + } + return address; + } + + @Override + public int updateOperandOffset(long jumpInsAddr, long jumpTargetAddr, int jumpOffset) { + /* + a:jump d: + b: + c:X + d: + */ + if (jumpTargetAddr > remOffset && jumpInsAddr < remOffset) { + return jumpOffset - byteCount; + } + /* + a:X1 + b:X2 + c: + d:jump a: + */ + if (jumpTargetAddr <= remOffset && jumpInsAddr > remOffset) { + return jumpOffset + byteCount; + } + + return jumpOffset; + } + }, body); + code.remove(pos); + //checkValidOffsets(body); + } + + /** + * Inserts instruction at specified point. Handles offsets properly. Note: + * If newinstruction is jump, the offset operand must be handled properly by + * caller. All old jump offsets to pos are targeted before new instruction. + * + * @param pos Position in the list + * @param instruction Instruction False means before new instruction + * @param body Method body (used for try handling) + */ + public void insertInstruction(int pos, AVM2Instruction instruction, MethodBody body) { + insertInstruction(pos, instruction, false, body); + } + + /** + * Replaces instruction by another. Properly handles offsets. Note: If + * newinstruction is jump, the offset operand must be handled properly by + * caller. + * + * @param pos + * @param instruction + * @param body + */ + public void replaceInstruction(int pos, AVM2Instruction instruction, MethodBody body) { + AVM2Instruction oldInstruction = code.get(pos); + instruction.setAddress(oldInstruction.getAddress()); + int oldByteCount = oldInstruction.getBytesLength(); + int newByteCount = instruction.getBytesLength(); + int byteDelta = newByteCount - oldByteCount; + + if (byteDelta != 0) { + updateOffsets(new OffsetUpdater() { + + @Override + public long updateInstructionOffset(long address) { + if (address > instruction.getAddress()) { + return address + byteDelta; + } + return address; + } + + @Override + public int updateOperandOffset(long insAddr, long targetAddress, int offset) { + if (targetAddress > instruction.getAddress() && insAddr <= instruction.getAddress()) { + return offset + byteDelta; + } + if (targetAddress <= instruction.getAddress() && insAddr > instruction.getAddress()) { + return offset - byteDelta; + } + return offset; + } + }, body); + } + code.set(pos, instruction); + } + + /** + * Inserts instruction at specified point. Handles offsets properly. Note: + * If newinstruction is jump, the offset operand must be handled properly by + * caller. + * + * @param pos Position in the list + * @param instruction Instruction + * @param mapOffsetsAfterIns Map all jumps to the pos after new instruction? + * False means before new instruction + * @param body Method body (used for try handling) + */ + public void insertInstruction(int pos, AVM2Instruction instruction, boolean mapOffsetsAfterIns, MethodBody body) { + //checkValidOffsets(body); + if (pos < 0) { + pos = 0; + } + if (pos > code.size()) { + pos = code.size(); + } + final int byteCount = instruction.getBytesLength(); + if (pos == code.size()) { + instruction.setAddress(code.get(pos - 1).getAddress() + code.get(pos - 1).getBytesLength()); + } else { + instruction.setAddress(code.get(pos).getAddress()); + } + final long x = instruction.getAddress(); + updateOffsets(new OffsetUpdater() { + + @Override + public long updateInstructionOffset(long offset) { + if (offset >= x) { + return offset + byteCount; + } + return offset; + } + + @Override + public int updateOperandOffset(long j, long t, int offset_jt) { + + /* + j:jump t: + n: + n: + x:# + t: + */ + if (((t > x) || (mapOffsetsAfterIns && (t == x))) && (j < x)) { + return offset_jt + byteCount; + } + /* + t: + x:# + n: + n: + j:jump t: + */ + if (((t < x) || (mapOffsetsAfterIns && (t == x))) && (j > x)) { + return offset_jt - byteCount; + } + + /* + t: + n: + n: + j:x: # jump t: + */ + if ((j == x) && (t < x)) { + return offset_jt - byteCount; + } + + return offset_jt; + } + }, body); + instruction.setAddress(x); + code.add(pos, instruction); + //checkValidOffsets(body); + } + + public int removeTraps(Trait trait, int methodInfo, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { + SWFDecompilerPlugin.fireAvm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); + try (Statistics s = new Statistics("AVM2DeobfuscatorGetSet")) { + new AVM2DeobfuscatorGetSet().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); + } + try (Statistics s = new Statistics("AVM2DeobfuscatorSimple")) { + new AVM2DeobfuscatorSimpleOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); + } + try (Statistics s = new Statistics("AVM2DeobfuscatorRegisters")) { + new AVM2DeobfuscatorRegistersOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); + } + try (Statistics s = new Statistics("AVM2DeobfuscatorJumps")) { + new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); + } + return 1; + } + + private void handleRegister(CodeStats stats, int reg) { + if (reg + 1 > stats.maxlocal) { + stats.maxlocal = reg + 1; + } + } + + private boolean walkCode(CodeStats stats, int pos, int stack, int scope, ABC abc) { + while (pos < code.size()) { + AVM2Instruction ins = code.get(pos); + if (stats.instructionStats[pos].seen) { + // check stack mismatch here + return true; + } + + if (ins.definition instanceof NewFunctionIns) { + MethodBody innerBody = abc.findBody(ins.operands[0]); + innerBody.autoFillStats(abc, stats.initscope + (stats.has_activation ? 1 : 0), false); + } + + stats.instructionStats[pos].seen = true; + stats.instructionStats[pos].stackpos = stack; + stats.instructionStats[pos].scopepos = scope; + + int stackDelta = ins.definition.getStackDelta(ins, abc); + int scopeDelta = ins.definition.getScopeStackDelta(ins, abc); + int oldStack = stack; + + //+" deltaScope:"+(scopeDelta>0?"+"+scopeDelta:scopeDelta)+" stack:"+stack+" scope:"+scope); + stack += stackDelta; + scope += scopeDelta; + + stats.instructionStats[pos].stackpos_after = stack; + stats.instructionStats[pos].scopepos_after = scope; + + if (stack > stats.maxstack) { + stats.maxstack = stack; + } + if (scope > stats.maxscope) { + stats.maxscope = scope; + } + + //System.out.println("stack "+oldStack+(stackDelta>=0?"+"+stackDelta:stackDelta)+" max:"+stats.maxstack+" "+ins); + if ((ins.definition instanceof DXNSIns) || (ins.definition instanceof DXNSLateIns)) { + stats.has_set_dxns = true; + } + if (ins.definition instanceof NewActivationIns) { + stats.has_activation = true; + } + if (ins.definition instanceof SetLocalTypeIns) { + handleRegister(stats, ((SetLocalTypeIns) ins.definition).getRegisterId(ins)); + } else if (ins.definition instanceof GetLocalTypeIns) { + handleRegister(stats, ((GetLocalTypeIns) ins.definition).getRegisterId(ins)); + } else { + for (int i = 0; i < ins.definition.operands.length; i++) { + int op = ins.definition.operands[i]; + if (op == DAT_LOCAL_REG_INDEX) { + handleRegister(stats, ins.operands[i]); + } + } + } + if (ins.definition instanceof ReturnValueIns) { + // check stack=1 + return true; + } + if (ins.definition instanceof ReturnVoidIns) { + // check stack=0 + return true; + } + if (ins.definition instanceof JumpIns) { + try { + pos = adr2pos(ins.getTargetAddress()); + continue; + } catch (ConvertException ex) { + return false; + } + } else if (ins.definition instanceof IfTypeIns) { + try { + int newpos = adr2pos(ins.getTargetAddress()); + walkCode(stats, newpos, stack, scope, abc); + } catch (ConvertException ex) { + return false; + } + } + if (ins.definition instanceof LookupSwitchIns) { + for (int i = 0; i < ins.operands.length; i++) { + if (i == 1) { + continue; + } + try { + int newpos = adr2pos(pos2adr(pos) + ins.operands[i]); + if (!walkCode(stats, newpos, stack, scope, abc)) { + return false; + } + } catch (ConvertException ex) { + return false; + } + } + } + pos++; + } + return true; + } + + public CodeStats getStats(ABC abc, MethodBody body, int initScope) { + CodeStats stats = new CodeStats(this); + stats.initscope = initScope; + if (!walkCode(stats, 0, 0, initScope, abc)) { + return null; + } + int scopePos = -1; + int prevStart = 0; + for (int e = 0; e < body.exceptions.length; e++) { + ABCException ex = body.exceptions[e]; + try { + if (scopePos == -1) { + scopePos = stats.instructionStats[adr2pos(ex.end) - 1].scopepos_after; + } + List visited = new ArrayList<>(); + for (int i = 0; i < stats.instructionStats.length; i++) { + if (stats.instructionStats[i].seen) { + visited.add(i); + } + } + if (!walkCode(stats, adr2pos(ex.target), 1 + (ex.isFinally() ? 1 : 0), scopePos, abc)) { + return null; + } + int maxIp = 0; + // searching for visited instruction in second run which has maximum position + for (int i = 0; i < stats.instructionStats.length; i++) { + if (stats.instructionStats[i].seen && !visited.contains(i)) { + maxIp = i; + } + } + scopePos = stats.instructionStats[maxIp].scopepos_after; + int stackPos = stats.instructionStats[maxIp].stackpos_after; + int nextIp = maxIp + 1; + if (code.get(maxIp).definition instanceof JumpIns) { + nextIp = adr2pos(pos2adr(nextIp) + code.get(maxIp).operands[0]); + } + if (nextIp < stats.instructionStats.length) { + InstructionStats nextIpStat = stats.instructionStats[nextIp]; + int origScopePos = nextIpStat.scopepos; + int origStackPos = nextIpStat.stackpos; + + if (prevStart == ex.start && ex.isFinally() && !code.get(nextIp).isExit() && nextIpStat.seen) { + for (int i = 0; i < stats.instructionStats.length; i++) { + stats.instructionStats[i].seen = false; + } + // Rerun rest with new scopePos, stackPos + if (!walkCode(stats, nextIp, origStackPos + 1/*magic!*/, scopePos - 1 /*magic!*/, abc)) { + return null; + } + scopePos--; + } + } + prevStart = ex.start; + } catch (ConvertException ex1) { + // ignore + } + } + //stats.maxscope+=initScope; + return stats; + } + + private void visitCode(int ip, int lastIp, HashMap> refs) throws InterruptedException { + List toVisit = new ArrayList<>(); + List toVisitLast = new ArrayList<>(); + toVisit.add(ip); + toVisitLast.add(lastIp); + while (!toVisit.isEmpty()) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + ip = toVisit.remove(0); + lastIp = toVisitLast.remove(0); + while (ip < code.size()) { + if (!refs.containsKey(ip)) { + refs.put(ip, new ArrayList<>()); + } + refs.get(ip).add(lastIp); + lastIp = ip; + if (refs.get(ip).size() > 1) { + break; + } + AVM2Instruction ins = code.get(ip); + if (ins.definition instanceof ThrowIns) { + break; + } + if (ins.definition instanceof ReturnValueIns) { + break; + } + if (ins.definition instanceof ReturnVoidIns) { + break; + } + if (ins.definition instanceof LookupSwitchIns) { + try { + for (int i = 2; i < ins.operands.length; i++) { + toVisit.add(adr2pos(pos2adr(ip) + ins.operands[i])); + toVisitLast.add(ip); + } + ip = adr2pos(pos2adr(ip) + ins.operands[0]); + continue; + } catch (ConvertException ex) { + } + } + if (ins.definition instanceof JumpIns) { + try { + ip = adr2pos(ins.getTargetAddress()); + continue; + } catch (ConvertException ex) { + logger.log(Level.FINE, null, ex); + } + } else if (ins.definition instanceof IfTypeIns) { + try { + toVisit.add(adr2pos(ins.getTargetAddress())); + toVisitLast.add(ip); + } catch (ConvertException ex) { + logger.log(Level.FINE, null, ex); + } + } + ip++; + } + }; + } + + public HashMap> visitCode(MethodBody body) throws InterruptedException { + HashMap> refs = new HashMap<>(); + for (int i = 0; i < code.size(); i++) { + refs.put(i, new ArrayList<>()); + } + visitCode(0, 0, refs); + int pos = 0; + for (ABCException e : body.exceptions) { + pos++; + try { + visitCode(adr2pos(e.start, true), adr2pos(e.start, true) - 1, refs); + visitCode(adr2pos(e.start, true), -1, refs); + visitCode(adr2pos(e.target), adr2pos(e.end, true), refs); + visitCode(adr2pos(e.end, true), -pos, refs); + } catch (ConvertException ex) { + logger.log(Level.SEVERE, "Visitcode error", ex); + } + } + return refs; + } + + public void removeIgnored(MethodBody body) throws InterruptedException { + //System.err.println("removing ignored..."); + for (int i = 0; i < code.size(); i++) { + if (code.get(i).isIgnored()) { + removeInstruction(i, body); + i--; + } + } + //System.err.println("/ignored removed"); + } + + public int removeDeadCode(MethodBody body) throws InterruptedException { + HashMap> refs = visitCode(body); + int cnt = 0; + for (int i = code.size() - 1; i >= 0; i--) { + if (refs.get(i).isEmpty()) { + code.get(i).setIgnored(true, 0); + cnt++; + } + } + + removeIgnored(body); + + for (int i = code.size() - 1; i >= 0; i--) { + AVM2Instruction ins = code.get(i); + if (ins.definition instanceof JumpIns) { + if (ins.operands[0] == 0) { + ins.setIgnored(true, 0); + cnt++; + } + } + } + + removeIgnored(body); + + return cnt; + } + + public boolean inlineJumpExit() { + boolean modified = false; + int csize = code.size(); + for (int i = 0; i < csize; i++) { + AVM2Instruction ins = code.get(i); + int insLen = code.get(i).getBytesLength(); + long ofs = pos2adr(i); + if (ins.definition instanceof JumpIns) { + long targetOfs = ofs + insLen + ins.operands[0]; + try { + int ni = adr2pos(targetOfs); + if (ni < code.size() && ni > -1) { + AVM2Instruction ins2 = code.get(ni); + if (ins2.isExit()) { + code.set(i, new AVM2Instruction(ofs, ins2.definition, ins2.operands)); + modified = true; + } + } + } catch (ConvertException ex) { + //ignore + } + } + } + + return modified; + } + + private static int getMostCommonIp(AVM2GraphSource code, List branches) { + List> reachable = new ArrayList<>(); + for (int i = 0; i < branches.size(); i++) { + List r = new ArrayList<>(); + getReachableIps(code, branches.get(i), r); + } + + int commonLevel; + Map levelMap = new HashMap<>(); + for (List first : reachable) { + int maxclevel = 0; + Set visited = new HashSet<>(); + for (Integer p : first) { + if (visited.contains(p)) { + continue; + } + visited.add(p); + boolean common = true; + commonLevel = 1; + for (List r : reachable) { + if (r == first) { + continue; + } + if (r.contains(p)) { + commonLevel++; + } + } + if (commonLevel <= maxclevel) { + continue; + } + maxclevel = commonLevel; + if (levelMap.containsKey(p)) { + if (levelMap.get(p) > commonLevel) { + commonLevel = levelMap.get(p); + } + } + levelMap.put(p, commonLevel); + if (common) { + //return p; + } + } + } + for (int i = reachable.size() - 1; i >= 2; i--) { + for (Integer p : levelMap.keySet()) { + if (levelMap.get(p) == i) { + return p; + } + } + } + for (Integer p : levelMap.keySet()) { + if (levelMap.get(p) == branches.size()) { + return p; + } + } + return -1; + } + + public static void getReachableIps(AVM2GraphSource code, int ip, List reachable) { + do { + if (reachable.contains(ip)) { + return; + } + reachable.add(ip); + GraphSourceItem ins = code.get(ip); + if (ins.isJump() || ins.isBranch()) { + List branches = ins.getBranches(code); + for (int i = 1; i < branches.size(); i++) { + getReachableIps(code, branches.get(i), reachable); + } + ip = branches.get(0); + continue; + } + ip++; + } while (ip < code.size()); + } + + public static boolean isDirectAncestor(int currentIp, int ancestor, HashMap> refs) { + return isDirectAncestor(currentIp, ancestor, refs, new ArrayList<>()); + } + + private static boolean isDirectAncestor(int currentIp, int ancestor, HashMap> refs, List visited) { + if (currentIp == -1) { + return true; + } + do { + if (currentIp == ancestor) { + return true; + } + if (currentIp == 0) { + return false; + } + if (visited.contains(currentIp)) { + return true; + } + visited.add(currentIp); + if (refs.containsKey(currentIp)) { + List currentRefs = refs.get(currentIp); + if ((currentRefs != null) && (!currentRefs.isEmpty())) { + for (int i = 1; i < currentRefs.size(); i++) { + if (!isDirectAncestor(currentRefs.get(i), ancestor, refs, visited)) { + return false; + } + } + currentIp = currentRefs.get(0); + continue; + } + } + currentIp--; + } while (currentIp >= 0); + return false; + } + + public static boolean getPreviousReachableIps(int currentIp, HashMap> refs, Set reachable, Set visited) { + do { + if (visited.contains(currentIp)) { + return false; + } + reachable.add(currentIp); + visited.add(currentIp); + if (refs.containsKey(currentIp)) { + List currentRefs = refs.get(currentIp); + if ((currentRefs != null) && (!currentRefs.isEmpty())) { + if (currentRefs.size() == 1) { + currentIp = currentRefs.get(0); + continue; + } + boolean r = false; + for (int i = 0; i < currentRefs.size(); i++) { + Set nr = new HashSet<>(); + boolean v = getPreviousReachableIps(currentRefs.get(i), refs, nr, visited); + if ((!v) || nr.contains(0)) { + reachable.addAll(nr); + } + r = r || v; + } + return r; + } + } + currentIp--; + } while (currentIp >= 0); + return true; + } + + @Override + public AVM2Code clone() { + try { + AVM2Code ret = (AVM2Code) super.clone(); + if (code != null) { + List codeCopy = new ArrayList<>(code.size()); + for (AVM2Instruction ins : code) { + codeCopy.add(ins.clone()); + } + ret.code = codeCopy; + } + + ret.killedRegs = new HashMap<>(); + return ret; + } catch (CloneNotSupportedException ex) { + throw new RuntimeException(); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/XMLAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/XMLAVM2Item.java index b089505c6..8292763e2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/XMLAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/XMLAVM2Item.java @@ -1,61 +1,61 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.avm2.model; - -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TypeItem; -import com.jpexs.decompiler.graph.model.LocalData; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class XMLAVM2Item extends AVM2Item { - - public List parts; - - public XMLAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, List parts) { - super(instruction, lineStartIns, NOPRECEDENCE); - this.parts = parts; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - for (GraphTargetItem part : parts) { - if (part instanceof StringAVM2Item) { - writer.append(((StringAVM2Item) part).getValue()); - } else { - part.toString(writer, localData); - } - } - return writer; - } - - @Override - public GraphTargetItem returnType() { - return new TypeItem(DottedChain.XML); - } - - @Override - public boolean hasReturnValue() { - return true; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.avm2.model; + +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class XMLAVM2Item extends AVM2Item { + + public List parts; + + public XMLAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, List parts) { + super(instruction, lineStartIns, NOPRECEDENCE); + this.parts = parts; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + for (GraphTargetItem part : parts) { + if (part instanceof StringAVM2Item) { + writer.append(((StringAVM2Item) part).getValue()); + } else { + part.toString(writer, localData); + } + } + return writer; + } + + @Override + public GraphTargetItem returnType() { + return new TypeItem(DottedChain.XML); + } + + @Override + public boolean hasReturnValue() { + return true; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index d2a9d5df4..dcfde7578 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -1,475 +1,475 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.abc.types; - -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ABCInputStream; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.CodeStats; -import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFField; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.MemoryInputStream; -import com.jpexs.helpers.stat.Statistics; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public final class MethodBody implements Cloneable { - - private static final Logger logger = Logger.getLogger(MethodBody.class.getName()); - - private static final String DEBUG_FIXED = null; - - @Internal - public boolean deleted; - - @Internal - boolean debugMode = false; - - public int method_info; - - public int max_stack; - - public int max_regs; - - public int init_scope_depth; - - public int max_scope_depth; - - @SWFField - private byte[] codeBytes; - - private AVM2Code code; - - public ABCException[] exceptions; - - public Traits traits; - - @Internal - public transient List convertedItems; - - @Internal - public transient Throwable convertException; - - @Internal - private ABC abc; - - public MethodBody() { - this.traits = new Traits(); - this.codeBytes = SWFInputStream.BYTE_ARRAY_EMPTY; - this.exceptions = new ABCException[0]; - this.abc = null; - } - - public void setAbc(ABC abc) { - this.abc = abc; - } - - public MethodBody(ABC abc, Traits traits, byte[] codeBytes, ABCException[] exceptions) { - this.traits = traits; - this.codeBytes = codeBytes; - this.exceptions = exceptions; - this.abc = abc; - } - - public synchronized void setCodeBytes(byte codeBytes[]) { - this.codeBytes = codeBytes; - this.code = null; - } - - public void setModified() { - this.codeBytes = null; - } - - public synchronized byte[] getCodeBytes() { - if (codeBytes != null) { - return codeBytes; - } else { - return code.getBytes(); - } - } - - public synchronized AVM2Code getCode() { - if (code == null) { - AVM2Code avm2Code; - try { - ABCInputStream ais = new ABCInputStream(new MemoryInputStream(codeBytes)); - avm2Code = new AVM2Code(ais, this); - avm2Code.removeWrongIndices(abc.constants); - } catch (UnknownInstructionCode | IOException ex) { - avm2Code = new AVM2Code(); - logger.log(Level.SEVERE, null, ex); - } - avm2Code.compact(); - code = avm2Code; - } - return code; - } - - public void setCode(AVM2Code code) { - this.code = code; - this.codeBytes = null; - } - - public List getExceptionEntries() { - List ret = new ArrayList<>(); - AVM2Code code = getCode(); - for (ABCException e : exceptions) { - ret.add(code.adr2pos(e.start, true)); - ret.add(code.adr2pos(e.end, true)); - ret.add(code.adr2pos(e.target)); - } - return ret; - } - - public void markOffsets() { - getCode().markOffsets(); - } - - @Override - public String toString() { - String s = ""; - s += "method_info=" + method_info + " max_stack=" + max_stack + " max_regs=" + max_regs + " scope_depth=" + init_scope_depth + " max_scope=" + max_scope_depth; - s += "\r\nCode:\r\n" + getCode().toString(); - return s; - } - - public int removeDeadCode(AVM2ConstantPool constants, Trait trait, MethodInfo info) throws InterruptedException { - return getCode().removeDeadCode(this); - } - - public int removeTraps(ABC abc, Trait trait, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { - - return getCode().removeTraps(trait, method_info, this, abc, scriptIndex, classIndex, isStatic, path); - } - - public void deobfuscate(DeobfuscationLevel level, Trait trait, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { - if (level == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE) { - removeDeadCode(abc.constants, trait, abc.method_info.get(method_info)); - } else if (level == DeobfuscationLevel.LEVEL_REMOVE_TRAPS) { - removeTraps(abc, trait, scriptIndex, classIndex, isStatic, path); - } else if (level == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW) { - removeTraps(abc, trait, scriptIndex, classIndex, isStatic, path); - } - - ((Tag) abc.parentTag).setModified(true); - } - - public void removeInstruction(int pos) { - getCode().removeInstruction(pos, this); - } - - /** - * Replaces instruction by another. Properly handles offsets. Note: If - * newinstruction is jump, the offset operand must be handled properly by - * caller. - * - * @param pos - * @param instruction - */ - public void replaceInstruction(int pos, AVM2Instruction instruction) { - getCode().replaceInstruction(pos, instruction, this); - } - - /** - * Inserts instruction at specified point. Handles offsets properly. Note: - * If newinstruction is jump, the offset operand must be handled properly by - * caller. All old jump offsets to pos are targeted before new instruction. - * - * @param pos Position in the list - * @param instruction Instruction False means before new instruction - */ - public void insertInstruction(int pos, AVM2Instruction instruction) { - getCode().insertInstruction(pos, instruction, this); - } - - public void insertAll(int pos, List list) { - for (AVM2Instruction ins : list) { - insertInstruction(pos++, ins); - } - } - - /** - * Inserts instruction at specified point. Handles offsets properly. Note: - * If newinstruction is jump, the offset operand must be handled properly by - * caller. - * - * @param pos Position in the list - * @param instruction Instruction - * @param mapOffsetsAfterIns Map all jumps to the pos after new instruction? - * False means before new instruction - */ - public void insertInstruction(int pos, AVM2Instruction instruction, boolean mapOffsetsAfterIns) { - getCode().insertInstruction(pos, instruction, mapOffsetsAfterIns, this); - } - - public int getLocalReservedCount() { - MethodInfo methodInfo = abc.method_info.get(this.method_info); - int pos = methodInfo.param_types.length + 1; - if (methodInfo.flagNeed_arguments()) { - pos++; - } - if (methodInfo.flagNeed_rest()) { - pos++; - } - return pos; - } - - public HashMap getLocalRegNames(ABC abc) { - HashMap ret = new HashMap<>(); - for (int i = 1; i <= abc.method_info.get(this.method_info).param_types.length; i++) { - String paramName = "param" + i; - if (abc.method_info.get(this.method_info).flagHas_paramnames() && Configuration.paramNamesEnable.get()) { - paramName = abc.constants.getString(abc.method_info.get(this.method_info).paramNames[i - 1]); - } - ret.put(i, paramName); - } - int pos = abc.method_info.get(this.method_info).param_types.length + 1; - if (abc.method_info.get(this.method_info).flagNeed_arguments()) { - ret.put(pos, "arguments"); - pos++; - } - if (abc.method_info.get(this.method_info).flagNeed_rest()) { - ret.put(pos, "rest"); - pos++; - } - - if (Configuration.getLocalNamesFromDebugInfo.get()) { - Map debugRegNames = getCode().getLocalRegNamesFromDebug(abc); - for (int k : debugRegNames.keySet()) { - ret.put(k, debugRegNames.get(k)); - } - } - return ret; - } - - public void convert(final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, final List initTraits, boolean firstLevel) throws InterruptedException { - if (debugMode) { - System.err.println("Decompiling " + path); - } - if (exportMode != ScriptExportMode.AS) { - getCode().toASMSource(abc.constants, trait, abc.method_info.get(this.method_info), this, exportMode, writer); - } else { - if ((DEBUG_FIXED != null && !path.endsWith(DEBUG_FIXED)) || (!Configuration.decompile.get())) { - writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); - return; - } - int timeout = Configuration.decompilationTimeoutSingleMethod.get(); - convertException = null; - try { - Callable callable = new Callable() { - @Override - public Void call() throws InterruptedException { - try (Statistics s1 = new Statistics("MethodBody.convert")) { - MethodBody converted = convertMethodBody(convertData, path, isStatic, scriptIndex, classIndex, abc, trait, scopeStack, initializerType != GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, fullyQualifiedNames, initTraits); - HashMap localRegNames = getLocalRegNames(abc); - List convertedItems1; - try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) { - convertedItems1 = converted.getCode().toGraphTargetItems(convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted)); - } - try (Statistics s = new Statistics("Graph.graphToString")) { - Graph.graphToString(convertedItems1, writer, LocalData.create(abc.constants, localRegNames, fullyQualifiedNames)); - } - convertedItems = convertedItems1; - } - return null; - } - }; - if (firstLevel) { - CancellableWorker.call(callable, timeout, TimeUnit.SECONDS); - } else { - callable.call(); - } - } catch (InterruptedException ex) { - throw ex; - } catch (Exception | OutOfMemoryError | StackOverflowError ex) { - - convertException = ex; - Throwable cause = ex.getCause(); - if (ex instanceof ExecutionException && cause instanceof Exception) { - convertException = (Exception) cause; - } - if (convertException instanceof TimeoutException) { - logger.log(Level.SEVERE, "Decompilation timeout in: " + path, convertException); - } else { - logger.log(Level.SEVERE, "Decompilation error in: " + path, convertException); - } - - } - } - } - - public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames) throws InterruptedException { - if (exportMode != ScriptExportMode.AS) { - getCode().toASMSource(abc.constants, trait, abc.method_info.get(this.method_info), this, exportMode, writer); - } else { - if ((DEBUG_FIXED != null && !path.endsWith(DEBUG_FIXED)) || (!Configuration.decompile.get())) { - //writer.startMethod(this.method_info); - writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); - //writer.endMethod(); - return writer; - } - int timeout = Configuration.decompilationTimeoutSingleMethod.get(); - - try (Statistics s = new Statistics("MethodBody.toString")) { - if (convertException == null) { - HashMap localRegNames = getLocalRegNames(abc); - //writer.startMethod(this.method_info); - if (Configuration.showMethodBodyId.get()) { - writer.appendNoHilight("// method body index: "); - writer.appendNoHilight(abc.findBodyIndex(this.method_info)); - writer.appendNoHilight(" method index: "); - writer.appendNoHilight(this.method_info); - writer.newLine(); - } - Graph.graphToString(convertedItems, writer, LocalData.create(abc.constants, localRegNames, fullyQualifiedNames)); - //writer.endMethod(); - } else if (convertException instanceof TimeoutException) { - // exception was logged in convert method - Helper.appendTimeoutCommentAs3(writer, timeout, getCode().code.size()); - } else { - // exception was logged in convert method - Helper.appendErrorComment(writer, convertException); - } - } - } - return writer; - } - - public MethodBody convertMethodBody(ConvertData convertData, String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, ScopeStack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, List initTraits) throws InterruptedException { - MethodBody body = clone(); - AVM2Code code = body.getCode(); - code.fixJumps(path, body); - - if (convertData.deobfuscationMode != 0) { - try { - code.removeTraps(trait, method_info, body, abc, scriptIndex, classIndex, isStatic, path); - } catch (ThreadDeath | InterruptedException ex) { - throw ex; - } catch (Throwable ex) { - //ignore - logger.log(Level.SEVERE, "Deobfuscation failed in: " + path, ex); - body = clone(); - code = body.getCode(); - code.fixJumps(path, body); - return body; - } - } - - return body; - } - - public String toSource() { - ConvertData convertData = new ConvertData(); - convertData.deobfuscationMode = 0; - try { - convert(convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - writer.indent().indent().indent(); - toString("", ScriptExportMode.AS, abc, null, writer, new ArrayList<>()); - writer.unindent().unindent().unindent(); - return writer.toString(); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - - return null; - } - - @Override - public MethodBody clone() { - try { - MethodBody ret = (MethodBody) super.clone(); - if (code != null) { - ret.code = code.clone(); - } - - if (exceptions != null) { - ret.exceptions = new ABCException[exceptions.length]; - for (int i = 0; i < exceptions.length; i++) { - ret.exceptions[i] = exceptions[i].clone(); - } - } - - // maybe deep clone traits - /*if (traits != null) { - ret.traits = traits.clone(); - }*/ - ret.convertedItems = null; - ret.convertException = null; - - return ret; - } catch (CloneNotSupportedException ex) { - throw new RuntimeException(); - } - } - - public boolean autoFillStats(ABC abc, int initScope, boolean hasThis) { - //System.out.println("--------------"); - CodeStats stats = getCode().getStats(abc, this, initScope); - if (stats == null) { - return false; - } - if (stats.has_activation) { - initScope++; - } - max_stack = stats.maxstack; - max_scope_depth = stats.maxscope + (stats.has_activation ? 1 : 0); - max_regs = stats.maxlocal; - init_scope_depth = initScope; - abc.method_info.get(method_info).setFlagSetsdxns(stats.has_set_dxns); - abc.method_info.get(method_info).setFlagNeed_activation(stats.has_activation); - MethodInfo mi = abc.method_info.get(method_info); - int min_regs = mi.param_types.length + 1 + (mi.flagNeed_rest() ? 1 : 0); - if (max_regs < min_regs) { - max_regs = min_regs; - } - return true; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.abc.types; + +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ABCInputStream; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.CodeStats; +import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFField; +import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.MemoryInputStream; +import com.jpexs.helpers.stat.Statistics; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public final class MethodBody implements Cloneable { + + private static final Logger logger = Logger.getLogger(MethodBody.class.getName()); + + private static final String DEBUG_FIXED = null; + + @Internal + public boolean deleted; + + @Internal + boolean debugMode = false; + + public int method_info; + + public int max_stack; + + public int max_regs; + + public int init_scope_depth; + + public int max_scope_depth; + + @SWFField + private byte[] codeBytes; + + private AVM2Code code; + + public ABCException[] exceptions; + + public Traits traits; + + @Internal + public transient List convertedItems; + + @Internal + public transient Throwable convertException; + + @Internal + private ABC abc; + + public MethodBody() { + this.traits = new Traits(); + this.codeBytes = SWFInputStream.BYTE_ARRAY_EMPTY; + this.exceptions = new ABCException[0]; + this.abc = null; + } + + public void setAbc(ABC abc) { + this.abc = abc; + } + + public MethodBody(ABC abc, Traits traits, byte[] codeBytes, ABCException[] exceptions) { + this.traits = traits; + this.codeBytes = codeBytes; + this.exceptions = exceptions; + this.abc = abc; + } + + public synchronized void setCodeBytes(byte codeBytes[]) { + this.codeBytes = codeBytes; + this.code = null; + } + + public void setModified() { + this.codeBytes = null; + } + + public synchronized byte[] getCodeBytes() { + if (codeBytes != null) { + return codeBytes; + } else { + return code.getBytes(); + } + } + + public synchronized AVM2Code getCode() { + if (code == null) { + AVM2Code avm2Code; + try { + ABCInputStream ais = new ABCInputStream(new MemoryInputStream(codeBytes)); + avm2Code = new AVM2Code(ais, this); + avm2Code.removeWrongIndices(abc.constants); + } catch (UnknownInstructionCode | IOException ex) { + avm2Code = new AVM2Code(); + logger.log(Level.SEVERE, null, ex); + } + avm2Code.compact(); + code = avm2Code; + } + return code; + } + + public void setCode(AVM2Code code) { + this.code = code; + this.codeBytes = null; + } + + public List getExceptionEntries() { + List ret = new ArrayList<>(); + AVM2Code code = getCode(); + for (ABCException e : exceptions) { + ret.add(code.adr2pos(e.start, true)); + ret.add(code.adr2pos(e.end, true)); + ret.add(code.adr2pos(e.target)); + } + return ret; + } + + public void markOffsets() { + getCode().markOffsets(); + } + + @Override + public String toString() { + String s = ""; + s += "method_info=" + method_info + " max_stack=" + max_stack + " max_regs=" + max_regs + " scope_depth=" + init_scope_depth + " max_scope=" + max_scope_depth; + s += "\r\nCode:\r\n" + getCode().toString(); + return s; + } + + public int removeDeadCode(AVM2ConstantPool constants, Trait trait, MethodInfo info) throws InterruptedException { + return getCode().removeDeadCode(this); + } + + public int removeTraps(ABC abc, Trait trait, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { + + return getCode().removeTraps(trait, method_info, this, abc, scriptIndex, classIndex, isStatic, path); + } + + public void deobfuscate(DeobfuscationLevel level, Trait trait, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { + if (level == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE) { + removeDeadCode(abc.constants, trait, abc.method_info.get(method_info)); + } else if (level == DeobfuscationLevel.LEVEL_REMOVE_TRAPS) { + removeTraps(abc, trait, scriptIndex, classIndex, isStatic, path); + } else if (level == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW) { + removeTraps(abc, trait, scriptIndex, classIndex, isStatic, path); + } + + ((Tag) abc.parentTag).setModified(true); + } + + public void removeInstruction(int pos) { + getCode().removeInstruction(pos, this); + } + + /** + * Replaces instruction by another. Properly handles offsets. Note: If + * newinstruction is jump, the offset operand must be handled properly by + * caller. + * + * @param pos + * @param instruction + */ + public void replaceInstruction(int pos, AVM2Instruction instruction) { + getCode().replaceInstruction(pos, instruction, this); + } + + /** + * Inserts instruction at specified point. Handles offsets properly. Note: + * If newinstruction is jump, the offset operand must be handled properly by + * caller. All old jump offsets to pos are targeted before new instruction. + * + * @param pos Position in the list + * @param instruction Instruction False means before new instruction + */ + public void insertInstruction(int pos, AVM2Instruction instruction) { + getCode().insertInstruction(pos, instruction, this); + } + + public void insertAll(int pos, List list) { + for (AVM2Instruction ins : list) { + insertInstruction(pos++, ins); + } + } + + /** + * Inserts instruction at specified point. Handles offsets properly. Note: + * If newinstruction is jump, the offset operand must be handled properly by + * caller. + * + * @param pos Position in the list + * @param instruction Instruction + * @param mapOffsetsAfterIns Map all jumps to the pos after new instruction? + * False means before new instruction + */ + public void insertInstruction(int pos, AVM2Instruction instruction, boolean mapOffsetsAfterIns) { + getCode().insertInstruction(pos, instruction, mapOffsetsAfterIns, this); + } + + public int getLocalReservedCount() { + MethodInfo methodInfo = abc.method_info.get(this.method_info); + int pos = methodInfo.param_types.length + 1; + if (methodInfo.flagNeed_arguments()) { + pos++; + } + if (methodInfo.flagNeed_rest()) { + pos++; + } + return pos; + } + + public HashMap getLocalRegNames(ABC abc) { + HashMap ret = new HashMap<>(); + for (int i = 1; i <= abc.method_info.get(this.method_info).param_types.length; i++) { + String paramName = "param" + i; + if (abc.method_info.get(this.method_info).flagHas_paramnames() && Configuration.paramNamesEnable.get()) { + paramName = abc.constants.getString(abc.method_info.get(this.method_info).paramNames[i - 1]); + } + ret.put(i, paramName); + } + int pos = abc.method_info.get(this.method_info).param_types.length + 1; + if (abc.method_info.get(this.method_info).flagNeed_arguments()) { + ret.put(pos, "arguments"); + pos++; + } + if (abc.method_info.get(this.method_info).flagNeed_rest()) { + ret.put(pos, "rest"); + pos++; + } + + if (Configuration.getLocalNamesFromDebugInfo.get()) { + Map debugRegNames = getCode().getLocalRegNamesFromDebug(abc); + for (int k : debugRegNames.keySet()) { + ret.put(k, debugRegNames.get(k)); + } + } + return ret; + } + + public void convert(final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, final List initTraits, boolean firstLevel) throws InterruptedException { + if (debugMode) { + System.err.println("Decompiling " + path); + } + if (exportMode != ScriptExportMode.AS) { + getCode().toASMSource(abc.constants, trait, abc.method_info.get(this.method_info), this, exportMode, writer); + } else { + if ((DEBUG_FIXED != null && !path.endsWith(DEBUG_FIXED)) || (!Configuration.decompile.get())) { + writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); + return; + } + int timeout = Configuration.decompilationTimeoutSingleMethod.get(); + convertException = null; + try { + Callable callable = new Callable() { + @Override + public Void call() throws InterruptedException { + try (Statistics s1 = new Statistics("MethodBody.convert")) { + MethodBody converted = convertMethodBody(convertData, path, isStatic, scriptIndex, classIndex, abc, trait, scopeStack, initializerType != GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, fullyQualifiedNames, initTraits); + HashMap localRegNames = getLocalRegNames(abc); + List convertedItems1; + try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) { + convertedItems1 = converted.getCode().toGraphTargetItems(convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted)); + } + try (Statistics s = new Statistics("Graph.graphToString")) { + Graph.graphToString(convertedItems1, writer, LocalData.create(abc.constants, localRegNames, fullyQualifiedNames)); + } + convertedItems = convertedItems1; + } + return null; + } + }; + if (firstLevel) { + CancellableWorker.call(callable, timeout, TimeUnit.SECONDS); + } else { + callable.call(); + } + } catch (InterruptedException ex) { + throw ex; + } catch (Exception | OutOfMemoryError | StackOverflowError ex) { + + convertException = ex; + Throwable cause = ex.getCause(); + if (ex instanceof ExecutionException && cause instanceof Exception) { + convertException = (Exception) cause; + } + if (convertException instanceof TimeoutException) { + logger.log(Level.SEVERE, "Decompilation timeout in: " + path, convertException); + } else { + logger.log(Level.SEVERE, "Decompilation error in: " + path, convertException); + } + + } + } + } + + public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames) throws InterruptedException { + if (exportMode != ScriptExportMode.AS) { + getCode().toASMSource(abc.constants, trait, abc.method_info.get(this.method_info), this, exportMode, writer); + } else { + if ((DEBUG_FIXED != null && !path.endsWith(DEBUG_FIXED)) || (!Configuration.decompile.get())) { + //writer.startMethod(this.method_info); + writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine(); + //writer.endMethod(); + return writer; + } + int timeout = Configuration.decompilationTimeoutSingleMethod.get(); + + try (Statistics s = new Statistics("MethodBody.toString")) { + if (convertException == null) { + HashMap localRegNames = getLocalRegNames(abc); + //writer.startMethod(this.method_info); + if (Configuration.showMethodBodyId.get()) { + writer.appendNoHilight("// method body index: "); + writer.appendNoHilight(abc.findBodyIndex(this.method_info)); + writer.appendNoHilight(" method index: "); + writer.appendNoHilight(this.method_info); + writer.newLine(); + } + Graph.graphToString(convertedItems, writer, LocalData.create(abc.constants, localRegNames, fullyQualifiedNames)); + //writer.endMethod(); + } else if (convertException instanceof TimeoutException) { + // exception was logged in convert method + Helper.appendTimeoutCommentAs3(writer, timeout, getCode().code.size()); + } else { + // exception was logged in convert method + Helper.appendErrorComment(writer, convertException); + } + } + } + return writer; + } + + public MethodBody convertMethodBody(ConvertData convertData, String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, ScopeStack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, List initTraits) throws InterruptedException { + MethodBody body = clone(); + AVM2Code code = body.getCode(); + code.fixJumps(path, body); + + if (convertData.deobfuscationMode != 0) { + try { + code.removeTraps(trait, method_info, body, abc, scriptIndex, classIndex, isStatic, path); + } catch (ThreadDeath | InterruptedException ex) { + throw ex; + } catch (Throwable ex) { + //ignore + logger.log(Level.SEVERE, "Deobfuscation failed in: " + path, ex); + body = clone(); + code = body.getCode(); + code.fixJumps(path, body); + return body; + } + } + + return body; + } + + public String toSource() { + ConvertData convertData = new ConvertData(); + convertData.deobfuscationMode = 0; + try { + convert(convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + writer.indent().indent().indent(); + toString("", ScriptExportMode.AS, abc, null, writer, new ArrayList<>()); + writer.unindent().unindent().unindent(); + return writer.toString(); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + + return null; + } + + @Override + public MethodBody clone() { + try { + MethodBody ret = (MethodBody) super.clone(); + if (code != null) { + ret.code = code.clone(); + } + + if (exceptions != null) { + ret.exceptions = new ABCException[exceptions.length]; + for (int i = 0; i < exceptions.length; i++) { + ret.exceptions[i] = exceptions[i].clone(); + } + } + + // maybe deep clone traits + /*if (traits != null) { + ret.traits = traits.clone(); + }*/ + ret.convertedItems = null; + ret.convertException = null; + + return ret; + } catch (CloneNotSupportedException ex) { + throw new RuntimeException(); + } + } + + public boolean autoFillStats(ABC abc, int initScope, boolean hasThis) { + //System.out.println("--------------"); + CodeStats stats = getCode().getStats(abc, this, initScope); + if (stats == null) { + return false; + } + if (stats.has_activation) { + initScope++; + } + max_stack = stats.maxstack; + max_scope_depth = stats.maxscope + (stats.has_activation ? 1 : 0); + max_regs = stats.maxlocal; + init_scope_depth = initScope; + abc.method_info.get(method_info).setFlagSetsdxns(stats.has_set_dxns); + abc.method_info.get(method_info).setFlagNeed_activation(stats.has_activation); + MethodInfo mi = abc.method_info.get(method_info); + int min_regs = mi.param_types.length + 1 + (mi.flagNeed_rest() ? 1 : 0); + if (max_regs < min_regs) { + max_regs = min_regs; + } + return true; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java index 489f5f072..89a9cefc8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java @@ -1,1496 +1,1496 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action; - -import com.jpexs.decompiler.flash.AppResources; -import com.jpexs.decompiler.flash.BaseLocalData; -import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; -import com.jpexs.decompiler.flash.action.model.ActionItem; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.ExtendsActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; -import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; -import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem; -import com.jpexs.decompiler.flash.action.model.SetVariableActionItem; -import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; -import com.jpexs.decompiler.flash.action.model.TemporaryRegister; -import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; -import com.jpexs.decompiler.flash.action.parser.ActionParseException; -import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; -import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; -import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionStore; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionWith; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.action.swf7.ActionTry; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.ecma.Undefined; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.CodeFormatting; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.flash.helpers.collections.MyEntry; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.CommentItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.PopItem; -import com.jpexs.decompiler.graph.model.ScriptEndItem; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Represents one ACTIONRECORD, also has some static method to work with Actions - * - * @author JPEXS - */ -public abstract class Action implements GraphSourceItem { - - private static final int INFORM_LISTENER_RESOLUTION = 100; - - private boolean ignored = false; - - public long fileOffset = -1; - - /** - * Action type identifier - */ - private int actionCode; - - /** - * Length of action data - */ - protected int actionLength; - - private long address; - - @Override - public long getLineOffset() { - return fileOffset; - } - - /** - * Names of ActionScript properties - */ - public static final String[] propertyNames = new String[]{ - "_X", - "_Y", - "_xscale", - "_yscale", - "_currentframe", - "_totalframes", - "_alpha", - "_visible", - "_width", - "_height", - "_rotation", - "_target", - "_framesloaded", - "_name", - "_droptarget", - "_url", - "_highquality", - "_focusrect", - "_soundbuftime", - "_quality", - "_xmouse", - "_ymouse" - }; - - public static final List propertyNamesList = Arrays.asList(propertyNames); - - private static final Logger logger = Logger.getLogger(Action.class.getName()); - - /** - * Constructor - * - * @param actionCode Action type identifier - * @param actionLength Length of action data - */ - public Action(int actionCode, int actionLength) { - this.actionCode = actionCode; - this.actionLength = actionLength; - } - - public Action() { - } - - /** - * Returns address of this action - * - * @return address of this action - */ - @Override - public long getAddress() { - return address; - } - - /** - * Return code of this action - * - * @return code of this action - */ - public int getActionCode() { - return actionCode; - } - - /** - * Gets all addresses which are referenced from this action and/or - * subactions - * - * @param refs list of addresses - */ - public void getRef(Set refs) { - } - - /** - * Gets all addresses which are referenced from the list of actions - * - * @param list List of actions - * @return List of addresses - */ - public static Set getActionsAllRefs(List list) { - Set ret = new HashSet<>(); - for (Action a : list) { - a.getRef(ret); - } - return ret; - } - - public int getTotalActionLength() { - return actionLength + 1 + (actionCode >= 0x80 ? 2 : 0); - } - - /** - * Sets address of this instruction - * - * @param address Address - */ - public void setAddress(long address) { - this.address = address; - } - - /** - * Returns a string representation of the object - * - * @return a string representation of the object. - */ - @Override - public String toString() { - return "Action" + actionCode; - } - - /** - * Reads String from FlasmLexer - * - * @param lex FlasmLexer - * @return String value - * @throws IOException - * @throws ActionParseException When read object is not String - */ - protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_STRING) { - throw new ActionParseException("String expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads Block startServer from FlasmLexer - * - * @param lex FlasmLexer - * @throws IOException - * @throws ActionParseException When read object is not Block startServer - */ - protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { - throw new ActionParseException("Block startServer ", lex.yyline()); - } - } - - /** - * Reads Identifier from FlasmLexer - * - * @param lex FlasmLexer - * @return Identifier name - * @throws IOException - * @throws ActionParseException When read object is not Identifier - */ - protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { - throw new ActionParseException("Identifier expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads long value from FlasmLexer - * - * @param lex FlasmLexer - * @return long value - * @throws IOException - * @throws ActionParseException When read object is not long value - */ - protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { - throw new ActionParseException("Integer expected", lex.yyline()); - } - return (Long) symb.value; - } - - /** - * Reads boolean value from FlasmLexer - * - * @param lex FlasmLexer - * @return boolean value - * @throws IOException - * @throws ActionParseException When read object is not boolean value - */ - protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { - throw new ActionParseException("Boolean expected", lex.yyline()); - } - return (Boolean) symb.value; - } - - /** - * Gets action converted to bytes - * - * @param version SWF version - * @return Array of bytes - */ - public final byte[] getBytes(int version) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, version); - try { - getContentBytes(sos); - sos.close(); - } catch (IOException e) { - throw new Error("This should never happen.", e); - } - return surroundWithAction(baos.toByteArray(), version); - } - - protected void getContentBytes(SWFOutputStream sos) throws IOException { - } - - /** - * Gets the length of action converted to bytes - * - * @return Length - */ - public final int getBytesLength() { - return getContentBytesLength() + (actionCode >= 0x80 ? 3 : 1); - } - - protected int getContentBytesLength() { - return 0; - } - - /** - * Updates the action length to the length calculated from action bytes - */ - public void updateLength() { - int length = getBytesLength(); - actionLength = length - 1 - (actionCode >= 0x80 ? 2 : 0); - } - - /** - * Surrounds byte array with Action header - * - * @param data Byte array - * @param version SWF version - * @return Byte array - */ - private byte[] surroundWithAction(byte[] data, int version) { - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, version); - try { - sos2.writeUI8(actionCode); - if (actionCode >= 0x80) { - sos2.writeUI16(data.length); - } - sos2.write(data); - sos2.close(); - } catch (IOException e) { - throw new Error("This should never happen.", e); - } - return baos2.toByteArray(); - } - - @Override - public long getFileOffset() { - return fileOffset; - } - - /** - * Converts list of Actions to bytes - * - * @param list List of actions - * @param addZero Whether or not to add 0 UI8 value to the end - * @param version SWF version - * @return Array of bytes - */ - public static byte[] actionsToBytes(List list, boolean addZero, int version) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Action lastAction = null; - for (Action a : list) { - try { - lastAction = a; - baos.write(a.getBytes(version)); - } catch (IOException e) { - } - } - if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { - baos.write(0); - } - return baos.toByteArray(); - } - - public static ByteArrayRange actionsToByteArrayRange(List list, boolean addZero, int version) { - byte[] bytes = Action.actionsToBytes(list, addZero, version); - return new ByteArrayRange(bytes); - } - - public static void setConstantPools(ASMSource src, List> constantPools, boolean tryInline) throws ConstantPoolTooBigException { - try { - ActionList actions = src.getActions(); - int poolIdx = 0; - for (Action action : actions) { - if (action instanceof ActionConstantPool) { - ActionConstantPool cPool = (ActionConstantPool) action; - List constantPool = constantPools.get(poolIdx); - - int size = ActionConstantPool.calculateSize(constantPool); - if (size > 0xffff && tryInline) { - for (int i = 0; i < constantPool.size(); i++) { - int refCount = actions.getConstantPoolIndexReferenceCount(i); - if (refCount == 1) { - actions.inlineConstantPoolString(i, constantPool.get(i)); - constantPool.set(i, ""); - } - } - - size = ActionConstantPool.calculateSize(constantPool); - } - - if (size > 0xffff) { - throw new ConstantPoolTooBigException(poolIdx, size); - } - - cPool.constantPool = constantPool; - - poolIdx++; - if (constantPools.size() <= poolIdx) { - break; - } - } - } - - actions.removeNonReferencedConstantPoolItems(); - src.setActions(actions); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - /** - * Set addresses of actions in the list - * - * @param list List of actions - * @param baseAddress Address of first action in the list - */ - public static void setActionsAddresses(List list, long baseAddress) { - long offset = baseAddress; - for (Action a : list) { - a.setAddress(offset); - offset += a.getTotalActionLength(); - } - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @return source ASM - * - */ - public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToString(listeners, address, list, version, exportMode, writer); - return writer.toString(); - } - - private static void informListeners(List listeners, int pos, int count) { - if (pos % INFORM_LISTENER_RESOLUTION == 0) { - DisassemblyListener[] listenersArray = listeners.toArray(new DisassemblyListener[listeners.size()]); - for (DisassemblyListener listener : listenersArray) { - listener.progressToString(pos + 1, count); - } - } - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @param writer - * @return GraphTextWriter - */ - public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - if (exportMode == ScriptExportMode.CONSTANTS) { - return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); - } - - long offset; - Set importantOffsets = getActionsAllRefs(list); - /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); - if (!cps.isEmpty()) { - setConstantPool(list, cps.get(cps.size() - 1)); - }*/ - HashMap> containers = new HashMap<>(); - HashMap containersPos = new HashMap<>(); - offset = address; - int pos = 0; - boolean lastPush = false; - byte[] fileData = list.fileData; - for (Action a : list) { - informListeners(listeners, pos, list.size()); - - if (exportMode == ScriptExportMode.PCODE_HEX) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("; "); - long fileOffset = a.getFileOffset(); - if (Configuration.showFileOffsetInPcodeHex.get()) { - writer.appendNoHilight("@"); - writer.appendNoHilight(Helper.formatHex(fileOffset, 8)); - writer.appendNoHilight(" "); - } - - byte[] bytes = a.getBytes(version); - writer.appendNoHilight(Helper.bytesToHexString(bytes)); - - if (Configuration.showOriginalBytesInPcodeHex.get()) { - if (fileData != null && fileOffset != -1 && fileData.length > fileOffset + bytes.length - 1) { - boolean same = true; - for (int i = 0; i < bytes.length; i++) { - byte b = fileData[(int) (fileOffset + i)]; - if (b != bytes[i]) { - same = false; - break; - } - } - - if (!same) { - writer.appendNoHilight(" ("); - for (int i = 0; i < bytes.length; i++) { - if (i != 0) { - writer.appendNoHilight(" "); - } - - writer.appendNoHilight(Helper.byteToHex(fileData[(int) (fileOffset + i)])); - } - - writer.appendNoHilight(")"); - } - - } - } - - writer.newLine(); - } - - offset = a.getAddress(); - - if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - containersPos.put(cnt, 0); - List sizes = cnt.getContainerSizes(); - long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); - for (Long size : sizes) { - addr += size; - if (size == 0) { - continue; - } - if (!containers.containsKey(addr)) { - containers.put(addr, new ArrayList<>()); - } - containers.get(addr).add(cnt); - } - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("}").newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - } - - if (a.isIgnored()) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - if (!(a instanceof ActionEnd)) { - int len = a.getTotalActionLength(); - for (int i = 0; i < len; i++) { - writer.appendNoHilight("Nop").newLine(); - } - } - } else { - //if (!(a instanceof ActionNop)) { - String add = ""; - // honfika: commented out the following lines, because it makes no sense - /*if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - add = "; ofs" + Helper.formatAddress(offset) + add; - add = "";*/ - if ((a instanceof ActionPush) && lastPush) { - writer.appendNoHilight(" "); - ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); - } else { - if (lastPush) { - writer.newLine(); - //lastPush = false; - } - - writer.append("", offset, a.getFileOffset()); - - int fixBranch = -1; - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - if (aif.jumpUsed && !aif.ignoreUsed) { - fixBranch = 0; - } - if (!aif.jumpUsed && aif.ignoreUsed) { - fixBranch = 1; - } - } - - if (fixBranch > -1) { - writer.appendNoHilight("FFDec_DeobfuscatePop"); - if (fixBranch == 0) { //jump - writer.newLine(); - writer.appendNoHilight("Jump loc"); - writer.appendNoHilight(Helper.formatAddress(((ActionIf) a).getTargetAddress())); - } else { - //nojump, ignore - } - } else { - a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); - } - writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); - writer.appendNoHilight(add); - if (!(a instanceof ActionPush)) { - writer.newLine(); - } - } - lastPush = a instanceof ActionPush; - //} - } - - offset += a.getTotalActionLength(); - pos++; - } - if (lastPush) { - writer.newLine(); - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - writer.appendNoHilight("}"); - writer.newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (importantOffsets.contains(offset)) { - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - writer.newLine(); - } - - return writer; - } - - public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - int poolIdx = 0; - writer.appendNoHilight(Helper.constants).newLine(); - for (Action a : list) { - if (a instanceof ActionConstantPool) { - if (poolIdx > 0) { - writer.appendNoHilight("---").newLine(); - } - - ActionConstantPool cPool = (ActionConstantPool) a; - int constIdx = 0; - for (String c : cPool.constantPool) { - writer.appendNoHilight(constIdx); - writer.appendNoHilight("|"); - writer.appendNoHilight(Helper.escapeString(c)); - writer.newLine(); - constIdx++; - } - - poolIdx++; - } - } - - return writer; - } - - /** - * Convert action to ASM source - * - * @param container - * @param knownAddreses List of important offsets to mark as labels - * @param exportMode PCode or hex? - * @return String of P-code source - */ - public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { - return toString(); - } - - public abstract boolean execute(LocalDataArea lda); - - /* { - //throw new UnsupportedOperationException("Action " + toString() + " not implemented"); - return false; - }*/ - /** - * Translates this function to stack and output. - * - * @param lineStartIns Line start instruction - * @param stack Stack - * @param output Output - * @param regNames Register names - * @param variables Variables - * @param functions Functions - * @param staticOperation the value of staticOperation - * @param path the value of path - * @throws java.lang.InterruptedException - */ - public void translate(GraphSourceItem lineStartIns, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { - } - - @Override - public int getStackPopCount(BaseLocalData localData, TranslateStack stack) { - return 0; - } - - @Override - public int getStackPushCount(BaseLocalData localData, TranslateStack stack) { - return 0; - } - - /** - * Pops long value off the stack - * - * @param stack Stack - * @return long value - */ - protected long popLong(TranslateStack stack) { - GraphTargetItem item = stack.pop(); - if (item instanceof DirectValueActionItem) { - return (long) (double) EcmaScript.toNumberAs2(((DirectValueActionItem) item).value); - } - - return 0; - } - - /** - * Converts action index to address in the specified list of actions - * - * @param actions List of actions - * @param ip Action index - * @return address - */ - public static long ip2adr(List actions, int ip) { - /* List actions=new ArrayList(); - for(GraphSourceItem s:sources){ - if(s instanceof Action){ - actions.add((Action)s); - } - }*/ - if (ip >= actions.size()) { - if (actions.isEmpty()) { - return 0; - } - return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - } - if (ip == -1) { - return 0; - } - return actions.get(ip).getAddress(); - } - - /** - * Converts address to action index in the specified list of actions - * - * @param actions List of actions - * @param addr Address - * @return action index - */ - public static int adr2ip(List actions, long addr) { - for (int ip = 0; ip < actions.size(); ip++) { - if (actions.get(ip).getAddress() == addr) { - return ip; - } - } - if (actions.size() > 0) { - long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - if (addr == outpos) { - return actions.size(); - } - } - return -1; - } - - public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { - return actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @return source - * @throws java.lang.InterruptedException - */ - public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToSource(asm, actions, path, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @param writer - * @throws java.lang.InterruptedException - */ - public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { - writer.suspendMeasure(); - List tree = null; - Throwable convertException = null; - int timeout = Configuration.decompilationTimeoutSingleMethod.get(); - final SWF swf = asm == null ? null : asm.getSwf(); - final int version = swf == null ? SWF.DEFAULT_VERSION : swf.version; - try { - tree = CancellableWorker.call(new Callable>() { - @Override - public List call() throws Exception { - int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; - List tree = actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path); - SWFDecompilerPlugin.fireActionTreeCreated(tree, swf); - if (Configuration.autoDeobfuscate.get()) { - new ActionDeobfuscator().actionTreeCreated(tree, swf); - } - - Graph.graphToString(tree, new NulWriter(), new LocalData()); - return tree; - } - }, timeout, TimeUnit.SECONDS); - } catch (InterruptedException ex) { - throw ex; - } catch (Exception | OutOfMemoryError | StackOverflowError ex) { - - convertException = ex; - Throwable cause = ex.getCause(); - if (ex instanceof ExecutionException && cause instanceof Exception) { - convertException = cause; - } - if (convertException instanceof TimeoutException) { - logger.log(Level.SEVERE, "Decompilation timeout in: " + path, convertException); - } else { - logger.log(Level.SEVERE, "Decompilation error in: " + path, convertException); - } - - } - writer.continueMeasure(); - - if (asm != null) { - asm.getActionSourcePrefix(writer); - } - if (convertException == null) { - Graph.graphToString(tree, writer, new LocalData()); - } else if (convertException instanceof TimeoutException) { - Helper.appendTimeoutCommentAs2(writer, timeout, actions.size()); - } else { - Helper.appendErrorComment(writer, convertException); - } - if (asm != null) { - asm.getActionSourceSuffix(writer); - } - } - - /** - * Converts list of actions to List of treeItems - * - * @param regNames Register names - * @param variables - * @param functions - * @param actions List of actions - * @param version SWF version - * @param staticOperation - * @param path - * @return List of treeItems - * @throws java.lang.InterruptedException - */ - public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { - return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); - } - - @Override - public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { - ActionLocalData aLocalData = (ActionLocalData) localData; - /*int expectedSize = stack.size() - getStackPopCount(localData, stack); - if (expectedSize < 0) { - expectedSize = 0; - } - expectedSize += getStackPushCount(localData, stack);*/ - - translate(aLocalData.lineStartAction, stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); - /*if (stack.size() != expectedSize && !(this instanceof ActionPushDuplicate)) { - throw new Error("HONFIKA stack size mismatch"); - }*/ - } - - @Override - public boolean isJump() { - return false; - } - - @Override - public boolean isBranch() { - return false; - } - - @Override - public boolean isExit() { - return false; - } - - @Override - public List getBranches(GraphSource code) { - return new ArrayList<>(); - } - - @Override - public boolean isIgnored() { - return ignored; - } - - @Override - public void setIgnored(boolean ignored, int pos) { - this.ignored = ignored; - } - - public static List actionsPartToTree(Reference fi, HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { - if (start < actions.size() && (end > 0) && (start > 0)) { - logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""}); - } - ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); - localData.lineStartAction = fi.getVal(); - List output = new ArrayList<>(); - int ip = start; - boolean isWhile = false; - boolean isForIn = false; - GraphTargetItem inItem = null; - int loopStart = 0; - loopip: - while (ip <= end) { - - long addr = ip2adr(actions, ip); - if (ip > end) { - break; - } - if (ip >= actions.size()) { - output.add(new ScriptEndItem()); - break; - } - if (Configuration.simplifyExpressions.get()) { - stack.simplify(); - } - Action action = actions.get(ip); - if (action.isIgnored()) { - ip++; - continue; - } - - //FunctionActionItem after DefineFunction(/2) are left on the stack. For linestart offsets we consider this kind of stack empty. - boolean isStackEmpty = true; - for (int i = 0; i < stack.size(); i++) { - if ((!(stack.get(i) instanceof FunctionActionItem))) { - isStackEmpty = false; - break; - } - } - - if (isStackEmpty) { - localData.lineStartAction = action; - fi.setVal(action); - } - if (action instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; - //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); - long endAddr = action.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> outs = new ArrayList<>(); - HashMap variables2 = Helper.deepCopy(variables); - if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { - for (int r = 0; r < 256; r++) { - if (variables2.containsKey("__register" + r)) { - variables2.remove("__register" + r); - } - } - } - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - outs.add(new ArrayList<>()); - continue; - } - List out; - try { - HashMap regNames = cnt.getRegNames(); - if (action instanceof ActionWith || action instanceof ActionTry) { - for (Map.Entry e : registerNames.entrySet()) { - if (!regNames.containsKey(e.getKey())) { - regNames.put(e.getKey(), e.getValue()); - } - } - } - out = ActionGraph.translateViaGraph(regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); - } catch (OutOfMemoryError | TranslateException | StackOverflowError ex) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); - if (ex instanceof OutOfMemoryError) { - Helper.freeMem(); - } - - out = new ArrayList<>(); - out.add(new CommentItem(new String[]{ - "", - " * " + AppResources.translate("decompilationError"), - " * " + AppResources.translate("decompilationError.obfuscated"), - Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, - " * " + AppResources.translate("decompilationError.errorType") + ": " - + ex.getClass().getSimpleName(), - ""})); - } - outs.add(out); - endAddr += size; - } - - ((GraphSourceItemContainer) action).translateContainer(outs, action, stack, output, registerNames, variables, functions); - ip = adr2ip(actions, endAddr); - continue; - } - - //return in for..in - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) == Null.INSTANCE)) { - if (ip + 3 <= end) { - if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { - if (actions.get(ip + 2) instanceof ActionNot) { - if (actions.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) actions.get(ip + 3); - if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - continue; - } - } - } - } - } - } - - /*ActionJump && ActionIf removed*/ - /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { - loopStart = ip + 1; - isForIn = true; - ip += 4; - action.translate(localData, stack, output); - EnumerateActionItem en = (EnumerateActionItem) stack.peek(); - inItem = en.object; - continue; - } else*/ /*if (action instanceof ActionTry) { - ActionTry atry = (ActionTry) action; - List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); - ActionItem catchName; - if (atry.catchInRegisterFlag) { - catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList<>()); - } else { - catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList<>()); - } - List catchExceptions = new ArrayList(); - catchExceptions.add(catchName); - List> catchCommands = new ArrayList>(); - catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); - List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); - output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); - } else if (action instanceof ActionWith) { - ActionWith awith = (ActionWith) action; - List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions - output.add(new WithActionItem(action, stack.pop(), withCommands)); - } else */ if (false) { - } /*if (action instanceof ActionStoreRegister) { - if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { - action.translate(localData, stack, output); - stack.pop(); - ip++; - } else { - try { - action.translate(localData, stack, output); - } catch (Exception ex) { - // ignore - } - } - } */ /*else if (action instanceof ActionStrictEquals) { - if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { - List caseValues = new ArrayList(); - List> caseCommands = new ArrayList>(); - caseValues.add(stack.pop()); - ActionItem switchedObject = stack.pop(); - if (output.size() > 0) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - output.remove(output.size() - 1); - } - } - int caseStart = ip + 2; - List caseBodyIps = new ArrayList(); - long defaultAddr = 0; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); - ip++; - do { - ip++; - if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { - caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); - caseStart = ip + 1; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); - if (actions.get(ip + 1) instanceof ActionJump) { - defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); - ip = adr2ip(actions, defaultAddr, version); - break; - } - } - } while (ip < end); - - for (int i = 0; i < caseBodyIps.size(); i++) { - int caseEnd = ip - 1; - if (i < caseBodyIps.size() - 1) { - caseEnd = caseBodyIps.get(i + 1) - 1; - } - caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); - } - output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); - continue; - } else { - action.translate(stack, constants, output, registerNames); - } - } */ else { - - if (action instanceof ActionStore) { - ActionStore store = (ActionStore) action; - store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); - ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; - } - - action.translate(localData, stack, output, staticOperation, path); - } - - ip++; - } - //output = checkClass(output); - logger.log(Level.FINE, "Leaving {0}-{1}", new Object[]{start, end}); - return output; - } - - public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { - GraphTargetItem t = ti; - if (!(t instanceof GetMemberActionItem)) { - return ti; - } - GetMemberActionItem lastMember = null; - while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { - lastMember = (GetMemberActionItem) t; - t = ((GetMemberActionItem) t).object; - } - if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { - GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; - if (v.name instanceof DirectValueActionItem) { - if (((DirectValueActionItem) v.name).value instanceof String) { - if (((DirectValueActionItem) v.name).value.equals("_global")) { - GetVariableActionItem gvt = new GetVariableActionItem(null, null, ((GetMemberActionItem) t).memberName); - if (lastMember == null) { - return gvt; - } else { - lastMember.object = gvt; - } - } - } - } - } - return ti; - } - - public static List checkClass(List output) { - if (true) { - //return output; - } - List ret = new ArrayList<>(); - List functions = new ArrayList<>(); - List staticFunctions = new ArrayList<>(); - List> vars = new ArrayList<>(); - List> staticVars = new ArrayList<>(); - GraphTargetItem className; - GraphTargetItem extendsOp = null; - List implementsOp = new ArrayList<>(); - boolean ok = true; - int prevCount = 0; - for (GraphTargetItem t : output) { - if (t instanceof IfItem) { - IfItem it = (IfItem) t; - if (it.expression instanceof NotItem) { - NotItem nti = (NotItem) it.expression; - if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { - if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { - if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { - // ignore - } else { - List parts = it.onTrue; - className = getWithoutGlobal(nti.value); - if (parts.size() >= 1) { - int ipos = 0; - - while ((parts.get(ipos) instanceof PopItem) || ((parts.get(ipos) instanceof IfItem) && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem)))) { - ipos++; - } - if (parts.get(ipos) instanceof ExtendsActionItem) { - ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); - extendsOp = getWithoutGlobal(et.superclass); - ipos++; - } - if (parts.get(ipos) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); - int instanceReg = sr.register.number; - if (sr.value instanceof GetMemberActionItem) { - GetMemberActionItem gm = (GetMemberActionItem) sr.value; - //gm.memberName should be "prototype" - if (gm.object instanceof TemporaryRegister) { - TemporaryRegister tm = (TemporaryRegister) gm.object; - int classReg = tm.getRegId(); - if (tm.value instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) tm.value; - if (sm.value instanceof StoreRegisterActionItem) { - sr = (StoreRegisterActionItem) sm.value; - if (sr.value instanceof FunctionActionItem) { - ((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; - functions.add((FunctionActionItem) sr.value); - - for (; ipos < parts.size(); ipos++) { - if (parts.get(ipos) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); - implementsOp = io.superclasses; - continue; - } - if (parts.get(ipos) instanceof SetMemberActionItem) { - sm = (SetMemberActionItem) parts.get(ipos); - int rnum = -1; - if (sm.object instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) sm.object; - if (dv.value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) dv.value; - rnum = rn.number; - } - } - if (sm.object instanceof TemporaryRegister) { - rnum = ((TemporaryRegister) sm.object).getRegId(); - } - if (rnum == instanceReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - functions.add((FunctionActionItem) sm.value); - } else { - vars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } else if (rnum == classReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - staticFunctions.add((FunctionActionItem) sm.value); - } else { - staticVars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } - - } - } - - } - - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); - return output2; - } - } - } else if (parts.get(ipos) instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); - if (sm.value instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) sm.value; - if (f.actions.isEmpty()) { - if (parts.size() == 2) { - if (parts.get(1) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); - implementsOp = iot.superclasses; - } else { - //ok = false; - break; - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); - return output2; - } - } - } - } - } - } else { - //ok = false; - } - } else { - ok = false; - } - } else { - ok = false; - } - } else if (!(t instanceof PopItem)) { - prevCount++; - //ok = false; - } - if (!ok) { - break; - } - } - return output; - } - - @Override - public boolean ignoredLoops() { - return false; - } - - public static void setConstantPool(List actions, ConstantPool cpool) { - for (GraphSourceItem a : actions) { - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - if (a instanceof ActionDefineFunction) { - if (cpool != null) { - //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); - } - } - if (a instanceof ActionDefineFunction2) { - if (cpool != null) { - //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); - } - } - } - } - - public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { - writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); - return writer; - } - - public static double toFloatPoint(Object o) { - if (o instanceof Double) { - return (Double) o; - } - if (o instanceof Integer) { - return (Integer) o; - } - if (o instanceof Long) { - return (Long) o; - } - if (o == Null.INSTANCE) { - return Double.NaN; - } - if (o == Undefined.INSTANCE) { - return Double.NaN; - } - if (o instanceof Boolean) { - return (Boolean) o ? 1.0 : 0.0; - } - if (o instanceof String) { - try { - return Double.parseDouble((String) o); - } catch (NumberFormatException nfe) { - return Double.NaN; - } - } - return 0; - } - - public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { - GraphTargetItem ret = get; - boolean boxed = false; - if (get instanceof VariableActionItem) { - boxed = true; - ret = ((VariableActionItem) ret).getBoxedValue(); - } - if (ret instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) ret; - ret = new SetVariableActionItem(null, null, gv.name, value); - } else if (ret instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) ret; - ret = new SetMemberActionItem(null, null, mem.object, mem.memberName, value); - } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { - ret = new StoreRegisterActionItem(null, null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); - } else if (ret instanceof GetPropertyActionItem) { - GetPropertyActionItem gp = (GetPropertyActionItem) ret; - ret = new SetPropertyActionItem(null, null, gp.target, gp.propertyIndex, value); - } - if (boxed) { - GraphTargetItem b = ret; - ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); - ((VariableActionItem) ret).setBoxedValue((ActionItem) b); - variables.remove((VariableActionItem) get); - variables.add((VariableActionItem) ret); - } - return ret; - } - - @Override - public boolean isDeobfuscatePop() { - return false; - } - - @Override - public int getLine() { - return 0; - } - - @Override - public String getFile() { - return null; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.AppResources; +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; +import com.jpexs.decompiler.flash.action.model.ActionItem; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.ExtendsActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; +import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; +import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.SetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.TemporaryRegister; +import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionWith; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.action.swf7.ActionTry; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.CommentItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.ScriptEndItem; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents one ACTIONRECORD, also has some static method to work with Actions + * + * @author JPEXS + */ +public abstract class Action implements GraphSourceItem { + + private static final int INFORM_LISTENER_RESOLUTION = 100; + + private boolean ignored = false; + + public long fileOffset = -1; + + /** + * Action type identifier + */ + private int actionCode; + + /** + * Length of action data + */ + protected int actionLength; + + private long address; + + @Override + public long getLineOffset() { + return fileOffset; + } + + /** + * Names of ActionScript properties + */ + public static final String[] propertyNames = new String[]{ + "_X", + "_Y", + "_xscale", + "_yscale", + "_currentframe", + "_totalframes", + "_alpha", + "_visible", + "_width", + "_height", + "_rotation", + "_target", + "_framesloaded", + "_name", + "_droptarget", + "_url", + "_highquality", + "_focusrect", + "_soundbuftime", + "_quality", + "_xmouse", + "_ymouse" + }; + + public static final List propertyNamesList = Arrays.asList(propertyNames); + + private static final Logger logger = Logger.getLogger(Action.class.getName()); + + /** + * Constructor + * + * @param actionCode Action type identifier + * @param actionLength Length of action data + */ + public Action(int actionCode, int actionLength) { + this.actionCode = actionCode; + this.actionLength = actionLength; + } + + public Action() { + } + + /** + * Returns address of this action + * + * @return address of this action + */ + @Override + public long getAddress() { + return address; + } + + /** + * Return code of this action + * + * @return code of this action + */ + public int getActionCode() { + return actionCode; + } + + /** + * Gets all addresses which are referenced from this action and/or + * subactions + * + * @param refs list of addresses + */ + public void getRef(Set refs) { + } + + /** + * Gets all addresses which are referenced from the list of actions + * + * @param list List of actions + * @return List of addresses + */ + public static Set getActionsAllRefs(List list) { + Set ret = new HashSet<>(); + for (Action a : list) { + a.getRef(ret); + } + return ret; + } + + public int getTotalActionLength() { + return actionLength + 1 + (actionCode >= 0x80 ? 2 : 0); + } + + /** + * Sets address of this instruction + * + * @param address Address + */ + public void setAddress(long address) { + this.address = address; + } + + /** + * Returns a string representation of the object + * + * @return a string representation of the object. + */ + @Override + public String toString() { + return "Action" + actionCode; + } + + /** + * Reads String from FlasmLexer + * + * @param lex FlasmLexer + * @return String value + * @throws IOException + * @throws ActionParseException When read object is not String + */ + protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_STRING) { + throw new ActionParseException("String expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads Block startServer from FlasmLexer + * + * @param lex FlasmLexer + * @throws IOException + * @throws ActionParseException When read object is not Block startServer + */ + protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { + throw new ActionParseException("Block startServer ", lex.yyline()); + } + } + + /** + * Reads Identifier from FlasmLexer + * + * @param lex FlasmLexer + * @return Identifier name + * @throws IOException + * @throws ActionParseException When read object is not Identifier + */ + protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { + throw new ActionParseException("Identifier expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads long value from FlasmLexer + * + * @param lex FlasmLexer + * @return long value + * @throws IOException + * @throws ActionParseException When read object is not long value + */ + protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { + throw new ActionParseException("Integer expected", lex.yyline()); + } + return (Long) symb.value; + } + + /** + * Reads boolean value from FlasmLexer + * + * @param lex FlasmLexer + * @return boolean value + * @throws IOException + * @throws ActionParseException When read object is not boolean value + */ + protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { + throw new ActionParseException("Boolean expected", lex.yyline()); + } + return (Boolean) symb.value; + } + + /** + * Gets action converted to bytes + * + * @param version SWF version + * @return Array of bytes + */ + public final byte[] getBytes(int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, version); + try { + getContentBytes(sos); + sos.close(); + } catch (IOException e) { + throw new Error("This should never happen.", e); + } + return surroundWithAction(baos.toByteArray(), version); + } + + protected void getContentBytes(SWFOutputStream sos) throws IOException { + } + + /** + * Gets the length of action converted to bytes + * + * @return Length + */ + public final int getBytesLength() { + return getContentBytesLength() + (actionCode >= 0x80 ? 3 : 1); + } + + protected int getContentBytesLength() { + return 0; + } + + /** + * Updates the action length to the length calculated from action bytes + */ + public void updateLength() { + int length = getBytesLength(); + actionLength = length - 1 - (actionCode >= 0x80 ? 2 : 0); + } + + /** + * Surrounds byte array with Action header + * + * @param data Byte array + * @param version SWF version + * @return Byte array + */ + private byte[] surroundWithAction(byte[] data, int version) { + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, version); + try { + sos2.writeUI8(actionCode); + if (actionCode >= 0x80) { + sos2.writeUI16(data.length); + } + sos2.write(data); + sos2.close(); + } catch (IOException e) { + throw new Error("This should never happen.", e); + } + return baos2.toByteArray(); + } + + @Override + public long getFileOffset() { + return fileOffset; + } + + /** + * Converts list of Actions to bytes + * + * @param list List of actions + * @param addZero Whether or not to add 0 UI8 value to the end + * @param version SWF version + * @return Array of bytes + */ + public static byte[] actionsToBytes(List list, boolean addZero, int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Action lastAction = null; + for (Action a : list) { + try { + lastAction = a; + baos.write(a.getBytes(version)); + } catch (IOException e) { + } + } + if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { + baos.write(0); + } + return baos.toByteArray(); + } + + public static ByteArrayRange actionsToByteArrayRange(List list, boolean addZero, int version) { + byte[] bytes = Action.actionsToBytes(list, addZero, version); + return new ByteArrayRange(bytes); + } + + public static void setConstantPools(ASMSource src, List> constantPools, boolean tryInline) throws ConstantPoolTooBigException { + try { + ActionList actions = src.getActions(); + int poolIdx = 0; + for (Action action : actions) { + if (action instanceof ActionConstantPool) { + ActionConstantPool cPool = (ActionConstantPool) action; + List constantPool = constantPools.get(poolIdx); + + int size = ActionConstantPool.calculateSize(constantPool); + if (size > 0xffff && tryInline) { + for (int i = 0; i < constantPool.size(); i++) { + int refCount = actions.getConstantPoolIndexReferenceCount(i); + if (refCount == 1) { + actions.inlineConstantPoolString(i, constantPool.get(i)); + constantPool.set(i, ""); + } + } + + size = ActionConstantPool.calculateSize(constantPool); + } + + if (size > 0xffff) { + throw new ConstantPoolTooBigException(poolIdx, size); + } + + cPool.constantPool = constantPool; + + poolIdx++; + if (constantPools.size() <= poolIdx) { + break; + } + } + } + + actions.removeNonReferencedConstantPoolItems(); + src.setActions(actions); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + /** + * Set addresses of actions in the list + * + * @param list List of actions + * @param baseAddress Address of first action in the list + */ + public static void setActionsAddresses(List list, long baseAddress) { + long offset = baseAddress; + for (Action a : list) { + a.setAddress(offset); + offset += a.getTotalActionLength(); + } + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @return source ASM + * + */ + public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToString(listeners, address, list, version, exportMode, writer); + return writer.toString(); + } + + private static void informListeners(List listeners, int pos, int count) { + if (pos % INFORM_LISTENER_RESOLUTION == 0) { + DisassemblyListener[] listenersArray = listeners.toArray(new DisassemblyListener[listeners.size()]); + for (DisassemblyListener listener : listenersArray) { + listener.progressToString(pos + 1, count); + } + } + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @param writer + * @return GraphTextWriter + */ + public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + if (exportMode == ScriptExportMode.CONSTANTS) { + return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); + } + + long offset; + Set importantOffsets = getActionsAllRefs(list); + /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); + if (!cps.isEmpty()) { + setConstantPool(list, cps.get(cps.size() - 1)); + }*/ + HashMap> containers = new HashMap<>(); + HashMap containersPos = new HashMap<>(); + offset = address; + int pos = 0; + boolean lastPush = false; + byte[] fileData = list.fileData; + for (Action a : list) { + informListeners(listeners, pos, list.size()); + + if (exportMode == ScriptExportMode.PCODE_HEX) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("; "); + long fileOffset = a.getFileOffset(); + if (Configuration.showFileOffsetInPcodeHex.get()) { + writer.appendNoHilight("@"); + writer.appendNoHilight(Helper.formatHex(fileOffset, 8)); + writer.appendNoHilight(" "); + } + + byte[] bytes = a.getBytes(version); + writer.appendNoHilight(Helper.bytesToHexString(bytes)); + + if (Configuration.showOriginalBytesInPcodeHex.get()) { + if (fileData != null && fileOffset != -1 && fileData.length > fileOffset + bytes.length - 1) { + boolean same = true; + for (int i = 0; i < bytes.length; i++) { + byte b = fileData[(int) (fileOffset + i)]; + if (b != bytes[i]) { + same = false; + break; + } + } + + if (!same) { + writer.appendNoHilight(" ("); + for (int i = 0; i < bytes.length; i++) { + if (i != 0) { + writer.appendNoHilight(" "); + } + + writer.appendNoHilight(Helper.byteToHex(fileData[(int) (fileOffset + i)])); + } + + writer.appendNoHilight(")"); + } + + } + } + + writer.newLine(); + } + + offset = a.getAddress(); + + if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + containersPos.put(cnt, 0); + List sizes = cnt.getContainerSizes(); + long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); + for (Long size : sizes) { + addr += size; + if (size == 0) { + continue; + } + if (!containers.containsKey(addr)) { + containers.put(addr, new ArrayList<>()); + } + containers.get(addr).add(cnt); + } + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("}").newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + } + + if (a.isIgnored()) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + if (!(a instanceof ActionEnd)) { + int len = a.getTotalActionLength(); + for (int i = 0; i < len; i++) { + writer.appendNoHilight("Nop").newLine(); + } + } + } else { + //if (!(a instanceof ActionNop)) { + String add = ""; + // honfika: commented out the following lines, because it makes no sense + /*if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + add = "; ofs" + Helper.formatAddress(offset) + add; + add = "";*/ + if ((a instanceof ActionPush) && lastPush) { + writer.appendNoHilight(" "); + ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); + } else { + if (lastPush) { + writer.newLine(); + //lastPush = false; + } + + writer.append("", offset, a.getFileOffset()); + + int fixBranch = -1; + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + if (aif.jumpUsed && !aif.ignoreUsed) { + fixBranch = 0; + } + if (!aif.jumpUsed && aif.ignoreUsed) { + fixBranch = 1; + } + } + + if (fixBranch > -1) { + writer.appendNoHilight("FFDec_DeobfuscatePop"); + if (fixBranch == 0) { //jump + writer.newLine(); + writer.appendNoHilight("Jump loc"); + writer.appendNoHilight(Helper.formatAddress(((ActionIf) a).getTargetAddress())); + } else { + //nojump, ignore + } + } else { + a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); + } + writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); + writer.appendNoHilight(add); + if (!(a instanceof ActionPush)) { + writer.newLine(); + } + } + lastPush = a instanceof ActionPush; + //} + } + + offset += a.getTotalActionLength(); + pos++; + } + if (lastPush) { + writer.newLine(); + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + writer.appendNoHilight("}"); + writer.newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (importantOffsets.contains(offset)) { + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + writer.newLine(); + } + + return writer; + } + + public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + int poolIdx = 0; + writer.appendNoHilight(Helper.constants).newLine(); + for (Action a : list) { + if (a instanceof ActionConstantPool) { + if (poolIdx > 0) { + writer.appendNoHilight("---").newLine(); + } + + ActionConstantPool cPool = (ActionConstantPool) a; + int constIdx = 0; + for (String c : cPool.constantPool) { + writer.appendNoHilight(constIdx); + writer.appendNoHilight("|"); + writer.appendNoHilight(Helper.escapeString(c)); + writer.newLine(); + constIdx++; + } + + poolIdx++; + } + } + + return writer; + } + + /** + * Convert action to ASM source + * + * @param container + * @param knownAddreses List of important offsets to mark as labels + * @param exportMode PCode or hex? + * @return String of P-code source + */ + public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { + return toString(); + } + + public abstract boolean execute(LocalDataArea lda); + + /* { + //throw new UnsupportedOperationException("Action " + toString() + " not implemented"); + return false; + }*/ + /** + * Translates this function to stack and output. + * + * @param lineStartIns Line start instruction + * @param stack Stack + * @param output Output + * @param regNames Register names + * @param variables Variables + * @param functions Functions + * @param staticOperation the value of staticOperation + * @param path the value of path + * @throws java.lang.InterruptedException + */ + public void translate(GraphSourceItem lineStartIns, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { + } + + @Override + public int getStackPopCount(BaseLocalData localData, TranslateStack stack) { + return 0; + } + + @Override + public int getStackPushCount(BaseLocalData localData, TranslateStack stack) { + return 0; + } + + /** + * Pops long value off the stack + * + * @param stack Stack + * @return long value + */ + protected long popLong(TranslateStack stack) { + GraphTargetItem item = stack.pop(); + if (item instanceof DirectValueActionItem) { + return (long) (double) EcmaScript.toNumberAs2(((DirectValueActionItem) item).value); + } + + return 0; + } + + /** + * Converts action index to address in the specified list of actions + * + * @param actions List of actions + * @param ip Action index + * @return address + */ + public static long ip2adr(List actions, int ip) { + /* List actions=new ArrayList(); + for(GraphSourceItem s:sources){ + if(s instanceof Action){ + actions.add((Action)s); + } + }*/ + if (ip >= actions.size()) { + if (actions.isEmpty()) { + return 0; + } + return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + } + if (ip == -1) { + return 0; + } + return actions.get(ip).getAddress(); + } + + /** + * Converts address to action index in the specified list of actions + * + * @param actions List of actions + * @param addr Address + * @return action index + */ + public static int adr2ip(List actions, long addr) { + for (int ip = 0; ip < actions.size(); ip++) { + if (actions.get(ip).getAddress() == addr) { + return ip; + } + } + if (actions.size() > 0) { + long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + if (addr == outpos) { + return actions.size(); + } + } + return -1; + } + + public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { + return actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @return source + * @throws java.lang.InterruptedException + */ + public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToSource(asm, actions, path, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @param writer + * @throws java.lang.InterruptedException + */ + public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { + writer.suspendMeasure(); + List tree = null; + Throwable convertException = null; + int timeout = Configuration.decompilationTimeoutSingleMethod.get(); + final SWF swf = asm == null ? null : asm.getSwf(); + final int version = swf == null ? SWF.DEFAULT_VERSION : swf.version; + try { + tree = CancellableWorker.call(new Callable>() { + @Override + public List call() throws Exception { + int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; + List tree = actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path); + SWFDecompilerPlugin.fireActionTreeCreated(tree, swf); + if (Configuration.autoDeobfuscate.get()) { + new ActionDeobfuscator().actionTreeCreated(tree, swf); + } + + Graph.graphToString(tree, new NulWriter(), new LocalData()); + return tree; + } + }, timeout, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + throw ex; + } catch (Exception | OutOfMemoryError | StackOverflowError ex) { + + convertException = ex; + Throwable cause = ex.getCause(); + if (ex instanceof ExecutionException && cause instanceof Exception) { + convertException = cause; + } + if (convertException instanceof TimeoutException) { + logger.log(Level.SEVERE, "Decompilation timeout in: " + path, convertException); + } else { + logger.log(Level.SEVERE, "Decompilation error in: " + path, convertException); + } + + } + writer.continueMeasure(); + + if (asm != null) { + asm.getActionSourcePrefix(writer); + } + if (convertException == null) { + Graph.graphToString(tree, writer, new LocalData()); + } else if (convertException instanceof TimeoutException) { + Helper.appendTimeoutCommentAs2(writer, timeout, actions.size()); + } else { + Helper.appendErrorComment(writer, convertException); + } + if (asm != null) { + asm.getActionSourceSuffix(writer); + } + } + + /** + * Converts list of actions to List of treeItems + * + * @param regNames Register names + * @param variables + * @param functions + * @param actions List of actions + * @param version SWF version + * @param staticOperation + * @param path + * @return List of treeItems + * @throws java.lang.InterruptedException + */ + public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { + return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); + } + + @Override + public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { + ActionLocalData aLocalData = (ActionLocalData) localData; + /*int expectedSize = stack.size() - getStackPopCount(localData, stack); + if (expectedSize < 0) { + expectedSize = 0; + } + expectedSize += getStackPushCount(localData, stack);*/ + + translate(aLocalData.lineStartAction, stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); + /*if (stack.size() != expectedSize && !(this instanceof ActionPushDuplicate)) { + throw new Error("HONFIKA stack size mismatch"); + }*/ + } + + @Override + public boolean isJump() { + return false; + } + + @Override + public boolean isBranch() { + return false; + } + + @Override + public boolean isExit() { + return false; + } + + @Override + public List getBranches(GraphSource code) { + return new ArrayList<>(); + } + + @Override + public boolean isIgnored() { + return ignored; + } + + @Override + public void setIgnored(boolean ignored, int pos) { + this.ignored = ignored; + } + + public static List actionsPartToTree(Reference fi, HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { + if (start < actions.size() && (end > 0) && (start > 0)) { + logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""}); + } + ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); + localData.lineStartAction = fi.getVal(); + List output = new ArrayList<>(); + int ip = start; + boolean isWhile = false; + boolean isForIn = false; + GraphTargetItem inItem = null; + int loopStart = 0; + loopip: + while (ip <= end) { + + long addr = ip2adr(actions, ip); + if (ip > end) { + break; + } + if (ip >= actions.size()) { + output.add(new ScriptEndItem()); + break; + } + if (Configuration.simplifyExpressions.get()) { + stack.simplify(); + } + Action action = actions.get(ip); + if (action.isIgnored()) { + ip++; + continue; + } + + //FunctionActionItem after DefineFunction(/2) are left on the stack. For linestart offsets we consider this kind of stack empty. + boolean isStackEmpty = true; + for (int i = 0; i < stack.size(); i++) { + if ((!(stack.get(i) instanceof FunctionActionItem))) { + isStackEmpty = false; + break; + } + } + + if (isStackEmpty) { + localData.lineStartAction = action; + fi.setVal(action); + } + if (action instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; + //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); + long endAddr = action.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> outs = new ArrayList<>(); + HashMap variables2 = Helper.deepCopy(variables); + if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { + for (int r = 0; r < 256; r++) { + if (variables2.containsKey("__register" + r)) { + variables2.remove("__register" + r); + } + } + } + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + outs.add(new ArrayList<>()); + continue; + } + List out; + try { + HashMap regNames = cnt.getRegNames(); + if (action instanceof ActionWith || action instanceof ActionTry) { + for (Map.Entry e : registerNames.entrySet()) { + if (!regNames.containsKey(e.getKey())) { + regNames.put(e.getKey(), e.getValue()); + } + } + } + out = ActionGraph.translateViaGraph(regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); + } catch (OutOfMemoryError | TranslateException | StackOverflowError ex) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); + if (ex instanceof OutOfMemoryError) { + Helper.freeMem(); + } + + out = new ArrayList<>(); + out.add(new CommentItem(new String[]{ + "", + " * " + AppResources.translate("decompilationError"), + " * " + AppResources.translate("decompilationError.obfuscated"), + Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, + " * " + AppResources.translate("decompilationError.errorType") + ": " + + ex.getClass().getSimpleName(), + ""})); + } + outs.add(out); + endAddr += size; + } + + ((GraphSourceItemContainer) action).translateContainer(outs, action, stack, output, registerNames, variables, functions); + ip = adr2ip(actions, endAddr); + continue; + } + + //return in for..in + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) == Null.INSTANCE)) { + if (ip + 3 <= end) { + if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { + if (actions.get(ip + 2) instanceof ActionNot) { + if (actions.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) actions.get(ip + 3); + if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + continue; + } + } + } + } + } + } + + /*ActionJump && ActionIf removed*/ + /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { + loopStart = ip + 1; + isForIn = true; + ip += 4; + action.translate(localData, stack, output); + EnumerateActionItem en = (EnumerateActionItem) stack.peek(); + inItem = en.object; + continue; + } else*/ /*if (action instanceof ActionTry) { + ActionTry atry = (ActionTry) action; + List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); + ActionItem catchName; + if (atry.catchInRegisterFlag) { + catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList<>()); + } else { + catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList<>()); + } + List catchExceptions = new ArrayList(); + catchExceptions.add(catchName); + List> catchCommands = new ArrayList>(); + catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); + List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); + output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); + } else if (action instanceof ActionWith) { + ActionWith awith = (ActionWith) action; + List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions + output.add(new WithActionItem(action, stack.pop(), withCommands)); + } else */ if (false) { + } /*if (action instanceof ActionStoreRegister) { + if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { + action.translate(localData, stack, output); + stack.pop(); + ip++; + } else { + try { + action.translate(localData, stack, output); + } catch (Exception ex) { + // ignore + } + } + } */ /*else if (action instanceof ActionStrictEquals) { + if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { + List caseValues = new ArrayList(); + List> caseCommands = new ArrayList>(); + caseValues.add(stack.pop()); + ActionItem switchedObject = stack.pop(); + if (output.size() > 0) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + output.remove(output.size() - 1); + } + } + int caseStart = ip + 2; + List caseBodyIps = new ArrayList(); + long defaultAddr = 0; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); + ip++; + do { + ip++; + if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { + caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); + caseStart = ip + 1; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); + if (actions.get(ip + 1) instanceof ActionJump) { + defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); + ip = adr2ip(actions, defaultAddr, version); + break; + } + } + } while (ip < end); + + for (int i = 0; i < caseBodyIps.size(); i++) { + int caseEnd = ip - 1; + if (i < caseBodyIps.size() - 1) { + caseEnd = caseBodyIps.get(i + 1) - 1; + } + caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); + } + output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); + continue; + } else { + action.translate(stack, constants, output, registerNames); + } + } */ else { + + if (action instanceof ActionStore) { + ActionStore store = (ActionStore) action; + store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); + ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; + } + + action.translate(localData, stack, output, staticOperation, path); + } + + ip++; + } + //output = checkClass(output); + logger.log(Level.FINE, "Leaving {0}-{1}", new Object[]{start, end}); + return output; + } + + public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { + GraphTargetItem t = ti; + if (!(t instanceof GetMemberActionItem)) { + return ti; + } + GetMemberActionItem lastMember = null; + while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { + lastMember = (GetMemberActionItem) t; + t = ((GetMemberActionItem) t).object; + } + if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { + GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; + if (v.name instanceof DirectValueActionItem) { + if (((DirectValueActionItem) v.name).value instanceof String) { + if (((DirectValueActionItem) v.name).value.equals("_global")) { + GetVariableActionItem gvt = new GetVariableActionItem(null, null, ((GetMemberActionItem) t).memberName); + if (lastMember == null) { + return gvt; + } else { + lastMember.object = gvt; + } + } + } + } + } + return ti; + } + + public static List checkClass(List output) { + if (true) { + //return output; + } + List ret = new ArrayList<>(); + List functions = new ArrayList<>(); + List staticFunctions = new ArrayList<>(); + List> vars = new ArrayList<>(); + List> staticVars = new ArrayList<>(); + GraphTargetItem className; + GraphTargetItem extendsOp = null; + List implementsOp = new ArrayList<>(); + boolean ok = true; + int prevCount = 0; + for (GraphTargetItem t : output) { + if (t instanceof IfItem) { + IfItem it = (IfItem) t; + if (it.expression instanceof NotItem) { + NotItem nti = (NotItem) it.expression; + if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { + if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { + if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { + // ignore + } else { + List parts = it.onTrue; + className = getWithoutGlobal(nti.value); + if (parts.size() >= 1) { + int ipos = 0; + + while ((parts.get(ipos) instanceof PopItem) || ((parts.get(ipos) instanceof IfItem) && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem)))) { + ipos++; + } + if (parts.get(ipos) instanceof ExtendsActionItem) { + ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); + extendsOp = getWithoutGlobal(et.superclass); + ipos++; + } + if (parts.get(ipos) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); + int instanceReg = sr.register.number; + if (sr.value instanceof GetMemberActionItem) { + GetMemberActionItem gm = (GetMemberActionItem) sr.value; + //gm.memberName should be "prototype" + if (gm.object instanceof TemporaryRegister) { + TemporaryRegister tm = (TemporaryRegister) gm.object; + int classReg = tm.getRegId(); + if (tm.value instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) tm.value; + if (sm.value instanceof StoreRegisterActionItem) { + sr = (StoreRegisterActionItem) sm.value; + if (sr.value instanceof FunctionActionItem) { + ((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; + functions.add((FunctionActionItem) sr.value); + + for (; ipos < parts.size(); ipos++) { + if (parts.get(ipos) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); + implementsOp = io.superclasses; + continue; + } + if (parts.get(ipos) instanceof SetMemberActionItem) { + sm = (SetMemberActionItem) parts.get(ipos); + int rnum = -1; + if (sm.object instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) sm.object; + if (dv.value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) dv.value; + rnum = rn.number; + } + } + if (sm.object instanceof TemporaryRegister) { + rnum = ((TemporaryRegister) sm.object).getRegId(); + } + if (rnum == instanceReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + functions.add((FunctionActionItem) sm.value); + } else { + vars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } else if (rnum == classReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + staticFunctions.add((FunctionActionItem) sm.value); + } else { + staticVars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } + + } + } + + } + + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); + return output2; + } + } + } else if (parts.get(ipos) instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); + if (sm.value instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) sm.value; + if (f.actions.isEmpty()) { + if (parts.size() == 2) { + if (parts.get(1) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); + implementsOp = iot.superclasses; + } else { + //ok = false; + break; + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); + return output2; + } + } + } + } + } + } else { + //ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + } else if (!(t instanceof PopItem)) { + prevCount++; + //ok = false; + } + if (!ok) { + break; + } + } + return output; + } + + @Override + public boolean ignoredLoops() { + return false; + } + + public static void setConstantPool(List actions, ConstantPool cpool) { + for (GraphSourceItem a : actions) { + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + if (a instanceof ActionDefineFunction) { + if (cpool != null) { + //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); + } + } + if (a instanceof ActionDefineFunction2) { + if (cpool != null) { + //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); + } + } + } + } + + public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { + writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); + return writer; + } + + public static double toFloatPoint(Object o) { + if (o instanceof Double) { + return (Double) o; + } + if (o instanceof Integer) { + return (Integer) o; + } + if (o instanceof Long) { + return (Long) o; + } + if (o == Null.INSTANCE) { + return Double.NaN; + } + if (o == Undefined.INSTANCE) { + return Double.NaN; + } + if (o instanceof Boolean) { + return (Boolean) o ? 1.0 : 0.0; + } + if (o instanceof String) { + try { + return Double.parseDouble((String) o); + } catch (NumberFormatException nfe) { + return Double.NaN; + } + } + return 0; + } + + public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { + GraphTargetItem ret = get; + boolean boxed = false; + if (get instanceof VariableActionItem) { + boxed = true; + ret = ((VariableActionItem) ret).getBoxedValue(); + } + if (ret instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) ret; + ret = new SetVariableActionItem(null, null, gv.name, value); + } else if (ret instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) ret; + ret = new SetMemberActionItem(null, null, mem.object, mem.memberName, value); + } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { + ret = new StoreRegisterActionItem(null, null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); + } else if (ret instanceof GetPropertyActionItem) { + GetPropertyActionItem gp = (GetPropertyActionItem) ret; + ret = new SetPropertyActionItem(null, null, gp.target, gp.propertyIndex, value); + } + if (boxed) { + GraphTargetItem b = ret; + ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); + ((VariableActionItem) ret).setBoxedValue((ActionItem) b); + variables.remove((VariableActionItem) get); + variables.add((VariableActionItem) ret); + } + return ret; + } + + @Override + public boolean isDeobfuscatePop() { + return false; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public String getFile() { + return null; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java index 7b9ed41aa..f2bfa8360 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java @@ -1,93 +1,93 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action; - -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Stack; - -/** - * - * @author JPEXS - */ -public class LocalDataArea { - - public List constantPool; - - public Stack stack = new Stack<>(); - - public List functions = new ArrayList<>(); - - public Map localVariables = new HashMap<>(); - - public List withs = new ArrayList<>(); - - public Map localRegisters = new HashMap<>(); - - public Object target; - - public Stage stage; - - public Long jump; - - public Object returnValue; - - public String executionException; - - public LocalDataArea(Stage stage) { - this.stage = stage; - this.target = this.stage; - } - - public LocalDataArea(Stage stage, boolean preserveVariableOrder) { - this.stage = stage; - target = this.stage; - if (preserveVariableOrder) { - localVariables = new LinkedHashMap<>(); - } - } - - public void clear() { - constantPool = null; - stack.clear(); - localVariables.clear(); - localRegisters.clear(); - withs.clear(); - functions.clear(); - stage.clear(); - jump = null; - returnValue = null; - executionException = null; - target = stage; - } - - public Object pop() { - return stack.pop(); - } - - public Double popAsNumber() { - return EcmaScript.toNumberAs2(stack.pop()); - } - - public String popAsString() { - return EcmaScript.toString(stack.pop()); - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +/** + * + * @author JPEXS + */ +public class LocalDataArea { + + public List constantPool; + + public Stack stack = new Stack<>(); + + public List functions = new ArrayList<>(); + + public Map localVariables = new HashMap<>(); + + public List withs = new ArrayList<>(); + + public Map localRegisters = new HashMap<>(); + + public Object target; + + public Stage stage; + + public Long jump; + + public Object returnValue; + + public String executionException; + + public LocalDataArea(Stage stage) { + this.stage = stage; + this.target = this.stage; + } + + public LocalDataArea(Stage stage, boolean preserveVariableOrder) { + this.stage = stage; + target = this.stage; + if (preserveVariableOrder) { + localVariables = new LinkedHashMap<>(); + } + } + + public void clear() { + constantPool = null; + stack.clear(); + localVariables.clear(); + localRegisters.clear(); + withs.clear(); + functions.clear(); + stage.clear(); + jump = null; + returnValue = null; + executionException = null; + target = stage; + } + + public Object pop() { + return stack.pop(); + } + + public Double popAsNumber() { + return EcmaScript.toNumberAs2(stack.pop()); + } + + public String popAsString() { + return EcmaScript.toString(stack.pop()); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/ActionUnknown.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/ActionUnknown.java index 1b079ceb9..0273d1aee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/ActionUnknown.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/ActionUnknown.java @@ -1,51 +1,51 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.special; - -import com.jpexs.decompiler.flash.action.LocalDataArea; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.helpers.Helper; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ActionUnknown extends ActionNop { - - public ActionUnknown(int actionCode, int actionLength) { - super(actionCode); - this.actionLength = actionLength; - } - - @Override - public String toString() { - return "Unknown_" + Helper.byteToHex((byte) getActionCode()); - } - - @Override - public boolean execute(LocalDataArea lda) { - return true; - } - - @Override - public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.special; + +import com.jpexs.decompiler.flash.action.LocalDataArea; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.helpers.Helper; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionUnknown extends ActionNop { + + public ActionUnknown(int actionCode, int actionLength) { + super(actionCode); + this.actionLength = actionLength; + } + + @Override + public String toString() { + return "Unknown_" + Helper.byteToHex((byte) getActionCode()); + } + + @Override + public boolean execute(LocalDataArea lda) { + return true; + } + + @Override + public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index 0ead00e93..c23795331 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -1,455 +1,455 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.action.swf4; - -import com.jpexs.decompiler.flash.BaseLocalData; -import com.jpexs.decompiler.flash.EndOfStreamException; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.LocalDataArea; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.TemporaryRegister; -import com.jpexs.decompiler.flash.action.parser.ActionParseException; -import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; -import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.dumpview.DumpInfo; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.ecma.Undefined; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.FalseItem; -import com.jpexs.decompiler.graph.model.TrueItem; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Set; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 4) -public class ActionPush extends Action { - - public List values; - - public List replacement; - - public List constantPool; - - public ActionPush(int actionLength, SWFInputStream sis, int version) throws IOException { - super(0x96, actionLength); - int type; - values = new ArrayList<>(); - DumpInfo di = sis.dumpInfo; - sis = sis.getLimitedStream(actionLength); - sis.dumpInfo = di; - try { - while (sis.available() > 0) { - type = sis.readUI8("type"); - switch (type) { - case 0: - values.add(sis.readString("string")); - break; - case 1: - values.add(sis.readFLOAT("float")); - break; - case 2: - values.add(Null.INSTANCE); - break; - case 3: - values.add(Undefined.INSTANCE); - break; - case 4: - values.add(new RegisterNumber(sis.readUI8("registerNumber"))); - break; - case 5: - int b = sis.readUI8("boolean"); - if (b == 0) { - values.add((Boolean) false); - } else { - values.add((Boolean) true); - } - - break; - case 6: - values.add(sis.readDOUBLE("double")); - break; - case 7: - long el = sis.readSI32("integer"); - values.add((Long) el); - break; - case 8: - values.add(new ConstantIndex(sis.readUI8("constantIndex"))); - break; - case 9: - values.add(new ConstantIndex(sis.readUI16("constantIndex"))); - break; - } - } - } catch (EndOfStreamException ex) { - } - } - - @Override - protected void getContentBytes(SWFOutputStream sos) throws IOException { - for (Object o : values) { - if (o instanceof String) { - sos.writeUI8(0); - sos.writeString((String) o); - } else if (o instanceof Float) { - sos.writeUI8(1); - sos.writeFLOAT((Float) o); - } else if (o == Null.INSTANCE) { - sos.writeUI8(2); - } else if (o == Undefined.INSTANCE) { - sos.writeUI8(3); - } else if (o instanceof RegisterNumber) { - sos.writeUI8(4); - sos.writeUI8(((RegisterNumber) o).number); - } else if (o instanceof Boolean) { - sos.writeUI8(5); - sos.writeUI8((Boolean) o ? 1 : 0); - } else if (o instanceof Number) { - if (o instanceof Long) { - long l = (Long) o; - if (l < -0x80000000 || l > 0x7fffffff) { - o = (double) l; - } - } - if (o instanceof Double || o instanceof Float) { - sos.writeUI8(6); - sos.writeDOUBLE(((Number) o).doubleValue()); - } else if (o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte) { - sos.writeUI8(7); - sos.writeSI32(((Number) o).longValue()); - } - } else if (o instanceof ConstantIndex) { - int cIndex = ((ConstantIndex) o).index; - if (cIndex < 256) { - sos.writeUI8(8); - sos.writeUI8(cIndex); - } else { - sos.writeUI8(9); - sos.writeUI16(cIndex); - } - } - } - } - - /** - * Gets the length of action converted to bytes - * - * @return Length - */ - @Override - protected int getContentBytesLength() { - int res = 0; - for (Object o : values) { - if (o instanceof String) { - res += Utf8Helper.getBytesLength((String) o) + 2; - } else if (o instanceof Float) { - res += 5; - } else if (o == Null.INSTANCE) { - res++; - } else if (o == Undefined.INSTANCE) { - res++; - } else if (o instanceof RegisterNumber) { - res += 2; - } else if (o instanceof Boolean) { - res += 2; - } else if (o instanceof Number) { - if (o instanceof Long) { - long l = (Long) o; - if (l < -0x80000000 || l > 0x7fffffff) { - o = (double) l; - } - } - if (o instanceof Double || o instanceof Float) { - res += 9; - } else if (o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte) { - res += 5; - } - } else if (o instanceof ConstantIndex) { - int cIndex = ((ConstantIndex) o).index; - if (cIndex < 256) { - res += 2; - } else { - res += 3; - } - } - } - - return res; - } - - public static boolean isValidValue(Object value) { - if (value instanceof String) { - for (char ch : ((String) value).toCharArray()) { - if (ch == 0) { - return false; - } - } - } - if (value instanceof Long) { - long l = (Long) value; - if (l < -0x80000000 || l > 0x7fffffff) { - return false; - } - } - return true; - } - - public ActionPush(Object value) { - super(0x96, 0); - this.values = new ArrayList<>(); - this.values.add(value); - updateLength(); - } - - public ActionPush(Object[] values) { - super(0x96, 0); - this.values = new ArrayList<>(); - this.values.addAll(Arrays.asList(values)); - updateLength(); - } - - public ActionPush(FlasmLexer lexer, List constantPool) throws IOException, ActionParseException { - super(0x96, 0); - this.constantPool = constantPool; - values = new ArrayList<>(); - int count = 0; - loop: - while (true) { - ASMParsedSymbol symb = lexer.yylex(); - switch (symb.type) { - case ASMParsedSymbol.TYPE_STRING: - count++; - if (constantPool.contains((String) symb.value)) { - values.add(new ConstantIndex(constantPool.indexOf(symb.value))); - } else { - values.add(symb.value); - } - break; - case ASMParsedSymbol.TYPE_FLOAT: - case ASMParsedSymbol.TYPE_NULL: - case ASMParsedSymbol.TYPE_UNDEFINED: - case ASMParsedSymbol.TYPE_REGISTER: - case ASMParsedSymbol.TYPE_BOOLEAN: - case ASMParsedSymbol.TYPE_INTEGER: - case ASMParsedSymbol.TYPE_CONSTANT: - count++; - values.add(symb.value); - break; - case ASMParsedSymbol.TYPE_EOL: - case ASMParsedSymbol.TYPE_EOF: - if (count == 0) { - throw new ActionParseException("Arguments expected", lexer.yyline()); - } else { - break loop; - } - case ASMParsedSymbol.TYPE_COMMENT: - break; - default: - throw new ActionParseException("Arguments expected, " + symb.type + " " + symb.value + " found", lexer.yyline()); - } - } - } - - @Override - public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { - if (replacement == null || replacement.size() < values.size()) { - return toString(writer); - } - List oldVal = values; - values = replacement; - toString(writer); - values = oldVal; - return writer; - } - - public GraphTextWriter paramsToStringReplaced(List container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { - if (replacement == null || replacement.size() < values.size()) { - return paramsToString(writer); - } - List oldVal = values; - values = replacement; - paramsToString(writer); - values = oldVal; - return writer; - } - - public String toStringNoQ(int i) { - String ret; - Object value = values.get(i); - if (value instanceof ConstantIndex) { - ret = ((ConstantIndex) value).toStringNoQ(constantPool, Configuration.resolveConstants.get()); - } else if (value instanceof String) { - ret = (String) value; - } else if (value instanceof RegisterNumber) { - ret = ((RegisterNumber) value).toStringNoName(); - } else { - ret = value.toString(); - } - return ret; - } - - public String toString(int i) { - String ret; - Object value = values.get(i); - if (value instanceof ConstantIndex) { - ret = ((ConstantIndex) value).toString(constantPool, Configuration.resolveConstants.get()); - } else if (value instanceof String) { - ret = "\"" + Helper.escapeActionScriptString((String) value) + "\""; - } else if (value instanceof RegisterNumber) { - ret = ((RegisterNumber) value).toStringNoName(); - } else { - ret = value.toString(); - } - return ret; - } - - public GraphTextWriter paramsToString(GraphTextWriter writer) { - int pos = 0; - for (int i = 0; i < values.size(); i++) { - if (pos > 0) { - writer.appendNoHilight(" "); - } - writer.append(toString(i), getAddress() + pos + 1, getFileOffset()); - pos++; - } - return writer; - } - - @Override - public String toString() { - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - toString(writer); - return writer.toString(); - } - - public GraphTextWriter toString(GraphTextWriter writer) { - writer.appendNoHilight("Push "); - paramsToString(writer); - return writer; - } - - @Override - public boolean execute(LocalDataArea lda) { - for (Object value : values) { - if (value instanceof ConstantIndex) { - ConstantIndex constantIndex = (ConstantIndex) value; - List cPool = lda.constantPool != null ? lda.constantPool : constantPool; - lda.stack.push(constantIndex.toStringNoQ(cPool, true)); - } else if (value instanceof RegisterNumber) { - int rn = ((RegisterNumber) value).number; - if (lda.localRegisters.containsKey(rn)) { - lda.stack.push(lda.localRegisters.get(rn)); - } else { - lda.stack.push(Undefined.INSTANCE); - } - } else { - lda.stack.push(value); - } - } - - return true; - } - - @Override - public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - int pos = 0; - for (Object o : values) { - if (o instanceof ConstantIndex) { - if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) { - o = "\u00A7\u00A7constant" + ((ConstantIndex) o).index; - } else { - o = constantPool.get(((ConstantIndex) o).index); - } - } - /*if (o instanceof RegisterNumber) { - if (regNames.containsKey(((RegisterNumber) o).number)) { - ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); - } else if (output.size() >= 2) { //chained assignments:, ignore for class prototype assignment - GraphTargetItem last = output.get(output.size() - 1); - GraphTargetItem prev = output.get(output.size() - 2); - if (last instanceof SetTypeActionItem) { - if (prev instanceof StoreRegisterActionItem) { - StoreRegisterActionItem str = (StoreRegisterActionItem) prev; - if (str.register.number == ((RegisterNumber) o).number) { - SetTypeActionItem stt = (SetTypeActionItem) last; - stt.setTempRegister(((RegisterNumber) o).number); - if ((stt.getValue() instanceof IncrementActionItem) && (((IncrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { - stack.push(new PreIncrementActionItem(this, lineStartAction, stt.getObject())); - } else if ((stt.getValue() instanceof DecrementActionItem) && (((DecrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { - stack.push(new PreDecrementActionItem(this, lineStartAction, stt.getObject())); - } else { - //stack.push(last); - continue; - } - output.remove(output.size() - 1); - output.remove(output.size() - 1); - pos++; - continue; - } - } - } - } - }*/ - if (o instanceof Boolean) { - Boolean b = (Boolean) o; - if (b) { - stack.push(new TrueItem(this, lineStartAction)); - } else { - stack.push(new FalseItem(this, lineStartAction)); - } - } else { - DirectValueActionItem dvt = new DirectValueActionItem(this, lineStartAction, pos, o, constantPool); - - if (o instanceof RegisterNumber) {//TemporaryRegister - dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); - if (regNames.containsKey(((RegisterNumber) o).number)) { - ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); - } - } - if (dvt.computedRegValue instanceof TemporaryRegister) { - stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); - } else { - stack.push(dvt); - } - } - pos++; - } - } - - @Override - public int getStackPushCount(BaseLocalData localData, TranslateStack stack) { - return values.size(); - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action.swf4; + +import com.jpexs.decompiler.flash.BaseLocalData; +import com.jpexs.decompiler.flash.EndOfStreamException; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.LocalDataArea; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.TemporaryRegister; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.dumpview.DumpInfo; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.FalseItem; +import com.jpexs.decompiler.graph.model.TrueItem; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 4) +public class ActionPush extends Action { + + public List values; + + public List replacement; + + public List constantPool; + + public ActionPush(int actionLength, SWFInputStream sis, int version) throws IOException { + super(0x96, actionLength); + int type; + values = new ArrayList<>(); + DumpInfo di = sis.dumpInfo; + sis = sis.getLimitedStream(actionLength); + sis.dumpInfo = di; + try { + while (sis.available() > 0) { + type = sis.readUI8("type"); + switch (type) { + case 0: + values.add(sis.readString("string")); + break; + case 1: + values.add(sis.readFLOAT("float")); + break; + case 2: + values.add(Null.INSTANCE); + break; + case 3: + values.add(Undefined.INSTANCE); + break; + case 4: + values.add(new RegisterNumber(sis.readUI8("registerNumber"))); + break; + case 5: + int b = sis.readUI8("boolean"); + if (b == 0) { + values.add((Boolean) false); + } else { + values.add((Boolean) true); + } + + break; + case 6: + values.add(sis.readDOUBLE("double")); + break; + case 7: + long el = sis.readSI32("integer"); + values.add((Long) el); + break; + case 8: + values.add(new ConstantIndex(sis.readUI8("constantIndex"))); + break; + case 9: + values.add(new ConstantIndex(sis.readUI16("constantIndex"))); + break; + } + } + } catch (EndOfStreamException ex) { + } + } + + @Override + protected void getContentBytes(SWFOutputStream sos) throws IOException { + for (Object o : values) { + if (o instanceof String) { + sos.writeUI8(0); + sos.writeString((String) o); + } else if (o instanceof Float) { + sos.writeUI8(1); + sos.writeFLOAT((Float) o); + } else if (o == Null.INSTANCE) { + sos.writeUI8(2); + } else if (o == Undefined.INSTANCE) { + sos.writeUI8(3); + } else if (o instanceof RegisterNumber) { + sos.writeUI8(4); + sos.writeUI8(((RegisterNumber) o).number); + } else if (o instanceof Boolean) { + sos.writeUI8(5); + sos.writeUI8((Boolean) o ? 1 : 0); + } else if (o instanceof Number) { + if (o instanceof Long) { + long l = (Long) o; + if (l < -0x80000000 || l > 0x7fffffff) { + o = (double) l; + } + } + if (o instanceof Double || o instanceof Float) { + sos.writeUI8(6); + sos.writeDOUBLE(((Number) o).doubleValue()); + } else if (o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte) { + sos.writeUI8(7); + sos.writeSI32(((Number) o).longValue()); + } + } else if (o instanceof ConstantIndex) { + int cIndex = ((ConstantIndex) o).index; + if (cIndex < 256) { + sos.writeUI8(8); + sos.writeUI8(cIndex); + } else { + sos.writeUI8(9); + sos.writeUI16(cIndex); + } + } + } + } + + /** + * Gets the length of action converted to bytes + * + * @return Length + */ + @Override + protected int getContentBytesLength() { + int res = 0; + for (Object o : values) { + if (o instanceof String) { + res += Utf8Helper.getBytesLength((String) o) + 2; + } else if (o instanceof Float) { + res += 5; + } else if (o == Null.INSTANCE) { + res++; + } else if (o == Undefined.INSTANCE) { + res++; + } else if (o instanceof RegisterNumber) { + res += 2; + } else if (o instanceof Boolean) { + res += 2; + } else if (o instanceof Number) { + if (o instanceof Long) { + long l = (Long) o; + if (l < -0x80000000 || l > 0x7fffffff) { + o = (double) l; + } + } + if (o instanceof Double || o instanceof Float) { + res += 9; + } else if (o instanceof Long || o instanceof Integer || o instanceof Short || o instanceof Byte) { + res += 5; + } + } else if (o instanceof ConstantIndex) { + int cIndex = ((ConstantIndex) o).index; + if (cIndex < 256) { + res += 2; + } else { + res += 3; + } + } + } + + return res; + } + + public static boolean isValidValue(Object value) { + if (value instanceof String) { + for (char ch : ((String) value).toCharArray()) { + if (ch == 0) { + return false; + } + } + } + if (value instanceof Long) { + long l = (Long) value; + if (l < -0x80000000 || l > 0x7fffffff) { + return false; + } + } + return true; + } + + public ActionPush(Object value) { + super(0x96, 0); + this.values = new ArrayList<>(); + this.values.add(value); + updateLength(); + } + + public ActionPush(Object[] values) { + super(0x96, 0); + this.values = new ArrayList<>(); + this.values.addAll(Arrays.asList(values)); + updateLength(); + } + + public ActionPush(FlasmLexer lexer, List constantPool) throws IOException, ActionParseException { + super(0x96, 0); + this.constantPool = constantPool; + values = new ArrayList<>(); + int count = 0; + loop: + while (true) { + ASMParsedSymbol symb = lexer.yylex(); + switch (symb.type) { + case ASMParsedSymbol.TYPE_STRING: + count++; + if (constantPool.contains((String) symb.value)) { + values.add(new ConstantIndex(constantPool.indexOf(symb.value))); + } else { + values.add(symb.value); + } + break; + case ASMParsedSymbol.TYPE_FLOAT: + case ASMParsedSymbol.TYPE_NULL: + case ASMParsedSymbol.TYPE_UNDEFINED: + case ASMParsedSymbol.TYPE_REGISTER: + case ASMParsedSymbol.TYPE_BOOLEAN: + case ASMParsedSymbol.TYPE_INTEGER: + case ASMParsedSymbol.TYPE_CONSTANT: + count++; + values.add(symb.value); + break; + case ASMParsedSymbol.TYPE_EOL: + case ASMParsedSymbol.TYPE_EOF: + if (count == 0) { + throw new ActionParseException("Arguments expected", lexer.yyline()); + } else { + break loop; + } + case ASMParsedSymbol.TYPE_COMMENT: + break; + default: + throw new ActionParseException("Arguments expected, " + symb.type + " " + symb.value + " found", lexer.yyline()); + } + } + } + + @Override + public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { + if (replacement == null || replacement.size() < values.size()) { + return toString(writer); + } + List oldVal = values; + values = replacement; + toString(writer); + values = oldVal; + return writer; + } + + public GraphTextWriter paramsToStringReplaced(List container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { + if (replacement == null || replacement.size() < values.size()) { + return paramsToString(writer); + } + List oldVal = values; + values = replacement; + paramsToString(writer); + values = oldVal; + return writer; + } + + public String toStringNoQ(int i) { + String ret; + Object value = values.get(i); + if (value instanceof ConstantIndex) { + ret = ((ConstantIndex) value).toStringNoQ(constantPool, Configuration.resolveConstants.get()); + } else if (value instanceof String) { + ret = (String) value; + } else if (value instanceof RegisterNumber) { + ret = ((RegisterNumber) value).toStringNoName(); + } else { + ret = value.toString(); + } + return ret; + } + + public String toString(int i) { + String ret; + Object value = values.get(i); + if (value instanceof ConstantIndex) { + ret = ((ConstantIndex) value).toString(constantPool, Configuration.resolveConstants.get()); + } else if (value instanceof String) { + ret = "\"" + Helper.escapeActionScriptString((String) value) + "\""; + } else if (value instanceof RegisterNumber) { + ret = ((RegisterNumber) value).toStringNoName(); + } else { + ret = value.toString(); + } + return ret; + } + + public GraphTextWriter paramsToString(GraphTextWriter writer) { + int pos = 0; + for (int i = 0; i < values.size(); i++) { + if (pos > 0) { + writer.appendNoHilight(" "); + } + writer.append(toString(i), getAddress() + pos + 1, getFileOffset()); + pos++; + } + return writer; + } + + @Override + public String toString() { + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + toString(writer); + return writer.toString(); + } + + public GraphTextWriter toString(GraphTextWriter writer) { + writer.appendNoHilight("Push "); + paramsToString(writer); + return writer; + } + + @Override + public boolean execute(LocalDataArea lda) { + for (Object value : values) { + if (value instanceof ConstantIndex) { + ConstantIndex constantIndex = (ConstantIndex) value; + List cPool = lda.constantPool != null ? lda.constantPool : constantPool; + lda.stack.push(constantIndex.toStringNoQ(cPool, true)); + } else if (value instanceof RegisterNumber) { + int rn = ((RegisterNumber) value).number; + if (lda.localRegisters.containsKey(rn)) { + lda.stack.push(lda.localRegisters.get(rn)); + } else { + lda.stack.push(Undefined.INSTANCE); + } + } else { + lda.stack.push(value); + } + } + + return true; + } + + @Override + public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { + int pos = 0; + for (Object o : values) { + if (o instanceof ConstantIndex) { + if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) { + o = "\u00A7\u00A7constant" + ((ConstantIndex) o).index; + } else { + o = constantPool.get(((ConstantIndex) o).index); + } + } + /*if (o instanceof RegisterNumber) { + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + } else if (output.size() >= 2) { //chained assignments:, ignore for class prototype assignment + GraphTargetItem last = output.get(output.size() - 1); + GraphTargetItem prev = output.get(output.size() - 2); + if (last instanceof SetTypeActionItem) { + if (prev instanceof StoreRegisterActionItem) { + StoreRegisterActionItem str = (StoreRegisterActionItem) prev; + if (str.register.number == ((RegisterNumber) o).number) { + SetTypeActionItem stt = (SetTypeActionItem) last; + stt.setTempRegister(((RegisterNumber) o).number); + if ((stt.getValue() instanceof IncrementActionItem) && (((IncrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { + stack.push(new PreIncrementActionItem(this, lineStartAction, stt.getObject())); + } else if ((stt.getValue() instanceof DecrementActionItem) && (((DecrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { + stack.push(new PreDecrementActionItem(this, lineStartAction, stt.getObject())); + } else { + //stack.push(last); + continue; + } + output.remove(output.size() - 1); + output.remove(output.size() - 1); + pos++; + continue; + } + } + } + } + }*/ + if (o instanceof Boolean) { + Boolean b = (Boolean) o; + if (b) { + stack.push(new TrueItem(this, lineStartAction)); + } else { + stack.push(new FalseItem(this, lineStartAction)); + } + } else { + DirectValueActionItem dvt = new DirectValueActionItem(this, lineStartAction, pos, o, constantPool); + + if (o instanceof RegisterNumber) {//TemporaryRegister + dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + } + } + if (dvt.computedRegValue instanceof TemporaryRegister) { + stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); + } else { + stack.push(dvt); + } + } + pos++; + } + } + + @Override + public int getStackPushCount(BaseLocalData localData, TranslateStack stack) { + return values.size(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index adf5b2f20..36cd7e4bb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -1,1062 +1,1062 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.configuration; - -import com.jpexs.decompiler.flash.ApplicationInfo; -import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode; -import com.jpexs.decompiler.flash.helpers.CodeFormatting; -import com.jpexs.decompiler.flash.importers.TextImportResizeTextBoundsMode; -import com.jpexs.helpers.Helper; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JOptionPane; - -/** - * - * @author JPEXS - */ -public class Configuration { - - private static final String CONFIG_NAME = "config.bin"; - - private static final File unspecifiedFile = new File("unspecified"); - - private static File directory = unspecifiedFile; - - public static final Level logLevel; - - public static boolean showStat; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem openMultipleFiles = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem decompile = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("decompilation") - public static final ConfigurationItem parallelSpeedUp = null; - - @ConfigurationDefaultInt(10) - @ConfigurationCategory("decompilation") - public static final ConfigurationItem parallelSpeedUpThreadCount = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem autoDeobfuscate = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("") - public static final ConfigurationItem cacheOnDisk = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("") - public static final ConfigurationItem cacheImages = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("display") - public static final ConfigurationItem internalFlashViewer = null; - - @ConfigurationDefaultInt(1000) - @ConfigurationCategory("display") - public static final ConfigurationItem setMovieDelay = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("display") - public static final ConfigurationItem dumpView = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("display") - public static final ConfigurationItem useHexColorFormat = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("display") - public static final ConfigurationItem showOldTextDuringTextEditing = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("ui") - public static final ConfigurationItem gotoMainClassOnStartup = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem autoRenameIdentifiers = null; - - @ConfigurationDefaultBoolean(false) - public static final ConfigurationItem offeredAssociation = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem decimalAddress = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem showAllAddresses = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("display") - public static final ConfigurationItem useFrameCache = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem useRibbonInterface = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("export") - public static final ConfigurationItem overwriteExistingFiles = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("export") - public static final ConfigurationItem openFolderAfterFlaExport = null; - - @ConfigurationCategory("export") - public static final ConfigurationItem overrideTextExportFileName = null; - - @ConfigurationDefaultBoolean(false) - public static final ConfigurationItem useDetailedLogging = null; - - /** - * Debug mode = throwing an error when comparing original file and - * recompiled - */ - @ConfigurationDefaultBoolean(false) - @ConfigurationInternal - public static final ConfigurationItem _debugMode = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationInternal - public static final ConfigurationItem _showDebugMenu = null; - - /** - * Turn off resolving constants in ActionScript 2 - */ - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem resolveConstants = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - @ConfigurationInternal - public static final ConfigurationItem showFileOffsetInPcodeHex = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - @ConfigurationInternal - public static final ConfigurationItem showOriginalBytesInPcodeHex = null; - - /** - * Limit of code subs (for obfuscated code) - */ - @ConfigurationDefaultInt(500) - @ConfigurationCategory("limit") - public static final ConfigurationItem sublimiter = null; - - /** - * Total export timeout in seconds - */ - @ConfigurationDefaultInt(30 * 60) - @ConfigurationCategory("limit") - public static final ConfigurationItem exportTimeout = null; - - /** - * Decompilation timeout in seconds for a single file - */ - @ConfigurationDefaultInt(5 * 60) - @ConfigurationCategory("limit") - public static final ConfigurationItem decompilationTimeoutFile = null; - - /** - * Using parameter names in decompiling may cause problems because official - * programs like Flash CS 5.5 inserts wrong parameter names indices - */ - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem paramNamesEnable = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem displayFileName = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationInternal - public static final ConfigurationItem _debugCopy = null; - - @ConfigurationDefaultBoolean(false) - public static final ConfigurationItem dumpTags = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("export") - public static final ConfigurationItem setFFDecVersionInExportedFont = null; - - @ConfigurationDefaultInt(60) - @ConfigurationCategory("limit") - public static final ConfigurationItem decompilationTimeoutSingleMethod = null; - - @ConfigurationDefaultInt(1) - public static final ConfigurationItem lastRenameType = null; - - @ConfigurationDefaultString(".") - @ConfigurationDirectory - public static final ConfigurationItem lastSaveDir = null; - - @ConfigurationDefaultString(".") - @ConfigurationDirectory - public static final ConfigurationItem lastOpenDir = null; - - @ConfigurationDefaultString(".") - @ConfigurationDirectory - public static final ConfigurationItem lastExportDir = null; - - @ConfigurationDefaultString("en") - @ConfigurationCategory("ui") - public static final ConfigurationItem locale = null; - - @ConfigurationDefaultString("_loc%d_") - @ConfigurationCategory("script") - public static final ConfigurationItem registerNameFormat = null; - - @ConfigurationDefaultInt(15) - public static final ConfigurationItem maxRecentFileCount = null; - - public static final ConfigurationItem recentFiles = null; - - public static final ConfigurationItem> fontPairingMap = null; - - public static final ConfigurationItem> swfSpecificConfigs = null; - - @ConfigurationDefaultCalendar(0) - public static final ConfigurationItem lastUpdatesCheckDate = null; - - @ConfigurationDefaultInt(1000) - @ConfigurationName("gui.window.width") - public static final ConfigurationItem guiWindowWidth = null; - - @ConfigurationDefaultInt(700) - @ConfigurationName("gui.window.height") - public static final ConfigurationItem guiWindowHeight = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationName("gui.window.maximized.horizontal") - public static final ConfigurationItem guiWindowMaximizedHorizontal = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationName("gui.window.maximized.vertical") - public static final ConfigurationItem guiWindowMaximizedVertical = null; - - @ConfigurationDefaultDouble(0.5) - @ConfigurationName("gui.avm2.splitPane.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiAvm2SplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.5) - @ConfigurationName("gui.actionSplitPane.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiActionSplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.5) - @ConfigurationName("gui.previewSplitPane.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiPreviewSplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.3333333333) - @ConfigurationName("gui.splitPane1.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiSplitPane1DividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.6) - @ConfigurationName("gui.splitPane2.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiSplitPane2DividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.5) - @ConfigurationName("gui.timeLineSplitPane.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiTimeLineSplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.6) - @ConfigurationName("gui.dump.splitPane.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiDumpSplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultString("com.jpexs.decompiler.flash.gui.OceanicSkin") - @ConfigurationName("gui.skin") - @ConfigurationCategory("ui") - public static final ConfigurationItem guiSkin = null; - - @ConfigurationDefaultInt(3) - @ConfigurationCategory("export") - public static final ConfigurationItem saveAsExeScaleMode = null; - - @ConfigurationCategory("export") - public static final ConfigurationItem exeExportMode = null; - - @ConfigurationDefaultInt(1024 * 1024/*1MiB*/) - @ConfigurationCategory("limit") - public static final ConfigurationItem syntaxHighlightLimit = null; - - public static final ConfigurationItem guiFontPreviewSampleText = null; - - @ConfigurationName("gui.fontPreviewWindow.width") - public static final ConfigurationItem guiFontPreviewWidth = null; - - @ConfigurationName("gui.fontPreviewWindow.height") - public static final ConfigurationItem guiFontPreviewHeight = null; - - @ConfigurationName("gui.fontPreviewWindow.posX") - public static final ConfigurationItem guiFontPreviewPosX = null; - - @ConfigurationName("gui.fontPreviewWindow.posY") - public static final ConfigurationItem guiFontPreviewPosY = null; - - @ConfigurationDefaultInt(3) - @ConfigurationName("formatting.indent.size") - @ConfigurationCategory("format") - public static final ConfigurationItem indentSize = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationName("formatting.indent.useTabs") - @ConfigurationCategory("format") - public static final ConfigurationItem indentUseTabs = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("format") - public static final ConfigurationItem beginBlockOnNewLine = null; - - @ConfigurationDefaultInt(1000 * 60 * 60 * 24) - @ConfigurationCategory("update") - @ConfigurationName("check.updates.delay") - public static final ConfigurationItem checkForUpdatesDelay = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("update") - @ConfigurationName("check.updates.stable") - public static final ConfigurationItem checkForUpdatesStable = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("update") - @ConfigurationName("check.updates.nightly") - public static final ConfigurationItem checkForUpdatesNightly = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("update") - @ConfigurationName("check.updates.enabled") - public static final ConfigurationItem checkForUpdatesAuto = null; - - @ConfigurationCategory("update") - public static final ConfigurationItem updateProxyAddress = null; - - @ConfigurationDefaultString("") - @ConfigurationName("export.formats") - public static final ConfigurationItem lastSelectedExportFormats = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("export") - public static final ConfigurationItem textExportSingleFile = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("export") - public static final ConfigurationItem scriptExportSingleFile = null; - - @ConfigurationDefaultString("--- SEPARATOR ---") - @ConfigurationCategory("export") - public static final ConfigurationItem textExportSingleFileSeparator = null; - - @ConfigurationDefaultString("--- RECORDSEPARATOR ---") - @ConfigurationCategory("export") - public static final ConfigurationItem textExportSingleFileRecordSeparator = null; - - @ConfigurationCategory("import") - public static final ConfigurationItem textImportResizeTextBoundsMode = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("import") - public static final ConfigurationItem resetLetterSpacingOnTextImport = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationName("warning.experimental.as12edit") - @ConfigurationCategory("script") - public static final ConfigurationItem warningExperimentalAS12Edit = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationName("warning.experimental.as3edit") - @ConfigurationCategory("script") - public static final ConfigurationItem warningExperimentalAS3Edit = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem showCodeSavedMessage = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem showTraitSavedMessage = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("export") - public static final ConfigurationItem packJavaScripts = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("export") - public static final ConfigurationItem textExportExportFontFace = null; - - @ConfigurationDefaultInt(128) - public static final ConfigurationItem lzmaFastBytes = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem showMethodBodyId = null; - - @ConfigurationDefaultDouble(1.0) - @ConfigurationName("export.zoom") - public static final ConfigurationItem lastSelectedExportZoom = null; - - public static final ConfigurationItem pluginPath = null; - - @ConfigurationDefaultInt(55556) - @ConfigurationCategory("script") - public static final ConfigurationItem debuggerPort = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem randomDebuggerPackage = null; - - @ConfigurationDefaultBoolean(true) - public static final ConfigurationItem displayDebuggerInfo = null; - - @ConfigurationDefaultString("debugConsole") - public static final ConfigurationItem lastDebuggerReplaceFunction = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem getLocalNamesFromDebugInfo = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("ui") - public static final ConfigurationItem tagTreeShowEmptyFolders = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("ui") - public static final ConfigurationItem autoLoadEmbeddedSwfs = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem showCloseConfirmation = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("ui") - public static final ConfigurationItem editorMode = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("ui") - public static final ConfigurationItem autoSaveTagModifications = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem saveSessionOnExit = null; - - public static final ConfigurationItem lastSessionFiles = null; - - public static final ConfigurationItem lastSessionFileTitles = null; - - public static final ConfigurationItem lastSessionSelection = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem loopMedia = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("ui") - public static final ConfigurationItem allowOnlyOneInstance = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem ignoreCLikePackages = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem smartNumberFormatting = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem enableScriptInitializerDisplay = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("ui") - public static final ConfigurationItem autoOpenLoadedSWFs = null; - - @ConfigurationDefaultString("") - @ConfigurationCategory("paths") - @ConfigurationFile - public static final ConfigurationItem playerLocation = null; - - @ConfigurationDefaultString("") - @ConfigurationCategory("paths") - @ConfigurationFile - public static final ConfigurationItem playerDebugLocation = null; - - @ConfigurationDefaultString("") - @ConfigurationCategory("paths") - @ConfigurationFile(".*\\.swc$") - public static final ConfigurationItem playerLibLocation = null; - - @ConfigurationDefaultDouble(0.7) - @ConfigurationName("gui.avm2.splitPane.vars.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiAvm2VarsSplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultDouble(0.7) - @ConfigurationName("gui.action.splitPane.vars.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiActionVarsSplitPaneDividerLocationPercent = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem debugHalt = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationName("warning.svgImport") - @ConfigurationCategory("import") - public static final ConfigurationItem warningSvgImport = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationName("warning.hexViewNotUpToDate") - @ConfigurationCategory("import") - public static final ConfigurationItem warningHexViewNotUpToDate = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationName("shapeImport.useNonSmoothedFill") - @ConfigurationCategory("import") - public static final ConfigurationItem shapeImportUseNonSmoothedFill = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("display") - @ConfigurationName("internalFlashViewer.execute.as12") - public static final ConfigurationItem internalFlashViewerExecuteAs12 = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem displayDupInstructions = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem useRegExprLiteral = null; - - @ConfigurationDefaultBoolean(true) - @ConfigurationCategory("script") - public static final ConfigurationItem handleSkinPartsAutomatically = null; - - @ConfigurationDefaultBoolean(false) - //@ConfigurationCategory("script") - @ConfigurationInternal - public static final ConfigurationItem _ignoreAdditionalFlexClasses = null; - - @ConfigurationDefaultBoolean(false) - //@ConfigurationCategory("script") - @ConfigurationInternal - public static final ConfigurationItem _enableFlexExport = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationCategory("script") - public static final ConfigurationItem simplifyExpressions = null; - - @ConfigurationDefaultBoolean(false) - @ConfigurationInternal - public static final ConfigurationItem hwAcceleratedGraphics = null; - - @ConfigurationDefaultDouble(0.85) - @ConfigurationName("gui.avm2.splitPane.docs.dividerLocationPercent") - @ConfigurationInternal - public static final ConfigurationItem guiAvm2DocsSplitPaneDividerLocationPercent = null; - - private enum OSId { - - WINDOWS, OSX, UNIX - } - - private static OSId getOSId() { - PrivilegedAction doGetOSName = new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("os.name"); - } - }; - OSId id = OSId.UNIX; - String osName = AccessController.doPrivileged(doGetOSName); - if (osName != null) { - if (osName.toLowerCase().startsWith("mac os x")) { - id = OSId.OSX; - } else if (osName.contains("Windows")) { - id = OSId.WINDOWS; - } - } - return id; - } - - public static String getFFDecHome() { - if (directory == unspecifiedFile) { - directory = null; - String userHome = null; - try { - userHome = System.getProperty("user.home"); - } catch (SecurityException ignore) { - } - if (userHome != null) { - String applicationId = ApplicationInfo.SHORT_APPLICATION_NAME; - OSId osId = getOSId(); - if (osId == OSId.WINDOWS) { - File appDataDir = null; - try { - String appDataEV = System.getenv("APPDATA"); - if ((appDataEV != null) && (appDataEV.length() > 0)) { - appDataDir = new File(appDataEV); - } - } catch (SecurityException ignore) { - } - String vendorId = ApplicationInfo.VENDOR; - if ((appDataDir != null) && appDataDir.isDirectory()) { - // ${APPDATA}\{vendorId}\${applicationId} - String path = vendorId + "\\" + applicationId + "\\"; - directory = new File(appDataDir, path); - } else { - // ${userHome}\Application Data\${vendorId}\${applicationId} - String path = "Application Data\\" + vendorId + "\\" + applicationId + "\\"; - directory = new File(userHome, path); - } - } else if (osId == OSId.OSX) { - // ${userHome}/Library/Application Support/${applicationId} - String path = "Library/Application Support/" + applicationId + "/"; - directory = new File(userHome, path); - } else { - // ${userHome}/.${applicationId}/ - String path = "." + applicationId + "/"; - directory = new File(userHome, path); - } - } else { - //no home, then use application directory - directory = new File("."); - } - } - if (!directory.exists()) { - if (!directory.mkdirs()) { - if (!directory.exists()) { - directory = new File("."); //fallback to current directory - } - } - } - String ret = directory.getAbsolutePath(); - if (!ret.endsWith(File.separator)) { - ret += File.separator; - } - return ret; - } - - public static List getRecentFiles() { - String files = recentFiles.get(); - if (files == null || files.isEmpty()) { - return new ArrayList<>(); - } - return Arrays.asList(files.split("::")); - } - - public static void addRecentFile(String path) { - List recentFilesArray = new ArrayList<>(getRecentFiles()); - int idx = recentFilesArray.indexOf(path); - if (idx != -1) { - recentFilesArray.remove(idx); - } - recentFilesArray.add(path); - while (recentFilesArray.size() > maxRecentFileCount.get()) { - recentFilesArray.remove(0); - } - recentFiles.set(Helper.joinStrings(recentFilesArray, "::")); - } - - public static void removeRecentFile(String path) { - List recentFilesArray = new ArrayList<>(getRecentFiles()); - int idx = recentFilesArray.indexOf(path); - if (idx != -1) { - recentFilesArray.remove(idx); - } - recentFiles.set(Helper.joinStrings(recentFilesArray, "::")); - } - - public static Map getFontToNameMap() { - HashMap map = fontPairingMap.get(); - if (map == null) { - map = new HashMap<>(); - fontPairingMap.set(map); - } - - return map; - } - - public static void addFontPair(String fileName, int fontId, String fontName, String installedName) { - Map fontPairs = getFontToNameMap(); - fontPairs.put(fontName, installedName); - - SwfSpecificConfiguration swfConf = getOrCreateSwfSpecificConfiguration(fileName); - swfConf.fontPairingMap.put(fontId + "_" + fontName, installedName); - } - - public static SwfSpecificConfiguration getSwfSpecificConfiguration(String fileName) { - HashMap map = swfSpecificConfigs.get(); - if (map == null) { - map = new HashMap<>(); - swfSpecificConfigs.set(map); - } - - return map.get(fileName); - } - - public static SwfSpecificConfiguration getOrCreateSwfSpecificConfiguration(String fileName) { - SwfSpecificConfiguration swfConf = getSwfSpecificConfiguration(fileName); - if (swfConf == null) { - swfConf = new SwfSpecificConfiguration(); - swfSpecificConfigs.get().put(fileName, swfConf); - } - - return swfConf; - } - - private static String getConfigFile() throws IOException { - return getFFDecHome() + CONFIG_NAME; - } - - private static HashMap loadFromFile(String file) { - try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { - - @SuppressWarnings("unchecked") - HashMap cfg = (HashMap) ois.readObject(); - return cfg; - } catch (ClassNotFoundException | IOException ex) { - // ignore - } - - return new HashMap<>(); - } - - private static void saveToFile(String file) { - HashMap config = new HashMap<>(); - for (Entry entry : getConfigurationFields().entrySet()) { - try { - String name = entry.getKey(); - Field field = entry.getValue(); - ConfigurationItem item = (ConfigurationItem) field.get(null); - if (item.hasValue) { - config.put(name, item.get()); - } - } catch (IllegalArgumentException | IllegalAccessException ex) { - Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); - } - } - try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) { - oos.writeObject(config); - } catch (IOException ex) { - //TODO: move this to GUI - JOptionPane.showMessageDialog(null, "Cannot save configuration.", "Error", JOptionPane.ERROR_MESSAGE); - Logger.getLogger(Configuration.class.getName()).severe("Configuration directory is read only."); - } - } - - public static void saveConfig() { - try { - saveToFile(getConfigFile()); - } catch (IOException ex) { - // ignore - } - } - - static { - setConfigurationFields(); - if (useDetailedLogging.get()) { - logLevel = Level.FINEST; - } else if (_debugMode.get()) { - logLevel = Level.INFO; - } else { - logLevel = Level.WARNING; - } - //limit paralel threads? - //int processorCount = Runtime.getRuntime().availableProcessors(); - } - - @SuppressWarnings("unchecked") - public static void setConfigurationFields() { - try { - HashMap config = loadFromFile(getConfigFile()); - for (Entry entry : getConfigurationFields().entrySet()) { - String name = entry.getKey(); - Field field = entry.getValue(); - // remove final modifier from field - Field modifiersField = field.getClass().getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - - Object defaultValue = getDefaultValue(field); - Object value = null; - if (config.containsKey(name)) { - value = config.get(name); - - Class type; - Type type2 = ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0]; - if (type2 instanceof Class) { - type = (Class) type2; - } else { - type = (Class) ((ParameterizedType) type2).getRawType(); - } - if (value != null && !type.isAssignableFrom(value.getClass())) { - System.out.println("Configuration item has a wrong type: " + name + " expected: " + type.getSimpleName() + " actual: " + value.getClass().getSimpleName()); - value = null; - } - } - - if (value != null) { - field.set(null, new ConfigurationItem(name, defaultValue, value)); - } else { - field.set(null, new ConfigurationItem(name, defaultValue)); - } - } - } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ex) { - // Reflection exceptions. This should never happen - throw new Error(ex.getMessage()); - } catch (IOException ex) { - Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); - } - if (playerLibLocation.get("").isEmpty()) { - File swcFile = getPlayerSwcOld(); - if (swcFile != null) { - playerLibLocation.set(swcFile.getAbsolutePath()); - } - } - } - - public static Object getDefaultValue(Field field) { - Object defaultValue = null; - ConfigurationDefaultBoolean aBool = field.getAnnotation(ConfigurationDefaultBoolean.class); - if (aBool != null) { - defaultValue = aBool.value(); - } - ConfigurationDefaultInt aInt = field.getAnnotation(ConfigurationDefaultInt.class); - if (aInt != null) { - defaultValue = aInt.value(); - } - ConfigurationDefaultString aString = field.getAnnotation(ConfigurationDefaultString.class); - if (aString != null) { - defaultValue = aString.value(); - } - ConfigurationDefaultDouble aDouble = field.getAnnotation(ConfigurationDefaultDouble.class); - if (aDouble != null) { - defaultValue = aDouble.value(); - } - ConfigurationDefaultCalendar aCalendar = field.getAnnotation(ConfigurationDefaultCalendar.class); - if (aCalendar != null) { - GregorianCalendar mingc = new GregorianCalendar(); - mingc.setTime(new Date(aCalendar.value())); - defaultValue = mingc; - } - return defaultValue; - } - - public static Map getConfigurationFields() { - Field[] fields = Configuration.class.getFields(); - Map result = new HashMap<>(); - for (Field field : fields) { - if (ConfigurationItem.class.isAssignableFrom(field.getType())) { - ConfigurationName annotation = field.getAnnotation(ConfigurationName.class); - String name = annotation == null ? field.getName() : annotation.value(); - result.put(name, field); - } - } - return result; - } - - public static CodeFormatting getCodeFormatting() { - CodeFormatting ret = new CodeFormatting(); - String indentString = ""; - for (int i = 0; i < indentSize.get(); i++) { - indentString += indentUseTabs.get() ? "\t" : " "; - } - ret.indentString = indentString; - ret.beginBlockOnNewLine = beginBlockOnNewLine.get(); - return ret; - } - - public static int getParallelThreadCount() { - int count = parallelSpeedUpThreadCount.get(); - if (count < 2) { - count = 2; - } - - return count; - } - - public static File getPath(String folder) { - String home = getFFDecHome(); - File dir = new File(home + folder); - if (!dir.exists()) { - dir.mkdirs(); - } - return dir; - } - - public static File getFlashLibPath() { - return getPath("flashlib"); - } - - public static File getProjectorPath() { - return getPath("projector"); - } - - private static String getDownloadsHtml() throws IOException { - String html = Helper.downloadUrlString("https://www.adobe.com/support/flashplayer/downloads.html"); - return html; - } - - private static String getUrlFromDownloadsHtml(String urlPatternString) { - try { - String html = getDownloadsHtml(); - Pattern urlPattern = Pattern.compile(urlPatternString, Pattern.DOTALL); - Matcher matcher = urlPattern.matcher(html); - if (matcher.matches()) { - String url = matcher.group(1); - int a = url.length(); - return url; - } - - return null; - } catch (IOException ex) { - Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); - return null; - } - } - - private static String getLatestPlayerGlobalUrl() { - return getUrlFromDownloadsHtml(".* libNames = new ArrayList<>(); - for (File f : libs) { - libNames.add(f.getName()); - } - Collections.sort(libNames); - if (!libNames.isEmpty()) { - return new File(libsDir.getAbsolutePath() + File.separator + libNames.get(libNames.size() - 1)); - } else { - return null; - } - } - - return null; - } - - public static File getProjectorFile(ExeExportMode exportMode) { - File projectoDir = getProjectorPath(); - if (projectoDir != null && projectoDir.exists()) { - File[] projectors = projectoDir.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File dir, String name) { - switch (exportMode) { - case PROJECTOR_WIN: - return name.toLowerCase().endsWith(".exe"); - case PROJECTOR_MAC: - return name.toLowerCase().endsWith(".dmg"); - case PROJECTOR_LINUX: - return name.toLowerCase().endsWith(".gz"); - } - - return false; - } - }); - List projectorNames = new ArrayList<>(); - for (File f : projectors) { - projectorNames.add(f.getName()); - } - Collections.sort(projectorNames); - if (!projectorNames.isEmpty()) { - return new File(projectoDir.getAbsolutePath() + File.separator + projectorNames.get(projectorNames.size() - 1)); - } else { - return null; - } - } - - return null; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.configuration; + +import com.jpexs.decompiler.flash.ApplicationInfo; +import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.importers.TextImportResizeTextBoundsMode; +import com.jpexs.helpers.Helper; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JOptionPane; + +/** + * + * @author JPEXS + */ +public class Configuration { + + private static final String CONFIG_NAME = "config.bin"; + + private static final File unspecifiedFile = new File("unspecified"); + + private static File directory = unspecifiedFile; + + public static final Level logLevel; + + public static boolean showStat; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem openMultipleFiles = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem decompile = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("decompilation") + public static final ConfigurationItem parallelSpeedUp = null; + + @ConfigurationDefaultInt(10) + @ConfigurationCategory("decompilation") + public static final ConfigurationItem parallelSpeedUpThreadCount = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem autoDeobfuscate = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("") + public static final ConfigurationItem cacheOnDisk = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("") + public static final ConfigurationItem cacheImages = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("display") + public static final ConfigurationItem internalFlashViewer = null; + + @ConfigurationDefaultInt(1000) + @ConfigurationCategory("display") + public static final ConfigurationItem setMovieDelay = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("display") + public static final ConfigurationItem dumpView = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("display") + public static final ConfigurationItem useHexColorFormat = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("display") + public static final ConfigurationItem showOldTextDuringTextEditing = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("ui") + public static final ConfigurationItem gotoMainClassOnStartup = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem autoRenameIdentifiers = null; + + @ConfigurationDefaultBoolean(false) + public static final ConfigurationItem offeredAssociation = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem decimalAddress = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem showAllAddresses = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("display") + public static final ConfigurationItem useFrameCache = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem useRibbonInterface = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("export") + public static final ConfigurationItem overwriteExistingFiles = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("export") + public static final ConfigurationItem openFolderAfterFlaExport = null; + + @ConfigurationCategory("export") + public static final ConfigurationItem overrideTextExportFileName = null; + + @ConfigurationDefaultBoolean(false) + public static final ConfigurationItem useDetailedLogging = null; + + /** + * Debug mode = throwing an error when comparing original file and + * recompiled + */ + @ConfigurationDefaultBoolean(false) + @ConfigurationInternal + public static final ConfigurationItem _debugMode = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationInternal + public static final ConfigurationItem _showDebugMenu = null; + + /** + * Turn off resolving constants in ActionScript 2 + */ + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem resolveConstants = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + @ConfigurationInternal + public static final ConfigurationItem showFileOffsetInPcodeHex = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + @ConfigurationInternal + public static final ConfigurationItem showOriginalBytesInPcodeHex = null; + + /** + * Limit of code subs (for obfuscated code) + */ + @ConfigurationDefaultInt(500) + @ConfigurationCategory("limit") + public static final ConfigurationItem sublimiter = null; + + /** + * Total export timeout in seconds + */ + @ConfigurationDefaultInt(30 * 60) + @ConfigurationCategory("limit") + public static final ConfigurationItem exportTimeout = null; + + /** + * Decompilation timeout in seconds for a single file + */ + @ConfigurationDefaultInt(5 * 60) + @ConfigurationCategory("limit") + public static final ConfigurationItem decompilationTimeoutFile = null; + + /** + * Using parameter names in decompiling may cause problems because official + * programs like Flash CS 5.5 inserts wrong parameter names indices + */ + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem paramNamesEnable = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem displayFileName = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationInternal + public static final ConfigurationItem _debugCopy = null; + + @ConfigurationDefaultBoolean(false) + public static final ConfigurationItem dumpTags = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("export") + public static final ConfigurationItem setFFDecVersionInExportedFont = null; + + @ConfigurationDefaultInt(60) + @ConfigurationCategory("limit") + public static final ConfigurationItem decompilationTimeoutSingleMethod = null; + + @ConfigurationDefaultInt(1) + public static final ConfigurationItem lastRenameType = null; + + @ConfigurationDefaultString(".") + @ConfigurationDirectory + public static final ConfigurationItem lastSaveDir = null; + + @ConfigurationDefaultString(".") + @ConfigurationDirectory + public static final ConfigurationItem lastOpenDir = null; + + @ConfigurationDefaultString(".") + @ConfigurationDirectory + public static final ConfigurationItem lastExportDir = null; + + @ConfigurationDefaultString("en") + @ConfigurationCategory("ui") + public static final ConfigurationItem locale = null; + + @ConfigurationDefaultString("_loc%d_") + @ConfigurationCategory("script") + public static final ConfigurationItem registerNameFormat = null; + + @ConfigurationDefaultInt(15) + public static final ConfigurationItem maxRecentFileCount = null; + + public static final ConfigurationItem recentFiles = null; + + public static final ConfigurationItem> fontPairingMap = null; + + public static final ConfigurationItem> swfSpecificConfigs = null; + + @ConfigurationDefaultCalendar(0) + public static final ConfigurationItem lastUpdatesCheckDate = null; + + @ConfigurationDefaultInt(1000) + @ConfigurationName("gui.window.width") + public static final ConfigurationItem guiWindowWidth = null; + + @ConfigurationDefaultInt(700) + @ConfigurationName("gui.window.height") + public static final ConfigurationItem guiWindowHeight = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationName("gui.window.maximized.horizontal") + public static final ConfigurationItem guiWindowMaximizedHorizontal = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationName("gui.window.maximized.vertical") + public static final ConfigurationItem guiWindowMaximizedVertical = null; + + @ConfigurationDefaultDouble(0.5) + @ConfigurationName("gui.avm2.splitPane.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiAvm2SplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.5) + @ConfigurationName("gui.actionSplitPane.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiActionSplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.5) + @ConfigurationName("gui.previewSplitPane.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiPreviewSplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.3333333333) + @ConfigurationName("gui.splitPane1.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiSplitPane1DividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.6) + @ConfigurationName("gui.splitPane2.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiSplitPane2DividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.5) + @ConfigurationName("gui.timeLineSplitPane.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiTimeLineSplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.6) + @ConfigurationName("gui.dump.splitPane.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiDumpSplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultString("com.jpexs.decompiler.flash.gui.OceanicSkin") + @ConfigurationName("gui.skin") + @ConfigurationCategory("ui") + public static final ConfigurationItem guiSkin = null; + + @ConfigurationDefaultInt(3) + @ConfigurationCategory("export") + public static final ConfigurationItem saveAsExeScaleMode = null; + + @ConfigurationCategory("export") + public static final ConfigurationItem exeExportMode = null; + + @ConfigurationDefaultInt(1024 * 1024/*1MiB*/) + @ConfigurationCategory("limit") + public static final ConfigurationItem syntaxHighlightLimit = null; + + public static final ConfigurationItem guiFontPreviewSampleText = null; + + @ConfigurationName("gui.fontPreviewWindow.width") + public static final ConfigurationItem guiFontPreviewWidth = null; + + @ConfigurationName("gui.fontPreviewWindow.height") + public static final ConfigurationItem guiFontPreviewHeight = null; + + @ConfigurationName("gui.fontPreviewWindow.posX") + public static final ConfigurationItem guiFontPreviewPosX = null; + + @ConfigurationName("gui.fontPreviewWindow.posY") + public static final ConfigurationItem guiFontPreviewPosY = null; + + @ConfigurationDefaultInt(3) + @ConfigurationName("formatting.indent.size") + @ConfigurationCategory("format") + public static final ConfigurationItem indentSize = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationName("formatting.indent.useTabs") + @ConfigurationCategory("format") + public static final ConfigurationItem indentUseTabs = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("format") + public static final ConfigurationItem beginBlockOnNewLine = null; + + @ConfigurationDefaultInt(1000 * 60 * 60 * 24) + @ConfigurationCategory("update") + @ConfigurationName("check.updates.delay") + public static final ConfigurationItem checkForUpdatesDelay = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("update") + @ConfigurationName("check.updates.stable") + public static final ConfigurationItem checkForUpdatesStable = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("update") + @ConfigurationName("check.updates.nightly") + public static final ConfigurationItem checkForUpdatesNightly = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("update") + @ConfigurationName("check.updates.enabled") + public static final ConfigurationItem checkForUpdatesAuto = null; + + @ConfigurationCategory("update") + public static final ConfigurationItem updateProxyAddress = null; + + @ConfigurationDefaultString("") + @ConfigurationName("export.formats") + public static final ConfigurationItem lastSelectedExportFormats = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("export") + public static final ConfigurationItem textExportSingleFile = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("export") + public static final ConfigurationItem scriptExportSingleFile = null; + + @ConfigurationDefaultString("--- SEPARATOR ---") + @ConfigurationCategory("export") + public static final ConfigurationItem textExportSingleFileSeparator = null; + + @ConfigurationDefaultString("--- RECORDSEPARATOR ---") + @ConfigurationCategory("export") + public static final ConfigurationItem textExportSingleFileRecordSeparator = null; + + @ConfigurationCategory("import") + public static final ConfigurationItem textImportResizeTextBoundsMode = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("import") + public static final ConfigurationItem resetLetterSpacingOnTextImport = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationName("warning.experimental.as12edit") + @ConfigurationCategory("script") + public static final ConfigurationItem warningExperimentalAS12Edit = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationName("warning.experimental.as3edit") + @ConfigurationCategory("script") + public static final ConfigurationItem warningExperimentalAS3Edit = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem showCodeSavedMessage = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem showTraitSavedMessage = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("export") + public static final ConfigurationItem packJavaScripts = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("export") + public static final ConfigurationItem textExportExportFontFace = null; + + @ConfigurationDefaultInt(128) + public static final ConfigurationItem lzmaFastBytes = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem showMethodBodyId = null; + + @ConfigurationDefaultDouble(1.0) + @ConfigurationName("export.zoom") + public static final ConfigurationItem lastSelectedExportZoom = null; + + public static final ConfigurationItem pluginPath = null; + + @ConfigurationDefaultInt(55556) + @ConfigurationCategory("script") + public static final ConfigurationItem debuggerPort = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem randomDebuggerPackage = null; + + @ConfigurationDefaultBoolean(true) + public static final ConfigurationItem displayDebuggerInfo = null; + + @ConfigurationDefaultString("debugConsole") + public static final ConfigurationItem lastDebuggerReplaceFunction = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem getLocalNamesFromDebugInfo = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("ui") + public static final ConfigurationItem tagTreeShowEmptyFolders = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("ui") + public static final ConfigurationItem autoLoadEmbeddedSwfs = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem showCloseConfirmation = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("ui") + public static final ConfigurationItem editorMode = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("ui") + public static final ConfigurationItem autoSaveTagModifications = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem saveSessionOnExit = null; + + public static final ConfigurationItem lastSessionFiles = null; + + public static final ConfigurationItem lastSessionFileTitles = null; + + public static final ConfigurationItem lastSessionSelection = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem loopMedia = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static final ConfigurationItem allowOnlyOneInstance = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem ignoreCLikePackages = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem smartNumberFormatting = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem enableScriptInitializerDisplay = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("ui") + public static final ConfigurationItem autoOpenLoadedSWFs = null; + + @ConfigurationDefaultString("") + @ConfigurationCategory("paths") + @ConfigurationFile + public static final ConfigurationItem playerLocation = null; + + @ConfigurationDefaultString("") + @ConfigurationCategory("paths") + @ConfigurationFile + public static final ConfigurationItem playerDebugLocation = null; + + @ConfigurationDefaultString("") + @ConfigurationCategory("paths") + @ConfigurationFile(".*\\.swc$") + public static final ConfigurationItem playerLibLocation = null; + + @ConfigurationDefaultDouble(0.7) + @ConfigurationName("gui.avm2.splitPane.vars.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiAvm2VarsSplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultDouble(0.7) + @ConfigurationName("gui.action.splitPane.vars.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiActionVarsSplitPaneDividerLocationPercent = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem debugHalt = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationName("warning.svgImport") + @ConfigurationCategory("import") + public static final ConfigurationItem warningSvgImport = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationName("warning.hexViewNotUpToDate") + @ConfigurationCategory("import") + public static final ConfigurationItem warningHexViewNotUpToDate = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationName("shapeImport.useNonSmoothedFill") + @ConfigurationCategory("import") + public static final ConfigurationItem shapeImportUseNonSmoothedFill = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("display") + @ConfigurationName("internalFlashViewer.execute.as12") + public static final ConfigurationItem internalFlashViewerExecuteAs12 = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem displayDupInstructions = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem useRegExprLiteral = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("script") + public static final ConfigurationItem handleSkinPartsAutomatically = null; + + @ConfigurationDefaultBoolean(false) + //@ConfigurationCategory("script") + @ConfigurationInternal + public static final ConfigurationItem _ignoreAdditionalFlexClasses = null; + + @ConfigurationDefaultBoolean(false) + //@ConfigurationCategory("script") + @ConfigurationInternal + public static final ConfigurationItem _enableFlexExport = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("script") + public static final ConfigurationItem simplifyExpressions = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationInternal + public static final ConfigurationItem hwAcceleratedGraphics = null; + + @ConfigurationDefaultDouble(0.85) + @ConfigurationName("gui.avm2.splitPane.docs.dividerLocationPercent") + @ConfigurationInternal + public static final ConfigurationItem guiAvm2DocsSplitPaneDividerLocationPercent = null; + + private enum OSId { + + WINDOWS, OSX, UNIX + } + + private static OSId getOSId() { + PrivilegedAction doGetOSName = new PrivilegedAction() { + @Override + public String run() { + return System.getProperty("os.name"); + } + }; + OSId id = OSId.UNIX; + String osName = AccessController.doPrivileged(doGetOSName); + if (osName != null) { + if (osName.toLowerCase().startsWith("mac os x")) { + id = OSId.OSX; + } else if (osName.contains("Windows")) { + id = OSId.WINDOWS; + } + } + return id; + } + + public static String getFFDecHome() { + if (directory == unspecifiedFile) { + directory = null; + String userHome = null; + try { + userHome = System.getProperty("user.home"); + } catch (SecurityException ignore) { + } + if (userHome != null) { + String applicationId = ApplicationInfo.SHORT_APPLICATION_NAME; + OSId osId = getOSId(); + if (osId == OSId.WINDOWS) { + File appDataDir = null; + try { + String appDataEV = System.getenv("APPDATA"); + if ((appDataEV != null) && (appDataEV.length() > 0)) { + appDataDir = new File(appDataEV); + } + } catch (SecurityException ignore) { + } + String vendorId = ApplicationInfo.VENDOR; + if ((appDataDir != null) && appDataDir.isDirectory()) { + // ${APPDATA}\{vendorId}\${applicationId} + String path = vendorId + "\\" + applicationId + "\\"; + directory = new File(appDataDir, path); + } else { + // ${userHome}\Application Data\${vendorId}\${applicationId} + String path = "Application Data\\" + vendorId + "\\" + applicationId + "\\"; + directory = new File(userHome, path); + } + } else if (osId == OSId.OSX) { + // ${userHome}/Library/Application Support/${applicationId} + String path = "Library/Application Support/" + applicationId + "/"; + directory = new File(userHome, path); + } else { + // ${userHome}/.${applicationId}/ + String path = "." + applicationId + "/"; + directory = new File(userHome, path); + } + } else { + //no home, then use application directory + directory = new File("."); + } + } + if (!directory.exists()) { + if (!directory.mkdirs()) { + if (!directory.exists()) { + directory = new File("."); //fallback to current directory + } + } + } + String ret = directory.getAbsolutePath(); + if (!ret.endsWith(File.separator)) { + ret += File.separator; + } + return ret; + } + + public static List getRecentFiles() { + String files = recentFiles.get(); + if (files == null || files.isEmpty()) { + return new ArrayList<>(); + } + return Arrays.asList(files.split("::")); + } + + public static void addRecentFile(String path) { + List recentFilesArray = new ArrayList<>(getRecentFiles()); + int idx = recentFilesArray.indexOf(path); + if (idx != -1) { + recentFilesArray.remove(idx); + } + recentFilesArray.add(path); + while (recentFilesArray.size() > maxRecentFileCount.get()) { + recentFilesArray.remove(0); + } + recentFiles.set(Helper.joinStrings(recentFilesArray, "::")); + } + + public static void removeRecentFile(String path) { + List recentFilesArray = new ArrayList<>(getRecentFiles()); + int idx = recentFilesArray.indexOf(path); + if (idx != -1) { + recentFilesArray.remove(idx); + } + recentFiles.set(Helper.joinStrings(recentFilesArray, "::")); + } + + public static Map getFontToNameMap() { + HashMap map = fontPairingMap.get(); + if (map == null) { + map = new HashMap<>(); + fontPairingMap.set(map); + } + + return map; + } + + public static void addFontPair(String fileName, int fontId, String fontName, String installedName) { + Map fontPairs = getFontToNameMap(); + fontPairs.put(fontName, installedName); + + SwfSpecificConfiguration swfConf = getOrCreateSwfSpecificConfiguration(fileName); + swfConf.fontPairingMap.put(fontId + "_" + fontName, installedName); + } + + public static SwfSpecificConfiguration getSwfSpecificConfiguration(String fileName) { + HashMap map = swfSpecificConfigs.get(); + if (map == null) { + map = new HashMap<>(); + swfSpecificConfigs.set(map); + } + + return map.get(fileName); + } + + public static SwfSpecificConfiguration getOrCreateSwfSpecificConfiguration(String fileName) { + SwfSpecificConfiguration swfConf = getSwfSpecificConfiguration(fileName); + if (swfConf == null) { + swfConf = new SwfSpecificConfiguration(); + swfSpecificConfigs.get().put(fileName, swfConf); + } + + return swfConf; + } + + private static String getConfigFile() throws IOException { + return getFFDecHome() + CONFIG_NAME; + } + + private static HashMap loadFromFile(String file) { + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + + @SuppressWarnings("unchecked") + HashMap cfg = (HashMap) ois.readObject(); + return cfg; + } catch (ClassNotFoundException | IOException ex) { + // ignore + } + + return new HashMap<>(); + } + + private static void saveToFile(String file) { + HashMap config = new HashMap<>(); + for (Entry entry : getConfigurationFields().entrySet()) { + try { + String name = entry.getKey(); + Field field = entry.getValue(); + ConfigurationItem item = (ConfigurationItem) field.get(null); + if (item.hasValue) { + config.put(name, item.get()); + } + } catch (IllegalArgumentException | IllegalAccessException ex) { + Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); + } + } + try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) { + oos.writeObject(config); + } catch (IOException ex) { + //TODO: move this to GUI + JOptionPane.showMessageDialog(null, "Cannot save configuration.", "Error", JOptionPane.ERROR_MESSAGE); + Logger.getLogger(Configuration.class.getName()).severe("Configuration directory is read only."); + } + } + + public static void saveConfig() { + try { + saveToFile(getConfigFile()); + } catch (IOException ex) { + // ignore + } + } + + static { + setConfigurationFields(); + if (useDetailedLogging.get()) { + logLevel = Level.FINEST; + } else if (_debugMode.get()) { + logLevel = Level.INFO; + } else { + logLevel = Level.WARNING; + } + //limit paralel threads? + //int processorCount = Runtime.getRuntime().availableProcessors(); + } + + @SuppressWarnings("unchecked") + public static void setConfigurationFields() { + try { + HashMap config = loadFromFile(getConfigFile()); + for (Entry entry : getConfigurationFields().entrySet()) { + String name = entry.getKey(); + Field field = entry.getValue(); + // remove final modifier from field + Field modifiersField = field.getClass().getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + Object defaultValue = getDefaultValue(field); + Object value = null; + if (config.containsKey(name)) { + value = config.get(name); + + Class type; + Type type2 = ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0]; + if (type2 instanceof Class) { + type = (Class) type2; + } else { + type = (Class) ((ParameterizedType) type2).getRawType(); + } + if (value != null && !type.isAssignableFrom(value.getClass())) { + System.out.println("Configuration item has a wrong type: " + name + " expected: " + type.getSimpleName() + " actual: " + value.getClass().getSimpleName()); + value = null; + } + } + + if (value != null) { + field.set(null, new ConfigurationItem(name, defaultValue, value)); + } else { + field.set(null, new ConfigurationItem(name, defaultValue)); + } + } + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ex) { + // Reflection exceptions. This should never happen + throw new Error(ex.getMessage()); + } catch (IOException ex) { + Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); + } + if (playerLibLocation.get("").isEmpty()) { + File swcFile = getPlayerSwcOld(); + if (swcFile != null) { + playerLibLocation.set(swcFile.getAbsolutePath()); + } + } + } + + public static Object getDefaultValue(Field field) { + Object defaultValue = null; + ConfigurationDefaultBoolean aBool = field.getAnnotation(ConfigurationDefaultBoolean.class); + if (aBool != null) { + defaultValue = aBool.value(); + } + ConfigurationDefaultInt aInt = field.getAnnotation(ConfigurationDefaultInt.class); + if (aInt != null) { + defaultValue = aInt.value(); + } + ConfigurationDefaultString aString = field.getAnnotation(ConfigurationDefaultString.class); + if (aString != null) { + defaultValue = aString.value(); + } + ConfigurationDefaultDouble aDouble = field.getAnnotation(ConfigurationDefaultDouble.class); + if (aDouble != null) { + defaultValue = aDouble.value(); + } + ConfigurationDefaultCalendar aCalendar = field.getAnnotation(ConfigurationDefaultCalendar.class); + if (aCalendar != null) { + GregorianCalendar mingc = new GregorianCalendar(); + mingc.setTime(new Date(aCalendar.value())); + defaultValue = mingc; + } + return defaultValue; + } + + public static Map getConfigurationFields() { + Field[] fields = Configuration.class.getFields(); + Map result = new HashMap<>(); + for (Field field : fields) { + if (ConfigurationItem.class.isAssignableFrom(field.getType())) { + ConfigurationName annotation = field.getAnnotation(ConfigurationName.class); + String name = annotation == null ? field.getName() : annotation.value(); + result.put(name, field); + } + } + return result; + } + + public static CodeFormatting getCodeFormatting() { + CodeFormatting ret = new CodeFormatting(); + String indentString = ""; + for (int i = 0; i < indentSize.get(); i++) { + indentString += indentUseTabs.get() ? "\t" : " "; + } + ret.indentString = indentString; + ret.beginBlockOnNewLine = beginBlockOnNewLine.get(); + return ret; + } + + public static int getParallelThreadCount() { + int count = parallelSpeedUpThreadCount.get(); + if (count < 2) { + count = 2; + } + + return count; + } + + public static File getPath(String folder) { + String home = getFFDecHome(); + File dir = new File(home + folder); + if (!dir.exists()) { + dir.mkdirs(); + } + return dir; + } + + public static File getFlashLibPath() { + return getPath("flashlib"); + } + + public static File getProjectorPath() { + return getPath("projector"); + } + + private static String getDownloadsHtml() throws IOException { + String html = Helper.downloadUrlString("https://www.adobe.com/support/flashplayer/downloads.html"); + return html; + } + + private static String getUrlFromDownloadsHtml(String urlPatternString) { + try { + String html = getDownloadsHtml(); + Pattern urlPattern = Pattern.compile(urlPatternString, Pattern.DOTALL); + Matcher matcher = urlPattern.matcher(html); + if (matcher.matches()) { + String url = matcher.group(1); + int a = url.length(); + return url; + } + + return null; + } catch (IOException ex) { + Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } + + private static String getLatestPlayerGlobalUrl() { + return getUrlFromDownloadsHtml(".* libNames = new ArrayList<>(); + for (File f : libs) { + libNames.add(f.getName()); + } + Collections.sort(libNames); + if (!libNames.isEmpty()) { + return new File(libsDir.getAbsolutePath() + File.separator + libNames.get(libNames.size() - 1)); + } else { + return null; + } + } + + return null; + } + + public static File getProjectorFile(ExeExportMode exportMode) { + File projectoDir = getProjectorPath(); + if (projectoDir != null && projectoDir.exists()) { + File[] projectors = projectoDir.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + switch (exportMode) { + case PROJECTOR_WIN: + return name.toLowerCase().endsWith(".exe"); + case PROJECTOR_MAC: + return name.toLowerCase().endsWith(".dmg"); + case PROJECTOR_LINUX: + return name.toLowerCase().endsWith(".gz"); + } + + return false; + } + }); + List projectorNames = new ArrayList<>(); + for (File f : projectors) { + projectorNames.add(f.getName()); + } + Collections.sort(projectorNames); + if (!projectorNames.isEmpty()) { + return new File(projectoDir.getAbsolutePath() + File.separator + projectorNames.get(projectorNames.size() - 1)); + } else { + return null; + } + } + + return null; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/SwfSpecificConfiguration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/SwfSpecificConfiguration.java index 9b04c3c80..22963d29e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/SwfSpecificConfiguration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/SwfSpecificConfiguration.java @@ -1,32 +1,32 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.configuration; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -/** - * - * @author JPEXS - */ -public class SwfSpecificConfiguration implements Serializable { - - public Map fontPairingMap = new HashMap<>(); - - public String lastSelectedPath = null; -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.configuration; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author JPEXS + */ +public class SwfSpecificConfiguration implements Serializable { + + public Map fontPairingMap = new HashMap<>(); + + public String lastSelectedPath = null; +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java index a3efd0e77..31c6728b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java @@ -1,164 +1,164 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.dumpview; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.TagStub; -import com.jpexs.decompiler.flash.treeitems.TreeItem; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public class DumpInfo implements TreeItem { - - public String name; - - public String type; - - public TagStub tagToResolve = null; - - public Tag resolvedTag = null; - - public Object previewValue; - - public long startByte; - - public int startBit; - - public long lengthBytes; - - public int lengthBits; - - public DumpInfo parent; - - private List childInfos; - - public DumpInfo(String name, String type, Object value, long startByte, long lengthBytes) { - - this.name = name; - this.type = type; - this.previewValue = value; - this.startByte = startByte; - this.lengthBytes = lengthBytes; - } - - public DumpInfo(String name, String type, Object value, long startByte, int startBit, long lengthBytes, int lengthBits) { - - this.name = name; - this.type = type; - this.previewValue = value; - this.startByte = startByte; - this.lengthBytes = lengthBytes; - this.startBit = startBit; - this.lengthBits = lengthBits; - } - - public int getChildCount() { - return childInfos == null ? 0 : childInfos.size(); - } - - public List getChildInfos() { - if (childInfos == null) { - childInfos = new ArrayList<>(); - } - return childInfos; - } - - public void sortChildren() { - if (childInfos == null) { - return; - } - - Collections.sort(childInfos, new Comparator() { - - @Override - public int compare(DumpInfo o1, DumpInfo o2) { - int res = Long.compare(o1.startByte, o2.startByte); - if (res != 0) { - return res; - } - - return Integer.compare(o1.startBit, o1.startBit); - } - }); - } - - public long getEndByte() { - int end = (int) startByte; - if (lengthBytes != 0) { - end += lengthBytes; - } else { - int bits = startBit + lengthBits; - end += bits / 8; - if (bits % 8 != 0) { - end++; - } - } - return end - 1; - } - - @Override - public String toString() { - String value = previewValue == null ? "" : previewValue.toString(); - return name + " (" + type + ")" + (value.isEmpty() ? "" : " = " + value); - } - - public void resolveTag() { - if (tagToResolve != null) { - TagStub tagStub = tagToResolve; - try { - SWFInputStream sis = tagStub.getDataStream(); - sis.seek(tagStub.getDataPos()); - sis.dumpInfo = this; - resolvedTag = SWFInputStream.resolveTag(tagStub, 0, false, true, false); - } catch (InterruptedException | IOException ex) { - Logger.getLogger(DumpInfo.class.getName()).log(Level.SEVERE, null, ex); - } - tagToResolve = null; - } - } - - public Tag getTag() { - resolveTag(); - return resolvedTag; - } - - @Override - public SWF getSwf() { - Tag tag = getTag(); - if (tag != null) { - return tag.getSwf(); - } - - return DumpInfoSwfNode.getSwfNode(this).getSwf(); - } - - @Override - public boolean isModified() { - return false; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.dumpview; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagStub; +import com.jpexs.decompiler.flash.treeitems.TreeItem; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class DumpInfo implements TreeItem { + + public String name; + + public String type; + + public TagStub tagToResolve = null; + + public Tag resolvedTag = null; + + public Object previewValue; + + public long startByte; + + public int startBit; + + public long lengthBytes; + + public int lengthBits; + + public DumpInfo parent; + + private List childInfos; + + public DumpInfo(String name, String type, Object value, long startByte, long lengthBytes) { + + this.name = name; + this.type = type; + this.previewValue = value; + this.startByte = startByte; + this.lengthBytes = lengthBytes; + } + + public DumpInfo(String name, String type, Object value, long startByte, int startBit, long lengthBytes, int lengthBits) { + + this.name = name; + this.type = type; + this.previewValue = value; + this.startByte = startByte; + this.lengthBytes = lengthBytes; + this.startBit = startBit; + this.lengthBits = lengthBits; + } + + public int getChildCount() { + return childInfos == null ? 0 : childInfos.size(); + } + + public List getChildInfos() { + if (childInfos == null) { + childInfos = new ArrayList<>(); + } + return childInfos; + } + + public void sortChildren() { + if (childInfos == null) { + return; + } + + Collections.sort(childInfos, new Comparator() { + + @Override + public int compare(DumpInfo o1, DumpInfo o2) { + int res = Long.compare(o1.startByte, o2.startByte); + if (res != 0) { + return res; + } + + return Integer.compare(o1.startBit, o1.startBit); + } + }); + } + + public long getEndByte() { + int end = (int) startByte; + if (lengthBytes != 0) { + end += lengthBytes; + } else { + int bits = startBit + lengthBits; + end += bits / 8; + if (bits % 8 != 0) { + end++; + } + } + return end - 1; + } + + @Override + public String toString() { + String value = previewValue == null ? "" : previewValue.toString(); + return name + " (" + type + ")" + (value.isEmpty() ? "" : " = " + value); + } + + public void resolveTag() { + if (tagToResolve != null) { + TagStub tagStub = tagToResolve; + try { + SWFInputStream sis = tagStub.getDataStream(); + sis.seek(tagStub.getDataPos()); + sis.dumpInfo = this; + resolvedTag = SWFInputStream.resolveTag(tagStub, 0, false, true, false); + } catch (InterruptedException | IOException ex) { + Logger.getLogger(DumpInfo.class.getName()).log(Level.SEVERE, null, ex); + } + tagToResolve = null; + } + } + + public Tag getTag() { + resolveTag(); + return resolvedTag; + } + + @Override + public SWF getSwf() { + Tag tag = getTag(); + if (tag != null) { + return tag.getSwf(); + } + + return DumpInfoSwfNode.getSwfNode(this).getSwf(); + } + + @Override + public boolean isModified() { + return false; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java index cc92435ef..1f7e90540 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java @@ -1,164 +1,164 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.exporters; - -import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; -import com.jpexs.decompiler.flash.EventListener; -import com.jpexs.decompiler.flash.ReadOnlyTagList; -import com.jpexs.decompiler.flash.RetryTask; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; -import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; -import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings; -import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; -import com.jpexs.decompiler.flash.helpers.BMPFile; -import com.jpexs.decompiler.flash.helpers.ImageHelper; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.base.RenderContext; -import com.jpexs.decompiler.flash.tags.base.ShapeTag; -import com.jpexs.decompiler.flash.tags.enums.ImageFormat; -import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.Path; -import com.jpexs.helpers.SerializableImage; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public class ShapeExporter { - - public List exportShapes(AbortRetryIgnoreHandler handler, final String outdir, ReadOnlyTagList tags, final ShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException { - List ret = new ArrayList<>(); - if (tags.isEmpty()) { - return ret; - } - - File foutdir = new File(outdir); - Path.createDirectorySafe(foutdir); - - int count = 0; - for (Tag t : tags) { - if (t instanceof ShapeTag) { - count++; - } - } - - if (count == 0) { - return ret; - } - - int currentIndex = 1; - for (final Tag t : tags) { - if (t instanceof ShapeTag) { - final ShapeTag st = (ShapeTag) t; - if (evl != null) { - evl.handleExportingEvent("shape", currentIndex, count, t.getName()); - } - - int characterID = st.getCharacterId(); - String ext = ".svg"; - if (settings.mode == ShapeExportMode.PNG) { - ext = ".png"; - } - if (settings.mode == ShapeExportMode.BMP) { - ext = ".bmp"; - } - if (settings.mode == ShapeExportMode.CANVAS) { - ext = ".html"; - } - - final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName() + ext)); - new RetryTask(() -> { - switch (settings.mode) { - case SVG: - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) { - ExportRectangle rect = new ExportRectangle(st.getRect()); - rect.xMax *= settings.zoom; - rect.yMax *= settings.zoom; - rect.xMin *= settings.zoom; - rect.yMin *= settings.zoom; - SVGExporter exporter = new SVGExporter(rect, settings.zoom); - st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0); - fos.write(Utf8Helper.getBytes(exporter.getSVG())); - } - break; - case PNG: - case BMP: - RECT rect = st.getRect(); - int newWidth = (int) (rect.getWidth() * settings.zoom / SWF.unitDivisor) + 1; - int newHeight = (int) (rect.getHeight() * settings.zoom / SWF.unitDivisor) + 1; - SerializableImage img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB_PRE); - img.fillTransparent(); - Matrix m = Matrix.getScaleInstance(settings.zoom); - m.translate(-rect.Xmin, -rect.Ymin); - st.toImage(0, 0, 0, new RenderContext(), img, false, m, m, m, new CXFORMWITHALPHA()); - if (settings.mode == ShapeExportMode.PNG) { - ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, file); - } else { - BMPFile.saveBitmap(img.getBufferedImage(), file); - } - break; - case CANVAS: - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) { - SHAPE shp = st.getShapes(); - int deltaX = -shp.getBounds().Xmin; - int deltaY = -shp.getBounds().Ymin; - CanvasShapeExporter cse = new CanvasShapeExporter(null, SWF.unitDivisor / settings.zoom, ((Tag) st).getSwf(), shp, new CXFORMWITHALPHA(), deltaX, deltaY); - cse.export(); - Set needed = new HashSet<>(); - needed.add(st.getCharacterId()); - st.getNeededCharactersDeep(needed); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWF.writeLibrary(st.getSwf(), needed, baos); - fos.write(Utf8Helper.getBytes(cse.getHtml(new String(baos.toByteArray(), Utf8Helper.charset), SWF.getTypePrefix(st) + st.getCharacterId(), st.getRect()))); - } - break; - } - }, handler).run(); - ret.add(file); - - if (evl != null) { - evl.handleExportedEvent("shape", currentIndex, count, t.getName()); - } - - currentIndex++; - } - } - if (settings.mode == ShapeExportMode.CANVAS) { - File fcanvas = new File(foutdir + File.separator + "canvas.js"); - Helper.saveStream(SWF.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/canvas.js"), fcanvas); - ret.add(fcanvas); - } - return ret; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.exporters; + +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.ReadOnlyTagList; +import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; +import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; +import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings; +import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; +import com.jpexs.decompiler.flash.helpers.BMPFile; +import com.jpexs.decompiler.flash.helpers.ImageHelper; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.RenderContext; +import com.jpexs.decompiler.flash.tags.base.ShapeTag; +import com.jpexs.decompiler.flash.tags.enums.ImageFormat; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Path; +import com.jpexs.helpers.SerializableImage; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * + * @author JPEXS + */ +public class ShapeExporter { + + public List exportShapes(AbortRetryIgnoreHandler handler, final String outdir, ReadOnlyTagList tags, final ShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException { + List ret = new ArrayList<>(); + if (tags.isEmpty()) { + return ret; + } + + File foutdir = new File(outdir); + Path.createDirectorySafe(foutdir); + + int count = 0; + for (Tag t : tags) { + if (t instanceof ShapeTag) { + count++; + } + } + + if (count == 0) { + return ret; + } + + int currentIndex = 1; + for (final Tag t : tags) { + if (t instanceof ShapeTag) { + final ShapeTag st = (ShapeTag) t; + if (evl != null) { + evl.handleExportingEvent("shape", currentIndex, count, t.getName()); + } + + int characterID = st.getCharacterId(); + String ext = ".svg"; + if (settings.mode == ShapeExportMode.PNG) { + ext = ".png"; + } + if (settings.mode == ShapeExportMode.BMP) { + ext = ".bmp"; + } + if (settings.mode == ShapeExportMode.CANVAS) { + ext = ".html"; + } + + final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName() + ext)); + new RetryTask(() -> { + switch (settings.mode) { + case SVG: + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) { + ExportRectangle rect = new ExportRectangle(st.getRect()); + rect.xMax *= settings.zoom; + rect.yMax *= settings.zoom; + rect.xMin *= settings.zoom; + rect.yMin *= settings.zoom; + SVGExporter exporter = new SVGExporter(rect, settings.zoom); + st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0); + fos.write(Utf8Helper.getBytes(exporter.getSVG())); + } + break; + case PNG: + case BMP: + RECT rect = st.getRect(); + int newWidth = (int) (rect.getWidth() * settings.zoom / SWF.unitDivisor) + 1; + int newHeight = (int) (rect.getHeight() * settings.zoom / SWF.unitDivisor) + 1; + SerializableImage img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB_PRE); + img.fillTransparent(); + Matrix m = Matrix.getScaleInstance(settings.zoom); + m.translate(-rect.Xmin, -rect.Ymin); + st.toImage(0, 0, 0, new RenderContext(), img, false, m, m, m, new CXFORMWITHALPHA()); + if (settings.mode == ShapeExportMode.PNG) { + ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, file); + } else { + BMPFile.saveBitmap(img.getBufferedImage(), file); + } + break; + case CANVAS: + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) { + SHAPE shp = st.getShapes(); + int deltaX = -shp.getBounds().Xmin; + int deltaY = -shp.getBounds().Ymin; + CanvasShapeExporter cse = new CanvasShapeExporter(null, SWF.unitDivisor / settings.zoom, ((Tag) st).getSwf(), shp, new CXFORMWITHALPHA(), deltaX, deltaY); + cse.export(); + Set needed = new HashSet<>(); + needed.add(st.getCharacterId()); + st.getNeededCharactersDeep(needed); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWF.writeLibrary(st.getSwf(), needed, baos); + fos.write(Utf8Helper.getBytes(cse.getHtml(new String(baos.toByteArray(), Utf8Helper.charset), SWF.getTypePrefix(st) + st.getCharacterId(), st.getRect()))); + } + break; + } + }, handler).run(); + ret.add(file); + + if (evl != null) { + evl.handleExportedEvent("shape", currentIndex, count, t.getName()); + } + + currentIndex++; + } + } + if (settings.mode == ShapeExportMode.CANVAS) { + File fcanvas = new File(foutdir + File.separator + "canvas.js"); + Helper.saveStream(SWF.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/canvas.js"), fcanvas); + ret.add(fcanvas); + } + return ret; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java index 0a203b52a..bef21beee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java @@ -1,433 +1,433 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.exporters.commonshape; - -import com.jpexs.decompiler.flash.types.MATRIX; -import java.awt.geom.AffineTransform; - -/** - * - * @author JPEXS - */ -public final class Matrix implements Cloneable { - - public double scaleX = 1; - - public double scaleY = 1; - - public double rotateSkew0; - - public double rotateSkew1; - - public double translateX; - - public double translateY; - - public static Matrix getScaleInstance(double scale) { - Matrix mat = new Matrix(); - mat.scale(scale); - return mat; - } - - public static Matrix getTranslateInstance(double x, double y) { - Matrix mat = new Matrix(); - mat.translate(x, y); - return mat; - } - - public Matrix() { - scaleX = 1; - scaleY = 1; - } - - public Matrix(MATRIX matrix) { - if (matrix == null) { - matrix = new MATRIX(); - } - translateX = matrix.translateX; - translateY = matrix.translateY; - if (matrix.hasScale) { - scaleX = matrix.getScaleXFloat(); - scaleY = matrix.getScaleYFloat(); - } else { - scaleX = 1; - scaleY = 1; - } - if (matrix.hasRotate) { - rotateSkew0 = matrix.getRotateSkew0Float(); - rotateSkew1 = matrix.getRotateSkew1Float(); - } - } - - public Matrix(AffineTransform transform) { - this(); - if (transform != null) { - scaleX = transform.getScaleX(); - rotateSkew1 = transform.getShearX(); - translateX = transform.getTranslateX(); - rotateSkew0 = transform.getShearY(); - scaleY = transform.getScaleY(); - translateY = transform.getTranslateY(); - } - } - - @Override - public Matrix clone() { - try { - Matrix mat = (Matrix) super.clone(); - return mat; - } catch (CloneNotSupportedException ex) { - throw new RuntimeException(); - } - } - - public Point transform(double x, double y) { - Point result = new Point( - scaleX * x + rotateSkew1 * y + translateX, - rotateSkew0 * x + scaleY * y + translateY); - return result; - } - - public Point transform(Point point) { - return transform(point.x, point.y); - } - - public Point deltaTransform(double x, double y) { - Point result = new Point( - scaleX * x + rotateSkew1 * y, - rotateSkew0 * x + scaleY * y); - return result; - } - - public Point deltaTransform(Point point) { - return deltaTransform(point.x, point.y); - } - - public java.awt.Point deltaTransform(java.awt.Point point) { - Point p = deltaTransform(point.x, point.y); - return new java.awt.Point((int) p.x, (int) p.y); - } - - public java.awt.Point transform(java.awt.Point point) { - Point p = transform(point.x, point.y); - return new java.awt.Point((int) p.x, (int) p.y); - } - - public ExportRectangle transform(ExportRectangle rect) { - double minX = Double.MAX_VALUE; - double minY = Double.MAX_VALUE; - double maxX = Double.MIN_VALUE; - double maxY = Double.MIN_VALUE; - Point point; - point = transform(rect.xMin, rect.yMin); - if (point.x < minX) { - minX = point.x; - } - if (point.x > maxX) { - maxX = point.x; - } - if (point.y < minY) { - minY = point.y; - } - if (point.y > maxY) { - maxY = point.y; - } - point = transform(rect.xMax, rect.yMin); - if (point.x < minX) { - minX = point.x; - } - if (point.x > maxX) { - maxX = point.x; - } - if (point.y < minY) { - minY = point.y; - } - if (point.y > maxY) { - maxY = point.y; - } - point = transform(rect.xMin, rect.yMax); - if (point.x < minX) { - minX = point.x; - } - if (point.x > maxX) { - maxX = point.x; - } - if (point.y < minY) { - minY = point.y; - } - if (point.y > maxY) { - maxY = point.y; - } - point = transform(rect.xMax, rect.yMax); - if (point.x < minX) { - minX = point.x; - } - if (point.x > maxX) { - maxX = point.x; - } - if (point.y < minY) { - minY = point.y; - } - if (point.y > maxY) { - maxY = point.y; - } - return new ExportRectangle(minX, minY, maxX, maxY); - } - - public void translate(double x, double y) { - translateX = scaleX * x + rotateSkew1 * y + translateX; - translateY = rotateSkew0 * x + scaleY * y + translateY; - } - - public void scale(double factor) { - scaleX *= factor; - scaleY *= factor; - rotateSkew0 *= factor; - rotateSkew1 *= factor; - } - - public Matrix concatenate(Matrix m) { - Matrix result = new Matrix(); - result.scaleX = scaleX * m.scaleX + rotateSkew1 * m.rotateSkew0; - result.rotateSkew0 = rotateSkew0 * m.scaleX + scaleY * m.rotateSkew0; - result.rotateSkew1 = scaleX * m.rotateSkew1 + rotateSkew1 * m.scaleY; - result.scaleY = rotateSkew0 * m.rotateSkew1 + scaleY * m.scaleY; - result.translateX = scaleX * m.translateX + rotateSkew1 * m.translateY + translateX; - result.translateY = rotateSkew0 * m.translateX + scaleY * m.translateY + translateY; - return result; - } - - public Matrix preConcatenate(Matrix m) { - Matrix result = new Matrix(); - result.scaleX = m.scaleX * scaleX + m.rotateSkew1 * rotateSkew0; - result.rotateSkew0 = m.rotateSkew0 * scaleX + m.scaleY * rotateSkew0; - result.rotateSkew1 = m.scaleX * rotateSkew1 + m.rotateSkew1 * scaleY; - result.scaleY = m.rotateSkew0 * rotateSkew1 + m.scaleY * scaleY; - result.translateX = m.scaleX * translateX + m.rotateSkew1 * translateY + m.translateX; - result.translateY = m.rotateSkew0 * translateX + m.scaleY * translateY + m.translateY; - return result; - } - - public AffineTransform toTransform() { - AffineTransform transform = new AffineTransform(scaleX, rotateSkew0, - rotateSkew1, scaleY, - translateX, translateY); - return transform; - } - - public String getSvgTransformationString(double translateDivisor, double unitDivisor) { - double translateX = roundPixels400(this.translateX / translateDivisor); - double translateY = roundPixels400(this.translateY / translateDivisor); - double rotateSkew0 = roundPixels400(this.rotateSkew0 / unitDivisor); - double rotateSkew1 = roundPixels400(this.rotateSkew1 / unitDivisor); - double scaleX = roundPixels400(this.scaleX / unitDivisor); - double scaleY = roundPixels400(this.scaleY / unitDivisor); - return "matrix(" + scaleX + ", " + rotateSkew0 + ", " - + rotateSkew1 + ", " + scaleY + ", " + translateX + ", " + translateY + ")"; - } - - public static String[] parseSvgNumberList(String params) { - while (params.contains(" ")) { - params = params.replaceAll(" ", " "); - } - - params = params.trim(); - params = params.replace(", ", ","); - params = params.replace(" ", ","); - String[] args = params.split(","); - return args; - } - - public static Matrix parseSvgMatrix(String transformStr, double translateDivisor, double unitDivisor) { - Matrix ret = new Matrix(); - while (transformStr != null && transformStr.length() > 0) { - String funcName = transformStr.split("\\(")[0]; - transformStr = transformStr.substring(funcName.length() + 1); - String params = transformStr.split("\\)")[0]; - transformStr = transformStr.substring(params.length() + 1).trim(); - String[] args = parseSvgNumberList(params); - funcName = funcName.trim(); - switch (funcName) { - case "matrix": - if (args.length == 6) { - double scaleX = Double.parseDouble(args[0].trim()); - double rotateSkew0 = Double.parseDouble(args[1].trim()); - double rotateSkew1 = Double.parseDouble(args[2].trim()); - double scaleY = Double.parseDouble(args[3].trim()); - double translateX = Double.parseDouble(args[4].trim()); - double translateY = Double.parseDouble(args[5].trim()); - Matrix result = new Matrix(); - result.translateX = translateX; - result.translateY = translateY; - result.rotateSkew0 = rotateSkew0; - result.rotateSkew1 = rotateSkew1; - result.scaleX = scaleX; - result.scaleY = scaleY; - ret = ret.concatenate(result); - } - break; - case "translate": - if (args.length == 1 || args.length == 2) { - double translateX = Double.parseDouble(args[0].trim()); - double translateY = 0; - if (args.length == 2) { - translateY = Double.parseDouble(args[1].trim()); - } - - Matrix result = new Matrix(); - result.translateX = translateX; - result.translateY = translateY; - ret = ret.concatenate(result); - } - break; - case "scale": - if (args.length == 1 || args.length == 2) { - double scaleX = Double.parseDouble(args[0].trim()); - double scaleY = scaleX; - if (args.length == 2) { - scaleY = Double.parseDouble(args[1].trim()); - } - - Matrix result = new Matrix(); - result.scaleX = scaleX; - result.scaleY = scaleY; - ret = ret.concatenate(result); - } - break; - case "skewX": - if (args.length == 1) { - double angle = Double.parseDouble(args[0].trim()) * Math.PI / 180; - - Matrix result = new Matrix(); - result.rotateSkew1 = Math.tan(angle); - ret = ret.concatenate(result); - } - break; - case "skewY": - if (args.length == 1) { - double angle = Double.parseDouble(args[0].trim()) * Math.PI / 180; - - Matrix result = new Matrix(); - result.rotateSkew0 = Math.tan(angle); - ret = ret.concatenate(result); - } - break; - case "rotate": - if (args.length == 1 || args.length == 3) { - double rotateAngle = Double.parseDouble(args[0].trim()); - double tx = 0; - double ty = 0; - if (args.length > 1) { - tx = Double.parseDouble(args[1].trim()); - ty = Double.parseDouble(args[2].trim()); - } - - double angleRad = -rotateAngle * Math.PI / 180; - Matrix result = new Matrix(); - result.rotateSkew0 = -Math.sin(angleRad); - result.rotateSkew1 = Math.sin(angleRad); - result.scaleX = Math.cos(angleRad); - result.scaleY = Math.cos(angleRad); - result = result.preConcatenate(getTranslateInstance(tx, ty)) - .concatenate(getTranslateInstance(-tx, -ty)); - ret = ret.concatenate(result); - } - break; - } - } - - ret.translateX *= translateDivisor; - ret.translateY *= translateDivisor; - ret.rotateSkew0 *= unitDivisor; - ret.rotateSkew1 *= unitDivisor; - ret.scaleX *= unitDivisor; - ret.scaleY *= unitDivisor; - return ret; - } - - private double roundPixels400(double pixels) { - return Math.round(pixels * 10000) / 10000.0; - } - - @Override - public String toString() { - return "[Matrix scale:" + scaleX + "," + scaleY + ", rotate:" + rotateSkew0 + "," + rotateSkew1 + ", translate:" + translateX + "," + translateY + "]"; - } - - public Matrix inverse() { - double a = scaleX; - double b = rotateSkew1; - double tx = translateX; - double c = rotateSkew0; - double d = scaleY; - double ty = translateY; - - double det = a * d - b * c; - - double a2 = d / det; - double b2 = -b / det; - double tx2 = (b * ty - tx * d) / det; - double c2 = -c / det; - double d2 = a / det; - double ty2 = (tx * c - a * ty) / det; - - Matrix ret = new Matrix(); - ret.scaleX = a2; - ret.rotateSkew0 = c2; - ret.rotateSkew1 = b2; - ret.scaleY = d2; - ret.translateX = tx2; - ret.translateY = ty2; - return ret; - } - - public double getTotalSkewAngleX() { - Point px = deltaTransform(new Point(0, 1)); - return ((180 / Math.PI) * Math.atan2(px.y, px.x) - 90); - } - - public double getTotalSkewAngleY() { - Point py = deltaTransform(new Point(1, 0)); - return ((180 / Math.PI) * Math.atan2(py.y, py.x)); - } - - public double getTotalScaleX() { - return Math.sqrt(scaleX * scaleX + rotateSkew0 * rotateSkew0); - } - - public double getTotalScaleY() { - return Math.sqrt(rotateSkew1 * rotateSkew1 + scaleY * scaleY); - } - - private int fromFloat(double f) { - return (int) (f * (1 << 16)); - } - - public MATRIX toMATRIX() { - MATRIX result = new MATRIX(); - - result.translateX = (int) translateX; - result.translateY = (int) translateY; - result.hasRotate = true; - result.hasScale = true; - result.scaleX = fromFloat(scaleX); - result.scaleY = fromFloat(scaleY); - result.rotateSkew0 = fromFloat(rotateSkew0); - result.rotateSkew1 = fromFloat(rotateSkew1); - return result; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.exporters.commonshape; + +import com.jpexs.decompiler.flash.types.MATRIX; +import java.awt.geom.AffineTransform; + +/** + * + * @author JPEXS + */ +public final class Matrix implements Cloneable { + + public double scaleX = 1; + + public double scaleY = 1; + + public double rotateSkew0; + + public double rotateSkew1; + + public double translateX; + + public double translateY; + + public static Matrix getScaleInstance(double scale) { + Matrix mat = new Matrix(); + mat.scale(scale); + return mat; + } + + public static Matrix getTranslateInstance(double x, double y) { + Matrix mat = new Matrix(); + mat.translate(x, y); + return mat; + } + + public Matrix() { + scaleX = 1; + scaleY = 1; + } + + public Matrix(MATRIX matrix) { + if (matrix == null) { + matrix = new MATRIX(); + } + translateX = matrix.translateX; + translateY = matrix.translateY; + if (matrix.hasScale) { + scaleX = matrix.getScaleXFloat(); + scaleY = matrix.getScaleYFloat(); + } else { + scaleX = 1; + scaleY = 1; + } + if (matrix.hasRotate) { + rotateSkew0 = matrix.getRotateSkew0Float(); + rotateSkew1 = matrix.getRotateSkew1Float(); + } + } + + public Matrix(AffineTransform transform) { + this(); + if (transform != null) { + scaleX = transform.getScaleX(); + rotateSkew1 = transform.getShearX(); + translateX = transform.getTranslateX(); + rotateSkew0 = transform.getShearY(); + scaleY = transform.getScaleY(); + translateY = transform.getTranslateY(); + } + } + + @Override + public Matrix clone() { + try { + Matrix mat = (Matrix) super.clone(); + return mat; + } catch (CloneNotSupportedException ex) { + throw new RuntimeException(); + } + } + + public Point transform(double x, double y) { + Point result = new Point( + scaleX * x + rotateSkew1 * y + translateX, + rotateSkew0 * x + scaleY * y + translateY); + return result; + } + + public Point transform(Point point) { + return transform(point.x, point.y); + } + + public Point deltaTransform(double x, double y) { + Point result = new Point( + scaleX * x + rotateSkew1 * y, + rotateSkew0 * x + scaleY * y); + return result; + } + + public Point deltaTransform(Point point) { + return deltaTransform(point.x, point.y); + } + + public java.awt.Point deltaTransform(java.awt.Point point) { + Point p = deltaTransform(point.x, point.y); + return new java.awt.Point((int) p.x, (int) p.y); + } + + public java.awt.Point transform(java.awt.Point point) { + Point p = transform(point.x, point.y); + return new java.awt.Point((int) p.x, (int) p.y); + } + + public ExportRectangle transform(ExportRectangle rect) { + double minX = Double.MAX_VALUE; + double minY = Double.MAX_VALUE; + double maxX = Double.MIN_VALUE; + double maxY = Double.MIN_VALUE; + Point point; + point = transform(rect.xMin, rect.yMin); + if (point.x < minX) { + minX = point.x; + } + if (point.x > maxX) { + maxX = point.x; + } + if (point.y < minY) { + minY = point.y; + } + if (point.y > maxY) { + maxY = point.y; + } + point = transform(rect.xMax, rect.yMin); + if (point.x < minX) { + minX = point.x; + } + if (point.x > maxX) { + maxX = point.x; + } + if (point.y < minY) { + minY = point.y; + } + if (point.y > maxY) { + maxY = point.y; + } + point = transform(rect.xMin, rect.yMax); + if (point.x < minX) { + minX = point.x; + } + if (point.x > maxX) { + maxX = point.x; + } + if (point.y < minY) { + minY = point.y; + } + if (point.y > maxY) { + maxY = point.y; + } + point = transform(rect.xMax, rect.yMax); + if (point.x < minX) { + minX = point.x; + } + if (point.x > maxX) { + maxX = point.x; + } + if (point.y < minY) { + minY = point.y; + } + if (point.y > maxY) { + maxY = point.y; + } + return new ExportRectangle(minX, minY, maxX, maxY); + } + + public void translate(double x, double y) { + translateX = scaleX * x + rotateSkew1 * y + translateX; + translateY = rotateSkew0 * x + scaleY * y + translateY; + } + + public void scale(double factor) { + scaleX *= factor; + scaleY *= factor; + rotateSkew0 *= factor; + rotateSkew1 *= factor; + } + + public Matrix concatenate(Matrix m) { + Matrix result = new Matrix(); + result.scaleX = scaleX * m.scaleX + rotateSkew1 * m.rotateSkew0; + result.rotateSkew0 = rotateSkew0 * m.scaleX + scaleY * m.rotateSkew0; + result.rotateSkew1 = scaleX * m.rotateSkew1 + rotateSkew1 * m.scaleY; + result.scaleY = rotateSkew0 * m.rotateSkew1 + scaleY * m.scaleY; + result.translateX = scaleX * m.translateX + rotateSkew1 * m.translateY + translateX; + result.translateY = rotateSkew0 * m.translateX + scaleY * m.translateY + translateY; + return result; + } + + public Matrix preConcatenate(Matrix m) { + Matrix result = new Matrix(); + result.scaleX = m.scaleX * scaleX + m.rotateSkew1 * rotateSkew0; + result.rotateSkew0 = m.rotateSkew0 * scaleX + m.scaleY * rotateSkew0; + result.rotateSkew1 = m.scaleX * rotateSkew1 + m.rotateSkew1 * scaleY; + result.scaleY = m.rotateSkew0 * rotateSkew1 + m.scaleY * scaleY; + result.translateX = m.scaleX * translateX + m.rotateSkew1 * translateY + m.translateX; + result.translateY = m.rotateSkew0 * translateX + m.scaleY * translateY + m.translateY; + return result; + } + + public AffineTransform toTransform() { + AffineTransform transform = new AffineTransform(scaleX, rotateSkew0, + rotateSkew1, scaleY, + translateX, translateY); + return transform; + } + + public String getSvgTransformationString(double translateDivisor, double unitDivisor) { + double translateX = roundPixels400(this.translateX / translateDivisor); + double translateY = roundPixels400(this.translateY / translateDivisor); + double rotateSkew0 = roundPixels400(this.rotateSkew0 / unitDivisor); + double rotateSkew1 = roundPixels400(this.rotateSkew1 / unitDivisor); + double scaleX = roundPixels400(this.scaleX / unitDivisor); + double scaleY = roundPixels400(this.scaleY / unitDivisor); + return "matrix(" + scaleX + ", " + rotateSkew0 + ", " + + rotateSkew1 + ", " + scaleY + ", " + translateX + ", " + translateY + ")"; + } + + public static String[] parseSvgNumberList(String params) { + while (params.contains(" ")) { + params = params.replaceAll(" ", " "); + } + + params = params.trim(); + params = params.replace(", ", ","); + params = params.replace(" ", ","); + String[] args = params.split(","); + return args; + } + + public static Matrix parseSvgMatrix(String transformStr, double translateDivisor, double unitDivisor) { + Matrix ret = new Matrix(); + while (transformStr != null && transformStr.length() > 0) { + String funcName = transformStr.split("\\(")[0]; + transformStr = transformStr.substring(funcName.length() + 1); + String params = transformStr.split("\\)")[0]; + transformStr = transformStr.substring(params.length() + 1).trim(); + String[] args = parseSvgNumberList(params); + funcName = funcName.trim(); + switch (funcName) { + case "matrix": + if (args.length == 6) { + double scaleX = Double.parseDouble(args[0].trim()); + double rotateSkew0 = Double.parseDouble(args[1].trim()); + double rotateSkew1 = Double.parseDouble(args[2].trim()); + double scaleY = Double.parseDouble(args[3].trim()); + double translateX = Double.parseDouble(args[4].trim()); + double translateY = Double.parseDouble(args[5].trim()); + Matrix result = new Matrix(); + result.translateX = translateX; + result.translateY = translateY; + result.rotateSkew0 = rotateSkew0; + result.rotateSkew1 = rotateSkew1; + result.scaleX = scaleX; + result.scaleY = scaleY; + ret = ret.concatenate(result); + } + break; + case "translate": + if (args.length == 1 || args.length == 2) { + double translateX = Double.parseDouble(args[0].trim()); + double translateY = 0; + if (args.length == 2) { + translateY = Double.parseDouble(args[1].trim()); + } + + Matrix result = new Matrix(); + result.translateX = translateX; + result.translateY = translateY; + ret = ret.concatenate(result); + } + break; + case "scale": + if (args.length == 1 || args.length == 2) { + double scaleX = Double.parseDouble(args[0].trim()); + double scaleY = scaleX; + if (args.length == 2) { + scaleY = Double.parseDouble(args[1].trim()); + } + + Matrix result = new Matrix(); + result.scaleX = scaleX; + result.scaleY = scaleY; + ret = ret.concatenate(result); + } + break; + case "skewX": + if (args.length == 1) { + double angle = Double.parseDouble(args[0].trim()) * Math.PI / 180; + + Matrix result = new Matrix(); + result.rotateSkew1 = Math.tan(angle); + ret = ret.concatenate(result); + } + break; + case "skewY": + if (args.length == 1) { + double angle = Double.parseDouble(args[0].trim()) * Math.PI / 180; + + Matrix result = new Matrix(); + result.rotateSkew0 = Math.tan(angle); + ret = ret.concatenate(result); + } + break; + case "rotate": + if (args.length == 1 || args.length == 3) { + double rotateAngle = Double.parseDouble(args[0].trim()); + double tx = 0; + double ty = 0; + if (args.length > 1) { + tx = Double.parseDouble(args[1].trim()); + ty = Double.parseDouble(args[2].trim()); + } + + double angleRad = -rotateAngle * Math.PI / 180; + Matrix result = new Matrix(); + result.rotateSkew0 = -Math.sin(angleRad); + result.rotateSkew1 = Math.sin(angleRad); + result.scaleX = Math.cos(angleRad); + result.scaleY = Math.cos(angleRad); + result = result.preConcatenate(getTranslateInstance(tx, ty)) + .concatenate(getTranslateInstance(-tx, -ty)); + ret = ret.concatenate(result); + } + break; + } + } + + ret.translateX *= translateDivisor; + ret.translateY *= translateDivisor; + ret.rotateSkew0 *= unitDivisor; + ret.rotateSkew1 *= unitDivisor; + ret.scaleX *= unitDivisor; + ret.scaleY *= unitDivisor; + return ret; + } + + private double roundPixels400(double pixels) { + return Math.round(pixels * 10000) / 10000.0; + } + + @Override + public String toString() { + return "[Matrix scale:" + scaleX + "," + scaleY + ", rotate:" + rotateSkew0 + "," + rotateSkew1 + ", translate:" + translateX + "," + translateY + "]"; + } + + public Matrix inverse() { + double a = scaleX; + double b = rotateSkew1; + double tx = translateX; + double c = rotateSkew0; + double d = scaleY; + double ty = translateY; + + double det = a * d - b * c; + + double a2 = d / det; + double b2 = -b / det; + double tx2 = (b * ty - tx * d) / det; + double c2 = -c / det; + double d2 = a / det; + double ty2 = (tx * c - a * ty) / det; + + Matrix ret = new Matrix(); + ret.scaleX = a2; + ret.rotateSkew0 = c2; + ret.rotateSkew1 = b2; + ret.scaleY = d2; + ret.translateX = tx2; + ret.translateY = ty2; + return ret; + } + + public double getTotalSkewAngleX() { + Point px = deltaTransform(new Point(0, 1)); + return ((180 / Math.PI) * Math.atan2(px.y, px.x) - 90); + } + + public double getTotalSkewAngleY() { + Point py = deltaTransform(new Point(1, 0)); + return ((180 / Math.PI) * Math.atan2(py.y, py.x)); + } + + public double getTotalScaleX() { + return Math.sqrt(scaleX * scaleX + rotateSkew0 * rotateSkew0); + } + + public double getTotalScaleY() { + return Math.sqrt(rotateSkew1 * rotateSkew1 + scaleY * scaleY); + } + + private int fromFloat(double f) { + return (int) (f * (1 << 16)); + } + + public MATRIX toMATRIX() { + MATRIX result = new MATRIX(); + + result.translateX = (int) translateX; + result.translateY = (int) translateY; + result.hasRotate = true; + result.hasScale = true; + result.scaleX = fromFloat(scaleX); + result.scaleY = fromFloat(scaleY); + result.rotateSkew0 = fromFloat(rotateSkew0); + result.rotateSkew1 = fromFloat(rotateSkew1); + return result; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/NulWriter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/NulWriter.java index 2b8252896..bd5d93f3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/NulWriter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/NulWriter.java @@ -1,162 +1,162 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.helpers; - -import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import java.util.Stack; - -/** - * Provides methods for highlighting positions of instructions in the text. - * - * @author JPEXS - */ -public class NulWriter extends GraphTextWriter { - - private final Stack loopStack = new Stack<>(); - - private final Stack stringAddedStack = new Stack<>(); - - private boolean stringAdded = false; - - public NulWriter() { - super(new CodeFormatting()); - } - - public void startLoop(long loopId, int loopType) { - LoopWithType loop = new LoopWithType(); - loop.loopId = loopId; - loop.type = loopType; - loopStack.add(loop); - } - - public LoopWithType endLoop(long loopId) { - LoopWithType loopIdInStack = loopStack.pop(); - if (loopId != loopIdInStack.loopId) { - throw new Error("LoopId mismatch"); - } - return loopIdInStack; - } - - public long getLoop() { - if (loopStack.isEmpty()) { - return -1; - } - return loopStack.peek().loopId; - } - - public long getNonSwitchLoop() { - if (loopStack.isEmpty()) { - return -1; - } - - int pos = loopStack.size() - 1; - LoopWithType loop; - do { - loop = loopStack.get(pos); - pos--; - } while ((pos >= 0) && (loop.type == LoopWithType.LOOP_TYPE_SWITCH)); - - if (loop.type == LoopWithType.LOOP_TYPE_SWITCH) { - return -1; - } - - return loop.loopId; - } - - public void setLoopUsed(long loopId) { - if (loopStack.isEmpty()) { - return; - } - - int pos = loopStack.size() - 1; - LoopWithType loop = null; - do { - loop = loopStack.get(pos); - pos--; - } while ((pos >= 0) && (loop.loopId != loopId)); - - if (loop.loopId == loopId) { - loop.used = true; - } - } - - @Override - public NulWriter hilightSpecial(String text, HighlightSpecialType type, String specialValue, HighlightData data) { - stringAdded = true; - return this; - } - - @Override - public GraphTextWriter append(char value) { - stringAdded = true; - return this; - } - - @Override - public GraphTextWriter append(int value) { - stringAdded = true; - return this; - } - - @Override - public GraphTextWriter append(long value) { - stringAdded = true; - return this; - } - - @Override - public NulWriter append(String str) { - stringAdded = true; - return this; - } - - @Override - public GraphTextWriter appendWithData(String str, HighlightData data) { - stringAdded = true; - return this; - } - - @Override - public NulWriter append(String str, long offset, long fileOffset) { - stringAdded = true; - return this; - } - - @Override - public NulWriter appendNoHilight(int i) { - stringAdded = true; - return this; - } - - @Override - public NulWriter appendNoHilight(String str) { - stringAdded = true; - return this; - } - - public void mark() { - stringAddedStack.add(stringAdded); - stringAdded = false; - } - - public boolean getMark() { - boolean result = stringAdded; - stringAdded = stringAddedStack.pop() || result; - return result; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.helpers; + +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import java.util.Stack; + +/** + * Provides methods for highlighting positions of instructions in the text. + * + * @author JPEXS + */ +public class NulWriter extends GraphTextWriter { + + private final Stack loopStack = new Stack<>(); + + private final Stack stringAddedStack = new Stack<>(); + + private boolean stringAdded = false; + + public NulWriter() { + super(new CodeFormatting()); + } + + public void startLoop(long loopId, int loopType) { + LoopWithType loop = new LoopWithType(); + loop.loopId = loopId; + loop.type = loopType; + loopStack.add(loop); + } + + public LoopWithType endLoop(long loopId) { + LoopWithType loopIdInStack = loopStack.pop(); + if (loopId != loopIdInStack.loopId) { + throw new Error("LoopId mismatch"); + } + return loopIdInStack; + } + + public long getLoop() { + if (loopStack.isEmpty()) { + return -1; + } + return loopStack.peek().loopId; + } + + public long getNonSwitchLoop() { + if (loopStack.isEmpty()) { + return -1; + } + + int pos = loopStack.size() - 1; + LoopWithType loop; + do { + loop = loopStack.get(pos); + pos--; + } while ((pos >= 0) && (loop.type == LoopWithType.LOOP_TYPE_SWITCH)); + + if (loop.type == LoopWithType.LOOP_TYPE_SWITCH) { + return -1; + } + + return loop.loopId; + } + + public void setLoopUsed(long loopId) { + if (loopStack.isEmpty()) { + return; + } + + int pos = loopStack.size() - 1; + LoopWithType loop = null; + do { + loop = loopStack.get(pos); + pos--; + } while ((pos >= 0) && (loop.loopId != loopId)); + + if (loop.loopId == loopId) { + loop.used = true; + } + } + + @Override + public NulWriter hilightSpecial(String text, HighlightSpecialType type, String specialValue, HighlightData data) { + stringAdded = true; + return this; + } + + @Override + public GraphTextWriter append(char value) { + stringAdded = true; + return this; + } + + @Override + public GraphTextWriter append(int value) { + stringAdded = true; + return this; + } + + @Override + public GraphTextWriter append(long value) { + stringAdded = true; + return this; + } + + @Override + public NulWriter append(String str) { + stringAdded = true; + return this; + } + + @Override + public GraphTextWriter appendWithData(String str, HighlightData data) { + stringAdded = true; + return this; + } + + @Override + public NulWriter append(String str, long offset, long fileOffset) { + stringAdded = true; + return this; + } + + @Override + public NulWriter appendNoHilight(int i) { + stringAdded = true; + return this; + } + + @Override + public NulWriter appendNoHilight(String str) { + stringAdded = true; + return this; + } + + public void mark() { + stringAddedStack.add(stringAdded); + stringAdded = false; + } + + public boolean getMark() { + boolean result = stringAdded; + stringAdded = stringAddedStack.pop() || result; + return result; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties index ce6af2bd8..d15c905c2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties @@ -1,38 +1,38 @@ -# Copyright (C) 2010-2016 JPEXS, All rights reserved. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 3.0 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. - -decompilationError = Decompilation error -decompilationError.timeout = Timeout ({0}) was reached -decompilationError.timeout.description = Not decompiled due to timeout -decompilationError.obfuscated = Code may be obfuscated -decompilationError.errorType = Error type -decompilationError.error.description = Not decompiled due to error -decompilationError.actionCount = Action count: -decompilationError.instructionCount = Instruction count: - -decompilation.skipped = Decompilation skipped -decompilation.unsupported = Unsupported by decompiler -decompilerMark = decompiler mark - -#example: 1 hour and 2 minutes -timeFormat.and = and -timeFormat.hour = hour -timeFormat.hours = hours -timeFormat.minute = minute -timeFormat.minutes = minutes -timeFormat.second = second -timeFormat.seconds = seconds - -fontNotFound = Font with id=%fontId% was not found. +# Copyright (C) 2010-2016 JPEXS, All rights reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3.0 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. + +decompilationError = Decompilation error +decompilationError.timeout = Timeout ({0}) was reached +decompilationError.timeout.description = Not decompiled due to timeout +decompilationError.obfuscated = Code may be obfuscated +decompilationError.errorType = Error type +decompilationError.error.description = Not decompiled due to error +decompilationError.actionCount = Action count: +decompilationError.instructionCount = Instruction count: + +decompilation.skipped = Decompilation skipped +decompilation.unsupported = Unsupported by decompiler +decompilerMark = decompiler mark + +#example: 1 hour and 2 minutes +timeFormat.and = and +timeFormat.hour = hour +timeFormat.hours = hours +timeFormat.minute = minute +timeFormat.minutes = minutes +timeFormat.second = second +timeFormat.seconds = seconds + +fontNotFound = Font with id=%fontId% was not found. diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java index 6a700163b..05bf32095 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java @@ -1,585 +1,585 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.helpers.FontHelper; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.annotations.Conditional; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.Font; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 3) -public class DefineFont2Tag extends FontTag { - - public static final int ID = 48; - - public static final String NAME = "DefineFont2"; - - @SWFType(BasicType.UI16) - public int fontID; - - public boolean fontFlagsHasLayout; - - public boolean fontFlagsShiftJIS; - - public boolean fontFlagsSmallText; - - public boolean fontFlagsANSI; - - public boolean fontFlagsWideOffsets; - - public boolean fontFlagsWideCodes; - - public boolean fontFlagsItalic; - - public boolean fontFlagsBold; - - public LANGCODE languageCode; - - public String fontName; - - public List glyphShapeTable; - - @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") - public List codeTable; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontAscent; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontDescent; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public int fontLeading; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public List fontAdvanceTable; - - @Conditional("fontFlagsHasLayout") - public List fontBoundsTable; - - @Conditional("fontFlagsHasLayout") - public List fontKerningTable; - - /** - * Constructor - * - * @param swf - */ - public DefineFont2Tag(SWF swf) { - super(swf, ID, NAME, null); - fontID = swf.getNextCharacterId(); - languageCode = new LANGCODE(); - fontName = "New font"; - glyphShapeTable = new ArrayList<>(); - codeTable = new ArrayList<>(); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public DefineFont2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - fontID = sis.readUI16("fontId"); - fontFlagsHasLayout = sis.readUB(1, "fontFlagsHasLayout") == 1; - fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; - fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; - fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; - fontFlagsWideOffsets = sis.readUB(1, "fontFlagsWideOffsets") == 1; - fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; - fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; - fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; - languageCode = sis.readLANGCODE("languageCode"); - if (swf.version >= 6) { - fontName = sis.readNetString("fontName", Utf8Helper.charset); - } else { - fontName = sis.readNetString("fontName"); - } - int numGlyphs = sis.readUI16("numGlyphs"); - long[] offsetTable = new long[numGlyphs]; - long pos = sis.getPos(); - for (int i = 0; i < numGlyphs; i++) { //offsetTable - if (fontFlagsWideOffsets) { - offsetTable[i] = sis.readUI32("offset"); - } else { - offsetTable[i] = sis.readUI16("offset"); - } - } - if (numGlyphs > 0) { //codeTableOffset - if (fontFlagsWideOffsets) { - sis.readUI32("codeTableOffset"); - } else { - sis.readUI16("codeTableOffset"); - } - } - - glyphShapeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - sis.seek(pos + offsetTable[i]); - glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); - } - - codeTable = new ArrayList<>(); //[numGlyphs]; - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - codeTable.add(sis.readUI16("code")); - } else { - codeTable.add(sis.readUI8("code")); - } - } - - if (fontFlagsHasLayout) { - fontAscent = sis.readUI16("fontAscent"); - fontDescent = sis.readUI16("fontDescent"); - fontLeading = sis.readSI16("fontLeading"); - fontAdvanceTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontAdvanceTable.add(sis.readSI16("fontAdvance")); - } - fontBoundsTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontBoundsTable.add(sis.readRECT("rect")); - } - int kerningCount = sis.readUI16("kerningCount"); - fontKerningTable = new ArrayList<>(); - for (int i = 0; i < kerningCount; i++) { - fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record")); - } - } - } - - private void checkWideParameters() { - int numGlyphs = glyphShapeTable.size(); - - if (!fontFlagsWideOffsets) { - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); - for (int i = 0; i < numGlyphs; i++) { - long offset = ((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos()); - if (offset > 0xffff) { - fontFlagsWideOffsets = true; - checkWideParameters(); - return; - } - try { - sos3.writeSHAPE(glyphShapeTable.get(i), 1); - } catch (IOException ex) { - //should not happen - return; - } - } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); - - if (numGlyphs > 0) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (offset > 0xffff) { - fontFlagsWideOffsets = true; - checkWideParameters(); - return; - } - } - } - - if (!fontFlagsWideCodes) { - for (int i = 0; i < numGlyphs; i++) { - long code = codeTable.get(i); - if (code > 0xffff) { - fontFlagsWideCodes = true; - } - } - } - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - checkWideParameters(); - sos.writeUI16(fontID); - sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeLANGCODE(languageCode); - if (swf.version >= 6) { - sos.writeNetString(fontName, Utf8Helper.charset); - } else { - sos.writeNetString(fontName); - } - int numGlyphs = glyphShapeTable.size(); - sos.writeUI16(numGlyphs); - - List offsetTable = new ArrayList<>(); - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); - for (int i = 0; i < numGlyphs; i++) { - offsetTable.add((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos()); - sos3.writeSHAPE(glyphShapeTable.get(i), 1); - } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); - for (Long offset : offsetTable) { - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) (long) offset); - } - } - if (numGlyphs > 0) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) offset); - } - sos.write(baGlyphShapes); - - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - sos.writeUI16(codeTable.get(i)); - } else { - sos.writeUI8(codeTable.get(i)); - } - } - } - if (fontFlagsHasLayout) { - sos.writeSI16(fontAscent); - sos.writeSI16(fontDescent); - sos.writeSI16(fontLeading); - for (int i = 0; i < numGlyphs; i++) { - sos.writeSI16(fontAdvanceTable.get(i)); - } - for (int i = 0; i < numGlyphs; i++) { - sos.writeRECT(fontBoundsTable.get(i)); - } - sos.writeUI16(fontKerningTable.size()); - for (int k = 0; k < fontKerningTable.size(); k++) { - sos.writeKERNINGRECORD(fontKerningTable.get(k), fontFlagsWideCodes); - } - } - } - - @Override - public boolean isSmall() { - return fontFlagsSmallText; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); - } - - @Override - public RECT getGlyphBounds(int glyphIndex) { - if (fontFlagsHasLayout) { - return fontBoundsTable.get(glyphIndex); - } - return super.getGlyphBounds(glyphIndex); - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - if (fontFlagsHasLayout) { - return fontAdvanceTable.get(glyphIndex); - } else { - return -1; - } - } - - @Override - public List getGlyphShapeTable() { - return glyphShapeTable; - } - - @Override - public int getCharacterId() { - return fontID; - } - - @Override - public void setCharacterId(int characterId) { - this.fontID = characterId; - } - - @Override - public char glyphToChar(int glyphIndex) { - return (char) (int) codeTable.get(glyphIndex); - } - - @Override - public int charToGlyph(char c) { - return codeTable.indexOf((int) c); - } - - @Override - public String getFontNameIntag() { - String ret = fontName; - if (ret.contains("" + (char) 0)) { - ret = ret.substring(0, ret.indexOf(0)); - } - return ret; - } - - @Override - public boolean isBold() { - return fontFlagsBold; - } - - @Override - public boolean isItalic() { - return fontFlagsItalic; - } - - @Override - public boolean isSmallEditable() { - return true; - } - - @Override - public boolean isBoldEditable() { - return true; - } - - @Override - public boolean isItalicEditable() { - return true; - } - - @Override - public void setSmall(boolean value) { - fontFlagsSmallText = value; - } - - @Override - public void setBold(boolean value) { - fontFlagsBold = value; - } - - @Override - public void setItalic(boolean value) { - fontFlagsItalic = value; - } - - @Override - public double getDivider() { - return 1; - } - - @Override - public int getAscent() { - if (fontFlagsHasLayout) { - return fontAscent; - } - return -1; - } - - @Override - public int getDescent() { - if (fontFlagsHasLayout) { - return fontDescent; - } - return -1; - } - - @Override - public int getLeading() { - if (fontFlagsHasLayout) { - return fontLeading; - } - return -1; - } - - @Override - public void addCharacter(char character, Font font) { - int fontStyle = getFontStyle(); - - SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); - - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = codeTable.size(); - } - - if (!exists) { - shiftGlyphIndices(fontID, pos, true); - glyphShapeTable.add(pos, shp); - codeTable.add(pos, (int) character); - } else { - glyphShapeTable.set(pos, shp); - } - - if (fontFlagsHasLayout) { - Font fnt = new Font(fontName, fontStyle, 1024); - if (!exists) { - fontBoundsTable.add(pos, shp.getBounds()); - fontAdvanceTable.add(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); - } else { - fontBoundsTable.set(pos, shp.getBounds()); - fontAdvanceTable.set(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); - } - } - - checkWideParameters(); - setModified(true); - getSwf().clearImageCache(); - } - - @Override - public boolean removeCharacter(char character) { - int code = (int) character; - int pos = -1; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - pos = i; - break; - } - - return false; - } - } - - if (pos == -1) { - return false; - } - - glyphShapeTable.remove(pos); - codeTable.remove(pos); - - if (fontFlagsHasLayout) { - fontBoundsTable.remove(pos); - fontAdvanceTable.remove(pos); - } - - shiftGlyphIndices(fontID, pos + 1, false); - - checkWideParameters(); - setModified(true); - getSwf().clearImageCache(); - return true; - } - - @Override - public void setAdvanceValues(Font font) { - boolean hasLayout = fontFlagsHasLayout; - fontFlagsHasLayout = true; - fontAdvanceTable = new ArrayList<>(); - if (!hasLayout) { - fontBoundsTable = new ArrayList<>(); - fontKerningTable = new ArrayList<>(); - } - - for (Integer character : codeTable) { - char ch = (char) (int) character; - SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), ch); - fontBoundsTable.add(shp.getBounds()); - int fontStyle = getFontStyle(); - Font fnt = new Font(font.getFontName(), fontStyle, 1024); // Not multiplied with divider as it causes problems to create font with height around 20k - fontAdvanceTable.add((int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, ch))); - } - } - - @Override - public int getCharacterCount() { - return codeTable.size(); - } - - @Override - public String getCharacters() { - StringBuilder ret = new StringBuilder(codeTable.size()); - for (int i : codeTable) { - ret.append((char) i); - } - return ret.toString(); - } - - @Override - public boolean hasLayout() { - return fontFlagsHasLayout; - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - char c1 = glyphToChar(glyphIndex); - char c2 = glyphToChar(nextGlyphIndex); - return getCharKerningAdjustment(c1, c2); - } - - @Override - public int getCharKerningAdjustment(char c1, char c2) { - int kerningAdjustment = 0; - for (KERNINGRECORD ker : fontKerningTable) { - if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { - kerningAdjustment = ker.fontKerningAdjustment; - break; - } - } - return kerningAdjustment; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.helpers.FontHelper; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.Font; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 3) +public class DefineFont2Tag extends FontTag { + + public static final int ID = 48; + + public static final String NAME = "DefineFont2"; + + @SWFType(BasicType.UI16) + public int fontID; + + public boolean fontFlagsHasLayout; + + public boolean fontFlagsShiftJIS; + + public boolean fontFlagsSmallText; + + public boolean fontFlagsANSI; + + public boolean fontFlagsWideOffsets; + + public boolean fontFlagsWideCodes; + + public boolean fontFlagsItalic; + + public boolean fontFlagsBold; + + public LANGCODE languageCode; + + public String fontName; + + public List glyphShapeTable; + + @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") + public List codeTable; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontAscent; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontDescent; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public int fontLeading; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public List fontAdvanceTable; + + @Conditional("fontFlagsHasLayout") + public List fontBoundsTable; + + @Conditional("fontFlagsHasLayout") + public List fontKerningTable; + + /** + * Constructor + * + * @param swf + */ + public DefineFont2Tag(SWF swf) { + super(swf, ID, NAME, null); + fontID = swf.getNextCharacterId(); + languageCode = new LANGCODE(); + fontName = "New font"; + glyphShapeTable = new ArrayList<>(); + codeTable = new ArrayList<>(); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public DefineFont2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + fontID = sis.readUI16("fontId"); + fontFlagsHasLayout = sis.readUB(1, "fontFlagsHasLayout") == 1; + fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; + fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; + fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; + fontFlagsWideOffsets = sis.readUB(1, "fontFlagsWideOffsets") == 1; + fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; + fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; + fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; + languageCode = sis.readLANGCODE("languageCode"); + if (swf.version >= 6) { + fontName = sis.readNetString("fontName", Utf8Helper.charset); + } else { + fontName = sis.readNetString("fontName"); + } + int numGlyphs = sis.readUI16("numGlyphs"); + long[] offsetTable = new long[numGlyphs]; + long pos = sis.getPos(); + for (int i = 0; i < numGlyphs; i++) { //offsetTable + if (fontFlagsWideOffsets) { + offsetTable[i] = sis.readUI32("offset"); + } else { + offsetTable[i] = sis.readUI16("offset"); + } + } + if (numGlyphs > 0) { //codeTableOffset + if (fontFlagsWideOffsets) { + sis.readUI32("codeTableOffset"); + } else { + sis.readUI16("codeTableOffset"); + } + } + + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + sis.seek(pos + offsetTable[i]); + glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); + } + + codeTable = new ArrayList<>(); //[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + codeTable.add(sis.readUI16("code")); + } else { + codeTable.add(sis.readUI8("code")); + } + } + + if (fontFlagsHasLayout) { + fontAscent = sis.readUI16("fontAscent"); + fontDescent = sis.readUI16("fontDescent"); + fontLeading = sis.readSI16("fontLeading"); + fontAdvanceTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontAdvanceTable.add(sis.readSI16("fontAdvance")); + } + fontBoundsTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontBoundsTable.add(sis.readRECT("rect")); + } + int kerningCount = sis.readUI16("kerningCount"); + fontKerningTable = new ArrayList<>(); + for (int i = 0; i < kerningCount; i++) { + fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record")); + } + } + } + + private void checkWideParameters() { + int numGlyphs = glyphShapeTable.size(); + + if (!fontFlagsWideOffsets) { + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); + for (int i = 0; i < numGlyphs; i++) { + long offset = ((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos()); + if (offset > 0xffff) { + fontFlagsWideOffsets = true; + checkWideParameters(); + return; + } + try { + sos3.writeSHAPE(glyphShapeTable.get(i), 1); + } catch (IOException ex) { + //should not happen + return; + } + } + byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); + + if (numGlyphs > 0) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (offset > 0xffff) { + fontFlagsWideOffsets = true; + checkWideParameters(); + return; + } + } + } + + if (!fontFlagsWideCodes) { + for (int i = 0; i < numGlyphs; i++) { + long code = codeTable.get(i); + if (code > 0xffff) { + fontFlagsWideCodes = true; + } + } + } + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + checkWideParameters(); + sos.writeUI16(fontID); + sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeLANGCODE(languageCode); + if (swf.version >= 6) { + sos.writeNetString(fontName, Utf8Helper.charset); + } else { + sos.writeNetString(fontName); + } + int numGlyphs = glyphShapeTable.size(); + sos.writeUI16(numGlyphs); + + List offsetTable = new ArrayList<>(); + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); + for (int i = 0; i < numGlyphs; i++) { + offsetTable.add((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos()); + sos3.writeSHAPE(glyphShapeTable.get(i), 1); + } + byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); + for (Long offset : offsetTable) { + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) (long) offset); + } + } + if (numGlyphs > 0) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) offset); + } + sos.write(baGlyphShapes); + + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + sos.writeUI16(codeTable.get(i)); + } else { + sos.writeUI8(codeTable.get(i)); + } + } + } + if (fontFlagsHasLayout) { + sos.writeSI16(fontAscent); + sos.writeSI16(fontDescent); + sos.writeSI16(fontLeading); + for (int i = 0; i < numGlyphs; i++) { + sos.writeSI16(fontAdvanceTable.get(i)); + } + for (int i = 0; i < numGlyphs; i++) { + sos.writeRECT(fontBoundsTable.get(i)); + } + sos.writeUI16(fontKerningTable.size()); + for (int k = 0; k < fontKerningTable.size(); k++) { + sos.writeKERNINGRECORD(fontKerningTable.get(k), fontFlagsWideCodes); + } + } + } + + @Override + public boolean isSmall() { + return fontFlagsSmallText; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); + } + + @Override + public RECT getGlyphBounds(int glyphIndex) { + if (fontFlagsHasLayout) { + return fontBoundsTable.get(glyphIndex); + } + return super.getGlyphBounds(glyphIndex); + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + if (fontFlagsHasLayout) { + return fontAdvanceTable.get(glyphIndex); + } else { + return -1; + } + } + + @Override + public List getGlyphShapeTable() { + return glyphShapeTable; + } + + @Override + public int getCharacterId() { + return fontID; + } + + @Override + public void setCharacterId(int characterId) { + this.fontID = characterId; + } + + @Override + public char glyphToChar(int glyphIndex) { + return (char) (int) codeTable.get(glyphIndex); + } + + @Override + public int charToGlyph(char c) { + return codeTable.indexOf((int) c); + } + + @Override + public String getFontNameIntag() { + String ret = fontName; + if (ret.contains("" + (char) 0)) { + ret = ret.substring(0, ret.indexOf(0)); + } + return ret; + } + + @Override + public boolean isBold() { + return fontFlagsBold; + } + + @Override + public boolean isItalic() { + return fontFlagsItalic; + } + + @Override + public boolean isSmallEditable() { + return true; + } + + @Override + public boolean isBoldEditable() { + return true; + } + + @Override + public boolean isItalicEditable() { + return true; + } + + @Override + public void setSmall(boolean value) { + fontFlagsSmallText = value; + } + + @Override + public void setBold(boolean value) { + fontFlagsBold = value; + } + + @Override + public void setItalic(boolean value) { + fontFlagsItalic = value; + } + + @Override + public double getDivider() { + return 1; + } + + @Override + public int getAscent() { + if (fontFlagsHasLayout) { + return fontAscent; + } + return -1; + } + + @Override + public int getDescent() { + if (fontFlagsHasLayout) { + return fontDescent; + } + return -1; + } + + @Override + public int getLeading() { + if (fontFlagsHasLayout) { + return fontLeading; + } + return -1; + } + + @Override + public void addCharacter(char character, Font font) { + int fontStyle = getFontStyle(); + + SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); + + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = codeTable.size(); + } + + if (!exists) { + shiftGlyphIndices(fontID, pos, true); + glyphShapeTable.add(pos, shp); + codeTable.add(pos, (int) character); + } else { + glyphShapeTable.set(pos, shp); + } + + if (fontFlagsHasLayout) { + Font fnt = new Font(fontName, fontStyle, 1024); + if (!exists) { + fontBoundsTable.add(pos, shp.getBounds()); + fontAdvanceTable.add(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); + } else { + fontBoundsTable.set(pos, shp.getBounds()); + fontAdvanceTable.set(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); + } + } + + checkWideParameters(); + setModified(true); + getSwf().clearImageCache(); + } + + @Override + public boolean removeCharacter(char character) { + int code = (int) character; + int pos = -1; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + pos = i; + break; + } + + return false; + } + } + + if (pos == -1) { + return false; + } + + glyphShapeTable.remove(pos); + codeTable.remove(pos); + + if (fontFlagsHasLayout) { + fontBoundsTable.remove(pos); + fontAdvanceTable.remove(pos); + } + + shiftGlyphIndices(fontID, pos + 1, false); + + checkWideParameters(); + setModified(true); + getSwf().clearImageCache(); + return true; + } + + @Override + public void setAdvanceValues(Font font) { + boolean hasLayout = fontFlagsHasLayout; + fontFlagsHasLayout = true; + fontAdvanceTable = new ArrayList<>(); + if (!hasLayout) { + fontBoundsTable = new ArrayList<>(); + fontKerningTable = new ArrayList<>(); + } + + for (Integer character : codeTable) { + char ch = (char) (int) character; + SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), ch); + fontBoundsTable.add(shp.getBounds()); + int fontStyle = getFontStyle(); + Font fnt = new Font(font.getFontName(), fontStyle, 1024); // Not multiplied with divider as it causes problems to create font with height around 20k + fontAdvanceTable.add((int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, ch))); + } + } + + @Override + public int getCharacterCount() { + return codeTable.size(); + } + + @Override + public String getCharacters() { + StringBuilder ret = new StringBuilder(codeTable.size()); + for (int i : codeTable) { + ret.append((char) i); + } + return ret.toString(); + } + + @Override + public boolean hasLayout() { + return fontFlagsHasLayout; + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + char c1 = glyphToChar(glyphIndex); + char c2 = glyphToChar(nextGlyphIndex); + return getCharKerningAdjustment(c1, c2); + } + + @Override + public int getCharKerningAdjustment(char c1, char c2) { + int kerningAdjustment = 0; + for (KERNINGRECORD ker : fontKerningTable) { + if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { + kerningAdjustment = ker.fontKerningAdjustment; + break; + } + } + return kerningAdjustment; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java index 195b40409..5f113c6de 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java @@ -1,601 +1,601 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.helpers.FontHelper; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.annotations.Conditional; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.Font; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 8) -public class DefineFont3Tag extends FontTag { - - public static final int ID = 75; - - public static final String NAME = "DefineFont3"; - - @SWFType(BasicType.UI16) - public int fontID; - - public boolean fontFlagsHasLayout; - - public boolean fontFlagsShiftJIS; - - public boolean fontFlagsSmallText; - - public boolean fontFlagsANSI; - - public boolean fontFlagsWideOffsets; - - public boolean fontFlagsWideCodes; - - public boolean fontFlagsItalic; - - public boolean fontFlagsBold; - - public LANGCODE languageCode; - - public String fontName; - - public List glyphShapeTable; - - @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") - public List codeTable; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontAscent; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontDescent; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public int fontLeading; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public List fontAdvanceTable; - - @Conditional("fontFlagsHasLayout") - public List fontBoundsTable; - - @Conditional("fontFlagsHasLayout") - public List fontKerningTable; - - /** - * Constructor - * - * @param swf - */ - public DefineFont3Tag(SWF swf) { - super(swf, ID, NAME, null); - fontID = swf.getNextCharacterId(); - languageCode = new LANGCODE(); - fontName = "New font"; - glyphShapeTable = new ArrayList<>(); - codeTable = new ArrayList<>(); - } - - public DefineFont3Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - fontID = sis.readUI16("fontId"); - fontFlagsHasLayout = sis.readUB(1, "fontFlagsHasLayout") == 1; - fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; - fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; - fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; - fontFlagsWideOffsets = sis.readUB(1, "fontFlagsWideOffsets") == 1; - fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; - fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; - fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; - languageCode = sis.readLANGCODE("languageCode"); - if (swf.version >= 6) { - fontName = sis.readNetString("fontName", Utf8Helper.charset); - } else { - fontName = sis.readNetString("fontName"); - } - int numGlyphs = sis.readUI16("numGlyphs"); - long[] offsetTable = new long[numGlyphs]; - long pos = sis.getPos(); - for (int i = 0; i < numGlyphs; i++) { //offsetTable - if (fontFlagsWideOffsets) { - offsetTable[i] = sis.readUI32("offset"); - } else { - offsetTable[i] = sis.readUI16("offset"); - } - } - if (numGlyphs > 0) { - if (fontFlagsWideOffsets) { - sis.readUI32("codeTableOffset"); //codeTableOffset - } else { - sis.readUI16("codeTableOffset"); //codeTableOffset - } - } - glyphShapeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - sis.seek(pos + offsetTable[i]); - glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); - } - codeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - codeTable.add(sis.readUI16("code")); - } else { - codeTable.add(sis.readUI8("code")); - } - } - if (fontFlagsHasLayout) { - fontAscent = sis.readUI16("fontAscent"); - fontDescent = sis.readUI16("fontDescent"); - fontLeading = sis.readSI16("fontLeading"); - fontAdvanceTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontAdvanceTable.add(sis.readSI16("fontAdvance")); - } - fontBoundsTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontBoundsTable.add(sis.readRECT("rect")); - } - int kerningCount = sis.readUI16("kerningCount"); - fontKerningTable = new ArrayList<>(); - for (int i = 0; i < kerningCount; i++) { - fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record")); - } - } - } - - private void checkWideParameters() { - int numGlyphs = glyphShapeTable.size(); - - if (!fontFlagsWideOffsets) { - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); - for (int i = 0; i < numGlyphs; i++) { - long offset = (glyphShapeTable.size()) * 2 + sos3.getPos(); - if (offset > 0xffff) { - fontFlagsWideOffsets = true; - checkWideParameters(); - return; - } - try { - sos3.writeSHAPE(glyphShapeTable.get(i), 1); - } catch (IOException ex) { - //should not happen - return; - } - } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); - - if (numGlyphs > 0) { - long maxOffset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * 2 + baGlyphShapes.length; - if (maxOffset > 0xffff) { - fontFlagsWideOffsets = true; - checkWideParameters(); - return; - } - } - } - - if (!fontFlagsWideCodes) { - for (int i = 0; i < numGlyphs; i++) { - long code = codeTable.get(i); - if (code > 0xffff) { - fontFlagsWideCodes = true; - } - } - } - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - checkWideParameters(); - List offsetTable = new ArrayList<>(); - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); - int numGlyphs = glyphShapeTable.size(); - for (int i = 0; i < numGlyphs; i++) { - offsetTable.add(sos3.getPos()); - sos3.writeSHAPE(glyphShapeTable.get(i), 1); - } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); - - sos.writeUI16(fontID); - sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeLANGCODE(languageCode); - if (swf.version >= 6) { - sos.writeNetString(fontName, Utf8Helper.charset); - } else { - sos.writeNetString(fontName); - } - sos.writeUI16(numGlyphs); - - for (long offset : offsetTable) { - long offset2 = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + offset; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset2); - } else { - sos.writeUI16((int) offset2); - } - } - if (numGlyphs > 0) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) offset); - } - sos.write(baGlyphShapes); - - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - sos.writeUI16(codeTable.get(i)); - } else { - sos.writeUI8(codeTable.get(i)); - } - } - } - if (fontFlagsHasLayout) { - sos.writeSI16(fontAscent); - sos.writeSI16(fontDescent); - sos.writeSI16(fontLeading); - for (int i = 0; i < numGlyphs; i++) { - sos.writeSI16(fontAdvanceTable.get(i)); - } - for (int i = 0; i < numGlyphs; i++) { - sos.writeRECT(fontBoundsTable.get(i)); - } - sos.writeUI16(fontKerningTable.size()); - for (int k = 0; k < fontKerningTable.size(); k++) { - sos.writeKERNINGRECORD(fontKerningTable.get(k), fontFlagsWideCodes); - } - } - } - - @Override - public boolean isSmall() { - return fontFlagsSmallText; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - if (fontFlagsHasLayout && glyphIndex != -1) { - return fontAdvanceTable.get(glyphIndex); - } else { - return -1; - } - } - - @Override - public char glyphToChar(int glyphIndex) { - return (char) (int) codeTable.get(glyphIndex); - } - - @Override - public int charToGlyph(char c) { - return codeTable.indexOf((int) c); - } - - @Override - public List getGlyphShapeTable() { - return glyphShapeTable; - } - - @Override - public int getCharacterId() { - return fontID; - } - - @Override - public void setCharacterId(int characterId) { - this.fontID = characterId; - } - - @Override - public String getFontNameIntag() { - String ret = fontName; - if (ret.contains("" + (char) 0)) { - ret = ret.substring(0, ret.indexOf(0)); - } - return ret; - } - - @Override - public boolean isBold() { - return fontFlagsBold; - } - - @Override - public boolean isItalic() { - return fontFlagsItalic; - } - - @Override - public boolean isSmallEditable() { - return true; - } - - @Override - public boolean isBoldEditable() { - return true; - } - - @Override - public boolean isItalicEditable() { - return true; - } - - @Override - public void setSmall(boolean value) { - fontFlagsSmallText = value; - } - - @Override - public void setBold(boolean value) { - fontFlagsBold = value; - } - - @Override - public void setItalic(boolean value) { - fontFlagsItalic = value; - } - - @Override - public double getDivider() { - return 20; - } - - @Override - public int getAscent() { - if (fontFlagsHasLayout) { - return fontAscent; - } - return -1; - } - - @Override - public int getDescent() { - if (fontFlagsHasLayout) { - return fontDescent; - } - return -1; - } - - @Override - public int getLeading() { - if (fontFlagsHasLayout) { - return fontLeading; - } - return -1; - } - - @Override - public void addCharacter(char character, Font font) { - - //Font Align Zones will be removed as adding new character zones is not supported:-( - for (int i = 0; i < swf.getTags().size(); i++) { - Tag t = swf.getTags().get(i); - if (t instanceof DefineFontAlignZonesTag) { - DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t; - if (fa.fontID == fontID) { - swf.removeTag(t); - i--; - } - } - } - int fontStyle = getFontStyle(); - SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = codeTable.size(); - } - - if (!exists) { - shiftGlyphIndices(fontID, pos, true); - glyphShapeTable.add(pos, shp); - codeTable.add(pos, (int) character); - } else { - glyphShapeTable.set(pos, shp); - } - if (fontFlagsHasLayout) { - - Font fnt = new Font(fontName, fontStyle, 1024); // Not multiplied with divider as it causes problems to create font with height around 20k - if (!exists) { - fontBoundsTable.add(pos, shp.getBounds()); - fontAdvanceTable.add(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); - } else { - fontBoundsTable.set(pos, shp.getBounds()); - fontAdvanceTable.set(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); - } - } - - checkWideParameters(); - setModified(true); - getSwf().clearImageCache(); - } - - @Override - public boolean removeCharacter(char character) { - - //Font Align Zones will be removed as removing character zones is not supported:-( - for (int i = 0; i < swf.getTags().size(); i++) { - Tag t = swf.getTags().get(i); - if (t instanceof DefineFontAlignZonesTag) { - DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t; - if (fa.fontID == fontID) { - swf.removeTag(t); - i--; - } - } - } - - int code = (int) character; - int pos = -1; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - pos = i; - break; - } - - return false; - } - } - if (pos == -1) { - return false; - } - - glyphShapeTable.remove(pos); - codeTable.remove(pos); - - if (fontFlagsHasLayout) { - fontBoundsTable.remove(pos); - fontAdvanceTable.remove(pos); - } - - shiftGlyphIndices(fontID, pos + 1, false); - - checkWideParameters(); - setModified(true); - getSwf().clearImageCache(); - return true; - } - - @Override - public void setAdvanceValues(Font font) { - boolean hasLayout = fontFlagsHasLayout; - fontFlagsHasLayout = true; - fontAdvanceTable = new ArrayList<>(); - if (!hasLayout) { - fontBoundsTable = new ArrayList<>(); - fontKerningTable = new ArrayList<>(); - } - - for (Integer character : codeTable) { - char ch = (char) (int) character; - SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), ch); - fontBoundsTable.add(shp.getBounds()); - int fontStyle = getFontStyle(); - Font fnt = new Font(font.getFontName(), fontStyle, 1024); // Not multiplied with divider as it causes problems to create font with height around 20k - fontAdvanceTable.add((int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, ch))); - } - } - - @Override - public int getCharacterCount() { - return codeTable.size(); - } - - @Override - public String getCharacters() { - StringBuilder ret = new StringBuilder(codeTable.size()); - for (int i : codeTable) { - ret.append((char) i); - } - return ret.toString(); - } - - @Override - public boolean hasLayout() { - return fontFlagsHasLayout; - } - - @Override - public RECT getGlyphBounds(int glyphIndex) { - if (fontFlagsHasLayout) { - return fontBoundsTable.get(glyphIndex); - } - return super.getGlyphBounds(glyphIndex); - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - if (glyphIndex == -1 || nextGlyphIndex == -1) { - return 0; - } - char c1 = glyphToChar(glyphIndex); - char c2 = glyphToChar(nextGlyphIndex); - return getCharKerningAdjustment(c1, c2); - } - - @Override - public int getCharKerningAdjustment(char c1, char c2) { - int kerningAdjustment = 0; - for (KERNINGRECORD ker : fontKerningTable) { - if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { - kerningAdjustment = ker.fontKerningAdjustment; - break; - } - } - return kerningAdjustment; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.helpers.FontHelper; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.Font; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 8) +public class DefineFont3Tag extends FontTag { + + public static final int ID = 75; + + public static final String NAME = "DefineFont3"; + + @SWFType(BasicType.UI16) + public int fontID; + + public boolean fontFlagsHasLayout; + + public boolean fontFlagsShiftJIS; + + public boolean fontFlagsSmallText; + + public boolean fontFlagsANSI; + + public boolean fontFlagsWideOffsets; + + public boolean fontFlagsWideCodes; + + public boolean fontFlagsItalic; + + public boolean fontFlagsBold; + + public LANGCODE languageCode; + + public String fontName; + + public List glyphShapeTable; + + @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") + public List codeTable; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontAscent; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontDescent; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public int fontLeading; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public List fontAdvanceTable; + + @Conditional("fontFlagsHasLayout") + public List fontBoundsTable; + + @Conditional("fontFlagsHasLayout") + public List fontKerningTable; + + /** + * Constructor + * + * @param swf + */ + public DefineFont3Tag(SWF swf) { + super(swf, ID, NAME, null); + fontID = swf.getNextCharacterId(); + languageCode = new LANGCODE(); + fontName = "New font"; + glyphShapeTable = new ArrayList<>(); + codeTable = new ArrayList<>(); + } + + public DefineFont3Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + fontID = sis.readUI16("fontId"); + fontFlagsHasLayout = sis.readUB(1, "fontFlagsHasLayout") == 1; + fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; + fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; + fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; + fontFlagsWideOffsets = sis.readUB(1, "fontFlagsWideOffsets") == 1; + fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; + fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; + fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; + languageCode = sis.readLANGCODE("languageCode"); + if (swf.version >= 6) { + fontName = sis.readNetString("fontName", Utf8Helper.charset); + } else { + fontName = sis.readNetString("fontName"); + } + int numGlyphs = sis.readUI16("numGlyphs"); + long[] offsetTable = new long[numGlyphs]; + long pos = sis.getPos(); + for (int i = 0; i < numGlyphs; i++) { //offsetTable + if (fontFlagsWideOffsets) { + offsetTable[i] = sis.readUI32("offset"); + } else { + offsetTable[i] = sis.readUI16("offset"); + } + } + if (numGlyphs > 0) { + if (fontFlagsWideOffsets) { + sis.readUI32("codeTableOffset"); //codeTableOffset + } else { + sis.readUI16("codeTableOffset"); //codeTableOffset + } + } + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + sis.seek(pos + offsetTable[i]); + glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); + } + codeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + codeTable.add(sis.readUI16("code")); + } else { + codeTable.add(sis.readUI8("code")); + } + } + if (fontFlagsHasLayout) { + fontAscent = sis.readUI16("fontAscent"); + fontDescent = sis.readUI16("fontDescent"); + fontLeading = sis.readSI16("fontLeading"); + fontAdvanceTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontAdvanceTable.add(sis.readSI16("fontAdvance")); + } + fontBoundsTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontBoundsTable.add(sis.readRECT("rect")); + } + int kerningCount = sis.readUI16("kerningCount"); + fontKerningTable = new ArrayList<>(); + for (int i = 0; i < kerningCount; i++) { + fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record")); + } + } + } + + private void checkWideParameters() { + int numGlyphs = glyphShapeTable.size(); + + if (!fontFlagsWideOffsets) { + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); + for (int i = 0; i < numGlyphs; i++) { + long offset = (glyphShapeTable.size()) * 2 + sos3.getPos(); + if (offset > 0xffff) { + fontFlagsWideOffsets = true; + checkWideParameters(); + return; + } + try { + sos3.writeSHAPE(glyphShapeTable.get(i), 1); + } catch (IOException ex) { + //should not happen + return; + } + } + byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); + + if (numGlyphs > 0) { + long maxOffset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * 2 + baGlyphShapes.length; + if (maxOffset > 0xffff) { + fontFlagsWideOffsets = true; + checkWideParameters(); + return; + } + } + } + + if (!fontFlagsWideCodes) { + for (int i = 0; i < numGlyphs; i++) { + long code = codeTable.get(i); + if (code > 0xffff) { + fontFlagsWideCodes = true; + } + } + } + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + checkWideParameters(); + List offsetTable = new ArrayList<>(); + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); + int numGlyphs = glyphShapeTable.size(); + for (int i = 0; i < numGlyphs; i++) { + offsetTable.add(sos3.getPos()); + sos3.writeSHAPE(glyphShapeTable.get(i), 1); + } + byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); + + sos.writeUI16(fontID); + sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeLANGCODE(languageCode); + if (swf.version >= 6) { + sos.writeNetString(fontName, Utf8Helper.charset); + } else { + sos.writeNetString(fontName); + } + sos.writeUI16(numGlyphs); + + for (long offset : offsetTable) { + long offset2 = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + offset; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset2); + } else { + sos.writeUI16((int) offset2); + } + } + if (numGlyphs > 0) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) offset); + } + sos.write(baGlyphShapes); + + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + sos.writeUI16(codeTable.get(i)); + } else { + sos.writeUI8(codeTable.get(i)); + } + } + } + if (fontFlagsHasLayout) { + sos.writeSI16(fontAscent); + sos.writeSI16(fontDescent); + sos.writeSI16(fontLeading); + for (int i = 0; i < numGlyphs; i++) { + sos.writeSI16(fontAdvanceTable.get(i)); + } + for (int i = 0; i < numGlyphs; i++) { + sos.writeRECT(fontBoundsTable.get(i)); + } + sos.writeUI16(fontKerningTable.size()); + for (int k = 0; k < fontKerningTable.size(); k++) { + sos.writeKERNINGRECORD(fontKerningTable.get(k), fontFlagsWideCodes); + } + } + } + + @Override + public boolean isSmall() { + return fontFlagsSmallText; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + if (fontFlagsHasLayout && glyphIndex != -1) { + return fontAdvanceTable.get(glyphIndex); + } else { + return -1; + } + } + + @Override + public char glyphToChar(int glyphIndex) { + return (char) (int) codeTable.get(glyphIndex); + } + + @Override + public int charToGlyph(char c) { + return codeTable.indexOf((int) c); + } + + @Override + public List getGlyphShapeTable() { + return glyphShapeTable; + } + + @Override + public int getCharacterId() { + return fontID; + } + + @Override + public void setCharacterId(int characterId) { + this.fontID = characterId; + } + + @Override + public String getFontNameIntag() { + String ret = fontName; + if (ret.contains("" + (char) 0)) { + ret = ret.substring(0, ret.indexOf(0)); + } + return ret; + } + + @Override + public boolean isBold() { + return fontFlagsBold; + } + + @Override + public boolean isItalic() { + return fontFlagsItalic; + } + + @Override + public boolean isSmallEditable() { + return true; + } + + @Override + public boolean isBoldEditable() { + return true; + } + + @Override + public boolean isItalicEditable() { + return true; + } + + @Override + public void setSmall(boolean value) { + fontFlagsSmallText = value; + } + + @Override + public void setBold(boolean value) { + fontFlagsBold = value; + } + + @Override + public void setItalic(boolean value) { + fontFlagsItalic = value; + } + + @Override + public double getDivider() { + return 20; + } + + @Override + public int getAscent() { + if (fontFlagsHasLayout) { + return fontAscent; + } + return -1; + } + + @Override + public int getDescent() { + if (fontFlagsHasLayout) { + return fontDescent; + } + return -1; + } + + @Override + public int getLeading() { + if (fontFlagsHasLayout) { + return fontLeading; + } + return -1; + } + + @Override + public void addCharacter(char character, Font font) { + + //Font Align Zones will be removed as adding new character zones is not supported:-( + for (int i = 0; i < swf.getTags().size(); i++) { + Tag t = swf.getTags().get(i); + if (t instanceof DefineFontAlignZonesTag) { + DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t; + if (fa.fontID == fontID) { + swf.removeTag(t); + i--; + } + } + } + int fontStyle = getFontStyle(); + SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = codeTable.size(); + } + + if (!exists) { + shiftGlyphIndices(fontID, pos, true); + glyphShapeTable.add(pos, shp); + codeTable.add(pos, (int) character); + } else { + glyphShapeTable.set(pos, shp); + } + if (fontFlagsHasLayout) { + + Font fnt = new Font(fontName, fontStyle, 1024); // Not multiplied with divider as it causes problems to create font with height around 20k + if (!exists) { + fontBoundsTable.add(pos, shp.getBounds()); + fontAdvanceTable.add(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); + } else { + fontBoundsTable.set(pos, shp.getBounds()); + fontAdvanceTable.set(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character))); + } + } + + checkWideParameters(); + setModified(true); + getSwf().clearImageCache(); + } + + @Override + public boolean removeCharacter(char character) { + + //Font Align Zones will be removed as removing character zones is not supported:-( + for (int i = 0; i < swf.getTags().size(); i++) { + Tag t = swf.getTags().get(i); + if (t instanceof DefineFontAlignZonesTag) { + DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t; + if (fa.fontID == fontID) { + swf.removeTag(t); + i--; + } + } + } + + int code = (int) character; + int pos = -1; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + pos = i; + break; + } + + return false; + } + } + if (pos == -1) { + return false; + } + + glyphShapeTable.remove(pos); + codeTable.remove(pos); + + if (fontFlagsHasLayout) { + fontBoundsTable.remove(pos); + fontAdvanceTable.remove(pos); + } + + shiftGlyphIndices(fontID, pos + 1, false); + + checkWideParameters(); + setModified(true); + getSwf().clearImageCache(); + return true; + } + + @Override + public void setAdvanceValues(Font font) { + boolean hasLayout = fontFlagsHasLayout; + fontFlagsHasLayout = true; + fontAdvanceTable = new ArrayList<>(); + if (!hasLayout) { + fontBoundsTable = new ArrayList<>(); + fontKerningTable = new ArrayList<>(); + } + + for (Integer character : codeTable) { + char ch = (char) (int) character; + SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), ch); + fontBoundsTable.add(shp.getBounds()); + int fontStyle = getFontStyle(); + Font fnt = new Font(font.getFontName(), fontStyle, 1024); // Not multiplied with divider as it causes problems to create font with height around 20k + fontAdvanceTable.add((int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, ch))); + } + } + + @Override + public int getCharacterCount() { + return codeTable.size(); + } + + @Override + public String getCharacters() { + StringBuilder ret = new StringBuilder(codeTable.size()); + for (int i : codeTable) { + ret.append((char) i); + } + return ret.toString(); + } + + @Override + public boolean hasLayout() { + return fontFlagsHasLayout; + } + + @Override + public RECT getGlyphBounds(int glyphIndex) { + if (fontFlagsHasLayout) { + return fontBoundsTable.get(glyphIndex); + } + return super.getGlyphBounds(glyphIndex); + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + if (glyphIndex == -1 || nextGlyphIndex == -1) { + return 0; + } + char c1 = glyphToChar(glyphIndex); + char c2 = glyphToChar(nextGlyphIndex); + return getCharKerningAdjustment(c1, c2); + } + + @Override + public int getCharKerningAdjustment(char c1, char c2) { + int kerningAdjustment = 0; + for (KERNINGRECORD ker : fontKerningTable) { + if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { + kerningAdjustment = ker.fontKerningAdjustment; + break; + } + } + return kerningAdjustment; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java index 10a79b9c9..dc599f5b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java @@ -1,183 +1,183 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.FontInfoTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 6) -public class DefineFontInfo2Tag extends FontInfoTag { - - public static final int ID = 62; - - public static final String NAME = "DefineFontInfo2"; - - public String fontName; - - @Reserved - @SWFType(value = BasicType.UB, count = 2) - public int reserved; - - public boolean fontFlagsSmallText; - - public boolean fontFlagsShiftJIS; - - public boolean fontFlagsANSI; - - public boolean fontFlagsItalic; - - public boolean fontFlagsBold; - - public boolean fontFlagsWideCodes; //always 1 - - public LANGCODE languageCode; - - @SWFType(BasicType.UI16) - public List codeTable; - - /** - * Constructor - * - * @param swf - */ - public DefineFontInfo2Tag(SWF swf) { - super(swf, ID, NAME, null); - fontName = "New Font Info Name"; - languageCode = new LANGCODE(); - codeTable = new ArrayList<>(); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public DefineFontInfo2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - fontID = sis.readUI16("fontID"); - if (swf.version >= 6) { - fontName = sis.readNetString("fontName", Utf8Helper.charset); - } else { - fontName = sis.readNetString("fontName"); - } - reserved = (int) sis.readUB(2, "reserved"); - fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; - fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; - fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; - fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; - fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; - fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; //Always 1 - languageCode = sis.readLANGCODE("languageCode"); - int ctLen = sis.available() / 2; - codeTable = new ArrayList<>(); - for (int i = 0; i < ctLen; i++) { - codeTable.add(sis.readUI16("code")); - } - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - sos.writeUI16(fontID); - if (swf.version >= 6) { - sos.writeNetString(fontName, Utf8Helper.charset); - } else { - sos.writeNetString(fontName); - } - sos.writeUB(2, reserved); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - sos.writeLANGCODE(languageCode); - for (int c : codeTable) { - sos.writeUI16(c); - } - } - - @Override - public List getCodeTable() { - return codeTable; - } - - @Override - public void addFontCharacter(int index, int character) { - codeTable.add(index, character); - setModified(true); - } - - @Override - public void removeFontCharacter(int index) { - codeTable.remove(index); - setModified(true); - } - - @Override - public String getFontName() { - return fontName; - } - - @Override - public boolean getFontFlagsBold() { - return fontFlagsBold; - } - - @Override - public void setFontFlagsBold(boolean value) { - fontFlagsBold = value; - } - - @Override - public boolean getFontFlagsItalic() { - return fontFlagsItalic; - } - - @Override - public void setFontFlagsItalic(boolean value) { - fontFlagsItalic = value; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.FontInfoTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 6) +public class DefineFontInfo2Tag extends FontInfoTag { + + public static final int ID = 62; + + public static final String NAME = "DefineFontInfo2"; + + public String fontName; + + @Reserved + @SWFType(value = BasicType.UB, count = 2) + public int reserved; + + public boolean fontFlagsSmallText; + + public boolean fontFlagsShiftJIS; + + public boolean fontFlagsANSI; + + public boolean fontFlagsItalic; + + public boolean fontFlagsBold; + + public boolean fontFlagsWideCodes; //always 1 + + public LANGCODE languageCode; + + @SWFType(BasicType.UI16) + public List codeTable; + + /** + * Constructor + * + * @param swf + */ + public DefineFontInfo2Tag(SWF swf) { + super(swf, ID, NAME, null); + fontName = "New Font Info Name"; + languageCode = new LANGCODE(); + codeTable = new ArrayList<>(); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public DefineFontInfo2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + fontID = sis.readUI16("fontID"); + if (swf.version >= 6) { + fontName = sis.readNetString("fontName", Utf8Helper.charset); + } else { + fontName = sis.readNetString("fontName"); + } + reserved = (int) sis.readUB(2, "reserved"); + fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; + fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; + fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; + fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; + fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; + fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; //Always 1 + languageCode = sis.readLANGCODE("languageCode"); + int ctLen = sis.available() / 2; + codeTable = new ArrayList<>(); + for (int i = 0; i < ctLen; i++) { + codeTable.add(sis.readUI16("code")); + } + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + sos.writeUI16(fontID); + if (swf.version >= 6) { + sos.writeNetString(fontName, Utf8Helper.charset); + } else { + sos.writeNetString(fontName); + } + sos.writeUB(2, reserved); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + sos.writeLANGCODE(languageCode); + for (int c : codeTable) { + sos.writeUI16(c); + } + } + + @Override + public List getCodeTable() { + return codeTable; + } + + @Override + public void addFontCharacter(int index, int character) { + codeTable.add(index, character); + setModified(true); + } + + @Override + public void removeFontCharacter(int index) { + codeTable.remove(index); + setModified(true); + } + + @Override + public String getFontName() { + return fontName; + } + + @Override + public boolean getFontFlagsBold() { + return fontFlagsBold; + } + + @Override + public void setFontFlagsBold(boolean value) { + fontFlagsBold = value; + } + + @Override + public boolean getFontFlagsItalic() { + return fontFlagsItalic; + } + + @Override + public void setFontFlagsItalic(boolean value) { + fontFlagsItalic = value; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java index 456785a12..c141e60f2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java @@ -1,184 +1,184 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.FontInfoTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 1) -public class DefineFontInfoTag extends FontInfoTag { - - public static final int ID = 13; - - public static final String NAME = "DefineFontInfo"; - - public String fontName; - - @Reserved - @SWFType(value = BasicType.UB, count = 2) - public int reserved; - - public boolean fontFlagsSmallText; - - public boolean fontFlagsShiftJIS; - - public boolean fontFlagsANSI; - - public boolean fontFlagsItalic; - - public boolean fontFlagsBold; - - public boolean fontFlagsWideCodes; - - @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") - public List codeTable; - - /** - * Constructor - * - * @param swf - */ - public DefineFontInfoTag(SWF swf) { - super(swf, ID, NAME, null); - fontName = "New Font Info Name"; - codeTable = new ArrayList<>(); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public DefineFontInfoTag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - fontID = sis.readUI16("fontId"); - if (swf.version >= 6) { - fontName = sis.readNetString("fontName", Utf8Helper.charset); - } else { - fontName = sis.readNetString("fontName"); - } - reserved = (int) sis.readUB(2, "reserved"); - fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; - fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; - fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; - fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; - fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; - fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; - codeTable = new ArrayList<>(); - while (sis.available() > 0) { - if (fontFlagsWideCodes) { - codeTable.add(sis.readUI16("code")); - } else { - codeTable.add(sis.readUI8("code")); - } - } - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - sos.writeUI16(fontID); - if (swf.version >= 6) { - sos.writeNetString(fontName, Utf8Helper.charset); - } else { - sos.writeNetString(fontName); - } - sos.writeUB(2, reserved); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - for (int code : codeTable) { - if (fontFlagsWideCodes) { - sos.writeUI16(code); - } else { - sos.writeUI8(code); - } - } - } - - @Override - public List getCodeTable() { - return codeTable; - } - - @Override - public void addFontCharacter(int index, int character) { - codeTable.add(index, character); - setModified(true); - } - - @Override - public void removeFontCharacter(int index) { - codeTable.remove(index); - setModified(true); - } - - @Override - public String getFontName() { - return fontName; - } - - @Override - public boolean getFontFlagsBold() { - return fontFlagsBold; - } - - @Override - public void setFontFlagsBold(boolean value) { - fontFlagsBold = value; - } - - @Override - public boolean getFontFlagsItalic() { - return fontFlagsItalic; - } - - @Override - public void setFontFlagsItalic(boolean value) { - fontFlagsItalic = value; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.FontInfoTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 1) +public class DefineFontInfoTag extends FontInfoTag { + + public static final int ID = 13; + + public static final String NAME = "DefineFontInfo"; + + public String fontName; + + @Reserved + @SWFType(value = BasicType.UB, count = 2) + public int reserved; + + public boolean fontFlagsSmallText; + + public boolean fontFlagsShiftJIS; + + public boolean fontFlagsANSI; + + public boolean fontFlagsItalic; + + public boolean fontFlagsBold; + + public boolean fontFlagsWideCodes; + + @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") + public List codeTable; + + /** + * Constructor + * + * @param swf + */ + public DefineFontInfoTag(SWF swf) { + super(swf, ID, NAME, null); + fontName = "New Font Info Name"; + codeTable = new ArrayList<>(); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public DefineFontInfoTag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + fontID = sis.readUI16("fontId"); + if (swf.version >= 6) { + fontName = sis.readNetString("fontName", Utf8Helper.charset); + } else { + fontName = sis.readNetString("fontName"); + } + reserved = (int) sis.readUB(2, "reserved"); + fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1; + fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1; + fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1; + fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1; + fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1; + fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; + codeTable = new ArrayList<>(); + while (sis.available() > 0) { + if (fontFlagsWideCodes) { + codeTable.add(sis.readUI16("code")); + } else { + codeTable.add(sis.readUI8("code")); + } + } + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + sos.writeUI16(fontID); + if (swf.version >= 6) { + sos.writeNetString(fontName, Utf8Helper.charset); + } else { + sos.writeNetString(fontName); + } + sos.writeUB(2, reserved); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + for (int code : codeTable) { + if (fontFlagsWideCodes) { + sos.writeUI16(code); + } else { + sos.writeUI8(code); + } + } + } + + @Override + public List getCodeTable() { + return codeTable; + } + + @Override + public void addFontCharacter(int index, int character) { + codeTable.add(index, character); + setModified(true); + } + + @Override + public void removeFontCharacter(int index) { + codeTable.remove(index); + setModified(true); + } + + @Override + public String getFontName() { + return fontName; + } + + @Override + public boolean getFontFlagsBold() { + return fontFlagsBold; + } + + @Override + public void setFontFlagsBold(boolean value) { + fontFlagsBold = value; + } + + @Override + public boolean getFontFlagsItalic() { + return fontFlagsItalic; + } + + @Override + public void setFontFlagsItalic(boolean value) { + fontFlagsItalic = value; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java index 154b0320f..f7b79f8be 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java @@ -1,382 +1,382 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.tags.base.FontInfoTag; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.helpers.ByteArrayRange; -import java.awt.Font; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 1) -public class DefineFontTag extends FontTag { - - public static final int ID = 10; - - public static final String NAME = "DefineFont"; - - @SWFType(BasicType.UI16) - public int fontId; - - public List glyphShapeTable; - - @Internal - private FontInfoTag fontInfoTag = null; - - /** - * Constructor - * - * @param swf - */ - public DefineFontTag(SWF swf) { - super(swf, ID, NAME, null); - fontId = swf.getNextCharacterId(); - glyphShapeTable = new ArrayList<>(); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public DefineFontTag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - fontId = sis.readUI16("fontId"); - glyphShapeTable = new ArrayList<>(); - - if (sis.available() > 0) { - long pos = sis.getPos(); - int firstOffset = sis.readUI16("firstOffset"); - int nGlyphs = firstOffset / 2; - - long[] offsetTable = new long[nGlyphs]; - offsetTable[0] = firstOffset; - for (int i = 1; i < nGlyphs; i++) { - offsetTable[i] = sis.readUI16("offset"); - } - for (int i = 0; i < nGlyphs; i++) { - sis.seek(pos + offsetTable[i]); - glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); - } - } - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - sos.writeUI16(fontId); - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - List offsetTable = new ArrayList<>(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion()); - for (SHAPE shape : glyphShapeTable) { - offsetTable.add(glyphShapeTable.size() * 2 + (int) sos2.getPos()); - sos2.writeSHAPE(shape, 1); - } - for (int offset : offsetTable) { - sos.writeUI16(offset); - } - sos.write(baos2.toByteArray()); - } - - @Override - public boolean isSmall() { - return false; - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - return -1; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); - } - - private void ensureFontInfo() { - if (fontInfoTag == null) { - List characterIdTags = swf.getCharacterIdTags(fontId); - if (characterIdTags != null) { - for (CharacterIdTag t : characterIdTags) { - if (t instanceof FontInfoTag) { - if (((FontInfoTag) t).fontID == fontId) { - fontInfoTag = (FontInfoTag) t; - break; - } - } - } - } - } - } - - @Override - public char glyphToChar(int glyphIndex) { - ensureFontInfo(); - if (fontInfoTag != null) { - return (char) (int) fontInfoTag.getCodeTable().get(glyphIndex); - } else { - return '?'; - } - } - - @Override - public int charToGlyph(char c) { - ensureFontInfo(); - if (fontInfoTag != null) { - return fontInfoTag.getCodeTable().indexOf((int) c); - } - return -1; - - } - - @Override - public List getGlyphShapeTable() { - return glyphShapeTable; - } - - @Override - public int getCharacterId() { - return fontId; - } - - @Override - public void setCharacterId(int characterId) { - this.fontId = characterId; - } - - @Override - public String getFontNameIntag() { - ensureFontInfo(); - if (fontInfoTag != null) { - return fontInfoTag.getFontName(); - } - return null; - } - - @Override - public boolean isBold() { - if (fontInfoTag != null) { - return fontInfoTag.getFontFlagsBold(); - } - return false; - } - - @Override - public boolean isItalic() { - if (fontInfoTag != null) { - return fontInfoTag.getFontFlagsItalic(); - } - return false; - } - - @Override - public boolean isSmallEditable() { - return false; - } - - @Override - public boolean isBoldEditable() { - return fontInfoTag != null; - } - - @Override - public boolean isItalicEditable() { - return fontInfoTag != null; - } - - @Override - public void setSmall(boolean value) { - } - - @Override - public void setBold(boolean value) { - if (fontInfoTag != null) { - fontInfoTag.setFontFlagsBold(value); - } - } - - @Override - public void setItalic(boolean value) { - if (fontInfoTag != null) { - fontInfoTag.setFontFlagsItalic(value); - } - } - - @Override - public int getAscent() { - return -1; - } - - @Override - public int getDescent() { - return -1; - } - - @Override - public int getLeading() { - return -1; - } - - @Override - public double getDivider() { - return 1; - } - - @Override - public void addCharacter(char character, Font font) { - SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); - ensureFontInfo(); - int code = (int) character; - int pos = -1; - boolean exists = false; - if (fontInfoTag != null) { - List codeTable = fontInfoTag.getCodeTable(); - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - exists = true; - } - - pos = i; - break; - } - } - - if (pos == -1) { - pos = codeTable.size(); - } - } else { - pos = 0; - } - - if (!exists) { - shiftGlyphIndices(fontId, pos, true); - glyphShapeTable.add(pos, shp); - if (fontInfoTag != null) { - fontInfoTag.addFontCharacter(pos, (int) character); - } - } else { - glyphShapeTable.set(pos, shp); - } - - setModified(true); - getSwf().clearImageCache(); - } - - @Override - public boolean removeCharacter(char character) { - ensureFontInfo(); - if (fontInfoTag == null) { - return false; - } - - int code = (int) character; - int pos = -1; - List codeTable = fontInfoTag.getCodeTable(); - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - pos = i; - break; - } - - return false; - } - } - - if (pos == -1) { - return false; - } - - glyphShapeTable.remove(pos); - fontInfoTag.removeFontCharacter(pos); - - shiftGlyphIndices(fontId, pos + 1, false); - - setModified(true); - getSwf().clearImageCache(); - return true; - } - - @Override - public void setAdvanceValues(Font font) { - throw new UnsupportedOperationException("Setting the advance values for DefineFontTag is not supported."); - } - - @Override - public int getCharacterCount() { - ensureFontInfo(); - if (fontInfoTag != null) { - List codeTable = fontInfoTag.getCodeTable(); - return codeTable.size(); - } - return 0; - } - - @Override - public String getCharacters() { - ensureFontInfo(); - if (fontInfoTag != null) { - List codeTable = fontInfoTag.getCodeTable(); - StringBuilder ret = new StringBuilder(codeTable.size()); - for (int i : codeTable) { - ret.append((char) i); - } - return ret.toString(); - } - return ""; - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - return 0; - } - - @Override - public int getCharKerningAdjustment(char c1, char c2) { - return 0; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.tags.base.FontInfoTag; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import com.jpexs.helpers.ByteArrayRange; +import java.awt.Font; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 1) +public class DefineFontTag extends FontTag { + + public static final int ID = 10; + + public static final String NAME = "DefineFont"; + + @SWFType(BasicType.UI16) + public int fontId; + + public List glyphShapeTable; + + @Internal + private FontInfoTag fontInfoTag = null; + + /** + * Constructor + * + * @param swf + */ + public DefineFontTag(SWF swf) { + super(swf, ID, NAME, null); + fontId = swf.getNextCharacterId(); + glyphShapeTable = new ArrayList<>(); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public DefineFontTag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + fontId = sis.readUI16("fontId"); + glyphShapeTable = new ArrayList<>(); + + if (sis.available() > 0) { + long pos = sis.getPos(); + int firstOffset = sis.readUI16("firstOffset"); + int nGlyphs = firstOffset / 2; + + long[] offsetTable = new long[nGlyphs]; + offsetTable[0] = firstOffset; + for (int i = 1; i < nGlyphs; i++) { + offsetTable[i] = sis.readUI16("offset"); + } + for (int i = 0; i < nGlyphs; i++) { + sis.seek(pos + offsetTable[i]); + glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); + } + } + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + sos.writeUI16(fontId); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + List offsetTable = new ArrayList<>(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion()); + for (SHAPE shape : glyphShapeTable) { + offsetTable.add(glyphShapeTable.size() * 2 + (int) sos2.getPos()); + sos2.writeSHAPE(shape, 1); + } + for (int offset : offsetTable) { + sos.writeUI16(offset); + } + sos.write(baos2.toByteArray()); + } + + @Override + public boolean isSmall() { + return false; + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + return -1; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); + } + + private void ensureFontInfo() { + if (fontInfoTag == null) { + List characterIdTags = swf.getCharacterIdTags(fontId); + if (characterIdTags != null) { + for (CharacterIdTag t : characterIdTags) { + if (t instanceof FontInfoTag) { + if (((FontInfoTag) t).fontID == fontId) { + fontInfoTag = (FontInfoTag) t; + break; + } + } + } + } + } + } + + @Override + public char glyphToChar(int glyphIndex) { + ensureFontInfo(); + if (fontInfoTag != null) { + return (char) (int) fontInfoTag.getCodeTable().get(glyphIndex); + } else { + return '?'; + } + } + + @Override + public int charToGlyph(char c) { + ensureFontInfo(); + if (fontInfoTag != null) { + return fontInfoTag.getCodeTable().indexOf((int) c); + } + return -1; + + } + + @Override + public List getGlyphShapeTable() { + return glyphShapeTable; + } + + @Override + public int getCharacterId() { + return fontId; + } + + @Override + public void setCharacterId(int characterId) { + this.fontId = characterId; + } + + @Override + public String getFontNameIntag() { + ensureFontInfo(); + if (fontInfoTag != null) { + return fontInfoTag.getFontName(); + } + return null; + } + + @Override + public boolean isBold() { + if (fontInfoTag != null) { + return fontInfoTag.getFontFlagsBold(); + } + return false; + } + + @Override + public boolean isItalic() { + if (fontInfoTag != null) { + return fontInfoTag.getFontFlagsItalic(); + } + return false; + } + + @Override + public boolean isSmallEditable() { + return false; + } + + @Override + public boolean isBoldEditable() { + return fontInfoTag != null; + } + + @Override + public boolean isItalicEditable() { + return fontInfoTag != null; + } + + @Override + public void setSmall(boolean value) { + } + + @Override + public void setBold(boolean value) { + if (fontInfoTag != null) { + fontInfoTag.setFontFlagsBold(value); + } + } + + @Override + public void setItalic(boolean value) { + if (fontInfoTag != null) { + fontInfoTag.setFontFlagsItalic(value); + } + } + + @Override + public int getAscent() { + return -1; + } + + @Override + public int getDescent() { + return -1; + } + + @Override + public int getLeading() { + return -1; + } + + @Override + public double getDivider() { + return 1; + } + + @Override + public void addCharacter(char character, Font font) { + SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character); + ensureFontInfo(); + int code = (int) character; + int pos = -1; + boolean exists = false; + if (fontInfoTag != null) { + List codeTable = fontInfoTag.getCodeTable(); + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + exists = true; + } + + pos = i; + break; + } + } + + if (pos == -1) { + pos = codeTable.size(); + } + } else { + pos = 0; + } + + if (!exists) { + shiftGlyphIndices(fontId, pos, true); + glyphShapeTable.add(pos, shp); + if (fontInfoTag != null) { + fontInfoTag.addFontCharacter(pos, (int) character); + } + } else { + glyphShapeTable.set(pos, shp); + } + + setModified(true); + getSwf().clearImageCache(); + } + + @Override + public boolean removeCharacter(char character) { + ensureFontInfo(); + if (fontInfoTag == null) { + return false; + } + + int code = (int) character; + int pos = -1; + List codeTable = fontInfoTag.getCodeTable(); + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + pos = i; + break; + } + + return false; + } + } + + if (pos == -1) { + return false; + } + + glyphShapeTable.remove(pos); + fontInfoTag.removeFontCharacter(pos); + + shiftGlyphIndices(fontId, pos + 1, false); + + setModified(true); + getSwf().clearImageCache(); + return true; + } + + @Override + public void setAdvanceValues(Font font) { + throw new UnsupportedOperationException("Setting the advance values for DefineFontTag is not supported."); + } + + @Override + public int getCharacterCount() { + ensureFontInfo(); + if (fontInfoTag != null) { + List codeTable = fontInfoTag.getCodeTable(); + return codeTable.size(); + } + return 0; + } + + @Override + public String getCharacters() { + ensureFontInfo(); + if (fontInfoTag != null) { + List codeTable = fontInfoTag.getCodeTable(); + StringBuilder ret = new StringBuilder(codeTable.size()); + for (int i : codeTable) { + ret.append((char) i); + } + return ret.toString(); + } + return ""; + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + return 0; + } + + @Override + public int getCharKerningAdjustment(char c1, char c2) { + return 0; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoABCTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoABCTag.java index 96f0bafd7..4a68db226 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoABCTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoABCTag.java @@ -1,112 +1,112 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ABCInputStream; -import com.jpexs.decompiler.flash.abc.types.ScriptInfo; -import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; -import com.jpexs.decompiler.flash.types.annotations.SWFField; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.helpers.ByteArrayRange; -import java.io.IOException; - -/** - * Defines a series of ActionScript 3 bytecodes to be executed - * - * @author JPEXS - */ -@SWFVersion(from = 9) -public class DoABCTag extends Tag implements ABCContainerTag { - - public static final int ID = 72; - - public static final String NAME = "DoABC"; - - /** - * ActionScript 3 bytecodes - */ - @HideInRawEdit - @SWFField - private ABC abc; - - /** - * Constructor - * - * @param swf - */ - public DoABCTag(SWF swf) { - super(swf, ID, NAME, null); - abc = new ABC(this); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public DoABCTag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - ABCInputStream ais = new ABCInputStream(sis.getBaseStream()); - - // put it to the dumpview: - sis.readByteRangeEx(sis.available(), "abcBytes"); - abc = new ABC(ais, swf, this); - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - abc.saveToStream(sos); - } - - @Override - public ABC getABC() { - return abc; - } - - @Override - public int compareTo(ABCContainerTag o) { - return 0; - } - - @Override - public void setModified(boolean value) { - super.setModified(value); - if (value == false && !isModified()) { - ABC abc = getABC(); - for (ScriptInfo si : abc.script_info) { - si.setModified(false); - } - } - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ABCInputStream; +import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; +import com.jpexs.decompiler.flash.types.annotations.SWFField; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.helpers.ByteArrayRange; +import java.io.IOException; + +/** + * Defines a series of ActionScript 3 bytecodes to be executed + * + * @author JPEXS + */ +@SWFVersion(from = 9) +public class DoABCTag extends Tag implements ABCContainerTag { + + public static final int ID = 72; + + public static final String NAME = "DoABC"; + + /** + * ActionScript 3 bytecodes + */ + @HideInRawEdit + @SWFField + private ABC abc; + + /** + * Constructor + * + * @param swf + */ + public DoABCTag(SWF swf) { + super(swf, ID, NAME, null); + abc = new ABC(this); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public DoABCTag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + ABCInputStream ais = new ABCInputStream(sis.getBaseStream()); + + // put it to the dumpview: + sis.readByteRangeEx(sis.available(), "abcBytes"); + abc = new ABC(ais, swf, this); + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + abc.saveToStream(sos); + } + + @Override + public ABC getABC() { + return abc; + } + + @Override + public int compareTo(ABCContainerTag o) { + return 0; + } + + @Override + public void setModified(boolean value) { + super.setModified(value); + if (value == false && !isModified()) { + ABC abc = getABC(); + for (ScriptInfo si : abc.script_info) { + si.setModified(false); + } + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoActionTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoActionTag.java index a2897ffad..ea53f2642 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoActionTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DoActionTag.java @@ -1,224 +1,224 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.ConstantPoolTooBigException; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Instructs Flash Player to perform a list of actions when the current frame is - * complete. - * - * @author JPEXS - */ -@SWFVersion(from = 1) -public class DoActionTag extends Tag implements ASMSource { - - public static final int ID = 12; - - public static final String NAME = "DoAction"; - - /** - * List of actions to perform - */ - @HideInRawEdit - public ByteArrayRange actionBytes; - - @Internal - private String scriptName = "-"; - - @Override - public String getScriptName() { - return scriptName; - } - - /** - * Constructor - * - * @param swf - */ - public DoActionTag(SWF swf) { - super(swf, ID, NAME, null); - actionBytes = ByteArrayRange.EMPTY; - } - - /** - * Constructor - * - * @param swf - * @param data - */ - public DoActionTag(SWF swf, ByteArrayRange data) { - super(swf, ID, NAME, data); - actionBytes = ByteArrayRange.EMPTY; - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws java.io.IOException - */ - public DoActionTag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public void setScriptName(String scriptName) { - this.scriptName = scriptName; - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes"); - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - sos.write(getActionBytes()); - } - - /** - * Converts actions to ASM source - * - * @param exportMode PCode or hex? - * @param writer - * @param actions - * @return ASM source - * @throws java.lang.InterruptedException - */ - @Override - public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException { - if (actions == null) { - actions = getActions(); - } - - return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer); - } - - /** - * Whether or not this object contains ASM source - * - * @return True when contains - */ - @Override - public boolean containsSource() { - return true; - } - - @Override - public ActionList getActions() throws InterruptedException { - return SWF.getCachedActionList(this, listeners); - } - - @Override - public void setActions(List actions) { - actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version); - } - - @Override - public ByteArrayRange getActionBytes() { - return actionBytes; - } - - @Override - public void setActionBytes(byte[] actionBytes) { - this.actionBytes = new ByteArrayRange(actionBytes); - SWF.uncache(this); - } - - @Override - public void setConstantPools(List> constantPools) throws ConstantPoolTooBigException { - Action.setConstantPools(this, constantPools, false); - } - - @Override - public void setModified() { - setModified(true); - } - - @Override - public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) { - return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData()); - } - - List listeners = new ArrayList<>(); - - @Override - public void addDisassemblyListener(DisassemblyListener listener) { - listeners.add(listener); - } - - @Override - public void removeDisassemblyListener(DisassemblyListener listener) { - listeners.remove(listener); - } - - @Override - public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) { - return writer; - } - - @Override - public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) { - return writer; - } - - @Override - public int getPrefixLineCount() { - return 0; - } - - @Override - public String removePrefixAndSuffix(String source) { - return source; - } - - @Override - public Tag getSourceTag() { - return this; - } - - @Override - public void setSourceTag(Tag t) { - //nothing - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ConstantPoolTooBigException; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Instructs Flash Player to perform a list of actions when the current frame is + * complete. + * + * @author JPEXS + */ +@SWFVersion(from = 1) +public class DoActionTag extends Tag implements ASMSource { + + public static final int ID = 12; + + public static final String NAME = "DoAction"; + + /** + * List of actions to perform + */ + @HideInRawEdit + public ByteArrayRange actionBytes; + + @Internal + private String scriptName = "-"; + + @Override + public String getScriptName() { + return scriptName; + } + + /** + * Constructor + * + * @param swf + */ + public DoActionTag(SWF swf) { + super(swf, ID, NAME, null); + actionBytes = ByteArrayRange.EMPTY; + } + + /** + * Constructor + * + * @param swf + * @param data + */ + public DoActionTag(SWF swf, ByteArrayRange data) { + super(swf, ID, NAME, data); + actionBytes = ByteArrayRange.EMPTY; + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws java.io.IOException + */ + public DoActionTag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public void setScriptName(String scriptName) { + this.scriptName = scriptName; + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes"); + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + sos.write(getActionBytes()); + } + + /** + * Converts actions to ASM source + * + * @param exportMode PCode or hex? + * @param writer + * @param actions + * @return ASM source + * @throws java.lang.InterruptedException + */ + @Override + public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException { + if (actions == null) { + actions = getActions(); + } + + return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer); + } + + /** + * Whether or not this object contains ASM source + * + * @return True when contains + */ + @Override + public boolean containsSource() { + return true; + } + + @Override + public ActionList getActions() throws InterruptedException { + return SWF.getCachedActionList(this, listeners); + } + + @Override + public void setActions(List actions) { + actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version); + } + + @Override + public ByteArrayRange getActionBytes() { + return actionBytes; + } + + @Override + public void setActionBytes(byte[] actionBytes) { + this.actionBytes = new ByteArrayRange(actionBytes); + SWF.uncache(this); + } + + @Override + public void setConstantPools(List> constantPools) throws ConstantPoolTooBigException { + Action.setConstantPools(this, constantPools, false); + } + + @Override + public void setModified() { + setModified(true); + } + + @Override + public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) { + return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData()); + } + + List listeners = new ArrayList<>(); + + @Override + public void addDisassemblyListener(DisassemblyListener listener) { + listeners.add(listener); + } + + @Override + public void removeDisassemblyListener(DisassemblyListener listener) { + listeners.remove(listener); + } + + @Override + public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) { + return writer; + } + + @Override + public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) { + return writer; + } + + @Override + public int getPrefixLineCount() { + return 0; + } + + @Override + public String removePrefixAndSuffix(String source) { + return source; + } + + @Override + public Tag getSourceTag() { + return this; + } + + @Override + public void setSourceTag(Tag t) { + //nothing + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java index c028aa7e9..74e2397d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java @@ -1,261 +1,261 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; -import com.jpexs.decompiler.flash.timeline.Timeline; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Conditional; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.annotations.SWFVersion; -import com.jpexs.decompiler.flash.types.sound.SoundExportFormat; -import com.jpexs.decompiler.flash.types.sound.SoundFormat; -import com.jpexs.helpers.ByteArrayRange; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -@SWFVersion(from = 3) -public class SoundStreamHead2Tag extends Tag implements SoundStreamHeadTypeTag { - - public static final int ID = 45; - - public static final String NAME = "SoundStreamHead2"; - - @Reserved - @SWFType(value = BasicType.UB, count = 4) - public int reserved; - - @SWFType(value = BasicType.UB, count = 2) - public int playBackSoundRate; - - public boolean playBackSoundSize; - - public boolean playBackSoundType; - - @SWFType(value = BasicType.UB, count = 4) - public int streamSoundCompression; - - @SWFType(value = BasicType.UB, count = 2) - public int streamSoundRate; - - public boolean streamSoundSize; - - public boolean streamSoundType; - - @SWFType(BasicType.UI16) - public int streamSoundSampleCount; - - @SWFType(BasicType.SI16) - @Conditional(value = "streamSoundCompression", options = {2}) - public int latencySeek; - - @Internal - private int virtualCharacterId = 0; - - /** - * Constructor - * - * @param swf - */ - public SoundStreamHead2Tag(SWF swf) { - super(swf, ID, NAME, null); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public SoundStreamHead2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - reserved = (int) sis.readUB(4, "reserved"); - playBackSoundRate = (int) sis.readUB(2, "playBackSoundRate"); - playBackSoundSize = sis.readUB(1, "playBackSoundSize") == 1; - playBackSoundType = sis.readUB(1, "playBackSoundType") == 1; - streamSoundCompression = (int) sis.readUB(4, "streamSoundCompression"); - streamSoundRate = (int) sis.readUB(2, "streamSoundRate"); - streamSoundSize = sis.readUB(1, "streamSoundSize") == 1; - streamSoundType = sis.readUB(1, "streamSoundType") == 1; - streamSoundSampleCount = sis.readUI16("streamSoundSampleCount"); - if (streamSoundCompression == 2) { - latencySeek = sis.readSI16("latencySeek"); - } - } - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - sos.writeUB(4, reserved); - sos.writeUB(2, playBackSoundRate); - sos.writeUB(1, playBackSoundSize ? 1 : 0); - sos.writeUB(1, playBackSoundType ? 1 : 0); - sos.writeUB(4, streamSoundCompression); - sos.writeUB(2, streamSoundRate); - sos.writeUB(1, streamSoundSize ? 1 : 0); - sos.writeUB(1, streamSoundType ? 1 : 0); - sos.writeUI16(streamSoundSampleCount); - if (streamSoundCompression == 2) { - sos.writeSI16(latencySeek); - } - } - - @Override - public int getCharacterId() { - return virtualCharacterId; - } - - @Override - public void setCharacterId(int characterId) { - virtualCharacterId = characterId; - } - - @Override - public SoundExportFormat getExportFormat() { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - return SoundExportFormat.MP3; - } - if (streamSoundCompression == SoundFormat.FORMAT_ADPCM) { - return SoundExportFormat.WAV; - } - if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { - return SoundExportFormat.WAV; - } - if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { - return SoundExportFormat.WAV; - } - if (streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER16KHZ || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER8KHZ) { - return SoundExportFormat.WAV; - } - return SoundExportFormat.FLV; - } - - @Override - public long getSoundSampleCount() { - return streamSoundSampleCount; - } - - @Override - public void setVirtualCharacterId(int ch) { - virtualCharacterId = ch; - } - - @Override - public int getSoundFormatId() { - return streamSoundCompression; - } - - @Override - public int getSoundRate() { - return streamSoundRate; - } - - @Override - public boolean getSoundSize() { - return streamSoundSize; - } - - @Override - public boolean getSoundType() { - return streamSoundType; - } - - @Override - public List getBlocks() { - Timeline timeline = swf.getTimeline(); - List ret = timeline.getSoundStreamBlocks(this); - return ret; - - } - - @Override - public boolean importSupported() { - return false; - } - - @Override - public boolean setSound(InputStream is, int newSoundFormat) { - return false; - } - - @Override - public List getRawSoundData() { - List ret = new ArrayList<>(); - List blocks = getBlocks(); - if (blocks != null) { - for (SoundStreamBlockTag block : blocks) { - ByteArrayRange data = block.streamSoundData; - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - ret.add(data.getSubRange(4, data.getLength() - 4)); - } else { - ret.add(data); - } - } - } - return ret; - } - - @Override - public long getTotalSoundSampleCount() { - return getBlocks().size() * streamSoundSampleCount; - } - - @Override - public SoundFormat getSoundFormat() { - final int[] rateMap = {5512, 11025, 22050, 44100}; - return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); - } - - @Override - public String getCharacterExportFileName() { - String exportName = swf.getExportName(getCharacterId()); - return getCharacterId() + (exportName != null ? "_" + exportName : ""); - } - - @Override - public void getTagInfo(TagInfo tagInfo) { - super.getTagInfo(tagInfo); - SoundFormat soundFormat = getSoundFormat(); - tagInfo.addInfo("general", "codecName", soundFormat.getFormatName()); - tagInfo.addInfo("general", "exportFormat", soundFormat.getNativeExportFormat()); - tagInfo.addInfo("general", "samplingRate", soundFormat.samplingRate); - tagInfo.addInfo("general", "stereo", soundFormat.stereo); - tagInfo.addInfo("general", "sampleCount", streamSoundSampleCount); - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.annotations.SWFVersion; +import com.jpexs.decompiler.flash.types.sound.SoundExportFormat; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import com.jpexs.helpers.ByteArrayRange; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +@SWFVersion(from = 3) +public class SoundStreamHead2Tag extends Tag implements SoundStreamHeadTypeTag { + + public static final int ID = 45; + + public static final String NAME = "SoundStreamHead2"; + + @Reserved + @SWFType(value = BasicType.UB, count = 4) + public int reserved; + + @SWFType(value = BasicType.UB, count = 2) + public int playBackSoundRate; + + public boolean playBackSoundSize; + + public boolean playBackSoundType; + + @SWFType(value = BasicType.UB, count = 4) + public int streamSoundCompression; + + @SWFType(value = BasicType.UB, count = 2) + public int streamSoundRate; + + public boolean streamSoundSize; + + public boolean streamSoundType; + + @SWFType(BasicType.UI16) + public int streamSoundSampleCount; + + @SWFType(BasicType.SI16) + @Conditional(value = "streamSoundCompression", options = {2}) + public int latencySeek; + + @Internal + private int virtualCharacterId = 0; + + /** + * Constructor + * + * @param swf + */ + public SoundStreamHead2Tag(SWF swf) { + super(swf, ID, NAME, null); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public SoundStreamHead2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + reserved = (int) sis.readUB(4, "reserved"); + playBackSoundRate = (int) sis.readUB(2, "playBackSoundRate"); + playBackSoundSize = sis.readUB(1, "playBackSoundSize") == 1; + playBackSoundType = sis.readUB(1, "playBackSoundType") == 1; + streamSoundCompression = (int) sis.readUB(4, "streamSoundCompression"); + streamSoundRate = (int) sis.readUB(2, "streamSoundRate"); + streamSoundSize = sis.readUB(1, "streamSoundSize") == 1; + streamSoundType = sis.readUB(1, "streamSoundType") == 1; + streamSoundSampleCount = sis.readUI16("streamSoundSampleCount"); + if (streamSoundCompression == 2) { + latencySeek = sis.readSI16("latencySeek"); + } + } + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + sos.writeUB(4, reserved); + sos.writeUB(2, playBackSoundRate); + sos.writeUB(1, playBackSoundSize ? 1 : 0); + sos.writeUB(1, playBackSoundType ? 1 : 0); + sos.writeUB(4, streamSoundCompression); + sos.writeUB(2, streamSoundRate); + sos.writeUB(1, streamSoundSize ? 1 : 0); + sos.writeUB(1, streamSoundType ? 1 : 0); + sos.writeUI16(streamSoundSampleCount); + if (streamSoundCompression == 2) { + sos.writeSI16(latencySeek); + } + } + + @Override + public int getCharacterId() { + return virtualCharacterId; + } + + @Override + public void setCharacterId(int characterId) { + virtualCharacterId = characterId; + } + + @Override + public SoundExportFormat getExportFormat() { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + return SoundExportFormat.MP3; + } + if (streamSoundCompression == SoundFormat.FORMAT_ADPCM) { + return SoundExportFormat.WAV; + } + if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { + return SoundExportFormat.WAV; + } + if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { + return SoundExportFormat.WAV; + } + if (streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER16KHZ || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER8KHZ) { + return SoundExportFormat.WAV; + } + return SoundExportFormat.FLV; + } + + @Override + public long getSoundSampleCount() { + return streamSoundSampleCount; + } + + @Override + public void setVirtualCharacterId(int ch) { + virtualCharacterId = ch; + } + + @Override + public int getSoundFormatId() { + return streamSoundCompression; + } + + @Override + public int getSoundRate() { + return streamSoundRate; + } + + @Override + public boolean getSoundSize() { + return streamSoundSize; + } + + @Override + public boolean getSoundType() { + return streamSoundType; + } + + @Override + public List getBlocks() { + Timeline timeline = swf.getTimeline(); + List ret = timeline.getSoundStreamBlocks(this); + return ret; + + } + + @Override + public boolean importSupported() { + return false; + } + + @Override + public boolean setSound(InputStream is, int newSoundFormat) { + return false; + } + + @Override + public List getRawSoundData() { + List ret = new ArrayList<>(); + List blocks = getBlocks(); + if (blocks != null) { + for (SoundStreamBlockTag block : blocks) { + ByteArrayRange data = block.streamSoundData; + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + ret.add(data.getSubRange(4, data.getLength() - 4)); + } else { + ret.add(data); + } + } + } + return ret; + } + + @Override + public long getTotalSoundSampleCount() { + return getBlocks().size() * streamSoundSampleCount; + } + + @Override + public SoundFormat getSoundFormat() { + final int[] rateMap = {5512, 11025, 22050, 44100}; + return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); + } + + @Override + public String getCharacterExportFileName() { + String exportName = swf.getExportName(getCharacterId()); + return getCharacterId() + (exportName != null ? "_" + exportName : ""); + } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + SoundFormat soundFormat = getSoundFormat(); + tagInfo.addInfo("general", "codecName", soundFormat.getFormatName()); + tagInfo.addInfo("general", "exportFormat", soundFormat.getNativeExportFormat()); + tagInfo.addInfo("general", "samplingRate", soundFormat.samplingRate); + tagInfo.addInfo("general", "stereo", soundFormat.stereo); + tagInfo.addInfo("general", "sampleCount", streamSoundSampleCount); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontInfoTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontInfoTag.java index 950a4754c..ba2147976 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontInfoTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontInfoTag.java @@ -1,64 +1,64 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.ByteArrayRange; -import java.util.List; - -/** - * - * @author JPEXS - */ -public abstract class FontInfoTag extends Tag implements CharacterIdTag { - - @SWFType(BasicType.UI16) - public int fontID; - - public FontInfoTag(SWF swf, int id, String name, ByteArrayRange data) { - super(swf, id, name, data); - } - - public abstract List getCodeTable(); - - public abstract void addFontCharacter(int index, int character); - - public abstract void removeFontCharacter(int index); - - @Override - public int getCharacterId() { - return fontID; - } - - @Override - public void setCharacterId(int characterId) { - this.fontID = characterId; - } - - public abstract String getFontName(); - - public abstract boolean getFontFlagsBold(); - - public abstract void setFontFlagsBold(boolean value); - - public abstract boolean getFontFlagsItalic(); - - public abstract void setFontFlagsItalic(boolean value); -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.ByteArrayRange; +import java.util.List; + +/** + * + * @author JPEXS + */ +public abstract class FontInfoTag extends Tag implements CharacterIdTag { + + @SWFType(BasicType.UI16) + public int fontID; + + public FontInfoTag(SWF swf, int id, String name, ByteArrayRange data) { + super(swf, id, name, data); + } + + public abstract List getCodeTable(); + + public abstract void addFontCharacter(int index, int character); + + public abstract void removeFontCharacter(int index); + + @Override + public int getCharacterId() { + return fontID; + } + + @Override + public void setCharacterId(int characterId) { + this.fontID = characterId; + } + + public abstract String getFontName(); + + public abstract boolean getFontFlagsBold(); + + public abstract void setFontFlagsBold(boolean value); + + public abstract boolean getFontFlagsItalic(); + + public abstract void setFontFlagsItalic(boolean value); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index ed2234cad..fdebc05d4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -1,417 +1,417 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; -import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; -import com.jpexs.decompiler.flash.helpers.FontHelper; -import com.jpexs.decompiler.flash.tags.DefineFontNameTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.decompiler.flash.types.GLYPHENTRY; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.TEXTRECORD; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.SerializableImage; -import java.awt.Color; -import java.awt.Font; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.font.FontRenderContext; -import java.awt.font.GlyphMetrics; -import java.awt.font.GlyphVector; -import java.awt.geom.Area; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public abstract class FontTag extends DrawableTag implements AloneTag { - - public static final int PREVIEWSIZE = 500; - - public FontTag(SWF swf, int id, String name, ByteArrayRange data) { - super(swf, id, name, data); - } - - public abstract List getGlyphShapeTable(); - - public abstract void addCharacter(char character, Font font); - - public abstract boolean removeCharacter(char character); - - public abstract void setAdvanceValues(Font font); - - public abstract char glyphToChar(int glyphIndex); - - public abstract int charToGlyph(char c); - - public abstract double getGlyphAdvance(int glyphIndex); - - public abstract int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex); - - public abstract int getCharKerningAdjustment(char c1, char c2); - - public abstract int getGlyphWidth(int glyphIndex); - - public abstract String getFontNameIntag(); - - public abstract boolean isSmall(); - - public abstract boolean isBold(); - - public abstract boolean isItalic(); - - public abstract boolean isSmallEditable(); - - public abstract boolean isBoldEditable(); - - public abstract boolean isItalicEditable(); - - public abstract void setSmall(boolean value); - - public abstract void setBold(boolean value); - - public abstract void setItalic(boolean value); - - public abstract double getDivider(); - - public abstract int getAscent(); - - public abstract int getDescent(); - - public abstract int getLeading(); - - public String getFontName() { - DefineFontNameTag fontNameTag = getFontNameTag(); - if (fontNameTag == null) { - return getFontNameIntag(); - } - return fontNameTag.fontName; - } - - public String getFontCopyright() { - DefineFontNameTag fontNameTag = getFontNameTag(); - if (fontNameTag == null) { - return ""; - } - return fontNameTag.fontCopyright; - } - - public static Map> installedFontsByFamily; - - public static Map installedFontsByName; - - public static String defaultFontName; - - static { - reload(); - } - - public int getFontId() { - return getCharacterId(); - } - - public boolean hasLayout() { - return false; - } - - public boolean containsChar(char character) { - return charToGlyph(character) > -1; - } - - public int getFontStyle() { - int fontStyle = 0; - if (isBold()) { - fontStyle |= Font.BOLD; - } - if (isItalic()) { - fontStyle |= Font.ITALIC; - } - return fontStyle; - } - - public abstract int getCharacterCount(); - - public abstract String getCharacters(); - - @Override - public String getName() { - String nameAppend = ""; - if (exportName != null) { - nameAppend = ": " + exportName; - } - if (className != null) { - nameAppend = ": " + className; - } - String fontName = getFontNameIntag(); - if (fontName != null) { - nameAppend = ": " + fontName; - } - return tagName + " (" + getCharacterId() + nameAppend + ")"; - } - - @Override - public String getExportFileName() { - String result = super.getExportFileName(); - String fontName = getFontNameIntag(); - if (fontName != null) { - fontName = fontName.replace(" ", "_"); - } - return result + (fontName != null ? "_" + fontName : ""); - } - - public String getSystemFontName() { - int fontId = getFontId(); - String selectedFont = swf.sourceFontNamesMap.get(fontId); - if (selectedFont == null) { - SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(swf.getShortFileName()); - String key = fontId + "_" + getFontNameIntag(); - if (swfConf != null) { - selectedFont = swfConf.fontPairingMap.get(key); - } - } - - if (selectedFont == null) { - selectedFont = Configuration.getFontToNameMap().get(getFontNameIntag()); - } - - if (selectedFont != null && FontTag.installedFontsByName.containsKey(selectedFont)) { - return selectedFont; - } - - // findInstalledFontName always returns an available font name - return FontTag.findInstalledFontName(getFontName()); - } - - public Font getSystemFont() { - return FontTag.installedFontsByName.get(getSystemFontName()); - } - - protected void shiftGlyphIndices(int fontId, int startIndex, boolean increment) { - for (Tag t : swf.getTags()) { - List textRecords = null; - if (t instanceof StaticTextTag) { - textRecords = ((StaticTextTag) t).textRecords; - } - - if (textRecords != null) { - int curFontId = 0; - for (TEXTRECORD tr : textRecords) { - if (tr.styleFlagsHasFont) { - curFontId = tr.fontId; - } - - if (curFontId != fontId) { - continue; - } - - for (GLYPHENTRY en : tr.glyphEntries) { - if (en == null) { //Currently edited - continue; - } - if (en.glyphIndex >= startIndex) { - if (increment) { - en.glyphIndex++; - } else { - en.glyphIndex--; - } - } - } - - t.setModified(true); - } - } - } - } - - public static float getSystemFontAdvance(String fontName, int fontStyle, int fontSize, Character character, Character nextCharacter) { - return getSystemFontAdvance(new Font(fontName, fontStyle, fontSize), character, nextCharacter); - } - - public static float getSystemFontAdvance(Font aFont, Character character, Character nextCharacter) { - String chars = "" + character + (nextCharacter == null ? "" : nextCharacter); - GlyphVector gv = aFont.layoutGlyphVector(new FontRenderContext(aFont.getTransform(), true, true), chars.toCharArray(), 0, chars.length(), Font.LAYOUT_LEFT_TO_RIGHT); - GlyphMetrics gm = gv.getGlyphMetrics(0); - return gm.getAdvanceX(); - } - - public static void reload() { - installedFontsByFamily = FontHelper.getInstalledFonts(); - installedFontsByName = new HashMap<>(); - - for (String fam : installedFontsByFamily.keySet()) { - for (String nam : installedFontsByFamily.get(fam).keySet()) { - installedFontsByName.put(nam, installedFontsByFamily.get(fam).get(nam)); - } - } - - if (installedFontsByFamily.containsKey("Times New Roman")) { - defaultFontName = "Times New Roman"; - } else if (installedFontsByFamily.containsKey("Arial")) { - defaultFontName = "Arial"; - } else { - defaultFontName = installedFontsByFamily.keySet().iterator().next(); - } - } - - public static String getFontNameWithFallback(String fontName) { - if (installedFontsByFamily.containsKey(fontName)) { - return fontName; - } - if (installedFontsByFamily.containsKey("Times New Roman")) { - return "Times New Roman"; - } - if (installedFontsByFamily.containsKey("Arial")) { - return "Arial"; - } - - //First font - return installedFontsByFamily.keySet().iterator().next(); - } - - public static String isFontFamilyInstalled(String fontFamily) { - if (installedFontsByFamily.containsKey(fontFamily)) { - return fontFamily; - } - if (fontFamily.contains("_")) { - String beforeUnderscore = fontFamily.substring(0, fontFamily.indexOf('_')); - if (installedFontsByFamily.containsKey(beforeUnderscore)) { - return beforeUnderscore; - } - } - return null; - } - - public static String findInstalledFontName(String fontName) { - if (installedFontsByName.containsKey(fontName)) { - return fontName; - } - if (fontName != null && fontName.contains("_")) { - String beforeUnderscore = fontName.substring(0, fontName.indexOf('_')); - if (installedFontsByName.containsKey(beforeUnderscore)) { - return beforeUnderscore; - } - } - return defaultFontName; - } - - @Override - public int getUsedParameters() { - return PARAMETER_FRAME; - } - - @Override - public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, boolean stroked) { - RECT r = getRect(); - return new Area(new Rectangle(r.Xmin, r.Ymin, r.getWidth(), r.getHeight())); - } - - @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform) { - SHAPERECORD.shapeListToImage(swf, getGlyphShapeTable(), image, frame, Color.black, colorTransform); - } - - @Override - public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) { - } - - @Override - public void toHtmlCanvas(StringBuilder result, double unitDivisor) { - List shapes = getGlyphShapeTable(); - result.append("\tdefaultFill = textColor;\r\n"); - result.append("\tswitch(ch){\r\n"); - for (int i = 0; i < shapes.size(); i++) { - char c = glyphToChar(i); - String cs = "" + c; - cs = cs.replace("\\", "\\\\").replace("\"", "\\\""); - result.append("\t\tcase \"").append(cs).append("\":\r\n"); - CanvasShapeExporter exporter = new CanvasShapeExporter(null, unitDivisor, swf, shapes.get(i), null, 0, 0); - exporter.export(); - result.append("\t\t").append(exporter.getShapeData().replaceAll("\r\n", "\r\n\t\t")); - result.append("\tbreak;\r\n"); - } - result.append("\t}\r\n"); - } - - @Override - public int getNumFrames() { - int frameCount = (getGlyphShapeTable().size() - 1) / SHAPERECORD.MAX_CHARACTERS_IN_FONT_PREVIEW + 1; - if (frameCount < 1) { - frameCount = 1; - } - return frameCount; - } - - @Override - public boolean isSingleFrame() { - return true; - } - - @Override - public RECT getRect() { - return getRect(null); // parameter not used - } - - @Override - public RECT getRect(Set added) { - return new RECT(0, (int) (PREVIEWSIZE * SWF.unitDivisor), 0, (int) (PREVIEWSIZE * SWF.unitDivisor)); - } - - @Override - public String getCharacterExportFileName() { - return super.getCharacterExportFileName() + "_" + getFontNameIntag(); - } - - public DefineFontNameTag getFontNameTag() { - for (Tag t : swf.getTags()) { - if (t instanceof DefineFontNameTag) { - DefineFontNameTag dfn = (DefineFontNameTag) t; - if (dfn.fontId == getFontId()) { - return dfn; - } - } - } - return null; - } - - public String getCopyright() { - DefineFontNameTag dfn = getFontNameTag(); - if (dfn == null) { - return null; - } - return dfn.fontCopyright; - } - - public RECT getGlyphBounds(int glyphIndex) { - return getGlyphShapeTable().get(glyphIndex).getBounds(); - } - - public FontTag toClassicFont() { - return this; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; +import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; +import com.jpexs.decompiler.flash.helpers.FontHelper; +import com.jpexs.decompiler.flash.tags.DefineFontNameTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.GLYPHENTRY; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.TEXTRECORD; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.SerializableImage; +import java.awt.Color; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.geom.Area; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author JPEXS + */ +public abstract class FontTag extends DrawableTag implements AloneTag { + + public static final int PREVIEWSIZE = 500; + + public FontTag(SWF swf, int id, String name, ByteArrayRange data) { + super(swf, id, name, data); + } + + public abstract List getGlyphShapeTable(); + + public abstract void addCharacter(char character, Font font); + + public abstract boolean removeCharacter(char character); + + public abstract void setAdvanceValues(Font font); + + public abstract char glyphToChar(int glyphIndex); + + public abstract int charToGlyph(char c); + + public abstract double getGlyphAdvance(int glyphIndex); + + public abstract int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex); + + public abstract int getCharKerningAdjustment(char c1, char c2); + + public abstract int getGlyphWidth(int glyphIndex); + + public abstract String getFontNameIntag(); + + public abstract boolean isSmall(); + + public abstract boolean isBold(); + + public abstract boolean isItalic(); + + public abstract boolean isSmallEditable(); + + public abstract boolean isBoldEditable(); + + public abstract boolean isItalicEditable(); + + public abstract void setSmall(boolean value); + + public abstract void setBold(boolean value); + + public abstract void setItalic(boolean value); + + public abstract double getDivider(); + + public abstract int getAscent(); + + public abstract int getDescent(); + + public abstract int getLeading(); + + public String getFontName() { + DefineFontNameTag fontNameTag = getFontNameTag(); + if (fontNameTag == null) { + return getFontNameIntag(); + } + return fontNameTag.fontName; + } + + public String getFontCopyright() { + DefineFontNameTag fontNameTag = getFontNameTag(); + if (fontNameTag == null) { + return ""; + } + return fontNameTag.fontCopyright; + } + + public static Map> installedFontsByFamily; + + public static Map installedFontsByName; + + public static String defaultFontName; + + static { + reload(); + } + + public int getFontId() { + return getCharacterId(); + } + + public boolean hasLayout() { + return false; + } + + public boolean containsChar(char character) { + return charToGlyph(character) > -1; + } + + public int getFontStyle() { + int fontStyle = 0; + if (isBold()) { + fontStyle |= Font.BOLD; + } + if (isItalic()) { + fontStyle |= Font.ITALIC; + } + return fontStyle; + } + + public abstract int getCharacterCount(); + + public abstract String getCharacters(); + + @Override + public String getName() { + String nameAppend = ""; + if (exportName != null) { + nameAppend = ": " + exportName; + } + if (className != null) { + nameAppend = ": " + className; + } + String fontName = getFontNameIntag(); + if (fontName != null) { + nameAppend = ": " + fontName; + } + return tagName + " (" + getCharacterId() + nameAppend + ")"; + } + + @Override + public String getExportFileName() { + String result = super.getExportFileName(); + String fontName = getFontNameIntag(); + if (fontName != null) { + fontName = fontName.replace(" ", "_"); + } + return result + (fontName != null ? "_" + fontName : ""); + } + + public String getSystemFontName() { + int fontId = getFontId(); + String selectedFont = swf.sourceFontNamesMap.get(fontId); + if (selectedFont == null) { + SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(swf.getShortFileName()); + String key = fontId + "_" + getFontNameIntag(); + if (swfConf != null) { + selectedFont = swfConf.fontPairingMap.get(key); + } + } + + if (selectedFont == null) { + selectedFont = Configuration.getFontToNameMap().get(getFontNameIntag()); + } + + if (selectedFont != null && FontTag.installedFontsByName.containsKey(selectedFont)) { + return selectedFont; + } + + // findInstalledFontName always returns an available font name + return FontTag.findInstalledFontName(getFontName()); + } + + public Font getSystemFont() { + return FontTag.installedFontsByName.get(getSystemFontName()); + } + + protected void shiftGlyphIndices(int fontId, int startIndex, boolean increment) { + for (Tag t : swf.getTags()) { + List textRecords = null; + if (t instanceof StaticTextTag) { + textRecords = ((StaticTextTag) t).textRecords; + } + + if (textRecords != null) { + int curFontId = 0; + for (TEXTRECORD tr : textRecords) { + if (tr.styleFlagsHasFont) { + curFontId = tr.fontId; + } + + if (curFontId != fontId) { + continue; + } + + for (GLYPHENTRY en : tr.glyphEntries) { + if (en == null) { //Currently edited + continue; + } + if (en.glyphIndex >= startIndex) { + if (increment) { + en.glyphIndex++; + } else { + en.glyphIndex--; + } + } + } + + t.setModified(true); + } + } + } + } + + public static float getSystemFontAdvance(String fontName, int fontStyle, int fontSize, Character character, Character nextCharacter) { + return getSystemFontAdvance(new Font(fontName, fontStyle, fontSize), character, nextCharacter); + } + + public static float getSystemFontAdvance(Font aFont, Character character, Character nextCharacter) { + String chars = "" + character + (nextCharacter == null ? "" : nextCharacter); + GlyphVector gv = aFont.layoutGlyphVector(new FontRenderContext(aFont.getTransform(), true, true), chars.toCharArray(), 0, chars.length(), Font.LAYOUT_LEFT_TO_RIGHT); + GlyphMetrics gm = gv.getGlyphMetrics(0); + return gm.getAdvanceX(); + } + + public static void reload() { + installedFontsByFamily = FontHelper.getInstalledFonts(); + installedFontsByName = new HashMap<>(); + + for (String fam : installedFontsByFamily.keySet()) { + for (String nam : installedFontsByFamily.get(fam).keySet()) { + installedFontsByName.put(nam, installedFontsByFamily.get(fam).get(nam)); + } + } + + if (installedFontsByFamily.containsKey("Times New Roman")) { + defaultFontName = "Times New Roman"; + } else if (installedFontsByFamily.containsKey("Arial")) { + defaultFontName = "Arial"; + } else { + defaultFontName = installedFontsByFamily.keySet().iterator().next(); + } + } + + public static String getFontNameWithFallback(String fontName) { + if (installedFontsByFamily.containsKey(fontName)) { + return fontName; + } + if (installedFontsByFamily.containsKey("Times New Roman")) { + return "Times New Roman"; + } + if (installedFontsByFamily.containsKey("Arial")) { + return "Arial"; + } + + //First font + return installedFontsByFamily.keySet().iterator().next(); + } + + public static String isFontFamilyInstalled(String fontFamily) { + if (installedFontsByFamily.containsKey(fontFamily)) { + return fontFamily; + } + if (fontFamily.contains("_")) { + String beforeUnderscore = fontFamily.substring(0, fontFamily.indexOf('_')); + if (installedFontsByFamily.containsKey(beforeUnderscore)) { + return beforeUnderscore; + } + } + return null; + } + + public static String findInstalledFontName(String fontName) { + if (installedFontsByName.containsKey(fontName)) { + return fontName; + } + if (fontName != null && fontName.contains("_")) { + String beforeUnderscore = fontName.substring(0, fontName.indexOf('_')); + if (installedFontsByName.containsKey(beforeUnderscore)) { + return beforeUnderscore; + } + } + return defaultFontName; + } + + @Override + public int getUsedParameters() { + return PARAMETER_FRAME; + } + + @Override + public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, boolean stroked) { + RECT r = getRect(); + return new Area(new Rectangle(r.Xmin, r.Ymin, r.getWidth(), r.getHeight())); + } + + @Override + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform) { + SHAPERECORD.shapeListToImage(swf, getGlyphShapeTable(), image, frame, Color.black, colorTransform); + } + + @Override + public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) { + } + + @Override + public void toHtmlCanvas(StringBuilder result, double unitDivisor) { + List shapes = getGlyphShapeTable(); + result.append("\tdefaultFill = textColor;\r\n"); + result.append("\tswitch(ch){\r\n"); + for (int i = 0; i < shapes.size(); i++) { + char c = glyphToChar(i); + String cs = "" + c; + cs = cs.replace("\\", "\\\\").replace("\"", "\\\""); + result.append("\t\tcase \"").append(cs).append("\":\r\n"); + CanvasShapeExporter exporter = new CanvasShapeExporter(null, unitDivisor, swf, shapes.get(i), null, 0, 0); + exporter.export(); + result.append("\t\t").append(exporter.getShapeData().replaceAll("\r\n", "\r\n\t\t")); + result.append("\tbreak;\r\n"); + } + result.append("\t}\r\n"); + } + + @Override + public int getNumFrames() { + int frameCount = (getGlyphShapeTable().size() - 1) / SHAPERECORD.MAX_CHARACTERS_IN_FONT_PREVIEW + 1; + if (frameCount < 1) { + frameCount = 1; + } + return frameCount; + } + + @Override + public boolean isSingleFrame() { + return true; + } + + @Override + public RECT getRect() { + return getRect(null); // parameter not used + } + + @Override + public RECT getRect(Set added) { + return new RECT(0, (int) (PREVIEWSIZE * SWF.unitDivisor), 0, (int) (PREVIEWSIZE * SWF.unitDivisor)); + } + + @Override + public String getCharacterExportFileName() { + return super.getCharacterExportFileName() + "_" + getFontNameIntag(); + } + + public DefineFontNameTag getFontNameTag() { + for (Tag t : swf.getTags()) { + if (t instanceof DefineFontNameTag) { + DefineFontNameTag dfn = (DefineFontNameTag) t; + if (dfn.fontId == getFontId()) { + return dfn; + } + } + } + return null; + } + + public String getCopyright() { + DefineFontNameTag dfn = getFontNameTag(); + if (dfn == null) { + return null; + } + return dfn.fontCopyright; + } + + public RECT getGlyphBounds(int glyphIndex) { + return getGlyphShapeTable().get(glyphIndex).getBounds(); + } + + public FontTag toClassicFont() { + return this; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java index e0ffddddc..bf3f8b40c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java @@ -1,281 +1,281 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; -import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter; -import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; -import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter; -import com.jpexs.decompiler.flash.helpers.ImageHelper; -import com.jpexs.decompiler.flash.tags.TagInfo; -import com.jpexs.decompiler.flash.tags.enums.ImageFormat; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.decompiler.flash.types.FILLSTYLE; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.LINESTYLE; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.SerializableImage; -import java.awt.Dimension; -import java.awt.Shape; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public abstract class ImageTag extends DrawableTag { - - @SWFType(BasicType.UI16) - public int characterID; - - protected SerializableImage cachedImage; - - public ImageTag(SWF swf, int id, String name, ByteArrayRange data) { - super(swf, id, name, data); - } - - public abstract InputStream getOriginalImageData(); - - protected abstract SerializableImage getImage(); - - public abstract Dimension getImageDimension(); - - public abstract void setImage(byte[] data) throws IOException; - - public abstract ImageFormat getImageFormat(); - - public abstract ImageFormat getOriginalImageFormat(); - - public boolean importSupported() { - return true; - } - - public static ImageFormat getImageFormat(byte[] data) { - return getImageFormat(new ByteArrayRange(data)); - } - - public static ImageFormat getImageFormat(ByteArrayRange data) { - if (hasErrorHeader(data)) { - return ImageFormat.JPEG; - } - - if (data.getLength() > 2 && ((data.get(0) & 0xff) == 0xff) && ((data.get(1) & 0xff) == 0xd8)) { - return ImageFormat.JPEG; - } - - if (data.getLength() > 6 && ((data.get(0) & 0xff) == 0x47) && ((data.get(1) & 0xff) == 0x49) && ((data.get(2) & 0xff) == 0x46) && ((data.get(3) & 0xff) == 0x38) && ((data.get(4) & 0xff) == 0x39) && ((data.get(5) & 0xff) == 0x61)) { - return ImageFormat.GIF; - } - - if (data.getLength() > 8 && ((data.get(0) & 0xff) == 0x89) && ((data.get(1) & 0xff) == 0x50) && ((data.get(2) & 0xff) == 0x4e) && ((data.get(3) & 0xff) == 0x47) && ((data.get(4) & 0xff) == 0x0d) && ((data.get(5) & 0xff) == 0x0a) && ((data.get(6) & 0xff) == 0x1a) && ((data.get(7) & 0xff) == 0x0a)) { - return ImageFormat.PNG; - } - - return ImageFormat.UNKNOWN; - } - - public SerializableImage getImageCached() { - if (cachedImage != null) { - return cachedImage; - } - - SerializableImage image = getImage(); - if (Configuration.cacheImages.get()) { - cachedImage = image; - } - - return image; - } - - public InputStream getImageData() { - InputStream is = getOriginalImageData(); - if (is != null) { - return is; - } - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageHelper.write(getImage().getBufferedImage(), getImageFormat(), baos); - return new ByteArrayInputStream(baos.toByteArray()); - } - - public static boolean hasErrorHeader(byte[] data) { - return hasErrorHeader(new ByteArrayRange(data)); - } - - public static boolean hasErrorHeader(ByteArrayRange data) { - if (data.getLength() > 4) { - if ((data.get(0) & 0xff) == 0xff && (data.get(1) & 0xff) == 0xd9 - && (data.get(2) & 0xff) == 0xff && (data.get(3) & 0xff) == 0xd8) { - return true; - } - } - return false; - } - - private SHAPEWITHSTYLE getShape() { - RECT rect = getRect(); - return getShape(rect, false); - } - - public SHAPEWITHSTYLE getShape(RECT rect, boolean fill) { - boolean translated = rect.Xmin != 0 || rect.Ymin != 0; - SHAPEWITHSTYLE shape = new SHAPEWITHSTYLE(); - shape.fillStyles = new FILLSTYLEARRAY(); - shape.fillStyles.fillStyles = new FILLSTYLE[1]; - FILLSTYLE fillStyle = new FILLSTYLE(); - fillStyle.fillStyleType = Configuration.shapeImportUseNonSmoothedFill.get() - ? FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP : FILLSTYLE.REPEATING_BITMAP; - fillStyle.bitmapId = getCharacterId(); - MATRIX matrix = new MATRIX(); - matrix.hasScale = true; - if (fill) { - RECT imageRect = getRect(); - matrix.scaleX = (int) ((((long) SWF.unitDivisor) << 16) * rect.getWidth() / imageRect.getWidth()); - matrix.scaleY = (int) ((((long) SWF.unitDivisor) << 16) * rect.getHeight() / imageRect.getHeight()); - } else { - matrix.scaleX = ((int) SWF.unitDivisor) << 16; - matrix.scaleY = matrix.scaleX; - } - if (translated) { - matrix.translateX = rect.Xmin; - matrix.translateY = rect.Ymin; - } - fillStyle.bitmapMatrix = matrix; - shape.fillStyles.fillStyles[0] = fillStyle; - - shape.lineStyles = new LINESTYLEARRAY(); - shape.lineStyles.lineStyles = new LINESTYLE[0]; - shape.shapeRecords = new ArrayList<>(); - StyleChangeRecord style = new StyleChangeRecord(); - style.stateFillStyle0 = true; - style.fillStyle0 = 1; - style.stateMoveTo = true; - if (translated) { - style.moveDeltaX = rect.Xmin; - style.moveDeltaY = rect.Ymin; - } - shape.shapeRecords.add(style); - StraightEdgeRecord top = new StraightEdgeRecord(); - top.generalLineFlag = true; - top.deltaX = rect.getWidth(); - StraightEdgeRecord right = new StraightEdgeRecord(); - right.generalLineFlag = true; - right.deltaY = rect.getHeight(); - StraightEdgeRecord bottom = new StraightEdgeRecord(); - bottom.generalLineFlag = true; - bottom.deltaX = -rect.getWidth(); - StraightEdgeRecord left = new StraightEdgeRecord(); - left.generalLineFlag = true; - left.deltaY = -rect.getHeight(); - shape.shapeRecords.add(top); - shape.shapeRecords.add(right); - shape.shapeRecords.add(bottom); - shape.shapeRecords.add(left); - shape.shapeRecords.add(new EndShapeRecord()); - return shape; - } - - @Override - public RECT getRect() { - return getRect(null); // parameter not used - } - - @Override - public RECT getRect(Set added) { - Dimension dimension = getImageDimension(); - int widthInTwips = (int) (dimension.getWidth() * SWF.unitDivisor); - int heightInTwips = (int) (dimension.getHeight() * SWF.unitDivisor); - return new RECT(0, widthInTwips, 0, heightInTwips); - } - - @Override - public int getUsedParameters() { - return 0; - } - - @Override - public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, boolean stroked) { - return transformation.toTransform().createTransformedShape(getShape().getOutline(swf, stroked)); - } - - @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform) { - BitmapExporter.export(swf, getShape(), null, image, transformation, strokeTransformation, colorTransform); - } - - @Override - public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException { - SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, getShape(), exporter, null, colorTransform, 1); - shapeExporter.export(); - } - - @Override - public void toHtmlCanvas(StringBuilder result, double unitDivisor) { - CanvasShapeExporter cse = new CanvasShapeExporter(null, unitDivisor, swf, getShape(), null, 0, 0); - cse.export(); - result.append(cse.getShapeData()); - } - - @Override - public int getNumFrames() { - return 1; - } - - @Override - public boolean isSingleFrame() { - return true; - } - - public void clearCache() { - cachedImage = null; - } - - @Override - public void getTagInfo(TagInfo tagInfo) { - super.getTagInfo(tagInfo); - Dimension dimension = getImageDimension(); - tagInfo.addInfo("general", "width", dimension.getWidth()); - tagInfo.addInfo("general", "height", dimension.getHeight()); - } - - @Override - public int getCharacterId() { - return characterID; - } - - @Override - public void setCharacterId(int characterId) { - this.characterID = characterId; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; +import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter; +import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; +import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter; +import com.jpexs.decompiler.flash.helpers.ImageHelper; +import com.jpexs.decompiler.flash.tags.TagInfo; +import com.jpexs.decompiler.flash.tags.enums.ImageFormat; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.FILLSTYLE; +import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.LINESTYLE; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.SerializableImage; +import java.awt.Dimension; +import java.awt.Shape; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Set; + +/** + * + * @author JPEXS + */ +public abstract class ImageTag extends DrawableTag { + + @SWFType(BasicType.UI16) + public int characterID; + + protected SerializableImage cachedImage; + + public ImageTag(SWF swf, int id, String name, ByteArrayRange data) { + super(swf, id, name, data); + } + + public abstract InputStream getOriginalImageData(); + + protected abstract SerializableImage getImage(); + + public abstract Dimension getImageDimension(); + + public abstract void setImage(byte[] data) throws IOException; + + public abstract ImageFormat getImageFormat(); + + public abstract ImageFormat getOriginalImageFormat(); + + public boolean importSupported() { + return true; + } + + public static ImageFormat getImageFormat(byte[] data) { + return getImageFormat(new ByteArrayRange(data)); + } + + public static ImageFormat getImageFormat(ByteArrayRange data) { + if (hasErrorHeader(data)) { + return ImageFormat.JPEG; + } + + if (data.getLength() > 2 && ((data.get(0) & 0xff) == 0xff) && ((data.get(1) & 0xff) == 0xd8)) { + return ImageFormat.JPEG; + } + + if (data.getLength() > 6 && ((data.get(0) & 0xff) == 0x47) && ((data.get(1) & 0xff) == 0x49) && ((data.get(2) & 0xff) == 0x46) && ((data.get(3) & 0xff) == 0x38) && ((data.get(4) & 0xff) == 0x39) && ((data.get(5) & 0xff) == 0x61)) { + return ImageFormat.GIF; + } + + if (data.getLength() > 8 && ((data.get(0) & 0xff) == 0x89) && ((data.get(1) & 0xff) == 0x50) && ((data.get(2) & 0xff) == 0x4e) && ((data.get(3) & 0xff) == 0x47) && ((data.get(4) & 0xff) == 0x0d) && ((data.get(5) & 0xff) == 0x0a) && ((data.get(6) & 0xff) == 0x1a) && ((data.get(7) & 0xff) == 0x0a)) { + return ImageFormat.PNG; + } + + return ImageFormat.UNKNOWN; + } + + public SerializableImage getImageCached() { + if (cachedImage != null) { + return cachedImage; + } + + SerializableImage image = getImage(); + if (Configuration.cacheImages.get()) { + cachedImage = image; + } + + return image; + } + + public InputStream getImageData() { + InputStream is = getOriginalImageData(); + if (is != null) { + return is; + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageHelper.write(getImage().getBufferedImage(), getImageFormat(), baos); + return new ByteArrayInputStream(baos.toByteArray()); + } + + public static boolean hasErrorHeader(byte[] data) { + return hasErrorHeader(new ByteArrayRange(data)); + } + + public static boolean hasErrorHeader(ByteArrayRange data) { + if (data.getLength() > 4) { + if ((data.get(0) & 0xff) == 0xff && (data.get(1) & 0xff) == 0xd9 + && (data.get(2) & 0xff) == 0xff && (data.get(3) & 0xff) == 0xd8) { + return true; + } + } + return false; + } + + private SHAPEWITHSTYLE getShape() { + RECT rect = getRect(); + return getShape(rect, false); + } + + public SHAPEWITHSTYLE getShape(RECT rect, boolean fill) { + boolean translated = rect.Xmin != 0 || rect.Ymin != 0; + SHAPEWITHSTYLE shape = new SHAPEWITHSTYLE(); + shape.fillStyles = new FILLSTYLEARRAY(); + shape.fillStyles.fillStyles = new FILLSTYLE[1]; + FILLSTYLE fillStyle = new FILLSTYLE(); + fillStyle.fillStyleType = Configuration.shapeImportUseNonSmoothedFill.get() + ? FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP : FILLSTYLE.REPEATING_BITMAP; + fillStyle.bitmapId = getCharacterId(); + MATRIX matrix = new MATRIX(); + matrix.hasScale = true; + if (fill) { + RECT imageRect = getRect(); + matrix.scaleX = (int) ((((long) SWF.unitDivisor) << 16) * rect.getWidth() / imageRect.getWidth()); + matrix.scaleY = (int) ((((long) SWF.unitDivisor) << 16) * rect.getHeight() / imageRect.getHeight()); + } else { + matrix.scaleX = ((int) SWF.unitDivisor) << 16; + matrix.scaleY = matrix.scaleX; + } + if (translated) { + matrix.translateX = rect.Xmin; + matrix.translateY = rect.Ymin; + } + fillStyle.bitmapMatrix = matrix; + shape.fillStyles.fillStyles[0] = fillStyle; + + shape.lineStyles = new LINESTYLEARRAY(); + shape.lineStyles.lineStyles = new LINESTYLE[0]; + shape.shapeRecords = new ArrayList<>(); + StyleChangeRecord style = new StyleChangeRecord(); + style.stateFillStyle0 = true; + style.fillStyle0 = 1; + style.stateMoveTo = true; + if (translated) { + style.moveDeltaX = rect.Xmin; + style.moveDeltaY = rect.Ymin; + } + shape.shapeRecords.add(style); + StraightEdgeRecord top = new StraightEdgeRecord(); + top.generalLineFlag = true; + top.deltaX = rect.getWidth(); + StraightEdgeRecord right = new StraightEdgeRecord(); + right.generalLineFlag = true; + right.deltaY = rect.getHeight(); + StraightEdgeRecord bottom = new StraightEdgeRecord(); + bottom.generalLineFlag = true; + bottom.deltaX = -rect.getWidth(); + StraightEdgeRecord left = new StraightEdgeRecord(); + left.generalLineFlag = true; + left.deltaY = -rect.getHeight(); + shape.shapeRecords.add(top); + shape.shapeRecords.add(right); + shape.shapeRecords.add(bottom); + shape.shapeRecords.add(left); + shape.shapeRecords.add(new EndShapeRecord()); + return shape; + } + + @Override + public RECT getRect() { + return getRect(null); // parameter not used + } + + @Override + public RECT getRect(Set added) { + Dimension dimension = getImageDimension(); + int widthInTwips = (int) (dimension.getWidth() * SWF.unitDivisor); + int heightInTwips = (int) (dimension.getHeight() * SWF.unitDivisor); + return new RECT(0, widthInTwips, 0, heightInTwips); + } + + @Override + public int getUsedParameters() { + return 0; + } + + @Override + public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, boolean stroked) { + return transformation.toTransform().createTransformedShape(getShape().getOutline(swf, stroked)); + } + + @Override + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform) { + BitmapExporter.export(swf, getShape(), null, image, transformation, strokeTransformation, colorTransform); + } + + @Override + public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException { + SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, getShape(), exporter, null, colorTransform, 1); + shapeExporter.export(); + } + + @Override + public void toHtmlCanvas(StringBuilder result, double unitDivisor) { + CanvasShapeExporter cse = new CanvasShapeExporter(null, unitDivisor, swf, getShape(), null, 0, 0); + cse.export(); + result.append(cse.getShapeData()); + } + + @Override + public int getNumFrames() { + return 1; + } + + @Override + public boolean isSingleFrame() { + return true; + } + + public void clearCache() { + cachedImage = null; + } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + Dimension dimension = getImageDimension(); + tagInfo.addInfo("general", "width", dimension.getWidth()); + tagInfo.addInfo("general", "height", dimension.getHeight()); + } + + @Override + public int getCharacterId() { + return characterID; + } + + @Override + public void setCharacterId(int characterId) { + this.characterID = characterId; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java index 609f1be69..5980c4e2a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java @@ -1,459 +1,459 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.tags.gfx; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.helpers.FontHelper; -import com.jpexs.decompiler.flash.tags.DefineFont2Tag; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.gfx.FontType; -import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; -import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; -import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType; -import com.jpexs.decompiler.flash.types.gfx.GlyphType; -import com.jpexs.decompiler.flash.types.gfx.KerningPairType; -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.MemoryInputStream; -import java.awt.Font; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author JPEXS - */ -public final class DefineCompactedFont extends FontTag { - - public static final int ID = 1005; - - public static final String NAME = "DefineCompactedFont"; - - public int fontId; - - public List fonts; - - private List shapeCache; - - /** - * Gets data bytes - * - * @param sos SWF output stream - * @throws java.io.IOException - */ - @Override - public void getData(SWFOutputStream sos) throws IOException { - sos.writeUI16(fontId); - for (FontType ft : fonts) { - ft.write(new GFxOutputStream(sos)); - } - } - - /** - * Constructor - * - * @param swf - */ - public DefineCompactedFont(SWF swf) { - super(swf, ID, NAME, null); - fontId = swf.getNextCharacterId(); - - fonts = new ArrayList<>(); - FontType ft = new FontType(); - fonts.add(ft); - - rebuildShapeCache(); - } - - /** - * Constructor - * - * @param sis - * @param data - * @throws IOException - */ - public DefineCompactedFont(SWFInputStream sis, ByteArrayRange data) throws IOException { - super(sis.getSwf(), ID, NAME, data); - readData(sis, data, 0, false, false, false); - } - - @Override - public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - fontId = sis.readUI16("fontId"); - fonts = new ArrayList<>(); - - MemoryInputStream mis = sis.getBaseStream(); - while (mis.available() > 0) { - GFxInputStream gis = new GFxInputStream(mis); - gis.dumpInfo = sis.dumpInfo; - gis.newDumpLevel("fontType", "FontType"); - fonts.add(new FontType(gis)); - gis.endDumpLevel(); - } - sis.skipBytes(sis.available()); - if (fonts.size() > 1) { - Logger.getLogger(DefineCompactedFont.class.getName()).log(Level.WARNING, "Compacted font has more than one FontType inside. This may cause problems while editing."); - } - rebuildShapeCache(); - } - - public void rebuildShapeCache() { - shapeCache = fonts.get(0).getGlyphShapes(); - } - - @Override - public String getFontNameIntag() { - StringBuilder ret = new StringBuilder(); - for (int i = 0; i < fonts.size(); i++) { - if (i > 0) { - ret.append(", "); - } - ret.append(fonts.get(i).fontName); - } - return ret.toString(); - } - - @Override - public int getCharacterId() { - return fontId; - } - - @Override - public void setCharacterId(int characterId) { - this.fontId = characterId; - } - - @Override - public List getGlyphShapeTable() { - return shapeCache; - } - - @Override - public void addCharacter(char character, Font cfont) { - int fontStyle = getFontStyle(); - FontType font = fonts.get(0); - - double d = 1; - SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(cfont, (int) (font.nominalSize * d), character); - - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < font.glyphInfo.size(); i++) { - if (font.glyphInfo.get(i).glyphCode >= code) { - if (font.glyphInfo.get(i).glyphCode == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = font.glyphInfo.size(); - } - - if (!exists) { - shiftGlyphIndices(fontId, pos, true); - } - - Font fnt = cfont.deriveFont(fontStyle, Math.round(font.nominalSize * d)); - int advance = (int) Math.round(FontHelper.getFontAdvance(fnt, character)); - if (!exists) { - font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0)); - font.glyphs.add(pos, new GlyphType(shp.shapeRecords)); - shapeCache.add(pos, font.glyphs.get(pos).toSHAPE()); - } else { - font.glyphInfo.set(pos, new GlyphInfoType(code, advance, 0)); - font.glyphs.set(pos, new GlyphType(shp.shapeRecords)); - shapeCache.set(pos, font.glyphs.get(pos).toSHAPE()); - } - - setModified(true); - getSwf().clearImageCache(); - } - - @Override - public boolean removeCharacter(char character) { - FontType font = fonts.get(0); - - int code = (int) character; - int pos = -1; - for (int i = 0; i < font.glyphInfo.size(); i++) { - if (font.glyphInfo.get(i).glyphCode >= code) { - if (font.glyphInfo.get(i).glyphCode == code) { - pos = i; - break; - } - - return false; - } - } - - if (pos == -1) { - return false; - } - - font.glyphInfo.remove(pos); - font.glyphs.remove(pos); - shapeCache.remove(pos); - shiftGlyphIndices(fontId, pos + 1, false); - - setModified(true); - getSwf().clearImageCache(); - return true; - } - - @Override - public void setAdvanceValues(Font font) { - throw new UnsupportedOperationException("Setting the advance values for DefineCompactedFont is not supported."); - } - - @Override - public char glyphToChar(int glyphIndex) { - return (char) fonts.get(0).glyphInfo.get(glyphIndex).glyphCode; - } - - @Override - public int charToGlyph(char c) { - FontType ft = fonts.get(0); - for (int i = 0; i < ft.glyphInfo.size(); i++) { - if (ft.glyphInfo.get(i).glyphCode == c) { - return i; - } - } - return -1; - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - return resize(fonts.get(0).glyphInfo.get(glyphIndex).advanceX); - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - char c1 = glyphToChar(glyphIndex); - char c2 = glyphToChar(nextGlyphIndex); - return getCharKerningAdjustment(c1, c2); - } - - @Override - public int getCharKerningAdjustment(char c1, char c2) { - for (KerningPairType kp : fonts.get(0).kerning) { - if (kp.char1 == c1 && kp.char2 == c2) { - return resize(kp.advance); - } - } - return 0; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return resize(getGlyphShapeTable().get(glyphIndex).getBounds().getWidth()); - } - - @Override - public boolean isSmall() { - return false; - } - - @Override - public boolean isBold() { - return (fonts.get(0).flags & FontType.FF_Bold) == FontType.FF_Bold; - } - - @Override - public boolean isItalic() { - return (fonts.get(0).flags & FontType.FF_Italic) == FontType.FF_Italic; - } - - @Override - public boolean isSmallEditable() { - return false; - } - - @Override - public boolean isBoldEditable() { - return true; - } - - @Override - public boolean isItalicEditable() { - return true; - } - - @Override - public void setSmall(boolean value) { - } - - @Override - public void setBold(boolean value) { - for (FontType font : fonts) { - font.flags &= FontType.FF_Bold; - if (!value) { - font.flags ^= FontType.FF_Bold; - } - } - } - - @Override - public void setItalic(boolean value) { - for (FontType font : fonts) { - font.flags &= FontType.FF_Italic; - if (!value) { - font.flags ^= FontType.FF_Italic; - } - } - } - - @Override - public double getDivider() { - return 1; - } - - @Override - public int getAscent() { - return fonts.get(0).ascent; - } - - @Override - public int getDescent() { - return fonts.get(0).descent; - } - - @Override - public int getLeading() { - return fonts.get(0).leading; - } - - @Override - public int getCharacterCount() { - FontType ft = fonts.get(0); - return ft.glyphInfo.size(); - } - - @Override - public String getCharacters() { - FontType ft = fonts.get(0); - StringBuilder ret = new StringBuilder(ft.glyphInfo.size()); - for (GlyphInfoType gi : ft.glyphInfo) { - ret.append((char) gi.glyphCode); - } - return ret.toString(); - } - - @Override - public RECT getGlyphBounds(int glyphIndex) { - GlyphType gt = fonts.get(0).glyphs.get(glyphIndex); - return new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3])); - } - - public SHAPE resizeShape(SHAPE shp) { - SHAPE ret = new SHAPE(); - ret.numFillBits = 1; - ret.numLineBits = 0; - List recs = new ArrayList<>(); - for (SHAPERECORD r : shp.shapeRecords) { - SHAPERECORD c = r.clone(); - if (c instanceof StyleChangeRecord) { - StyleChangeRecord scr = (StyleChangeRecord) c; - scr.moveDeltaX = resize(scr.moveDeltaX); - scr.moveDeltaY = resize(scr.moveDeltaY); - scr.calculateBits(); - } - if (c instanceof CurvedEdgeRecord) { - CurvedEdgeRecord cer = (CurvedEdgeRecord) c; - cer.controlDeltaX = resize(cer.controlDeltaX); - cer.controlDeltaY = resize(cer.controlDeltaY); - cer.anchorDeltaX = resize(cer.anchorDeltaX); - cer.anchorDeltaY = resize(cer.anchorDeltaY); - cer.calculateBits(); - } - if (c instanceof StraightEdgeRecord) { - StraightEdgeRecord ser = (StraightEdgeRecord) c; - ser.deltaX = resize(ser.deltaX); - ser.deltaY = resize(ser.deltaY); - ser.calculateBits(); - } - recs.add(c); - } - ret.shapeRecords = recs; - return ret; - } - - protected int resize(double val) { - FontType ft = fonts.get(0); - return (int) Math.round(val * 1024.0 / ft.nominalSize); - } - - @Override - public FontTag toClassicFont() { - DefineFont2Tag ret = new DefineFont2Tag(swf); - ret.fontID = getFontId(); - ret.fontFlagsBold = isBold(); - ret.fontFlagsItalic = isItalic(); - ret.fontFlagsWideOffsets = true; - ret.fontFlagsWideCodes = true; - ret.fontFlagsHasLayout = true; - ret.fontAscent = (getAscent()); - ret.fontDescent = (getDescent()); - ret.fontLeading = (getLeading()); - ret.fontAdvanceTable = new ArrayList<>(); - ret.fontBoundsTable = new ArrayList<>(); - ret.codeTable = new ArrayList<>(); - ret.glyphShapeTable = new ArrayList<>(); - List shp = getGlyphShapeTable(); - for (int g = 0; g < shp.size(); g++) { - ret.fontAdvanceTable.add(resize(getGlyphAdvance(g))); - ret.codeTable.add((int) glyphToChar(g)); - - SHAPE shpX = resizeShape(shp.get(g)); - ret.glyphShapeTable.add(shpX); - ret.fontBoundsTable.add(getGlyphBounds(g)); - } - ret.fontName = getFontNameIntag(); - ret.languageCode = new LANGCODE(1); - ret.fontKerningTable = new ArrayList<>(); - - FontType ft = fonts.get(0); - for (int i = 0; i < ft.kerning.size(); i++) { - KERNINGRECORD kr = new KERNINGRECORD(); - kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance); - kr.fontKerningCode1 = ft.kerning.get(i).char1; - kr.fontKerningCode2 = ft.kerning.get(i).char2; - ret.fontKerningTable.add(kr); - } - - return ret; - } - - @Override - public boolean hasLayout() { - return true; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.helpers.FontHelper; +import com.jpexs.decompiler.flash.tags.DefineFont2Tag; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.gfx.FontType; +import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; +import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; +import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType; +import com.jpexs.decompiler.flash.types.gfx.GlyphType; +import com.jpexs.decompiler.flash.types.gfx.KerningPairType; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.MemoryInputStream; +import java.awt.Font; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public final class DefineCompactedFont extends FontTag { + + public static final int ID = 1005; + + public static final String NAME = "DefineCompactedFont"; + + public int fontId; + + public List fonts; + + private List shapeCache; + + /** + * Gets data bytes + * + * @param sos SWF output stream + * @throws java.io.IOException + */ + @Override + public void getData(SWFOutputStream sos) throws IOException { + sos.writeUI16(fontId); + for (FontType ft : fonts) { + ft.write(new GFxOutputStream(sos)); + } + } + + /** + * Constructor + * + * @param swf + */ + public DefineCompactedFont(SWF swf) { + super(swf, ID, NAME, null); + fontId = swf.getNextCharacterId(); + + fonts = new ArrayList<>(); + FontType ft = new FontType(); + fonts.add(ft); + + rebuildShapeCache(); + } + + /** + * Constructor + * + * @param sis + * @param data + * @throws IOException + */ + public DefineCompactedFont(SWFInputStream sis, ByteArrayRange data) throws IOException { + super(sis.getSwf(), ID, NAME, data); + readData(sis, data, 0, false, false, false); + } + + @Override + public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { + fontId = sis.readUI16("fontId"); + fonts = new ArrayList<>(); + + MemoryInputStream mis = sis.getBaseStream(); + while (mis.available() > 0) { + GFxInputStream gis = new GFxInputStream(mis); + gis.dumpInfo = sis.dumpInfo; + gis.newDumpLevel("fontType", "FontType"); + fonts.add(new FontType(gis)); + gis.endDumpLevel(); + } + sis.skipBytes(sis.available()); + if (fonts.size() > 1) { + Logger.getLogger(DefineCompactedFont.class.getName()).log(Level.WARNING, "Compacted font has more than one FontType inside. This may cause problems while editing."); + } + rebuildShapeCache(); + } + + public void rebuildShapeCache() { + shapeCache = fonts.get(0).getGlyphShapes(); + } + + @Override + public String getFontNameIntag() { + StringBuilder ret = new StringBuilder(); + for (int i = 0; i < fonts.size(); i++) { + if (i > 0) { + ret.append(", "); + } + ret.append(fonts.get(i).fontName); + } + return ret.toString(); + } + + @Override + public int getCharacterId() { + return fontId; + } + + @Override + public void setCharacterId(int characterId) { + this.fontId = characterId; + } + + @Override + public List getGlyphShapeTable() { + return shapeCache; + } + + @Override + public void addCharacter(char character, Font cfont) { + int fontStyle = getFontStyle(); + FontType font = fonts.get(0); + + double d = 1; + SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(cfont, (int) (font.nominalSize * d), character); + + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < font.glyphInfo.size(); i++) { + if (font.glyphInfo.get(i).glyphCode >= code) { + if (font.glyphInfo.get(i).glyphCode == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = font.glyphInfo.size(); + } + + if (!exists) { + shiftGlyphIndices(fontId, pos, true); + } + + Font fnt = cfont.deriveFont(fontStyle, Math.round(font.nominalSize * d)); + int advance = (int) Math.round(FontHelper.getFontAdvance(fnt, character)); + if (!exists) { + font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0)); + font.glyphs.add(pos, new GlyphType(shp.shapeRecords)); + shapeCache.add(pos, font.glyphs.get(pos).toSHAPE()); + } else { + font.glyphInfo.set(pos, new GlyphInfoType(code, advance, 0)); + font.glyphs.set(pos, new GlyphType(shp.shapeRecords)); + shapeCache.set(pos, font.glyphs.get(pos).toSHAPE()); + } + + setModified(true); + getSwf().clearImageCache(); + } + + @Override + public boolean removeCharacter(char character) { + FontType font = fonts.get(0); + + int code = (int) character; + int pos = -1; + for (int i = 0; i < font.glyphInfo.size(); i++) { + if (font.glyphInfo.get(i).glyphCode >= code) { + if (font.glyphInfo.get(i).glyphCode == code) { + pos = i; + break; + } + + return false; + } + } + + if (pos == -1) { + return false; + } + + font.glyphInfo.remove(pos); + font.glyphs.remove(pos); + shapeCache.remove(pos); + shiftGlyphIndices(fontId, pos + 1, false); + + setModified(true); + getSwf().clearImageCache(); + return true; + } + + @Override + public void setAdvanceValues(Font font) { + throw new UnsupportedOperationException("Setting the advance values for DefineCompactedFont is not supported."); + } + + @Override + public char glyphToChar(int glyphIndex) { + return (char) fonts.get(0).glyphInfo.get(glyphIndex).glyphCode; + } + + @Override + public int charToGlyph(char c) { + FontType ft = fonts.get(0); + for (int i = 0; i < ft.glyphInfo.size(); i++) { + if (ft.glyphInfo.get(i).glyphCode == c) { + return i; + } + } + return -1; + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + return resize(fonts.get(0).glyphInfo.get(glyphIndex).advanceX); + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + char c1 = glyphToChar(glyphIndex); + char c2 = glyphToChar(nextGlyphIndex); + return getCharKerningAdjustment(c1, c2); + } + + @Override + public int getCharKerningAdjustment(char c1, char c2) { + for (KerningPairType kp : fonts.get(0).kerning) { + if (kp.char1 == c1 && kp.char2 == c2) { + return resize(kp.advance); + } + } + return 0; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return resize(getGlyphShapeTable().get(glyphIndex).getBounds().getWidth()); + } + + @Override + public boolean isSmall() { + return false; + } + + @Override + public boolean isBold() { + return (fonts.get(0).flags & FontType.FF_Bold) == FontType.FF_Bold; + } + + @Override + public boolean isItalic() { + return (fonts.get(0).flags & FontType.FF_Italic) == FontType.FF_Italic; + } + + @Override + public boolean isSmallEditable() { + return false; + } + + @Override + public boolean isBoldEditable() { + return true; + } + + @Override + public boolean isItalicEditable() { + return true; + } + + @Override + public void setSmall(boolean value) { + } + + @Override + public void setBold(boolean value) { + for (FontType font : fonts) { + font.flags &= FontType.FF_Bold; + if (!value) { + font.flags ^= FontType.FF_Bold; + } + } + } + + @Override + public void setItalic(boolean value) { + for (FontType font : fonts) { + font.flags &= FontType.FF_Italic; + if (!value) { + font.flags ^= FontType.FF_Italic; + } + } + } + + @Override + public double getDivider() { + return 1; + } + + @Override + public int getAscent() { + return fonts.get(0).ascent; + } + + @Override + public int getDescent() { + return fonts.get(0).descent; + } + + @Override + public int getLeading() { + return fonts.get(0).leading; + } + + @Override + public int getCharacterCount() { + FontType ft = fonts.get(0); + return ft.glyphInfo.size(); + } + + @Override + public String getCharacters() { + FontType ft = fonts.get(0); + StringBuilder ret = new StringBuilder(ft.glyphInfo.size()); + for (GlyphInfoType gi : ft.glyphInfo) { + ret.append((char) gi.glyphCode); + } + return ret.toString(); + } + + @Override + public RECT getGlyphBounds(int glyphIndex) { + GlyphType gt = fonts.get(0).glyphs.get(glyphIndex); + return new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3])); + } + + public SHAPE resizeShape(SHAPE shp) { + SHAPE ret = new SHAPE(); + ret.numFillBits = 1; + ret.numLineBits = 0; + List recs = new ArrayList<>(); + for (SHAPERECORD r : shp.shapeRecords) { + SHAPERECORD c = r.clone(); + if (c instanceof StyleChangeRecord) { + StyleChangeRecord scr = (StyleChangeRecord) c; + scr.moveDeltaX = resize(scr.moveDeltaX); + scr.moveDeltaY = resize(scr.moveDeltaY); + scr.calculateBits(); + } + if (c instanceof CurvedEdgeRecord) { + CurvedEdgeRecord cer = (CurvedEdgeRecord) c; + cer.controlDeltaX = resize(cer.controlDeltaX); + cer.controlDeltaY = resize(cer.controlDeltaY); + cer.anchorDeltaX = resize(cer.anchorDeltaX); + cer.anchorDeltaY = resize(cer.anchorDeltaY); + cer.calculateBits(); + } + if (c instanceof StraightEdgeRecord) { + StraightEdgeRecord ser = (StraightEdgeRecord) c; + ser.deltaX = resize(ser.deltaX); + ser.deltaY = resize(ser.deltaY); + ser.calculateBits(); + } + recs.add(c); + } + ret.shapeRecords = recs; + return ret; + } + + protected int resize(double val) { + FontType ft = fonts.get(0); + return (int) Math.round(val * 1024.0 / ft.nominalSize); + } + + @Override + public FontTag toClassicFont() { + DefineFont2Tag ret = new DefineFont2Tag(swf); + ret.fontID = getFontId(); + ret.fontFlagsBold = isBold(); + ret.fontFlagsItalic = isItalic(); + ret.fontFlagsWideOffsets = true; + ret.fontFlagsWideCodes = true; + ret.fontFlagsHasLayout = true; + ret.fontAscent = (getAscent()); + ret.fontDescent = (getDescent()); + ret.fontLeading = (getLeading()); + ret.fontAdvanceTable = new ArrayList<>(); + ret.fontBoundsTable = new ArrayList<>(); + ret.codeTable = new ArrayList<>(); + ret.glyphShapeTable = new ArrayList<>(); + List shp = getGlyphShapeTable(); + for (int g = 0; g < shp.size(); g++) { + ret.fontAdvanceTable.add(resize(getGlyphAdvance(g))); + ret.codeTable.add((int) glyphToChar(g)); + + SHAPE shpX = resizeShape(shp.get(g)); + ret.glyphShapeTable.add(shpX); + ret.fontBoundsTable.add(getGlyphBounds(g)); + } + ret.fontName = getFontNameIntag(); + ret.languageCode = new LANGCODE(1); + ret.fontKerningTable = new ArrayList<>(); + + FontType ft = fonts.get(0); + for (int i = 0; i < ft.kerning.size(); i++) { + KERNINGRECORD kr = new KERNINGRECORD(); + kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance); + kr.fontKerningCode1 = ft.kerning.get(i).char1; + kr.fontKerningCode2 = ft.kerning.get(i).char2; + ret.fontKerningTable.add(kr); + } + + return ret; + } + + @Override + public boolean hasLayout() { + return true; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/LINESTYLE.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/LINESTYLE.java index 781e37869..172e5e810 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/LINESTYLE.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/LINESTYLE.java @@ -1,52 +1,52 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.types; - -import com.jpexs.decompiler.flash.tags.DefineShape3Tag; -import com.jpexs.decompiler.flash.tags.DefineShape4Tag; -import com.jpexs.decompiler.flash.tags.base.NeedsCharacters; -import com.jpexs.decompiler.flash.types.annotations.ConditionalType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.Serializable; -import java.util.Set; - -/** - * - * @author JPEXS - */ -public class LINESTYLE implements NeedsCharacters, Serializable { - - @SWFType(BasicType.UI16) - public int width; - - @ConditionalType(tags = {DefineShape3Tag.ID, DefineShape4Tag.ID}, type = RGBA.class) - public RGB color; - - @Override - public void getNeededCharacters(Set needed) { - } - - @Override - public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { - return false; - } - - @Override - public boolean removeCharacter(int characterId) { - return false; - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.types; + +import com.jpexs.decompiler.flash.tags.DefineShape3Tag; +import com.jpexs.decompiler.flash.tags.DefineShape4Tag; +import com.jpexs.decompiler.flash.tags.base.NeedsCharacters; +import com.jpexs.decompiler.flash.types.annotations.ConditionalType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.Serializable; +import java.util.Set; + +/** + * + * @author JPEXS + */ +public class LINESTYLE implements NeedsCharacters, Serializable { + + @SWFType(BasicType.UI16) + public int width; + + @ConditionalType(tags = {DefineShape3Tag.ID, DefineShape4Tag.ID}, type = RGBA.class) + public RGB color; + + @Override + public void getNeededCharacters(Set needed) { + } + + @Override + public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { + return false; + } + + @Override + public boolean removeCharacter(int characterId) { + return false; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/EdgeType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/EdgeType.java index 4d33087b2..13e7b1c2a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/EdgeType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/EdgeType.java @@ -1,484 +1,484 @@ -/* - * Copyright (C) 2010-2016 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.flash.types.gfx; - -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; -import java.io.IOException; -import java.io.Serializable; - -/** - * - * @author JPEXS - */ -public class EdgeType implements Serializable { - - private static final int[] sizes = new int[]{1, 2, 1, 2, 1, 2, 3, 4, 2, 3, 4, 5, 6, 7, 8, 9}; - - private static final int Edge_H12 = 0; // 2 bytes - - private static final int Edge_H20 = 1; // 3 bytes - - private static final int Edge_V12 = 2; // 2 bytes - - private static final int Edge_V20 = 3; // 3 bytes - - private static final int Edge_L6 = 4; // 2 bytes - - private static final int Edge_L10 = 5; // 3 bytes - - private static final int Edge_L14 = 6; // 4 bytes - - private static final int Edge_L18 = 7; // 5 bytes - - private static final int Edge_C5 = 8; // 3 bytes - - private static final int Edge_C7 = 9; // 4 bytes - - private static final int Edge_C9 = 10; // 5 bytes - - private static final int Edge_C11 = 11; // 6 bytes - - private static final int Edge_C13 = 12; // 7 bytes - - private static final int Edge_C15 = 13; // 8 bytes - - private static final int Edge_C17 = 14; // 9 bytes - - private static final int Edge_C19 = 15; // 10 bytes - - private static final int Edge_HLine = 0; - - private static final int Edge_VLine = 1; - - private static final int Edge_Line = 2; - - private static final int Edge_Quad = 3; - - public int[] data; - - public EdgeType(boolean vertical, int v) { - data = new int[]{vertical ? Edge_VLine : Edge_HLine, v}; - } - - public EdgeType(int x, int y) { - data = new int[]{Edge_Line, x, y}; - } - - public EdgeType(int cx, int cy, int ax, int ay) { - data = new int[]{Edge_Quad, cx, cy, ax, ay}; - } - - @Override - public String toString() { - String ret = "[Edge data:"; - for (int i = 0; i < data.length; i++) { - if (i > 0) { - ret += ", "; - } - ret += "" + data[i]; - } - ret += "]"; - return ret; - } - - public EdgeType(GFxInputStream sis) throws IOException { - data = readEdge(sis); - /*if((raw[0]&0xf) == Edge_V20){ - data[1] = 0; - } - if((raw[0]&0xf) == Edge_C17){ - //System.out.println("========== 17 : "+toString()) ; - data[1] = 0; - data[2] = 0; - data[3] = 0; - data[4] = 0; - }*/ - } - - private static int SInt8(int val) { - /*boolean sign = (val & 0x80) == 0x80; - val = val & 0x7F; - if (sign) { - val = -val; - } - return val;*/ - return (byte) val; - } - - public SHAPERECORD toSHAPERECORD() { - int multiplier = 1; - StraightEdgeRecord ser; - CurvedEdgeRecord cer; - switch (data[0]) { - case Edge_HLine: - ser = new StraightEdgeRecord(); - ser.generalLineFlag = false; - ser.deltaX = data[1] * multiplier; - ser.calculateBits(); - return ser; - case Edge_VLine: - ser = new StraightEdgeRecord(); - ser.generalLineFlag = false; - ser.vertLineFlag = true; - ser.deltaY = data[1] * multiplier; - ser.calculateBits(); - return ser; - case Edge_Line: - ser = new StraightEdgeRecord(); - ser.generalLineFlag = true; - ser.deltaX = data[1] * multiplier; - ser.deltaY = data[2] * multiplier; - ser.calculateBits(); - return ser; - case Edge_Quad: - cer = new CurvedEdgeRecord(); - cer.controlDeltaX = data[1] * multiplier; - cer.controlDeltaY = data[2] * multiplier; - cer.anchorDeltaX = data[3] * multiplier; - cer.anchorDeltaY = data[4] * multiplier; - cer.calculateBits(); - return cer; - } - return null; - } - - private int[] readEdge(GFxInputStream sis) throws IOException { - byte firstByte = (byte) sis.readUI8("firstByte"); - byte raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8, raw9; - raw1 = (byte) sis.readUI8("byte1"); - int[] data = new int[5]; - - switch (firstByte & 0xF) { - case Edge_H12: - data[0] = Edge_HLine; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8(raw1 & 0xff) << 4); - break; - - case Edge_H20: - raw2 = (byte) sis.readUI8("byte2"); - data[0] = Edge_HLine; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 & 0xff) << 12); - break; - - case Edge_V12: - data[0] = Edge_VLine; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8(raw1 & 0xff) << 4); - break; - - case Edge_V20: - data[0] = Edge_VLine; - raw2 = (byte) sis.readUI8("byte2"); - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 & 0xff) << 12); - break; - - case Edge_L6: - data[0] = Edge_Line; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 6) >> 2); - data[2] = SInt8(raw1 & 0xff) >> 2; - break; - - case Edge_L10: - raw2 = (byte) sis.readUI8("byte2"); - data[0] = Edge_Line; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 2) << 2); - data[2] = ((raw1 & 0xff) >> 6) | (SInt8((raw2 & 0xff)) << 2); - break; - - case Edge_L14: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - data[0] = Edge_Line; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 6) << 6); - data[2] = ((raw2 & 0xff) >> 2) | (SInt8((raw3 & 0xff)) << 6); - break; - - case Edge_L18: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - data[0] = Edge_Line; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 2) << 10); - data[2] = ((raw2 & 0xff) >> 6) | ((raw3 & 0xff) << 2) | (SInt8((raw4 & 0xff)) << 10); - break; - - case Edge_C5: - raw2 = (byte) sis.readUI8("byte2"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 7) >> 3); - data[2] = SInt8((raw1 & 0xff) << 2) >> 3; - data[3] = ((raw1 & 0xff) >> 6) | (SInt8((raw2 & 0xff) << 5) >> 3); - data[4] = SInt8((raw2 & 0xff)) >> 3; - break; - - case Edge_C7: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 5) >> 1); - data[2] = ((raw1 & 0xff) >> 3) | (SInt8((raw2 & 0xff) << 6) >> 1); - data[3] = ((raw2 & 0xff) >> 2) | (SInt8((raw3 & 0xff) << 7) >> 1); - data[4] = SInt8(raw3) >> 1; - break; - - case Edge_C9: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 3) << 1); - data[2] = ((raw1 & 0xff) >> 5) | (SInt8((raw2 & 0xff) << 2) << 1); - data[3] = ((raw2 & 0xff) >> 6) | (SInt8((raw3 & 0xff) << 1) << 1); - data[4] = ((raw3 & 0xff) >> 7) | (SInt8(raw4 & 0xff) << 1); - break; - - case Edge_C11: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - raw5 = (byte) sis.readUI8("byte5"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 1) << 3); - data[2] = (raw1 >> 7) | ((raw2 & 0xff) << 1) | (SInt8((raw3 & 0xff) << 6) << 3); - data[3] = ((raw3 & 0xff) >> 2) | (SInt8((raw4 & 0xff) << 3) << 3); - data[4] = ((raw4 & 0xff) >> 5) | (SInt8(raw5 & 0xff) << 3); - break; - - case Edge_C13: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - raw5 = (byte) sis.readUI8("byte5"); - raw6 = (byte) sis.readUI8("byte6"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 7) << 5); - data[2] = ((raw2 & 0xff) >> 1) | (SInt8((raw3 & 0xff) << 2) << 5); - data[3] = ((raw3 & 0xff) >> 6) | ((raw4 & 0xff) << 2) | (SInt8((raw5 & 0xff) << 5) << 5); - data[4] = ((raw5 & 0xff) >> 3) | (SInt8(raw6 & 0xff) << 5); - break; - - case Edge_C15: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - raw5 = (byte) sis.readUI8("byte5"); - raw6 = (byte) sis.readUI8("byte6"); - raw7 = (byte) sis.readUI8("byte7"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 5) << 7); - data[2] = ((raw2 & 0xff) >> 3) | ((raw3 & 0xff) << 5) | (SInt8((raw4 & 0xff) << 6) << 7); - data[3] = ((raw4 & 0xff) >> 2) | ((raw5 & 0xff) << 6) | (SInt8((raw6 & 0xff) << 7) << 7); - data[4] = ((raw6 & 0xff) >> 1) | (SInt8((raw7 & 0xff)) << 7); - break; - - case Edge_C17: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - raw5 = (byte) sis.readUI8("byte5"); - raw6 = (byte) sis.readUI8("byte6"); - raw7 = (byte) sis.readUI8("byte7"); - raw8 = (byte) sis.readUI8("byte8"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 3) << 9); - data[2] = ((raw2 & 0xff) >> 5) | ((raw3 & 0xff) << 3) | (SInt8((raw4 & 0xff) << 2) << 9); - data[3] = ((raw4 & 0xff) >> 6) | ((raw5 & 0xff) << 2) | (SInt8((raw6 & 0xff) << 1) << 9); - data[4] = ((raw6 & 0xff) >> 7) | ((raw7 & 0xff) << 1) | (SInt8(raw8 & 0xff) << 9); - break; - - case Edge_C19: - raw2 = (byte) sis.readUI8("byte2"); - raw3 = (byte) sis.readUI8("byte3"); - raw4 = (byte) sis.readUI8("byte4"); - raw5 = (byte) sis.readUI8("byte5"); - raw6 = (byte) sis.readUI8("byte6"); - raw7 = (byte) sis.readUI8("byte7"); - raw8 = (byte) sis.readUI8("byte8"); - raw9 = (byte) sis.readUI8("byte9"); - data[0] = Edge_Quad; - data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 << 1) << 11); - data[2] = ((raw2 & 0xff) >> 7) | ((raw3 & 0xff) << 1) | ((raw4 & 0xff) << 9) | (SInt8(raw5 << 6) << 11); - data[3] = ((raw5 & 0xff) >> 2) | ((raw6 & 0xff) << 6) | (SInt8(raw7 << 3) << 11); - data[4] = ((raw7 & 0xff) >> 5) | ((raw8 & 0xff) << 3) | (SInt8(raw9) << 11); - break; - } - return data; - } - - public void write(GFxOutputStream sos) throws IOException { - int x; - int y; - int m1 = 1; - int m2 = 3; - int m3 = 7; - int m4 = 0xF; - int m5 = 0x1F; - int m6 = 0x3F; - int m7 = 0x7F; - switch (data[0]) { - case Edge_HLine: - x = data[1]; - if (x >= GFxOutputStream.MinSInt12 && x <= GFxOutputStream.MaxSInt12) { - sos.writeUI8((x << 4) | Edge_H12); - sos.writeUI8(x >> 4); - return; - } - sos.writeUI8((x << 4) | Edge_H20); - sos.writeUI8(x >> 4); - sos.writeUI8(x >> 12); - break; - case Edge_VLine: - y = data[1]; - if (y >= GFxOutputStream.MinSInt12 && y <= GFxOutputStream.MaxSInt12) { - sos.writeUI8((y << 4) | Edge_V12); - sos.writeUI8(y >> 4); - return; - } - sos.writeUI8((y << 4) | Edge_V20); - sos.writeUI8(y >> 4); - sos.writeUI8(y >> 12); - return; - case Edge_Line: - x = data[1]; - y = data[2]; - if (x >= GFxOutputStream.MinSInt6 && x <= GFxOutputStream.MaxSInt6 && y >= GFxOutputStream.MinSInt6 && y <= GFxOutputStream.MaxSInt6) { - sos.writeUI8((x << 4) | Edge_L6); - sos.writeUI8(((x >> 4) & m2) | (y << 2)); - return; - } - if (x >= GFxOutputStream.MinSInt10 && x <= GFxOutputStream.MaxSInt10 && y >= GFxOutputStream.MinSInt10 && y <= GFxOutputStream.MaxSInt10) { - sos.writeUI8((x << 4) | Edge_L10); - sos.writeUI8(((x >> 4) & m6) | (y << 6)); - sos.writeUI8(y >> 2); - return; - } - if (x >= GFxOutputStream.MinSInt14 && x <= GFxOutputStream.MaxSInt14 && y >= GFxOutputStream.MinSInt14 && y <= GFxOutputStream.MaxSInt14) { - sos.writeUI8((x << 4) | Edge_L14); - sos.writeUI8(x >> 4); - sos.writeUI8(((x >> 12) & m2) | (y << 2)); - sos.writeUI8(y >> 6); - return; - } - sos.writeUI8((x << 4) | Edge_L18); - sos.writeUI8(x >> 4); - sos.writeUI8(((x >> 12) & m6) | (y << 6)); - sos.writeUI8(y >> 2); - sos.writeUI8(y >> 10); - return; - case Edge_Quad: - int cx = data[1]; - int cy = data[2]; - int ax = data[3]; - int ay = data[4]; - int minV = cx; - int maxV = cx; - if (cy < minV) { - minV = cy; - } - if (cy > maxV) { - maxV = cy; - } - if (ax < minV) { - minV = ax; - } - if (ax > maxV) { - maxV = ax; - } - if (ay < minV) { - minV = ay; - } - if (ay > maxV) { - maxV = ay; - } - - if (minV >= GFxOutputStream.MinSInt5 && maxV <= GFxOutputStream.MaxSInt5) { - sos.writeUI8(((cx << 4) | Edge_C5)); - sos.writeUI8((((cx >> 4) & m1) | ((cy << 1) & m6) | (ax << 6))); - sos.writeUI8((((ax >> 2) & m3) | (ay << 3))); - return; - } - if (minV >= GFxOutputStream.MinSInt7 && maxV <= GFxOutputStream.MaxSInt7) { - sos.writeUI8(((cx << 4) | Edge_C7)); - sos.writeUI8((((cx >> 4) & m3) | (cy << 3))); - sos.writeUI8((((cy >> 5) & m2) | (ax << 2))); - sos.writeUI8((((ax >> 6) & m1) | (ay << 1))); - return; - } - if (minV >= GFxOutputStream.MinSInt9 && maxV <= GFxOutputStream.MaxSInt9) { - sos.writeUI8(((cx << 4) | Edge_C9)); - sos.writeUI8((((cx >> 4) & m5) | (cy << 5))); - sos.writeUI8((((cy >> 3) & m6) | (ax << 6))); - sos.writeUI8((((ax >> 2) & m7) | (ay << 7))); - sos.writeUI8(((ay >> 1))); - return; - } - if (minV >= GFxOutputStream.MinSInt11 && maxV <= GFxOutputStream.MaxSInt11) { - sos.writeUI8(((cx << 4) | Edge_C11)); - sos.writeUI8((((cx >> 4) & m7) | (cy << 7))); - sos.writeUI8(((cy >> 1))); - sos.writeUI8((((cy >> 9) & m2) | (ax << 2))); - sos.writeUI8((((ax >> 6) & m5) | (ay << 5))); - sos.writeUI8(((ay >> 3))); - return; - } - if (minV >= GFxOutputStream.MinSInt13 && maxV <= GFxOutputStream.MaxSInt13) { - sos.writeUI8(((cx << 4) | Edge_C13)); - sos.writeUI8(((cx >> 4))); - sos.writeUI8((((cx >> 12) & m1) | (cy << 1))); - sos.writeUI8((((cy >> 7) & m6) | (ax << 6))); - sos.writeUI8(((ax >> 2))); - sos.writeUI8((((ax >> 10) & m3) | (ay << 3))); - sos.writeUI8(((ay >> 5))); - return; - } - if (minV >= GFxOutputStream.MinSInt15 && maxV <= GFxOutputStream.MaxSInt15) { - sos.writeUI8(((cx << 4) | Edge_C15)); - sos.writeUI8(((cx >> 4))); - sos.writeUI8((((cx >> 12) & m3) | (cy << 3))); - sos.writeUI8(((cy >> 5))); - sos.writeUI8((((cy >> 13) & m2) | (ax << 2))); - sos.writeUI8(((ax >> 6))); - sos.writeUI8((((ax >> 14) & m1) | (ay << 1))); - sos.writeUI8(((ay >> 7))); - return; - } - if (minV >= GFxOutputStream.MinSInt17 && maxV <= GFxOutputStream.MaxSInt17) { - sos.writeUI8(((cx << 4) | Edge_C17)); - sos.writeUI8(((cx >> 4))); - sos.writeUI8((((cx >> 12) & m5) | (cy << 5))); - sos.writeUI8(((cy >> 3))); - sos.writeUI8((((cy >> 11) & m6) | (ax << 6))); - sos.writeUI8(((ax >> 2))); - sos.writeUI8((((ax >> 10) & m7) | (ay << 7))); - sos.writeUI8(((ay >> 1))); - sos.writeUI8(((ay >> 9))); - return; - } - sos.writeUI8(((cx << 4) | Edge_C19)); - sos.writeUI8(((cx >> 4))); - sos.writeUI8((((cx >> 12) & m7) | (cy << 7))); - sos.writeUI8(((cy >> 1))); - sos.writeUI8(((cy >> 9))); - sos.writeUI8((((cy >> 17) & m2) | (ax << 2))); - sos.writeUI8(((ax >> 6))); - sos.writeUI8((((ax >> 14) & m5) | (ay << 5))); - sos.writeUI8(((ay >> 3))); - sos.writeUI8(((ay >> 11))); - } - } -} +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.types.gfx; + +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; +import java.io.IOException; +import java.io.Serializable; + +/** + * + * @author JPEXS + */ +public class EdgeType implements Serializable { + + private static final int[] sizes = new int[]{1, 2, 1, 2, 1, 2, 3, 4, 2, 3, 4, 5, 6, 7, 8, 9}; + + private static final int Edge_H12 = 0; // 2 bytes + + private static final int Edge_H20 = 1; // 3 bytes + + private static final int Edge_V12 = 2; // 2 bytes + + private static final int Edge_V20 = 3; // 3 bytes + + private static final int Edge_L6 = 4; // 2 bytes + + private static final int Edge_L10 = 5; // 3 bytes + + private static final int Edge_L14 = 6; // 4 bytes + + private static final int Edge_L18 = 7; // 5 bytes + + private static final int Edge_C5 = 8; // 3 bytes + + private static final int Edge_C7 = 9; // 4 bytes + + private static final int Edge_C9 = 10; // 5 bytes + + private static final int Edge_C11 = 11; // 6 bytes + + private static final int Edge_C13 = 12; // 7 bytes + + private static final int Edge_C15 = 13; // 8 bytes + + private static final int Edge_C17 = 14; // 9 bytes + + private static final int Edge_C19 = 15; // 10 bytes + + private static final int Edge_HLine = 0; + + private static final int Edge_VLine = 1; + + private static final int Edge_Line = 2; + + private static final int Edge_Quad = 3; + + public int[] data; + + public EdgeType(boolean vertical, int v) { + data = new int[]{vertical ? Edge_VLine : Edge_HLine, v}; + } + + public EdgeType(int x, int y) { + data = new int[]{Edge_Line, x, y}; + } + + public EdgeType(int cx, int cy, int ax, int ay) { + data = new int[]{Edge_Quad, cx, cy, ax, ay}; + } + + @Override + public String toString() { + String ret = "[Edge data:"; + for (int i = 0; i < data.length; i++) { + if (i > 0) { + ret += ", "; + } + ret += "" + data[i]; + } + ret += "]"; + return ret; + } + + public EdgeType(GFxInputStream sis) throws IOException { + data = readEdge(sis); + /*if((raw[0]&0xf) == Edge_V20){ + data[1] = 0; + } + if((raw[0]&0xf) == Edge_C17){ + //System.out.println("========== 17 : "+toString()) ; + data[1] = 0; + data[2] = 0; + data[3] = 0; + data[4] = 0; + }*/ + } + + private static int SInt8(int val) { + /*boolean sign = (val & 0x80) == 0x80; + val = val & 0x7F; + if (sign) { + val = -val; + } + return val;*/ + return (byte) val; + } + + public SHAPERECORD toSHAPERECORD() { + int multiplier = 1; + StraightEdgeRecord ser; + CurvedEdgeRecord cer; + switch (data[0]) { + case Edge_HLine: + ser = new StraightEdgeRecord(); + ser.generalLineFlag = false; + ser.deltaX = data[1] * multiplier; + ser.calculateBits(); + return ser; + case Edge_VLine: + ser = new StraightEdgeRecord(); + ser.generalLineFlag = false; + ser.vertLineFlag = true; + ser.deltaY = data[1] * multiplier; + ser.calculateBits(); + return ser; + case Edge_Line: + ser = new StraightEdgeRecord(); + ser.generalLineFlag = true; + ser.deltaX = data[1] * multiplier; + ser.deltaY = data[2] * multiplier; + ser.calculateBits(); + return ser; + case Edge_Quad: + cer = new CurvedEdgeRecord(); + cer.controlDeltaX = data[1] * multiplier; + cer.controlDeltaY = data[2] * multiplier; + cer.anchorDeltaX = data[3] * multiplier; + cer.anchorDeltaY = data[4] * multiplier; + cer.calculateBits(); + return cer; + } + return null; + } + + private int[] readEdge(GFxInputStream sis) throws IOException { + byte firstByte = (byte) sis.readUI8("firstByte"); + byte raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8, raw9; + raw1 = (byte) sis.readUI8("byte1"); + int[] data = new int[5]; + + switch (firstByte & 0xF) { + case Edge_H12: + data[0] = Edge_HLine; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8(raw1 & 0xff) << 4); + break; + + case Edge_H20: + raw2 = (byte) sis.readUI8("byte2"); + data[0] = Edge_HLine; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 & 0xff) << 12); + break; + + case Edge_V12: + data[0] = Edge_VLine; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8(raw1 & 0xff) << 4); + break; + + case Edge_V20: + data[0] = Edge_VLine; + raw2 = (byte) sis.readUI8("byte2"); + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 & 0xff) << 12); + break; + + case Edge_L6: + data[0] = Edge_Line; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 6) >> 2); + data[2] = SInt8(raw1 & 0xff) >> 2; + break; + + case Edge_L10: + raw2 = (byte) sis.readUI8("byte2"); + data[0] = Edge_Line; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 2) << 2); + data[2] = ((raw1 & 0xff) >> 6) | (SInt8((raw2 & 0xff)) << 2); + break; + + case Edge_L14: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + data[0] = Edge_Line; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 6) << 6); + data[2] = ((raw2 & 0xff) >> 2) | (SInt8((raw3 & 0xff)) << 6); + break; + + case Edge_L18: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + data[0] = Edge_Line; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 2) << 10); + data[2] = ((raw2 & 0xff) >> 6) | ((raw3 & 0xff) << 2) | (SInt8((raw4 & 0xff)) << 10); + break; + + case Edge_C5: + raw2 = (byte) sis.readUI8("byte2"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 7) >> 3); + data[2] = SInt8((raw1 & 0xff) << 2) >> 3; + data[3] = ((raw1 & 0xff) >> 6) | (SInt8((raw2 & 0xff) << 5) >> 3); + data[4] = SInt8((raw2 & 0xff)) >> 3; + break; + + case Edge_C7: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 5) >> 1); + data[2] = ((raw1 & 0xff) >> 3) | (SInt8((raw2 & 0xff) << 6) >> 1); + data[3] = ((raw2 & 0xff) >> 2) | (SInt8((raw3 & 0xff) << 7) >> 1); + data[4] = SInt8(raw3) >> 1; + break; + + case Edge_C9: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 3) << 1); + data[2] = ((raw1 & 0xff) >> 5) | (SInt8((raw2 & 0xff) << 2) << 1); + data[3] = ((raw2 & 0xff) >> 6) | (SInt8((raw3 & 0xff) << 1) << 1); + data[4] = ((raw3 & 0xff) >> 7) | (SInt8(raw4 & 0xff) << 1); + break; + + case Edge_C11: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + raw5 = (byte) sis.readUI8("byte5"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | (SInt8((raw1 & 0xff) << 1) << 3); + data[2] = (raw1 >> 7) | ((raw2 & 0xff) << 1) | (SInt8((raw3 & 0xff) << 6) << 3); + data[3] = ((raw3 & 0xff) >> 2) | (SInt8((raw4 & 0xff) << 3) << 3); + data[4] = ((raw4 & 0xff) >> 5) | (SInt8(raw5 & 0xff) << 3); + break; + + case Edge_C13: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + raw5 = (byte) sis.readUI8("byte5"); + raw6 = (byte) sis.readUI8("byte6"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 7) << 5); + data[2] = ((raw2 & 0xff) >> 1) | (SInt8((raw3 & 0xff) << 2) << 5); + data[3] = ((raw3 & 0xff) >> 6) | ((raw4 & 0xff) << 2) | (SInt8((raw5 & 0xff) << 5) << 5); + data[4] = ((raw5 & 0xff) >> 3) | (SInt8(raw6 & 0xff) << 5); + break; + + case Edge_C15: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + raw5 = (byte) sis.readUI8("byte5"); + raw6 = (byte) sis.readUI8("byte6"); + raw7 = (byte) sis.readUI8("byte7"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 5) << 7); + data[2] = ((raw2 & 0xff) >> 3) | ((raw3 & 0xff) << 5) | (SInt8((raw4 & 0xff) << 6) << 7); + data[3] = ((raw4 & 0xff) >> 2) | ((raw5 & 0xff) << 6) | (SInt8((raw6 & 0xff) << 7) << 7); + data[4] = ((raw6 & 0xff) >> 1) | (SInt8((raw7 & 0xff)) << 7); + break; + + case Edge_C17: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + raw5 = (byte) sis.readUI8("byte5"); + raw6 = (byte) sis.readUI8("byte6"); + raw7 = (byte) sis.readUI8("byte7"); + raw8 = (byte) sis.readUI8("byte8"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8((raw2 & 0xff) << 3) << 9); + data[2] = ((raw2 & 0xff) >> 5) | ((raw3 & 0xff) << 3) | (SInt8((raw4 & 0xff) << 2) << 9); + data[3] = ((raw4 & 0xff) >> 6) | ((raw5 & 0xff) << 2) | (SInt8((raw6 & 0xff) << 1) << 9); + data[4] = ((raw6 & 0xff) >> 7) | ((raw7 & 0xff) << 1) | (SInt8(raw8 & 0xff) << 9); + break; + + case Edge_C19: + raw2 = (byte) sis.readUI8("byte2"); + raw3 = (byte) sis.readUI8("byte3"); + raw4 = (byte) sis.readUI8("byte4"); + raw5 = (byte) sis.readUI8("byte5"); + raw6 = (byte) sis.readUI8("byte6"); + raw7 = (byte) sis.readUI8("byte7"); + raw8 = (byte) sis.readUI8("byte8"); + raw9 = (byte) sis.readUI8("byte9"); + data[0] = Edge_Quad; + data[1] = ((firstByte & 0xff) >> 4) | ((raw1 & 0xff) << 4) | (SInt8(raw2 << 1) << 11); + data[2] = ((raw2 & 0xff) >> 7) | ((raw3 & 0xff) << 1) | ((raw4 & 0xff) << 9) | (SInt8(raw5 << 6) << 11); + data[3] = ((raw5 & 0xff) >> 2) | ((raw6 & 0xff) << 6) | (SInt8(raw7 << 3) << 11); + data[4] = ((raw7 & 0xff) >> 5) | ((raw8 & 0xff) << 3) | (SInt8(raw9) << 11); + break; + } + return data; + } + + public void write(GFxOutputStream sos) throws IOException { + int x; + int y; + int m1 = 1; + int m2 = 3; + int m3 = 7; + int m4 = 0xF; + int m5 = 0x1F; + int m6 = 0x3F; + int m7 = 0x7F; + switch (data[0]) { + case Edge_HLine: + x = data[1]; + if (x >= GFxOutputStream.MinSInt12 && x <= GFxOutputStream.MaxSInt12) { + sos.writeUI8((x << 4) | Edge_H12); + sos.writeUI8(x >> 4); + return; + } + sos.writeUI8((x << 4) | Edge_H20); + sos.writeUI8(x >> 4); + sos.writeUI8(x >> 12); + break; + case Edge_VLine: + y = data[1]; + if (y >= GFxOutputStream.MinSInt12 && y <= GFxOutputStream.MaxSInt12) { + sos.writeUI8((y << 4) | Edge_V12); + sos.writeUI8(y >> 4); + return; + } + sos.writeUI8((y << 4) | Edge_V20); + sos.writeUI8(y >> 4); + sos.writeUI8(y >> 12); + return; + case Edge_Line: + x = data[1]; + y = data[2]; + if (x >= GFxOutputStream.MinSInt6 && x <= GFxOutputStream.MaxSInt6 && y >= GFxOutputStream.MinSInt6 && y <= GFxOutputStream.MaxSInt6) { + sos.writeUI8((x << 4) | Edge_L6); + sos.writeUI8(((x >> 4) & m2) | (y << 2)); + return; + } + if (x >= GFxOutputStream.MinSInt10 && x <= GFxOutputStream.MaxSInt10 && y >= GFxOutputStream.MinSInt10 && y <= GFxOutputStream.MaxSInt10) { + sos.writeUI8((x << 4) | Edge_L10); + sos.writeUI8(((x >> 4) & m6) | (y << 6)); + sos.writeUI8(y >> 2); + return; + } + if (x >= GFxOutputStream.MinSInt14 && x <= GFxOutputStream.MaxSInt14 && y >= GFxOutputStream.MinSInt14 && y <= GFxOutputStream.MaxSInt14) { + sos.writeUI8((x << 4) | Edge_L14); + sos.writeUI8(x >> 4); + sos.writeUI8(((x >> 12) & m2) | (y << 2)); + sos.writeUI8(y >> 6); + return; + } + sos.writeUI8((x << 4) | Edge_L18); + sos.writeUI8(x >> 4); + sos.writeUI8(((x >> 12) & m6) | (y << 6)); + sos.writeUI8(y >> 2); + sos.writeUI8(y >> 10); + return; + case Edge_Quad: + int cx = data[1]; + int cy = data[2]; + int ax = data[3]; + int ay = data[4]; + int minV = cx; + int maxV = cx; + if (cy < minV) { + minV = cy; + } + if (cy > maxV) { + maxV = cy; + } + if (ax < minV) { + minV = ax; + } + if (ax > maxV) { + maxV = ax; + } + if (ay < minV) { + minV = ay; + } + if (ay > maxV) { + maxV = ay; + } + + if (minV >= GFxOutputStream.MinSInt5 && maxV <= GFxOutputStream.MaxSInt5) { + sos.writeUI8(((cx << 4) | Edge_C5)); + sos.writeUI8((((cx >> 4) & m1) | ((cy << 1) & m6) | (ax << 6))); + sos.writeUI8((((ax >> 2) & m3) | (ay << 3))); + return; + } + if (minV >= GFxOutputStream.MinSInt7 && maxV <= GFxOutputStream.MaxSInt7) { + sos.writeUI8(((cx << 4) | Edge_C7)); + sos.writeUI8((((cx >> 4) & m3) | (cy << 3))); + sos.writeUI8((((cy >> 5) & m2) | (ax << 2))); + sos.writeUI8((((ax >> 6) & m1) | (ay << 1))); + return; + } + if (minV >= GFxOutputStream.MinSInt9 && maxV <= GFxOutputStream.MaxSInt9) { + sos.writeUI8(((cx << 4) | Edge_C9)); + sos.writeUI8((((cx >> 4) & m5) | (cy << 5))); + sos.writeUI8((((cy >> 3) & m6) | (ax << 6))); + sos.writeUI8((((ax >> 2) & m7) | (ay << 7))); + sos.writeUI8(((ay >> 1))); + return; + } + if (minV >= GFxOutputStream.MinSInt11 && maxV <= GFxOutputStream.MaxSInt11) { + sos.writeUI8(((cx << 4) | Edge_C11)); + sos.writeUI8((((cx >> 4) & m7) | (cy << 7))); + sos.writeUI8(((cy >> 1))); + sos.writeUI8((((cy >> 9) & m2) | (ax << 2))); + sos.writeUI8((((ax >> 6) & m5) | (ay << 5))); + sos.writeUI8(((ay >> 3))); + return; + } + if (minV >= GFxOutputStream.MinSInt13 && maxV <= GFxOutputStream.MaxSInt13) { + sos.writeUI8(((cx << 4) | Edge_C13)); + sos.writeUI8(((cx >> 4))); + sos.writeUI8((((cx >> 12) & m1) | (cy << 1))); + sos.writeUI8((((cy >> 7) & m6) | (ax << 6))); + sos.writeUI8(((ax >> 2))); + sos.writeUI8((((ax >> 10) & m3) | (ay << 3))); + sos.writeUI8(((ay >> 5))); + return; + } + if (minV >= GFxOutputStream.MinSInt15 && maxV <= GFxOutputStream.MaxSInt15) { + sos.writeUI8(((cx << 4) | Edge_C15)); + sos.writeUI8(((cx >> 4))); + sos.writeUI8((((cx >> 12) & m3) | (cy << 3))); + sos.writeUI8(((cy >> 5))); + sos.writeUI8((((cy >> 13) & m2) | (ax << 2))); + sos.writeUI8(((ax >> 6))); + sos.writeUI8((((ax >> 14) & m1) | (ay << 1))); + sos.writeUI8(((ay >> 7))); + return; + } + if (minV >= GFxOutputStream.MinSInt17 && maxV <= GFxOutputStream.MaxSInt17) { + sos.writeUI8(((cx << 4) | Edge_C17)); + sos.writeUI8(((cx >> 4))); + sos.writeUI8((((cx >> 12) & m5) | (cy << 5))); + sos.writeUI8(((cy >> 3))); + sos.writeUI8((((cy >> 11) & m6) | (ax << 6))); + sos.writeUI8(((ax >> 2))); + sos.writeUI8((((ax >> 10) & m7) | (ay << 7))); + sos.writeUI8(((ay >> 1))); + sos.writeUI8(((ay >> 9))); + return; + } + sos.writeUI8(((cx << 4) | Edge_C19)); + sos.writeUI8(((cx >> 4))); + sos.writeUI8((((cx >> 12) & m7) | (cy << 7))); + sos.writeUI8(((cy >> 1))); + sos.writeUI8(((cy >> 9))); + sos.writeUI8((((cy >> 17) & m2) | (ax << 2))); + sos.writeUI8(((ax >> 6))); + sos.writeUI8((((ax >> 14) & m5) | (ay << 5))); + sos.writeUI8(((ay >> 3))); + sos.writeUI8(((ay >> 11))); + } + } +} diff --git a/libsrc/gif/build.xml b/libsrc/gif/build.xml index ece3c2dfc..98a4066c1 100644 --- a/libsrc/gif/build.xml +++ b/libsrc/gif/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project gif. - - - + + + + + + + + + + + Builds, tests, and runs the project gif. + + + diff --git a/libsrc/gif/nbproject/build-impl.xml b/libsrc/gif/nbproject/build-impl.xml index ce27c129d..97e89d6e4 100644 --- a/libsrc/gif/nbproject/build-impl.xml +++ b/libsrc/gif/nbproject/build-impl.xml @@ -1,1413 +1,1413 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.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/gif/nbproject/genfiles.properties b/libsrc/gif/nbproject/genfiles.properties index a6fe2d3a4..f6ad3154e 100644 --- a/libsrc/gif/nbproject/genfiles.properties +++ b/libsrc/gif/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=c07cf2d0 -build.xml.script.CRC32=d45952bc -build.xml.stylesheet.CRC32=8064a381@1.68.1.46 -# 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=c07cf2d0 -nbproject/build-impl.xml.script.CRC32=178a9ed1 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 +build.xml.data.CRC32=c07cf2d0 +build.xml.script.CRC32=d45952bc +build.xml.stylesheet.CRC32=8064a381@1.68.1.46 +# 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=c07cf2d0 +nbproject/build-impl.xml.script.CRC32=178a9ed1 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 diff --git a/libsrc/gif/nbproject/project.properties b/libsrc/gif/nbproject/project.properties index ece97db38..a89068288 100644 --- a/libsrc/gif/nbproject/project.properties +++ b/libsrc/gif/nbproject/project.properties @@ -1,71 +1,71 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -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 -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# Files in build.classes.dir which should be excluded from distribution jar -dist.archive.excludes= -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=../../lib/gif.jar -dist.javadoc.dir=${dist.dir}/javadoc -excludes= -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.7 -javac.target=1.7 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -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= -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=true -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. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processor.options= +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +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 +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=../../lib/gif.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +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.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +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= +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=true +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. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/libsrc/gif/nbproject/project.xml b/libsrc/gif/nbproject/project.xml index fb4075c8c..0d3438be0 100644 --- a/libsrc/gif/nbproject/project.xml +++ b/libsrc/gif/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - gif - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + gif + + + + + + + + + diff --git a/libsrc/gnujpdf/build.xml b/libsrc/gnujpdf/build.xml index 129873d08..91a08e173 100644 --- a/libsrc/gnujpdf/build.xml +++ b/libsrc/gnujpdf/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project gnujpdf. - - - + + + + + + + + + + + Builds, tests, and runs the project gnujpdf. + + + diff --git a/libsrc/gnujpdf/manifest.mf b/libsrc/gnujpdf/manifest.mf index 1574df4a2..328e8e5bc 100644 --- a/libsrc/gnujpdf/manifest.mf +++ b/libsrc/gnujpdf/manifest.mf @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/libsrc/gnujpdf/nbproject/build-impl.xml b/libsrc/gnujpdf/nbproject/build-impl.xml index 37c89a9a2..33af81dd9 100644 --- a/libsrc/gnujpdf/nbproject/build-impl.xml +++ b/libsrc/gnujpdf/nbproject/build-impl.xml @@ -1,1413 +1,1413 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.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/gnujpdf/nbproject/genfiles.properties b/libsrc/gnujpdf/nbproject/genfiles.properties index f953a5337..53351327a 100644 --- a/libsrc/gnujpdf/nbproject/genfiles.properties +++ b/libsrc/gnujpdf/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=fb275268 -build.xml.script.CRC32=7438dbfb -build.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=fb275268 -nbproject/build-impl.xml.script.CRC32=1ec9d904 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.2.48 +build.xml.data.CRC32=fb275268 +build.xml.script.CRC32=7438dbfb +build.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=fb275268 +nbproject/build-impl.xml.script.CRC32=1ec9d904 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.2.48 diff --git a/libsrc/gnujpdf/nbproject/project.xml b/libsrc/gnujpdf/nbproject/project.xml index d93419e09..e19109d84 100644 --- a/libsrc/gnujpdf/nbproject/project.xml +++ b/libsrc/gnujpdf/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - gnujpdf - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + gnujpdf + + + + + + + + + diff --git a/libsrc/jpacker/build.xml b/libsrc/jpacker/build.xml index 047caae7f..71c89e109 100644 --- a/libsrc/jpacker/build.xml +++ b/libsrc/jpacker/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project jpacker. - - - + + + + + + + + + + + Builds, tests, and runs the project jpacker. + + + diff --git a/libsrc/jpacker/manifest.mf b/libsrc/jpacker/manifest.mf index 1574df4a2..328e8e5bc 100644 --- a/libsrc/jpacker/manifest.mf +++ b/libsrc/jpacker/manifest.mf @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/libsrc/jpacker/nbproject/build-impl.xml b/libsrc/jpacker/nbproject/build-impl.xml index 2a5b22266..e5e6088e9 100644 --- a/libsrc/jpacker/nbproject/build-impl.xml +++ b/libsrc/jpacker/nbproject/build-impl.xml @@ -1,1413 +1,1413 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.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/jpacker/nbproject/genfiles.properties b/libsrc/jpacker/nbproject/genfiles.properties index 8f3ed7bcf..bb7c8aa6b 100644 --- a/libsrc/jpacker/nbproject/genfiles.properties +++ b/libsrc/jpacker/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=811ea359 -build.xml.script.CRC32=f4a6aa27 -build.xml.stylesheet.CRC32=8064a381@1.74.1.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=811ea359 -nbproject/build-impl.xml.script.CRC32=a8ed580a -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 +build.xml.data.CRC32=811ea359 +build.xml.script.CRC32=f4a6aa27 +build.xml.stylesheet.CRC32=8064a381@1.74.1.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=811ea359 +nbproject/build-impl.xml.script.CRC32=a8ed580a +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 diff --git a/libsrc/jpacker/nbproject/project.properties b/libsrc/jpacker/nbproject/project.properties index 853b1b314..9132b5c64 100644 --- a/libsrc/jpacker/nbproject/project.properties +++ b/libsrc/jpacker/nbproject/project.properties @@ -1,77 +1,77 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -application.title=jpacker -application.vendor= -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 -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# Files in build.classes.dir which should be excluded from distribution jar -dist.archive.excludes= -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=../../lib/jpacker.jar -dist.javadoc.dir=${dist.dir}/javadoc -endorsed.classpath= -excludes= -file.reference.jargs.jar=jargs.jar -includes=** -jar.compress=false -javac.classpath=\ - ${file.reference.jargs.jar} -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=false -javac.processorpath=\ - ${javac.classpath} -javac.source=1.7 -javac.target=1.7 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -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.jpacker.JPacker -manifest.file=manifest.mf -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=true -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. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=jpacker +application.vendor= +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 +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=../../lib/jpacker.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.jargs.jar=jargs.jar +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.jargs.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +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.jpacker.JPacker +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=true +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. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/libsrc/jpacker/nbproject/project.xml b/libsrc/jpacker/nbproject/project.xml index 469362643..e27e0f828 100644 --- a/libsrc/jpacker/nbproject/project.xml +++ b/libsrc/jpacker/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - jpacker - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + jpacker + + + + + + + + + diff --git a/libsrc/jpproxy/build.xml b/libsrc/jpproxy/build.xml index 5f5b4b941..ae7c00dcd 100644 --- a/libsrc/jpproxy/build.xml +++ b/libsrc/jpproxy/build.xml @@ -1,158 +1,158 @@ - - - - Builds project JPProxy. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + Builds project JPProxy. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libsrc/jpproxy/manifest.mf b/libsrc/jpproxy/manifest.mf index 1574df4a2..328e8e5bc 100644 --- a/libsrc/jpproxy/manifest.mf +++ b/libsrc/jpproxy/manifest.mf @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/libsrc/jpproxy/nbproject/project.properties b/libsrc/jpproxy/nbproject/project.properties index a546f0851..e41c2ecde 100644 --- a/libsrc/jpproxy/nbproject/project.properties +++ b/libsrc/jpproxy/nbproject/project.properties @@ -1,74 +1,74 @@ -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} +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 index ba3b6b9e1..0c1291edb 100644 --- a/libsrc/jpproxy/nbproject/project.xml +++ b/libsrc/jpproxy/nbproject/project.xml @@ -1,13 +1,13 @@ - - - org.netbeans.modules.java.j2seproject - - - JPProxy - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + JPProxy + + + + + + + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/CHANGELOG.txt b/libsrc/jsyntaxpane/jsyntaxpane/CHANGELOG.txt index 7cf5a2857..9a25a9e38 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/CHANGELOG.txt +++ b/libsrc/jsyntaxpane/jsyntaxpane/CHANGELOG.txt @@ -1,90 +1,90 @@ -Version 0.9.5 - Java Reflection Completions additions - * Configuration class overhaul. Each kit now has its own COnfiguration file - which merges the superclass(es) Configurations. - * Usable Reflect Completions Dialog (Java with F1 or Menu) - * Java ENTER key responds properly to multi line comments - * Font can be changed for each Kit - * Kits for XHTML and Xpath added. XHTML has a simple Preview Action. - * Added Execute Script to JacaScript (can also be used for Groovy if Groovy - Scripting support is installed properly). - * Hotkeys for actions are displayed in Popup Menus - * Word Completion action can also do CamelCase matches - * Smart Home Action (and Smart Home Extend Selection) - * Enhanced JavaScript support. Issue 115 - * Better Undo grouping - * Replace DIalog ENhancement. Only for updatedable editors and added single replace. - * Added append method to SyntaxDocument - * Fixed Issue 130 - Compound Undo on multiple lines. -Version 0.9.4 - IntelliSense additions - * Adding IntelliSense to Java with simple List of selectable keywords - * Added Toggle Comment Actions using Control SLASH - * Fixed Issue 47. - * Added Clojure, Scala, DOS Batch and 'nix bash support - * Added Configurable Popup menus with default Tango Desktop icons - * Added configurable format for the CaretMonitor class - * Toggle Comments Action selects the lines affected after being performed - * Added multi-line support in ActionUtils.insertMagicSTring method. - * GotoLine dialog responds to ESC key -Version 0.9.3 - Start of scripts for the document: - * Added new methods getLine() to SyntaxDocument - * SyntaxDocument getIndexOf methods deprecated, use getMatchers instead - * Added Line Numbering to Java - * Added CaretMonitor Class - * Merged Find And Replace dialogs into one. - * Created SyntaxComponent interface and have all UI components implement - that interface. DefaultSyntaxKit will use config.properties class to - dynamically install these components. - * Added Right Margin option and Single Color Selection Options - * Added Python, C and C++ Support - * Added Ruby Syntax Support - * Fixed Issue 37 (NPE for LineNumbersRuler) - * Fixed Issue 39 (Highlighting Tokens overrides selection highlights) - * Fixed some JavaDoc comments. - * Fixed Line Numbers being displayed for the height of the editor and now - just for the actual available lines. - * Fixed Margin typo in all project. Issue 43 - * Changing Actions to be more configurable: - * SyntaxActions renamed to ActionUtils - * Removed all inner classes from SyntaxActions - * Will create new SyntaxAction interface that will allow dynamic addition - actions (in the addKeyActions of DefaultSyntaxKit - * Added Text AA property to SyntaxView -Version 0.9.2: - * Fixing Java Indentation and Un-Indentattion Actions - * Added and used (in the Tester) clearUndoes on the SyntaxDocument - * Added Basic JFlex Syntax - * Added getContentTypes to DefaultSyntaxKit to get all registered - ContentTypes. This is now also used in the SyntaxTester instead of - hardcoding the types. - * Cleanup and optimization of Lexers by removing duplicate Java Code - (replaced with Regex OR) - * Removed calls to deprecated calls in SyntaxView - * Modified the SyntaxDOcument to override the fireXXX methods and parse - the document at that time instead of overriding the inserUpdate method. - This fixes issue 24. - * Added Groovy GString expression highlights - * Removed getLanguages method from Lexer interface and implementations. - * Added WARNING and ERROR TokenTypes and added their default styles. - * Moved Keymaps and install methods to SyntaxKits instead of the Lexers - * Removed deprecated methods from SyntaxActions class - * Split SyntaxActions into new package and moved inner classes to the new - package - * Added Token HighLighter to Java - * Added Pairs Highlighter to Java - * Token class made immutable (all final fields) - * Added Find and Replace Dialogs and Action to Java (mapped to C-F and - C-H ) - * Added pair matching to XML tags - * Added CDATA matching and pair highlights for XML - * Added Comment Pair Highlighting in XML - * Fixed highlighting with selections so the selection always appears - * Merged Find and Replace Dialogs into one - * Fixed issue 33 (undable to add new line after final closing brace for - Java) - * Added Groovy Multi-Line strings and fixed Comments as Regex issue. - * Fixes to empty find text field causing NPE -Version 0.9.1 - * Fixed empty strings in XML syntax Issue 29 - * Fixed TAL lexer using incorrect package name -Version 0.9.0 +Version 0.9.5 - Java Reflection Completions additions + * Configuration class overhaul. Each kit now has its own COnfiguration file + which merges the superclass(es) Configurations. + * Usable Reflect Completions Dialog (Java with F1 or Menu) + * Java ENTER key responds properly to multi line comments + * Font can be changed for each Kit + * Kits for XHTML and Xpath added. XHTML has a simple Preview Action. + * Added Execute Script to JacaScript (can also be used for Groovy if Groovy + Scripting support is installed properly). + * Hotkeys for actions are displayed in Popup Menus + * Word Completion action can also do CamelCase matches + * Smart Home Action (and Smart Home Extend Selection) + * Enhanced JavaScript support. Issue 115 + * Better Undo grouping + * Replace DIalog ENhancement. Only for updatedable editors and added single replace. + * Added append method to SyntaxDocument + * Fixed Issue 130 - Compound Undo on multiple lines. +Version 0.9.4 - IntelliSense additions + * Adding IntelliSense to Java with simple List of selectable keywords + * Added Toggle Comment Actions using Control SLASH + * Fixed Issue 47. + * Added Clojure, Scala, DOS Batch and 'nix bash support + * Added Configurable Popup menus with default Tango Desktop icons + * Added configurable format for the CaretMonitor class + * Toggle Comments Action selects the lines affected after being performed + * Added multi-line support in ActionUtils.insertMagicSTring method. + * GotoLine dialog responds to ESC key +Version 0.9.3 - Start of scripts for the document: + * Added new methods getLine() to SyntaxDocument + * SyntaxDocument getIndexOf methods deprecated, use getMatchers instead + * Added Line Numbering to Java + * Added CaretMonitor Class + * Merged Find And Replace dialogs into one. + * Created SyntaxComponent interface and have all UI components implement + that interface. DefaultSyntaxKit will use config.properties class to + dynamically install these components. + * Added Right Margin option and Single Color Selection Options + * Added Python, C and C++ Support + * Added Ruby Syntax Support + * Fixed Issue 37 (NPE for LineNumbersRuler) + * Fixed Issue 39 (Highlighting Tokens overrides selection highlights) + * Fixed some JavaDoc comments. + * Fixed Line Numbers being displayed for the height of the editor and now + just for the actual available lines. + * Fixed Margin typo in all project. Issue 43 + * Changing Actions to be more configurable: + * SyntaxActions renamed to ActionUtils + * Removed all inner classes from SyntaxActions + * Will create new SyntaxAction interface that will allow dynamic addition + actions (in the addKeyActions of DefaultSyntaxKit + * Added Text AA property to SyntaxView +Version 0.9.2: + * Fixing Java Indentation and Un-Indentattion Actions + * Added and used (in the Tester) clearUndoes on the SyntaxDocument + * Added Basic JFlex Syntax + * Added getContentTypes to DefaultSyntaxKit to get all registered + ContentTypes. This is now also used in the SyntaxTester instead of + hardcoding the types. + * Cleanup and optimization of Lexers by removing duplicate Java Code + (replaced with Regex OR) + * Removed calls to deprecated calls in SyntaxView + * Modified the SyntaxDOcument to override the fireXXX methods and parse + the document at that time instead of overriding the inserUpdate method. + This fixes issue 24. + * Added Groovy GString expression highlights + * Removed getLanguages method from Lexer interface and implementations. + * Added WARNING and ERROR TokenTypes and added their default styles. + * Moved Keymaps and install methods to SyntaxKits instead of the Lexers + * Removed deprecated methods from SyntaxActions class + * Split SyntaxActions into new package and moved inner classes to the new + package + * Added Token HighLighter to Java + * Added Pairs Highlighter to Java + * Token class made immutable (all final fields) + * Added Find and Replace Dialogs and Action to Java (mapped to C-F and + C-H ) + * Added pair matching to XML tags + * Added CDATA matching and pair highlights for XML + * Added Comment Pair Highlighting in XML + * Fixed highlighting with selections so the selection always appears + * Merged Find and Replace Dialogs into one + * Fixed issue 33 (undable to add new line after final closing brace for + Java) + * Added Groovy Multi-Line strings and fixed Comments as Regex issue. + * Fixes to empty find text field causing NPE +Version 0.9.1 + * Fixed empty strings in XML syntax Issue 29 + * Fixed TAL lexer using incorrect package name +Version 0.9.0 * Initial version after major overhaul \ No newline at end of file diff --git a/libsrc/jsyntaxpane/jsyntaxpane/nbactions.xml b/libsrc/jsyntaxpane/jsyntaxpane/nbactions.xml index 379f9d6af..3460d9b4f 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/nbactions.xml +++ b/libsrc/jsyntaxpane/jsyntaxpane/nbactions.xml @@ -1,41 +1,41 @@ - - - - run - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.1:exec - - - -classpath %classpath jsyntaxpane.SyntaxTester - java - - - - debug - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.1:exec - - - -Xdebug -Djava.compiler=none -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath jsyntaxpane.SyntaxTester - true - java - - - - profile - - jar - - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.1:exec - - - ${profiler.args} -classpath %classpath jsyntaxpane.SyntaxTester - profile - ${profiler.java} - - - + + + + run + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1:exec + + + -classpath %classpath jsyntaxpane.SyntaxTester + java + + + + debug + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1:exec + + + -Xdebug -Djava.compiler=none -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath jsyntaxpane.SyntaxTester + true + java + + + + profile + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1:exec + + + ${profiler.args} -classpath %classpath jsyntaxpane.SyntaxTester + profile + ${profiler.java} + + + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_es.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_es.properties index 046bca6cc..a7941b7a4 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_es.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_es.properties @@ -1,118 +1,118 @@ -DefaultAction.copy-to-clipboard.MenuText = Copiar -DefaultAction.cut-to-clipboard.MenuText = Cortar -DefaultAction.paste-from-clipboard.MenuText = Pegar -DefaultAction.select-all.MenuText = Seleccionar todo - -Action.find.MenuText = Buscar -Action.find.ToolTip = Mostrar el di\u00e1logo de Buscar y Reemplazar -Action.find-next.MenuText = Buscar siguiente -Action.find-next.ToolTip = Repetir la \u00faltima b\u00fasqueda -Action.goto-line.MenuText = Ir al n\u00famero de l\u00ednea -Action.goto-line.ToolTip = Ir al n\u00famero de l\u00ednea -Action.indent.MenuText = Indentar -Action.unindent.MenuText = Quitar indentaci\u00f3n -Action.undo.MenuText = Deshacer -Action.redo.MenuText = Rehacer -Action.delete-lines.MenuText = Borrar l\u00ednea(s) -Action.dup-lines-up.MenuText = Duplicar las l\u00edneas superiores -Action.dup-lines-down.MenuText = Duplicar las l\u00edneas inferiores -Action.toggle-lines.MenuText = Alternar n\u00famero de l\u00edneas -Action.show-abbs.MenuText = Mostrar abreviaciones -Action.show-abbs.ToolTip = Mostrar abreviaciones -Action.complete-word.MenuText = Completar palabra -Action.jump-to-pair.MenuText = Saltar al par -Action.toggle-comments.MenuText = Alternar comentarios - -# !!!! FFDec translators - please do not edit anything below this line !!! -#========================================================================== - -Components = jsyntaxpane.components.PairsMarker, \ - jsyntaxpane.components.LineNumbersRuler -# This is the color to highlight tokens whenever the cursor is on them -TokenMarker.Color = 0xffeeaa -# Colors for PairMarkers -PairMarker.Color = 0xffbb77 -# -# Right Margin for LineNumbers border in pixels, Default = 5 -LineNumbers.RightMargin = 7 -# Foreground for line numbers, Default = Black -LineNumbers.Foreground = 0x333300 -# Background for line numbers, Default = White -LineNumbers.Background = 0xeeeeff -# Color to use for highlighting current line background -LineNumbers.CurrentBack = 0xccccee -# Default color for the Caret, Black -CaretColor = 0x000000 -# Actions: -Action.quick-find = jsyntaxpane.actions.QuickFindAction, control F -Action.find = jsyntaxpane.actions.FindReplaceAction, control H -Action.find-next = jsyntaxpane.actions.FindNextAction, F3 -Action.goto-line = jsyntaxpane.actions.GotoLineAction, control G - -Action.indent = jsyntaxpane.actions.IndentAction, TAB -Action.indent.Abbreviations = ${class_path}/abbreviations.properties -Action.unindent = jsyntaxpane.actions.UnindentAction, shift TAB - -Action.jindent = jsyntaxpane.actions.JIndentAction, ENTER -Action.undo = jsyntaxpane.actions.UndoAction, menu Z -Action.redo = jsyntaxpane.actions.RedoAction, menu Y -Action.delete-lines = jsyntaxpane.actions.DeleteLinesAction, control E -Action.dup-lines-up = jsyntaxpane.actions.DuplicateLinesAction, shift control UP -Action.dup-lines-down = jsyntaxpane.actions.DuplicateLinesAction, shift control DOWN - -Action.toggle-lines = jsyntaxpane.actions.ToggleComponentAction, control F2 -Action.toggle-lines.Component = jsyntaxpane.components.LineNumbersRuler - -Action.toggle-comments = jsyntaxpane.actions.ToggleCommentsAction, control SLASH -Action.toggle-comments.SmallIcon = comment.png -Action.jump-to-pair = jsyntaxpane.actions.JumpToPairAction, control OPEN_BRACKET -Action.complete-word = jsyntaxpane.actions.CompleteWordAction, control K - -Action.smart-home = jsyntaxpane.actions.SmartHomeAction, HOME -Action.smart-home-select = jsyntaxpane.actions.SmartHomeSelectAction, shift HOME -Action.show-abbs = jsyntaxpane.actions.ShowAbbsAction, F8 - -# -# View configuration: -TextAA = ON -DEFAULT_EDIT_MENU= \ - cut-to-clipboard , \ - copy-to-clipboard , \ - paste-from-clipboard , \ - - , \ - select-all , \ - - , \ - undo , \ - redo , \ - - , \ - find , \ - find-next , \ - goto-line , \ - jump-to-pair , \ - - , \ - complete-word - -# Default Popup Menu -PopupMenu = \ - ${DEFAULT_EDIT_MENU} , \ - - , \ - goto-line , \ - toggle-comments -# TokenType attributes -Style.OPERATOR = 0x000000, 0 -Style.DELIMITER = 0x000000, 1 -Style.KEYWORD = 0x3333ee, 0 -Style.KEYWORD2 = 0x3333ee, 3 -Style.TYPE = 0x000000, 2 -Style.TYPE2 = 0x000000, 1 -Style.TYPE3 = 0x000000, 3 -Style.STRING = 0xcc6600, 0 -Style.STRING2 = 0xcc6600, 1 -Style.NUMBER = 0x999933, 1 -Style.REGEX = 0xcc6600, 0 -Style.IDENTIFIER = 0x000000, 0 -Style.COMMENT = 0x339933, 2 -Style.COMMENT2 = 0x339933, 3 -Style.DEFAULT = 0x000000, 0 -Style.WARNING = 0xCC0000, 0 -Style.ERROR = 0xCC0000, 3 +DefaultAction.copy-to-clipboard.MenuText = Copiar +DefaultAction.cut-to-clipboard.MenuText = Cortar +DefaultAction.paste-from-clipboard.MenuText = Pegar +DefaultAction.select-all.MenuText = Seleccionar todo + +Action.find.MenuText = Buscar +Action.find.ToolTip = Mostrar el di\u00e1logo de Buscar y Reemplazar +Action.find-next.MenuText = Buscar siguiente +Action.find-next.ToolTip = Repetir la \u00faltima b\u00fasqueda +Action.goto-line.MenuText = Ir al n\u00famero de l\u00ednea +Action.goto-line.ToolTip = Ir al n\u00famero de l\u00ednea +Action.indent.MenuText = Indentar +Action.unindent.MenuText = Quitar indentaci\u00f3n +Action.undo.MenuText = Deshacer +Action.redo.MenuText = Rehacer +Action.delete-lines.MenuText = Borrar l\u00ednea(s) +Action.dup-lines-up.MenuText = Duplicar las l\u00edneas superiores +Action.dup-lines-down.MenuText = Duplicar las l\u00edneas inferiores +Action.toggle-lines.MenuText = Alternar n\u00famero de l\u00edneas +Action.show-abbs.MenuText = Mostrar abreviaciones +Action.show-abbs.ToolTip = Mostrar abreviaciones +Action.complete-word.MenuText = Completar palabra +Action.jump-to-pair.MenuText = Saltar al par +Action.toggle-comments.MenuText = Alternar comentarios + +# !!!! FFDec translators - please do not edit anything below this line !!! +#========================================================================== + +Components = jsyntaxpane.components.PairsMarker, \ + jsyntaxpane.components.LineNumbersRuler +# This is the color to highlight tokens whenever the cursor is on them +TokenMarker.Color = 0xffeeaa +# Colors for PairMarkers +PairMarker.Color = 0xffbb77 +# +# Right Margin for LineNumbers border in pixels, Default = 5 +LineNumbers.RightMargin = 7 +# Foreground for line numbers, Default = Black +LineNumbers.Foreground = 0x333300 +# Background for line numbers, Default = White +LineNumbers.Background = 0xeeeeff +# Color to use for highlighting current line background +LineNumbers.CurrentBack = 0xccccee +# Default color for the Caret, Black +CaretColor = 0x000000 +# Actions: +Action.quick-find = jsyntaxpane.actions.QuickFindAction, control F +Action.find = jsyntaxpane.actions.FindReplaceAction, control H +Action.find-next = jsyntaxpane.actions.FindNextAction, F3 +Action.goto-line = jsyntaxpane.actions.GotoLineAction, control G + +Action.indent = jsyntaxpane.actions.IndentAction, TAB +Action.indent.Abbreviations = ${class_path}/abbreviations.properties +Action.unindent = jsyntaxpane.actions.UnindentAction, shift TAB + +Action.jindent = jsyntaxpane.actions.JIndentAction, ENTER +Action.undo = jsyntaxpane.actions.UndoAction, menu Z +Action.redo = jsyntaxpane.actions.RedoAction, menu Y +Action.delete-lines = jsyntaxpane.actions.DeleteLinesAction, control E +Action.dup-lines-up = jsyntaxpane.actions.DuplicateLinesAction, shift control UP +Action.dup-lines-down = jsyntaxpane.actions.DuplicateLinesAction, shift control DOWN + +Action.toggle-lines = jsyntaxpane.actions.ToggleComponentAction, control F2 +Action.toggle-lines.Component = jsyntaxpane.components.LineNumbersRuler + +Action.toggle-comments = jsyntaxpane.actions.ToggleCommentsAction, control SLASH +Action.toggle-comments.SmallIcon = comment.png +Action.jump-to-pair = jsyntaxpane.actions.JumpToPairAction, control OPEN_BRACKET +Action.complete-word = jsyntaxpane.actions.CompleteWordAction, control K + +Action.smart-home = jsyntaxpane.actions.SmartHomeAction, HOME +Action.smart-home-select = jsyntaxpane.actions.SmartHomeSelectAction, shift HOME +Action.show-abbs = jsyntaxpane.actions.ShowAbbsAction, F8 + +# +# View configuration: +TextAA = ON +DEFAULT_EDIT_MENU= \ + cut-to-clipboard , \ + copy-to-clipboard , \ + paste-from-clipboard , \ + - , \ + select-all , \ + - , \ + undo , \ + redo , \ + - , \ + find , \ + find-next , \ + goto-line , \ + jump-to-pair , \ + - , \ + complete-word + +# Default Popup Menu +PopupMenu = \ + ${DEFAULT_EDIT_MENU} , \ + - , \ + goto-line , \ + toggle-comments +# TokenType attributes +Style.OPERATOR = 0x000000, 0 +Style.DELIMITER = 0x000000, 1 +Style.KEYWORD = 0x3333ee, 0 +Style.KEYWORD2 = 0x3333ee, 3 +Style.TYPE = 0x000000, 2 +Style.TYPE2 = 0x000000, 1 +Style.TYPE3 = 0x000000, 3 +Style.STRING = 0xcc6600, 0 +Style.STRING2 = 0xcc6600, 1 +Style.NUMBER = 0x999933, 1 +Style.REGEX = 0xcc6600, 0 +Style.IDENTIFIER = 0x000000, 0 +Style.COMMENT = 0x339933, 2 +Style.COMMENT2 = 0x339933, 3 +Style.DEFAULT = 0x000000, 0 +Style.WARNING = 0xCC0000, 0 +Style.ERROR = 0xCC0000, 3 diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_pt.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_pt.properties index 7f65923c8..3c3208292 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_pt.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/defaultsyntaxkit/config_pt.properties @@ -1,118 +1,118 @@ -DefaultAction.copy-to-clipboard.MenuText = Copiar -DefaultAction.cut-to-clipboard.MenuText = Cortar -DefaultAction.paste-from-clipboard.MenuText = Colar -DefaultAction.select-all.MenuText = Selecionar tudo - -Action.find.MenuText = Procurar -Action.find.ToolTip = Mostrar procura e trocar dialogo -Action.find-next.MenuText = Procurar proximo -Action.find-next.ToolTip = Repetir ultima procura -Action.goto-line.MenuText = Ir para numero de linha -Action.goto-line.ToolTip = Ir para numero de linha -Action.indent.MenuText = Indentar -Action.unindent.MenuText = Des-identar -Action.undo.MenuText = Voltar a tr\u00e1s -Action.redo.MenuText = Voltar a fazer -Action.delete-lines.MenuText = apagar linha(s) -Action.dup-lines-up.MenuText = Duplicar linhas a cima -Action.dup-lines-down.MenuText = Duplicar linhas a baixo -Action.toggle-lines.MenuText = Alternar numero de linhas -Action.show-abbs.MenuText = Mostrar abrevia\u00e7\u00f5es -Action.show-abbs.ToolTip = Mostrar abrevia\u00e7\u00f5es -Action.complete-word.MenuText = Completar palavra -Action.jump-to-pair.MenuText = Ir para o par -Action.toggle-comments.MenuText = Alternar coment\u00e1rios - -# !!!! FFDec translators - please do not edit anything below this line !!! -#========================================================================== - -Components = jsyntaxpane.components.PairsMarker, \ - jsyntaxpane.components.LineNumbersRuler -# This is the color to highlight tokens whenever the cursor is on them -TokenMarker.Color = 0xffeeaa -# Colors for PairMarkers -PairMarker.Color = 0xffbb77 -# -# Right Margin for LineNumbers border in pixels, Default = 5 -LineNumbers.RightMargin = 7 -# Foreground for line numbers, Default = Black -LineNumbers.Foreground = 0x333300 -# Background for line numbers, Default = White -LineNumbers.Background = 0xeeeeff -# Color to use for highlighting current line background -LineNumbers.CurrentBack = 0xccccee -# Default color for the Caret, Black -CaretColor = 0x000000 -# Actions: -Action.quick-find = jsyntaxpane.actions.QuickFindAction, control F -Action.find = jsyntaxpane.actions.FindReplaceAction, control H -Action.find-next = jsyntaxpane.actions.FindNextAction, F3 -Action.goto-line = jsyntaxpane.actions.GotoLineAction, control G - -Action.indent = jsyntaxpane.actions.IndentAction, TAB -Action.indent.Abbreviations = ${class_path}/abbreviations.properties -Action.unindent = jsyntaxpane.actions.UnindentAction, shift TAB - -Action.jindent = jsyntaxpane.actions.JIndentAction, ENTER -Action.undo = jsyntaxpane.actions.UndoAction, menu Z -Action.redo = jsyntaxpane.actions.RedoAction, menu Y -Action.delete-lines = jsyntaxpane.actions.DeleteLinesAction, control E -Action.dup-lines-up = jsyntaxpane.actions.DuplicateLinesAction, shift control UP -Action.dup-lines-down = jsyntaxpane.actions.DuplicateLinesAction, shift control DOWN - -Action.toggle-lines = jsyntaxpane.actions.ToggleComponentAction, control F2 -Action.toggle-lines.Component = jsyntaxpane.components.LineNumbersRuler - -Action.toggle-comments = jsyntaxpane.actions.ToggleCommentsAction, control SLASH -Action.toggle-comments.SmallIcon = comment.png -Action.jump-to-pair = jsyntaxpane.actions.JumpToPairAction, control OPEN_BRACKET -Action.complete-word = jsyntaxpane.actions.CompleteWordAction, control K - -Action.smart-home = jsyntaxpane.actions.SmartHomeAction, HOME -Action.smart-home-select = jsyntaxpane.actions.SmartHomeSelectAction, shift HOME -Action.show-abbs = jsyntaxpane.actions.ShowAbbsAction, F8 - -# -# View configuration: -TextAA = ON -DEFAULT_EDIT_MENU= \ - cut-to-clipboard , \ - copy-to-clipboard , \ - paste-from-clipboard , \ - - , \ - select-all , \ - - , \ - undo , \ - redo , \ - - , \ - find , \ - find-next , \ - goto-line , \ - jump-to-pair , \ - - , \ - complete-word - -# Default Popup Menu -PopupMenu = \ - ${DEFAULT_EDIT_MENU} , \ - - , \ - goto-line , \ - toggle-comments -# TokenType attributes -Style.OPERATOR = 0x000000, 0 -Style.DELIMITER = 0x000000, 1 -Style.KEYWORD = 0x3333ee, 0 -Style.KEYWORD2 = 0x3333ee, 3 -Style.TYPE = 0x000000, 2 -Style.TYPE2 = 0x000000, 1 -Style.TYPE3 = 0x000000, 3 -Style.STRING = 0xcc6600, 0 -Style.STRING2 = 0xcc6600, 1 -Style.NUMBER = 0x999933, 1 -Style.REGEX = 0xcc6600, 0 -Style.IDENTIFIER = 0x000000, 0 -Style.COMMENT = 0x339933, 2 -Style.COMMENT2 = 0x339933, 3 -Style.DEFAULT = 0x000000, 0 -Style.WARNING = 0xCC0000, 0 -Style.ERROR = 0xCC0000, 3 +DefaultAction.copy-to-clipboard.MenuText = Copiar +DefaultAction.cut-to-clipboard.MenuText = Cortar +DefaultAction.paste-from-clipboard.MenuText = Colar +DefaultAction.select-all.MenuText = Selecionar tudo + +Action.find.MenuText = Procurar +Action.find.ToolTip = Mostrar procura e trocar dialogo +Action.find-next.MenuText = Procurar proximo +Action.find-next.ToolTip = Repetir ultima procura +Action.goto-line.MenuText = Ir para numero de linha +Action.goto-line.ToolTip = Ir para numero de linha +Action.indent.MenuText = Indentar +Action.unindent.MenuText = Des-identar +Action.undo.MenuText = Voltar a tr\u00e1s +Action.redo.MenuText = Voltar a fazer +Action.delete-lines.MenuText = apagar linha(s) +Action.dup-lines-up.MenuText = Duplicar linhas a cima +Action.dup-lines-down.MenuText = Duplicar linhas a baixo +Action.toggle-lines.MenuText = Alternar numero de linhas +Action.show-abbs.MenuText = Mostrar abrevia\u00e7\u00f5es +Action.show-abbs.ToolTip = Mostrar abrevia\u00e7\u00f5es +Action.complete-word.MenuText = Completar palavra +Action.jump-to-pair.MenuText = Ir para o par +Action.toggle-comments.MenuText = Alternar coment\u00e1rios + +# !!!! FFDec translators - please do not edit anything below this line !!! +#========================================================================== + +Components = jsyntaxpane.components.PairsMarker, \ + jsyntaxpane.components.LineNumbersRuler +# This is the color to highlight tokens whenever the cursor is on them +TokenMarker.Color = 0xffeeaa +# Colors for PairMarkers +PairMarker.Color = 0xffbb77 +# +# Right Margin for LineNumbers border in pixels, Default = 5 +LineNumbers.RightMargin = 7 +# Foreground for line numbers, Default = Black +LineNumbers.Foreground = 0x333300 +# Background for line numbers, Default = White +LineNumbers.Background = 0xeeeeff +# Color to use for highlighting current line background +LineNumbers.CurrentBack = 0xccccee +# Default color for the Caret, Black +CaretColor = 0x000000 +# Actions: +Action.quick-find = jsyntaxpane.actions.QuickFindAction, control F +Action.find = jsyntaxpane.actions.FindReplaceAction, control H +Action.find-next = jsyntaxpane.actions.FindNextAction, F3 +Action.goto-line = jsyntaxpane.actions.GotoLineAction, control G + +Action.indent = jsyntaxpane.actions.IndentAction, TAB +Action.indent.Abbreviations = ${class_path}/abbreviations.properties +Action.unindent = jsyntaxpane.actions.UnindentAction, shift TAB + +Action.jindent = jsyntaxpane.actions.JIndentAction, ENTER +Action.undo = jsyntaxpane.actions.UndoAction, menu Z +Action.redo = jsyntaxpane.actions.RedoAction, menu Y +Action.delete-lines = jsyntaxpane.actions.DeleteLinesAction, control E +Action.dup-lines-up = jsyntaxpane.actions.DuplicateLinesAction, shift control UP +Action.dup-lines-down = jsyntaxpane.actions.DuplicateLinesAction, shift control DOWN + +Action.toggle-lines = jsyntaxpane.actions.ToggleComponentAction, control F2 +Action.toggle-lines.Component = jsyntaxpane.components.LineNumbersRuler + +Action.toggle-comments = jsyntaxpane.actions.ToggleCommentsAction, control SLASH +Action.toggle-comments.SmallIcon = comment.png +Action.jump-to-pair = jsyntaxpane.actions.JumpToPairAction, control OPEN_BRACKET +Action.complete-word = jsyntaxpane.actions.CompleteWordAction, control K + +Action.smart-home = jsyntaxpane.actions.SmartHomeAction, HOME +Action.smart-home-select = jsyntaxpane.actions.SmartHomeSelectAction, shift HOME +Action.show-abbs = jsyntaxpane.actions.ShowAbbsAction, F8 + +# +# View configuration: +TextAA = ON +DEFAULT_EDIT_MENU= \ + cut-to-clipboard , \ + copy-to-clipboard , \ + paste-from-clipboard , \ + - , \ + select-all , \ + - , \ + undo , \ + redo , \ + - , \ + find , \ + find-next , \ + goto-line , \ + jump-to-pair , \ + - , \ + complete-word + +# Default Popup Menu +PopupMenu = \ + ${DEFAULT_EDIT_MENU} , \ + - , \ + goto-line , \ + toggle-comments +# TokenType attributes +Style.OPERATOR = 0x000000, 0 +Style.DELIMITER = 0x000000, 1 +Style.KEYWORD = 0x3333ee, 0 +Style.KEYWORD2 = 0x3333ee, 3 +Style.TYPE = 0x000000, 2 +Style.TYPE2 = 0x000000, 1 +Style.TYPE3 = 0x000000, 3 +Style.STRING = 0xcc6600, 0 +Style.STRING2 = 0xcc6600, 1 +Style.NUMBER = 0x999933, 1 +Style.REGEX = 0xcc6600, 0 +Style.IDENTIFIER = 0x000000, 0 +Style.COMMENT = 0x339933, 2 +Style.COMMENT2 = 0x339933, 3 +Style.DEFAULT = 0x000000, 0 +Style.WARNING = 0xCC0000, 0 +Style.ERROR = 0xCC0000, 3 diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/javasyntaxkit/combocompletions.txt b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/javasyntaxkit/combocompletions.txt index 916b81178..d2a4db7b5 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/javasyntaxkit/combocompletions.txt +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/javasyntaxkit/combocompletions.txt @@ -1,18 +1,18 @@ -public -protected -private -class -static -toString() -equals(|) -hashCode() -JTextField -JEditorPane -JTextPane -JComboBox -JList -JTree -jsyntaxpane -setContentType("text/|lang|") -setProperty("|key|") -for(int i=0; i < |max|; i++) {\n\t// loop body \n} +public +protected +private +class +static +toString() +equals(|) +hashCode() +JTextField +JEditorPane +JTextPane +JComboBox +JList +JTree +jsyntaxpane +setContentType("text/|lang|") +setProperty("|key|") +for(int i=0; i < |max|; i++) {\n\t// loop body \n} diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/combocompletions.txt b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/combocompletions.txt index e0afce77d..1d7de5de7 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/combocompletions.txt +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/combocompletions.txt @@ -1,30 +1,30 @@ -and -break -do -else -else \n\t#{p:block} -elseif -elseif (#{p:exp}) then \n\t#{p:block} -end -false -for -for #{p:var}=#{p:num},#{p:max} do \n\t|block \nend -for #{p:namelist} in #{p:explist} do \n\t#{p:block} \nend -function -function #{p:name} () \n\nend -if -if (#{p:exp}) then \n\t#{p:block} \nend -in -local -local function #{p:name} () \n\nend -nil -not -or -repeat -repeat \n\t#{p:block} \nuntil #{p:exp} -return -then -true -until -while +and +break +do +else +else \n\t#{p:block} +elseif +elseif (#{p:exp}) then \n\t#{p:block} +end +false +for +for #{p:var}=#{p:num},#{p:max} do \n\t|block \nend +for #{p:namelist} in #{p:explist} do \n\t#{p:block} \nend +function +function #{p:name} () \n\nend +if +if (#{p:exp}) then \n\t#{p:block} \nend +in +local +local function #{p:name} () \n\nend +nil +not +or +repeat +repeat \n\t#{p:block} \nuntil #{p:exp} +return +then +true +until +while while (#{p:exp}) do \n\t#{p:block} \nend \ No newline at end of file diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/config.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/config.properties index 8758f7c54..86089d0fc 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/config.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/META-INF/services/jsyntaxpane/syntaxkits/luasyntaxkit/config.properties @@ -1,23 +1,23 @@ -# -# Lua Properties: -# - -# For completions, you have to define the Action (key to trigger completions): -Action.combo-completion = jsyntaxpane.actions.ComboCompletionAction, control SPACE -Action.combo-completion.MenuText = Completions -Action.combo-completion.ItemsURL=${class_path}/combocompletions.txt - -# auto fill-in actions -Action.parenthesis = jsyntaxpane.actions.PairAction, typed ( -Action.brackets = jsyntaxpane.actions.PairAction, typed [ -Action.quotes = jsyntaxpane.actions.PairAction, typed ' -Action.double-quotes = jsyntaxpane.actions.PairAction, typed " -Action.close-curly = jsyntaxpane.actions.JUnindentAction, typed } - -# Style is one of: 0 = plain, 1=bold, 2=italic, 3=bold/italic -Style.OPERATOR = 0x000000, 0 -Style.KEYWORD = 0x3333ee, 0 -Style.STRING = 0xcc6600, 0 -Style.NUMBER = 0x999933, 1 -Style.IDENTIFIER = 0x000000, 0 +# +# Lua Properties: +# + +# For completions, you have to define the Action (key to trigger completions): +Action.combo-completion = jsyntaxpane.actions.ComboCompletionAction, control SPACE +Action.combo-completion.MenuText = Completions +Action.combo-completion.ItemsURL=${class_path}/combocompletions.txt + +# auto fill-in actions +Action.parenthesis = jsyntaxpane.actions.PairAction, typed ( +Action.brackets = jsyntaxpane.actions.PairAction, typed [ +Action.quotes = jsyntaxpane.actions.PairAction, typed ' +Action.double-quotes = jsyntaxpane.actions.PairAction, typed " +Action.close-curly = jsyntaxpane.actions.JUnindentAction, typed } + +# Style is one of: 0 = plain, 1=bold, 2=italic, 3=bold/italic +Style.OPERATOR = 0x000000, 0 +Style.KEYWORD = 0x3333ee, 0 +Style.STRING = 0xcc6600, 0 +Style.NUMBER = 0x999933, 1 +Style.IDENTIFIER = 0x000000, 0 Style.COMMENT = 0x339933, 2 \ No newline at end of file diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle.properties index 9bf4beeae..4f06188ed 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = Caret Position -SyntaxTester.lblToken.text = Token under cursor -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = NO Token at cursor - -HTMLPreviewFrame.title = HTML Preview -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Wrap -QuickFindDialog.jChkRegExp.text = Reg Exp -QuickFindDialog.jChkIgnoreCase.text = Ignore Case -QuickFindDialog.jLabel1.text = Quick Find -QuickFindDialog.NotFound = not found -ReplaceDialog.jChkRegex.text = Regular Expression -ReplaceDialog.jChkIgnoreCase.text = Ignore Case -ReplaceDialog.jLblReplace.text = Replace -ReplaceDialog.jTglHighlight.text = Highlight -ReplaceDialog.jBtnReplaceAll.text = Replace All -ReplaceDialog.jBtnPrev.text = Previous -ReplaceDialog.jChkWrap.toolTipText = Wrap to beginning when end is reached -ReplaceDialog.jChkWrap.text = Wrap around -ReplaceDialog.title = Find and Replace -ReplaceDialog.jBtnNext.text = Next -ReplaceDialog.jLblFind.text = Find -ReplaceDialog.jBtnReplace.text = Replace -ShowAbbsDialog.title = Abbreviations -GotoLineDialog.title = Goto Line -GotoLineDialog.jBtnOk.text = Go - -DocumentSearchData.SearchStringNotFound = Search String {0} not found -DocumentSearchData.Find = Find -ScriptAction.NoScriptConfigured = Action does not have script function configured -ScriptAction.ErrorInScript = Error in Script -ScriptAction.NoScriptFoundIn = No script is found in: -ScriptRunnerAction.ErrorExecutingScript = Error executing script:\\n -ScriptRunnerAction.ScriptError = Script Error -ScriptRunnerAction.ScriptEngineNotFound = Script Engine for [{0}] not found. Disable this Action? -ShowAbbsAction.NoAbbsForType = No Abbreviations exist for this content type - +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = Caret Position +SyntaxTester.lblToken.text = Token under cursor +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = NO Token at cursor + +HTMLPreviewFrame.title = HTML Preview +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Wrap +QuickFindDialog.jChkRegExp.text = Reg Exp +QuickFindDialog.jChkIgnoreCase.text = Ignore Case +QuickFindDialog.jLabel1.text = Quick Find +QuickFindDialog.NotFound = not found +ReplaceDialog.jChkRegex.text = Regular Expression +ReplaceDialog.jChkIgnoreCase.text = Ignore Case +ReplaceDialog.jLblReplace.text = Replace +ReplaceDialog.jTglHighlight.text = Highlight +ReplaceDialog.jBtnReplaceAll.text = Replace All +ReplaceDialog.jBtnPrev.text = Previous +ReplaceDialog.jChkWrap.toolTipText = Wrap to beginning when end is reached +ReplaceDialog.jChkWrap.text = Wrap around +ReplaceDialog.title = Find and Replace +ReplaceDialog.jBtnNext.text = Next +ReplaceDialog.jLblFind.text = Find +ReplaceDialog.jBtnReplace.text = Replace +ShowAbbsDialog.title = Abbreviations +GotoLineDialog.title = Goto Line +GotoLineDialog.jBtnOk.text = Go + +DocumentSearchData.SearchStringNotFound = Search String {0} not found +DocumentSearchData.Find = Find +ScriptAction.NoScriptConfigured = Action does not have script function configured +ScriptAction.ErrorInScript = Error in Script +ScriptAction.NoScriptFoundIn = No script is found in: +ScriptRunnerAction.ErrorExecutingScript = Error executing script:\\n +ScriptRunnerAction.ScriptError = Script Error +ScriptRunnerAction.ScriptEngineNotFound = Script Engine for [{0}] not found. Disable this Action? +ShowAbbsAction.NoAbbsForType = No Abbreviations exist for this content type + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_cs.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_cs.properties index 18f39c86a..c4f09c760 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_cs.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_cs.properties @@ -1,38 +1,38 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = Pozice v textu -SyntaxTester.lblToken.text = Token pod kurzorem -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = \u017d\u00e1dn\u00fd token pod kurzorem - -HTMLPreviewFrame.title = HTML n\u00e1hled -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = V\u0161ude -QuickFindDialog.jChkRegExp.text = Regul\u00e1r -QuickFindDialog.jChkIgnoreCase.text = Nerozli\u0161ovat velikost -QuickFindDialog.jLabel1.text = Rychle naj\u00edt -QuickFindDialog.NotFound = nenalezeno -ReplaceDialog.jChkRegex.text = Regul\u00e1rn\u00ed v\u00fdraz -ReplaceDialog.jChkIgnoreCase.text = Nerozli\u0161ovat velikost -ReplaceDialog.jLblReplace.text = Nahradit -ReplaceDialog.jTglHighlight.text = Zv\u00fdrazn\u011bn\u00ed -ReplaceDialog.jBtnReplaceAll.text = Nahradit v\u0161e -ReplaceDialog.jBtnPrev.text = P\u0159edchoz\u00ed -ReplaceDialog.jChkWrap.toolTipText = P\u0159ej\u00edt na za\u010d\u00e1tek textu p\u0159i dosa\u017een\u00ed konce dokumentu -ReplaceDialog.jChkWrap.text = V cel\u00e9m textu -ReplaceDialog.title = Naj\u00edt a nahradit -ReplaceDialog.jBtnNext.text = Dal\u0161\u00ed -ReplaceDialog.jLblFind.text = Naj\u00edt -ReplaceDialog.jBtnReplace.text = Nahradit -ShowAbbsDialog.title = Zkratky -GotoLineDialog.title = P\u0159ej\u00edt na \u0159\u00e1dek -GotoLineDialog.jBtnOk.text = P\u0159ej\u00edt - -DocumentSearchData.SearchStringNotFound = Hledan\u00fd \u0159et\u011bzec {0} nenalezen -DocumentSearchData.Find = Naj\u00edt -ScriptAction.NoScriptConfigured = Akce nem\u00e1 nastaven skript funkce -ScriptAction.ErrorInScript = Chyba v skriptu -ScriptAction.NoScriptFoundIn = Nenalezen skript v: -ScriptRunnerAction.ErrorExecutingScript = Chyba vykon\u00e1v\u00e1n\u00ed skriptu:\\n -ScriptRunnerAction.ScriptError = Chyba skriptu -ScriptRunnerAction.ScriptEngineNotFound = Engine skriptu [{0}] nenalezen. Zak\u00e1zat tuto akci? -ShowAbbsAction.NoAbbsForType = Pro tento typ obsahu neexistuj\u00ed zkratky +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = Pozice v textu +SyntaxTester.lblToken.text = Token pod kurzorem +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = \u017d\u00e1dn\u00fd token pod kurzorem + +HTMLPreviewFrame.title = HTML n\u00e1hled +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = V\u0161ude +QuickFindDialog.jChkRegExp.text = Regul\u00e1r +QuickFindDialog.jChkIgnoreCase.text = Nerozli\u0161ovat velikost +QuickFindDialog.jLabel1.text = Rychle naj\u00edt +QuickFindDialog.NotFound = nenalezeno +ReplaceDialog.jChkRegex.text = Regul\u00e1rn\u00ed v\u00fdraz +ReplaceDialog.jChkIgnoreCase.text = Nerozli\u0161ovat velikost +ReplaceDialog.jLblReplace.text = Nahradit +ReplaceDialog.jTglHighlight.text = Zv\u00fdrazn\u011bn\u00ed +ReplaceDialog.jBtnReplaceAll.text = Nahradit v\u0161e +ReplaceDialog.jBtnPrev.text = P\u0159edchoz\u00ed +ReplaceDialog.jChkWrap.toolTipText = P\u0159ej\u00edt na za\u010d\u00e1tek textu p\u0159i dosa\u017een\u00ed konce dokumentu +ReplaceDialog.jChkWrap.text = V cel\u00e9m textu +ReplaceDialog.title = Naj\u00edt a nahradit +ReplaceDialog.jBtnNext.text = Dal\u0161\u00ed +ReplaceDialog.jLblFind.text = Naj\u00edt +ReplaceDialog.jBtnReplace.text = Nahradit +ShowAbbsDialog.title = Zkratky +GotoLineDialog.title = P\u0159ej\u00edt na \u0159\u00e1dek +GotoLineDialog.jBtnOk.text = P\u0159ej\u00edt + +DocumentSearchData.SearchStringNotFound = Hledan\u00fd \u0159et\u011bzec {0} nenalezen +DocumentSearchData.Find = Naj\u00edt +ScriptAction.NoScriptConfigured = Akce nem\u00e1 nastaven skript funkce +ScriptAction.ErrorInScript = Chyba v skriptu +ScriptAction.NoScriptFoundIn = Nenalezen skript v: +ScriptRunnerAction.ErrorExecutingScript = Chyba vykon\u00e1v\u00e1n\u00ed skriptu:\\n +ScriptRunnerAction.ScriptError = Chyba skriptu +ScriptRunnerAction.ScriptEngineNotFound = Engine skriptu [{0}] nenalezen. Zak\u00e1zat tuto akci? +ShowAbbsAction.NoAbbsForType = Pro tento typ obsahu neexistuj\u00ed zkratky diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_de.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_de.properties index 4f510c6f5..20749ff46 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_de.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_de.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = Einf\u00FCgemarkenposition -SyntaxTester.lblToken.text = Zeichen unter dem Cursor -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = KEIN Zeichen unter den dem Cursor - -HTMLPreviewFrame.title = HTML Vorschau -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Wickeln -QuickFindDialog.jChkRegExp.text = Regul\u00E4rer Ausdruck -QuickFindDialog.jChkIgnoreCase.text = Gross/klein ignorieren -QuickFindDialog.jLabel1.text = Einfache Suche -QuickFindDialog.NotFound = Nicht gefunden -ReplaceDialog.jChkRegex.text = Regul\u00E4rer Ausdruck -ReplaceDialog.jChkIgnoreCase.text = Gross/klein ignorieren -ReplaceDialog.jLblReplace.text = Ersetzen -ReplaceDialog.jTglHighlight.text = Markieren -ReplaceDialog.jBtnReplaceAll.text = Alle ersetzen -ReplaceDialog.jBtnPrev.text = Vorheriges -ReplaceDialog.jChkWrap.toolTipText = Zum Anfang gehen, wenn das Ende erreicht ist -ReplaceDialog.jChkWrap.text = Rundum wickeln -ReplaceDialog.title = Suchen und ersetzen -ReplaceDialog.jBtnNext.text = N\u00E4chstes -ReplaceDialog.jLblFind.text = Suchen -ReplaceDialog.jBtnReplace.text = Ersetzen -ShowAbbsDialog.title = Abk\u00FCrzungen -GotoLineDialog.title = Zur Linie gehen -GotoLineDialog.jBtnOk.text = Go - -DocumentSearchData.SearchStringNotFound = String {0} konnte nicht gefunden werden -DocumentSearchData.Find = Suchen -ScriptAction.NoScriptConfigured = Aktion hat keine konfigurierte Skript-Funktion -ScriptAction.ErrorInScript = Fehler im Skript -ScriptAction.NoScriptFoundIn = Keine Skripts gefunden in: -ScriptRunnerAction.ErrorExecutingScript = Fehler beim ausf\u00FChren des Skripts:\\n -ScriptRunnerAction.ScriptError = Skript Fehler -ScriptRunnerAction.ScriptEngineNotFound = Skript-Motor fu00FCr [{0}] konnte nicht gefunden werden. Diese Aktion deaktivieren? -ShowAbbsAction.NoAbbsForType = Es existieren keine Abk\u00FCrzungen fu00FCr diesen Inhaltstyp - +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = Einf\u00FCgemarkenposition +SyntaxTester.lblToken.text = Zeichen unter dem Cursor +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = KEIN Zeichen unter den dem Cursor + +HTMLPreviewFrame.title = HTML Vorschau +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Wickeln +QuickFindDialog.jChkRegExp.text = Regul\u00E4rer Ausdruck +QuickFindDialog.jChkIgnoreCase.text = Gross/klein ignorieren +QuickFindDialog.jLabel1.text = Einfache Suche +QuickFindDialog.NotFound = Nicht gefunden +ReplaceDialog.jChkRegex.text = Regul\u00E4rer Ausdruck +ReplaceDialog.jChkIgnoreCase.text = Gross/klein ignorieren +ReplaceDialog.jLblReplace.text = Ersetzen +ReplaceDialog.jTglHighlight.text = Markieren +ReplaceDialog.jBtnReplaceAll.text = Alle ersetzen +ReplaceDialog.jBtnPrev.text = Vorheriges +ReplaceDialog.jChkWrap.toolTipText = Zum Anfang gehen, wenn das Ende erreicht ist +ReplaceDialog.jChkWrap.text = Rundum wickeln +ReplaceDialog.title = Suchen und ersetzen +ReplaceDialog.jBtnNext.text = N\u00E4chstes +ReplaceDialog.jLblFind.text = Suchen +ReplaceDialog.jBtnReplace.text = Ersetzen +ShowAbbsDialog.title = Abk\u00FCrzungen +GotoLineDialog.title = Zur Linie gehen +GotoLineDialog.jBtnOk.text = Go + +DocumentSearchData.SearchStringNotFound = String {0} konnte nicht gefunden werden +DocumentSearchData.Find = Suchen +ScriptAction.NoScriptConfigured = Aktion hat keine konfigurierte Skript-Funktion +ScriptAction.ErrorInScript = Fehler im Skript +ScriptAction.NoScriptFoundIn = Keine Skripts gefunden in: +ScriptRunnerAction.ErrorExecutingScript = Fehler beim ausf\u00FChren des Skripts:\\n +ScriptRunnerAction.ScriptError = Skript Fehler +ScriptRunnerAction.ScriptEngineNotFound = Skript-Motor fu00FCr [{0}] konnte nicht gefunden werden. Diese Aktion deaktivieren? +ShowAbbsAction.NoAbbsForType = Es existieren keine Abk\u00FCrzungen fu00FCr diesen Inhaltstyp + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_es.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_es.properties index d5b2ec4fa..bfef57d9d 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_es.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_es.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = Tester JSyntaxPane -SyntaxTester.lblCaretPos.text = Posici\u00f3n de intercalaci\u00f3n -SyntaxTester.lblToken.text = Token bajo el cursor -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = Ning\u00fan Token bajo el cursor - -HTMLPreviewFrame.title = Vista preeliminar de HTML -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Envolver -QuickFindDialog.jChkRegExp.text = Expresi\u00f3n regular -QuickFindDialog.jChkIgnoreCase.text = Ignorar el case -QuickFindDialog.jLabel1.text = B\u00fasqueda r\u00e1pida -QuickFindDialog.NotFound = no encontrado -ReplaceDialog.jChkRegex.text = Expresi\u00f3n regular -ReplaceDialog.jChkIgnoreCase.text = Ignorar el caso -ReplaceDialog.jLblReplace.text = Reemplazar -ReplaceDialog.jTglHighlight.text = Resaltar -ReplaceDialog.jBtnReplaceAll.text = Reemplazar todo -ReplaceDialog.jBtnPrev.text = Previo -ReplaceDialog.jChkWrap.toolTipText = Envolver al inicio cuando el final es alcanzado -ReplaceDialog.jChkWrap.text = Envolver alrededor -ReplaceDialog.title = Buscar y reemplazar -ReplaceDialog.jBtnNext.text = Siguiente -ReplaceDialog.jLblFind.text = Buscar -ReplaceDialog.jBtnReplace.text = Reemplazar -ShowAbbsDialog.title = Abreviaciones -GotoLineDialog.title = Ir a la l\u00ednea -GotoLineDialog.jBtnOk.text = Ir a - -DocumentSearchData.SearchStringNotFound = Buscando cadena {0} no encontrada -DocumentSearchData.Find = Buscar -ScriptAction.NoScriptConfigured = La Acci\u00f3n no tiene un script de funci\u00f3n configurada -ScriptAction.ErrorInScript = Error en el script -ScriptAction.NoScriptFoundIn = Ning\u00fan script es encontrado en: -ScriptRunnerAction.ErrorExecutingScript = Error ejecutando script:\\n -ScriptRunnerAction.ScriptError = Error de script -ScriptRunnerAction.ScriptEngineNotFound = Motor de Script para [{0}] no encontrado. Inhabilitar la acci\u00f3n? -ShowAbbsAction.NoAbbsForType = Ninguna abreviaci\u00f3n existe para este tipo de contenido - +SyntaxTester.title = Tester JSyntaxPane +SyntaxTester.lblCaretPos.text = Posici\u00f3n de intercalaci\u00f3n +SyntaxTester.lblToken.text = Token bajo el cursor +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = Ning\u00fan Token bajo el cursor + +HTMLPreviewFrame.title = Vista preeliminar de HTML +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Envolver +QuickFindDialog.jChkRegExp.text = Expresi\u00f3n regular +QuickFindDialog.jChkIgnoreCase.text = Ignorar el case +QuickFindDialog.jLabel1.text = B\u00fasqueda r\u00e1pida +QuickFindDialog.NotFound = no encontrado +ReplaceDialog.jChkRegex.text = Expresi\u00f3n regular +ReplaceDialog.jChkIgnoreCase.text = Ignorar el caso +ReplaceDialog.jLblReplace.text = Reemplazar +ReplaceDialog.jTglHighlight.text = Resaltar +ReplaceDialog.jBtnReplaceAll.text = Reemplazar todo +ReplaceDialog.jBtnPrev.text = Previo +ReplaceDialog.jChkWrap.toolTipText = Envolver al inicio cuando el final es alcanzado +ReplaceDialog.jChkWrap.text = Envolver alrededor +ReplaceDialog.title = Buscar y reemplazar +ReplaceDialog.jBtnNext.text = Siguiente +ReplaceDialog.jLblFind.text = Buscar +ReplaceDialog.jBtnReplace.text = Reemplazar +ShowAbbsDialog.title = Abreviaciones +GotoLineDialog.title = Ir a la l\u00ednea +GotoLineDialog.jBtnOk.text = Ir a + +DocumentSearchData.SearchStringNotFound = Buscando cadena {0} no encontrada +DocumentSearchData.Find = Buscar +ScriptAction.NoScriptConfigured = La Acci\u00f3n no tiene un script de funci\u00f3n configurada +ScriptAction.ErrorInScript = Error en el script +ScriptAction.NoScriptFoundIn = Ning\u00fan script es encontrado en: +ScriptRunnerAction.ErrorExecutingScript = Error ejecutando script:\\n +ScriptRunnerAction.ScriptError = Error de script +ScriptRunnerAction.ScriptEngineNotFound = Motor de Script para [{0}] no encontrado. Inhabilitar la acci\u00f3n? +ShowAbbsAction.NoAbbsForType = Ninguna abreviaci\u00f3n existe para este tipo de contenido + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_hu.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_hu.properties index d4922d346..7bb5c808b 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_hu.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_hu.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = JSyntaxPane Tesztel\u0151 -SyntaxTester.lblCaretPos.text = Kurzor Poz\u00edci\u00f3 -SyntaxTester.lblToken.text = Token a kurzor alatt -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = Nem tal\u00e1lhat\u00f3 Token a kurzorn\u00e1l - -HTMLPreviewFrame.title = HTML El\u0151n\u00e9zet -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Csomagol -QuickFindDialog.jChkRegExp.text = Reg Kif -QuickFindDialog.jChkIgnoreCase.text = Kis- \u00e9s nagybet\u0171k megk\u00fcl\u00f6nb\u00f6ztet\u00e9s\u00e9nek mell\u0151z\u00e9se -QuickFindDialog.jLabel1.text = Gyors keres\u00e9s -QuickFindDialog.NotFound = nem tal\u00e1lhat\u00f3 -ReplaceDialog.jChkRegex.text = Regul\u00e1ris Kifejez\u00e9s -ReplaceDialog.jChkIgnoreCase.text = Kis- \u00e9s nagybet\u0171k megk\u00fcl\u00f6nb\u00f6ztet\u00e9s\u00e9nek mell\u0151z\u00e9se -ReplaceDialog.jLblReplace.text = Csere -ReplaceDialog.jTglHighlight.text = Kiemel\u00e9s -ReplaceDialog.jBtnReplaceAll.text = Mind cser\u00e9lje -ReplaceDialog.jBtnPrev.text = El\u0151z\u0151 -ReplaceDialog.jChkWrap.toolTipText = Folytat\u00e1s az elej\u00e9r\u0151l, ha a v\u00e9g\u00e9hez \u00e9rt -ReplaceDialog.jChkWrap.text = K\u00f6rbe csomagol -ReplaceDialog.title = Keres\u00e9s \u00e9s Csere -ReplaceDialog.jBtnNext.text = K\u00f6vetkez\u0151 -ReplaceDialog.jLblFind.text = Keres\u00e9s -ReplaceDialog.jBtnReplace.text = Csere -ShowAbbsDialog.title = R\u00f6vid\u00edt\u00e9s -GotoLineDialog.title = Sorhoz ugr\u00e1s -GotoLineDialog.jBtnOk.text = Ugr\u00e1s - -DocumentSearchData.SearchStringNotFound = Keresett sz\u00f6veg {0} nem tal\u00e1lhat\u00f3 -DocumentSearchData.Find = Keres\u00e9s -ScriptAction.NoScriptConfigured = Az akci\u00f3hoz nincs szkript konfigur\u00e1lva -ScriptAction.ErrorInScript = Hiba a Szkriptben -ScriptAction.NoScriptFoundIn = Szkript nem tal\u00e1lhat\u00f3 a k\u00f6vetkez\u0151ben: -ScriptRunnerAction.ErrorExecutingScript = Hiba a szkript futtat\u00e1sakor:\\n -ScriptRunnerAction.ScriptError = Szkript hiba -ScriptRunnerAction.ScriptEngineNotFound = Script Engine [{0}]-hoz nem tal\u00e1lhat\u00f3. Akci\u00f3 letilt\u00e1sa? -ShowAbbsAction.NoAbbsForType = Ehhez a tartalom t\u00edpushoz nem tal\u00e1lhat\u00f3 r\u00f6vid\u00edt\u00e9s - +SyntaxTester.title = JSyntaxPane Tesztel\u0151 +SyntaxTester.lblCaretPos.text = Kurzor Poz\u00edci\u00f3 +SyntaxTester.lblToken.text = Token a kurzor alatt +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = Nem tal\u00e1lhat\u00f3 Token a kurzorn\u00e1l + +HTMLPreviewFrame.title = HTML El\u0151n\u00e9zet +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Csomagol +QuickFindDialog.jChkRegExp.text = Reg Kif +QuickFindDialog.jChkIgnoreCase.text = Kis- \u00e9s nagybet\u0171k megk\u00fcl\u00f6nb\u00f6ztet\u00e9s\u00e9nek mell\u0151z\u00e9se +QuickFindDialog.jLabel1.text = Gyors keres\u00e9s +QuickFindDialog.NotFound = nem tal\u00e1lhat\u00f3 +ReplaceDialog.jChkRegex.text = Regul\u00e1ris Kifejez\u00e9s +ReplaceDialog.jChkIgnoreCase.text = Kis- \u00e9s nagybet\u0171k megk\u00fcl\u00f6nb\u00f6ztet\u00e9s\u00e9nek mell\u0151z\u00e9se +ReplaceDialog.jLblReplace.text = Csere +ReplaceDialog.jTglHighlight.text = Kiemel\u00e9s +ReplaceDialog.jBtnReplaceAll.text = Mind cser\u00e9lje +ReplaceDialog.jBtnPrev.text = El\u0151z\u0151 +ReplaceDialog.jChkWrap.toolTipText = Folytat\u00e1s az elej\u00e9r\u0151l, ha a v\u00e9g\u00e9hez \u00e9rt +ReplaceDialog.jChkWrap.text = K\u00f6rbe csomagol +ReplaceDialog.title = Keres\u00e9s \u00e9s Csere +ReplaceDialog.jBtnNext.text = K\u00f6vetkez\u0151 +ReplaceDialog.jLblFind.text = Keres\u00e9s +ReplaceDialog.jBtnReplace.text = Csere +ShowAbbsDialog.title = R\u00f6vid\u00edt\u00e9s +GotoLineDialog.title = Sorhoz ugr\u00e1s +GotoLineDialog.jBtnOk.text = Ugr\u00e1s + +DocumentSearchData.SearchStringNotFound = Keresett sz\u00f6veg {0} nem tal\u00e1lhat\u00f3 +DocumentSearchData.Find = Keres\u00e9s +ScriptAction.NoScriptConfigured = Az akci\u00f3hoz nincs szkript konfigur\u00e1lva +ScriptAction.ErrorInScript = Hiba a Szkriptben +ScriptAction.NoScriptFoundIn = Szkript nem tal\u00e1lhat\u00f3 a k\u00f6vetkez\u0151ben: +ScriptRunnerAction.ErrorExecutingScript = Hiba a szkript futtat\u00e1sakor:\\n +ScriptRunnerAction.ScriptError = Szkript hiba +ScriptRunnerAction.ScriptEngineNotFound = Script Engine [{0}]-hoz nem tal\u00e1lhat\u00f3. Akci\u00f3 letilt\u00e1sa? +ShowAbbsAction.NoAbbsForType = Ehhez a tartalom t\u00edpushoz nem tal\u00e1lhat\u00f3 r\u00f6vid\u00edt\u00e9s + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_nl.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_nl.properties index 1fdf790f5..f3c7c420d 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_nl.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_nl.properties @@ -1,38 +1,38 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = Cursor Positie -SyntaxTester.lblToken.text = Token bij de cursor -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = GEEN Token bij de cursor - -HTMLPreviewFrame.title = HTML Voorbeeld -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Wikkelen -QuickFindDialog.jChkRegExp.text = Reguliere Expressie -QuickFindDialog.jChkIgnoreCase.text = Hoofdletterongevoelig -QuickFindDialog.jLabel1.text = Snel Zoeken -QuickFindDialog.NotFound = niet gevonden -ReplaceDialog.jChkRegex.text = Reguliere Expressie -ReplaceDialog.jChkIgnoreCase.text = Hoofdletterongevoelig -ReplaceDialog.jLblReplace.text = Vervangen -ReplaceDialog.jTglHighlight.text = Highlighten -ReplaceDialog.jBtnReplaceAll.text = Alles vervangen -ReplaceDialog.jBtnPrev.text = Vorig resultaat -ReplaceDialog.jChkWrap.toolTipText = Tot begin wikkelen, wanneer het einde is bereikt -ReplaceDialog.jChkWrap.text = Rond wikkelen -ReplaceDialog.title = Zoeken en Vervangen -ReplaceDialog.jBtnNext.text = Volgend resultaat -ReplaceDialog.jLblFind.text = Zoeken -ReplaceDialog.jBtnReplace.text = Vervangen -ShowAbbsDialog.title = Afkortingen -GotoLineDialog.title = Naar Lijn gaan -GotoLineDialog.jBtnOk.text = Go - -DocumentSearchData.SearchStringNotFound = Zoekstring {0} is niet gevonden -DocumentSearchData.Find = Zoeken -ScriptAction.NoScriptConfigured = Actie heeft geen geconfigureerd script functie -ScriptAction.ErrorInScript = Fout in het Script -ScriptAction.NoScriptFoundIn = Geen script wordt gevonden in: -ScriptRunnerAction.ErrorExecutingScript = Fout bij uitvoeren van script:\\n -ScriptRunnerAction.ScriptError = Script Fout -ScriptRunnerAction.ScriptEngineNotFound = Script Motor voor [{0}] is niet gevonden. Deze Actie deactiveren? -ShowAbbsAction.NoAbbsForType = Geen Afkortingen bestaan voor dit inhoudstype +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = Cursor Positie +SyntaxTester.lblToken.text = Token bij de cursor +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = GEEN Token bij de cursor + +HTMLPreviewFrame.title = HTML Voorbeeld +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Wikkelen +QuickFindDialog.jChkRegExp.text = Reguliere Expressie +QuickFindDialog.jChkIgnoreCase.text = Hoofdletterongevoelig +QuickFindDialog.jLabel1.text = Snel Zoeken +QuickFindDialog.NotFound = niet gevonden +ReplaceDialog.jChkRegex.text = Reguliere Expressie +ReplaceDialog.jChkIgnoreCase.text = Hoofdletterongevoelig +ReplaceDialog.jLblReplace.text = Vervangen +ReplaceDialog.jTglHighlight.text = Highlighten +ReplaceDialog.jBtnReplaceAll.text = Alles vervangen +ReplaceDialog.jBtnPrev.text = Vorig resultaat +ReplaceDialog.jChkWrap.toolTipText = Tot begin wikkelen, wanneer het einde is bereikt +ReplaceDialog.jChkWrap.text = Rond wikkelen +ReplaceDialog.title = Zoeken en Vervangen +ReplaceDialog.jBtnNext.text = Volgend resultaat +ReplaceDialog.jLblFind.text = Zoeken +ReplaceDialog.jBtnReplace.text = Vervangen +ShowAbbsDialog.title = Afkortingen +GotoLineDialog.title = Naar Lijn gaan +GotoLineDialog.jBtnOk.text = Go + +DocumentSearchData.SearchStringNotFound = Zoekstring {0} is niet gevonden +DocumentSearchData.Find = Zoeken +ScriptAction.NoScriptConfigured = Actie heeft geen geconfigureerd script functie +ScriptAction.ErrorInScript = Fout in het Script +ScriptAction.NoScriptFoundIn = Geen script wordt gevonden in: +ScriptRunnerAction.ErrorExecutingScript = Fout bij uitvoeren van script:\\n +ScriptRunnerAction.ScriptError = Script Fout +ScriptRunnerAction.ScriptEngineNotFound = Script Motor voor [{0}] is niet gevonden. Deze Actie deactiveren? +ShowAbbsAction.NoAbbsForType = Geen Afkortingen bestaan voor dit inhoudstype diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_pt.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_pt.properties index 3d6c451f4..b223173a2 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_pt.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_pt.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = Tester JSyntaxPane -SyntaxTester.lblCaretPos.text = Posi\u00e7\u00e3o de intercala\u00e7\u00e3o -SyntaxTester.lblToken.text = Token no cursor -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = Nenhum token no cursor - -HTMLPreviewFrame.title = Pr\u00e9-visualiza\u00e7\u00e3o HTML -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Envolver -QuickFindDialog.jChkRegExp.text = Reg Exp -QuickFindDialog.jChkIgnoreCase.text = Ignorar caso -QuickFindDialog.jLabel1.text = Procura rapida -QuickFindDialog.NotFound = n\u00e3o encontrado -ReplaceDialog.jChkRegex.text = Express\u00e3o regular -ReplaceDialog.jChkIgnoreCase.text = Ignorar caso -ReplaceDialog.jLblReplace.text = Substituir -ReplaceDialog.jTglHighlight.text = Salientar -ReplaceDialog.jBtnReplaceAll.text = Substituir tudo -ReplaceDialog.jBtnPrev.text = Pr\u00e9vio -ReplaceDialog.jChkWrap.toolTipText = Envolver ao inicio quando chegar ao final -ReplaceDialog.jChkWrap.text = Envolver -ReplaceDialog.title = Procurar e substituir -ReplaceDialog.jBtnNext.text = Pr\u00f3ximo -ReplaceDialog.jLblFind.text = Procurar -ReplaceDialog.jBtnReplace.text = Substituir -ShowAbbsDialog.title = Abrevia\u00e7\u00f5es -GotoLineDialog.title = Ir para linha -GotoLineDialog.jBtnOk.text = Ir - -DocumentSearchData.SearchStringNotFound = Procura de String {0} n\u00e3o encontrada -DocumentSearchData.Find = Procura -ScriptAction.NoScriptConfigured = Ac\u00e7\u00e3o nao contem a fun\u00e7\u00e3o de script configurada -ScriptAction.ErrorInScript = Erro no Script -ScriptAction.NoScriptFoundIn = Nenhum script encontrado em: -ScriptRunnerAction.ErrorExecutingScript = Erro a executar script:\\n -ScriptRunnerAction.ScriptError = Erro de Script -ScriptRunnerAction.ScriptEngineNotFound = Motor de script para [{0}] n\u00e3o encontrado. Desabilitar esta ac\u00e7\u00e3o? -ShowAbbsAction.NoAbbsForType = N\u00e3o existem abreviaturas para este tipo de conteudo - +SyntaxTester.title = Tester JSyntaxPane +SyntaxTester.lblCaretPos.text = Posi\u00e7\u00e3o de intercala\u00e7\u00e3o +SyntaxTester.lblToken.text = Token no cursor +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = Nenhum token no cursor + +HTMLPreviewFrame.title = Pr\u00e9-visualiza\u00e7\u00e3o HTML +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Envolver +QuickFindDialog.jChkRegExp.text = Reg Exp +QuickFindDialog.jChkIgnoreCase.text = Ignorar caso +QuickFindDialog.jLabel1.text = Procura rapida +QuickFindDialog.NotFound = n\u00e3o encontrado +ReplaceDialog.jChkRegex.text = Express\u00e3o regular +ReplaceDialog.jChkIgnoreCase.text = Ignorar caso +ReplaceDialog.jLblReplace.text = Substituir +ReplaceDialog.jTglHighlight.text = Salientar +ReplaceDialog.jBtnReplaceAll.text = Substituir tudo +ReplaceDialog.jBtnPrev.text = Pr\u00e9vio +ReplaceDialog.jChkWrap.toolTipText = Envolver ao inicio quando chegar ao final +ReplaceDialog.jChkWrap.text = Envolver +ReplaceDialog.title = Procurar e substituir +ReplaceDialog.jBtnNext.text = Pr\u00f3ximo +ReplaceDialog.jLblFind.text = Procurar +ReplaceDialog.jBtnReplace.text = Substituir +ShowAbbsDialog.title = Abrevia\u00e7\u00f5es +GotoLineDialog.title = Ir para linha +GotoLineDialog.jBtnOk.text = Ir + +DocumentSearchData.SearchStringNotFound = Procura de String {0} n\u00e3o encontrada +DocumentSearchData.Find = Procura +ScriptAction.NoScriptConfigured = Ac\u00e7\u00e3o nao contem a fun\u00e7\u00e3o de script configurada +ScriptAction.ErrorInScript = Erro no Script +ScriptAction.NoScriptFoundIn = Nenhum script encontrado em: +ScriptRunnerAction.ErrorExecutingScript = Erro a executar script:\\n +ScriptRunnerAction.ScriptError = Erro de Script +ScriptRunnerAction.ScriptEngineNotFound = Motor de script para [{0}] n\u00e3o encontrado. Desabilitar esta ac\u00e7\u00e3o? +ShowAbbsAction.NoAbbsForType = N\u00e3o existem abreviaturas para este tipo de conteudo + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_ru.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_ru.properties index 39c933ad9..a142b7686 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_ru.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_ru.properties @@ -1,38 +1,38 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = \u041f\u043e\u0437\u0438\u0446\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0440\u0430 -SyntaxTester.lblToken.text = \u0422\u043e\u043a\u0435\u043d \u043f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = \u041D\u0415\u0422 \u0442\u043E\u043A\u0435\u043D\u0430 \u043F\u043E\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C - -HTMLPreviewFrame.title = \u041F\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 HTML -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043a\u043b\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a -QuickFindDialog.jChkRegExp.text = \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 -QuickFindDialog.jChkIgnoreCase.text = \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440 -QuickFindDialog.jLabel1.text = \u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u043e\u0438\u0441\u043a -QuickFindDialog.NotFound = \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e -ReplaceDialog.jChkRegex.text = \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 -ReplaceDialog.jChkIgnoreCase.text = \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440 -ReplaceDialog.jLblReplace.text = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c -ReplaceDialog.jTglHighlight.text = \u0412\u0438\u0434\u0435\u043B\u0438\u0442\u044C -ReplaceDialog.jBtnReplaceAll.text = \u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0441\u0451 -ReplaceDialog.jBtnPrev.text = \u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 -ReplaceDialog.jChkWrap.toolTipText = \u041D\u0430\u0447\u0430\u0442\u044C \u043f\u043e\u0438\u0441\u043a \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0446\u0430 \u0444\u0430\u0439\u043b\u0430 -ReplaceDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043a\u043b\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a -ReplaceDialog.title = \u041D\u0430\u0439\u0442\u0438 \u0438 \u0437\u0430\u043C\u0435\u043D\u0438\u0442\u044C -ReplaceDialog.jBtnNext.text = \u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 -ReplaceDialog.jLblFind.text = \u041d\u0430\u0439\u0442\u0438 -ReplaceDialog.jBtnReplace.text = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c -ShowAbbsDialog.title = \u0421\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f -GotoLineDialog.title = \u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u043A \u0441\u0442\u0440\u043E\u043A\u0435 -GotoLineDialog.jBtnOk.text = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 - -DocumentSearchData.SearchStringNotFound = \u0421\u0442\u0440\u043e\u043a\u0430 {0} \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 -DocumentSearchData.Find = \u041d\u0430\u0439\u0442\u0438 -ScriptAction.NoScriptConfigured = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 -ScriptAction.ErrorInScript = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 -ScriptAction.NoScriptFoundIn = \u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432: -ScriptRunnerAction.ErrorExecutingScript = \u041e\u0448\u0438\u0431\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430:\\n -ScriptRunnerAction.ScriptError = \u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 -ScriptRunnerAction.ScriptEngineNotFound = \u0421\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f [{0}] \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435? -ShowAbbsAction.NoAbbsForType = \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0439 +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = \u041f\u043e\u0437\u0438\u0446\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0440\u0430 +SyntaxTester.lblToken.text = \u0422\u043e\u043a\u0435\u043d \u043f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = \u041D\u0415\u0422 \u0442\u043E\u043A\u0435\u043D\u0430 \u043F\u043E\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C + +HTMLPreviewFrame.title = \u041F\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 HTML +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043a\u043b\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a +QuickFindDialog.jChkRegExp.text = \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 +QuickFindDialog.jChkIgnoreCase.text = \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440 +QuickFindDialog.jLabel1.text = \u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u043e\u0438\u0441\u043a +QuickFindDialog.NotFound = \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e +ReplaceDialog.jChkRegex.text = \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 +ReplaceDialog.jChkIgnoreCase.text = \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440 +ReplaceDialog.jLblReplace.text = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c +ReplaceDialog.jTglHighlight.text = \u0412\u0438\u0434\u0435\u043B\u0438\u0442\u044C +ReplaceDialog.jBtnReplaceAll.text = \u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0441\u0451 +ReplaceDialog.jBtnPrev.text = \u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 +ReplaceDialog.jChkWrap.toolTipText = \u041D\u0430\u0447\u0430\u0442\u044C \u043f\u043e\u0438\u0441\u043a \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u0440\u0438 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0446\u0430 \u0444\u0430\u0439\u043b\u0430 +ReplaceDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043a\u043b\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a +ReplaceDialog.title = \u041D\u0430\u0439\u0442\u0438 \u0438 \u0437\u0430\u043C\u0435\u043D\u0438\u0442\u044C +ReplaceDialog.jBtnNext.text = \u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 +ReplaceDialog.jLblFind.text = \u041d\u0430\u0439\u0442\u0438 +ReplaceDialog.jBtnReplace.text = \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c +ShowAbbsDialog.title = \u0421\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f +GotoLineDialog.title = \u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u043A \u0441\u0442\u0440\u043E\u043A\u0435 +GotoLineDialog.jBtnOk.text = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 + +DocumentSearchData.SearchStringNotFound = \u0421\u0442\u0440\u043e\u043a\u0430 {0} \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 +DocumentSearchData.Find = \u041d\u0430\u0439\u0442\u0438 +ScriptAction.NoScriptConfigured = \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 +ScriptAction.ErrorInScript = \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 +ScriptAction.NoScriptFoundIn = \u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432: +ScriptRunnerAction.ErrorExecutingScript = \u041e\u0448\u0438\u0431\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430:\\n +ScriptRunnerAction.ScriptError = \u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 +ScriptRunnerAction.ScriptEngineNotFound = \u0421\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0434\u043b\u044f [{0}] \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d. \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435? +ShowAbbsAction.NoAbbsForType = \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0439 diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_sv.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_sv.properties index a8bb4eb15..5f56e54a1 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_sv.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_sv.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = JSyntaxPane Testare -SyntaxTester.lblCaretPos.text = Mark\u00f6r Position -SyntaxTester.lblToken.text = Tecken under mark\u00f6ren -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = Inget tecken vid mark\u00f6ren - -HTMLPreviewFrame.title = HTML f\u00f6rhandsvisning -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Indelning -QuickFindDialog.jChkRegExp.text = Reg Exp -QuickFindDialog.jChkIgnoreCase.text = Ignorera stora/sm\u00e5 bokst\u00e4ver -QuickFindDialog.jLabel1.text = Snabb s\u00f6kning -QuickFindDialog.NotFound = hittades inte -ReplaceDialog.jChkRegex.text = Regular Expression -ReplaceDialog.jChkIgnoreCase.text = Ignorera stora/sm\u00e5 bokst\u00e4ver -ReplaceDialog.jLblReplace.text = Ers\u00e4tt -ReplaceDialog.jTglHighlight.text = Markera -ReplaceDialog.jBtnReplaceAll.text = Ers\u00e4tt Alla -ReplaceDialog.jBtnPrev.text = F\u00f6reg\u00e5ende -ReplaceDialog.jChkWrap.toolTipText = Indela till b\u00f6rjan n\u00e4r slutet har n\u00e5tts -ReplaceDialog.jChkWrap.text = Indela runt -ReplaceDialog.title = Hitta och Ers\u00e4tt -ReplaceDialog.jBtnNext.text = N\u00e4sta -ReplaceDialog.jLblFind.text = Hitta -ReplaceDialog.jBtnReplace.text = Ers\u00e4tt -ShowAbbsDialog.title = F\u00f6rkortningar -GotoLineDialog.title = G\u00e5 till rad -GotoLineDialog.jBtnOk.text = G\u00e5 - -DocumentSearchData.SearchStringNotFound = S\u00f6kte str\u00e4ng {0} men hittades inte -DocumentSearchData.Find = Hitta -ScriptAction.NoScriptConfigured = Action does not have script function configured -ScriptAction.ErrorInScript = Fel i Skript -ScriptAction.NoScriptFoundIn = Inget skript finns i: -ScriptRunnerAction.ErrorExecutingScript = Gick inte att k\u00f6ra skriptet:\\n -ScriptRunnerAction.ScriptError = Skript Fel -ScriptRunnerAction.ScriptEngineNotFound = Skriptmotor f\u00f6r [{0}] hittades inte. Inaktivera denna \u00e5tg\u00e4rd? -ShowAbbsAction.NoAbbsForType = Inga F\u00f6rkortningar finns f\u00f6r denna inneh\u00e5llstyp - +SyntaxTester.title = JSyntaxPane Testare +SyntaxTester.lblCaretPos.text = Mark\u00f6r Position +SyntaxTester.lblToken.text = Tecken under mark\u00f6ren +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = Inget tecken vid mark\u00f6ren + +HTMLPreviewFrame.title = HTML f\u00f6rhandsvisning +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Indelning +QuickFindDialog.jChkRegExp.text = Reg Exp +QuickFindDialog.jChkIgnoreCase.text = Ignorera stora/sm\u00e5 bokst\u00e4ver +QuickFindDialog.jLabel1.text = Snabb s\u00f6kning +QuickFindDialog.NotFound = hittades inte +ReplaceDialog.jChkRegex.text = Regular Expression +ReplaceDialog.jChkIgnoreCase.text = Ignorera stora/sm\u00e5 bokst\u00e4ver +ReplaceDialog.jLblReplace.text = Ers\u00e4tt +ReplaceDialog.jTglHighlight.text = Markera +ReplaceDialog.jBtnReplaceAll.text = Ers\u00e4tt Alla +ReplaceDialog.jBtnPrev.text = F\u00f6reg\u00e5ende +ReplaceDialog.jChkWrap.toolTipText = Indela till b\u00f6rjan n\u00e4r slutet har n\u00e5tts +ReplaceDialog.jChkWrap.text = Indela runt +ReplaceDialog.title = Hitta och Ers\u00e4tt +ReplaceDialog.jBtnNext.text = N\u00e4sta +ReplaceDialog.jLblFind.text = Hitta +ReplaceDialog.jBtnReplace.text = Ers\u00e4tt +ShowAbbsDialog.title = F\u00f6rkortningar +GotoLineDialog.title = G\u00e5 till rad +GotoLineDialog.jBtnOk.text = G\u00e5 + +DocumentSearchData.SearchStringNotFound = S\u00f6kte str\u00e4ng {0} men hittades inte +DocumentSearchData.Find = Hitta +ScriptAction.NoScriptConfigured = Action does not have script function configured +ScriptAction.ErrorInScript = Fel i Skript +ScriptAction.NoScriptFoundIn = Inget skript finns i: +ScriptRunnerAction.ErrorExecutingScript = Gick inte att k\u00f6ra skriptet:\\n +ScriptRunnerAction.ScriptError = Skript Fel +ScriptRunnerAction.ScriptEngineNotFound = Skriptmotor f\u00f6r [{0}] hittades inte. Inaktivera denna \u00e5tg\u00e4rd? +ShowAbbsAction.NoAbbsForType = Inga F\u00f6rkortningar finns f\u00f6r denna inneh\u00e5llstyp + diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_uk.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_uk.properties index e2d66813a..f5b470e21 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_uk.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_uk.properties @@ -1,38 +1,38 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = \u041F\u043E\u0437\u0438\u0446\u0456\u044F \u043A\u0443\u0440\u0441\u043E\u0440\u0430 -SyntaxTester.lblToken.text = \u0422\u043E\u043A\u0435\u043D \u043F\u0456\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = \u041D\u0415\u041C\u0410\u0404 \u0442\u043E\u043A\u0435\u043D\u0430 \u043F\u0456\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C - -HTMLPreviewFrame.title = \u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 HTML -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043A\u043B\u0438\u0442\u0438 \u043F\u043E\u0448\u0443\u043A -QuickFindDialog.jChkRegExp.text = \u0420\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u0438\u0439 \u0432\u0438\u0440\u0430\u0437 -QuickFindDialog.jChkIgnoreCase.text = \u0406\u0433\u043D\u043E\u0440\u0443\u0432\u0430\u0442\u0438 \u0440\u0435\u0433\u0456\u0441\u0442\u0440 -QuickFindDialog.jLabel1.text = \u0428\u0432\u0438\u0434\u043A\u0438\u0439 \u043F\u043E\u0448\u0443\u043A -QuickFindDialog.NotFound = \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E -ReplaceDialog.jChkRegex.text = \u0420\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u0438\u0439 \u0432\u0438\u0440\u0430\u0437 -ReplaceDialog.jChkIgnoreCase.text = \u0406\u0433\u043D\u043E\u0440\u0443\u0432\u0430\u0442\u0438 \u0440\u0435\u0433\u0456\u0441\u0442\u0440 -ReplaceDialog.jLblReplace.text = \u0417\u0430\u043C\u0456\u043D\u0438\u0442\u0438 -ReplaceDialog.jTglHighlight.text = \u0412\u0438\u0434\u0456\u043B\u0438\u0442\u0438 -ReplaceDialog.jBtnReplaceAll.text = \u0417\u0430\u043C\u0456\u043D\u0438\u0442\u0438 \u0432\u0441\u0435 -ReplaceDialog.jBtnPrev.text = \u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 -ReplaceDialog.jChkWrap.toolTipText = \u041F\u043E\u0447\u0430\u0442\u0438 \u043F\u043E\u0448\u0443\u043A \u0437\u0430\u043D\u043E\u0432\u043E \u043F\u0440\u0438 \u0434\u043E\u0441\u044F\u0433\u043D\u0435\u043D\u043D\u0456 \u043A\u0456\u043D\u0446\u044F \u0444\u0430\u0439\u043B\u0443 -ReplaceDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043A\u043B\u0438\u0442\u0438 \u043F\u043E\u0448\u0443\u043A -ReplaceDialog.title = \u0417\u043D\u0430\u0439\u0442\u0438 \u0456 \u0437\u0430\u043C\u0456\u043D\u0438\u0442\u0438 -ReplaceDialog.jBtnNext.text = \u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 -ReplaceDialog.jLblFind.text = \u0417\u043D\u0430\u0439\u0442\u0438 -ReplaceDialog.jBtnReplace.text = \u0417\u0430\u043C\u0456\u043D\u0438\u0442\u0438 -ShowAbbsDialog.title = \u0421\u043A\u043E\u0440\u043E\u0447\u0435\u043D\u043D\u044F -GotoLineDialog.title = \u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043E \u0440\u044F\u0434\u043A\u0430 -GotoLineDialog.jBtnOk.text = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 - -DocumentSearchData.SearchStringNotFound = \u0420\u044F\u0434\u043E\u043A {0} \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E -DocumentSearchData.Find = \u0417\u043D\u0430\u0439\u0442\u0438 -ScriptAction.NoScriptConfigured = \u0414\u0456\u044F \u043D\u0435 \u043C\u0430\u0454 \u043D\u0430\u043B\u0430\u0448\u0442\u043E\u0432\u0430\u043D\u043E\u0433\u043E \u0441\u043A\u0440\u0438\u043F\u0442\u0430 -ScriptAction.ErrorInScript = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0432 \u0441\u043A\u0440\u0438\u043F\u0442\u0456 -ScriptAction.NoScriptFoundIn = \u0421\u043A\u0440\u0438\u043F\u0442 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0432: -ScriptRunnerAction.ErrorExecutingScript = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u0441\u043A\u0440\u0438\u043F\u0442\u0430:\\n -ScriptRunnerAction.ScriptError = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0441\u043A\u0440\u0438\u043F\u0442\u0430 -ScriptRunnerAction.ScriptEngineNotFound = \u0421\u043A\u0440\u0438\u043F\u0442\u043E\u0432\u0438\u0439 \u0440\u0443\u0448\u0456\u0439 \u0434\u043B\u044F [{0}] \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E. \u0412\u0438\u043C\u043A\u043D\u0443\u0442\u0438 \u0446\u044E \u0434\u0456\u044E? -ShowAbbsAction.NoAbbsForType = \u0414\u043B\u044F \u0446\u044C\u043E\u0433\u043E \u0442\u0438\u043F\u0443 \u0432\u043C\u0456\u0441\u0442\u0443 \u043D\u0435 \u0456\u0441\u043D\u0443\u0454 \u0441\u043A\u043E\u0440\u043E\u0447\u0435\u043D\u044C +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = \u041F\u043E\u0437\u0438\u0446\u0456\u044F \u043A\u0443\u0440\u0441\u043E\u0440\u0430 +SyntaxTester.lblToken.text = \u0422\u043E\u043A\u0435\u043D \u043F\u0456\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = \u041D\u0415\u041C\u0410\u0404 \u0442\u043E\u043A\u0435\u043D\u0430 \u043F\u0456\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C + +HTMLPreviewFrame.title = \u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 HTML +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043A\u043B\u0438\u0442\u0438 \u043F\u043E\u0448\u0443\u043A +QuickFindDialog.jChkRegExp.text = \u0420\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u0438\u0439 \u0432\u0438\u0440\u0430\u0437 +QuickFindDialog.jChkIgnoreCase.text = \u0406\u0433\u043D\u043E\u0440\u0443\u0432\u0430\u0442\u0438 \u0440\u0435\u0433\u0456\u0441\u0442\u0440 +QuickFindDialog.jLabel1.text = \u0428\u0432\u0438\u0434\u043A\u0438\u0439 \u043F\u043E\u0448\u0443\u043A +QuickFindDialog.NotFound = \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E +ReplaceDialog.jChkRegex.text = \u0420\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u0438\u0439 \u0432\u0438\u0440\u0430\u0437 +ReplaceDialog.jChkIgnoreCase.text = \u0406\u0433\u043D\u043E\u0440\u0443\u0432\u0430\u0442\u0438 \u0440\u0435\u0433\u0456\u0441\u0442\u0440 +ReplaceDialog.jLblReplace.text = \u0417\u0430\u043C\u0456\u043D\u0438\u0442\u0438 +ReplaceDialog.jTglHighlight.text = \u0412\u0438\u0434\u0456\u043B\u0438\u0442\u0438 +ReplaceDialog.jBtnReplaceAll.text = \u0417\u0430\u043C\u0456\u043D\u0438\u0442\u0438 \u0432\u0441\u0435 +ReplaceDialog.jBtnPrev.text = \u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 +ReplaceDialog.jChkWrap.toolTipText = \u041F\u043E\u0447\u0430\u0442\u0438 \u043F\u043E\u0448\u0443\u043A \u0437\u0430\u043D\u043E\u0432\u043E \u043F\u0440\u0438 \u0434\u043E\u0441\u044F\u0433\u043D\u0435\u043D\u043D\u0456 \u043A\u0456\u043D\u0446\u044F \u0444\u0430\u0439\u043B\u0443 +ReplaceDialog.jChkWrap.text = \u0417\u0430\u0446\u0438\u043A\u043B\u0438\u0442\u0438 \u043F\u043E\u0448\u0443\u043A +ReplaceDialog.title = \u0417\u043D\u0430\u0439\u0442\u0438 \u0456 \u0437\u0430\u043C\u0456\u043D\u0438\u0442\u0438 +ReplaceDialog.jBtnNext.text = \u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 +ReplaceDialog.jLblFind.text = \u0417\u043D\u0430\u0439\u0442\u0438 +ReplaceDialog.jBtnReplace.text = \u0417\u0430\u043C\u0456\u043D\u0438\u0442\u0438 +ShowAbbsDialog.title = \u0421\u043A\u043E\u0440\u043E\u0447\u0435\u043D\u043D\u044F +GotoLineDialog.title = \u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043E \u0440\u044F\u0434\u043A\u0430 +GotoLineDialog.jBtnOk.text = \u041f\u0435\u0440\u0435\u0439\u0442\u0438 + +DocumentSearchData.SearchStringNotFound = \u0420\u044F\u0434\u043E\u043A {0} \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E +DocumentSearchData.Find = \u0417\u043D\u0430\u0439\u0442\u0438 +ScriptAction.NoScriptConfigured = \u0414\u0456\u044F \u043D\u0435 \u043C\u0430\u0454 \u043D\u0430\u043B\u0430\u0448\u0442\u043E\u0432\u0430\u043D\u043E\u0433\u043E \u0441\u043A\u0440\u0438\u043F\u0442\u0430 +ScriptAction.ErrorInScript = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0432 \u0441\u043A\u0440\u0438\u043F\u0442\u0456 +ScriptAction.NoScriptFoundIn = \u0421\u043A\u0440\u0438\u043F\u0442 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0432: +ScriptRunnerAction.ErrorExecutingScript = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u0441\u043A\u0440\u0438\u043F\u0442\u0430:\\n +ScriptRunnerAction.ScriptError = \u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u0441\u043A\u0440\u0438\u043F\u0442\u0430 +ScriptRunnerAction.ScriptEngineNotFound = \u0421\u043A\u0440\u0438\u043F\u0442\u043E\u0432\u0438\u0439 \u0440\u0443\u0448\u0456\u0439 \u0434\u043B\u044F [{0}] \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E. \u0412\u0438\u043C\u043A\u043D\u0443\u0442\u0438 \u0446\u044E \u0434\u0456\u044E? +ShowAbbsAction.NoAbbsForType = \u0414\u043B\u044F \u0446\u044C\u043E\u0433\u043E \u0442\u0438\u043F\u0443 \u0432\u043C\u0456\u0441\u0442\u0443 \u043D\u0435 \u0456\u0441\u043D\u0443\u0454 \u0441\u043A\u043E\u0440\u043E\u0447\u0435\u043D\u044C diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_zh.properties b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_zh.properties index 9bf4beeae..4f06188ed 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_zh.properties +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/resources/jsyntaxpane/Bundle_zh.properties @@ -1,39 +1,39 @@ -SyntaxTester.title = JSyntaxPane Tester -SyntaxTester.lblCaretPos.text = Caret Position -SyntaxTester.lblToken.text = Token under cursor -SyntaxTester.jEdtTest.contentType = -NO_TOKEN_AT_CURSOR = NO Token at cursor - -HTMLPreviewFrame.title = HTML Preview -HTMLPreviewFrame.jEdtHtml.contentType = text/html -QuickFindDialog.jChkWrap.text = Wrap -QuickFindDialog.jChkRegExp.text = Reg Exp -QuickFindDialog.jChkIgnoreCase.text = Ignore Case -QuickFindDialog.jLabel1.text = Quick Find -QuickFindDialog.NotFound = not found -ReplaceDialog.jChkRegex.text = Regular Expression -ReplaceDialog.jChkIgnoreCase.text = Ignore Case -ReplaceDialog.jLblReplace.text = Replace -ReplaceDialog.jTglHighlight.text = Highlight -ReplaceDialog.jBtnReplaceAll.text = Replace All -ReplaceDialog.jBtnPrev.text = Previous -ReplaceDialog.jChkWrap.toolTipText = Wrap to beginning when end is reached -ReplaceDialog.jChkWrap.text = Wrap around -ReplaceDialog.title = Find and Replace -ReplaceDialog.jBtnNext.text = Next -ReplaceDialog.jLblFind.text = Find -ReplaceDialog.jBtnReplace.text = Replace -ShowAbbsDialog.title = Abbreviations -GotoLineDialog.title = Goto Line -GotoLineDialog.jBtnOk.text = Go - -DocumentSearchData.SearchStringNotFound = Search String {0} not found -DocumentSearchData.Find = Find -ScriptAction.NoScriptConfigured = Action does not have script function configured -ScriptAction.ErrorInScript = Error in Script -ScriptAction.NoScriptFoundIn = No script is found in: -ScriptRunnerAction.ErrorExecutingScript = Error executing script:\\n -ScriptRunnerAction.ScriptError = Script Error -ScriptRunnerAction.ScriptEngineNotFound = Script Engine for [{0}] not found. Disable this Action? -ShowAbbsAction.NoAbbsForType = No Abbreviations exist for this content type - +SyntaxTester.title = JSyntaxPane Tester +SyntaxTester.lblCaretPos.text = Caret Position +SyntaxTester.lblToken.text = Token under cursor +SyntaxTester.jEdtTest.contentType = +NO_TOKEN_AT_CURSOR = NO Token at cursor + +HTMLPreviewFrame.title = HTML Preview +HTMLPreviewFrame.jEdtHtml.contentType = text/html +QuickFindDialog.jChkWrap.text = Wrap +QuickFindDialog.jChkRegExp.text = Reg Exp +QuickFindDialog.jChkIgnoreCase.text = Ignore Case +QuickFindDialog.jLabel1.text = Quick Find +QuickFindDialog.NotFound = not found +ReplaceDialog.jChkRegex.text = Regular Expression +ReplaceDialog.jChkIgnoreCase.text = Ignore Case +ReplaceDialog.jLblReplace.text = Replace +ReplaceDialog.jTglHighlight.text = Highlight +ReplaceDialog.jBtnReplaceAll.text = Replace All +ReplaceDialog.jBtnPrev.text = Previous +ReplaceDialog.jChkWrap.toolTipText = Wrap to beginning when end is reached +ReplaceDialog.jChkWrap.text = Wrap around +ReplaceDialog.title = Find and Replace +ReplaceDialog.jBtnNext.text = Next +ReplaceDialog.jLblFind.text = Find +ReplaceDialog.jBtnReplace.text = Replace +ShowAbbsDialog.title = Abbreviations +GotoLineDialog.title = Goto Line +GotoLineDialog.jBtnOk.text = Go + +DocumentSearchData.SearchStringNotFound = Search String {0} not found +DocumentSearchData.Find = Find +ScriptAction.NoScriptConfigured = Action does not have script function configured +ScriptAction.ErrorInScript = Error in Script +ScriptAction.NoScriptFoundIn = No script is found in: +ScriptRunnerAction.ErrorExecutingScript = Error executing script:\\n +ScriptRunnerAction.ScriptError = Script Error +ScriptRunnerAction.ScriptEngineNotFound = Script Engine for [{0}] not found. Disable this Action? +ShowAbbsAction.NoAbbsForType = No Abbreviations exist for this content type + diff --git a/libsrc/jsyntaxpane/nbactions.xml b/libsrc/jsyntaxpane/nbactions.xml index a842b1e66..8e66559d9 100644 --- a/libsrc/jsyntaxpane/nbactions.xml +++ b/libsrc/jsyntaxpane/nbactions.xml @@ -1,32 +1,32 @@ - - - - run - - jar - - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.1:exec - - - -classpath %classpath jsyntaxpane.SyntaxTester - java - - - - debug - - jar - - - process-classes - org.codehaus.mojo:exec-maven-plugin:1.1:exec - - - -Xdebug -Djava.compiler=none -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath jsyntaxpane.SyntaxTester - true - java - - - + + + + run + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1:exec + + + -classpath %classpath jsyntaxpane.SyntaxTester + java + + + + debug + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1:exec + + + -Xdebug -Djava.compiler=none -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath jsyntaxpane.SyntaxTester + true + java + + + diff --git a/libsrc/nellymoser/build.xml b/libsrc/nellymoser/build.xml index f6b35ff31..ff771a57c 100644 --- a/libsrc/nellymoser/build.xml +++ b/libsrc/nellymoser/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project nellymoser. - - - + + + + + + + + + + + Builds, tests, and runs the project nellymoser. + + + diff --git a/libsrc/nellymoser/nbproject/build-impl.xml b/libsrc/nellymoser/nbproject/build-impl.xml index 0039b3234..75107a8b2 100644 --- a/libsrc/nellymoser/nbproject/build-impl.xml +++ b/libsrc/nellymoser/nbproject/build-impl.xml @@ -1,1413 +1,1413 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.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/nellymoser/nbproject/genfiles.properties b/libsrc/nellymoser/nbproject/genfiles.properties index c93a9a0f1..e8968fd72 100644 --- a/libsrc/nellymoser/nbproject/genfiles.properties +++ b/libsrc/nellymoser/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=413e5dbf -build.xml.script.CRC32=02c6606f -build.xml.stylesheet.CRC32=8064a381@1.68.1.46 -# 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=413e5dbf -nbproject/build-impl.xml.script.CRC32=36480124 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 +build.xml.data.CRC32=413e5dbf +build.xml.script.CRC32=02c6606f +build.xml.stylesheet.CRC32=8064a381@1.68.1.46 +# 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=413e5dbf +nbproject/build-impl.xml.script.CRC32=36480124 +nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48 diff --git a/libsrc/nellymoser/nbproject/project.properties b/libsrc/nellymoser/nbproject/project.properties index 7692c7845..30f72302e 100644 --- a/libsrc/nellymoser/nbproject/project.properties +++ b/libsrc/nellymoser/nbproject/project.properties @@ -1,71 +1,71 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -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 -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# Files in build.classes.dir which should be excluded from distribution jar -dist.archive.excludes= -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=../../lib/nellymoser.jar -dist.javadoc.dir=${dist.dir}/javadoc -excludes= -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.7 -javac.target=1.7 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -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= -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=true -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. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processor.options= +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +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 +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=../../lib/nellymoser.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +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.7 +javac.target=1.7 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +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= +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=true +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. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/libsrc/nellymoser/nbproject/project.xml b/libsrc/nellymoser/nbproject/project.xml index a9e9de8d2..75569803b 100644 --- a/libsrc/nellymoser/nbproject/project.xml +++ b/libsrc/nellymoser/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - nellymoser - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + nellymoser + + + + + + + + + diff --git a/libsrc/ttf/build.xml b/libsrc/ttf/build.xml index 8bc41cf96..997f0d32f 100644 --- a/libsrc/ttf/build.xml +++ b/libsrc/ttf/build.xml @@ -1,73 +1,73 @@ - - - - - - - - - - - Builds, tests, and runs the project ttf. - - - + + + + + + + + + + + Builds, tests, and runs the project ttf. + + + diff --git a/libsrc/ttf/manifest.mf b/libsrc/ttf/manifest.mf index 1574df4a2..328e8e5bc 100644 --- a/libsrc/ttf/manifest.mf +++ b/libsrc/ttf/manifest.mf @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/libsrc/ttf/nbproject/project.xml b/libsrc/ttf/nbproject/project.xml index bce7aa78c..e14ad6ea3 100644 --- a/libsrc/ttf/nbproject/project.xml +++ b/libsrc/ttf/nbproject/project.xml @@ -1,15 +1,15 @@ - - - org.netbeans.modules.java.j2seproject - - - ttf - - - - - - - - - + + + org.netbeans.modules.java.j2seproject + + + ttf + + + + + + + + + diff --git a/manifest.mf b/manifest.mf index 1574df4a2..328e8e5bc 100644 --- a/manifest.mf +++ b/manifest.mf @@ -1,3 +1,3 @@ -Manifest-Version: 1.0 -X-COMMENT: Main-Class will be added automatically by build - +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/nbbuild.xml b/nbbuild.xml index 8c5c8b9df..eea0e66fc 100644 --- a/nbbuild.xml +++ b/nbbuild.xml @@ -1,74 +1,74 @@ - - - - - - - - - - - Builds, tests, and runs the project ASDec. - - - + + + + + + + + + + + Builds, tests, and runs the project ASDec. + + + diff --git a/nbproject/ide-targets.xml b/nbproject/ide-targets.xml index 6ef055fbd..ab8db7552 100644 --- a/nbproject/ide-targets.xml +++ b/nbproject/ide-targets.xml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java b/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java index 13e065347..d639549cc 100644 --- a/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java @@ -1,631 +1,631 @@ -/* - * Copyright (C) 2010-2016 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.configuration.Configuration; -import com.jpexs.decompiler.flash.configuration.ConfigurationCategory; -import com.jpexs.decompiler.flash.configuration.ConfigurationDirectory; -import com.jpexs.decompiler.flash.configuration.ConfigurationFile; -import com.jpexs.decompiler.flash.configuration.ConfigurationInternal; -import com.jpexs.decompiler.flash.configuration.ConfigurationItem; -import com.jpexs.decompiler.flash.gui.helpers.SpringUtilities; -import com.jpexs.helpers.Helper; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.ResourceBundle; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; -import javax.swing.SpringLayout; -import javax.swing.WindowConstants; -import javax.swing.filechooser.FileFilter; -import javax.swing.table.DefaultTableModel; -import org.pushingpixels.substance.api.ColorSchemeAssociationKind; -import org.pushingpixels.substance.api.ComponentState; -import org.pushingpixels.substance.api.DecorationAreaType; -import org.pushingpixels.substance.api.SubstanceLookAndFeel; -import org.pushingpixels.substance.api.SubstanceSkin; -import org.pushingpixels.substance.api.renderers.SubstanceDefaultListCellRenderer; -import org.pushingpixels.substance.api.skin.SkinInfo; - -/** - * - * @author JPEXS - */ -public class AdvancedSettingsDialog extends AppDialog { - - private final Map componentsMap = new HashMap<>(); - - private JButton cancelButton; - - private JButton okButton; - - private JButton resetButton; - - /** - * Creates new form AdvancedSettingsDialog - * - * @param selectedCategory - */ - public AdvancedSettingsDialog(String selectedCategory) { - initComponents(selectedCategory); - View.centerScreen(this); - View.setWindowIcon(this); - - //configurationTable.setCellEditor(configurationTable.getDefaultEditor(null)); - pack(); - } - - private DefaultTableModel getModel() { - return new DefaultTableModel( - new Object[][]{}, - new String[]{ - translate("advancedSettings.columns.name"), - translate("advancedSettings.columns.value"), - translate("advancedSettings.columns.description") - } - ) { - Class[] types = new Class[]{ - String.class, Object.class, String.class - }; - - boolean[] canEdit = new boolean[]{ - false, true, false - }; - - @Override - public Class getColumnClass(int columnIndex) { - return types[columnIndex]; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return canEdit[columnIndex]; - } - }; - } - - private static class SkinSelect { - - private final String name; - - private final String className; - - public SkinSelect(String name, String className) { - this.name = name; - this.className = className; - } - - public String getClassName() { - return className; - } - - @Override - public String toString() { - return name; - } - } - - private void initComponents(String selectedCategory) { - okButton = new JButton(); - cancelButton = new JButton(); - resetButton = new JButton(); - - setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - setTitle(translate("advancedSettings.dialog.title")); - setModal(true); - setPreferredSize(new Dimension(800, 500)); - - okButton.setText(AppStrings.translate("button.ok")); - okButton.addActionListener(this::okButtonActionPerformed); - - cancelButton.setText(AppStrings.translate("button.cancel")); - cancelButton.addActionListener(this::cancelButtonActionPerformed); - - resetButton.setText(AppStrings.translate("button.reset")); - resetButton.addActionListener(this::resetButtonActionPerformed); - - Container cnt = getContentPane(); - cnt.setLayout(new BorderLayout()); - //cnt.add(new JScrollPane(configurationTable),BorderLayout.CENTER); - - JPanel buttonsPanel = new JPanel(new BorderLayout()); - - JPanel buttonsLeftPanel = new JPanel(new FlowLayout()); - buttonsLeftPanel.add(resetButton, BorderLayout.WEST); - - buttonsPanel.add(buttonsLeftPanel, BorderLayout.WEST); - - JPanel buttonsRightPanel = new JPanel(new FlowLayout()); - buttonsRightPanel.add(cancelButton); - buttonsRightPanel.add(okButton); - buttonsPanel.add(buttonsRightPanel, BorderLayout.EAST); - - cnt.add(buttonsPanel, BorderLayout.SOUTH); - - JTabbedPane tabPane = new JTabbedPane(); - - JComboBox skinComboBox = new JComboBox<>(); - skinComboBox.setRenderer(new SubstanceDefaultListCellRenderer() { - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - SubstanceDefaultListCellRenderer cmp = (SubstanceDefaultListCellRenderer) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); //To change body of generated methods, choose Tools | Templates. - final SkinSelect ss = (SkinSelect) value; - cmp.setIcon(new Icon() { - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - Graphics2D g2 = (Graphics2D) g; - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - try { - Class act = Class.forName(ss.getClassName()); - SubstanceSkin skin = (SubstanceSkin) act.newInstance(); - Color fill = skin.getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.FILL, ComponentState.ENABLED).getBackgroundFillColor(); - Color hilight = skin.getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.FILL, ComponentState.ROLLOVER_SELECTED).getBackgroundFillColor(); - Color border = skin.getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.BORDER, ComponentState.ENABLED).getDarkColor(); - g2.setColor(fill); - g2.fillOval(0, 0, 16, 16); - g2.setColor(hilight); - g2.fillArc(0, 0, 16, 16, -45, 90); - g2.setColor(border); - g2.drawOval(0, 0, 16, 16); - - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) { - //no icon - } - - } - - @Override - public int getIconWidth() { - return 16; - } - - @Override - public int getIconHeight() { - return 16; - } - }); - return cmp; - } - - }); - skinComboBox.addItem(new SkinSelect(OceanicSkin.NAME, OceanicSkin.class.getName())); - Map skins = SubstanceLookAndFeel.getAllSkins(); - for (String skinKey : skins.keySet()) { - SkinInfo skin = skins.get(skinKey); - skinComboBox.addItem(new SkinSelect(skin.getDisplayName(), skin.getClassName())); - if (skin.getClassName().equals(Configuration.guiSkin.get())) { - skinComboBox.setSelectedIndex(skinComboBox.getItemCount() - 1); - } - } - - Map tabs = new HashMap<>(); - getCategories(componentsMap, tabs, skinComboBox, getResourceBundle()); - - String catOrder[] = new String[]{"ui", "display", "decompilation", "script", "format", "export", "import", "paths", "limit", "update", "debug", "other"}; - - for (String cat : catOrder) { - if (!tabs.containsKey(cat)) { - continue; - } - - tabPane.add(translate("config.group.name." + cat), tabs.get(cat)); - tabPane.setToolTipTextAt(tabPane.getTabCount() - 1, translate("config.group.description." + cat)); - } - if (selectedCategory != null && tabs.containsKey(selectedCategory)) { - tabPane.setSelectedComponent(tabs.get(selectedCategory)); - } - - cnt.add(tabPane, BorderLayout.CENTER); - pack(); - } - - public static String selectConfigFile(ConfigurationItem config, String current, String pattern) { - JFileChooser fc = new JFileChooser(); - fc.setSelectedFile(new File(current)); - fc.setMultiSelectionEnabled(false); - fc.setCurrentDirectory(new File((String) config.get())); - FileFilter allSupportedFilter = new FileFilter() { - private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip"}; - - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - return f.getName().matches(pattern); - } - - @Override - public String getDescription() { - return ""; - } - }; - fc.setFileFilter(allSupportedFilter); - - fc.setAcceptAllFileFilterUsed(false); - JFrame f = new JFrame(); - View.setWindowIcon(f); - int returnVal = fc.showOpenDialog(f); - if (returnVal == JFileChooser.APPROVE_OPTION) { - return Helper.fixDialogFile(fc.getSelectedFile()).getAbsolutePath(); - } else { - return (String) config.get(); - } - } - - public static void getCategories(Map componentsMap, Map tabs, JComboBox skinComboBox, ResourceBundle resourceBundle) { - Map> categorized = new HashMap<>(); - - Map fields = Configuration.getConfigurationFields(); - String[] keys = new String[fields.size()]; - keys = fields.keySet().toArray(keys); - Arrays.sort(keys); - - for (String name : keys) { - Field field = fields.get(name); - ConfigurationCategory cat = field.getAnnotation(ConfigurationCategory.class); - String scat = (cat == null || cat.value().isEmpty()) ? "other" : cat.value(); - if (!categorized.containsKey(scat)) { - categorized.put(scat, new HashMap<>()); - } - - categorized.get(scat).put(name, field); - } - - for (String cat : categorized.keySet()) { - JPanel configPanel = new JPanel(new SpringLayout()); - int itemCount = 0; - List names = new ArrayList<>(categorized.get(cat).keySet()); - - final Map locNames = new HashMap<>(); - for (String name : names) { - String locName; - - if (resourceBundle.containsKey("config.name." + name)) { - locName = resourceBundle.getString("config.name." + name); - } else { //if it is undocumented, then it must have ConfigurationInternal annotation - Field f = fields.get(name); - ConfigurationInternal cint = f.getAnnotation(ConfigurationInternal.class); - if (cint == null) { - throw new RuntimeException("Missing configuration name: " + name); - } - - locName = "(Internal) " + name; - } - - locNames.put(name, locName); - } - - Collections.sort(names, new Comparator() { - @Override - public int compare(String name1, String name2) { - return locNames.get(name1).compareTo(locNames.get(name2)); - } - }); - for (String name : names) { - Field field = categorized.get(cat).get(name); - - String locName = locNames.get(name); - - try { - ConfigurationItem item = (ConfigurationItem) field.get(null); - - ParameterizedType listType = (ParameterizedType) field.getGenericType(); - java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0]; - if (!(itemType2 instanceof Class)) { - continue; - } - - Class itemType = (Class) itemType2; - - String description = ""; - if (resourceBundle.containsKey("config.description." + name)) { - description = resourceBundle.getString("config.description." + name); - } - - Object defaultValue = Configuration.getDefaultValue(field); - if (name.equals("gui.skin")) { - Class c; - try { - c = Class.forName((String) defaultValue); - defaultValue = c.getField("NAME").get(c); - } catch (ClassNotFoundException | NoSuchFieldException | SecurityException ex) { - Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex); - } - } - - if (defaultValue != null) { - description += " (" + resourceBundle.getString("default") + ": " + defaultValue + ")"; - } - - JLabel l = new JLabel(locName, JLabel.TRAILING); - l.setToolTipText(description); - configPanel.add(l); - Component c = null; - Component addComponent = null; - if (name.equals("gui.skin")) { - skinComboBox.setToolTipText(description); - skinComboBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, skinComboBox.getPreferredSize().height)); - c = skinComboBox; - } else if ((itemType == String.class) || (itemType == Integer.class) || (itemType == Long.class) || (itemType == Double.class) || (itemType == Float.class) || (itemType == Calendar.class)) { - ConfigurationFile confFile = field.getAnnotation(ConfigurationFile.class); - ConfigurationDirectory confDirectory = field.getAnnotation(ConfigurationDirectory.class); - - JTextField tf = new JTextField(); - Object val = item.get(); - if (val == null) { - val = ""; - } - if (itemType == Calendar.class) { - tf.setText(new SimpleDateFormat().format(((Calendar) val).getTime())); - } else { - tf.setText(val.toString()); - } - tf.setToolTipText(description); - tf.setMaximumSize(new Dimension(Integer.MAX_VALUE, tf.getPreferredSize().height)); - - c = tf; - if (confFile != null) { //|| confDirectory != null) { - JPanel p = new JPanel(new BorderLayout()); - p.setMaximumSize(new Dimension(Integer.MAX_VALUE, tf.getPreferredSize().height)); - p.add(tf, BorderLayout.CENTER); - JButton butSelect = new JButton(View.getIcon("folderopen16")); - butSelect.setToolTipText(ResourceBundle.getBundle(AppStrings.getResourcePath(MainFrame.class)).getString("FileChooser.openButtonText")); - butSelect.setMargin(new Insets(2, 2, 2, 2)); - butSelect.addActionListener((ActionEvent e) -> { - tf.setText(selectConfigFile(item, tf.getText(), confFile.value())); - }); - p.add(butSelect, BorderLayout.EAST); - addComponent = p; - } - } else if (itemType == Boolean.class) { - JCheckBox cb = new JCheckBox(); - cb.setSelected((Boolean) item.get()); - cb.setToolTipText(description); - c = cb; - } else if (itemType.isEnum()) { - JComboBox cb = new JComboBox<>(); - @SuppressWarnings("unchecked") - EnumSet enumValues = EnumSet.allOf(itemType); - String stringValue = null; - for (Object enumValue : enumValues) { - String enumValueStr = enumValue.toString(); - if (stringValue == null) { - stringValue = enumValueStr; - } - cb.addItem(enumValueStr); - } - if (item.get() != null) { - stringValue = item.get().toString(); - } - cb.setToolTipText(description); - cb.setSelectedItem(stringValue); - cb.setMaximumSize(new Dimension(Integer.MAX_VALUE, cb.getPreferredSize().height)); - c = cb; - } else { - throw new UnsupportedOperationException("Configuration ttem type '" + itemType.getName() + "' is not supported"); - } - - componentsMap.put(name, c); - if (addComponent == null) { - addComponent = c; - } - l.setLabelFor(c); - configPanel.add(addComponent); - } catch (IllegalArgumentException | IllegalAccessException ex) { - // Reflection exceptions. This should never happen - throw new Error(ex.getMessage()); - } - - itemCount++; - } - - SpringUtilities.makeCompactGrid(configPanel, - itemCount, 2, //rows, cols - 6, 6, //initX, initY - 6, 6); //xPad, yPad - //https://www.adobe.com/support/flashplayer/debug_downloads.html - if (resourceBundle.containsKey("config.group.tip." + cat)) { - String tip = resourceBundle.getString("config.group.tip." + cat); - String url = null; - if (resourceBundle.containsKey("config.group.link." + cat)) { - url = resourceBundle.getString("config.group.link." + cat); - } - JPanel p = new JPanel(new BorderLayout()); - p.add(configPanel, BorderLayout.CENTER); - JPanel tipPanel = new JPanel(new FlowLayout()); - tipPanel.add(new JLabel("" + resourceBundle.getString("tip") + "" + tip + "")); - if (url != null) { - String linkText = url; - if (resourceBundle.containsKey("config.group.linkText." + cat)) { - linkText = resourceBundle.getString("config.group.linkText." + cat); - } - tipPanel.add(new LinkLabel(linkText, url)); - } - p.add(tipPanel, BorderLayout.SOUTH); - configPanel = p; - } - tabs.put(cat, new JScrollPane(configPanel)); - } - } - - private void showRestartConfirmDialod() { - if (View.showConfirmDialog(this, translate("advancedSettings.restartConfirmation"), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { - View.execInEventDispatchLater(() -> { - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex); - } - SelectLanguageDialog.reloadUi(); - }); - - } - } - - @SuppressWarnings("unchecked") - private void okButtonActionPerformed(ActionEvent evt) { - boolean modified = false; - Map fields = Configuration.getConfigurationFields(); - Map values = new HashMap<>(); - for (String name : fields.keySet()) { - Component c = componentsMap.get(name); - Object value = null; - - ParameterizedType listType = (ParameterizedType) fields.get(name).getGenericType(); - java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0]; - if (!(itemType2 instanceof Class)) { - continue; - } - - Class itemType = (Class) itemType2; - if (name.equals("gui.skin")) { - value = ((SkinSelect) ((JComboBox) c).getSelectedItem()).className; - } else if (itemType == String.class) { - value = ((JTextField) c).getText(); - } - if (itemType == Boolean.class) { - value = ((JCheckBox) c).isSelected(); - } - - if (itemType == Calendar.class) { - Calendar cal = Calendar.getInstance(); - try { - cal.setTime(new SimpleDateFormat().parse(((JTextField) c).getText())); - } catch (ParseException ex) { - c.requestFocusInWindow(); - return; - } - value = cal; - } - - if (itemType.isEnum()) { - String stringValue = (String) ((JComboBox) c).getSelectedItem(); - value = Enum.valueOf(itemType, stringValue); - } - - try { - if (itemType == Integer.class) { - value = Integer.parseInt(((JTextField) c).getText()); - } - if (itemType == Long.class) { - value = Long.parseLong(((JTextField) c).getText()); - } - if (itemType == Double.class) { - value = Double.parseDouble(((JTextField) c).getText()); - } - if (itemType == Float.class) { - value = Float.parseFloat(((JTextField) c).getText()); - } - } catch (NumberFormatException nfe) { - if (!((JTextField) c).getText().isEmpty()) { - c.requestFocusInWindow(); - return; - } // else null - } - values.put(name, value); - } - - for (String name : fields.keySet()) { - Component c = componentsMap.get(name); - Object value = values.get(name); - - Field field = fields.get(name); - ConfigurationItem item = null; - try { - item = (ConfigurationItem) field.get(null); - } catch (IllegalArgumentException | IllegalAccessException ex) { - // Reflection exceptions. This should never happen - throw new Error(ex.getMessage()); - } - if (item.get() == null || !item.get().equals(value)) { - if (item.hasValue() || value != null) { - item.set(value); - modified = true; - } - } - } - Configuration.saveConfig(); - setVisible(false); - if (modified) { - showRestartConfirmDialod(); - } - } - - private void cancelButtonActionPerformed(ActionEvent evt) { - setVisible(false); - } - - private void resetButtonActionPerformed(ActionEvent evt) { - Map rfields = Configuration.getConfigurationFields(); - for (Entry entry : rfields.entrySet()) { - String name = entry.getKey(); - Field field = entry.getValue(); - try { - ConfigurationItem item = (ConfigurationItem) field.get(null); - item.unset(); - } catch (IllegalArgumentException | IllegalAccessException ex) { - // Reflection exceptions. This should never happen - throw new Error(ex.getMessage()); - } - } - Configuration.saveConfig(); - setVisible(false); - showRestartConfirmDialod(); - } -} +/* + * Copyright (C) 2010-2016 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.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.ConfigurationCategory; +import com.jpexs.decompiler.flash.configuration.ConfigurationDirectory; +import com.jpexs.decompiler.flash.configuration.ConfigurationFile; +import com.jpexs.decompiler.flash.configuration.ConfigurationInternal; +import com.jpexs.decompiler.flash.configuration.ConfigurationItem; +import com.jpexs.decompiler.flash.gui.helpers.SpringUtilities; +import com.jpexs.helpers.Helper; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.WindowConstants; +import javax.swing.filechooser.FileFilter; +import javax.swing.table.DefaultTableModel; +import org.pushingpixels.substance.api.ColorSchemeAssociationKind; +import org.pushingpixels.substance.api.ComponentState; +import org.pushingpixels.substance.api.DecorationAreaType; +import org.pushingpixels.substance.api.SubstanceLookAndFeel; +import org.pushingpixels.substance.api.SubstanceSkin; +import org.pushingpixels.substance.api.renderers.SubstanceDefaultListCellRenderer; +import org.pushingpixels.substance.api.skin.SkinInfo; + +/** + * + * @author JPEXS + */ +public class AdvancedSettingsDialog extends AppDialog { + + private final Map componentsMap = new HashMap<>(); + + private JButton cancelButton; + + private JButton okButton; + + private JButton resetButton; + + /** + * Creates new form AdvancedSettingsDialog + * + * @param selectedCategory + */ + public AdvancedSettingsDialog(String selectedCategory) { + initComponents(selectedCategory); + View.centerScreen(this); + View.setWindowIcon(this); + + //configurationTable.setCellEditor(configurationTable.getDefaultEditor(null)); + pack(); + } + + private DefaultTableModel getModel() { + return new DefaultTableModel( + new Object[][]{}, + new String[]{ + translate("advancedSettings.columns.name"), + translate("advancedSettings.columns.value"), + translate("advancedSettings.columns.description") + } + ) { + Class[] types = new Class[]{ + String.class, Object.class, String.class + }; + + boolean[] canEdit = new boolean[]{ + false, true, false + }; + + @Override + public Class getColumnClass(int columnIndex) { + return types[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit[columnIndex]; + } + }; + } + + private static class SkinSelect { + + private final String name; + + private final String className; + + public SkinSelect(String name, String className) { + this.name = name; + this.className = className; + } + + public String getClassName() { + return className; + } + + @Override + public String toString() { + return name; + } + } + + private void initComponents(String selectedCategory) { + okButton = new JButton(); + cancelButton = new JButton(); + resetButton = new JButton(); + + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setTitle(translate("advancedSettings.dialog.title")); + setModal(true); + setPreferredSize(new Dimension(800, 500)); + + okButton.setText(AppStrings.translate("button.ok")); + okButton.addActionListener(this::okButtonActionPerformed); + + cancelButton.setText(AppStrings.translate("button.cancel")); + cancelButton.addActionListener(this::cancelButtonActionPerformed); + + resetButton.setText(AppStrings.translate("button.reset")); + resetButton.addActionListener(this::resetButtonActionPerformed); + + Container cnt = getContentPane(); + cnt.setLayout(new BorderLayout()); + //cnt.add(new JScrollPane(configurationTable),BorderLayout.CENTER); + + JPanel buttonsPanel = new JPanel(new BorderLayout()); + + JPanel buttonsLeftPanel = new JPanel(new FlowLayout()); + buttonsLeftPanel.add(resetButton, BorderLayout.WEST); + + buttonsPanel.add(buttonsLeftPanel, BorderLayout.WEST); + + JPanel buttonsRightPanel = new JPanel(new FlowLayout()); + buttonsRightPanel.add(cancelButton); + buttonsRightPanel.add(okButton); + buttonsPanel.add(buttonsRightPanel, BorderLayout.EAST); + + cnt.add(buttonsPanel, BorderLayout.SOUTH); + + JTabbedPane tabPane = new JTabbedPane(); + + JComboBox skinComboBox = new JComboBox<>(); + skinComboBox.setRenderer(new SubstanceDefaultListCellRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + SubstanceDefaultListCellRenderer cmp = (SubstanceDefaultListCellRenderer) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); //To change body of generated methods, choose Tools | Templates. + final SkinSelect ss = (SkinSelect) value; + cmp.setIcon(new Icon() { + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + try { + Class act = Class.forName(ss.getClassName()); + SubstanceSkin skin = (SubstanceSkin) act.newInstance(); + Color fill = skin.getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.FILL, ComponentState.ENABLED).getBackgroundFillColor(); + Color hilight = skin.getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.FILL, ComponentState.ROLLOVER_SELECTED).getBackgroundFillColor(); + Color border = skin.getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.BORDER, ComponentState.ENABLED).getDarkColor(); + g2.setColor(fill); + g2.fillOval(0, 0, 16, 16); + g2.setColor(hilight); + g2.fillArc(0, 0, 16, 16, -45, 90); + g2.setColor(border); + g2.drawOval(0, 0, 16, 16); + + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) { + //no icon + } + + } + + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + }); + return cmp; + } + + }); + skinComboBox.addItem(new SkinSelect(OceanicSkin.NAME, OceanicSkin.class.getName())); + Map skins = SubstanceLookAndFeel.getAllSkins(); + for (String skinKey : skins.keySet()) { + SkinInfo skin = skins.get(skinKey); + skinComboBox.addItem(new SkinSelect(skin.getDisplayName(), skin.getClassName())); + if (skin.getClassName().equals(Configuration.guiSkin.get())) { + skinComboBox.setSelectedIndex(skinComboBox.getItemCount() - 1); + } + } + + Map tabs = new HashMap<>(); + getCategories(componentsMap, tabs, skinComboBox, getResourceBundle()); + + String catOrder[] = new String[]{"ui", "display", "decompilation", "script", "format", "export", "import", "paths", "limit", "update", "debug", "other"}; + + for (String cat : catOrder) { + if (!tabs.containsKey(cat)) { + continue; + } + + tabPane.add(translate("config.group.name." + cat), tabs.get(cat)); + tabPane.setToolTipTextAt(tabPane.getTabCount() - 1, translate("config.group.description." + cat)); + } + if (selectedCategory != null && tabs.containsKey(selectedCategory)) { + tabPane.setSelectedComponent(tabs.get(selectedCategory)); + } + + cnt.add(tabPane, BorderLayout.CENTER); + pack(); + } + + public static String selectConfigFile(ConfigurationItem config, String current, String pattern) { + JFileChooser fc = new JFileChooser(); + fc.setSelectedFile(new File(current)); + fc.setMultiSelectionEnabled(false); + fc.setCurrentDirectory(new File((String) config.get())); + FileFilter allSupportedFilter = new FileFilter() { + private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip"}; + + @Override + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + return f.getName().matches(pattern); + } + + @Override + public String getDescription() { + return ""; + } + }; + fc.setFileFilter(allSupportedFilter); + + fc.setAcceptAllFileFilterUsed(false); + JFrame f = new JFrame(); + View.setWindowIcon(f); + int returnVal = fc.showOpenDialog(f); + if (returnVal == JFileChooser.APPROVE_OPTION) { + return Helper.fixDialogFile(fc.getSelectedFile()).getAbsolutePath(); + } else { + return (String) config.get(); + } + } + + public static void getCategories(Map componentsMap, Map tabs, JComboBox skinComboBox, ResourceBundle resourceBundle) { + Map> categorized = new HashMap<>(); + + Map fields = Configuration.getConfigurationFields(); + String[] keys = new String[fields.size()]; + keys = fields.keySet().toArray(keys); + Arrays.sort(keys); + + for (String name : keys) { + Field field = fields.get(name); + ConfigurationCategory cat = field.getAnnotation(ConfigurationCategory.class); + String scat = (cat == null || cat.value().isEmpty()) ? "other" : cat.value(); + if (!categorized.containsKey(scat)) { + categorized.put(scat, new HashMap<>()); + } + + categorized.get(scat).put(name, field); + } + + for (String cat : categorized.keySet()) { + JPanel configPanel = new JPanel(new SpringLayout()); + int itemCount = 0; + List names = new ArrayList<>(categorized.get(cat).keySet()); + + final Map locNames = new HashMap<>(); + for (String name : names) { + String locName; + + if (resourceBundle.containsKey("config.name." + name)) { + locName = resourceBundle.getString("config.name." + name); + } else { //if it is undocumented, then it must have ConfigurationInternal annotation + Field f = fields.get(name); + ConfigurationInternal cint = f.getAnnotation(ConfigurationInternal.class); + if (cint == null) { + throw new RuntimeException("Missing configuration name: " + name); + } + + locName = "(Internal) " + name; + } + + locNames.put(name, locName); + } + + Collections.sort(names, new Comparator() { + @Override + public int compare(String name1, String name2) { + return locNames.get(name1).compareTo(locNames.get(name2)); + } + }); + for (String name : names) { + Field field = categorized.get(cat).get(name); + + String locName = locNames.get(name); + + try { + ConfigurationItem item = (ConfigurationItem) field.get(null); + + ParameterizedType listType = (ParameterizedType) field.getGenericType(); + java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0]; + if (!(itemType2 instanceof Class)) { + continue; + } + + Class itemType = (Class) itemType2; + + String description = ""; + if (resourceBundle.containsKey("config.description." + name)) { + description = resourceBundle.getString("config.description." + name); + } + + Object defaultValue = Configuration.getDefaultValue(field); + if (name.equals("gui.skin")) { + Class c; + try { + c = Class.forName((String) defaultValue); + defaultValue = c.getField("NAME").get(c); + } catch (ClassNotFoundException | NoSuchFieldException | SecurityException ex) { + Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex); + } + } + + if (defaultValue != null) { + description += " (" + resourceBundle.getString("default") + ": " + defaultValue + ")"; + } + + JLabel l = new JLabel(locName, JLabel.TRAILING); + l.setToolTipText(description); + configPanel.add(l); + Component c = null; + Component addComponent = null; + if (name.equals("gui.skin")) { + skinComboBox.setToolTipText(description); + skinComboBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, skinComboBox.getPreferredSize().height)); + c = skinComboBox; + } else if ((itemType == String.class) || (itemType == Integer.class) || (itemType == Long.class) || (itemType == Double.class) || (itemType == Float.class) || (itemType == Calendar.class)) { + ConfigurationFile confFile = field.getAnnotation(ConfigurationFile.class); + ConfigurationDirectory confDirectory = field.getAnnotation(ConfigurationDirectory.class); + + JTextField tf = new JTextField(); + Object val = item.get(); + if (val == null) { + val = ""; + } + if (itemType == Calendar.class) { + tf.setText(new SimpleDateFormat().format(((Calendar) val).getTime())); + } else { + tf.setText(val.toString()); + } + tf.setToolTipText(description); + tf.setMaximumSize(new Dimension(Integer.MAX_VALUE, tf.getPreferredSize().height)); + + c = tf; + if (confFile != null) { //|| confDirectory != null) { + JPanel p = new JPanel(new BorderLayout()); + p.setMaximumSize(new Dimension(Integer.MAX_VALUE, tf.getPreferredSize().height)); + p.add(tf, BorderLayout.CENTER); + JButton butSelect = new JButton(View.getIcon("folderopen16")); + butSelect.setToolTipText(ResourceBundle.getBundle(AppStrings.getResourcePath(MainFrame.class)).getString("FileChooser.openButtonText")); + butSelect.setMargin(new Insets(2, 2, 2, 2)); + butSelect.addActionListener((ActionEvent e) -> { + tf.setText(selectConfigFile(item, tf.getText(), confFile.value())); + }); + p.add(butSelect, BorderLayout.EAST); + addComponent = p; + } + } else if (itemType == Boolean.class) { + JCheckBox cb = new JCheckBox(); + cb.setSelected((Boolean) item.get()); + cb.setToolTipText(description); + c = cb; + } else if (itemType.isEnum()) { + JComboBox cb = new JComboBox<>(); + @SuppressWarnings("unchecked") + EnumSet enumValues = EnumSet.allOf(itemType); + String stringValue = null; + for (Object enumValue : enumValues) { + String enumValueStr = enumValue.toString(); + if (stringValue == null) { + stringValue = enumValueStr; + } + cb.addItem(enumValueStr); + } + if (item.get() != null) { + stringValue = item.get().toString(); + } + cb.setToolTipText(description); + cb.setSelectedItem(stringValue); + cb.setMaximumSize(new Dimension(Integer.MAX_VALUE, cb.getPreferredSize().height)); + c = cb; + } else { + throw new UnsupportedOperationException("Configuration ttem type '" + itemType.getName() + "' is not supported"); + } + + componentsMap.put(name, c); + if (addComponent == null) { + addComponent = c; + } + l.setLabelFor(c); + configPanel.add(addComponent); + } catch (IllegalArgumentException | IllegalAccessException ex) { + // Reflection exceptions. This should never happen + throw new Error(ex.getMessage()); + } + + itemCount++; + } + + SpringUtilities.makeCompactGrid(configPanel, + itemCount, 2, //rows, cols + 6, 6, //initX, initY + 6, 6); //xPad, yPad + //https://www.adobe.com/support/flashplayer/debug_downloads.html + if (resourceBundle.containsKey("config.group.tip." + cat)) { + String tip = resourceBundle.getString("config.group.tip." + cat); + String url = null; + if (resourceBundle.containsKey("config.group.link." + cat)) { + url = resourceBundle.getString("config.group.link." + cat); + } + JPanel p = new JPanel(new BorderLayout()); + p.add(configPanel, BorderLayout.CENTER); + JPanel tipPanel = new JPanel(new FlowLayout()); + tipPanel.add(new JLabel("" + resourceBundle.getString("tip") + "" + tip + "")); + if (url != null) { + String linkText = url; + if (resourceBundle.containsKey("config.group.linkText." + cat)) { + linkText = resourceBundle.getString("config.group.linkText." + cat); + } + tipPanel.add(new LinkLabel(linkText, url)); + } + p.add(tipPanel, BorderLayout.SOUTH); + configPanel = p; + } + tabs.put(cat, new JScrollPane(configPanel)); + } + } + + private void showRestartConfirmDialod() { + if (View.showConfirmDialog(this, translate("advancedSettings.restartConfirmation"), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + View.execInEventDispatchLater(() -> { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex); + } + SelectLanguageDialog.reloadUi(); + }); + + } + } + + @SuppressWarnings("unchecked") + private void okButtonActionPerformed(ActionEvent evt) { + boolean modified = false; + Map fields = Configuration.getConfigurationFields(); + Map values = new HashMap<>(); + for (String name : fields.keySet()) { + Component c = componentsMap.get(name); + Object value = null; + + ParameterizedType listType = (ParameterizedType) fields.get(name).getGenericType(); + java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0]; + if (!(itemType2 instanceof Class)) { + continue; + } + + Class itemType = (Class) itemType2; + if (name.equals("gui.skin")) { + value = ((SkinSelect) ((JComboBox) c).getSelectedItem()).className; + } else if (itemType == String.class) { + value = ((JTextField) c).getText(); + } + if (itemType == Boolean.class) { + value = ((JCheckBox) c).isSelected(); + } + + if (itemType == Calendar.class) { + Calendar cal = Calendar.getInstance(); + try { + cal.setTime(new SimpleDateFormat().parse(((JTextField) c).getText())); + } catch (ParseException ex) { + c.requestFocusInWindow(); + return; + } + value = cal; + } + + if (itemType.isEnum()) { + String stringValue = (String) ((JComboBox) c).getSelectedItem(); + value = Enum.valueOf(itemType, stringValue); + } + + try { + if (itemType == Integer.class) { + value = Integer.parseInt(((JTextField) c).getText()); + } + if (itemType == Long.class) { + value = Long.parseLong(((JTextField) c).getText()); + } + if (itemType == Double.class) { + value = Double.parseDouble(((JTextField) c).getText()); + } + if (itemType == Float.class) { + value = Float.parseFloat(((JTextField) c).getText()); + } + } catch (NumberFormatException nfe) { + if (!((JTextField) c).getText().isEmpty()) { + c.requestFocusInWindow(); + return; + } // else null + } + values.put(name, value); + } + + for (String name : fields.keySet()) { + Component c = componentsMap.get(name); + Object value = values.get(name); + + Field field = fields.get(name); + ConfigurationItem item = null; + try { + item = (ConfigurationItem) field.get(null); + } catch (IllegalArgumentException | IllegalAccessException ex) { + // Reflection exceptions. This should never happen + throw new Error(ex.getMessage()); + } + if (item.get() == null || !item.get().equals(value)) { + if (item.hasValue() || value != null) { + item.set(value); + modified = true; + } + } + } + Configuration.saveConfig(); + setVisible(false); + if (modified) { + showRestartConfirmDialod(); + } + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + setVisible(false); + } + + private void resetButtonActionPerformed(ActionEvent evt) { + Map rfields = Configuration.getConfigurationFields(); + for (Entry entry : rfields.entrySet()) { + String name = entry.getKey(); + Field field = entry.getValue(); + try { + ConfigurationItem item = (ConfigurationItem) field.get(null); + item.unset(); + } catch (IllegalArgumentException | IllegalAccessException ex) { + // Reflection exceptions. This should never happen + throw new Error(ex.getMessage()); + } + } + Configuration.saveConfig(); + setVisible(false); + showRestartConfirmDialod(); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/FontPanel.java b/src/com/jpexs/decompiler/flash/gui/FontPanel.java index c87b36bde..03e762a58 100644 --- a/src/com/jpexs/decompiler/flash/gui/FontPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FontPanel.java @@ -1,719 +1,719 @@ -/* - * Copyright (C) 2010-2016 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.SWF; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.gui.helpers.TableLayoutHelper; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.tags.base.TextTag; -import com.jpexs.decompiler.flash.treeitems.TreeItem; -import com.jpexs.helpers.Helper; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.FontFormatException; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.io.File; -import java.io.IOException; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; -import java.util.TreeSet; -import java.util.Vector; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.BorderFactory; -import javax.swing.ComboBoxModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.ScrollPaneConstants; -import javax.swing.filechooser.FileFilter; -import layout.TableLayout; - -/** - * - * @author JPEXS - */ -public class FontPanel extends JPanel { - - private final MainPanel mainPanel; - - private FontTag fontTag; - - /** - * Creates new form FontPanel - * - * @param mainPanel Main panel - */ - public FontPanel(MainPanel mainPanel) { - this.mainPanel = mainPanel; - initComponents(); - } - - public FontTag getFontTag() { - return fontTag; - } - - public void clear() { - fontTag = null; - } - - public static ComboBoxModel getFamilyModel() { - Set famSet = new TreeSet<>(); - for (Font f : FontTag.installedFontsByName.values()) { - famSet.add(new FontFamily(f)); - } - return new DefaultComboBoxModel<>(new Vector<>(famSet)); - } - - public static ComboBoxModel getFaceModel(FontFamily family) { - - Set faceSet = new TreeSet<>(); - for (Font f : FontTag.installedFontsByFamily.get(family.familyEn).values()) { - faceSet.add(new FontFace(f)); - } - - return new DefaultComboBoxModel<>(new Vector<>(faceSet)); - } - - private void setEditable(boolean editable) { - if (editable) { - buttonEdit.setVisible(false); - buttonSave.setVisible(true); - buttonCancel.setVisible(true); - if (fontTag.isBoldEditable()) { - fontIsBoldCheckBox.setEnabled(true); - } - if (fontTag.isItalicEditable()) { - fontIsItalicCheckBox.setEnabled(true); - } - } else { - buttonEdit.setVisible(true); - buttonSave.setVisible(false); - buttonCancel.setVisible(false); - fontIsBoldCheckBox.setEnabled(false); - fontIsItalicCheckBox.setEnabled(false); - } - } - - private String translate(String key) { - return mainPanel.translate(key); - } - - private void fontAddChars(FontTag ft, Set selChars, Font font) { - FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem(); - String oldchars = f.getCharacters(); - for (int ic : selChars) { - char c = (char) ic; - if (oldchars.indexOf((int) c) == -1) { - font = font.deriveFont(f.getFontStyle(), 1024); - if (!font.canDisplay(c)) { - String msg = translate("error.font.nocharacter").replace("%char%", "" + c); - Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, msg); - View.showMessageDialog(null, msg, translate("error"), JOptionPane.ERROR_MESSAGE); - return; - } - } - } - - String[] yesno = new String[]{translate("button.yes"), translate("button.no"), translate("button.yes.all"), translate("button.no.all")}; - boolean yestoall = false; - boolean notoall = false; - boolean replaced = false; - for (int ic : selChars) { - char c = (char) ic; - if (oldchars.indexOf((int) c) > -1) { - int opt = -1; - if (!(yestoall || notoall)) { - opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes")); - if (opt == 2) { - yestoall = true; - } - if (opt == 3) { - notoall = true; - } - } - - if (yestoall) { - opt = 0; // yes - } else if (notoall) { - opt = 1; // no - } - - if (opt == 1) { - continue; - } - - replaced = true; - } - - f.addCharacter(c, font); - oldchars += c; - } - - if (replaced) { - if (View.showConfirmDialog(null, translate("message.font.replace.updateTexts"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.YES_OPTION) { - int fontId = ft.getFontId(); - SWF swf = ft.getSwf(); - for (Tag tag : swf.getTags()) { - if (tag instanceof TextTag) { - TextTag textTag = (TextTag) tag; - if (textTag.getFontIds().contains(fontId)) { - String text = textTag.getFormattedText(true).text; - mainPanel.saveText(textTag, text, null, null); - } - } - } - } - } - } - - private void fontRemoveChars(FontTag ft, Set selChars) { - FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem(); - - for (int ic : selChars) { - char c = (char) ic; - f.removeCharacter(c); - } - } - - public void showFontTag(FontTag ft) { - SWF swf = ft.getSwf(); - fontTag = ft; - fontNameIntagLabel.setText(ft.getFontNameIntag()); - fontNameTextArea.setText(ft.getFontName()); - fontCopyrightTextArea.setText(ft.getFontCopyright()); - - fontIsBoldCheckBox.setSelected(ft.isBold()); - fontIsItalicCheckBox.setSelected(ft.isItalic()); - fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : Integer.toString(ft.getDescent())); - fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : Integer.toString(ft.getAscent())); - fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : Integer.toString(ft.getLeading())); - String chars = ft.getCharacters(); - fontCharactersTextArea.setText(chars); - fontCharactersScrollPane.getVerticalScrollBar().scrollRectToVisible(new Rectangle(0, 0, 1, 1)); - setAllowSave(false); - - Font selFont = ft.getSystemFont(); - fontFamilyNameSelection.setSelectedItem(new FontFamily(selFont)); - fontFaceSelection.setSelectedItem(new FontFace(selFont)); - - setAllowSave(true); - setEditable(false); - boolean readOnly = ((Tag) ft).isReadOnly(); - if (readOnly) { - addCharsPanel.setVisible(false); - buttonEdit.setVisible(false); - } - } - - private void initComponents() { - - contentScrollPane = new JScrollPane(); - addCharsPanel = new JPanel(); - fontParamsPanel = new JPanel(); - fontNameIntagLabel = new JLabel(); - JScrollPane fontDisplayNameScrollPane = new JScrollPane(); - fontNameTextArea = new JTextArea(); - JLabel jLabel3 = new JLabel(); - JScrollPane fontCopyrightScrollPane = new JScrollPane(); - fontCopyrightTextArea = new JTextArea(); - JLabel jLabel4 = new JLabel(); - fontIsBoldCheckBox = new JCheckBox(); - JLabel jLabel5 = new JLabel(); - fontIsItalicCheckBox = new JCheckBox(); - JLabel jLabel6 = new JLabel(); - fontAscentLabel = new JLabel(); - JLabel jLabel7 = new JLabel(); - fontDescentLabel = new JLabel(); - JLabel jLabel8 = new JLabel(); - fontLeadingLabel = new JLabel(); - JLabel jLabel9 = new JLabel(); - fontCharactersScrollPane = new JScrollPane(); - fontCharactersTextArea = new JTextArea(); - JLabel fontCharsAddLabel = new JLabel(); - fontAddCharactersField = new JTextField(); - fontAddCharsButton = new JButton(); - fontRemoveCharsButton = new JButton(); - fontSourceLabel = new JLabel(); - fontFamilyNameSelection = new JComboBox<>(); - fontFaceSelection = new JComboBox<>(); - fontEmbedButton = new JButton(); - buttonEdit = new JButton(); - buttonSave = new JButton(); - buttonCancel = new JButton(); - buttonPreviewFont = new JButton(); - buttonSetAdvanceValues = new JButton(); - addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent evt) { - formComponentResized(evt); - } - }); - - contentPanel = new JPanel(); - contentScrollPane.setBorder(null); - contentScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - - TableLayout tlFontParamsPanel; - fontParamsPanel.setLayout(tlFontParamsPanel = new TableLayout(new double[][]{ - {TableLayout.PREFERRED, TableLayout.FILL}, - {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL,} - })); - - JLabel fontNameIntagLabLabel = new JLabel(); - fontNameIntagLabLabel.setText(AppStrings.translate("font.name.intag")); - fontParamsPanel.add(fontNameIntagLabLabel, "0,0,R"); - - fontNameIntagLabel.setText(AppStrings.translate("value.unknown")); - fontNameIntagLabel.setMinimumSize(new Dimension(100, fontNameIntagLabel.getMinimumSize().height)); - fontNameIntagLabel.setPreferredSize(new Dimension(250, fontNameIntagLabel.getPreferredSize().height)); - fontParamsPanel.add(fontNameIntagLabel, "1,0"); - - JLabel fontNameNameLabLabel = new JLabel(); - fontNameNameLabLabel.setText(AppStrings.translate("font.name")); - fontParamsPanel.add(fontNameNameLabLabel, "0,1,R"); - - fontDisplayNameScrollPane.setBorder(null); - fontDisplayNameScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - fontDisplayNameScrollPane.setHorizontalScrollBar(null); - - fontNameTextArea.setEditable(false); - fontNameTextArea.setColumns(20); - fontNameTextArea.setFont(new JLabel().getFont()); - fontNameTextArea.setLineWrap(true); - fontNameTextArea.setText(AppStrings.translate("value.unknown")); - fontNameTextArea.setWrapStyleWord(true); - fontNameTextArea.setMinimumSize(new Dimension(100, fontNameTextArea.getMinimumSize().height)); - fontNameTextArea.setOpaque(false); - fontDisplayNameScrollPane.setViewportView(fontNameTextArea); - - fontParamsPanel.add(fontDisplayNameScrollPane, "1,1"); - - jLabel3.setText(AppStrings.translate("fontName.copyright")); - fontParamsPanel.add(jLabel3, "0,2,R"); - - fontCopyrightScrollPane.setBorder(null); - fontCopyrightScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - fontCopyrightScrollPane.setHorizontalScrollBar(null); - - fontCopyrightTextArea.setEditable(false); - fontCopyrightTextArea.setColumns(20); - fontCopyrightTextArea.setFont(new JLabel().getFont()); - fontCopyrightTextArea.setLineWrap(true); - fontCopyrightTextArea.setText(AppStrings.translate("value.unknown")); - fontCopyrightTextArea.setWrapStyleWord(true); - fontCopyrightTextArea.setMinimumSize(new Dimension(100, fontCopyrightTextArea.getMinimumSize().height)); - fontCopyrightTextArea.setOpaque(false); - fontCopyrightScrollPane.setViewportView(fontCopyrightTextArea); - - fontParamsPanel.add(fontCopyrightScrollPane, "1,2"); - - jLabel4.setText(AppStrings.translate("font.isbold")); - fontParamsPanel.add(jLabel4, "0,3,R"); - - fontIsBoldCheckBox.setEnabled(false); - - fontParamsPanel.add(fontIsBoldCheckBox, "1,3"); - - jLabel5.setText(AppStrings.translate("font.isitalic")); - - fontParamsPanel.add(jLabel5, "0,4,R"); - - fontIsItalicCheckBox.setEnabled(false); - fontParamsPanel.add(fontIsItalicCheckBox, "1,4"); - - jLabel6.setText(AppStrings.translate("font.ascent")); - fontParamsPanel.add(jLabel6, "0,5,R"); - - fontAscentLabel.setText(AppStrings.translate("value.unknown")); - fontParamsPanel.add(fontAscentLabel, "1,5"); - - jLabel7.setText(AppStrings.translate("font.descent")); - fontParamsPanel.add(jLabel7, "0,6,R"); - - fontDescentLabel.setText(AppStrings.translate("value.unknown")); - fontParamsPanel.add(fontDescentLabel, "1,6"); - - jLabel8.setText(AppStrings.translate("font.leading")); - fontParamsPanel.add(jLabel8, "0,7,R"); - - fontLeadingLabel.setText(AppStrings.translate("value.unknown")); - fontParamsPanel.add(fontLeadingLabel, "1,7"); - - jLabel9.setText(AppStrings.translate("font.characters")); - fontParamsPanel.add(jLabel9, "0,8,R,T"); - - fontCharactersScrollPane.setBorder(null); - fontCharactersScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - fontCharactersScrollPane.setHorizontalScrollBar(null); - fontCharactersScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - - fontCharactersTextArea.setEditable(false); - fontCharactersTextArea.setColumns(20); - fontCharactersTextArea.setFont(new JLabel().getFont()); - fontCharactersTextArea.setLineWrap(true); - fontCharactersTextArea.setWrapStyleWord(true); - fontCharactersTextArea.setMinimumSize(new Dimension(100, fontCharactersTextArea.getMinimumSize().height)); - fontCharactersTextArea.setOpaque(false); - fontCharactersScrollPane.setViewportView(fontCharactersTextArea); - fontParamsPanel.add(fontCharactersScrollPane, "1,8"); - - fontCharsAddLabel.setText(AppStrings.translate("font.characters.add")); - - fontAddCharsButton.setText(AppStrings.translate("button.ok")); - fontAddCharsButton.addActionListener(this::fontAddCharsButtonActionPerformed); - - fontRemoveCharsButton.setText(AppStrings.translate("button.remove")); - fontRemoveCharsButton.addActionListener(this::fontRemoveCharsButtonActionPerformed); - - fontSourceLabel.setText(AppStrings.translate("font.source")); - - fontFamilyNameSelection.setPreferredSize(new Dimension(100, fontFamilyNameSelection.getMinimumSize().height)); - fontFamilyNameSelection.setModel(getFamilyModel()); - fontFamilyNameSelection.setSelectedItem(FontTag.defaultFontName); - fontFaceSelection.setModel(getFaceModel((FontFamily) fontFamilyNameSelection.getSelectedItem())); - fontFamilyNameSelection.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent evt) { - fontFamilySelectionItemStateChanged(); - } - }); - - fontFaceSelection.addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent evt) { - fontFaceSelectionItemStateChanged(); - } - }); - - fontEmbedButton.setText(AppStrings.translate("button.font.embed")); - fontEmbedButton.addActionListener(this::fontEmbedButtonActionPerformed); - - buttonEdit.setIcon(View.getIcon("edit16")); - buttonEdit.setText(AppStrings.translate("button.edit")); - buttonEdit.addActionListener(this::buttonEditActionPerformed); - - buttonSave.setIcon(View.getIcon("save16")); - buttonSave.setText(AppStrings.translate("button.save")); - buttonSave.addActionListener(this::buttonSaveActionPerformed); - - buttonCancel.setIcon(View.getIcon("cancel16")); - buttonCancel.setText(AppStrings.translate("button.cancel")); - buttonCancel.addActionListener(this::buttonCancelActionPerformed); - - buttonPreviewFont.setText(AppStrings.translate("button.preview")); - buttonPreviewFont.addActionListener(this::buttonPreviewFontActionPerformed); - - buttonSetAdvanceValues.setText(AppStrings.translate("button.setAdvanceValues")); - buttonSetAdvanceValues.addActionListener(this::buttonSetAdvanceValuesActionPerformed); - - TableLayout tlAddCharsPanel; - addCharsPanel.setLayout(tlAddCharsPanel = new TableLayout(new double[][]{ - {TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}, - {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED} - })); - addCharsPanel.setBorder(BorderFactory.createRaisedBevelBorder()); - - addCharsPanel.add(fontCharsAddLabel, "0,0,R"); - addCharsPanel.add(fontAddCharactersField, "1,0,2,0"); - addCharsPanel.add(fontAddCharsButton, "3,0"); - //addCharsPanel.add(fontRemoveCharsButton, "3,0"); - addCharsPanel.add(fontEmbedButton, "4,0"); - - addCharsPanel.add(fontSourceLabel, "0,1,R"); - addCharsPanel.add(fontFamilyNameSelection, "1,1"); - addCharsPanel.add(fontFaceSelection, "2,1"); - addCharsPanel.add(buttonPreviewFont, "3,1"); - addCharsPanel.add(buttonSetAdvanceValues, "4,1"); - - JPanel buttonsPanel = new JPanel(new FlowLayout()); - buttonsPanel.add(buttonEdit); - buttonsPanel.add(buttonSave); - buttonsPanel.add(buttonCancel); - - TableLayout tlAll; - contentPanel.setLayout(tlAll = new TableLayout(new double[][]{ - {TableLayout.FILL}, - {TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED} - })); - - contentPanel.add(fontParamsPanel, "0,0"); - contentPanel.add(buttonsPanel, "0,1"); - contentPanel.add(addCharsPanel, "0,2"); - contentScrollPane.setViewportView(contentPanel); - - setLayout(new BorderLayout()); - add(contentScrollPane, BorderLayout.CENTER); - - TableLayoutHelper.addTableSpaces(tlAddCharsPanel, 10); - TableLayoutHelper.addTableSpaces(tlFontParamsPanel, 10); - TableLayoutHelper.addTableSpaces(tlAll, 10); - - addComponentListener(new ComponentAdapter() { - - @Override - public void componentResized(ComponentEvent e) { - contentPanel.setPreferredSize(new Dimension(Math.max(getSize().width, addCharsPanel.getPreferredSize().width + 20), getSize().height)); - contentPanel.revalidate(); - } - - }); - } - - private void fontAddCharsButtonActionPerformed(ActionEvent evt) { - String newchars = fontAddCharactersField.getText(); - - TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); - if (item instanceof FontTag) { - FontTag ft = (FontTag) item; - Set selChars = new TreeSet<>(); - for (int c = 0; c < newchars.length(); c++) { - selChars.add(newchars.codePointAt(c)); - } - - if (!selChars.isEmpty()) { - fontAddChars(ft, selChars, ((FontFace) fontFaceSelection.getSelectedItem()).font); - fontAddCharactersField.setText(""); - mainPanel.repaintTree(); - } - } - } - - private void fontRemoveCharsButtonActionPerformed(ActionEvent evt) { - String newchars = fontAddCharactersField.getText(); - - TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); - if (item instanceof FontTag) { - FontTag ft = (FontTag) item; - Set selChars = new TreeSet<>(); - for (int c = 0; c < newchars.length(); c++) { - selChars.add(newchars.codePointAt(c)); - } - - if (!selChars.isEmpty()) { - fontRemoveChars(ft, selChars); - fontAddCharactersField.setText(""); - mainPanel.repaintTree(); - } - } - } - - private void fontEmbedButtonActionPerformed(ActionEvent evt) { - TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); - if (item instanceof FontTag) { - FontTag ft = (FontTag) item; - FontEmbedDialog fed = new FontEmbedDialog((FontFace) fontFaceSelection.getSelectedItem(), fontAddCharactersField.getText()); - if (fed.showDialog() == AppDialog.OK_OPTION) { - Set selChars = fed.getSelectedChars(); - if (!selChars.isEmpty()) { - Font selFont = fed.getSelectedFont(); - fontFamilyNameSelection.setSelectedItem(new FontFamily(selFont)); - fontFaceSelection.setSelectedItem(new FontFace(selFont)); - fontAddChars(ft, selChars, selFont); - fontAddCharactersField.setText(""); - mainPanel.reload(true); - } - } - } - } - - private boolean allowSave = true; - - private synchronized void setAllowSave(boolean v) { - allowSave = v; - } - - private synchronized void savePair() { - if (!allowSave) { - return; - } - TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); - if (item instanceof FontTag) { - FontTag f = (FontTag) item; - SWF swf = f.getSwf(); - String selectedName = ((FontFace) fontFaceSelection.getSelectedItem()).font.getFontName(Locale.ENGLISH); - swf.sourceFontNamesMap.put(f.getFontId(), selectedName); - Configuration.addFontPair(swf.getShortFileName(), f.getFontId(), f.getFontNameIntag(), selectedName); - } - } - - private void fontFamilySelectionItemStateChanged() { - - savePair(); - fontFaceSelection.setModel(getFaceModel((FontFamily) fontFamilyNameSelection.getSelectedItem())); - } - - private void fontFaceSelectionItemStateChanged() { - savePair(); - } - - private void buttonEditActionPerformed(ActionEvent evt) { - setEditable(true); - } - - private void buttonSaveActionPerformed(ActionEvent evt) { - if (fontTag.isBoldEditable()) { - fontTag.setBold(fontIsBoldCheckBox.isSelected()); - } - if (fontTag.isItalicEditable()) { - fontTag.setItalic(fontIsItalicCheckBox.isSelected()); - } - setEditable(false); - } - - private void buttonCancelActionPerformed(ActionEvent evt) { - showFontTag(fontTag); - setEditable(false); - } - - private void buttonPreviewFontActionPerformed(ActionEvent evt) { - new FontPreviewDialog(null, true, ((FontFace) fontFaceSelection.getSelectedItem()).font).setVisible(true); - } - - private void buttonSetAdvanceValuesActionPerformed(ActionEvent evt) { - fontTag.setAdvanceValues(((FontFace) fontFaceSelection.getSelectedItem()).font); - } - - private void formComponentResized(ComponentEvent evt) { - fontParamsPanel.updateUI(); - } - - private void importTTFButtonActionPerformed(ActionEvent evt) { - TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); - if (item instanceof FontTag) { - FontTag ft = (FontTag) item; - - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - FileFilter ttfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".ttf")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return "TTF files"; - } - }; - fc.setFileFilter(ttfFilter); - - fc.setAcceptAllFileFilterUsed(false); - JFrame fr = new JFrame(); - View.setWindowIcon(fr); - int returnVal = fc.showOpenDialog(fr); - if (returnVal == JFileChooser.APPROVE_OPTION) { - Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); - File selfile = Helper.fixDialogFile(fc.getSelectedFile()); - Set selChars = new HashSet<>(); - try { - Font f = Font.createFont(Font.TRUETYPE_FONT, selfile); - int required[] = new int[]{0x0001, 0x0000, 0x000D, 0x0020}; - loopi: - for (char i = 0; i < Character.MAX_VALUE; i++) { - for (int r : required) { - if (r == i) { - continue loopi; - } - } - if (f.canDisplay((int) i)) { - selChars.add((int) i); - } - } - fontAddChars(ft, selChars, f); - mainPanel.reload(true); - } catch (FontFormatException ex) { - JOptionPane.showMessageDialog(mainPanel, "Invalid TTF font"); - } catch (IOException ex) { - Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - } - - private JButton buttonCancel; - - private JButton buttonEdit; - - private JButton buttonPreviewFont; - - private JButton buttonSetAdvanceValues; - - private JButton buttonSave; - - private JTextField fontAddCharactersField; - - private JButton fontAddCharsButton; - - private JButton fontRemoveCharsButton; - - private JLabel fontAscentLabel; - - private JScrollPane fontCharactersScrollPane; - - private JTextArea fontCharactersTextArea; - - private JTextArea fontCopyrightTextArea; - - private JLabel fontDescentLabel; - - private JTextArea fontNameTextArea; - - private JButton fontEmbedButton; - - private JCheckBox fontIsBoldCheckBox; - - private JCheckBox fontIsItalicCheckBox; - - private JLabel fontLeadingLabel; - - private JLabel fontNameIntagLabel; - - private JComboBox fontFamilyNameSelection; - - private JComboBox fontFaceSelection; - - private JLabel fontSourceLabel; - - private JPanel fontParamsPanel; - - private JPanel addCharsPanel; - - private JPanel contentPanel; - - private JScrollPane contentScrollPane; -} +/* + * Copyright (C) 2010-2016 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.SWF; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.gui.helpers.TableLayoutHelper; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.tags.base.TextTag; +import com.jpexs.decompiler.flash.treeitems.TreeItem; +import com.jpexs.helpers.Helper; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.TreeSet; +import java.util.Vector; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.BorderFactory; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.filechooser.FileFilter; +import layout.TableLayout; + +/** + * + * @author JPEXS + */ +public class FontPanel extends JPanel { + + private final MainPanel mainPanel; + + private FontTag fontTag; + + /** + * Creates new form FontPanel + * + * @param mainPanel Main panel + */ + public FontPanel(MainPanel mainPanel) { + this.mainPanel = mainPanel; + initComponents(); + } + + public FontTag getFontTag() { + return fontTag; + } + + public void clear() { + fontTag = null; + } + + public static ComboBoxModel getFamilyModel() { + Set famSet = new TreeSet<>(); + for (Font f : FontTag.installedFontsByName.values()) { + famSet.add(new FontFamily(f)); + } + return new DefaultComboBoxModel<>(new Vector<>(famSet)); + } + + public static ComboBoxModel getFaceModel(FontFamily family) { + + Set faceSet = new TreeSet<>(); + for (Font f : FontTag.installedFontsByFamily.get(family.familyEn).values()) { + faceSet.add(new FontFace(f)); + } + + return new DefaultComboBoxModel<>(new Vector<>(faceSet)); + } + + private void setEditable(boolean editable) { + if (editable) { + buttonEdit.setVisible(false); + buttonSave.setVisible(true); + buttonCancel.setVisible(true); + if (fontTag.isBoldEditable()) { + fontIsBoldCheckBox.setEnabled(true); + } + if (fontTag.isItalicEditable()) { + fontIsItalicCheckBox.setEnabled(true); + } + } else { + buttonEdit.setVisible(true); + buttonSave.setVisible(false); + buttonCancel.setVisible(false); + fontIsBoldCheckBox.setEnabled(false); + fontIsItalicCheckBox.setEnabled(false); + } + } + + private String translate(String key) { + return mainPanel.translate(key); + } + + private void fontAddChars(FontTag ft, Set selChars, Font font) { + FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem(); + String oldchars = f.getCharacters(); + for (int ic : selChars) { + char c = (char) ic; + if (oldchars.indexOf((int) c) == -1) { + font = font.deriveFont(f.getFontStyle(), 1024); + if (!font.canDisplay(c)) { + String msg = translate("error.font.nocharacter").replace("%char%", "" + c); + Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, msg); + View.showMessageDialog(null, msg, translate("error"), JOptionPane.ERROR_MESSAGE); + return; + } + } + } + + String[] yesno = new String[]{translate("button.yes"), translate("button.no"), translate("button.yes.all"), translate("button.no.all")}; + boolean yestoall = false; + boolean notoall = false; + boolean replaced = false; + for (int ic : selChars) { + char c = (char) ic; + if (oldchars.indexOf((int) c) > -1) { + int opt = -1; + if (!(yestoall || notoall)) { + opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes")); + if (opt == 2) { + yestoall = true; + } + if (opt == 3) { + notoall = true; + } + } + + if (yestoall) { + opt = 0; // yes + } else if (notoall) { + opt = 1; // no + } + + if (opt == 1) { + continue; + } + + replaced = true; + } + + f.addCharacter(c, font); + oldchars += c; + } + + if (replaced) { + if (View.showConfirmDialog(null, translate("message.font.replace.updateTexts"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.YES_OPTION) { + int fontId = ft.getFontId(); + SWF swf = ft.getSwf(); + for (Tag tag : swf.getTags()) { + if (tag instanceof TextTag) { + TextTag textTag = (TextTag) tag; + if (textTag.getFontIds().contains(fontId)) { + String text = textTag.getFormattedText(true).text; + mainPanel.saveText(textTag, text, null, null); + } + } + } + } + } + } + + private void fontRemoveChars(FontTag ft, Set selChars) { + FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem(); + + for (int ic : selChars) { + char c = (char) ic; + f.removeCharacter(c); + } + } + + public void showFontTag(FontTag ft) { + SWF swf = ft.getSwf(); + fontTag = ft; + fontNameIntagLabel.setText(ft.getFontNameIntag()); + fontNameTextArea.setText(ft.getFontName()); + fontCopyrightTextArea.setText(ft.getFontCopyright()); + + fontIsBoldCheckBox.setSelected(ft.isBold()); + fontIsItalicCheckBox.setSelected(ft.isItalic()); + fontDescentLabel.setText(ft.getDescent() == -1 ? translate("value.unknown") : Integer.toString(ft.getDescent())); + fontAscentLabel.setText(ft.getAscent() == -1 ? translate("value.unknown") : Integer.toString(ft.getAscent())); + fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : Integer.toString(ft.getLeading())); + String chars = ft.getCharacters(); + fontCharactersTextArea.setText(chars); + fontCharactersScrollPane.getVerticalScrollBar().scrollRectToVisible(new Rectangle(0, 0, 1, 1)); + setAllowSave(false); + + Font selFont = ft.getSystemFont(); + fontFamilyNameSelection.setSelectedItem(new FontFamily(selFont)); + fontFaceSelection.setSelectedItem(new FontFace(selFont)); + + setAllowSave(true); + setEditable(false); + boolean readOnly = ((Tag) ft).isReadOnly(); + if (readOnly) { + addCharsPanel.setVisible(false); + buttonEdit.setVisible(false); + } + } + + private void initComponents() { + + contentScrollPane = new JScrollPane(); + addCharsPanel = new JPanel(); + fontParamsPanel = new JPanel(); + fontNameIntagLabel = new JLabel(); + JScrollPane fontDisplayNameScrollPane = new JScrollPane(); + fontNameTextArea = new JTextArea(); + JLabel jLabel3 = new JLabel(); + JScrollPane fontCopyrightScrollPane = new JScrollPane(); + fontCopyrightTextArea = new JTextArea(); + JLabel jLabel4 = new JLabel(); + fontIsBoldCheckBox = new JCheckBox(); + JLabel jLabel5 = new JLabel(); + fontIsItalicCheckBox = new JCheckBox(); + JLabel jLabel6 = new JLabel(); + fontAscentLabel = new JLabel(); + JLabel jLabel7 = new JLabel(); + fontDescentLabel = new JLabel(); + JLabel jLabel8 = new JLabel(); + fontLeadingLabel = new JLabel(); + JLabel jLabel9 = new JLabel(); + fontCharactersScrollPane = new JScrollPane(); + fontCharactersTextArea = new JTextArea(); + JLabel fontCharsAddLabel = new JLabel(); + fontAddCharactersField = new JTextField(); + fontAddCharsButton = new JButton(); + fontRemoveCharsButton = new JButton(); + fontSourceLabel = new JLabel(); + fontFamilyNameSelection = new JComboBox<>(); + fontFaceSelection = new JComboBox<>(); + fontEmbedButton = new JButton(); + buttonEdit = new JButton(); + buttonSave = new JButton(); + buttonCancel = new JButton(); + buttonPreviewFont = new JButton(); + buttonSetAdvanceValues = new JButton(); + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent evt) { + formComponentResized(evt); + } + }); + + contentPanel = new JPanel(); + contentScrollPane.setBorder(null); + contentScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + + TableLayout tlFontParamsPanel; + fontParamsPanel.setLayout(tlFontParamsPanel = new TableLayout(new double[][]{ + {TableLayout.PREFERRED, TableLayout.FILL}, + {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL,} + })); + + JLabel fontNameIntagLabLabel = new JLabel(); + fontNameIntagLabLabel.setText(AppStrings.translate("font.name.intag")); + fontParamsPanel.add(fontNameIntagLabLabel, "0,0,R"); + + fontNameIntagLabel.setText(AppStrings.translate("value.unknown")); + fontNameIntagLabel.setMinimumSize(new Dimension(100, fontNameIntagLabel.getMinimumSize().height)); + fontNameIntagLabel.setPreferredSize(new Dimension(250, fontNameIntagLabel.getPreferredSize().height)); + fontParamsPanel.add(fontNameIntagLabel, "1,0"); + + JLabel fontNameNameLabLabel = new JLabel(); + fontNameNameLabLabel.setText(AppStrings.translate("font.name")); + fontParamsPanel.add(fontNameNameLabLabel, "0,1,R"); + + fontDisplayNameScrollPane.setBorder(null); + fontDisplayNameScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + fontDisplayNameScrollPane.setHorizontalScrollBar(null); + + fontNameTextArea.setEditable(false); + fontNameTextArea.setColumns(20); + fontNameTextArea.setFont(new JLabel().getFont()); + fontNameTextArea.setLineWrap(true); + fontNameTextArea.setText(AppStrings.translate("value.unknown")); + fontNameTextArea.setWrapStyleWord(true); + fontNameTextArea.setMinimumSize(new Dimension(100, fontNameTextArea.getMinimumSize().height)); + fontNameTextArea.setOpaque(false); + fontDisplayNameScrollPane.setViewportView(fontNameTextArea); + + fontParamsPanel.add(fontDisplayNameScrollPane, "1,1"); + + jLabel3.setText(AppStrings.translate("fontName.copyright")); + fontParamsPanel.add(jLabel3, "0,2,R"); + + fontCopyrightScrollPane.setBorder(null); + fontCopyrightScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + fontCopyrightScrollPane.setHorizontalScrollBar(null); + + fontCopyrightTextArea.setEditable(false); + fontCopyrightTextArea.setColumns(20); + fontCopyrightTextArea.setFont(new JLabel().getFont()); + fontCopyrightTextArea.setLineWrap(true); + fontCopyrightTextArea.setText(AppStrings.translate("value.unknown")); + fontCopyrightTextArea.setWrapStyleWord(true); + fontCopyrightTextArea.setMinimumSize(new Dimension(100, fontCopyrightTextArea.getMinimumSize().height)); + fontCopyrightTextArea.setOpaque(false); + fontCopyrightScrollPane.setViewportView(fontCopyrightTextArea); + + fontParamsPanel.add(fontCopyrightScrollPane, "1,2"); + + jLabel4.setText(AppStrings.translate("font.isbold")); + fontParamsPanel.add(jLabel4, "0,3,R"); + + fontIsBoldCheckBox.setEnabled(false); + + fontParamsPanel.add(fontIsBoldCheckBox, "1,3"); + + jLabel5.setText(AppStrings.translate("font.isitalic")); + + fontParamsPanel.add(jLabel5, "0,4,R"); + + fontIsItalicCheckBox.setEnabled(false); + fontParamsPanel.add(fontIsItalicCheckBox, "1,4"); + + jLabel6.setText(AppStrings.translate("font.ascent")); + fontParamsPanel.add(jLabel6, "0,5,R"); + + fontAscentLabel.setText(AppStrings.translate("value.unknown")); + fontParamsPanel.add(fontAscentLabel, "1,5"); + + jLabel7.setText(AppStrings.translate("font.descent")); + fontParamsPanel.add(jLabel7, "0,6,R"); + + fontDescentLabel.setText(AppStrings.translate("value.unknown")); + fontParamsPanel.add(fontDescentLabel, "1,6"); + + jLabel8.setText(AppStrings.translate("font.leading")); + fontParamsPanel.add(jLabel8, "0,7,R"); + + fontLeadingLabel.setText(AppStrings.translate("value.unknown")); + fontParamsPanel.add(fontLeadingLabel, "1,7"); + + jLabel9.setText(AppStrings.translate("font.characters")); + fontParamsPanel.add(jLabel9, "0,8,R,T"); + + fontCharactersScrollPane.setBorder(null); + fontCharactersScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + fontCharactersScrollPane.setHorizontalScrollBar(null); + fontCharactersScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + + fontCharactersTextArea.setEditable(false); + fontCharactersTextArea.setColumns(20); + fontCharactersTextArea.setFont(new JLabel().getFont()); + fontCharactersTextArea.setLineWrap(true); + fontCharactersTextArea.setWrapStyleWord(true); + fontCharactersTextArea.setMinimumSize(new Dimension(100, fontCharactersTextArea.getMinimumSize().height)); + fontCharactersTextArea.setOpaque(false); + fontCharactersScrollPane.setViewportView(fontCharactersTextArea); + fontParamsPanel.add(fontCharactersScrollPane, "1,8"); + + fontCharsAddLabel.setText(AppStrings.translate("font.characters.add")); + + fontAddCharsButton.setText(AppStrings.translate("button.ok")); + fontAddCharsButton.addActionListener(this::fontAddCharsButtonActionPerformed); + + fontRemoveCharsButton.setText(AppStrings.translate("button.remove")); + fontRemoveCharsButton.addActionListener(this::fontRemoveCharsButtonActionPerformed); + + fontSourceLabel.setText(AppStrings.translate("font.source")); + + fontFamilyNameSelection.setPreferredSize(new Dimension(100, fontFamilyNameSelection.getMinimumSize().height)); + fontFamilyNameSelection.setModel(getFamilyModel()); + fontFamilyNameSelection.setSelectedItem(FontTag.defaultFontName); + fontFaceSelection.setModel(getFaceModel((FontFamily) fontFamilyNameSelection.getSelectedItem())); + fontFamilyNameSelection.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent evt) { + fontFamilySelectionItemStateChanged(); + } + }); + + fontFaceSelection.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent evt) { + fontFaceSelectionItemStateChanged(); + } + }); + + fontEmbedButton.setText(AppStrings.translate("button.font.embed")); + fontEmbedButton.addActionListener(this::fontEmbedButtonActionPerformed); + + buttonEdit.setIcon(View.getIcon("edit16")); + buttonEdit.setText(AppStrings.translate("button.edit")); + buttonEdit.addActionListener(this::buttonEditActionPerformed); + + buttonSave.setIcon(View.getIcon("save16")); + buttonSave.setText(AppStrings.translate("button.save")); + buttonSave.addActionListener(this::buttonSaveActionPerformed); + + buttonCancel.setIcon(View.getIcon("cancel16")); + buttonCancel.setText(AppStrings.translate("button.cancel")); + buttonCancel.addActionListener(this::buttonCancelActionPerformed); + + buttonPreviewFont.setText(AppStrings.translate("button.preview")); + buttonPreviewFont.addActionListener(this::buttonPreviewFontActionPerformed); + + buttonSetAdvanceValues.setText(AppStrings.translate("button.setAdvanceValues")); + buttonSetAdvanceValues.addActionListener(this::buttonSetAdvanceValuesActionPerformed); + + TableLayout tlAddCharsPanel; + addCharsPanel.setLayout(tlAddCharsPanel = new TableLayout(new double[][]{ + {TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}, + {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED} + })); + addCharsPanel.setBorder(BorderFactory.createRaisedBevelBorder()); + + addCharsPanel.add(fontCharsAddLabel, "0,0,R"); + addCharsPanel.add(fontAddCharactersField, "1,0,2,0"); + addCharsPanel.add(fontAddCharsButton, "3,0"); + //addCharsPanel.add(fontRemoveCharsButton, "3,0"); + addCharsPanel.add(fontEmbedButton, "4,0"); + + addCharsPanel.add(fontSourceLabel, "0,1,R"); + addCharsPanel.add(fontFamilyNameSelection, "1,1"); + addCharsPanel.add(fontFaceSelection, "2,1"); + addCharsPanel.add(buttonPreviewFont, "3,1"); + addCharsPanel.add(buttonSetAdvanceValues, "4,1"); + + JPanel buttonsPanel = new JPanel(new FlowLayout()); + buttonsPanel.add(buttonEdit); + buttonsPanel.add(buttonSave); + buttonsPanel.add(buttonCancel); + + TableLayout tlAll; + contentPanel.setLayout(tlAll = new TableLayout(new double[][]{ + {TableLayout.FILL}, + {TableLayout.FILL, TableLayout.PREFERRED, TableLayout.PREFERRED} + })); + + contentPanel.add(fontParamsPanel, "0,0"); + contentPanel.add(buttonsPanel, "0,1"); + contentPanel.add(addCharsPanel, "0,2"); + contentScrollPane.setViewportView(contentPanel); + + setLayout(new BorderLayout()); + add(contentScrollPane, BorderLayout.CENTER); + + TableLayoutHelper.addTableSpaces(tlAddCharsPanel, 10); + TableLayoutHelper.addTableSpaces(tlFontParamsPanel, 10); + TableLayoutHelper.addTableSpaces(tlAll, 10); + + addComponentListener(new ComponentAdapter() { + + @Override + public void componentResized(ComponentEvent e) { + contentPanel.setPreferredSize(new Dimension(Math.max(getSize().width, addCharsPanel.getPreferredSize().width + 20), getSize().height)); + contentPanel.revalidate(); + } + + }); + } + + private void fontAddCharsButtonActionPerformed(ActionEvent evt) { + String newchars = fontAddCharactersField.getText(); + + TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); + if (item instanceof FontTag) { + FontTag ft = (FontTag) item; + Set selChars = new TreeSet<>(); + for (int c = 0; c < newchars.length(); c++) { + selChars.add(newchars.codePointAt(c)); + } + + if (!selChars.isEmpty()) { + fontAddChars(ft, selChars, ((FontFace) fontFaceSelection.getSelectedItem()).font); + fontAddCharactersField.setText(""); + mainPanel.repaintTree(); + } + } + } + + private void fontRemoveCharsButtonActionPerformed(ActionEvent evt) { + String newchars = fontAddCharactersField.getText(); + + TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); + if (item instanceof FontTag) { + FontTag ft = (FontTag) item; + Set selChars = new TreeSet<>(); + for (int c = 0; c < newchars.length(); c++) { + selChars.add(newchars.codePointAt(c)); + } + + if (!selChars.isEmpty()) { + fontRemoveChars(ft, selChars); + fontAddCharactersField.setText(""); + mainPanel.repaintTree(); + } + } + } + + private void fontEmbedButtonActionPerformed(ActionEvent evt) { + TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); + if (item instanceof FontTag) { + FontTag ft = (FontTag) item; + FontEmbedDialog fed = new FontEmbedDialog((FontFace) fontFaceSelection.getSelectedItem(), fontAddCharactersField.getText()); + if (fed.showDialog() == AppDialog.OK_OPTION) { + Set selChars = fed.getSelectedChars(); + if (!selChars.isEmpty()) { + Font selFont = fed.getSelectedFont(); + fontFamilyNameSelection.setSelectedItem(new FontFamily(selFont)); + fontFaceSelection.setSelectedItem(new FontFace(selFont)); + fontAddChars(ft, selChars, selFont); + fontAddCharactersField.setText(""); + mainPanel.reload(true); + } + } + } + } + + private boolean allowSave = true; + + private synchronized void setAllowSave(boolean v) { + allowSave = v; + } + + private synchronized void savePair() { + if (!allowSave) { + return; + } + TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); + if (item instanceof FontTag) { + FontTag f = (FontTag) item; + SWF swf = f.getSwf(); + String selectedName = ((FontFace) fontFaceSelection.getSelectedItem()).font.getFontName(Locale.ENGLISH); + swf.sourceFontNamesMap.put(f.getFontId(), selectedName); + Configuration.addFontPair(swf.getShortFileName(), f.getFontId(), f.getFontNameIntag(), selectedName); + } + } + + private void fontFamilySelectionItemStateChanged() { + + savePair(); + fontFaceSelection.setModel(getFaceModel((FontFamily) fontFamilyNameSelection.getSelectedItem())); + } + + private void fontFaceSelectionItemStateChanged() { + savePair(); + } + + private void buttonEditActionPerformed(ActionEvent evt) { + setEditable(true); + } + + private void buttonSaveActionPerformed(ActionEvent evt) { + if (fontTag.isBoldEditable()) { + fontTag.setBold(fontIsBoldCheckBox.isSelected()); + } + if (fontTag.isItalicEditable()) { + fontTag.setItalic(fontIsItalicCheckBox.isSelected()); + } + setEditable(false); + } + + private void buttonCancelActionPerformed(ActionEvent evt) { + showFontTag(fontTag); + setEditable(false); + } + + private void buttonPreviewFontActionPerformed(ActionEvent evt) { + new FontPreviewDialog(null, true, ((FontFace) fontFaceSelection.getSelectedItem()).font).setVisible(true); + } + + private void buttonSetAdvanceValuesActionPerformed(ActionEvent evt) { + fontTag.setAdvanceValues(((FontFace) fontFaceSelection.getSelectedItem()).font); + } + + private void formComponentResized(ComponentEvent evt) { + fontParamsPanel.updateUI(); + } + + private void importTTFButtonActionPerformed(ActionEvent evt) { + TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); + if (item instanceof FontTag) { + FontTag ft = (FontTag) item; + + JFileChooser fc = new JFileChooser(); + fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + FileFilter ttfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".ttf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return "TTF files"; + } + }; + fc.setFileFilter(ttfFilter); + + fc.setAcceptAllFileFilterUsed(false); + JFrame fr = new JFrame(); + View.setWindowIcon(fr); + int returnVal = fc.showOpenDialog(fr); + if (returnVal == JFileChooser.APPROVE_OPTION) { + Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); + File selfile = Helper.fixDialogFile(fc.getSelectedFile()); + Set selChars = new HashSet<>(); + try { + Font f = Font.createFont(Font.TRUETYPE_FONT, selfile); + int required[] = new int[]{0x0001, 0x0000, 0x000D, 0x0020}; + loopi: + for (char i = 0; i < Character.MAX_VALUE; i++) { + for (int r : required) { + if (r == i) { + continue loopi; + } + } + if (f.canDisplay((int) i)) { + selChars.add((int) i); + } + } + fontAddChars(ft, selChars, f); + mainPanel.reload(true); + } catch (FontFormatException ex) { + JOptionPane.showMessageDialog(mainPanel, "Invalid TTF font"); + } catch (IOException ex) { + Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + } + + private JButton buttonCancel; + + private JButton buttonEdit; + + private JButton buttonPreviewFont; + + private JButton buttonSetAdvanceValues; + + private JButton buttonSave; + + private JTextField fontAddCharactersField; + + private JButton fontAddCharsButton; + + private JButton fontRemoveCharsButton; + + private JLabel fontAscentLabel; + + private JScrollPane fontCharactersScrollPane; + + private JTextArea fontCharactersTextArea; + + private JTextArea fontCopyrightTextArea; + + private JLabel fontDescentLabel; + + private JTextArea fontNameTextArea; + + private JButton fontEmbedButton; + + private JCheckBox fontIsBoldCheckBox; + + private JCheckBox fontIsItalicCheckBox; + + private JLabel fontLeadingLabel; + + private JLabel fontNameIntagLabel; + + private JComboBox fontFamilyNameSelection; + + private JComboBox fontFaceSelection; + + private JLabel fontSourceLabel; + + private JPanel fontParamsPanel; + + private JPanel addCharsPanel; + + private JPanel contentPanel; + + private JScrollPane contentScrollPane; +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 53e043e7c..3b373bc09 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -1,3618 +1,3618 @@ -/* - * Copyright (C) 2010-2016 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.AbortRetryIgnoreHandler; -import com.jpexs.decompiler.flash.ApplicationInfo; -import com.jpexs.decompiler.flash.EventListener; -import com.jpexs.decompiler.flash.ReadOnlyTagList; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFSourceInfo; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.RenameType; -import com.jpexs.decompiler.flash.abc.ScriptPack; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.configuration.ConfigurationItem; -import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; -import com.jpexs.decompiler.flash.dumpview.DumpInfo; -import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode; -import com.jpexs.decompiler.flash.exporters.BinaryDataExporter; -import com.jpexs.decompiler.flash.exporters.FontExporter; -import com.jpexs.decompiler.flash.exporters.FrameExporter; -import com.jpexs.decompiler.flash.exporters.ImageExporter; -import com.jpexs.decompiler.flash.exporters.MorphShapeExporter; -import com.jpexs.decompiler.flash.exporters.MovieExporter; -import com.jpexs.decompiler.flash.exporters.ShapeExporter; -import com.jpexs.decompiler.flash.exporters.SoundExporter; -import com.jpexs.decompiler.flash.exporters.SymbolClassExporter; -import com.jpexs.decompiler.flash.exporters.TextExporter; -import com.jpexs.decompiler.flash.exporters.modes.BinaryDataExportMode; -import com.jpexs.decompiler.flash.exporters.modes.ButtonExportMode; -import com.jpexs.decompiler.flash.exporters.modes.FontExportMode; -import com.jpexs.decompiler.flash.exporters.modes.FrameExportMode; -import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode; -import com.jpexs.decompiler.flash.exporters.modes.MorphShapeExportMode; -import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; -import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode; -import com.jpexs.decompiler.flash.exporters.modes.SpriteExportMode; -import com.jpexs.decompiler.flash.exporters.modes.SymbolClassExportMode; -import com.jpexs.decompiler.flash.exporters.modes.TextExportMode; -import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter; -import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter; -import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.ButtonExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.FrameExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.MorphShapeExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.MovieExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.SpriteExportSettings; -import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings; -import com.jpexs.decompiler.flash.exporters.swf.SwfJavaExporter; -import com.jpexs.decompiler.flash.exporters.swf.SwfXmlExporter; -import com.jpexs.decompiler.flash.gui.abc.ABCPanel; -import com.jpexs.decompiler.flash.gui.abc.ABCPanelSearchResult; -import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel; -import com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane; -import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog; -import com.jpexs.decompiler.flash.gui.action.ActionPanel; -import com.jpexs.decompiler.flash.gui.action.ActionSearchResult; -import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; -import com.jpexs.decompiler.flash.gui.dumpview.DumpTree; -import com.jpexs.decompiler.flash.gui.dumpview.DumpTreeModel; -import com.jpexs.decompiler.flash.gui.dumpview.DumpViewPanel; -import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane; -import com.jpexs.decompiler.flash.gui.helpers.ObservableList; -import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; -import com.jpexs.decompiler.flash.gui.tagtree.TagTree; -import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel; -import com.jpexs.decompiler.flash.gui.timeline.TimelineViewPanel; -import com.jpexs.decompiler.flash.helpers.FileTextWriter; -import com.jpexs.decompiler.flash.helpers.Freed; -import com.jpexs.decompiler.flash.importers.AS2ScriptImporter; -import com.jpexs.decompiler.flash.importers.AS3ScriptImporter; -import com.jpexs.decompiler.flash.importers.BinaryDataImporter; -import com.jpexs.decompiler.flash.importers.ImageImporter; -import com.jpexs.decompiler.flash.importers.ShapeImporter; -import com.jpexs.decompiler.flash.importers.SwfXmlImporter; -import com.jpexs.decompiler.flash.importers.SymbolClassImporter; -import com.jpexs.decompiler.flash.importers.TextImporter; -import com.jpexs.decompiler.flash.importers.svg.SvgImporter; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; -import com.jpexs.decompiler.flash.tags.DefineSoundTag; -import com.jpexs.decompiler.flash.tags.DefineSpriteTag; -import com.jpexs.decompiler.flash.tags.DoActionTag; -import com.jpexs.decompiler.flash.tags.DoInitActionTag; -import com.jpexs.decompiler.flash.tags.FileAttributesTag; -import com.jpexs.decompiler.flash.tags.MetadataTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.TagInfo; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; -import com.jpexs.decompiler.flash.tags.base.ButtonTag; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.tags.base.DrawableTag; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler; -import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; -import com.jpexs.decompiler.flash.tags.base.ShapeTag; -import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; -import com.jpexs.decompiler.flash.tags.base.SoundTag; -import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag; -import com.jpexs.decompiler.flash.tags.base.TextImportErrorHandler; -import com.jpexs.decompiler.flash.tags.base.TextTag; -import com.jpexs.decompiler.flash.tags.text.TextAlign; -import com.jpexs.decompiler.flash.tags.text.TextParseException; -import com.jpexs.decompiler.flash.timeline.DepthState; -import com.jpexs.decompiler.flash.timeline.Frame; -import com.jpexs.decompiler.flash.timeline.TagScript; -import com.jpexs.decompiler.flash.timeline.Timeline; -import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.treeitems.FolderItem; -import com.jpexs.decompiler.flash.treeitems.HeaderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; -import com.jpexs.decompiler.flash.treeitems.TreeItem; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.sound.SoundFormat; -import com.jpexs.decompiler.flash.xfl.FLAVersion; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.Path; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.SerializableImage; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Desktop; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragGestureEvent; -import java.awt.dnd.DragGestureListener; -import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceDragEvent; -import java.awt.dnd.DragSourceDropEvent; -import java.awt.dnd.DragSourceEvent; -import java.awt.dnd.DragSourceListener; -import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.event.ActionEvent; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.CancellationException; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.UnsupportedAudioFileException; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.Icon; -import javax.swing.JColorChooser; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; -import javax.swing.SwingConstants; -import javax.swing.UIManager; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.filechooser.FileFilter; -import javax.swing.plaf.basic.BasicTreeUI; -import javax.swing.tree.DefaultTreeSelectionModel; -import javax.swing.tree.TreePath; -import jsyntaxpane.DefaultSyntaxKit; - -/** - * - * @author JPEXS - */ -public final class MainPanel extends JPanel implements TreeSelectionListener, SearchListener, Freed { - - private final MainFrame mainFrame; - - private final ObservableList swfs; - - private final JPanel welcomePanel; - - private final TimelineViewPanel timelineViewPanel; - - private final MainFrameStatusPanel statusPanel; - - private final MainFrameMenu mainMenu; - - private final JProgressBar progressBar = new JProgressBar(0, 100); - - public TagTree tagTree; - - public DumpTree dumpTree; - - private final FlashPlayerPanel flashPanel; - - private final FlashPlayerPanel flashPanel2; - - private final JPanel contentPanel; - - private final JPanel displayPanel; - - public FolderPreviewPanel folderPreviewPanel; - - private boolean isWelcomeScreen = true; - - private static final String CARDPREVIEWPANEL = "Preview card"; - - private static final String CARDFOLDERPREVIEWPANEL = "Folder preview card"; - - private static final String CARDEMPTYPANEL = "Empty card"; - - private static final String CARDDUMPVIEW = "Dump view"; - - private static final String CARDACTIONSCRIPTPANEL = "ActionScript card"; - - private static final String CARDACTIONSCRIPT3PANEL = "ActionScript3 card"; - - private static final String CARDHEADER = "Header card"; - - private static final String DETAILCARDAS3NAVIGATOR = "Traits list"; - - private static final String DETAILCARDTAGINFO = "Tag information"; - - private static final String DETAILCARDEMPTYPANEL = "Empty card"; - - private static final String SPLIT_PANE1 = "SPLITPANE1"; - - private static final String WELCOME_PANEL = "WELCOMEPANEL"; - - private static final String TIMELINE_PANEL = "TIMELINEPANEL"; - - private static final String RESOURCES_VIEW = "RESOURCES"; - - private static final String DUMP_VIEW = "DUMP"; - - private static final String TIMELINE_VIEW = "TIMELINE"; - - private final JPersistentSplitPane splitPane1; - - private final JPersistentSplitPane splitPane2; - - private JPanel detailPanel; - - private JTextField filterField = new MyTextField(""); - - private JPanel searchPanel; - - private ABCPanel abcPanel; - - private ActionPanel actionPanel; - - private final PreviewPanel previewPanel; - - private final HeaderInfoPanel headerPanel; - - private DumpViewPanel dumpViewPanel; - - private final JPanel treePanel; - - private final PreviewPanel dumpPreviewPanel; - - private final TagInfoPanel tagInfoPanel; - - private TreePanelMode treePanelMode; - - private CancellableWorker setSourceWorker; - - public TreeItem oldItem; - - // play morph shape in 2 second(s) - public static final int MORPH_SHAPE_ANIMATION_LENGTH = 2; - - public static final int MORPH_SHAPE_ANIMATION_FRAME_RATE = 30; - - private static final Logger logger = Logger.getLogger(MainPanel.class.getName()); - - public void setPercent(int percent) { - progressBar.setValue(percent); - progressBar.setVisible(true); - } - - public void hidePercent() { - if (progressBar.isVisible()) { - progressBar.setVisible(false); - } - } - - public MainFrame getMainFrame() { - return mainFrame; - } - - static { - try { - File.createTempFile("temp", ".swf").delete(); //First call to this is slow, so make it first - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - public void updateMenu() { - mainMenu.updateComponents(); - } - - private static void addTab(JTabbedPane tabbedPane, Component tab, String title, Icon icon) { - tabbedPane.add(tab); - - JLabel lbl = new JLabel(title); - lbl.setIcon(icon); - lbl.setIconTextGap(5); - lbl.setHorizontalTextPosition(SwingConstants.RIGHT); - - tabbedPane.setTabComponentAt(tabbedPane.getTabCount() - 1, lbl); - } - - public void setStatus(String s) { - statusPanel.setStatus(s); - } - - public void setWorkStatus(String s, CancellableWorker worker) { - statusPanel.setWorkStatus(s, worker); - mainMenu.updateComponents(); - } - - private JPanel createWelcomePanel() { - JPanel welcomePanel = new JPanel(); - welcomePanel.setLayout(new BoxLayout(welcomePanel, BoxLayout.Y_AXIS)); - JLabel welcomeToLabel = new JLabel(translate("startup.welcometo")); - welcomeToLabel.setFont(welcomeToLabel.getFont().deriveFont(40)); - welcomeToLabel.setAlignmentX(0.5f); - JPanel appNamePanel = new JPanel(new FlowLayout()); - JLabel jpLabel = new JLabel("JPEXS "); - jpLabel.setAlignmentX(0.5f); - jpLabel.setForeground(new Color(0, 0, 160)); - jpLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); - jpLabel.setHorizontalAlignment(SwingConstants.CENTER); - appNamePanel.add(jpLabel); - - JLabel ffLabel = new JLabel("Free Flash "); - ffLabel.setAlignmentX(0.5f); - ffLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); - ffLabel.setHorizontalAlignment(SwingConstants.CENTER); - appNamePanel.add(ffLabel); - - JLabel decLabel = new JLabel("Decompiler"); - decLabel.setAlignmentX(0.5f); - decLabel.setForeground(Color.red); - decLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); - decLabel.setHorizontalAlignment(SwingConstants.CENTER); - appNamePanel.add(decLabel); - appNamePanel.setAlignmentX(0.5f); - welcomePanel.add(Box.createGlue()); - welcomePanel.add(welcomeToLabel); - welcomePanel.add(appNamePanel); - JLabel startLabel = new JLabel(translate("startup.selectopen")); - startLabel.setAlignmentX(0.5f); - startLabel.setFont(startLabel.getFont().deriveFont(30)); - welcomePanel.add(startLabel); - welcomePanel.add(Box.createGlue()); - return welcomePanel; - } - - private JPanel createFolderPreviewCard() { - JPanel folderPreviewCard = new JPanel(new BorderLayout()); - folderPreviewPanel = new FolderPreviewPanel(this, new ArrayList<>()); - folderPreviewCard.add(new JScrollPane(folderPreviewPanel), BorderLayout.CENTER); - - return folderPreviewCard; - } - - private JPanel createDumpPreviewCard() { - JPanel dumpViewCard = new JPanel(new BorderLayout()); - dumpViewPanel = new DumpViewPanel(dumpTree); - dumpViewCard.add(new JScrollPane(dumpViewPanel), BorderLayout.CENTER); - - return dumpViewCard; - } - - public String translate(String key) { - return mainFrame.translate(key); - } - - public MainPanel(MainFrame mainFrame, MainFrameMenu mainMenu, FlashPlayerPanel flashPanel, FlashPlayerPanel previewFlashPanel) { - super(); - - this.mainFrame = mainFrame; - this.mainMenu = mainMenu; - this.flashPanel = flashPanel; - this.flashPanel2 = previewFlashPanel; - - mainFrame.setTitle(ApplicationInfo.applicationVerName); - - setLayout(new BorderLayout()); - swfs = new ObservableList<>(); - - detailPanel = new JPanel(); - detailPanel.setLayout(new CardLayout()); - - JPanel whitePanel = new JPanel(); - whitePanel.setBackground(Color.white); - detailPanel.add(whitePanel, DETAILCARDEMPTYPANEL); - - tagInfoPanel = new TagInfoPanel(this); - detailPanel.add(tagInfoPanel, DETAILCARDTAGINFO); - - UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName()); - tagTree = new TagTree(null, this); - tagTree.addTreeSelectionListener(this); - tagTree.setSelectionModel(new DefaultTreeSelectionModel() { - - private boolean isModified() { - if (abcPanel != null && abcPanel.isEditing()) { - abcPanel.tryAutoSave(); - } - - if (actionPanel != null && actionPanel.isEditing()) { - actionPanel.tryAutoSave(); - } - - if (previewPanel.isEditing()) { - previewPanel.tryAutoSave(); - } - - if (headerPanel.isEditing()) { - headerPanel.tryAutoSave(); - } - - return (abcPanel != null && abcPanel.isEditing()) - || (actionPanel != null && actionPanel.isEditing()) - || previewPanel.isEditing() || headerPanel.isEditing(); - } - - @Override - public void addSelectionPath(TreePath path) { - if (isModified()) { - return; - } - - super.addSelectionPath(path); - } - - @Override - public void addSelectionPaths(TreePath[] paths) { - if (isModified()) { - return; - } - - super.addSelectionPaths(paths); - } - - @Override - public void setSelectionPath(TreePath path) { - if (isModified()) { - return; - } - - super.setSelectionPath(path); - } - - @Override - public void setSelectionPaths(TreePath[] pPaths) { - if (isModified()) { - return; - } - - super.setSelectionPaths(pPaths); - } - - @Override - public void clearSelection() { - if (isModified()) { - return; - } - - super.clearSelection(); - } - - public void setSelection(TreePath[] selection) { - if (isModified()) { - return; - } - - this.selection = selection; - } - - @Override - public void removeSelectionPath(TreePath path) { - if (isModified()) { - return; - } - - super.removeSelectionPath(path); - } - - @Override - public void removeSelectionPaths(TreePath[] paths) { - if (isModified()) { - return; - } - - super.removeSelectionPaths(paths); - } - }); - - DragSource dragSource = DragSource.getDefaultDragSource(); - dragSource.createDefaultDragGestureRecognizer(tagTree, DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener() { - @Override - public void dragGestureRecognized(DragGestureEvent dge) { - dge.startDrag(DragSource.DefaultCopyDrop, new Transferable() { - @Override - public DataFlavor[] getTransferDataFlavors() { - return new DataFlavor[]{DataFlavor.javaFileListFlavor}; - } - - @Override - public boolean isDataFlavorSupported(DataFlavor flavor) { - return flavor.equals(DataFlavor.javaFileListFlavor); - } - - @Override - public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - if (flavor.equals(DataFlavor.javaFileListFlavor)) { - List files; - String tempDir = System.getProperty("java.io.tmpdir"); - if (!tempDir.endsWith(File.separator)) { - tempDir += File.separator; - } - Random rnd = new Random(); - tempDir += "ffdec" + File.separator + "export" + File.separator + System.currentTimeMillis() + "_" + rnd.nextInt(1000); - File fTempDir = new File(tempDir); - Path.createDirectorySafe(fTempDir); - - File ftemp = new File(tempDir); - ExportDialog exd = new ExportDialog(null); - try { - files = exportSelection(new GuiAbortRetryIgnoreHandler(), tempDir, exd); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - return null; - } - - files.clear(); - - File[] fs = ftemp.listFiles(); - files.addAll(Arrays.asList(fs)); - - Main.stopWork(); - - for (File f : files) { - f.deleteOnExit(); - } - new File(tempDir).deleteOnExit(); - return files; - - } - return null; - } - }, new DragSourceListener() { - @Override - public void dragEnter(DragSourceDragEvent dsde) { - enableDrop(false); - } - - @Override - public void dragOver(DragSourceDragEvent dsde) { - } - - @Override - public void dropActionChanged(DragSourceDragEvent dsde) { - } - - @Override - public void dragExit(DragSourceEvent dse) { - } - - @Override - public void dragDropEnd(DragSourceDropEvent dsde) { - enableDrop(true); - } - }); - } - }); - - tagTree.createContextMenu(); - - dumpTree = new DumpTree(null, this); - dumpTree.addTreeSelectionListener(this); - dumpTree.createContextMenu(); - - statusPanel = new MainFrameStatusPanel(this); - add(statusPanel, BorderLayout.SOUTH); - - displayPanel = new JPanel(new CardLayout()); - - DefaultSyntaxKit.initKit(); - previewPanel = new PreviewPanel(this, flashPanel); - - dumpPreviewPanel = new PreviewPanel(this, previewFlashPanel); - dumpPreviewPanel.setReadOnly(true); - - displayPanel.add(previewPanel, CARDPREVIEWPANEL); - displayPanel.add(createFolderPreviewCard(), CARDFOLDERPREVIEWPANEL); - displayPanel.add(createDumpPreviewCard(), CARDDUMPVIEW); - - headerPanel = new HeaderInfoPanel(); - displayPanel.add(headerPanel, CARDHEADER); - - displayPanel.add(new JPanel(), CARDEMPTYPANEL); - showCard(CARDEMPTYPANEL); - - searchPanel = new JPanel(); - searchPanel.setLayout(new BorderLayout()); - searchPanel.add(filterField, BorderLayout.CENTER); - searchPanel.add(new JLabel(View.getIcon("search16")), BorderLayout.WEST); - JLabel closeSearchButton = new JLabel(View.getIcon("cancel16")); - closeSearchButton.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - closeTagTreeSearch(); - } - }); - searchPanel.add(closeSearchButton, BorderLayout.EAST); - searchPanel.setVisible(false); - treePanel = new JPanel(new CardLayout()); - treePanel.add(createResourcesViewCard(), RESOURCES_VIEW); - treePanel.add(createDumpViewCard(), DUMP_VIEW); - //treePanel.add(searchPanel, BorderLayout.SOUTH); - //searchPanel.setVisible(false); - filterField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void changedUpdate(DocumentEvent e) { - warn(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - warn(); - } - - @Override - public void insertUpdate(DocumentEvent e) { - warn(); - } - - public void warn() { - doFilter(); - } - }); - - //displayPanel.setBorder(BorderFactory.createLineBorder(Color.black)); - splitPane2 = new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, treePanel, detailPanel, Configuration.guiSplitPane2DividerLocationPercent); - splitPane1 = new JPersistentSplitPane(JSplitPane.HORIZONTAL_SPLIT, splitPane2, displayPanel, Configuration.guiSplitPane1DividerLocationPercent); - - welcomePanel = createWelcomePanel(); - add(welcomePanel, BorderLayout.CENTER); - - timelineViewPanel = new TimelineViewPanel(); - - CardLayout cl3 = new CardLayout(); - contentPanel = new JPanel(cl3); - contentPanel.add(welcomePanel, WELCOME_PANEL); - contentPanel.add(splitPane1, SPLIT_PANE1); - contentPanel.add(timelineViewPanel, TIMELINE_PANEL); - add(contentPanel); - cl3.show(contentPanel, WELCOME_PANEL); - - tagTree.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if ((e.getKeyCode() == 'F') && (e.isControlDown())) { - searchPanel.setVisible(true); - filterField.requestFocusInWindow(); - } - } - }); - detailPanel.setVisible(false); - - updateUi(); - - this.swfs.addCollectionChangedListener((e) -> { - TagTreeModel ttm = tagTree.getModel(); - if (ttm != null) { - if (getCurrentSwf() == null) { - tagTree.setSelectionPath(ttm.getTreePath(ttm.getRoot())); - } - ttm.updateSwfs(e); - tagTree.expandRoot(); - tagTree.expandFirstLevelNodes(); - } - - DumpTreeModel dtm = dumpTree.getModel(); - if (dtm != null) { - List> expandedNodes = View.getExpandedNodes(dumpTree); - dtm.updateSwfs(); - View.expandTreeNodes(dumpTree, expandedNodes); - dumpTree.expandRoot(); - dumpTree.expandFirstLevelNodes(); - } - - if (swfs.isEmpty()) { - tagTree.setUI(new BasicTreeUI() { - { - setHashColor(Color.gray); - } - }); - dumpTree.setUI(new BasicTreeUI() { - { - setHashColor(Color.gray); - } - }); - } - }); - - //Opening files with drag&drop to main window - enableDrop(true); - } - - public void closeTagTreeSearch() { - filterField.setText(""); - doFilter(); - searchPanel.setVisible(false); - } - - public void loadSwfAtPos(SWFList newSwfs, int index) { - previewPanel.clear(); - swfs.set(index, newSwfs); - SWF swf = newSwfs.size() > 0 ? newSwfs.get(0) : null; - if (swf != null) { - updateUi(swf); - } - - doFilter(); - reload(false); - } - - public void load(SWFList newSwfs, boolean first) { - - previewPanel.clear(); - - swfs.add(newSwfs); - SWF swf = newSwfs.size() > 0 ? newSwfs.get(0) : null; - if (swf != null) { - updateUi(swf); - } - - doFilter(); - reload(false); - } - - private ABCPanel getABCPanel() { - if (abcPanel == null) { - abcPanel = new ABCPanel(this); - displayPanel.add(abcPanel, CARDACTIONSCRIPT3PANEL); - detailPanel.add(abcPanel.tabbedPane, DETAILCARDAS3NAVIGATOR); - } - - return abcPanel; - } - - private ActionPanel getActionPanel() { - if (actionPanel == null) { - actionPanel = new ActionPanel(MainPanel.this); - displayPanel.add(actionPanel, CARDACTIONSCRIPTPANEL); - } - - return actionPanel; - } - - private void updateUi(final SWF swf) { - - mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : "")); - - List abcList = swf.getAbcList(); - - boolean hasAbc = !abcList.isEmpty(); - - if (hasAbc) { - getABCPanel().setAbc(abcList.get(0).getABC()); - } - - if (isWelcomeScreen) { - CardLayout cl = (CardLayout) (contentPanel.getLayout()); - cl.show(contentPanel, SPLIT_PANE1); - isWelcomeScreen = false; - } - - mainMenu.updateComponents(swf); - } - - private void updateUi() { - if (!isWelcomeScreen && swfs.isEmpty()) { - CardLayout cl = (CardLayout) (contentPanel.getLayout()); - cl.show(contentPanel, WELCOME_PANEL); - isWelcomeScreen = true; - closeTagTreeSearch(); - } - - mainFrame.setTitle(ApplicationInfo.applicationVerName); - mainMenu.updateComponents(null); - - showView(getCurrentView()); - } - - private boolean closeConfirmation(SWFList swfList) { - String message = swfList == null - ? translate("message.confirm.closeAll") - : translate("message.confirm.close").replace("{swfName}", swfList.toString()); - - if (View.showConfirmDialog(this, message, translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) { - return false; - } - - return true; - } - - public boolean isModified() { - for (SWFList swfList : swfs) { - for (SWF swf : swfList) { - if (swf.isModified()) { - return true; - } - } - } - - return false; - } - - public boolean closeAll(boolean showCloseConfirmation) { - if (showCloseConfirmation && isModified()) { - boolean closeConfirmResult = closeConfirmation(swfs.size() == 1 ? swfs.get(0) : null); - if (!closeConfirmResult) { - return false; - } - } - - List swfsLists = new ArrayList<>(swfs); - swfs.clear(); - oldItem = null; - clear(); - updateUi(); - - for (SWFList swfList : swfsLists) { - List swfs2 = new ArrayList<>(swfList); - for (SWF swf : swfs2) { - swf.clearTagSwfs(); - } - } - - return true; - } - - public boolean close(SWFList swfList) { - boolean modified = false; - for (SWF swf : swfList) { - if (swf.isModified()) { - modified = true; - } - } - - if (modified) { - boolean closeConfirmResult = closeConfirmation(swfList); - if (!closeConfirmResult) { - return false; - } - } - - swfs.remove(swfList); - oldItem = null; - clear(); - updateUi(); - - List swfs2 = new ArrayList<>(swfList); - for (SWF swf : swfs2) { - swf.clearTagSwfs(); - } - - return true; - } - - public void enableDrop(boolean value) { - if (value) { - setDropTarget(new DropTarget() { - @Override - public synchronized void drop(DropTargetDropEvent dtde) { - try { - dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); - @SuppressWarnings("unchecked") - List droppedFiles = (List) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); - if (!droppedFiles.isEmpty()) { - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[droppedFiles.size()]; - for (int i = 0; i < droppedFiles.size(); i++) { - sourceInfos[i] = new SWFSourceInfo(null, droppedFiles.get(i).getAbsolutePath(), null); - } - Main.openFile(sourceInfos, null); - } - } catch (UnsupportedFlavorException | IOException ex) { - } - } - }); - } else { - setDropTarget(null); - } - } - - public void updateClassesList() { - List nodes = getASTreeNodes(tagTree); - boolean updateNeeded = false; - for (TreeItem n : nodes) { - if (n instanceof ClassesListTreeModel) { - ((ClassesListTreeModel) n).update(); - updateNeeded = true; - } - } - - refreshTree(); - - if (updateNeeded) { - tagTree.updateUI(); - } - } - - public void doFilter() { - List nodes = getASTreeNodes(tagTree); - for (TreeItem n : nodes) { - if (n instanceof ClassesListTreeModel) { - String filterText = filterField.getText(); - ((ClassesListTreeModel) n).setFilter(filterText); - TagTreeModel tm = tagTree.getModel(); - TreePath path = tm.getTreePath(n); - tm.updateNode(path); - if (!filterText.isEmpty()) { - View.expandTreeNodes(tagTree, path, true); - } - } - } - } - - public void renameIdentifier(SWF swf, String identifier) throws InterruptedException { - String oldName = identifier; - String newName = View.showInputDialog(translate("rename.enternew"), oldName); - if (newName != null) { - if (!oldName.equals(newName)) { - swf.renameAS2Identifier(oldName, newName); - View.showMessageDialog(null, translate("rename.finished.identifier")); - updateClassesList(); - reload(true); - } - } - } - - public void renameMultiname(List abcList, int multiNameIndex) { - String oldName = ""; - AVM2ConstantPool constants = getABCPanel().abc.constants; - if (constants.getMultiname(multiNameIndex).name_index > 0) { - oldName = constants.getString(constants.getMultiname(multiNameIndex).name_index); - } - - String newName = View.showInputDialog(translate("rename.enternew"), oldName); - if (newName != null) { - if (!oldName.equals(newName)) { - int mulCount = 0; - for (ABCContainerTag cnt : abcList) { - ABC abc = cnt.getABC(); - for (int m = 1; m < abc.constants.getMultinameCount(); m++) { - int ni = abc.constants.getMultiname(m).name_index; - String n = ""; - if (ni > 0) { - n = abc.constants.getString(ni); - } - if (n.equals(oldName)) { - abc.renameMultiname(m, newName); - mulCount++; - } - } - } - - View.showMessageDialog(null, translate("rename.finished.multiname").replace("%count%", Integer.toString(mulCount))); - if (abcPanel != null) { - abcPanel.reload(); - } - - updateClassesList(); - reload(true); - ABCPanel abcPanel = getABCPanel(); - abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().toRawString()); - } - } - } - - public List getASTreeNodes(TagTree tree) { - List result = new ArrayList<>(); - TagTreeModel tm = (TagTreeModel) tree.getModel(); - if (tm == null) { - return result; - } - TreeItem root = tm.getRoot(); - for (int i = 0; i < tm.getChildCount(root); i++) { - // first level node can be SWF and SWFBundle - TreeItem node = tm.getChild(root, i); - if (node instanceof SWFBundle) { - for (int j = 0; j < tm.getChildCount(node); j++) { - // child of SWFBundle should be SWF - SWF swfNode = (SWF) tm.getChild(node, j); - result.add(tm.getScriptsNode(swfNode)); - } - } else if (node instanceof SWF) { - SWF swfNode = (SWF) tm.getChild(root, i); - result.add(tm.getScriptsNode(swfNode)); - } - } - return result; - } - - public boolean confirmExperimental() { - return View.showConfirmDialog(null, translate("message.confirm.experimental"), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION; - } - - public List exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException, InterruptedException { - - List ret = new ArrayList<>(); - List sel = folderPreviewPanel.selectedItems.isEmpty() ? tagTree.getAllSelected() : new ArrayList<>(folderPreviewPanel.selectedItems.values()); - - Set usedSwfs = new HashSet<>(); - for (TreeItem d : sel) { - SWF selectedNodeSwf = d.getSwf(); - if (!usedSwfs.contains(selectedNodeSwf)) { - usedSwfs.add(selectedNodeSwf); - } - } - - Map usedSwfsIds = new HashMap<>(); - for (SWF swf : usedSwfs) { - List as3scripts = new ArrayList<>(); - List images = new ArrayList<>(); - List shapes = new ArrayList<>(); - List morphshapes = new ArrayList<>(); - List buttons = new ArrayList<>(); - List movies = new ArrayList<>(); - List sounds = new ArrayList<>(); - List texts = new ArrayList<>(); - List as12scripts = new ArrayList<>(); - List binaryData = new ArrayList<>(); - Map> frames = new HashMap<>(); - List fonts = new ArrayList<>(); - List symbolNames = new ArrayList<>(); - - for (TreeItem d : sel) { - SWF selectedNodeSwf = d.getSwf(); - - if (selectedNodeSwf != swf) { - continue; - } - - if (d instanceof TagScript) { - Tag tag = ((TagScript) d).getTag(); - if (tag instanceof DoActionTag || tag instanceof DoInitActionTag) { - as12scripts.add(d); - } - } - - if (d instanceof Tag || d instanceof ASMSource) { - TreeNodeType nodeType = TagTree.getTreeNodeType(d); - if (nodeType == TreeNodeType.IMAGE) { - images.add((Tag) d); - } - if (nodeType == TreeNodeType.SHAPE) { - shapes.add((Tag) d); - } - if (nodeType == TreeNodeType.BUTTON) { - buttons.add((Tag) d); - } - if (nodeType == TreeNodeType.MORPH_SHAPE) { - morphshapes.add((Tag) d); - } - if (nodeType == TreeNodeType.AS) { - as12scripts.add(d); - } - if (nodeType == TreeNodeType.MOVIE) { - movies.add((Tag) d); - } - if (nodeType == TreeNodeType.SOUND) { - sounds.add((Tag) d); - } - if (nodeType == TreeNodeType.BINARY_DATA) { - binaryData.add((Tag) d); - } - if (nodeType == TreeNodeType.TEXT) { - texts.add((Tag) d); - } - if (nodeType == TreeNodeType.FONT) { - fonts.add((Tag) d); - } - if (nodeType == TreeNodeType.OTHER_TAG) { - if (d instanceof SymbolClassTypeTag) { - symbolNames.add((Tag) d); - } - } - } - - if (d instanceof Frame) { - Frame fn = (Frame) d; - Timelined parent = fn.timeline.timelined; - int frame = fn.frame; - int parentId = 0; - if (parent instanceof CharacterTag) { - parentId = ((CharacterTag) parent).getCharacterId(); - } - if (!frames.containsKey(parentId)) { - frames.put(parentId, new ArrayList<>()); - } - frames.get(parentId).add(frame); - } - if (d instanceof ScriptPack) { - as3scripts.add((ScriptPack) d); - } - } - - String selFile2; - if (usedSwfs.size() > 1) { - selFile2 = selFile + File.separator + Helper.getNextId(swf.getShortFileName(), usedSwfsIds); - } else { - selFile2 = selFile; - } - - EventListener evl = swf.getExportEventListener(); - - if (export.isOptionEnabled(ImageExportMode.class)) { - ret.addAll(new ImageExporter().exportImages(handler, selFile2 + File.separator + ImageExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(images), - new ImageExportSettings(export.getValue(ImageExportMode.class)), evl)); - } - - if (export.isOptionEnabled(ShapeExportMode.class)) { - ret.addAll(new ShapeExporter().exportShapes(handler, selFile2 + File.separator + ShapeExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(shapes), - new ShapeExportSettings(export.getValue(ShapeExportMode.class), export.getZoom()), evl)); - } - - if (export.isOptionEnabled(MorphShapeExportMode.class)) { - ret.addAll(new MorphShapeExporter().exportMorphShapes(handler, selFile2 + File.separator + MorphShapeExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(morphshapes), - new MorphShapeExportSettings(export.getValue(MorphShapeExportMode.class), export.getZoom()), evl)); - } - - if (export.isOptionEnabled(TextExportMode.class)) { - ret.addAll(new TextExporter().exportTexts(handler, selFile2 + File.separator + TextExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(texts), - new TextExportSettings(export.getValue(TextExportMode.class), Configuration.textExportSingleFile.get(), export.getZoom()), evl)); - } - - if (export.isOptionEnabled(MovieExportMode.class)) { - ret.addAll(new MovieExporter().exportMovies(handler, selFile2 + File.separator + MovieExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(movies), - new MovieExportSettings(export.getValue(MovieExportMode.class)), evl)); - } - - if (export.isOptionEnabled(SoundExportMode.class)) { - ret.addAll(new SoundExporter().exportSounds(handler, selFile2 + File.separator + SoundExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(sounds), - new SoundExportSettings(export.getValue(SoundExportMode.class)), evl)); - } - - if (export.isOptionEnabled(BinaryDataExportMode.class)) { - ret.addAll(new BinaryDataExporter().exportBinaryData(handler, selFile2 + File.separator + BinaryDataExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(binaryData), - new BinaryDataExportSettings(export.getValue(BinaryDataExportMode.class)), evl)); - } - - if (export.isOptionEnabled(FontExportMode.class)) { - ret.addAll(new FontExporter().exportFonts(handler, selFile2 + File.separator + FontExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(fonts), - new FontExportSettings(export.getValue(FontExportMode.class)), evl)); - } - - if (export.isOptionEnabled(SymbolClassExportMode.class)) { - ret.addAll(new SymbolClassExporter().exportNames(selFile2, new ReadOnlyTagList(symbolNames), evl)); - } - - FrameExporter frameExporter = new FrameExporter(); - - if (export.isOptionEnabled(FrameExportMode.class)) { - FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom()); - for (Entry> entry : frames.entrySet()) { - int containerId = entry.getKey(); - if (containerId == 0) { - String subFolder = FrameExportSettings.EXPORT_FOLDER_NAME; - ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, containerId, entry.getValue(), fes, evl)); - } - } - } - - if (export.isOptionEnabled(SpriteExportMode.class)) { - SpriteExportSettings ses = new SpriteExportSettings(export.getValue(SpriteExportMode.class), export.getZoom()); - for (Entry> entry : frames.entrySet()) { - int containerId = entry.getKey(); - if (containerId != 0) { - String subFolder = SpriteExportSettings.EXPORT_FOLDER_NAME; - ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, containerId, entry.getValue(), ses, evl)); - } - } - } - - if (export.isOptionEnabled(ButtonExportMode.class)) { - ButtonExportSettings bes = new ButtonExportSettings(export.getValue(ButtonExportMode.class), export.getZoom()); - for (Tag tag : buttons) { - ButtonTag button = (ButtonTag) tag; - String subFolder = ButtonExportSettings.EXPORT_FOLDER_NAME; - List frameNums = new ArrayList<>(); - frameNums.add(0); // todo: export all frames - ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, button.getCharacterId(), frameNums, bes, evl)); - } - } - - if (export.isOptionEnabled(ScriptExportMode.class)) { - if (as3scripts.size() > 0 || as12scripts.size() > 0) { - boolean parallel = Configuration.parallelSpeedUp.get(); - String scriptsFolder = Path.combine(selFile2, ScriptExportSettings.EXPORT_FOLDER_NAME); - Path.createDirectorySafe(new File(scriptsFolder)); - boolean singleScriptFile = Configuration.scriptExportSingleFile.get(); - if (parallel && singleScriptFile) { - logger.log(Level.WARNING, AppStrings.translate("export.script.singleFilePallelModeWarning")); - singleScriptFile = false; - } - - ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), singleScriptFile); - String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); - try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { - scriptExportSettings.singleFileWriter = writer; - if (swf.isAS3()) { - ret.addAll(new AS3ScriptExporter().exportActionScript3(swf, handler, scriptsFolder, as3scripts, scriptExportSettings, parallel, evl)); - } else { - Map asmsToExport = swf.getASMs(true, as12scripts, false); - ret.addAll(new AS2ScriptExporter().exportAS2Scripts(handler, scriptsFolder, asmsToExport, scriptExportSettings, parallel, evl)); - } - } - } - } - } - - return ret; - } - - public void exportAll(SWF swf, AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException, InterruptedException { - boolean exportAll = false; - if (exportAll) { - exportAllDebug(swf, handler, selFile, export); - return; - } - - EventListener evl = swf.getExportEventListener(); - - if (export.isOptionEnabled(ImageExportMode.class)) { - new ImageExporter().exportImages(handler, Path.combine(selFile, ImageExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new ImageExportSettings(export.getValue(ImageExportMode.class)), evl); - } - - if (export.isOptionEnabled(ShapeExportMode.class)) { - new ShapeExporter().exportShapes(handler, Path.combine(selFile, ShapeExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new ShapeExportSettings(export.getValue(ShapeExportMode.class), export.getZoom()), evl); - } - - if (export.isOptionEnabled(MorphShapeExportMode.class)) { - new MorphShapeExporter().exportMorphShapes(handler, Path.combine(selFile, MorphShapeExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new MorphShapeExportSettings(export.getValue(MorphShapeExportMode.class), export.getZoom()), evl); - } - - if (export.isOptionEnabled(TextExportMode.class)) { - new TextExporter().exportTexts(handler, Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new TextExportSettings(export.getValue(TextExportMode.class), Configuration.textExportSingleFile.get(), export.getZoom()), evl); - } - - if (export.isOptionEnabled(MovieExportMode.class)) { - new MovieExporter().exportMovies(handler, Path.combine(selFile, MovieExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new MovieExportSettings(export.getValue(MovieExportMode.class)), evl); - } - - if (export.isOptionEnabled(SoundExportMode.class)) { - new SoundExporter().exportSounds(handler, Path.combine(selFile, SoundExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new SoundExportSettings(export.getValue(SoundExportMode.class)), evl); - } - - if (export.isOptionEnabled(BinaryDataExportMode.class)) { - new BinaryDataExporter().exportBinaryData(handler, Path.combine(selFile, BinaryDataExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new BinaryDataExportSettings(export.getValue(BinaryDataExportMode.class)), evl); - } - - if (export.isOptionEnabled(FontExportMode.class)) { - new FontExporter().exportFonts(handler, Path.combine(selFile, FontExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), - new FontExportSettings(export.getValue(FontExportMode.class)), evl); - } - - if (export.isOptionEnabled(SymbolClassExportMode.class)) { - new SymbolClassExporter().exportNames(selFile, swf.getTags(), evl); - } - - FrameExporter frameExporter = new FrameExporter(); - - if (export.isOptionEnabled(FrameExportMode.class)) { - FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom()); - frameExporter.exportFrames(handler, Path.combine(selFile, FrameExportSettings.EXPORT_FOLDER_NAME), swf, 0, null, fes, evl); - } - - if (export.isOptionEnabled(SpriteExportMode.class)) { - SpriteExportSettings ses = new SpriteExportSettings(export.getValue(SpriteExportMode.class), export.getZoom()); - for (CharacterTag c : swf.getCharacters().values()) { - if (c instanceof DefineSpriteTag) { - frameExporter.exportFrames(handler, Path.combine(selFile, SpriteExportSettings.EXPORT_FOLDER_NAME), swf, c.getCharacterId(), null, ses, evl); - } - } - } - - if (export.isOptionEnabled(ButtonExportMode.class)) { - ButtonExportSettings bes = new ButtonExportSettings(export.getValue(ButtonExportMode.class), export.getZoom()); - for (CharacterTag c : swf.getCharacters().values()) { - if (c instanceof ButtonTag) { - List frameNums = new ArrayList<>(); - frameNums.add(0); // todo: export all frames - frameExporter.exportFrames(handler, Path.combine(selFile, ButtonExportSettings.EXPORT_FOLDER_NAME), swf, c.getCharacterId(), frameNums, bes, evl); - } - } - } - - if (export.isOptionEnabled(ScriptExportMode.class)) { - boolean parallel = Configuration.parallelSpeedUp.get(); - String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); - Path.createDirectorySafe(new File(scriptsFolder)); - boolean singleScriptFile = Configuration.scriptExportSingleFile.get(); - if (parallel && singleScriptFile) { - logger.log(Level.WARNING, AppStrings.translate("export.script.singleFilePallelModeWarning")); - singleScriptFile = false; - } - - ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), singleScriptFile); - String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); - try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { - scriptExportSettings.singleFileWriter = writer; - swf.exportActionScript(handler, scriptsFolder, scriptExportSettings, parallel, evl); - } - } - } - - public void exportAllDebug(SWF swf, AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException, InterruptedException { - EventListener evl = swf.getExportEventListener(); - - if (export.isOptionEnabled(ImageExportMode.class)) { - for (ImageExportMode exportMode : ImageExportMode.values()) { - new ImageExporter().exportImages(handler, Path.combine(selFile, ImageExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new ImageExportSettings(exportMode), evl); - } - } - - if (export.isOptionEnabled(ShapeExportMode.class)) { - for (ShapeExportMode exportMode : ShapeExportMode.values()) { - new ShapeExporter().exportShapes(handler, Path.combine(selFile, ShapeExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new ShapeExportSettings(exportMode, export.getZoom()), evl); - } - } - - if (export.isOptionEnabled(MorphShapeExportMode.class)) { - for (MorphShapeExportMode exportMode : MorphShapeExportMode.values()) { - new MorphShapeExporter().exportMorphShapes(handler, Path.combine(selFile, MorphShapeExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new MorphShapeExportSettings(exportMode, export.getZoom()), evl); - } - } - - if (export.isOptionEnabled(TextExportMode.class)) { - for (TextExportMode exportMode : TextExportMode.values()) { - new TextExporter().exportTexts(handler, Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new TextExportSettings(exportMode, Configuration.textExportSingleFile.get(), export.getZoom()), evl); - } - } - - if (export.isOptionEnabled(MovieExportMode.class)) { - for (MovieExportMode exportMode : MovieExportMode.values()) { - new MovieExporter().exportMovies(handler, Path.combine(selFile, MovieExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new MovieExportSettings(exportMode), evl); - } - } - - if (export.isOptionEnabled(SoundExportMode.class)) { - for (SoundExportMode exportMode : SoundExportMode.values()) { - new SoundExporter().exportSounds(handler, Path.combine(selFile, SoundExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new SoundExportSettings(exportMode), evl); - } - } - - if (export.isOptionEnabled(BinaryDataExportMode.class)) { - for (BinaryDataExportMode exportMode : BinaryDataExportMode.values()) { - new BinaryDataExporter().exportBinaryData(handler, Path.combine(selFile, BinaryDataExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new BinaryDataExportSettings(exportMode), evl); - } - } - - if (export.isOptionEnabled(FontExportMode.class)) { - for (FontExportMode exportMode : FontExportMode.values()) { - new FontExporter().exportFonts(handler, Path.combine(selFile, FontExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), - new FontExportSettings(exportMode), evl); - } - } - - if (export.isOptionEnabled(SymbolClassExportMode.class)) { - for (SymbolClassExportMode exportMode : SymbolClassExportMode.values()) { - new SymbolClassExporter().exportNames(selFile, swf.getTags(), evl); - } - } - - FrameExporter frameExporter = new FrameExporter(); - - if (export.isOptionEnabled(FrameExportMode.class)) { - for (FrameExportMode exportMode : FrameExportMode.values()) { - FrameExportSettings fes = new FrameExportSettings(exportMode, export.getZoom()); - frameExporter.exportFrames(handler, Path.combine(selFile, FrameExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, 0, null, fes, evl); - } - } - - if (export.isOptionEnabled(SpriteExportMode.class)) { - for (SpriteExportMode exportMode : SpriteExportMode.values()) { - SpriteExportSettings ses = new SpriteExportSettings(exportMode, export.getZoom()); - for (CharacterTag c : swf.getCharacters().values()) { - if (c instanceof DefineSpriteTag) { - frameExporter.exportFrames(handler, Path.combine(selFile, SpriteExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, c.getCharacterId(), null, ses, evl); - } - } - } - } - - if (export.isOptionEnabled(ButtonExportMode.class)) { - for (ButtonExportMode exportMode : ButtonExportMode.values()) { - ButtonExportSettings bes = new ButtonExportSettings(exportMode, export.getZoom()); - for (CharacterTag c : swf.getCharacters().values()) { - if (c instanceof ButtonTag) { - List frameNums = new ArrayList<>(); - frameNums.add(0); // todo: export all frames - frameExporter.exportFrames(handler, Path.combine(selFile, ButtonExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, c.getCharacterId(), frameNums, bes, evl); - } - } - } - } - - if (export.isOptionEnabled(ScriptExportMode.class)) { - boolean parallel = Configuration.parallelSpeedUp.get(); - for (ScriptExportMode exportMode : ScriptExportMode.values()) { - String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME, exportMode.name()); - Path.createDirectorySafe(new File(scriptsFolder)); - boolean singleScriptFile = Configuration.scriptExportSingleFile.get(); - if (parallel && singleScriptFile) { - logger.log(Level.WARNING, AppStrings.translate("export.script.singleFilePallelModeWarning")); - singleScriptFile = false; - } - - ScriptExportSettings scriptExportSettings = new ScriptExportSettings(exportMode, singleScriptFile); - String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); - try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { - scriptExportSettings.singleFileWriter = writer; - swf.exportActionScript(handler, scriptsFolder, scriptExportSettings, parallel, evl); - } - } - } - } - - public List getSwfs() { - return swfs; - } - - public SWFList getCurrentSwfList() { - SWF swf = getCurrentSwf(); - if (swf == null) { - return null; - } - - return swf.swfList; - } - - public SWF getCurrentSwf() { - if (swfs == null || swfs.isEmpty()) { - return null; - } - - if (treePanelMode == TreePanelMode.TAG_TREE) { - TreeItem treeNode = (TreeItem) tagTree.getLastSelectedPathComponent(); - if (treeNode == null || treeNode instanceof SWFList) { - return null; - } - - return treeNode.getSwf(); - } else if (treePanelMode == TreePanelMode.DUMP_TREE) { - DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent(); - - if (dumpInfo == null) { - return null; - } - - return DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf(); - } - - return null; - } - - public void gotoFrame(int frame) { - TreeItem treeItem = (TreeItem) tagTree.getLastSelectedPathComponent(); - if (treeItem == null) { - return; - } - if (treeItem instanceof Timelined) { - Timelined t = (Timelined) treeItem; - Frame f = tagTree.getModel().getFrame(treeItem.getSwf(), t, frame); - if (f != null) { - setTagTreeSelectedNode(f); - } - } - } - - public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex) { - gotoScriptName(swf, scriptName); - if (abcPanel != null) { - if (Main.isDebugPCode()) { - if (classIndex != -1) { - boolean classChanged = false; - if (abcPanel.decompiledTextArea.getClassIndex() != classIndex) { - abcPanel.decompiledTextArea.setClassIndex(classIndex); - classChanged = true; - } - if (traitIndex != -10 && (classChanged || abcPanel.decompiledTextArea.lastTraitIndex != traitIndex)) { - abcPanel.decompiledTextArea.gotoTrait(traitIndex); - } - } - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.gotoInstrLine(line); - } else { - abcPanel.decompiledTextArea.gotoLine(line); - } - } else if (actionPanel != null) { - if (Main.isDebugPCode()) { - actionPanel.editor.gotoLine(line); - } else { - actionPanel.decompiledEditor.gotoLine(line); - } - } - refreshBreakPoints(); - - } - - public void refreshBreakPoints() { - if (abcPanel != null) { - abcPanel.decompiledTextArea.refreshMarkers(); - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.refreshMarkers(); - } - if (actionPanel != null) { - actionPanel.decompiledEditor.refreshMarkers(); - actionPanel.editor.refreshMarkers(); - } - } - - /* - public void debuggerBreakAt(SWF swf, String cls, int line) { - View.execInEventDispatchLater(new Runnable() { - - @Override - public void run() { - gotoClassLine(swf, cls, line); - if (abcPanel != null) { - abcPanel.decompiledTextArea.addColorMarker(line, DecompiledEditorPane.FG_IP_COLOR, DecompiledEditorPane.BG_IP_COLOR, DecompiledEditorPane.PRIORITY_IP); - } - } - }); - - }*/ - public void gotoScriptName(SWF swf, String scriptName) { - if (swf == null) { - return; - } - if (swf.isAS3()) { - String rawScriptName = scriptName; - if (rawScriptName.startsWith("#PCODE ")) { - rawScriptName = rawScriptName.substring(rawScriptName.indexOf(';') + 1); - } - - List abcList = swf.getAbcList(); - if (!abcList.isEmpty()) { - ABCPanel abcPanel = getABCPanel(); - abcPanel.setAbc(abcList.get(0).getABC()); - abcPanel.hilightScript(swf, rawScriptName); - } - } else { - String rawScriptName = scriptName; - if (rawScriptName.startsWith("#PCODE ")) { - rawScriptName = rawScriptName.substring("#PCODE ".length()); - } - Map asms = swf.getASMs(true); - if (actionPanel != null && asms.containsKey(rawScriptName)) { - actionPanel.setSource(asms.get(rawScriptName), true); - } - } - } - - public void gotoDocumentClass(SWF swf) { - if (swf == null) { - return; - } - - String documentClass = swf.getDocumentClass(); - if (documentClass != null && !Configuration.dumpView.get()) { - List abcList = swf.getAbcList(); - if (!abcList.isEmpty()) { - ABCPanel abcPanel = getABCPanel(); - for (ABCContainerTag c : abcList) { - if (c.getABC().findClassByName(documentClass) > -1) { - abcPanel.setAbc(c.getABC()); - abcPanel.hilightScript(swf, documentClass); - break; - } - } - } - } - } - - public void disableDecompilationChanged() { - clearAllScriptCache(); - - if (abcPanel != null) { - abcPanel.reload(); - } - - updateClassesList(); - } - - private void clearAllScriptCache() { - for (SWFList swfList : swfs) { - for (SWF swf : swfList) { - swf.clearScriptCache(); - } - } - } - - public void searchInActionScriptOrText(Boolean searchInText, SWF swf) { - SearchDialog searchDialog = new SearchDialog(getMainFrame().getWindow(), false); - if (searchInText != null) { - if (searchInText) { - searchDialog.searchInTextsRadioButton.setSelected(true); - } else { - searchDialog.searchInASRadioButton.setSelected(true); - } - } - - if (searchDialog.showDialog() == AppDialog.OK_OPTION) { - final String txt = searchDialog.searchField.getText(); - if (!txt.isEmpty()) { - if (swf.isAS3()) { - getABCPanel(); - } else { - getActionPanel(); - } - - boolean ignoreCase = searchDialog.ignoreCaseCheckBox.isSelected(); - boolean regexp = searchDialog.regexpCheckBox.isSelected(); - - if (searchDialog.searchInASRadioButton.isSelected()) { - new CancellableWorker() { - @Override - protected Void doInBackground() throws Exception { - List abcResult = null; - List actionResult = null; - if (swf.isAS3()) { - abcResult = getABCPanel().search(swf, txt, ignoreCase, regexp, this); - } else { - actionResult = getActionPanel().search(swf, txt, ignoreCase, regexp, this); - } - - List fAbcResult = abcResult; - List fActionResult = actionResult; - View.execInEventDispatch(() -> { - boolean found = false; - if (fAbcResult != null) { - found = true; - getABCPanel().searchPanel.setSearchText(txt); - SearchResultsDialog sr = new SearchResultsDialog<>(getMainFrame().getWindow(), txt, getABCPanel()); - sr.setResults(fAbcResult); - sr.setVisible(true); - } else if (fActionResult != null) { - found = true; - getActionPanel().searchPanel.setSearchText(txt); - - SearchResultsDialog sr = new SearchResultsDialog<>(getMainFrame().getWindow(), txt, getActionPanel()); - sr.setResults(fActionResult); - sr.setVisible(true); - } - - if (!found) { - View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); - } - - Main.stopWork(); - }); - - return null; - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - Main.stopWork(); - }); - - } - }.execute(); - } else if (searchDialog.searchInTextsRadioButton.isSelected()) { - new CancellableWorker() { - @Override - protected Void doInBackground() throws Exception { - List textResult; - SearchPanel textSearchPanel = previewPanel.getTextPanel().getSearchPanel(); - textSearchPanel.setOptions(ignoreCase, regexp); - textResult = searchText(txt, ignoreCase, regexp, swf); - - List fTextResult = textResult; - View.execInEventDispatch(() -> { - textSearchPanel.setSearchText(txt); - boolean found = textSearchPanel.setResults(fTextResult); - if (!found) { - View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); - } - - Main.stopWork(); - }); - - return null; - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - Main.stopWork(); - }); - - } - }.execute(); - } - } - } - } - - public void replaceText() { - SearchDialog replaceDialog = new SearchDialog(getMainFrame().getWindow(), true); - if (replaceDialog.showDialog() == AppDialog.OK_OPTION) { - final String txt = replaceDialog.searchField.getText(); - if (!txt.isEmpty()) { - final SWF swf = getCurrentSwf(); - - new CancellableWorker() { - @Override - protected Void doInBackground() throws Exception { - int findCount = 0; - boolean ignoreCase = replaceDialog.ignoreCaseCheckBox.isSelected(); - boolean regexp = replaceDialog.regexpCheckBox.isSelected(); - String replacement = replaceDialog.replaceField.getText(); - if (!regexp) { - replacement = Matcher.quoteReplacement(replacement); - } - Pattern pat; - if (regexp) { - pat = Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); - } else { - pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); - } - List textTags = new ArrayList<>(); - for (Tag tag : swf.getTags()) { - if (tag instanceof TextTag) { - textTags.add((TextTag) tag); - } - } - for (TextTag textTag : textTags) { - if (!replaceDialog.replaceInParametersCheckBox.isSelected()) { - List texts = textTag.getTexts(); - boolean found = false; - for (int i = 0; i < texts.size(); i++) { - String text = texts.get(i); - if (pat.matcher(text).find()) { - texts.set(i, text.replaceAll(txt, replacement)); - found = true; - findCount++; - } - } - if (found) { - String[] textArray = texts.toArray(new String[texts.size()]); - textTag.setFormattedText(getMissingCharacterHandler(), textTag.getFormattedText(false).text, textArray); - } - } else { - String text = textTag.getFormattedText(false).text; - if (pat.matcher(text).find()) { - textTag.setFormattedText(getMissingCharacterHandler(), text.replaceAll(txt, replacement), null); - findCount++; - } - } - } - - if (findCount > 0) { - swf.clearImageCache(); - repaintTree(); - } - - return null; - } - }.execute(); - } - } - } - - private List searchText(String txt, boolean ignoreCase, boolean regexp, SWF swf) { - if (txt != null && !txt.isEmpty()) { - List found = new ArrayList<>(); - Pattern pat; - if (regexp) { - pat = Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); - } else { - pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); - } - for (Tag tag : swf.getTags()) { - if (tag instanceof TextTag) { - TextTag textTag = (TextTag) tag; - if (pat.matcher(textTag.getFormattedText(false).text).find()) { - found.add(textTag); - } - } - } - - return found; - } - - return null; - } - - @Override - public void updateSearchPos(TextTag item) { - setTagTreeSelectedNode(item); - previewPanel.getTextPanel().updateSearchPos(); - } - - private void setDumpTreeSelectedNode(DumpInfo dumpInfo) { - DumpTreeModel dtm = (DumpTreeModel) dumpTree.getModel(); - TreePath tp = dtm.getDumpInfoPath(dumpInfo); - if (tp != null) { - dumpTree.setSelectionPath(tp); - dumpTree.scrollPathToVisible(tp); - } else { - showCard(CARDEMPTYPANEL); - } - } - - public void setTagTreeSelectedNode(TreeItem treeItem) { - TagTreeModel ttm = tagTree.getModel(); - TreePath tp = ttm.getTreePath(treeItem); - if (tp != null) { - tagTree.setSelectionPath(tp); - tagTree.scrollPathToVisible(tp); - } else { - showCard(CARDEMPTYPANEL); - } - } - - public void autoDeobfuscateChanged() { - Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable"); - clearAllScriptCache(); - if (abcPanel != null) { - abcPanel.reload(); - } - reload(true); - updateClassesList(); - } - - public void renameOneIdentifier(final SWF swf) { - if (swf == null) { - return; - } - - FileAttributesTag fileAttributes = swf.getFileAttributes(); - if (fileAttributes != null && fileAttributes.actionScript3) { - final int multiName = getABCPanel().decompiledTextArea.getMultinameUnderCaret(); - final List abcList = swf.getAbcList(); - if (multiName > 0) { - new CancellableWorker() { - @Override - public Void doInBackground() throws Exception { - renameMultiname(abcList, multiName); - return null; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.renaming") + "...", this); - } - - @Override - protected void done() { - Main.stopWork(); - } - }.execute(); - - } else { - View.showMessageDialog(null, translate("message.rename.notfound.multiname"), translate("message.rename.notfound.title"), JOptionPane.INFORMATION_MESSAGE); - } - } else { - final String identifier = getActionPanel().getStringUnderCursor(); - if (identifier != null) { - new CancellableWorker() { - @Override - public Void doInBackground() throws Exception { - try { - renameIdentifier(swf, identifier); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - return null; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.renaming") + "...", this); - } - - @Override - protected void done() { - Main.stopWork(); - } - }.execute(); - } else { - View.showMessageDialog(null, translate("message.rename.notfound.identifier"), translate("message.rename.notfound.title"), JOptionPane.INFORMATION_MESSAGE); - } - } - } - - public void exportFla(final SWF swf) { - if (swf == null) { - return; - } - JFileChooser fc = new JFileChooser(); - String selDir = Configuration.lastOpenDir.get(); - fc.setCurrentDirectory(new File(selDir)); - if (!selDir.endsWith(File.separator)) { - selDir += File.separator; - } - String fileName = new File(swf.getFile()).getName(); - fileName = fileName.substring(0, fileName.length() - 4) + ".fla"; - fc.setSelectedFile(new File(selDir + fileName)); - List flaFilters = new ArrayList<>(); - List xflFilters = new ArrayList<>(); - List versions = new ArrayList<>(); - boolean isAS3 = swf.isAS3(); - for (int i = FLAVersion.values().length - 1; i >= 0; i--) { - final FLAVersion v = FLAVersion.values()[i]; - if (!isAS3 && v.minASVersion() > 2) { - // This version does not support AS1/2 - } else { - versions.add(v); - FileFilter f = new FileFilter() { - @Override - public boolean accept(File f) { - return f.isDirectory() || (f.getName().toLowerCase().endsWith(".fla")); - } - - @Override - public String getDescription() { - return translate("filter.fla").replace("%version%", v.applicationName()); - } - }; - if (v == FLAVersion.CS6) { - fc.setFileFilter(f); - } else { - fc.addChoosableFileFilter(f); - } - flaFilters.add(f); - f = new FileFilter() { - @Override - public boolean accept(File f) { - return f.isDirectory() || (f.getName().toLowerCase().endsWith(".xfl")); - } - - @Override - public String getDescription() { - return translate("filter.xfl").replace("%version%", v.applicationName()); - } - }; - fc.addChoosableFileFilter(f); - xflFilters.add(f); - } - } - - fc.setAcceptAllFileFilterUsed(false); - JFrame f = new JFrame(); - View.setWindowIcon(f); - if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { - Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); - File sf = Helper.fixDialogFile(fc.getSelectedFile()); - - FileFilter selectedFilter = fc.getFileFilter(); - final boolean compressed = flaFilters.contains(selectedFilter); - String path = sf.getAbsolutePath(); - if (path.endsWith(".fla") || path.endsWith(".xfl")) { - path = path.substring(0, path.length() - 4); - } - path += compressed ? ".fla" : ".xfl"; - final FLAVersion selectedVersion = versions.get(compressed ? flaFilters.indexOf(selectedFilter) : xflFilters.indexOf(selectedFilter)); - final File selfile = new File(path); - new CancellableWorker() { - @Override - protected Void doInBackground() throws Exception { - Helper.freeMem(); - try { - AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); - if (compressed) { - swf.exportFla(errorHandler, selfile.getAbsolutePath(), new File(swf.getFile()).getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); - } else { - swf.exportXfl(errorHandler, selfile.getAbsolutePath(), new File(swf.getFile()).getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); - } - } catch (Exception ex) { - logger.log(Level.SEVERE, "FLA export error", ex); - View.showMessageDialog(null, translate("error.export") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage(), translate("error"), JOptionPane.ERROR_MESSAGE); - } - Helper.freeMem(); - return null; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.exporting.fla") + "...", this); - } - - @Override - protected void done() { - if (Configuration.openFolderAfterFlaExport.get()) { - try { - Desktop.getDesktop().open(selfile.getAbsoluteFile().getParentFile()); - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - Main.stopWork(); - } - }.execute(); - } - } - - public void importText(final SWF swf) { - JFileChooser chooser = new JFileChooser(); - chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); - chooser.setDialogTitle(translate("import.select.directory")); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setAcceptAllFileFilterUsed(false); - if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); - File textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_FORMATTED)); - TextImporter textImporter = new TextImporter(getMissingCharacterHandler(), new TextImportErrorHandler() { - - // "configuration items" for the current replace only - private final ConfigurationItem showAgainImportError = new ConfigurationItem<>("showAgainImportError", true, true); - - private final ConfigurationItem showAgainInvalidText = new ConfigurationItem<>("showAgainInvalidText", true, true); - - private String getTextTagInfo(TextTag textTag) { - StringBuilder ret = new StringBuilder(); - if (textTag != null) { - ret.append(" TextId: ").append(textTag.getCharacterId()).append(" (").append(String.join(", ", textTag.getTexts())).append(")"); - } - - return ret.toString(); - } - - @Override - public boolean handle(TextTag textTag) { - String msg = translate("error.text.import"); - logger.log(Level.SEVERE, msg + getTextTagInfo(textTag)); - return View.showConfirmDialog(MainPanel.this, msg, translate("error"), JOptionPane.OK_CANCEL_OPTION, showAgainImportError, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION; - } - - @Override - public boolean handle(TextTag textTag, String message, long line) { - String msg = translate("error.text.invalid.continue").replace("%text%", message).replace("%line%", Long.toString(line)); - logger.log(Level.SEVERE, msg + getTextTagInfo(textTag)); - return View.showConfirmDialog(MainPanel.this, msg, translate("error"), JOptionPane.OK_CANCEL_OPTION, showAgainInvalidText, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION; - } - }); - - // try to import formatted texts - if (textsFile.exists()) { - textImporter.importTextsSingleFileFormatted(textsFile, swf); - } else { - textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_PLAIN)); - // try to import plain texts - if (textsFile.exists()) { - textImporter.importTextsSingleFile(textsFile, swf); - } else { - textImporter.importTextsMultipleFiles(selFile, swf); - } - } - - swf.clearImageCache(); - reload(true); - } - } - - public void importScript(final SWF swf) { - JFileChooser chooser = new JFileChooser(); - chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); - chooser.setDialogTitle(translate("import.select.directory")); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setAcceptAllFileFilterUsed(false); - if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); - String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); - - int countAs2 = new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true)); - int countAs3 = new AS3ScriptImporter().importScripts(scriptsFolder, swf.getAS3Packs()); - - if (countAs3 > 0) { - updateClassesList(); - } - - View.showMessageDialog(this, translate("import.script.result").replace("%count%", Integer.toString(countAs2 + countAs3))); - if (countAs2 != 0 || countAs3 != 0) { - reload(true); - } - } - } - - public void importSymbolClass(final SWF swf) { - JFileChooser chooser = new JFileChooser(); - chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); - chooser.setDialogTitle(translate("import.select.directory")); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setAcceptAllFileFilterUsed(false); - if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); - File importFile = new File(Path.combine(selFile, SymbolClassExporter.SYMBOL_CLASS_EXPORT_FILENAME)); - SymbolClassImporter importer = new SymbolClassImporter(); - - if (importFile.exists()) { - importer.importSymbolClasses(importFile, swf); - } - } - } - - 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; - } - - public void export(final boolean onlySel) { - - final SWF swf = getCurrentSwf(); - List sel = tagTree.getAllSelected(); - if (!onlySel) { - sel = null; - } else if (sel.isEmpty()) { - return; - } - final ExportDialog export = new ExportDialog(sel); - if (export.showExportDialog() == AppDialog.OK_OPTION) { - final String selFile = selectExportDir(); - if (selFile != null) { - final long timeBefore = System.currentTimeMillis(); - - new CancellableWorker() { - @Override - public Void doInBackground() throws Exception { - try { - AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); - if (onlySel) { - exportSelection(errorHandler, selFile, export); - } else { - exportAll(swf, errorHandler, selFile, export); - } - } catch (Exception ex) { - logger.log(Level.SEVERE, "Error during export", ex); - View.showMessageDialog(null, translate("error.export") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage()); - } - return null; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.exporting") + "...", this); - } - - @Override - protected void done() { - Main.stopWork(); - long timeAfter = System.currentTimeMillis(); - final long timeMs = timeAfter - timeBefore; - - View.execInEventDispatchLater(() -> { - setStatus(translate("export.finishedin").replace("%time%", Helper.formatTimeSec(timeMs))); - }); - } - }.execute(); - - } - } - } - - public void exportJavaSource() { - List sel = tagTree.getSelected(); - for (TreeItem item : sel) { - if (item instanceof SWF) { - SWF swf = (SWF) item; - final String selFile = selectExportDir(); - if (selFile != null) { - Main.startWork(translate("work.exporting") + "...", null); - - try { - new SwfJavaExporter().exportJavaCode(swf, selFile); - Main.stopWork(); - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - } - } - } - - public void exportSwfXml() { - List sel = tagTree.getSelected(); - Set swfs = new HashSet<>(); - - for (TreeItem item : sel) { - swfs.add(item.getSwf()); - } - - for (SWF swf : swfs) { - final String selFile = selectExportDir(); - if (selFile != null) { - Main.startWork(translate("work.exporting") + "...", null); - - try { - File outFile = new File(selFile + File.separator + Helper.makeFileName("swf.xml")); - new SwfXmlExporter().exportXml(swf, outFile); - Main.stopWork(); - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - } - } - - public void importSwfXml() { - List sel = tagTree.getSelected(); - Set swfs = new HashSet<>(); - for (TreeItem item : sel) { - swfs.add(item.getSwf()); - } - if (swfs.size() > 1) { - return; - } - - for (SWF swf : swfs) { - File selectedFile = showImportFileChooser("filter.xml|*.xml"); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - String xml = Helper.readTextFile(selfile.getPath()); - try { - new SwfXmlImporter().importSwf(swf, xml); - swf.clearAllCache(); - swf.assignExportNamesToSymbols(); - swf.assignClassesToSymbols(); - refreshTree(swf); - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - } - } - - public void renameIdentifiers(final SWF swf) { - if (swf == null) { - return; - } - if (confirmExperimental()) { - RenameDialog renameDialog = new RenameDialog(); - if (renameDialog.showRenameDialog() == AppDialog.OK_OPTION) { - final RenameType renameType = renameDialog.getRenameType(); - new CancellableWorker() { - @Override - protected Integer doInBackground() throws Exception { - int cnt = swf.deobfuscateIdentifiers(renameType); - return cnt; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.renaming.identifiers") + "...", this); - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - try { - int cnt = get(); - Main.stopWork(); - View.showMessageDialog(null, translate("message.rename.renamed").replace("%count%", Integer.toString(cnt))); - swf.assignClassesToSymbols(); - swf.clearScriptCache(); - if (abcPanel != null) { - abcPanel.reload(); - } - updateClassesList(); - reload(true); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Error during renaming identifiers", ex); - Main.stopWork(); - View.showMessageDialog(null, translate("error.occured").replace("%error%", ex.getClass().getSimpleName())); - } - }); - } - }.execute(); - } - } - } - - public void deobfuscate() { - DeobfuscationDialog deobfuscationDialog = new DeobfuscationDialog(); - if (deobfuscationDialog.showDialog() == AppDialog.OK_OPTION) { - DeobfuscationLevel level = DeobfuscationLevel.getByLevel(deobfuscationDialog.codeProcessingLevel.getValue()); - new CancellableWorker() { - @Override - protected Void doInBackground() throws Exception { - try { - ABCPanel abcPanel = getABCPanel(); - if (deobfuscationDialog.processAllCheckbox.isSelected()) { - SWF swf = abcPanel.getSwf(); - swf.deobfuscate(level); - } else { - int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex(); - DecompiledEditorPane decompiledTextArea = abcPanel.decompiledTextArea; - Trait t = abcPanel.decompiledTextArea.getCurrentTrait(); - ABC abc = abcPanel.abc; - if (bi != -1) { - int scriptIndex = decompiledTextArea.getScriptLeaf().scriptIndex; - int classIndex = decompiledTextArea.getClassIndex(); - boolean isStatic = decompiledTextArea.getIsStatic(); - abc.bodies.get(bi).deobfuscate(level, t, scriptIndex, classIndex, isStatic, ""/*FIXME*/); - } - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(decompiledTextArea.getScriptLeaf().getPathScriptName(), bi, abc, t, abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getScriptIndex()); - } - } catch (Exception ex) { - logger.log(Level.SEVERE, "Deobfuscation error", ex); - } - - return null; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.deobfuscating") + "...", this); - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - Main.stopWork(); - View.showMessageDialog(null, translate("work.deobfuscating.complete")); - - clearAllScriptCache(); - getABCPanel().reload(); - updateClassesList(); - }); - } - }.execute(); - } - } - - public void removeNonScripts(SWF swf) { - if (swf == null) { - return; - } - - List tags = swf.getTags().toArrayList(); - List toRemove = new ArrayList<>(); - for (Tag tag : tags) { - System.out.println(tag.getClass()); - if (!(tag instanceof ABCContainerTag || tag instanceof ASMSource)) { - toRemove.add(tag); - } - } - - swf.removeTags(toRemove, true); - refreshTree(swf); - } - - public void removeExceptSelected(SWF swf) { - if (swf == null) { - return; - } - - List sel = tagTree.getAllSelected(); - Set needed = new HashSet<>(); - for (TreeItem item : sel) { - if (item instanceof CharacterTag) { - CharacterTag characterTag = (CharacterTag) item; - characterTag.getNeededCharactersDeep(needed); - needed.add(characterTag.getCharacterId()); - } - } - - List tagsToRemove = new ArrayList<>(); - for (Tag tag : swf.getTags()) { - if (tag instanceof CharacterTag) { - CharacterTag characterTag = (CharacterTag) tag; - if (!needed.contains(characterTag.getCharacterId())) { - tagsToRemove.add(tag); - } - } - } - - swf.removeTags(tagsToRemove, true); - refreshTree(swf); - } - - private void clear() { - dumpViewPanel.clear(); - previewPanel.clear(); - headerPanel.clear(); - folderPreviewPanel.clear(); - if (abcPanel != null) { - abcPanel.clearSwf(); - } - if (actionPanel != null) { - actionPanel.clearSource(); - } - } - - public void refreshTree() { - refreshTree(new SWF[0]); - } - - public void refreshTree(SWF swf) { - refreshTree(new SWF[]{swf}); - } - - public void refreshTree(SWF[] swfs) { - clear(); - showCard(CARDEMPTYPANEL); - TreeItem treeItem = tagTree.getCurrentTreeItem(); - - tagTree.updateSwfs(swfs); - - if (treeItem != null) { - SWF treeItemSwf = treeItem.getSwf().getRootSwf(); - if (this.swfs.contains(treeItemSwf.swfList)) { - setTagTreeSelectedNode(treeItem); - } - } - - reload(true); - } - - public void refreshDecompiled() { - clearAllScriptCache(); - if (abcPanel != null) { - abcPanel.reload(); - } - - reload(true); - updateClassesList(); - } - - private MissingCharacterHandler getMissingCharacterHandler() { - return new MissingCharacterHandler() { - - // "configuration items" for the current replace only - private final ConfigurationItem showAgainIgnoreMissingCharacters = new ConfigurationItem<>("showAgainIgnoreMissingCharacters", true, true); - - private boolean ignoreMissingCharacters = false; - - @Override - public boolean getIgnoreMissingCharacters() { - return ignoreMissingCharacters; - } - - @Override - public boolean handle(TextTag textTag, final FontTag font, final char character) { - String fontName = font.getSwf().sourceFontNamesMap.get(font.getFontId()); - if (fontName == null) { - fontName = font.getFontName(); - } - final Font f = FontTag.installedFontsByName.get(fontName); - if (f == null || !f.canDisplay(character)) { - String msg = translate("error.font.nocharacter").replace("%char%", "" + character); - logger.log(Level.SEVERE, "{0} FontId: {1} TextId: {2}", new Object[]{msg, font.getCharacterId(), textTag.getCharacterId()}); - ignoreMissingCharacters = View.showConfirmDialog(null, msg, translate("error"), - JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE, - showAgainIgnoreMissingCharacters, - ignoreMissingCharacters ? JOptionPane.OK_OPTION : JOptionPane.CANCEL_OPTION) == JOptionPane.OK_OPTION; - return false; - } - - font.addCharacter(character, f); - - return true; - } - }; - } - - public boolean saveText(TextTag textTag, String formattedText, String[] texts, LineMarkedEditorPane editor) { - try { - if (textTag.setFormattedText(getMissingCharacterHandler(), formattedText, texts)) { - return true; - } - } catch (TextParseException ex) { - if (editor != null) { - editor.gotoLine((int) ex.line); - editor.markError(); - } - - View.showMessageDialog(null, translate("error.text.invalid").replace("%text%", ex.text).replace("%line%", Long.toString(ex.line)), translate("error"), JOptionPane.ERROR_MESSAGE); - } - - return false; - } - - public boolean alignText(TextTag textTag, TextAlign textAlign) { - return (textTag.alignText(textAlign)); - } - - public boolean translateText(TextTag textTag, int diff) { - return textTag.translateText(diff); - } - - public boolean previousTag() { - if (getCurrentView() == VIEW_RESOURCES) { - if (tagTree.getSelectionRows().length > 0) { - int row = tagTree.getSelectionRows()[0]; - if (row > 0) { - tagTree.setSelectionRow(row - 1); - tagTree.scrollRowToVisible(row - 1); - previewPanel.focusTextPanel(); - } - } - return true; - } - return false; - } - - public boolean nextTag() { - if (getCurrentView() == VIEW_RESOURCES) { - if (tagTree.getSelectionRows().length > 0) { - int row = tagTree.getSelectionRows()[0]; - if (row < tagTree.getRowCount() - 1) { - tagTree.setSelectionRow(row + 1); - tagTree.scrollRowToVisible(row + 1); - previewPanel.focusTextPanel(); - } - } - return true; - } - return false; - } - - public void selectBkColorButtonActionPerformed(ActionEvent evt) { - Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectbkcolor.title"), View.getSwfBackgroundColor()); - if (newColor != null) { - View.setSwfBackgroundColor(newColor); - reload(true); - } - } - - public void replaceButtonActionPerformed(ActionEvent evt) { - TreeItem item = tagTree.getCurrentTreeItem(); - if (item == null) { - return; - } - - if (item instanceof DefineSoundTag) { - File selectedFile = showImportFileChooser("filter.sounds|*.mp3;*.wav|filter.sounds.mp3|*.mp3|filter.sounds.wav|*.wav"); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - DefineSoundTag ds = (DefineSoundTag) item; - int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN; - if (selfile.getName().toLowerCase().endsWith(".mp3")) { - soundFormat = SoundFormat.FORMAT_MP3; - } - - boolean ok = false; - try { - ok = ds.setSound(new FileInputStream(selfile), soundFormat); - } catch (IOException ex) { - //ignore - } - - if (!ok) { - View.showMessageDialog(null, translate("error.sound.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); - } else { - reload(true); - } - } - } - if (item instanceof ImageTag) { - ImageTag it = (ImageTag) item; - if (it.importSupported()) { - File selectedFile = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp"); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - byte[] data = Helper.readFile(selfile.getAbsolutePath()); - try { - Tag newTag = new ImageImporter().importImage(it, data); - SWF swf = it.getSwf(); - if (newTag != null) { - refreshTree(swf); - setTagTreeSelectedNode(newTag); - } - swf.clearImageCache(); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Invalid image", ex); - View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); - } - - reload(true); - } - } - } - if (item instanceof ShapeTag) { - ShapeTag st = (ShapeTag) item; - String filter = "filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg"; - File selectedFile = showImportFileChooser(filter); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - byte[] data = null; - String svgText = null; - if (".svg".equals(Path.getExtension(selfile))) { - svgText = Helper.readTextFile(selfile.getAbsolutePath()); - showSvgImportWarning(); - } else { - data = Helper.readFile(selfile.getAbsolutePath()); - } - try { - Tag newTag = svgText != null ? new SvgImporter().importSvg(st, svgText) : new ShapeImporter().importImage(st, data); - SWF swf = st.getSwf(); - if (newTag != null) { - refreshTree(swf); - setTagTreeSelectedNode(newTag); - } - - swf.clearImageCache(); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Invalid image", ex); - View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); - } - reload(true); - } - } - if (item instanceof DefineBinaryDataTag) { - DefineBinaryDataTag bt = (DefineBinaryDataTag) item; - File selectedFile = showImportFileChooser(""); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - byte[] data = Helper.readFile(selfile.getAbsolutePath()); - new BinaryDataImporter().importData(bt, data); - refreshTree(bt.getSwf()); - reload(true); - } - } - } - - public void replaceNoFillButtonActionPerformed(ActionEvent evt) { - TreeItem item = tagTree.getCurrentTreeItem(); - if (item == null) { - return; - } - - if (item instanceof ShapeTag) { - ShapeTag st = (ShapeTag) item; - String filter = "filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg"; - File selectedFile = showImportFileChooser(filter); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - byte[] data = null; - String svgText = null; - if (".svg".equals(Path.getExtension(selfile))) { - svgText = Helper.readTextFile(selfile.getAbsolutePath()); - showSvgImportWarning(); - } else { - data = Helper.readFile(selfile.getAbsolutePath()); - } - try { - Tag newTag = svgText != null ? new SvgImporter().importSvg(st, svgText, false) : new ShapeImporter().importImage(st, data, 0, false); - SWF swf = st.getSwf(); - if (newTag != null) { - refreshTree(swf); - setTagTreeSelectedNode(newTag); - } - - swf.clearImageCache(); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Invalid image", ex); - View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); - } - reload(true); - } - } - } - - private void showSvgImportWarning() { - View.showMessageDialog(null, AppStrings.translate("message.warning.svgImportExperimental"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE, Configuration.warningSvgImport); - } - - public void replaceAlphaButtonActionPerformed(ActionEvent evt) { - TreeItem item = tagTree.getCurrentTreeItem(); - if (item == null) { - return; - } - - if (item instanceof DefineBitsJPEG3Tag || item instanceof DefineBitsJPEG4Tag) { - ImageTag it = (ImageTag) item; - if (it.importSupported()) { - File selectedFile = showImportFileChooser(""); - if (selectedFile != null) { - File selfile = Helper.fixDialogFile(selectedFile); - byte[] data = Helper.readFile(selfile.getAbsolutePath()); - try { - new ImageImporter().importImageAlpha(it, data); - SWF swf = it.getSwf(); - swf.clearImageCache(); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Invalid alpha channel data", ex); - View.showMessageDialog(null, translate("error.image.alpha.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); - } - - reload(true); - } - } - } - } - - public void exportJavaSourceActionPerformed(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - exportJavaSource(); - } - - public void exportSwfXmlActionPerformed(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - exportSwfXml(); - } - - public void importSwfXmlActionPerformed(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - importSwfXml(); - } - - public void exportSelectionActionPerformed(ActionEvent evt) { - if (Main.isWorking()) { - return; - } - - export(true); - } - - public File showImportFileChooser(String filter) { - String[] filterArray = filter.length() > 0 ? filter.split("\\|") : new String[0]; - - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - boolean first = true; - for (int i = 0; i < filterArray.length; i += 2) { - final String filterName = filterArray[i]; - final String[] extensions = filterArray[i + 1].split(";"); - for (int j = 0; j < extensions.length; j++) { - if (extensions[j].startsWith("*.")) { - extensions[j] = extensions[j].substring(1); - } - } - FileFilter ff = new FileFilter() { - - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - String fileName = f.getName().toLowerCase(); - for (String ext : extensions) { - if (fileName.endsWith(ext)) { - return true; - } - } - return false; - } - - @Override - public String getDescription() { - StringBuilder extStr = new StringBuilder(); - boolean first = true; - for (String ext : extensions) { - if (first) { - first = false; - } else { - extStr.append(","); - } - - extStr.append("*").append(ext); - } - - return translate(filterName).replace("%extensions%", extStr); - } - }; - if (first) { - fc.setFileFilter(ff); - } else { - fc.addChoosableFileFilter(ff); - } - first = false; - } - - JFrame f = new JFrame(); - View.setWindowIcon(f); - if (fc.showOpenDialog(f) == JFileChooser.APPROVE_OPTION) { - File result = fc.getSelectedFile(); - Configuration.lastOpenDir.set(Helper.fixDialogFile(result).getParentFile().getAbsolutePath()); - return result; - } - - return null; - } - - private void showDetail(String card) { - CardLayout cl = (CardLayout) (detailPanel.getLayout()); - cl.show(detailPanel, card); - if (card.equals(DETAILCARDEMPTYPANEL)) { - if (detailPanel.isVisible()) { - detailPanel.setVisible(false); - } - } else if (!detailPanel.isVisible()) { - detailPanel.setVisible(true); - } - } - - private void showCard(String card) { - CardLayout cl = (CardLayout) (displayPanel.getLayout()); - cl.show(displayPanel, card); - } - - @Override - public void valueChanged(TreeSelectionEvent e) { - Object source = e.getSource(); - TreeItem treeItem = (TreeItem) e.getPath().getLastPathComponent(); - - if (!(treeItem instanceof SWFList)) { - SWF swf = treeItem.getSwf(); - if (swfs.isEmpty()) { - // show welcome panel after closing swfs - updateUi(); - } else { - if (swf == null) { - swf = swfs.get(0).get(0); - } - - updateUi(swf); - } - } else { - updateUi(); - } - - reload(false); - - if (source == dumpTree) { - Tag t = null; - if (treeItem instanceof DumpInfo) { - DumpInfo di = (DumpInfo) treeItem; - t = di.getTag(); - } - - showPreview(t, dumpPreviewPanel); - } - } - - public void unloadFlashPlayer() { - if (flashPanel != null) { - try { - flashPanel.close(); - } catch (IOException ex) { - // ignore - } - } - if (flashPanel2 != null) { - try { - flashPanel2.close(); - } catch (IOException ex) { - // ignore - } - } - } - - public void clearDebuggerColors() { - if (abcPanel != null) { - abcPanel.decompiledTextArea.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.clearDebuggerColors(); - } - if (actionPanel != null) { - actionPanel.decompiledEditor.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); - actionPanel.editor.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); - } - } - - private void stopFlashPlayer() { - if (flashPanel != null) { - if (!flashPanel.isStopped()) { - flashPanel.stopSWF(); - } - } - if (flashPanel2 != null) { - if (!flashPanel2.isStopped()) { - flashPanel2.stopSWF(); - } - } - } - - public boolean isInternalFlashViewerSelected() { - return mainMenu.isInternalFlashViewerSelected(); - } - - public static final int VIEW_RESOURCES = 0; - - public static final int VIEW_DUMP = 1; - - public static final int VIEW_TIMELINE = 2; - - private int getCurrentView() { - return Configuration.dumpView.get() ? VIEW_DUMP : VIEW_RESOURCES; - } - - public void setTreeModel(int view) { - switch (view) { - case VIEW_DUMP: - if (dumpTree.getModel() == null) { - DumpTreeModel dtm = new DumpTreeModel(swfs); - dumpTree.setModel(dtm); - dumpTree.expandFirstLevelNodes(); - } - break; - case VIEW_RESOURCES: - if (tagTree.getModel() == null) { - TagTreeModel ttm = new TagTreeModel(swfs, Configuration.tagTreeShowEmptyFolders.get()); - tagTree.setModel(ttm); - tagTree.expandFirstLevelNodes(); - } - break; - } - } - - private JPanel createDumpViewCard() { - JPanel r = new JPanel(new BorderLayout()); - r.add(new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(dumpTree), dumpPreviewPanel, Configuration.guiDumpSplitPaneDividerLocationPercent), BorderLayout.CENTER); - return r; - } - - private JPanel createResourcesViewCard() { - JPanel r = new JPanel(new BorderLayout()); - r.add(new JScrollPane(tagTree), BorderLayout.CENTER); - r.add(searchPanel, BorderLayout.SOUTH); - return r; - } - - public boolean showView(int view) { - - CardLayout cl = (CardLayout) (contentPanel.getLayout()); - CardLayout cl2 = (CardLayout) (treePanel.getLayout()); - - setTreeModel(view); - switch (view) { - case VIEW_DUMP: - if (!isWelcomeScreen) { - cl.show(contentPanel, SPLIT_PANE1); - } - cl2.show(treePanel, DUMP_VIEW); - treePanelMode = TreePanelMode.DUMP_TREE; - showDetail(DETAILCARDEMPTYPANEL); - reload(true); - return true; - case VIEW_RESOURCES: - if (!isWelcomeScreen) { - cl.show(contentPanel, SPLIT_PANE1); - } - cl2.show(treePanel, RESOURCES_VIEW); - - treePanelMode = TreePanelMode.TAG_TREE; - - treePanel.addComponentListener(new ComponentAdapter() { - - @Override - public void componentResized(ComponentEvent e) { - tagTree.scrollPathToVisible(tagTree.getSelectionPath()); - } - - }); - - reload(true); - return true; - case VIEW_TIMELINE: - final SWF swf = getCurrentSwf(); - if (swf != null) { - TreeItem item = tagTree.getCurrentTreeItem(); - if (item instanceof TagScript) { - item = ((TagScript) item).getTag(); - } - if (item instanceof Timelined) { - timelineViewPanel.setTimelined((Timelined) item); - } else if (item instanceof Frame) { - timelineViewPanel.setTimelined(((Frame) item).timeline.timelined); - } else { - timelineViewPanel.setTimelined(swf); - } - cl.show(contentPanel, TIMELINE_PANEL); - return true; - } - return false; - } - return false; - - } - - private void dumpViewReload(boolean forceReload) { - showDetail(DETAILCARDEMPTYPANEL); - - DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent(); - if (dumpInfo == null) { - showCard(CARDEMPTYPANEL); - return; - } - - dumpViewPanel.revalidate(); - dumpViewPanel.setSelectedNode(dumpInfo); - showCard(CARDDUMPVIEW); - } - - public void loadFromBinaryTag(final DefineBinaryDataTag binaryDataTag) { - loadFromBinaryTag(Arrays.asList(binaryDataTag)); - } - - public void loadFromBinaryTag(final List binaryDataTags) { - - Main.loadingDialog.setVisible(true); - new CancellableWorker() { - - @Override - protected Void doInBackground() throws Exception { - try { - for (DefineBinaryDataTag binaryDataTag : binaryDataTags) { - try { - InputStream is = new ByteArrayInputStream(binaryDataTag.binaryData.getRangeData()); - SWF bswf = new SWF(is, null, "(SWF Data)", new ProgressListener() { - - @Override - public void progress(int p) { - Main.loadingDialog.setPercent(p); - } - }, Configuration.parallelSpeedUp.get()); - binaryDataTag.innerSwf = bswf; - bswf.binaryData = binaryDataTag; - } catch (IOException ex) { - //ignore - } - } - } catch (InterruptedException ex) { - //ignore - } - - return null; - } - - @Override - protected void onStart() { - Main.startWork(AppStrings.translate("work.reading.swf") + "...", this); - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - Main.loadingDialog.setVisible(false); - Main.stopWork(); - }); - } - }.execute(); - } - - private void closeTag() { - previewPanel.closeTag(); - } - - public void showPreview(TreeItem treeItem, PreviewPanel previewPanel) { - previewPanel.clear(); - if (treeItem == null) { - previewPanel.showEmpty(); - return; - } - boolean internalViewer = isInternalFlashViewerSelected(); - if (treeItem instanceof SWF) { - SWF swf = (SWF) treeItem; - if (internalViewer) { - previewPanel.showImagePanel(swf, swf, -1); - } else { - previewPanel.setParametersPanelVisible(false); - if (flashPanel != null) { //same for flashPanel2 - previewPanel.showFlashViewerPanel(); - previewPanel.showSwf(swf); - } - } - } else if (treeItem instanceof MetadataTag) { - MetadataTag metadataTag = (MetadataTag) treeItem; - previewPanel.showMetaDataPanel(metadataTag); - } else if (treeItem instanceof DefineBinaryDataTag) { - DefineBinaryDataTag binaryTag = (DefineBinaryDataTag) treeItem; - previewPanel.showBinaryPanel(binaryTag); - } else if (treeItem instanceof ImageTag) { - ImageTag imageTag = (ImageTag) treeItem; - previewPanel.setImageReplaceButtonVisible(!((Tag) imageTag).isReadOnly() && imageTag.importSupported(), imageTag instanceof DefineBitsJPEG3Tag || imageTag instanceof DefineBitsJPEG4Tag); - previewPanel.showImagePanel(imageTag.getImageCached()); - - } else if ((treeItem instanceof DrawableTag) && (!(treeItem instanceof TextTag)) && (!(treeItem instanceof FontTag)) && internalViewer) { - final Tag tag = (Tag) treeItem; - DrawableTag d = (DrawableTag) tag; - Timelined timelined; - if (treeItem instanceof Timelined && !(treeItem instanceof ButtonTag)) { - timelined = (Timelined) tag; - } else { - timelined = makeTimelined(tag); - } - - previewPanel.setParametersPanelVisible(false); - previewPanel.showImagePanel(timelined, tag.getSwf(), -1); - } else if (treeItem instanceof Frame && internalViewer) { - Frame fn = (Frame) treeItem; - SWF swf = fn.getSwf(); - previewPanel.showImagePanel(fn.timeline.timelined, swf, fn.frame); - } else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) { - previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32"))); - previewPanel.setImageReplaceButtonVisible(((Tag) treeItem).isReadOnly() && (treeItem instanceof DefineSoundTag), false); - try { - SoundTagPlayer soundThread = new SoundTagPlayer((SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true); - previewPanel.setMedia(soundThread); - } catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) { - logger.log(Level.SEVERE, null, ex); - } - - } else if ((treeItem instanceof FontTag) && internalViewer) { - previewPanel.showFontPanel((FontTag) treeItem); - } else if ((treeItem instanceof TextTag) && internalViewer) { - previewPanel.showTextPanel((TextTag) treeItem); - } else if ((treeItem instanceof Frame) || (treeItem instanceof CharacterTag) || (treeItem instanceof FontTag) || (treeItem instanceof SoundStreamHeadTypeTag)) { - previewPanel.createAndShowTempSwf(treeItem); - - if (treeItem instanceof TextTag) { - previewPanel.showTextPanel((TextTag) treeItem); - } else if (treeItem instanceof FontTag) { - previewPanel.showFontPanel((FontTag) treeItem); - } else { - previewPanel.setParametersPanelVisible(false); - } - } else { - previewPanel.showEmpty(); - } - } - - public void reload(boolean forceReload) { - tagTree.scrollPathToVisible(tagTree.getSelectionPath()); - if (Configuration.dumpView.get()) { - dumpViewReload(forceReload); - return; - } - - TreeItem treeItem = null; - TreePath treePath = tagTree.getSelectionPath(); - if (treePath != null && tagTree.getModel().treePathExists(treePath)) { - treeItem = (TreeItem) treePath.getLastPathComponent(); - } - - // save last selected node to config - if (treeItem != null) { - SWF swf = treeItem.getSwf(); - if (swf != null) { - swf = swf.getRootSwf(); - } - - if (swf != null) { - SwfSpecificConfiguration swfConf = Configuration.getOrCreateSwfSpecificConfiguration(swf.getShortFileName()); - swfConf.lastSelectedPath = tagTree.getSelectionPathString(); - } - } - - if (!forceReload && (treeItem == oldItem)) { - return; - } - - if (oldItem != treeItem) { - closeTag(); - } - - oldItem = treeItem; - - // show the preview of the tag when the user clicks to the tagname inside the scripts node, too - // this is a little bit inconsistent, beacuse the frames (FrameScript) are not shown - boolean preferScript = false; - if (treeItem instanceof TagScript) { - treeItem = ((TagScript) treeItem).getTag(); - preferScript = true; - } - - folderPreviewPanel.clear(); - previewPanel.clear(); - stopFlashPlayer(); - - previewPanel.setImageReplaceButtonVisible(false, false); - - boolean internalViewer = isInternalFlashViewerSelected(); - - if (treeItem instanceof ScriptPack) { - final ScriptPack scriptLeaf = (ScriptPack) treeItem; - if (setSourceWorker != null) { - setSourceWorker.cancel(true); - setSourceWorker = null; - } - if (!Main.isInited() || !Main.isWorking() || Main.isDebugging()) { - CancellableWorker worker = new CancellableWorker() { - - @Override - protected Void doInBackground() throws Exception { - ABCPanel abcPanel = getABCPanel(); - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.clear(); - abcPanel.setAbc(scriptLeaf.abc); - abcPanel.decompiledTextArea.setScript(scriptLeaf, true); - abcPanel.decompiledTextArea.setNoTrait(); - return null; - } - - @Override - protected void onStart() { - Main.startWork(translate("work.decompiling") + "...", this); - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - setSourceWorker = null; - try { - get(); - } catch (CancellationException ex) { - getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("work.canceled")); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Error", ex); - getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("decompilationError") + ": " + ex); - } - - Main.stopWork(); - }); - } - }; - - worker.execute(); - setSourceWorker = worker; - } - - showDetail(DETAILCARDAS3NAVIGATOR); - showCard(CARDACTIONSCRIPT3PANEL); - return; - } - - if (treeItem instanceof Tag) { - Tag tag = (Tag) treeItem; - TagInfo tagInfo = new TagInfo(); - tag.getTagInfo(tagInfo); - if (!tagInfo.isEmpty()) { - tagInfoPanel.setTagInfos(tagInfo); - showDetail(DETAILCARDTAGINFO); - } else { - showDetail(DETAILCARDEMPTYPANEL); - } - } else { - showDetail(DETAILCARDEMPTYPANEL); - } - - if (treeItem instanceof HeaderItem) { - headerPanel.load(((HeaderItem) treeItem).getSwf()); - showCard(CARDHEADER); - } else if (treeItem instanceof FolderItem) { - showFolderPreview((FolderItem) treeItem); - } else if (treeItem instanceof SWF) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if (treeItem instanceof MetadataTag) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if (treeItem instanceof DefineBinaryDataTag) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if (treeItem instanceof ASMSource && (!(treeItem instanceof DrawableTag) || preferScript)) { - getActionPanel().setSource((ASMSource) treeItem, !forceReload); - showCard(CARDACTIONSCRIPTPANEL); - } else if (treeItem instanceof ImageTag) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if ((treeItem instanceof DrawableTag) && (!(treeItem instanceof TextTag)) && (!(treeItem instanceof FontTag)) && internalViewer) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if ((treeItem instanceof FontTag) && internalViewer) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if ((treeItem instanceof TextTag) && internalViewer) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if (treeItem instanceof Frame && internalViewer) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) { - showPreview(treeItem, previewPanel); - showCard(CARDPREVIEWPANEL); - } else if ((treeItem instanceof Frame) || (treeItem instanceof CharacterTag) || (treeItem instanceof FontTag) || (treeItem instanceof SoundStreamHeadTypeTag)) { - showPreview(treeItem, previewPanel); - - showCard(CARDPREVIEWPANEL); - } else if (treeItem instanceof Tag) { - showGenericTag((Tag) treeItem); - } else { - showCard(CARDEMPTYPANEL); - } - } - - public void repaintTree() { - tagTree.repaint(); - reload(true); - } - - public void showGenericTag(Tag tag) { - previewPanel.showGenericTagPanel(tag); - showCard(CARDPREVIEWPANEL); - } - - public void showTextTagWithNewValue(TextTag textTag, TextTag newTextTag) { - - previewPanel.showTextComparePanel(textTag, newTextTag); - } - - private void showFolderPreview(FolderItem item) { - List folderPreviewItems = new ArrayList<>(); - String folderName = item.getName(); - SWF swf = item.swf; - switch (folderName) { - case TagTreeModel.FOLDER_SHAPES: - for (Tag tag : swf.getTags()) { - if (tag instanceof ShapeTag) { - folderPreviewItems.add(tag); - } - } - break; - case TagTreeModel.FOLDER_MORPHSHAPES: - for (Tag tag : swf.getTags()) { - if (tag instanceof MorphShapeTag) { - folderPreviewItems.add(tag); - } - } - break; - case TagTreeModel.FOLDER_SPRITES: - for (Tag tag : swf.getTags()) { - if (tag instanceof DefineSpriteTag) { - folderPreviewItems.add(tag); - } - } - break; - case TagTreeModel.FOLDER_BUTTONS: - for (Tag tag : swf.getTags()) { - if (tag instanceof ButtonTag) { - folderPreviewItems.add(tag); - } - } - break; - case TagTreeModel.FOLDER_FONTS: - for (Tag tag : swf.getTags()) { - if (tag instanceof FontTag) { - folderPreviewItems.add(tag); - } - } - break; - case TagTreeModel.FOLDER_FRAMES: - for (Frame frame : swf.getTimeline().getFrames()) { - folderPreviewItems.add(frame); - } - break; - case TagTreeModel.FOLDER_IMAGES: - for (Tag tag : swf.getTags()) { - if (tag instanceof ImageTag) { - folderPreviewItems.add(tag); - } - } - break; - case TagTreeModel.FOLDER_TEXTS: - for (Tag tag : swf.getTags()) { - if (tag instanceof TextTag) { - folderPreviewItems.add(tag); - } - } - break; - } - - folderPreviewPanel.setItems(folderPreviewItems); - showCard(CARDFOLDERPREVIEWPANEL); - } - - private boolean isFreeing; - - @Override - public boolean isFreeing() { - return isFreeing; - } - - @Override - public void free() { - isFreeing = true; - } - - public void setErrorState(ErrorState errorState) { - statusPanel.setErrorState(errorState); - } - - public static Timelined makeTimelined(final Tag tag) { - return makeTimelined(tag, -1); - } - - public static Timelined makeTimelined(final Tag tag, final int fontFrameNum) { - - return new Timelined() { - - private Timeline tim; - - @Override - public Timeline getTimeline() { - if (tim == null) { - Timeline timeline = new Timeline(tag.getSwf(), this, ((CharacterTag) tag).getCharacterId(), getRect()); - initTimeline(timeline); - tim = timeline; - } - - return tim; - } - - @Override - public void resetTimeline() { - if (tim != null) { - tim.reset(tag.getSwf(), this, ((CharacterTag) tag).getCharacterId(), getRect()); - initTimeline(tim); - } - } - - private void initTimeline(Timeline timeline) { - if (tag instanceof MorphShapeTag) { - timeline.frameRate = MORPH_SHAPE_ANIMATION_FRAME_RATE; - int framesCnt = (int) (timeline.frameRate * MORPH_SHAPE_ANIMATION_LENGTH); - for (int i = 0; i < framesCnt; i++) { - Frame f = new Frame(timeline, i); - DepthState ds = new DepthState(tag.getSwf(), f); - ds.characterId = ((CharacterTag) tag).getCharacterId(); - ds.matrix = new MATRIX(); - ds.ratio = i * 65535 / framesCnt; - f.layers.put(1, ds); - f.layersChanged = true; - timeline.addFrame(f); - } - } else if (tag instanceof FontTag) { - int pageCount = PreviewPanel.getFontPageCount((FontTag) tag); - int frame = fontFrameNum; - if (frame < 0 || frame >= pageCount) { - frame = 0; - } - - Frame f = new Frame(timeline, 0); - DepthState ds = new DepthState(tag.getSwf(), f); - ds.characterId = ((CharacterTag) tag).getCharacterId(); - ds.matrix = new MATRIX(); - f.layers.put(1, ds); - f.layersChanged = true; - timeline.addFrame(f); - timeline.fontFrameNum = frame; - } else { - Frame f = new Frame(timeline, 0); - DepthState ds = new DepthState(tag.getSwf(), f); - ds.characterId = ((CharacterTag) tag).getCharacterId(); - ds.matrix = new MATRIX(); - f.layers.put(1, ds); - timeline.addFrame(f); - } - timeline.displayRect = getRect(); - } - - @Override - public RECT getRect() { - return getRect(new HashSet<>()); - } - - @Override - public RECT getRect(Set added) { - BoundedTag bt = (BoundedTag) tag; - if (!added.contains(bt)) { - return bt.getRect(added); - } - return new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE); - } - - @Override - public int hashCode() { - return tag.hashCode(); - } - - @Override - public void setModified(boolean value) { - } - - @Override - public ReadOnlyTagList getTags() { - return ReadOnlyTagList.EMPTY; - } - - @Override - public void removeTag(int index) { - } - - @Override - public void removeTag(Tag tag) { - } - - @Override - public void addTag(Tag tag) { - } - - @Override - public void addTag(int index, Tag tag) { - } - }; - } - - private void disposeInner(Container container) { - for (Component c : container.getComponents()) { - if (c instanceof Container) { - Container c2 = (Container) c; - disposeInner(c2); - } - } - - container.removeAll(); - container.setLayout(null); - if (container instanceof TagEditorPanel) { - Helper.emptyObject(container); - } - } - - public void dispose() { - setDropTarget(null); - disposeInner(this); - Helper.emptyObject(this); - } -} +/* + * Copyright (C) 2010-2016 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.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.ApplicationInfo; +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.ReadOnlyTagList; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFBundle; +import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.RenameType; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.ConfigurationItem; +import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; +import com.jpexs.decompiler.flash.dumpview.DumpInfo; +import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode; +import com.jpexs.decompiler.flash.exporters.BinaryDataExporter; +import com.jpexs.decompiler.flash.exporters.FontExporter; +import com.jpexs.decompiler.flash.exporters.FrameExporter; +import com.jpexs.decompiler.flash.exporters.ImageExporter; +import com.jpexs.decompiler.flash.exporters.MorphShapeExporter; +import com.jpexs.decompiler.flash.exporters.MovieExporter; +import com.jpexs.decompiler.flash.exporters.ShapeExporter; +import com.jpexs.decompiler.flash.exporters.SoundExporter; +import com.jpexs.decompiler.flash.exporters.SymbolClassExporter; +import com.jpexs.decompiler.flash.exporters.TextExporter; +import com.jpexs.decompiler.flash.exporters.modes.BinaryDataExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ButtonExportMode; +import com.jpexs.decompiler.flash.exporters.modes.FontExportMode; +import com.jpexs.decompiler.flash.exporters.modes.FrameExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode; +import com.jpexs.decompiler.flash.exporters.modes.MorphShapeExportMode; +import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; +import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode; +import com.jpexs.decompiler.flash.exporters.modes.SpriteExportMode; +import com.jpexs.decompiler.flash.exporters.modes.SymbolClassExportMode; +import com.jpexs.decompiler.flash.exporters.modes.TextExportMode; +import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter; +import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter; +import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.ButtonExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.FrameExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.MorphShapeExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.MovieExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.SpriteExportSettings; +import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings; +import com.jpexs.decompiler.flash.exporters.swf.SwfJavaExporter; +import com.jpexs.decompiler.flash.exporters.swf.SwfXmlExporter; +import com.jpexs.decompiler.flash.gui.abc.ABCPanel; +import com.jpexs.decompiler.flash.gui.abc.ABCPanelSearchResult; +import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel; +import com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane; +import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog; +import com.jpexs.decompiler.flash.gui.action.ActionPanel; +import com.jpexs.decompiler.flash.gui.action.ActionSearchResult; +import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; +import com.jpexs.decompiler.flash.gui.dumpview.DumpTree; +import com.jpexs.decompiler.flash.gui.dumpview.DumpTreeModel; +import com.jpexs.decompiler.flash.gui.dumpview.DumpViewPanel; +import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane; +import com.jpexs.decompiler.flash.gui.helpers.ObservableList; +import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; +import com.jpexs.decompiler.flash.gui.tagtree.TagTree; +import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel; +import com.jpexs.decompiler.flash.gui.timeline.TimelineViewPanel; +import com.jpexs.decompiler.flash.helpers.FileTextWriter; +import com.jpexs.decompiler.flash.helpers.Freed; +import com.jpexs.decompiler.flash.importers.AS2ScriptImporter; +import com.jpexs.decompiler.flash.importers.AS3ScriptImporter; +import com.jpexs.decompiler.flash.importers.BinaryDataImporter; +import com.jpexs.decompiler.flash.importers.ImageImporter; +import com.jpexs.decompiler.flash.importers.ShapeImporter; +import com.jpexs.decompiler.flash.importers.SwfXmlImporter; +import com.jpexs.decompiler.flash.importers.SymbolClassImporter; +import com.jpexs.decompiler.flash.importers.TextImporter; +import com.jpexs.decompiler.flash.importers.svg.SvgImporter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; +import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; +import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; +import com.jpexs.decompiler.flash.tags.DefineSoundTag; +import com.jpexs.decompiler.flash.tags.DefineSpriteTag; +import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.DoInitActionTag; +import com.jpexs.decompiler.flash.tags.FileAttributesTag; +import com.jpexs.decompiler.flash.tags.MetadataTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagInfo; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.ButtonTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler; +import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; +import com.jpexs.decompiler.flash.tags.base.ShapeTag; +import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; +import com.jpexs.decompiler.flash.tags.base.SoundTag; +import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag; +import com.jpexs.decompiler.flash.tags.base.TextImportErrorHandler; +import com.jpexs.decompiler.flash.tags.base.TextTag; +import com.jpexs.decompiler.flash.tags.text.TextAlign; +import com.jpexs.decompiler.flash.tags.text.TextParseException; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Frame; +import com.jpexs.decompiler.flash.timeline.TagScript; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.treeitems.FolderItem; +import com.jpexs.decompiler.flash.treeitems.HeaderItem; +import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.TreeItem; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import com.jpexs.decompiler.flash.xfl.FLAVersion; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Path; +import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.SerializableImage; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Desktop; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.JColorChooser; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.filechooser.FileFilter; +import javax.swing.plaf.basic.BasicTreeUI; +import javax.swing.tree.DefaultTreeSelectionModel; +import javax.swing.tree.TreePath; +import jsyntaxpane.DefaultSyntaxKit; + +/** + * + * @author JPEXS + */ +public final class MainPanel extends JPanel implements TreeSelectionListener, SearchListener, Freed { + + private final MainFrame mainFrame; + + private final ObservableList swfs; + + private final JPanel welcomePanel; + + private final TimelineViewPanel timelineViewPanel; + + private final MainFrameStatusPanel statusPanel; + + private final MainFrameMenu mainMenu; + + private final JProgressBar progressBar = new JProgressBar(0, 100); + + public TagTree tagTree; + + public DumpTree dumpTree; + + private final FlashPlayerPanel flashPanel; + + private final FlashPlayerPanel flashPanel2; + + private final JPanel contentPanel; + + private final JPanel displayPanel; + + public FolderPreviewPanel folderPreviewPanel; + + private boolean isWelcomeScreen = true; + + private static final String CARDPREVIEWPANEL = "Preview card"; + + private static final String CARDFOLDERPREVIEWPANEL = "Folder preview card"; + + private static final String CARDEMPTYPANEL = "Empty card"; + + private static final String CARDDUMPVIEW = "Dump view"; + + private static final String CARDACTIONSCRIPTPANEL = "ActionScript card"; + + private static final String CARDACTIONSCRIPT3PANEL = "ActionScript3 card"; + + private static final String CARDHEADER = "Header card"; + + private static final String DETAILCARDAS3NAVIGATOR = "Traits list"; + + private static final String DETAILCARDTAGINFO = "Tag information"; + + private static final String DETAILCARDEMPTYPANEL = "Empty card"; + + private static final String SPLIT_PANE1 = "SPLITPANE1"; + + private static final String WELCOME_PANEL = "WELCOMEPANEL"; + + private static final String TIMELINE_PANEL = "TIMELINEPANEL"; + + private static final String RESOURCES_VIEW = "RESOURCES"; + + private static final String DUMP_VIEW = "DUMP"; + + private static final String TIMELINE_VIEW = "TIMELINE"; + + private final JPersistentSplitPane splitPane1; + + private final JPersistentSplitPane splitPane2; + + private JPanel detailPanel; + + private JTextField filterField = new MyTextField(""); + + private JPanel searchPanel; + + private ABCPanel abcPanel; + + private ActionPanel actionPanel; + + private final PreviewPanel previewPanel; + + private final HeaderInfoPanel headerPanel; + + private DumpViewPanel dumpViewPanel; + + private final JPanel treePanel; + + private final PreviewPanel dumpPreviewPanel; + + private final TagInfoPanel tagInfoPanel; + + private TreePanelMode treePanelMode; + + private CancellableWorker setSourceWorker; + + public TreeItem oldItem; + + // play morph shape in 2 second(s) + public static final int MORPH_SHAPE_ANIMATION_LENGTH = 2; + + public static final int MORPH_SHAPE_ANIMATION_FRAME_RATE = 30; + + private static final Logger logger = Logger.getLogger(MainPanel.class.getName()); + + public void setPercent(int percent) { + progressBar.setValue(percent); + progressBar.setVisible(true); + } + + public void hidePercent() { + if (progressBar.isVisible()) { + progressBar.setVisible(false); + } + } + + public MainFrame getMainFrame() { + return mainFrame; + } + + static { + try { + File.createTempFile("temp", ".swf").delete(); //First call to this is slow, so make it first + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + public void updateMenu() { + mainMenu.updateComponents(); + } + + private static void addTab(JTabbedPane tabbedPane, Component tab, String title, Icon icon) { + tabbedPane.add(tab); + + JLabel lbl = new JLabel(title); + lbl.setIcon(icon); + lbl.setIconTextGap(5); + lbl.setHorizontalTextPosition(SwingConstants.RIGHT); + + tabbedPane.setTabComponentAt(tabbedPane.getTabCount() - 1, lbl); + } + + public void setStatus(String s) { + statusPanel.setStatus(s); + } + + public void setWorkStatus(String s, CancellableWorker worker) { + statusPanel.setWorkStatus(s, worker); + mainMenu.updateComponents(); + } + + private JPanel createWelcomePanel() { + JPanel welcomePanel = new JPanel(); + welcomePanel.setLayout(new BoxLayout(welcomePanel, BoxLayout.Y_AXIS)); + JLabel welcomeToLabel = new JLabel(translate("startup.welcometo")); + welcomeToLabel.setFont(welcomeToLabel.getFont().deriveFont(40)); + welcomeToLabel.setAlignmentX(0.5f); + JPanel appNamePanel = new JPanel(new FlowLayout()); + JLabel jpLabel = new JLabel("JPEXS "); + jpLabel.setAlignmentX(0.5f); + jpLabel.setForeground(new Color(0, 0, 160)); + jpLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); + jpLabel.setHorizontalAlignment(SwingConstants.CENTER); + appNamePanel.add(jpLabel); + + JLabel ffLabel = new JLabel("Free Flash "); + ffLabel.setAlignmentX(0.5f); + ffLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); + ffLabel.setHorizontalAlignment(SwingConstants.CENTER); + appNamePanel.add(ffLabel); + + JLabel decLabel = new JLabel("Decompiler"); + decLabel.setAlignmentX(0.5f); + decLabel.setForeground(Color.red); + decLabel.setFont(new Font("Tahoma", Font.BOLD, 50)); + decLabel.setHorizontalAlignment(SwingConstants.CENTER); + appNamePanel.add(decLabel); + appNamePanel.setAlignmentX(0.5f); + welcomePanel.add(Box.createGlue()); + welcomePanel.add(welcomeToLabel); + welcomePanel.add(appNamePanel); + JLabel startLabel = new JLabel(translate("startup.selectopen")); + startLabel.setAlignmentX(0.5f); + startLabel.setFont(startLabel.getFont().deriveFont(30)); + welcomePanel.add(startLabel); + welcomePanel.add(Box.createGlue()); + return welcomePanel; + } + + private JPanel createFolderPreviewCard() { + JPanel folderPreviewCard = new JPanel(new BorderLayout()); + folderPreviewPanel = new FolderPreviewPanel(this, new ArrayList<>()); + folderPreviewCard.add(new JScrollPane(folderPreviewPanel), BorderLayout.CENTER); + + return folderPreviewCard; + } + + private JPanel createDumpPreviewCard() { + JPanel dumpViewCard = new JPanel(new BorderLayout()); + dumpViewPanel = new DumpViewPanel(dumpTree); + dumpViewCard.add(new JScrollPane(dumpViewPanel), BorderLayout.CENTER); + + return dumpViewCard; + } + + public String translate(String key) { + return mainFrame.translate(key); + } + + public MainPanel(MainFrame mainFrame, MainFrameMenu mainMenu, FlashPlayerPanel flashPanel, FlashPlayerPanel previewFlashPanel) { + super(); + + this.mainFrame = mainFrame; + this.mainMenu = mainMenu; + this.flashPanel = flashPanel; + this.flashPanel2 = previewFlashPanel; + + mainFrame.setTitle(ApplicationInfo.applicationVerName); + + setLayout(new BorderLayout()); + swfs = new ObservableList<>(); + + detailPanel = new JPanel(); + detailPanel.setLayout(new CardLayout()); + + JPanel whitePanel = new JPanel(); + whitePanel.setBackground(Color.white); + detailPanel.add(whitePanel, DETAILCARDEMPTYPANEL); + + tagInfoPanel = new TagInfoPanel(this); + detailPanel.add(tagInfoPanel, DETAILCARDTAGINFO); + + UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName()); + tagTree = new TagTree(null, this); + tagTree.addTreeSelectionListener(this); + tagTree.setSelectionModel(new DefaultTreeSelectionModel() { + + private boolean isModified() { + if (abcPanel != null && abcPanel.isEditing()) { + abcPanel.tryAutoSave(); + } + + if (actionPanel != null && actionPanel.isEditing()) { + actionPanel.tryAutoSave(); + } + + if (previewPanel.isEditing()) { + previewPanel.tryAutoSave(); + } + + if (headerPanel.isEditing()) { + headerPanel.tryAutoSave(); + } + + return (abcPanel != null && abcPanel.isEditing()) + || (actionPanel != null && actionPanel.isEditing()) + || previewPanel.isEditing() || headerPanel.isEditing(); + } + + @Override + public void addSelectionPath(TreePath path) { + if (isModified()) { + return; + } + + super.addSelectionPath(path); + } + + @Override + public void addSelectionPaths(TreePath[] paths) { + if (isModified()) { + return; + } + + super.addSelectionPaths(paths); + } + + @Override + public void setSelectionPath(TreePath path) { + if (isModified()) { + return; + } + + super.setSelectionPath(path); + } + + @Override + public void setSelectionPaths(TreePath[] pPaths) { + if (isModified()) { + return; + } + + super.setSelectionPaths(pPaths); + } + + @Override + public void clearSelection() { + if (isModified()) { + return; + } + + super.clearSelection(); + } + + public void setSelection(TreePath[] selection) { + if (isModified()) { + return; + } + + this.selection = selection; + } + + @Override + public void removeSelectionPath(TreePath path) { + if (isModified()) { + return; + } + + super.removeSelectionPath(path); + } + + @Override + public void removeSelectionPaths(TreePath[] paths) { + if (isModified()) { + return; + } + + super.removeSelectionPaths(paths); + } + }); + + DragSource dragSource = DragSource.getDefaultDragSource(); + dragSource.createDefaultDragGestureRecognizer(tagTree, DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener() { + @Override + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(DragSource.DefaultCopyDrop, new Transferable() { + @Override + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{DataFlavor.javaFileListFlavor}; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.equals(DataFlavor.javaFileListFlavor); + } + + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if (flavor.equals(DataFlavor.javaFileListFlavor)) { + List files; + String tempDir = System.getProperty("java.io.tmpdir"); + if (!tempDir.endsWith(File.separator)) { + tempDir += File.separator; + } + Random rnd = new Random(); + tempDir += "ffdec" + File.separator + "export" + File.separator + System.currentTimeMillis() + "_" + rnd.nextInt(1000); + File fTempDir = new File(tempDir); + Path.createDirectorySafe(fTempDir); + + File ftemp = new File(tempDir); + ExportDialog exd = new ExportDialog(null); + try { + files = exportSelection(new GuiAbortRetryIgnoreHandler(), tempDir, exd); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + return null; + } + + files.clear(); + + File[] fs = ftemp.listFiles(); + files.addAll(Arrays.asList(fs)); + + Main.stopWork(); + + for (File f : files) { + f.deleteOnExit(); + } + new File(tempDir).deleteOnExit(); + return files; + + } + return null; + } + }, new DragSourceListener() { + @Override + public void dragEnter(DragSourceDragEvent dsde) { + enableDrop(false); + } + + @Override + public void dragOver(DragSourceDragEvent dsde) { + } + + @Override + public void dropActionChanged(DragSourceDragEvent dsde) { + } + + @Override + public void dragExit(DragSourceEvent dse) { + } + + @Override + public void dragDropEnd(DragSourceDropEvent dsde) { + enableDrop(true); + } + }); + } + }); + + tagTree.createContextMenu(); + + dumpTree = new DumpTree(null, this); + dumpTree.addTreeSelectionListener(this); + dumpTree.createContextMenu(); + + statusPanel = new MainFrameStatusPanel(this); + add(statusPanel, BorderLayout.SOUTH); + + displayPanel = new JPanel(new CardLayout()); + + DefaultSyntaxKit.initKit(); + previewPanel = new PreviewPanel(this, flashPanel); + + dumpPreviewPanel = new PreviewPanel(this, previewFlashPanel); + dumpPreviewPanel.setReadOnly(true); + + displayPanel.add(previewPanel, CARDPREVIEWPANEL); + displayPanel.add(createFolderPreviewCard(), CARDFOLDERPREVIEWPANEL); + displayPanel.add(createDumpPreviewCard(), CARDDUMPVIEW); + + headerPanel = new HeaderInfoPanel(); + displayPanel.add(headerPanel, CARDHEADER); + + displayPanel.add(new JPanel(), CARDEMPTYPANEL); + showCard(CARDEMPTYPANEL); + + searchPanel = new JPanel(); + searchPanel.setLayout(new BorderLayout()); + searchPanel.add(filterField, BorderLayout.CENTER); + searchPanel.add(new JLabel(View.getIcon("search16")), BorderLayout.WEST); + JLabel closeSearchButton = new JLabel(View.getIcon("cancel16")); + closeSearchButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + closeTagTreeSearch(); + } + }); + searchPanel.add(closeSearchButton, BorderLayout.EAST); + searchPanel.setVisible(false); + treePanel = new JPanel(new CardLayout()); + treePanel.add(createResourcesViewCard(), RESOURCES_VIEW); + treePanel.add(createDumpViewCard(), DUMP_VIEW); + //treePanel.add(searchPanel, BorderLayout.SOUTH); + //searchPanel.setVisible(false); + filterField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void changedUpdate(DocumentEvent e) { + warn(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + warn(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + warn(); + } + + public void warn() { + doFilter(); + } + }); + + //displayPanel.setBorder(BorderFactory.createLineBorder(Color.black)); + splitPane2 = new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, treePanel, detailPanel, Configuration.guiSplitPane2DividerLocationPercent); + splitPane1 = new JPersistentSplitPane(JSplitPane.HORIZONTAL_SPLIT, splitPane2, displayPanel, Configuration.guiSplitPane1DividerLocationPercent); + + welcomePanel = createWelcomePanel(); + add(welcomePanel, BorderLayout.CENTER); + + timelineViewPanel = new TimelineViewPanel(); + + CardLayout cl3 = new CardLayout(); + contentPanel = new JPanel(cl3); + contentPanel.add(welcomePanel, WELCOME_PANEL); + contentPanel.add(splitPane1, SPLIT_PANE1); + contentPanel.add(timelineViewPanel, TIMELINE_PANEL); + add(contentPanel); + cl3.show(contentPanel, WELCOME_PANEL); + + tagTree.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if ((e.getKeyCode() == 'F') && (e.isControlDown())) { + searchPanel.setVisible(true); + filterField.requestFocusInWindow(); + } + } + }); + detailPanel.setVisible(false); + + updateUi(); + + this.swfs.addCollectionChangedListener((e) -> { + TagTreeModel ttm = tagTree.getModel(); + if (ttm != null) { + if (getCurrentSwf() == null) { + tagTree.setSelectionPath(ttm.getTreePath(ttm.getRoot())); + } + ttm.updateSwfs(e); + tagTree.expandRoot(); + tagTree.expandFirstLevelNodes(); + } + + DumpTreeModel dtm = dumpTree.getModel(); + if (dtm != null) { + List> expandedNodes = View.getExpandedNodes(dumpTree); + dtm.updateSwfs(); + View.expandTreeNodes(dumpTree, expandedNodes); + dumpTree.expandRoot(); + dumpTree.expandFirstLevelNodes(); + } + + if (swfs.isEmpty()) { + tagTree.setUI(new BasicTreeUI() { + { + setHashColor(Color.gray); + } + }); + dumpTree.setUI(new BasicTreeUI() { + { + setHashColor(Color.gray); + } + }); + } + }); + + //Opening files with drag&drop to main window + enableDrop(true); + } + + public void closeTagTreeSearch() { + filterField.setText(""); + doFilter(); + searchPanel.setVisible(false); + } + + public void loadSwfAtPos(SWFList newSwfs, int index) { + previewPanel.clear(); + swfs.set(index, newSwfs); + SWF swf = newSwfs.size() > 0 ? newSwfs.get(0) : null; + if (swf != null) { + updateUi(swf); + } + + doFilter(); + reload(false); + } + + public void load(SWFList newSwfs, boolean first) { + + previewPanel.clear(); + + swfs.add(newSwfs); + SWF swf = newSwfs.size() > 0 ? newSwfs.get(0) : null; + if (swf != null) { + updateUi(swf); + } + + doFilter(); + reload(false); + } + + private ABCPanel getABCPanel() { + if (abcPanel == null) { + abcPanel = new ABCPanel(this); + displayPanel.add(abcPanel, CARDACTIONSCRIPT3PANEL); + detailPanel.add(abcPanel.tabbedPane, DETAILCARDAS3NAVIGATOR); + } + + return abcPanel; + } + + private ActionPanel getActionPanel() { + if (actionPanel == null) { + actionPanel = new ActionPanel(MainPanel.this); + displayPanel.add(actionPanel, CARDACTIONSCRIPTPANEL); + } + + return actionPanel; + } + + private void updateUi(final SWF swf) { + + mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : "")); + + List abcList = swf.getAbcList(); + + boolean hasAbc = !abcList.isEmpty(); + + if (hasAbc) { + getABCPanel().setAbc(abcList.get(0).getABC()); + } + + if (isWelcomeScreen) { + CardLayout cl = (CardLayout) (contentPanel.getLayout()); + cl.show(contentPanel, SPLIT_PANE1); + isWelcomeScreen = false; + } + + mainMenu.updateComponents(swf); + } + + private void updateUi() { + if (!isWelcomeScreen && swfs.isEmpty()) { + CardLayout cl = (CardLayout) (contentPanel.getLayout()); + cl.show(contentPanel, WELCOME_PANEL); + isWelcomeScreen = true; + closeTagTreeSearch(); + } + + mainFrame.setTitle(ApplicationInfo.applicationVerName); + mainMenu.updateComponents(null); + + showView(getCurrentView()); + } + + private boolean closeConfirmation(SWFList swfList) { + String message = swfList == null + ? translate("message.confirm.closeAll") + : translate("message.confirm.close").replace("{swfName}", swfList.toString()); + + if (View.showConfirmDialog(this, message, translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) { + return false; + } + + return true; + } + + public boolean isModified() { + for (SWFList swfList : swfs) { + for (SWF swf : swfList) { + if (swf.isModified()) { + return true; + } + } + } + + return false; + } + + public boolean closeAll(boolean showCloseConfirmation) { + if (showCloseConfirmation && isModified()) { + boolean closeConfirmResult = closeConfirmation(swfs.size() == 1 ? swfs.get(0) : null); + if (!closeConfirmResult) { + return false; + } + } + + List swfsLists = new ArrayList<>(swfs); + swfs.clear(); + oldItem = null; + clear(); + updateUi(); + + for (SWFList swfList : swfsLists) { + List swfs2 = new ArrayList<>(swfList); + for (SWF swf : swfs2) { + swf.clearTagSwfs(); + } + } + + return true; + } + + public boolean close(SWFList swfList) { + boolean modified = false; + for (SWF swf : swfList) { + if (swf.isModified()) { + modified = true; + } + } + + if (modified) { + boolean closeConfirmResult = closeConfirmation(swfList); + if (!closeConfirmResult) { + return false; + } + } + + swfs.remove(swfList); + oldItem = null; + clear(); + updateUi(); + + List swfs2 = new ArrayList<>(swfList); + for (SWF swf : swfs2) { + swf.clearTagSwfs(); + } + + return true; + } + + public void enableDrop(boolean value) { + if (value) { + setDropTarget(new DropTarget() { + @Override + public synchronized void drop(DropTargetDropEvent dtde) { + try { + dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); + @SuppressWarnings("unchecked") + List droppedFiles = (List) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); + if (!droppedFiles.isEmpty()) { + SWFSourceInfo[] sourceInfos = new SWFSourceInfo[droppedFiles.size()]; + for (int i = 0; i < droppedFiles.size(); i++) { + sourceInfos[i] = new SWFSourceInfo(null, droppedFiles.get(i).getAbsolutePath(), null); + } + Main.openFile(sourceInfos, null); + } + } catch (UnsupportedFlavorException | IOException ex) { + } + } + }); + } else { + setDropTarget(null); + } + } + + public void updateClassesList() { + List nodes = getASTreeNodes(tagTree); + boolean updateNeeded = false; + for (TreeItem n : nodes) { + if (n instanceof ClassesListTreeModel) { + ((ClassesListTreeModel) n).update(); + updateNeeded = true; + } + } + + refreshTree(); + + if (updateNeeded) { + tagTree.updateUI(); + } + } + + public void doFilter() { + List nodes = getASTreeNodes(tagTree); + for (TreeItem n : nodes) { + if (n instanceof ClassesListTreeModel) { + String filterText = filterField.getText(); + ((ClassesListTreeModel) n).setFilter(filterText); + TagTreeModel tm = tagTree.getModel(); + TreePath path = tm.getTreePath(n); + tm.updateNode(path); + if (!filterText.isEmpty()) { + View.expandTreeNodes(tagTree, path, true); + } + } + } + } + + public void renameIdentifier(SWF swf, String identifier) throws InterruptedException { + String oldName = identifier; + String newName = View.showInputDialog(translate("rename.enternew"), oldName); + if (newName != null) { + if (!oldName.equals(newName)) { + swf.renameAS2Identifier(oldName, newName); + View.showMessageDialog(null, translate("rename.finished.identifier")); + updateClassesList(); + reload(true); + } + } + } + + public void renameMultiname(List abcList, int multiNameIndex) { + String oldName = ""; + AVM2ConstantPool constants = getABCPanel().abc.constants; + if (constants.getMultiname(multiNameIndex).name_index > 0) { + oldName = constants.getString(constants.getMultiname(multiNameIndex).name_index); + } + + String newName = View.showInputDialog(translate("rename.enternew"), oldName); + if (newName != null) { + if (!oldName.equals(newName)) { + int mulCount = 0; + for (ABCContainerTag cnt : abcList) { + ABC abc = cnt.getABC(); + for (int m = 1; m < abc.constants.getMultinameCount(); m++) { + int ni = abc.constants.getMultiname(m).name_index; + String n = ""; + if (ni > 0) { + n = abc.constants.getString(ni); + } + if (n.equals(oldName)) { + abc.renameMultiname(m, newName); + mulCount++; + } + } + } + + View.showMessageDialog(null, translate("rename.finished.multiname").replace("%count%", Integer.toString(mulCount))); + if (abcPanel != null) { + abcPanel.reload(); + } + + updateClassesList(); + reload(true); + ABCPanel abcPanel = getABCPanel(); + abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().toRawString()); + } + } + } + + public List getASTreeNodes(TagTree tree) { + List result = new ArrayList<>(); + TagTreeModel tm = (TagTreeModel) tree.getModel(); + if (tm == null) { + return result; + } + TreeItem root = tm.getRoot(); + for (int i = 0; i < tm.getChildCount(root); i++) { + // first level node can be SWF and SWFBundle + TreeItem node = tm.getChild(root, i); + if (node instanceof SWFBundle) { + for (int j = 0; j < tm.getChildCount(node); j++) { + // child of SWFBundle should be SWF + SWF swfNode = (SWF) tm.getChild(node, j); + result.add(tm.getScriptsNode(swfNode)); + } + } else if (node instanceof SWF) { + SWF swfNode = (SWF) tm.getChild(root, i); + result.add(tm.getScriptsNode(swfNode)); + } + } + return result; + } + + public boolean confirmExperimental() { + return View.showConfirmDialog(null, translate("message.confirm.experimental"), translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION; + } + + public List exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException, InterruptedException { + + List ret = new ArrayList<>(); + List sel = folderPreviewPanel.selectedItems.isEmpty() ? tagTree.getAllSelected() : new ArrayList<>(folderPreviewPanel.selectedItems.values()); + + Set usedSwfs = new HashSet<>(); + for (TreeItem d : sel) { + SWF selectedNodeSwf = d.getSwf(); + if (!usedSwfs.contains(selectedNodeSwf)) { + usedSwfs.add(selectedNodeSwf); + } + } + + Map usedSwfsIds = new HashMap<>(); + for (SWF swf : usedSwfs) { + List as3scripts = new ArrayList<>(); + List images = new ArrayList<>(); + List shapes = new ArrayList<>(); + List morphshapes = new ArrayList<>(); + List buttons = new ArrayList<>(); + List movies = new ArrayList<>(); + List sounds = new ArrayList<>(); + List texts = new ArrayList<>(); + List as12scripts = new ArrayList<>(); + List binaryData = new ArrayList<>(); + Map> frames = new HashMap<>(); + List fonts = new ArrayList<>(); + List symbolNames = new ArrayList<>(); + + for (TreeItem d : sel) { + SWF selectedNodeSwf = d.getSwf(); + + if (selectedNodeSwf != swf) { + continue; + } + + if (d instanceof TagScript) { + Tag tag = ((TagScript) d).getTag(); + if (tag instanceof DoActionTag || tag instanceof DoInitActionTag) { + as12scripts.add(d); + } + } + + if (d instanceof Tag || d instanceof ASMSource) { + TreeNodeType nodeType = TagTree.getTreeNodeType(d); + if (nodeType == TreeNodeType.IMAGE) { + images.add((Tag) d); + } + if (nodeType == TreeNodeType.SHAPE) { + shapes.add((Tag) d); + } + if (nodeType == TreeNodeType.BUTTON) { + buttons.add((Tag) d); + } + if (nodeType == TreeNodeType.MORPH_SHAPE) { + morphshapes.add((Tag) d); + } + if (nodeType == TreeNodeType.AS) { + as12scripts.add(d); + } + if (nodeType == TreeNodeType.MOVIE) { + movies.add((Tag) d); + } + if (nodeType == TreeNodeType.SOUND) { + sounds.add((Tag) d); + } + if (nodeType == TreeNodeType.BINARY_DATA) { + binaryData.add((Tag) d); + } + if (nodeType == TreeNodeType.TEXT) { + texts.add((Tag) d); + } + if (nodeType == TreeNodeType.FONT) { + fonts.add((Tag) d); + } + if (nodeType == TreeNodeType.OTHER_TAG) { + if (d instanceof SymbolClassTypeTag) { + symbolNames.add((Tag) d); + } + } + } + + if (d instanceof Frame) { + Frame fn = (Frame) d; + Timelined parent = fn.timeline.timelined; + int frame = fn.frame; + int parentId = 0; + if (parent instanceof CharacterTag) { + parentId = ((CharacterTag) parent).getCharacterId(); + } + if (!frames.containsKey(parentId)) { + frames.put(parentId, new ArrayList<>()); + } + frames.get(parentId).add(frame); + } + if (d instanceof ScriptPack) { + as3scripts.add((ScriptPack) d); + } + } + + String selFile2; + if (usedSwfs.size() > 1) { + selFile2 = selFile + File.separator + Helper.getNextId(swf.getShortFileName(), usedSwfsIds); + } else { + selFile2 = selFile; + } + + EventListener evl = swf.getExportEventListener(); + + if (export.isOptionEnabled(ImageExportMode.class)) { + ret.addAll(new ImageExporter().exportImages(handler, selFile2 + File.separator + ImageExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(images), + new ImageExportSettings(export.getValue(ImageExportMode.class)), evl)); + } + + if (export.isOptionEnabled(ShapeExportMode.class)) { + ret.addAll(new ShapeExporter().exportShapes(handler, selFile2 + File.separator + ShapeExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(shapes), + new ShapeExportSettings(export.getValue(ShapeExportMode.class), export.getZoom()), evl)); + } + + if (export.isOptionEnabled(MorphShapeExportMode.class)) { + ret.addAll(new MorphShapeExporter().exportMorphShapes(handler, selFile2 + File.separator + MorphShapeExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(morphshapes), + new MorphShapeExportSettings(export.getValue(MorphShapeExportMode.class), export.getZoom()), evl)); + } + + if (export.isOptionEnabled(TextExportMode.class)) { + ret.addAll(new TextExporter().exportTexts(handler, selFile2 + File.separator + TextExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(texts), + new TextExportSettings(export.getValue(TextExportMode.class), Configuration.textExportSingleFile.get(), export.getZoom()), evl)); + } + + if (export.isOptionEnabled(MovieExportMode.class)) { + ret.addAll(new MovieExporter().exportMovies(handler, selFile2 + File.separator + MovieExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(movies), + new MovieExportSettings(export.getValue(MovieExportMode.class)), evl)); + } + + if (export.isOptionEnabled(SoundExportMode.class)) { + ret.addAll(new SoundExporter().exportSounds(handler, selFile2 + File.separator + SoundExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(sounds), + new SoundExportSettings(export.getValue(SoundExportMode.class)), evl)); + } + + if (export.isOptionEnabled(BinaryDataExportMode.class)) { + ret.addAll(new BinaryDataExporter().exportBinaryData(handler, selFile2 + File.separator + BinaryDataExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(binaryData), + new BinaryDataExportSettings(export.getValue(BinaryDataExportMode.class)), evl)); + } + + if (export.isOptionEnabled(FontExportMode.class)) { + ret.addAll(new FontExporter().exportFonts(handler, selFile2 + File.separator + FontExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(fonts), + new FontExportSettings(export.getValue(FontExportMode.class)), evl)); + } + + if (export.isOptionEnabled(SymbolClassExportMode.class)) { + ret.addAll(new SymbolClassExporter().exportNames(selFile2, new ReadOnlyTagList(symbolNames), evl)); + } + + FrameExporter frameExporter = new FrameExporter(); + + if (export.isOptionEnabled(FrameExportMode.class)) { + FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom()); + for (Entry> entry : frames.entrySet()) { + int containerId = entry.getKey(); + if (containerId == 0) { + String subFolder = FrameExportSettings.EXPORT_FOLDER_NAME; + ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, containerId, entry.getValue(), fes, evl)); + } + } + } + + if (export.isOptionEnabled(SpriteExportMode.class)) { + SpriteExportSettings ses = new SpriteExportSettings(export.getValue(SpriteExportMode.class), export.getZoom()); + for (Entry> entry : frames.entrySet()) { + int containerId = entry.getKey(); + if (containerId != 0) { + String subFolder = SpriteExportSettings.EXPORT_FOLDER_NAME; + ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, containerId, entry.getValue(), ses, evl)); + } + } + } + + if (export.isOptionEnabled(ButtonExportMode.class)) { + ButtonExportSettings bes = new ButtonExportSettings(export.getValue(ButtonExportMode.class), export.getZoom()); + for (Tag tag : buttons) { + ButtonTag button = (ButtonTag) tag; + String subFolder = ButtonExportSettings.EXPORT_FOLDER_NAME; + List frameNums = new ArrayList<>(); + frameNums.add(0); // todo: export all frames + ret.addAll(frameExporter.exportFrames(handler, selFile2 + File.separator + subFolder, swf, button.getCharacterId(), frameNums, bes, evl)); + } + } + + if (export.isOptionEnabled(ScriptExportMode.class)) { + if (as3scripts.size() > 0 || as12scripts.size() > 0) { + boolean parallel = Configuration.parallelSpeedUp.get(); + String scriptsFolder = Path.combine(selFile2, ScriptExportSettings.EXPORT_FOLDER_NAME); + Path.createDirectorySafe(new File(scriptsFolder)); + boolean singleScriptFile = Configuration.scriptExportSingleFile.get(); + if (parallel && singleScriptFile) { + logger.log(Level.WARNING, AppStrings.translate("export.script.singleFilePallelModeWarning")); + singleScriptFile = false; + } + + ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), singleScriptFile); + String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); + try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { + scriptExportSettings.singleFileWriter = writer; + if (swf.isAS3()) { + ret.addAll(new AS3ScriptExporter().exportActionScript3(swf, handler, scriptsFolder, as3scripts, scriptExportSettings, parallel, evl)); + } else { + Map asmsToExport = swf.getASMs(true, as12scripts, false); + ret.addAll(new AS2ScriptExporter().exportAS2Scripts(handler, scriptsFolder, asmsToExport, scriptExportSettings, parallel, evl)); + } + } + } + } + } + + return ret; + } + + public void exportAll(SWF swf, AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException, InterruptedException { + boolean exportAll = false; + if (exportAll) { + exportAllDebug(swf, handler, selFile, export); + return; + } + + EventListener evl = swf.getExportEventListener(); + + if (export.isOptionEnabled(ImageExportMode.class)) { + new ImageExporter().exportImages(handler, Path.combine(selFile, ImageExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new ImageExportSettings(export.getValue(ImageExportMode.class)), evl); + } + + if (export.isOptionEnabled(ShapeExportMode.class)) { + new ShapeExporter().exportShapes(handler, Path.combine(selFile, ShapeExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new ShapeExportSettings(export.getValue(ShapeExportMode.class), export.getZoom()), evl); + } + + if (export.isOptionEnabled(MorphShapeExportMode.class)) { + new MorphShapeExporter().exportMorphShapes(handler, Path.combine(selFile, MorphShapeExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new MorphShapeExportSettings(export.getValue(MorphShapeExportMode.class), export.getZoom()), evl); + } + + if (export.isOptionEnabled(TextExportMode.class)) { + new TextExporter().exportTexts(handler, Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new TextExportSettings(export.getValue(TextExportMode.class), Configuration.textExportSingleFile.get(), export.getZoom()), evl); + } + + if (export.isOptionEnabled(MovieExportMode.class)) { + new MovieExporter().exportMovies(handler, Path.combine(selFile, MovieExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new MovieExportSettings(export.getValue(MovieExportMode.class)), evl); + } + + if (export.isOptionEnabled(SoundExportMode.class)) { + new SoundExporter().exportSounds(handler, Path.combine(selFile, SoundExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new SoundExportSettings(export.getValue(SoundExportMode.class)), evl); + } + + if (export.isOptionEnabled(BinaryDataExportMode.class)) { + new BinaryDataExporter().exportBinaryData(handler, Path.combine(selFile, BinaryDataExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new BinaryDataExportSettings(export.getValue(BinaryDataExportMode.class)), evl); + } + + if (export.isOptionEnabled(FontExportMode.class)) { + new FontExporter().exportFonts(handler, Path.combine(selFile, FontExportSettings.EXPORT_FOLDER_NAME), swf.getTags(), + new FontExportSettings(export.getValue(FontExportMode.class)), evl); + } + + if (export.isOptionEnabled(SymbolClassExportMode.class)) { + new SymbolClassExporter().exportNames(selFile, swf.getTags(), evl); + } + + FrameExporter frameExporter = new FrameExporter(); + + if (export.isOptionEnabled(FrameExportMode.class)) { + FrameExportSettings fes = new FrameExportSettings(export.getValue(FrameExportMode.class), export.getZoom()); + frameExporter.exportFrames(handler, Path.combine(selFile, FrameExportSettings.EXPORT_FOLDER_NAME), swf, 0, null, fes, evl); + } + + if (export.isOptionEnabled(SpriteExportMode.class)) { + SpriteExportSettings ses = new SpriteExportSettings(export.getValue(SpriteExportMode.class), export.getZoom()); + for (CharacterTag c : swf.getCharacters().values()) { + if (c instanceof DefineSpriteTag) { + frameExporter.exportFrames(handler, Path.combine(selFile, SpriteExportSettings.EXPORT_FOLDER_NAME), swf, c.getCharacterId(), null, ses, evl); + } + } + } + + if (export.isOptionEnabled(ButtonExportMode.class)) { + ButtonExportSettings bes = new ButtonExportSettings(export.getValue(ButtonExportMode.class), export.getZoom()); + for (CharacterTag c : swf.getCharacters().values()) { + if (c instanceof ButtonTag) { + List frameNums = new ArrayList<>(); + frameNums.add(0); // todo: export all frames + frameExporter.exportFrames(handler, Path.combine(selFile, ButtonExportSettings.EXPORT_FOLDER_NAME), swf, c.getCharacterId(), frameNums, bes, evl); + } + } + } + + if (export.isOptionEnabled(ScriptExportMode.class)) { + boolean parallel = Configuration.parallelSpeedUp.get(); + String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); + Path.createDirectorySafe(new File(scriptsFolder)); + boolean singleScriptFile = Configuration.scriptExportSingleFile.get(); + if (parallel && singleScriptFile) { + logger.log(Level.WARNING, AppStrings.translate("export.script.singleFilePallelModeWarning")); + singleScriptFile = false; + } + + ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), singleScriptFile); + String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); + try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { + scriptExportSettings.singleFileWriter = writer; + swf.exportActionScript(handler, scriptsFolder, scriptExportSettings, parallel, evl); + } + } + } + + public void exportAllDebug(SWF swf, AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException, InterruptedException { + EventListener evl = swf.getExportEventListener(); + + if (export.isOptionEnabled(ImageExportMode.class)) { + for (ImageExportMode exportMode : ImageExportMode.values()) { + new ImageExporter().exportImages(handler, Path.combine(selFile, ImageExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new ImageExportSettings(exportMode), evl); + } + } + + if (export.isOptionEnabled(ShapeExportMode.class)) { + for (ShapeExportMode exportMode : ShapeExportMode.values()) { + new ShapeExporter().exportShapes(handler, Path.combine(selFile, ShapeExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new ShapeExportSettings(exportMode, export.getZoom()), evl); + } + } + + if (export.isOptionEnabled(MorphShapeExportMode.class)) { + for (MorphShapeExportMode exportMode : MorphShapeExportMode.values()) { + new MorphShapeExporter().exportMorphShapes(handler, Path.combine(selFile, MorphShapeExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new MorphShapeExportSettings(exportMode, export.getZoom()), evl); + } + } + + if (export.isOptionEnabled(TextExportMode.class)) { + for (TextExportMode exportMode : TextExportMode.values()) { + new TextExporter().exportTexts(handler, Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new TextExportSettings(exportMode, Configuration.textExportSingleFile.get(), export.getZoom()), evl); + } + } + + if (export.isOptionEnabled(MovieExportMode.class)) { + for (MovieExportMode exportMode : MovieExportMode.values()) { + new MovieExporter().exportMovies(handler, Path.combine(selFile, MovieExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new MovieExportSettings(exportMode), evl); + } + } + + if (export.isOptionEnabled(SoundExportMode.class)) { + for (SoundExportMode exportMode : SoundExportMode.values()) { + new SoundExporter().exportSounds(handler, Path.combine(selFile, SoundExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new SoundExportSettings(exportMode), evl); + } + } + + if (export.isOptionEnabled(BinaryDataExportMode.class)) { + for (BinaryDataExportMode exportMode : BinaryDataExportMode.values()) { + new BinaryDataExporter().exportBinaryData(handler, Path.combine(selFile, BinaryDataExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new BinaryDataExportSettings(exportMode), evl); + } + } + + if (export.isOptionEnabled(FontExportMode.class)) { + for (FontExportMode exportMode : FontExportMode.values()) { + new FontExporter().exportFonts(handler, Path.combine(selFile, FontExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf.getTags(), + new FontExportSettings(exportMode), evl); + } + } + + if (export.isOptionEnabled(SymbolClassExportMode.class)) { + for (SymbolClassExportMode exportMode : SymbolClassExportMode.values()) { + new SymbolClassExporter().exportNames(selFile, swf.getTags(), evl); + } + } + + FrameExporter frameExporter = new FrameExporter(); + + if (export.isOptionEnabled(FrameExportMode.class)) { + for (FrameExportMode exportMode : FrameExportMode.values()) { + FrameExportSettings fes = new FrameExportSettings(exportMode, export.getZoom()); + frameExporter.exportFrames(handler, Path.combine(selFile, FrameExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, 0, null, fes, evl); + } + } + + if (export.isOptionEnabled(SpriteExportMode.class)) { + for (SpriteExportMode exportMode : SpriteExportMode.values()) { + SpriteExportSettings ses = new SpriteExportSettings(exportMode, export.getZoom()); + for (CharacterTag c : swf.getCharacters().values()) { + if (c instanceof DefineSpriteTag) { + frameExporter.exportFrames(handler, Path.combine(selFile, SpriteExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, c.getCharacterId(), null, ses, evl); + } + } + } + } + + if (export.isOptionEnabled(ButtonExportMode.class)) { + for (ButtonExportMode exportMode : ButtonExportMode.values()) { + ButtonExportSettings bes = new ButtonExportSettings(exportMode, export.getZoom()); + for (CharacterTag c : swf.getCharacters().values()) { + if (c instanceof ButtonTag) { + List frameNums = new ArrayList<>(); + frameNums.add(0); // todo: export all frames + frameExporter.exportFrames(handler, Path.combine(selFile, ButtonExportSettings.EXPORT_FOLDER_NAME, exportMode.name()), swf, c.getCharacterId(), frameNums, bes, evl); + } + } + } + } + + if (export.isOptionEnabled(ScriptExportMode.class)) { + boolean parallel = Configuration.parallelSpeedUp.get(); + for (ScriptExportMode exportMode : ScriptExportMode.values()) { + String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME, exportMode.name()); + Path.createDirectorySafe(new File(scriptsFolder)); + boolean singleScriptFile = Configuration.scriptExportSingleFile.get(); + if (parallel && singleScriptFile) { + logger.log(Level.WARNING, AppStrings.translate("export.script.singleFilePallelModeWarning")); + singleScriptFile = false; + } + + ScriptExportSettings scriptExportSettings = new ScriptExportSettings(exportMode, singleScriptFile); + String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); + try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { + scriptExportSettings.singleFileWriter = writer; + swf.exportActionScript(handler, scriptsFolder, scriptExportSettings, parallel, evl); + } + } + } + } + + public List getSwfs() { + return swfs; + } + + public SWFList getCurrentSwfList() { + SWF swf = getCurrentSwf(); + if (swf == null) { + return null; + } + + return swf.swfList; + } + + public SWF getCurrentSwf() { + if (swfs == null || swfs.isEmpty()) { + return null; + } + + if (treePanelMode == TreePanelMode.TAG_TREE) { + TreeItem treeNode = (TreeItem) tagTree.getLastSelectedPathComponent(); + if (treeNode == null || treeNode instanceof SWFList) { + return null; + } + + return treeNode.getSwf(); + } else if (treePanelMode == TreePanelMode.DUMP_TREE) { + DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent(); + + if (dumpInfo == null) { + return null; + } + + return DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf(); + } + + return null; + } + + public void gotoFrame(int frame) { + TreeItem treeItem = (TreeItem) tagTree.getLastSelectedPathComponent(); + if (treeItem == null) { + return; + } + if (treeItem instanceof Timelined) { + Timelined t = (Timelined) treeItem; + Frame f = tagTree.getModel().getFrame(treeItem.getSwf(), t, frame); + if (f != null) { + setTagTreeSelectedNode(f); + } + } + } + + public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex) { + gotoScriptName(swf, scriptName); + if (abcPanel != null) { + if (Main.isDebugPCode()) { + if (classIndex != -1) { + boolean classChanged = false; + if (abcPanel.decompiledTextArea.getClassIndex() != classIndex) { + abcPanel.decompiledTextArea.setClassIndex(classIndex); + classChanged = true; + } + if (traitIndex != -10 && (classChanged || abcPanel.decompiledTextArea.lastTraitIndex != traitIndex)) { + abcPanel.decompiledTextArea.gotoTrait(traitIndex); + } + } + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.gotoInstrLine(line); + } else { + abcPanel.decompiledTextArea.gotoLine(line); + } + } else if (actionPanel != null) { + if (Main.isDebugPCode()) { + actionPanel.editor.gotoLine(line); + } else { + actionPanel.decompiledEditor.gotoLine(line); + } + } + refreshBreakPoints(); + + } + + public void refreshBreakPoints() { + if (abcPanel != null) { + abcPanel.decompiledTextArea.refreshMarkers(); + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.refreshMarkers(); + } + if (actionPanel != null) { + actionPanel.decompiledEditor.refreshMarkers(); + actionPanel.editor.refreshMarkers(); + } + } + + /* + public void debuggerBreakAt(SWF swf, String cls, int line) { + View.execInEventDispatchLater(new Runnable() { + + @Override + public void run() { + gotoClassLine(swf, cls, line); + if (abcPanel != null) { + abcPanel.decompiledTextArea.addColorMarker(line, DecompiledEditorPane.FG_IP_COLOR, DecompiledEditorPane.BG_IP_COLOR, DecompiledEditorPane.PRIORITY_IP); + } + } + }); + + }*/ + public void gotoScriptName(SWF swf, String scriptName) { + if (swf == null) { + return; + } + if (swf.isAS3()) { + String rawScriptName = scriptName; + if (rawScriptName.startsWith("#PCODE ")) { + rawScriptName = rawScriptName.substring(rawScriptName.indexOf(';') + 1); + } + + List abcList = swf.getAbcList(); + if (!abcList.isEmpty()) { + ABCPanel abcPanel = getABCPanel(); + abcPanel.setAbc(abcList.get(0).getABC()); + abcPanel.hilightScript(swf, rawScriptName); + } + } else { + String rawScriptName = scriptName; + if (rawScriptName.startsWith("#PCODE ")) { + rawScriptName = rawScriptName.substring("#PCODE ".length()); + } + Map asms = swf.getASMs(true); + if (actionPanel != null && asms.containsKey(rawScriptName)) { + actionPanel.setSource(asms.get(rawScriptName), true); + } + } + } + + public void gotoDocumentClass(SWF swf) { + if (swf == null) { + return; + } + + String documentClass = swf.getDocumentClass(); + if (documentClass != null && !Configuration.dumpView.get()) { + List abcList = swf.getAbcList(); + if (!abcList.isEmpty()) { + ABCPanel abcPanel = getABCPanel(); + for (ABCContainerTag c : abcList) { + if (c.getABC().findClassByName(documentClass) > -1) { + abcPanel.setAbc(c.getABC()); + abcPanel.hilightScript(swf, documentClass); + break; + } + } + } + } + } + + public void disableDecompilationChanged() { + clearAllScriptCache(); + + if (abcPanel != null) { + abcPanel.reload(); + } + + updateClassesList(); + } + + private void clearAllScriptCache() { + for (SWFList swfList : swfs) { + for (SWF swf : swfList) { + swf.clearScriptCache(); + } + } + } + + public void searchInActionScriptOrText(Boolean searchInText, SWF swf) { + SearchDialog searchDialog = new SearchDialog(getMainFrame().getWindow(), false); + if (searchInText != null) { + if (searchInText) { + searchDialog.searchInTextsRadioButton.setSelected(true); + } else { + searchDialog.searchInASRadioButton.setSelected(true); + } + } + + if (searchDialog.showDialog() == AppDialog.OK_OPTION) { + final String txt = searchDialog.searchField.getText(); + if (!txt.isEmpty()) { + if (swf.isAS3()) { + getABCPanel(); + } else { + getActionPanel(); + } + + boolean ignoreCase = searchDialog.ignoreCaseCheckBox.isSelected(); + boolean regexp = searchDialog.regexpCheckBox.isSelected(); + + if (searchDialog.searchInASRadioButton.isSelected()) { + new CancellableWorker() { + @Override + protected Void doInBackground() throws Exception { + List abcResult = null; + List actionResult = null; + if (swf.isAS3()) { + abcResult = getABCPanel().search(swf, txt, ignoreCase, regexp, this); + } else { + actionResult = getActionPanel().search(swf, txt, ignoreCase, regexp, this); + } + + List fAbcResult = abcResult; + List fActionResult = actionResult; + View.execInEventDispatch(() -> { + boolean found = false; + if (fAbcResult != null) { + found = true; + getABCPanel().searchPanel.setSearchText(txt); + SearchResultsDialog sr = new SearchResultsDialog<>(getMainFrame().getWindow(), txt, getABCPanel()); + sr.setResults(fAbcResult); + sr.setVisible(true); + } else if (fActionResult != null) { + found = true; + getActionPanel().searchPanel.setSearchText(txt); + + SearchResultsDialog sr = new SearchResultsDialog<>(getMainFrame().getWindow(), txt, getActionPanel()); + sr.setResults(fActionResult); + sr.setVisible(true); + } + + if (!found) { + View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); + } + + Main.stopWork(); + }); + + return null; + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + Main.stopWork(); + }); + + } + }.execute(); + } else if (searchDialog.searchInTextsRadioButton.isSelected()) { + new CancellableWorker() { + @Override + protected Void doInBackground() throws Exception { + List textResult; + SearchPanel textSearchPanel = previewPanel.getTextPanel().getSearchPanel(); + textSearchPanel.setOptions(ignoreCase, regexp); + textResult = searchText(txt, ignoreCase, regexp, swf); + + List fTextResult = textResult; + View.execInEventDispatch(() -> { + textSearchPanel.setSearchText(txt); + boolean found = textSearchPanel.setResults(fTextResult); + if (!found) { + View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); + } + + Main.stopWork(); + }); + + return null; + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + Main.stopWork(); + }); + + } + }.execute(); + } + } + } + } + + public void replaceText() { + SearchDialog replaceDialog = new SearchDialog(getMainFrame().getWindow(), true); + if (replaceDialog.showDialog() == AppDialog.OK_OPTION) { + final String txt = replaceDialog.searchField.getText(); + if (!txt.isEmpty()) { + final SWF swf = getCurrentSwf(); + + new CancellableWorker() { + @Override + protected Void doInBackground() throws Exception { + int findCount = 0; + boolean ignoreCase = replaceDialog.ignoreCaseCheckBox.isSelected(); + boolean regexp = replaceDialog.regexpCheckBox.isSelected(); + String replacement = replaceDialog.replaceField.getText(); + if (!regexp) { + replacement = Matcher.quoteReplacement(replacement); + } + Pattern pat; + if (regexp) { + pat = Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); + } else { + pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); + } + List textTags = new ArrayList<>(); + for (Tag tag : swf.getTags()) { + if (tag instanceof TextTag) { + textTags.add((TextTag) tag); + } + } + for (TextTag textTag : textTags) { + if (!replaceDialog.replaceInParametersCheckBox.isSelected()) { + List texts = textTag.getTexts(); + boolean found = false; + for (int i = 0; i < texts.size(); i++) { + String text = texts.get(i); + if (pat.matcher(text).find()) { + texts.set(i, text.replaceAll(txt, replacement)); + found = true; + findCount++; + } + } + if (found) { + String[] textArray = texts.toArray(new String[texts.size()]); + textTag.setFormattedText(getMissingCharacterHandler(), textTag.getFormattedText(false).text, textArray); + } + } else { + String text = textTag.getFormattedText(false).text; + if (pat.matcher(text).find()) { + textTag.setFormattedText(getMissingCharacterHandler(), text.replaceAll(txt, replacement), null); + findCount++; + } + } + } + + if (findCount > 0) { + swf.clearImageCache(); + repaintTree(); + } + + return null; + } + }.execute(); + } + } + } + + private List searchText(String txt, boolean ignoreCase, boolean regexp, SWF swf) { + if (txt != null && !txt.isEmpty()) { + List found = new ArrayList<>(); + Pattern pat; + if (regexp) { + pat = Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); + } else { + pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); + } + for (Tag tag : swf.getTags()) { + if (tag instanceof TextTag) { + TextTag textTag = (TextTag) tag; + if (pat.matcher(textTag.getFormattedText(false).text).find()) { + found.add(textTag); + } + } + } + + return found; + } + + return null; + } + + @Override + public void updateSearchPos(TextTag item) { + setTagTreeSelectedNode(item); + previewPanel.getTextPanel().updateSearchPos(); + } + + private void setDumpTreeSelectedNode(DumpInfo dumpInfo) { + DumpTreeModel dtm = (DumpTreeModel) dumpTree.getModel(); + TreePath tp = dtm.getDumpInfoPath(dumpInfo); + if (tp != null) { + dumpTree.setSelectionPath(tp); + dumpTree.scrollPathToVisible(tp); + } else { + showCard(CARDEMPTYPANEL); + } + } + + public void setTagTreeSelectedNode(TreeItem treeItem) { + TagTreeModel ttm = tagTree.getModel(); + TreePath tp = ttm.getTreePath(treeItem); + if (tp != null) { + tagTree.setSelectionPath(tp); + tagTree.scrollPathToVisible(tp); + } else { + showCard(CARDEMPTYPANEL); + } + } + + public void autoDeobfuscateChanged() { + Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable"); + clearAllScriptCache(); + if (abcPanel != null) { + abcPanel.reload(); + } + reload(true); + updateClassesList(); + } + + public void renameOneIdentifier(final SWF swf) { + if (swf == null) { + return; + } + + FileAttributesTag fileAttributes = swf.getFileAttributes(); + if (fileAttributes != null && fileAttributes.actionScript3) { + final int multiName = getABCPanel().decompiledTextArea.getMultinameUnderCaret(); + final List abcList = swf.getAbcList(); + if (multiName > 0) { + new CancellableWorker() { + @Override + public Void doInBackground() throws Exception { + renameMultiname(abcList, multiName); + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.renaming") + "...", this); + } + + @Override + protected void done() { + Main.stopWork(); + } + }.execute(); + + } else { + View.showMessageDialog(null, translate("message.rename.notfound.multiname"), translate("message.rename.notfound.title"), JOptionPane.INFORMATION_MESSAGE); + } + } else { + final String identifier = getActionPanel().getStringUnderCursor(); + if (identifier != null) { + new CancellableWorker() { + @Override + public Void doInBackground() throws Exception { + try { + renameIdentifier(swf, identifier); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.renaming") + "...", this); + } + + @Override + protected void done() { + Main.stopWork(); + } + }.execute(); + } else { + View.showMessageDialog(null, translate("message.rename.notfound.identifier"), translate("message.rename.notfound.title"), JOptionPane.INFORMATION_MESSAGE); + } + } + } + + public void exportFla(final SWF swf) { + if (swf == null) { + return; + } + JFileChooser fc = new JFileChooser(); + String selDir = Configuration.lastOpenDir.get(); + fc.setCurrentDirectory(new File(selDir)); + if (!selDir.endsWith(File.separator)) { + selDir += File.separator; + } + String fileName = new File(swf.getFile()).getName(); + fileName = fileName.substring(0, fileName.length() - 4) + ".fla"; + fc.setSelectedFile(new File(selDir + fileName)); + List flaFilters = new ArrayList<>(); + List xflFilters = new ArrayList<>(); + List versions = new ArrayList<>(); + boolean isAS3 = swf.isAS3(); + for (int i = FLAVersion.values().length - 1; i >= 0; i--) { + final FLAVersion v = FLAVersion.values()[i]; + if (!isAS3 && v.minASVersion() > 2) { + // This version does not support AS1/2 + } else { + versions.add(v); + FileFilter f = new FileFilter() { + @Override + public boolean accept(File f) { + return f.isDirectory() || (f.getName().toLowerCase().endsWith(".fla")); + } + + @Override + public String getDescription() { + return translate("filter.fla").replace("%version%", v.applicationName()); + } + }; + if (v == FLAVersion.CS6) { + fc.setFileFilter(f); + } else { + fc.addChoosableFileFilter(f); + } + flaFilters.add(f); + f = new FileFilter() { + @Override + public boolean accept(File f) { + return f.isDirectory() || (f.getName().toLowerCase().endsWith(".xfl")); + } + + @Override + public String getDescription() { + return translate("filter.xfl").replace("%version%", v.applicationName()); + } + }; + fc.addChoosableFileFilter(f); + xflFilters.add(f); + } + } + + fc.setAcceptAllFileFilterUsed(false); + JFrame f = new JFrame(); + View.setWindowIcon(f); + if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) { + Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); + File sf = Helper.fixDialogFile(fc.getSelectedFile()); + + FileFilter selectedFilter = fc.getFileFilter(); + final boolean compressed = flaFilters.contains(selectedFilter); + String path = sf.getAbsolutePath(); + if (path.endsWith(".fla") || path.endsWith(".xfl")) { + path = path.substring(0, path.length() - 4); + } + path += compressed ? ".fla" : ".xfl"; + final FLAVersion selectedVersion = versions.get(compressed ? flaFilters.indexOf(selectedFilter) : xflFilters.indexOf(selectedFilter)); + final File selfile = new File(path); + new CancellableWorker() { + @Override + protected Void doInBackground() throws Exception { + Helper.freeMem(); + try { + AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); + if (compressed) { + swf.exportFla(errorHandler, selfile.getAbsolutePath(), new File(swf.getFile()).getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); + } else { + swf.exportXfl(errorHandler, selfile.getAbsolutePath(), new File(swf.getFile()).getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); + } + } catch (Exception ex) { + logger.log(Level.SEVERE, "FLA export error", ex); + View.showMessageDialog(null, translate("error.export") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage(), translate("error"), JOptionPane.ERROR_MESSAGE); + } + Helper.freeMem(); + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.exporting.fla") + "...", this); + } + + @Override + protected void done() { + if (Configuration.openFolderAfterFlaExport.get()) { + try { + Desktop.getDesktop().open(selfile.getAbsoluteFile().getParentFile()); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + Main.stopWork(); + } + }.execute(); + } + } + + public void importText(final SWF swf) { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); + chooser.setDialogTitle(translate("import.select.directory")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); + File textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_FORMATTED)); + TextImporter textImporter = new TextImporter(getMissingCharacterHandler(), new TextImportErrorHandler() { + + // "configuration items" for the current replace only + private final ConfigurationItem showAgainImportError = new ConfigurationItem<>("showAgainImportError", true, true); + + private final ConfigurationItem showAgainInvalidText = new ConfigurationItem<>("showAgainInvalidText", true, true); + + private String getTextTagInfo(TextTag textTag) { + StringBuilder ret = new StringBuilder(); + if (textTag != null) { + ret.append(" TextId: ").append(textTag.getCharacterId()).append(" (").append(String.join(", ", textTag.getTexts())).append(")"); + } + + return ret.toString(); + } + + @Override + public boolean handle(TextTag textTag) { + String msg = translate("error.text.import"); + logger.log(Level.SEVERE, msg + getTextTagInfo(textTag)); + return View.showConfirmDialog(MainPanel.this, msg, translate("error"), JOptionPane.OK_CANCEL_OPTION, showAgainImportError, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION; + } + + @Override + public boolean handle(TextTag textTag, String message, long line) { + String msg = translate("error.text.invalid.continue").replace("%text%", message).replace("%line%", Long.toString(line)); + logger.log(Level.SEVERE, msg + getTextTagInfo(textTag)); + return View.showConfirmDialog(MainPanel.this, msg, translate("error"), JOptionPane.OK_CANCEL_OPTION, showAgainInvalidText, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION; + } + }); + + // try to import formatted texts + if (textsFile.exists()) { + textImporter.importTextsSingleFileFormatted(textsFile, swf); + } else { + textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_PLAIN)); + // try to import plain texts + if (textsFile.exists()) { + textImporter.importTextsSingleFile(textsFile, swf); + } else { + textImporter.importTextsMultipleFiles(selFile, swf); + } + } + + swf.clearImageCache(); + reload(true); + } + } + + public void importScript(final SWF swf) { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); + chooser.setDialogTitle(translate("import.select.directory")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); + String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME); + + int countAs2 = new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true)); + int countAs3 = new AS3ScriptImporter().importScripts(scriptsFolder, swf.getAS3Packs()); + + if (countAs3 > 0) { + updateClassesList(); + } + + View.showMessageDialog(this, translate("import.script.result").replace("%count%", Integer.toString(countAs2 + countAs3))); + if (countAs2 != 0 || countAs3 != 0) { + reload(true); + } + } + } + + public void importSymbolClass(final SWF swf) { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); + chooser.setDialogTitle(translate("import.select.directory")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); + File importFile = new File(Path.combine(selFile, SymbolClassExporter.SYMBOL_CLASS_EXPORT_FILENAME)); + SymbolClassImporter importer = new SymbolClassImporter(); + + if (importFile.exists()) { + importer.importSymbolClasses(importFile, swf); + } + } + } + + 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; + } + + public void export(final boolean onlySel) { + + final SWF swf = getCurrentSwf(); + List sel = tagTree.getAllSelected(); + if (!onlySel) { + sel = null; + } else if (sel.isEmpty()) { + return; + } + final ExportDialog export = new ExportDialog(sel); + if (export.showExportDialog() == AppDialog.OK_OPTION) { + final String selFile = selectExportDir(); + if (selFile != null) { + final long timeBefore = System.currentTimeMillis(); + + new CancellableWorker() { + @Override + public Void doInBackground() throws Exception { + try { + AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); + if (onlySel) { + exportSelection(errorHandler, selFile, export); + } else { + exportAll(swf, errorHandler, selFile, export); + } + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error during export", ex); + View.showMessageDialog(null, translate("error.export") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage()); + } + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.exporting") + "...", this); + } + + @Override + protected void done() { + Main.stopWork(); + long timeAfter = System.currentTimeMillis(); + final long timeMs = timeAfter - timeBefore; + + View.execInEventDispatchLater(() -> { + setStatus(translate("export.finishedin").replace("%time%", Helper.formatTimeSec(timeMs))); + }); + } + }.execute(); + + } + } + } + + public void exportJavaSource() { + List sel = tagTree.getSelected(); + for (TreeItem item : sel) { + if (item instanceof SWF) { + SWF swf = (SWF) item; + final String selFile = selectExportDir(); + if (selFile != null) { + Main.startWork(translate("work.exporting") + "...", null); + + try { + new SwfJavaExporter().exportJavaCode(swf, selFile); + Main.stopWork(); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + } + } + + public void exportSwfXml() { + List sel = tagTree.getSelected(); + Set swfs = new HashSet<>(); + + for (TreeItem item : sel) { + swfs.add(item.getSwf()); + } + + for (SWF swf : swfs) { + final String selFile = selectExportDir(); + if (selFile != null) { + Main.startWork(translate("work.exporting") + "...", null); + + try { + File outFile = new File(selFile + File.separator + Helper.makeFileName("swf.xml")); + new SwfXmlExporter().exportXml(swf, outFile); + Main.stopWork(); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + } + + public void importSwfXml() { + List sel = tagTree.getSelected(); + Set swfs = new HashSet<>(); + for (TreeItem item : sel) { + swfs.add(item.getSwf()); + } + if (swfs.size() > 1) { + return; + } + + for (SWF swf : swfs) { + File selectedFile = showImportFileChooser("filter.xml|*.xml"); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + String xml = Helper.readTextFile(selfile.getPath()); + try { + new SwfXmlImporter().importSwf(swf, xml); + swf.clearAllCache(); + swf.assignExportNamesToSymbols(); + swf.assignClassesToSymbols(); + refreshTree(swf); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + } + + public void renameIdentifiers(final SWF swf) { + if (swf == null) { + return; + } + if (confirmExperimental()) { + RenameDialog renameDialog = new RenameDialog(); + if (renameDialog.showRenameDialog() == AppDialog.OK_OPTION) { + final RenameType renameType = renameDialog.getRenameType(); + new CancellableWorker() { + @Override + protected Integer doInBackground() throws Exception { + int cnt = swf.deobfuscateIdentifiers(renameType); + return cnt; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.renaming.identifiers") + "...", this); + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + try { + int cnt = get(); + Main.stopWork(); + View.showMessageDialog(null, translate("message.rename.renamed").replace("%count%", Integer.toString(cnt))); + swf.assignClassesToSymbols(); + swf.clearScriptCache(); + if (abcPanel != null) { + abcPanel.reload(); + } + updateClassesList(); + reload(true); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error during renaming identifiers", ex); + Main.stopWork(); + View.showMessageDialog(null, translate("error.occured").replace("%error%", ex.getClass().getSimpleName())); + } + }); + } + }.execute(); + } + } + } + + public void deobfuscate() { + DeobfuscationDialog deobfuscationDialog = new DeobfuscationDialog(); + if (deobfuscationDialog.showDialog() == AppDialog.OK_OPTION) { + DeobfuscationLevel level = DeobfuscationLevel.getByLevel(deobfuscationDialog.codeProcessingLevel.getValue()); + new CancellableWorker() { + @Override + protected Void doInBackground() throws Exception { + try { + ABCPanel abcPanel = getABCPanel(); + if (deobfuscationDialog.processAllCheckbox.isSelected()) { + SWF swf = abcPanel.getSwf(); + swf.deobfuscate(level); + } else { + int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex(); + DecompiledEditorPane decompiledTextArea = abcPanel.decompiledTextArea; + Trait t = abcPanel.decompiledTextArea.getCurrentTrait(); + ABC abc = abcPanel.abc; + if (bi != -1) { + int scriptIndex = decompiledTextArea.getScriptLeaf().scriptIndex; + int classIndex = decompiledTextArea.getClassIndex(); + boolean isStatic = decompiledTextArea.getIsStatic(); + abc.bodies.get(bi).deobfuscate(level, t, scriptIndex, classIndex, isStatic, ""/*FIXME*/); + } + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(decompiledTextArea.getScriptLeaf().getPathScriptName(), bi, abc, t, abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getScriptIndex()); + } + } catch (Exception ex) { + logger.log(Level.SEVERE, "Deobfuscation error", ex); + } + + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.deobfuscating") + "...", this); + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + Main.stopWork(); + View.showMessageDialog(null, translate("work.deobfuscating.complete")); + + clearAllScriptCache(); + getABCPanel().reload(); + updateClassesList(); + }); + } + }.execute(); + } + } + + public void removeNonScripts(SWF swf) { + if (swf == null) { + return; + } + + List tags = swf.getTags().toArrayList(); + List toRemove = new ArrayList<>(); + for (Tag tag : tags) { + System.out.println(tag.getClass()); + if (!(tag instanceof ABCContainerTag || tag instanceof ASMSource)) { + toRemove.add(tag); + } + } + + swf.removeTags(toRemove, true); + refreshTree(swf); + } + + public void removeExceptSelected(SWF swf) { + if (swf == null) { + return; + } + + List sel = tagTree.getAllSelected(); + Set needed = new HashSet<>(); + for (TreeItem item : sel) { + if (item instanceof CharacterTag) { + CharacterTag characterTag = (CharacterTag) item; + characterTag.getNeededCharactersDeep(needed); + needed.add(characterTag.getCharacterId()); + } + } + + List tagsToRemove = new ArrayList<>(); + for (Tag tag : swf.getTags()) { + if (tag instanceof CharacterTag) { + CharacterTag characterTag = (CharacterTag) tag; + if (!needed.contains(characterTag.getCharacterId())) { + tagsToRemove.add(tag); + } + } + } + + swf.removeTags(tagsToRemove, true); + refreshTree(swf); + } + + private void clear() { + dumpViewPanel.clear(); + previewPanel.clear(); + headerPanel.clear(); + folderPreviewPanel.clear(); + if (abcPanel != null) { + abcPanel.clearSwf(); + } + if (actionPanel != null) { + actionPanel.clearSource(); + } + } + + public void refreshTree() { + refreshTree(new SWF[0]); + } + + public void refreshTree(SWF swf) { + refreshTree(new SWF[]{swf}); + } + + public void refreshTree(SWF[] swfs) { + clear(); + showCard(CARDEMPTYPANEL); + TreeItem treeItem = tagTree.getCurrentTreeItem(); + + tagTree.updateSwfs(swfs); + + if (treeItem != null) { + SWF treeItemSwf = treeItem.getSwf().getRootSwf(); + if (this.swfs.contains(treeItemSwf.swfList)) { + setTagTreeSelectedNode(treeItem); + } + } + + reload(true); + } + + public void refreshDecompiled() { + clearAllScriptCache(); + if (abcPanel != null) { + abcPanel.reload(); + } + + reload(true); + updateClassesList(); + } + + private MissingCharacterHandler getMissingCharacterHandler() { + return new MissingCharacterHandler() { + + // "configuration items" for the current replace only + private final ConfigurationItem showAgainIgnoreMissingCharacters = new ConfigurationItem<>("showAgainIgnoreMissingCharacters", true, true); + + private boolean ignoreMissingCharacters = false; + + @Override + public boolean getIgnoreMissingCharacters() { + return ignoreMissingCharacters; + } + + @Override + public boolean handle(TextTag textTag, final FontTag font, final char character) { + String fontName = font.getSwf().sourceFontNamesMap.get(font.getFontId()); + if (fontName == null) { + fontName = font.getFontName(); + } + final Font f = FontTag.installedFontsByName.get(fontName); + if (f == null || !f.canDisplay(character)) { + String msg = translate("error.font.nocharacter").replace("%char%", "" + character); + logger.log(Level.SEVERE, "{0} FontId: {1} TextId: {2}", new Object[]{msg, font.getCharacterId(), textTag.getCharacterId()}); + ignoreMissingCharacters = View.showConfirmDialog(null, msg, translate("error"), + JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE, + showAgainIgnoreMissingCharacters, + ignoreMissingCharacters ? JOptionPane.OK_OPTION : JOptionPane.CANCEL_OPTION) == JOptionPane.OK_OPTION; + return false; + } + + font.addCharacter(character, f); + + return true; + } + }; + } + + public boolean saveText(TextTag textTag, String formattedText, String[] texts, LineMarkedEditorPane editor) { + try { + if (textTag.setFormattedText(getMissingCharacterHandler(), formattedText, texts)) { + return true; + } + } catch (TextParseException ex) { + if (editor != null) { + editor.gotoLine((int) ex.line); + editor.markError(); + } + + View.showMessageDialog(null, translate("error.text.invalid").replace("%text%", ex.text).replace("%line%", Long.toString(ex.line)), translate("error"), JOptionPane.ERROR_MESSAGE); + } + + return false; + } + + public boolean alignText(TextTag textTag, TextAlign textAlign) { + return (textTag.alignText(textAlign)); + } + + public boolean translateText(TextTag textTag, int diff) { + return textTag.translateText(diff); + } + + public boolean previousTag() { + if (getCurrentView() == VIEW_RESOURCES) { + if (tagTree.getSelectionRows().length > 0) { + int row = tagTree.getSelectionRows()[0]; + if (row > 0) { + tagTree.setSelectionRow(row - 1); + tagTree.scrollRowToVisible(row - 1); + previewPanel.focusTextPanel(); + } + } + return true; + } + return false; + } + + public boolean nextTag() { + if (getCurrentView() == VIEW_RESOURCES) { + if (tagTree.getSelectionRows().length > 0) { + int row = tagTree.getSelectionRows()[0]; + if (row < tagTree.getRowCount() - 1) { + tagTree.setSelectionRow(row + 1); + tagTree.scrollRowToVisible(row + 1); + previewPanel.focusTextPanel(); + } + } + return true; + } + return false; + } + + public void selectBkColorButtonActionPerformed(ActionEvent evt) { + Color newColor = JColorChooser.showDialog(null, AppStrings.translate("dialog.selectbkcolor.title"), View.getSwfBackgroundColor()); + if (newColor != null) { + View.setSwfBackgroundColor(newColor); + reload(true); + } + } + + public void replaceButtonActionPerformed(ActionEvent evt) { + TreeItem item = tagTree.getCurrentTreeItem(); + if (item == null) { + return; + } + + if (item instanceof DefineSoundTag) { + File selectedFile = showImportFileChooser("filter.sounds|*.mp3;*.wav|filter.sounds.mp3|*.mp3|filter.sounds.wav|*.wav"); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + DefineSoundTag ds = (DefineSoundTag) item; + int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN; + if (selfile.getName().toLowerCase().endsWith(".mp3")) { + soundFormat = SoundFormat.FORMAT_MP3; + } + + boolean ok = false; + try { + ok = ds.setSound(new FileInputStream(selfile), soundFormat); + } catch (IOException ex) { + //ignore + } + + if (!ok) { + View.showMessageDialog(null, translate("error.sound.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); + } else { + reload(true); + } + } + } + if (item instanceof ImageTag) { + ImageTag it = (ImageTag) item; + if (it.importSupported()) { + File selectedFile = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp"); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + byte[] data = Helper.readFile(selfile.getAbsolutePath()); + try { + Tag newTag = new ImageImporter().importImage(it, data); + SWF swf = it.getSwf(); + if (newTag != null) { + refreshTree(swf); + setTagTreeSelectedNode(newTag); + } + swf.clearImageCache(); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Invalid image", ex); + View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); + } + + reload(true); + } + } + } + if (item instanceof ShapeTag) { + ShapeTag st = (ShapeTag) item; + String filter = "filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg"; + File selectedFile = showImportFileChooser(filter); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + byte[] data = null; + String svgText = null; + if (".svg".equals(Path.getExtension(selfile))) { + svgText = Helper.readTextFile(selfile.getAbsolutePath()); + showSvgImportWarning(); + } else { + data = Helper.readFile(selfile.getAbsolutePath()); + } + try { + Tag newTag = svgText != null ? new SvgImporter().importSvg(st, svgText) : new ShapeImporter().importImage(st, data); + SWF swf = st.getSwf(); + if (newTag != null) { + refreshTree(swf); + setTagTreeSelectedNode(newTag); + } + + swf.clearImageCache(); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Invalid image", ex); + View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); + } + reload(true); + } + } + if (item instanceof DefineBinaryDataTag) { + DefineBinaryDataTag bt = (DefineBinaryDataTag) item; + File selectedFile = showImportFileChooser(""); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + byte[] data = Helper.readFile(selfile.getAbsolutePath()); + new BinaryDataImporter().importData(bt, data); + refreshTree(bt.getSwf()); + reload(true); + } + } + } + + public void replaceNoFillButtonActionPerformed(ActionEvent evt) { + TreeItem item = tagTree.getCurrentTreeItem(); + if (item == null) { + return; + } + + if (item instanceof ShapeTag) { + ShapeTag st = (ShapeTag) item; + String filter = "filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg"; + File selectedFile = showImportFileChooser(filter); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + byte[] data = null; + String svgText = null; + if (".svg".equals(Path.getExtension(selfile))) { + svgText = Helper.readTextFile(selfile.getAbsolutePath()); + showSvgImportWarning(); + } else { + data = Helper.readFile(selfile.getAbsolutePath()); + } + try { + Tag newTag = svgText != null ? new SvgImporter().importSvg(st, svgText, false) : new ShapeImporter().importImage(st, data, 0, false); + SWF swf = st.getSwf(); + if (newTag != null) { + refreshTree(swf); + setTagTreeSelectedNode(newTag); + } + + swf.clearImageCache(); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Invalid image", ex); + View.showMessageDialog(null, translate("error.image.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); + } + reload(true); + } + } + } + + private void showSvgImportWarning() { + View.showMessageDialog(null, AppStrings.translate("message.warning.svgImportExperimental"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE, Configuration.warningSvgImport); + } + + public void replaceAlphaButtonActionPerformed(ActionEvent evt) { + TreeItem item = tagTree.getCurrentTreeItem(); + if (item == null) { + return; + } + + if (item instanceof DefineBitsJPEG3Tag || item instanceof DefineBitsJPEG4Tag) { + ImageTag it = (ImageTag) item; + if (it.importSupported()) { + File selectedFile = showImportFileChooser(""); + if (selectedFile != null) { + File selfile = Helper.fixDialogFile(selectedFile); + byte[] data = Helper.readFile(selfile.getAbsolutePath()); + try { + new ImageImporter().importImageAlpha(it, data); + SWF swf = it.getSwf(); + swf.clearImageCache(); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Invalid alpha channel data", ex); + View.showMessageDialog(null, translate("error.image.alpha.invalid"), translate("error"), JOptionPane.ERROR_MESSAGE); + } + + reload(true); + } + } + } + } + + public void exportJavaSourceActionPerformed(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + exportJavaSource(); + } + + public void exportSwfXmlActionPerformed(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + exportSwfXml(); + } + + public void importSwfXmlActionPerformed(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + importSwfXml(); + } + + public void exportSelectionActionPerformed(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + + export(true); + } + + public File showImportFileChooser(String filter) { + String[] filterArray = filter.length() > 0 ? filter.split("\\|") : new String[0]; + + JFileChooser fc = new JFileChooser(); + fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + boolean first = true; + for (int i = 0; i < filterArray.length; i += 2) { + final String filterName = filterArray[i]; + final String[] extensions = filterArray[i + 1].split(";"); + for (int j = 0; j < extensions.length; j++) { + if (extensions[j].startsWith("*.")) { + extensions[j] = extensions[j].substring(1); + } + } + FileFilter ff = new FileFilter() { + + @Override + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + String fileName = f.getName().toLowerCase(); + for (String ext : extensions) { + if (fileName.endsWith(ext)) { + return true; + } + } + return false; + } + + @Override + public String getDescription() { + StringBuilder extStr = new StringBuilder(); + boolean first = true; + for (String ext : extensions) { + if (first) { + first = false; + } else { + extStr.append(","); + } + + extStr.append("*").append(ext); + } + + return translate(filterName).replace("%extensions%", extStr); + } + }; + if (first) { + fc.setFileFilter(ff); + } else { + fc.addChoosableFileFilter(ff); + } + first = false; + } + + JFrame f = new JFrame(); + View.setWindowIcon(f); + if (fc.showOpenDialog(f) == JFileChooser.APPROVE_OPTION) { + File result = fc.getSelectedFile(); + Configuration.lastOpenDir.set(Helper.fixDialogFile(result).getParentFile().getAbsolutePath()); + return result; + } + + return null; + } + + private void showDetail(String card) { + CardLayout cl = (CardLayout) (detailPanel.getLayout()); + cl.show(detailPanel, card); + if (card.equals(DETAILCARDEMPTYPANEL)) { + if (detailPanel.isVisible()) { + detailPanel.setVisible(false); + } + } else if (!detailPanel.isVisible()) { + detailPanel.setVisible(true); + } + } + + private void showCard(String card) { + CardLayout cl = (CardLayout) (displayPanel.getLayout()); + cl.show(displayPanel, card); + } + + @Override + public void valueChanged(TreeSelectionEvent e) { + Object source = e.getSource(); + TreeItem treeItem = (TreeItem) e.getPath().getLastPathComponent(); + + if (!(treeItem instanceof SWFList)) { + SWF swf = treeItem.getSwf(); + if (swfs.isEmpty()) { + // show welcome panel after closing swfs + updateUi(); + } else { + if (swf == null) { + swf = swfs.get(0).get(0); + } + + updateUi(swf); + } + } else { + updateUi(); + } + + reload(false); + + if (source == dumpTree) { + Tag t = null; + if (treeItem instanceof DumpInfo) { + DumpInfo di = (DumpInfo) treeItem; + t = di.getTag(); + } + + showPreview(t, dumpPreviewPanel); + } + } + + public void unloadFlashPlayer() { + if (flashPanel != null) { + try { + flashPanel.close(); + } catch (IOException ex) { + // ignore + } + } + if (flashPanel2 != null) { + try { + flashPanel2.close(); + } catch (IOException ex) { + // ignore + } + } + } + + public void clearDebuggerColors() { + if (abcPanel != null) { + abcPanel.decompiledTextArea.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.clearDebuggerColors(); + } + if (actionPanel != null) { + actionPanel.decompiledEditor.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); + actionPanel.editor.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); + } + } + + private void stopFlashPlayer() { + if (flashPanel != null) { + if (!flashPanel.isStopped()) { + flashPanel.stopSWF(); + } + } + if (flashPanel2 != null) { + if (!flashPanel2.isStopped()) { + flashPanel2.stopSWF(); + } + } + } + + public boolean isInternalFlashViewerSelected() { + return mainMenu.isInternalFlashViewerSelected(); + } + + public static final int VIEW_RESOURCES = 0; + + public static final int VIEW_DUMP = 1; + + public static final int VIEW_TIMELINE = 2; + + private int getCurrentView() { + return Configuration.dumpView.get() ? VIEW_DUMP : VIEW_RESOURCES; + } + + public void setTreeModel(int view) { + switch (view) { + case VIEW_DUMP: + if (dumpTree.getModel() == null) { + DumpTreeModel dtm = new DumpTreeModel(swfs); + dumpTree.setModel(dtm); + dumpTree.expandFirstLevelNodes(); + } + break; + case VIEW_RESOURCES: + if (tagTree.getModel() == null) { + TagTreeModel ttm = new TagTreeModel(swfs, Configuration.tagTreeShowEmptyFolders.get()); + tagTree.setModel(ttm); + tagTree.expandFirstLevelNodes(); + } + break; + } + } + + private JPanel createDumpViewCard() { + JPanel r = new JPanel(new BorderLayout()); + r.add(new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(dumpTree), dumpPreviewPanel, Configuration.guiDumpSplitPaneDividerLocationPercent), BorderLayout.CENTER); + return r; + } + + private JPanel createResourcesViewCard() { + JPanel r = new JPanel(new BorderLayout()); + r.add(new JScrollPane(tagTree), BorderLayout.CENTER); + r.add(searchPanel, BorderLayout.SOUTH); + return r; + } + + public boolean showView(int view) { + + CardLayout cl = (CardLayout) (contentPanel.getLayout()); + CardLayout cl2 = (CardLayout) (treePanel.getLayout()); + + setTreeModel(view); + switch (view) { + case VIEW_DUMP: + if (!isWelcomeScreen) { + cl.show(contentPanel, SPLIT_PANE1); + } + cl2.show(treePanel, DUMP_VIEW); + treePanelMode = TreePanelMode.DUMP_TREE; + showDetail(DETAILCARDEMPTYPANEL); + reload(true); + return true; + case VIEW_RESOURCES: + if (!isWelcomeScreen) { + cl.show(contentPanel, SPLIT_PANE1); + } + cl2.show(treePanel, RESOURCES_VIEW); + + treePanelMode = TreePanelMode.TAG_TREE; + + treePanel.addComponentListener(new ComponentAdapter() { + + @Override + public void componentResized(ComponentEvent e) { + tagTree.scrollPathToVisible(tagTree.getSelectionPath()); + } + + }); + + reload(true); + return true; + case VIEW_TIMELINE: + final SWF swf = getCurrentSwf(); + if (swf != null) { + TreeItem item = tagTree.getCurrentTreeItem(); + if (item instanceof TagScript) { + item = ((TagScript) item).getTag(); + } + if (item instanceof Timelined) { + timelineViewPanel.setTimelined((Timelined) item); + } else if (item instanceof Frame) { + timelineViewPanel.setTimelined(((Frame) item).timeline.timelined); + } else { + timelineViewPanel.setTimelined(swf); + } + cl.show(contentPanel, TIMELINE_PANEL); + return true; + } + return false; + } + return false; + + } + + private void dumpViewReload(boolean forceReload) { + showDetail(DETAILCARDEMPTYPANEL); + + DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent(); + if (dumpInfo == null) { + showCard(CARDEMPTYPANEL); + return; + } + + dumpViewPanel.revalidate(); + dumpViewPanel.setSelectedNode(dumpInfo); + showCard(CARDDUMPVIEW); + } + + public void loadFromBinaryTag(final DefineBinaryDataTag binaryDataTag) { + loadFromBinaryTag(Arrays.asList(binaryDataTag)); + } + + public void loadFromBinaryTag(final List binaryDataTags) { + + Main.loadingDialog.setVisible(true); + new CancellableWorker() { + + @Override + protected Void doInBackground() throws Exception { + try { + for (DefineBinaryDataTag binaryDataTag : binaryDataTags) { + try { + InputStream is = new ByteArrayInputStream(binaryDataTag.binaryData.getRangeData()); + SWF bswf = new SWF(is, null, "(SWF Data)", new ProgressListener() { + + @Override + public void progress(int p) { + Main.loadingDialog.setPercent(p); + } + }, Configuration.parallelSpeedUp.get()); + binaryDataTag.innerSwf = bswf; + bswf.binaryData = binaryDataTag; + } catch (IOException ex) { + //ignore + } + } + } catch (InterruptedException ex) { + //ignore + } + + return null; + } + + @Override + protected void onStart() { + Main.startWork(AppStrings.translate("work.reading.swf") + "...", this); + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + Main.loadingDialog.setVisible(false); + Main.stopWork(); + }); + } + }.execute(); + } + + private void closeTag() { + previewPanel.closeTag(); + } + + public void showPreview(TreeItem treeItem, PreviewPanel previewPanel) { + previewPanel.clear(); + if (treeItem == null) { + previewPanel.showEmpty(); + return; + } + boolean internalViewer = isInternalFlashViewerSelected(); + if (treeItem instanceof SWF) { + SWF swf = (SWF) treeItem; + if (internalViewer) { + previewPanel.showImagePanel(swf, swf, -1); + } else { + previewPanel.setParametersPanelVisible(false); + if (flashPanel != null) { //same for flashPanel2 + previewPanel.showFlashViewerPanel(); + previewPanel.showSwf(swf); + } + } + } else if (treeItem instanceof MetadataTag) { + MetadataTag metadataTag = (MetadataTag) treeItem; + previewPanel.showMetaDataPanel(metadataTag); + } else if (treeItem instanceof DefineBinaryDataTag) { + DefineBinaryDataTag binaryTag = (DefineBinaryDataTag) treeItem; + previewPanel.showBinaryPanel(binaryTag); + } else if (treeItem instanceof ImageTag) { + ImageTag imageTag = (ImageTag) treeItem; + previewPanel.setImageReplaceButtonVisible(!((Tag) imageTag).isReadOnly() && imageTag.importSupported(), imageTag instanceof DefineBitsJPEG3Tag || imageTag instanceof DefineBitsJPEG4Tag); + previewPanel.showImagePanel(imageTag.getImageCached()); + + } else if ((treeItem instanceof DrawableTag) && (!(treeItem instanceof TextTag)) && (!(treeItem instanceof FontTag)) && internalViewer) { + final Tag tag = (Tag) treeItem; + DrawableTag d = (DrawableTag) tag; + Timelined timelined; + if (treeItem instanceof Timelined && !(treeItem instanceof ButtonTag)) { + timelined = (Timelined) tag; + } else { + timelined = makeTimelined(tag); + } + + previewPanel.setParametersPanelVisible(false); + previewPanel.showImagePanel(timelined, tag.getSwf(), -1); + } else if (treeItem instanceof Frame && internalViewer) { + Frame fn = (Frame) treeItem; + SWF swf = fn.getSwf(); + previewPanel.showImagePanel(fn.timeline.timelined, swf, fn.frame); + } else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) { + previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32"))); + previewPanel.setImageReplaceButtonVisible(((Tag) treeItem).isReadOnly() && (treeItem instanceof DefineSoundTag), false); + try { + SoundTagPlayer soundThread = new SoundTagPlayer((SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true); + previewPanel.setMedia(soundThread); + } catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) { + logger.log(Level.SEVERE, null, ex); + } + + } else if ((treeItem instanceof FontTag) && internalViewer) { + previewPanel.showFontPanel((FontTag) treeItem); + } else if ((treeItem instanceof TextTag) && internalViewer) { + previewPanel.showTextPanel((TextTag) treeItem); + } else if ((treeItem instanceof Frame) || (treeItem instanceof CharacterTag) || (treeItem instanceof FontTag) || (treeItem instanceof SoundStreamHeadTypeTag)) { + previewPanel.createAndShowTempSwf(treeItem); + + if (treeItem instanceof TextTag) { + previewPanel.showTextPanel((TextTag) treeItem); + } else if (treeItem instanceof FontTag) { + previewPanel.showFontPanel((FontTag) treeItem); + } else { + previewPanel.setParametersPanelVisible(false); + } + } else { + previewPanel.showEmpty(); + } + } + + public void reload(boolean forceReload) { + tagTree.scrollPathToVisible(tagTree.getSelectionPath()); + if (Configuration.dumpView.get()) { + dumpViewReload(forceReload); + return; + } + + TreeItem treeItem = null; + TreePath treePath = tagTree.getSelectionPath(); + if (treePath != null && tagTree.getModel().treePathExists(treePath)) { + treeItem = (TreeItem) treePath.getLastPathComponent(); + } + + // save last selected node to config + if (treeItem != null) { + SWF swf = treeItem.getSwf(); + if (swf != null) { + swf = swf.getRootSwf(); + } + + if (swf != null) { + SwfSpecificConfiguration swfConf = Configuration.getOrCreateSwfSpecificConfiguration(swf.getShortFileName()); + swfConf.lastSelectedPath = tagTree.getSelectionPathString(); + } + } + + if (!forceReload && (treeItem == oldItem)) { + return; + } + + if (oldItem != treeItem) { + closeTag(); + } + + oldItem = treeItem; + + // show the preview of the tag when the user clicks to the tagname inside the scripts node, too + // this is a little bit inconsistent, beacuse the frames (FrameScript) are not shown + boolean preferScript = false; + if (treeItem instanceof TagScript) { + treeItem = ((TagScript) treeItem).getTag(); + preferScript = true; + } + + folderPreviewPanel.clear(); + previewPanel.clear(); + stopFlashPlayer(); + + previewPanel.setImageReplaceButtonVisible(false, false); + + boolean internalViewer = isInternalFlashViewerSelected(); + + if (treeItem instanceof ScriptPack) { + final ScriptPack scriptLeaf = (ScriptPack) treeItem; + if (setSourceWorker != null) { + setSourceWorker.cancel(true); + setSourceWorker = null; + } + if (!Main.isInited() || !Main.isWorking() || Main.isDebugging()) { + CancellableWorker worker = new CancellableWorker() { + + @Override + protected Void doInBackground() throws Exception { + ABCPanel abcPanel = getABCPanel(); + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.clear(); + abcPanel.setAbc(scriptLeaf.abc); + abcPanel.decompiledTextArea.setScript(scriptLeaf, true); + abcPanel.decompiledTextArea.setNoTrait(); + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.decompiling") + "...", this); + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + setSourceWorker = null; + try { + get(); + } catch (CancellationException ex) { + getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("work.canceled")); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error", ex); + getABCPanel().decompiledTextArea.setText("// " + AppStrings.translate("decompilationError") + ": " + ex); + } + + Main.stopWork(); + }); + } + }; + + worker.execute(); + setSourceWorker = worker; + } + + showDetail(DETAILCARDAS3NAVIGATOR); + showCard(CARDACTIONSCRIPT3PANEL); + return; + } + + if (treeItem instanceof Tag) { + Tag tag = (Tag) treeItem; + TagInfo tagInfo = new TagInfo(); + tag.getTagInfo(tagInfo); + if (!tagInfo.isEmpty()) { + tagInfoPanel.setTagInfos(tagInfo); + showDetail(DETAILCARDTAGINFO); + } else { + showDetail(DETAILCARDEMPTYPANEL); + } + } else { + showDetail(DETAILCARDEMPTYPANEL); + } + + if (treeItem instanceof HeaderItem) { + headerPanel.load(((HeaderItem) treeItem).getSwf()); + showCard(CARDHEADER); + } else if (treeItem instanceof FolderItem) { + showFolderPreview((FolderItem) treeItem); + } else if (treeItem instanceof SWF) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if (treeItem instanceof MetadataTag) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if (treeItem instanceof DefineBinaryDataTag) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if (treeItem instanceof ASMSource && (!(treeItem instanceof DrawableTag) || preferScript)) { + getActionPanel().setSource((ASMSource) treeItem, !forceReload); + showCard(CARDACTIONSCRIPTPANEL); + } else if (treeItem instanceof ImageTag) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if ((treeItem instanceof DrawableTag) && (!(treeItem instanceof TextTag)) && (!(treeItem instanceof FontTag)) && internalViewer) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if ((treeItem instanceof FontTag) && internalViewer) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if ((treeItem instanceof TextTag) && internalViewer) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if (treeItem instanceof Frame && internalViewer) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) { + showPreview(treeItem, previewPanel); + showCard(CARDPREVIEWPANEL); + } else if ((treeItem instanceof Frame) || (treeItem instanceof CharacterTag) || (treeItem instanceof FontTag) || (treeItem instanceof SoundStreamHeadTypeTag)) { + showPreview(treeItem, previewPanel); + + showCard(CARDPREVIEWPANEL); + } else if (treeItem instanceof Tag) { + showGenericTag((Tag) treeItem); + } else { + showCard(CARDEMPTYPANEL); + } + } + + public void repaintTree() { + tagTree.repaint(); + reload(true); + } + + public void showGenericTag(Tag tag) { + previewPanel.showGenericTagPanel(tag); + showCard(CARDPREVIEWPANEL); + } + + public void showTextTagWithNewValue(TextTag textTag, TextTag newTextTag) { + + previewPanel.showTextComparePanel(textTag, newTextTag); + } + + private void showFolderPreview(FolderItem item) { + List folderPreviewItems = new ArrayList<>(); + String folderName = item.getName(); + SWF swf = item.swf; + switch (folderName) { + case TagTreeModel.FOLDER_SHAPES: + for (Tag tag : swf.getTags()) { + if (tag instanceof ShapeTag) { + folderPreviewItems.add(tag); + } + } + break; + case TagTreeModel.FOLDER_MORPHSHAPES: + for (Tag tag : swf.getTags()) { + if (tag instanceof MorphShapeTag) { + folderPreviewItems.add(tag); + } + } + break; + case TagTreeModel.FOLDER_SPRITES: + for (Tag tag : swf.getTags()) { + if (tag instanceof DefineSpriteTag) { + folderPreviewItems.add(tag); + } + } + break; + case TagTreeModel.FOLDER_BUTTONS: + for (Tag tag : swf.getTags()) { + if (tag instanceof ButtonTag) { + folderPreviewItems.add(tag); + } + } + break; + case TagTreeModel.FOLDER_FONTS: + for (Tag tag : swf.getTags()) { + if (tag instanceof FontTag) { + folderPreviewItems.add(tag); + } + } + break; + case TagTreeModel.FOLDER_FRAMES: + for (Frame frame : swf.getTimeline().getFrames()) { + folderPreviewItems.add(frame); + } + break; + case TagTreeModel.FOLDER_IMAGES: + for (Tag tag : swf.getTags()) { + if (tag instanceof ImageTag) { + folderPreviewItems.add(tag); + } + } + break; + case TagTreeModel.FOLDER_TEXTS: + for (Tag tag : swf.getTags()) { + if (tag instanceof TextTag) { + folderPreviewItems.add(tag); + } + } + break; + } + + folderPreviewPanel.setItems(folderPreviewItems); + showCard(CARDFOLDERPREVIEWPANEL); + } + + private boolean isFreeing; + + @Override + public boolean isFreeing() { + return isFreeing; + } + + @Override + public void free() { + isFreeing = true; + } + + public void setErrorState(ErrorState errorState) { + statusPanel.setErrorState(errorState); + } + + public static Timelined makeTimelined(final Tag tag) { + return makeTimelined(tag, -1); + } + + public static Timelined makeTimelined(final Tag tag, final int fontFrameNum) { + + return new Timelined() { + + private Timeline tim; + + @Override + public Timeline getTimeline() { + if (tim == null) { + Timeline timeline = new Timeline(tag.getSwf(), this, ((CharacterTag) tag).getCharacterId(), getRect()); + initTimeline(timeline); + tim = timeline; + } + + return tim; + } + + @Override + public void resetTimeline() { + if (tim != null) { + tim.reset(tag.getSwf(), this, ((CharacterTag) tag).getCharacterId(), getRect()); + initTimeline(tim); + } + } + + private void initTimeline(Timeline timeline) { + if (tag instanceof MorphShapeTag) { + timeline.frameRate = MORPH_SHAPE_ANIMATION_FRAME_RATE; + int framesCnt = (int) (timeline.frameRate * MORPH_SHAPE_ANIMATION_LENGTH); + for (int i = 0; i < framesCnt; i++) { + Frame f = new Frame(timeline, i); + DepthState ds = new DepthState(tag.getSwf(), f); + ds.characterId = ((CharacterTag) tag).getCharacterId(); + ds.matrix = new MATRIX(); + ds.ratio = i * 65535 / framesCnt; + f.layers.put(1, ds); + f.layersChanged = true; + timeline.addFrame(f); + } + } else if (tag instanceof FontTag) { + int pageCount = PreviewPanel.getFontPageCount((FontTag) tag); + int frame = fontFrameNum; + if (frame < 0 || frame >= pageCount) { + frame = 0; + } + + Frame f = new Frame(timeline, 0); + DepthState ds = new DepthState(tag.getSwf(), f); + ds.characterId = ((CharacterTag) tag).getCharacterId(); + ds.matrix = new MATRIX(); + f.layers.put(1, ds); + f.layersChanged = true; + timeline.addFrame(f); + timeline.fontFrameNum = frame; + } else { + Frame f = new Frame(timeline, 0); + DepthState ds = new DepthState(tag.getSwf(), f); + ds.characterId = ((CharacterTag) tag).getCharacterId(); + ds.matrix = new MATRIX(); + f.layers.put(1, ds); + timeline.addFrame(f); + } + timeline.displayRect = getRect(); + } + + @Override + public RECT getRect() { + return getRect(new HashSet<>()); + } + + @Override + public RECT getRect(Set added) { + BoundedTag bt = (BoundedTag) tag; + if (!added.contains(bt)) { + return bt.getRect(added); + } + return new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE); + } + + @Override + public int hashCode() { + return tag.hashCode(); + } + + @Override + public void setModified(boolean value) { + } + + @Override + public ReadOnlyTagList getTags() { + return ReadOnlyTagList.EMPTY; + } + + @Override + public void removeTag(int index) { + } + + @Override + public void removeTag(Tag tag) { + } + + @Override + public void addTag(Tag tag) { + } + + @Override + public void addTag(int index, Tag tag) { + } + }; + } + + private void disposeInner(Container container) { + for (Component c : container.getComponents()) { + if (c instanceof Container) { + Container c2 = (Container) c; + disposeInner(c2); + } + } + + container.removeAll(); + container.setLayout(null); + if (container instanceof TagEditorPanel) { + Helper.emptyObject(container); + } + } + + public void dispose() { + setDropTarget(null); + disposeInner(this); + Helper.emptyObject(this); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/QuickFindPanel.java b/src/com/jpexs/decompiler/flash/gui/QuickFindPanel.java index ccecbcf8c..70742dd6f 100644 --- a/src/com/jpexs/decompiler/flash/gui/QuickFindPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/QuickFindPanel.java @@ -1,247 +1,247 @@ -/* - * Copyright (C) 2010-2016 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 java.awt.Color; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.lang.ref.WeakReference; -import java.util.ResourceBundle; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.border.BevelBorder; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.JTextComponent; -import jsyntaxpane.actions.DocumentSearchData; -import jsyntaxpane.components.Markers; - -/** - * - * @author JPEXS - */ -public class QuickFindPanel extends JPanel { - - public JTextField findTextField; - - public JButton prevButton, nextButton; - - public JCheckBox ignoreCaseCheckbox, regExpCheckbox, wrapCheckbox; - - public JLabel statusLabel; - - private final Markers.SimpleMarker marker = new Markers.SimpleMarker(Color.pink); - - private WeakReference target; - - private WeakReference dsd; - - private int oldCaretPosition; - - public QuickFindPanel() { - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - - setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); - - JPanel pan1 = new JPanel(new WrapLayout()); - JPanel pan2 = new JPanel(new WrapLayout()); - pan1.setAlignmentX(0); - pan2.setAlignmentX(0); - pan1.setAlignmentY(0); - pan2.setAlignmentY(0); - - JLabel jLabel1 = new javax.swing.JLabel(); - findTextField = new javax.swing.JTextField(); - prevButton = new javax.swing.JButton(); - nextButton = new javax.swing.JButton(); - ignoreCaseCheckbox = new javax.swing.JCheckBox(); - regExpCheckbox = new javax.swing.JCheckBox(); - wrapCheckbox = new javax.swing.JCheckBox(); - statusLabel = new javax.swing.JLabel(); - - setName("QuickFindDialog"); - - jLabel1.setLabelFor(findTextField); - ResourceBundle bundle = ResourceBundle.getBundle("jsyntaxpane/Bundle"); - jLabel1.setText(bundle.getString("QuickFindDialog.jLabel1.text")); - pan1.add(jLabel1); - - findTextField.setColumns(30); - findTextField.setBorder(javax.swing.BorderFactory.createLineBorder(Color.black)); - findTextField.setMaximumSize(new java.awt.Dimension(200, 24)); - findTextField.setMinimumSize(new java.awt.Dimension(60, 24)); - pan1.add(findTextField); - - prevButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/META-INF/images/small-icons/go-up.png"))); - prevButton.setFocusable(false); - prevButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - prevButton.setOpaque(false); - prevButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - prevButton.addActionListener(this::previousButtonActionPerformed); - pan1.add(prevButton); - - nextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/META-INF/images/small-icons/go-down.png"))); - nextButton.setFocusable(false); - nextButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - nextButton.setMargin(new java.awt.Insets(2, 2, 2, 2)); - nextButton.setOpaque(false); - nextButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - nextButton.addActionListener(this::nextButtonActionPerformed); - pan1.add(nextButton); - - ignoreCaseCheckbox.setMnemonic('C'); - ignoreCaseCheckbox.setText(bundle.getString("QuickFindDialog.jChkIgnoreCase.text")); - ignoreCaseCheckbox.setFocusable(false); - ignoreCaseCheckbox.setOpaque(false); - ignoreCaseCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - pan2.add(ignoreCaseCheckbox); - //ignoreCaseCheckbox.addActionListener(this); - - regExpCheckbox.setMnemonic('R'); - regExpCheckbox.setText(bundle.getString("QuickFindDialog.jChkRegExp.text")); - regExpCheckbox.setFocusable(false); - regExpCheckbox.setOpaque(false); - regExpCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - pan2.add(regExpCheckbox); - //regExpCheckbox.addActionListener(this); - - wrapCheckbox.setMnemonic('W'); - wrapCheckbox.setText(bundle.getString("QuickFindDialog.jChkWrap.text")); - wrapCheckbox.setFocusable(false); - wrapCheckbox.setOpaque(false); - wrapCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - pan2.add(wrapCheckbox); - //wrapCheckbox.addActionListener(this); - - statusLabel.setFont(statusLabel.getFont().deriveFont(statusLabel.getFont().getStyle() | java.awt.Font.BOLD, statusLabel.getFont().getSize() - 2)); - statusLabel.setForeground(Color.red); - pan2.add(statusLabel); - - add(pan1); - add(pan2); - setPreferredSize(getMinimumSize()); - setVisible(false); - } - - private void previousButtonActionPerformed(ActionEvent evt) { - if (dsd.get().doFindPrev(target.get())) { - statusLabel.setText(null); - } else { - statusLabel.setText(java.util.ResourceBundle.getBundle("jsyntaxpane/Bundle").getString("QuickFindDialog.NotFound")); - } - } - - private void nextButtonActionPerformed(ActionEvent evt) { - if (dsd.get().doFindNext(target.get())) { - statusLabel.setText(null); - } else { - statusLabel.setText(java.util.ResourceBundle.getBundle("jsyntaxpane/Bundle").getString("QuickFindDialog.NotFound")); - } - } - - public void showQuickFind(final JTextComponent t, DocumentSearchData ds) { - dsd = new WeakReference<>(ds); - oldCaretPosition = t.getCaretPosition(); - Container view = t.getParent(); - Dimension wd = getSize(); - wd.width = t.getVisibleRect().width; - Point loc = new Point(0, view.getHeight()); - setSize(wd); - SwingUtilities.convertPointToScreen(loc, view); - setLocation(loc); - findTextField.setFont(t.getFont()); - final DocumentListener dl; - findTextField.getDocument().addDocumentListener(dl = new DocumentListener() { - - @Override - public void insertUpdate(DocumentEvent e) { - updateFind(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - updateFind(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - updateFind(); - } - - private void updateFind() { - JTextComponent t = target.get(); - DocumentSearchData d = dsd.get(); - String toFind = findTextField.getText(); - if (toFind == null || toFind.isEmpty()) { - statusLabel.setText(null); - return; - } - try { - d.setWrap(wrapCheckbox.isSelected()); - d.setPattern(toFind, - regExpCheckbox.isSelected(), - ignoreCaseCheckbox.isSelected()); - // The dsd doFindNext will always find from current pos, - // so we need to relocate to our saved pos before we call doFindNext - statusLabel.setText(null); - t.setCaretPosition(oldCaretPosition); - if (!d.doFindNext(t)) { - statusLabel.setText(java.util.ResourceBundle.getBundle("jsyntaxpane/Bundle").getString("QuickFindDialog.NotFound")); - } else { - statusLabel.setText(null); - } - } catch (PatternSyntaxException e) { - statusLabel.setText(e.getDescription()); - } - } - }); - this.target = new WeakReference<>(t); - Pattern p = dsd.get().getPattern(); - if (p != null) { - findTextField.setText(p.pattern()); - } - wrapCheckbox.setSelected(dsd.get().isWrap()); - - setVisible(true); - getParent().revalidate(); - getParent().repaint(); - findTextField.requestFocusInWindow(); - } - /* - @Override - public void focusGained(FocusEvent e) { - - } - - @Override - public void focusLost(FocusEvent e) { - removeFocusListener(this); - setVisible(false); - getParent().revalidate(); - getParent().repaint(); - }*/ -} +/* + * Copyright (C) 2010-2016 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 java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.lang.ref.WeakReference; +import java.util.ResourceBundle; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.border.BevelBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.JTextComponent; +import jsyntaxpane.actions.DocumentSearchData; +import jsyntaxpane.components.Markers; + +/** + * + * @author JPEXS + */ +public class QuickFindPanel extends JPanel { + + public JTextField findTextField; + + public JButton prevButton, nextButton; + + public JCheckBox ignoreCaseCheckbox, regExpCheckbox, wrapCheckbox; + + public JLabel statusLabel; + + private final Markers.SimpleMarker marker = new Markers.SimpleMarker(Color.pink); + + private WeakReference target; + + private WeakReference dsd; + + private int oldCaretPosition; + + public QuickFindPanel() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); + + JPanel pan1 = new JPanel(new WrapLayout()); + JPanel pan2 = new JPanel(new WrapLayout()); + pan1.setAlignmentX(0); + pan2.setAlignmentX(0); + pan1.setAlignmentY(0); + pan2.setAlignmentY(0); + + JLabel jLabel1 = new javax.swing.JLabel(); + findTextField = new javax.swing.JTextField(); + prevButton = new javax.swing.JButton(); + nextButton = new javax.swing.JButton(); + ignoreCaseCheckbox = new javax.swing.JCheckBox(); + regExpCheckbox = new javax.swing.JCheckBox(); + wrapCheckbox = new javax.swing.JCheckBox(); + statusLabel = new javax.swing.JLabel(); + + setName("QuickFindDialog"); + + jLabel1.setLabelFor(findTextField); + ResourceBundle bundle = ResourceBundle.getBundle("jsyntaxpane/Bundle"); + jLabel1.setText(bundle.getString("QuickFindDialog.jLabel1.text")); + pan1.add(jLabel1); + + findTextField.setColumns(30); + findTextField.setBorder(javax.swing.BorderFactory.createLineBorder(Color.black)); + findTextField.setMaximumSize(new java.awt.Dimension(200, 24)); + findTextField.setMinimumSize(new java.awt.Dimension(60, 24)); + pan1.add(findTextField); + + prevButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/META-INF/images/small-icons/go-up.png"))); + prevButton.setFocusable(false); + prevButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + prevButton.setOpaque(false); + prevButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + prevButton.addActionListener(this::previousButtonActionPerformed); + pan1.add(prevButton); + + nextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/META-INF/images/small-icons/go-down.png"))); + nextButton.setFocusable(false); + nextButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + nextButton.setMargin(new java.awt.Insets(2, 2, 2, 2)); + nextButton.setOpaque(false); + nextButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + nextButton.addActionListener(this::nextButtonActionPerformed); + pan1.add(nextButton); + + ignoreCaseCheckbox.setMnemonic('C'); + ignoreCaseCheckbox.setText(bundle.getString("QuickFindDialog.jChkIgnoreCase.text")); + ignoreCaseCheckbox.setFocusable(false); + ignoreCaseCheckbox.setOpaque(false); + ignoreCaseCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + pan2.add(ignoreCaseCheckbox); + //ignoreCaseCheckbox.addActionListener(this); + + regExpCheckbox.setMnemonic('R'); + regExpCheckbox.setText(bundle.getString("QuickFindDialog.jChkRegExp.text")); + regExpCheckbox.setFocusable(false); + regExpCheckbox.setOpaque(false); + regExpCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + pan2.add(regExpCheckbox); + //regExpCheckbox.addActionListener(this); + + wrapCheckbox.setMnemonic('W'); + wrapCheckbox.setText(bundle.getString("QuickFindDialog.jChkWrap.text")); + wrapCheckbox.setFocusable(false); + wrapCheckbox.setOpaque(false); + wrapCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + pan2.add(wrapCheckbox); + //wrapCheckbox.addActionListener(this); + + statusLabel.setFont(statusLabel.getFont().deriveFont(statusLabel.getFont().getStyle() | java.awt.Font.BOLD, statusLabel.getFont().getSize() - 2)); + statusLabel.setForeground(Color.red); + pan2.add(statusLabel); + + add(pan1); + add(pan2); + setPreferredSize(getMinimumSize()); + setVisible(false); + } + + private void previousButtonActionPerformed(ActionEvent evt) { + if (dsd.get().doFindPrev(target.get())) { + statusLabel.setText(null); + } else { + statusLabel.setText(java.util.ResourceBundle.getBundle("jsyntaxpane/Bundle").getString("QuickFindDialog.NotFound")); + } + } + + private void nextButtonActionPerformed(ActionEvent evt) { + if (dsd.get().doFindNext(target.get())) { + statusLabel.setText(null); + } else { + statusLabel.setText(java.util.ResourceBundle.getBundle("jsyntaxpane/Bundle").getString("QuickFindDialog.NotFound")); + } + } + + public void showQuickFind(final JTextComponent t, DocumentSearchData ds) { + dsd = new WeakReference<>(ds); + oldCaretPosition = t.getCaretPosition(); + Container view = t.getParent(); + Dimension wd = getSize(); + wd.width = t.getVisibleRect().width; + Point loc = new Point(0, view.getHeight()); + setSize(wd); + SwingUtilities.convertPointToScreen(loc, view); + setLocation(loc); + findTextField.setFont(t.getFont()); + final DocumentListener dl; + findTextField.getDocument().addDocumentListener(dl = new DocumentListener() { + + @Override + public void insertUpdate(DocumentEvent e) { + updateFind(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + updateFind(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + updateFind(); + } + + private void updateFind() { + JTextComponent t = target.get(); + DocumentSearchData d = dsd.get(); + String toFind = findTextField.getText(); + if (toFind == null || toFind.isEmpty()) { + statusLabel.setText(null); + return; + } + try { + d.setWrap(wrapCheckbox.isSelected()); + d.setPattern(toFind, + regExpCheckbox.isSelected(), + ignoreCaseCheckbox.isSelected()); + // The dsd doFindNext will always find from current pos, + // so we need to relocate to our saved pos before we call doFindNext + statusLabel.setText(null); + t.setCaretPosition(oldCaretPosition); + if (!d.doFindNext(t)) { + statusLabel.setText(java.util.ResourceBundle.getBundle("jsyntaxpane/Bundle").getString("QuickFindDialog.NotFound")); + } else { + statusLabel.setText(null); + } + } catch (PatternSyntaxException e) { + statusLabel.setText(e.getDescription()); + } + } + }); + this.target = new WeakReference<>(t); + Pattern p = dsd.get().getPattern(); + if (p != null) { + findTextField.setText(p.pattern()); + } + wrapCheckbox.setSelected(dsd.get().isWrap()); + + setVisible(true); + getParent().revalidate(); + getParent().repaint(); + findTextField.requestFocusInWindow(); + } + /* + @Override + public void focusGained(FocusEvent e) { + + } + + @Override + public void focusLost(FocusEvent e) { + removeFocusListener(this); + setVisible(false); + getParent().revalidate(); + getParent().repaint(); + }*/ +} diff --git a/src/com/jpexs/decompiler/flash/gui/SearchPanel.java b/src/com/jpexs/decompiler/flash/gui/SearchPanel.java index 1212b83f5..7d3effb8b 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchPanel.java @@ -1,142 +1,142 @@ -/* - * Copyright (C) 2010-2016 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 java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.text.JTextComponent; -import jsyntaxpane.actions.DocumentSearchData; - -/** - * - * @author JPEXS - * @param Element to search - */ -public class SearchPanel extends JPanel { - - private final SearchListener listener; - - private final JLabel searchPos; - - private int foundPos = 0; - - private final JLabel searchForLabel; - - private String searchFor; - - private boolean searchIgnoreCase; - - private boolean searchRegexp; - - private List found = new ArrayList<>(); - - public SearchPanel(LayoutManager lm, SearchListener listener) { - super(lm); - - this.listener = listener; - - JButton prevSearchButton = new JButton(View.getIcon("prev16")); - prevSearchButton.setMargin(new Insets(3, 3, 3, 3)); - prevSearchButton.addActionListener(this::prevButtonActionPerformed); - JButton nextSearchButton = new JButton(View.getIcon("next16")); - nextSearchButton.setMargin(new Insets(3, 3, 3, 3)); - nextSearchButton.addActionListener(this::nextButtonActionPerformed); - JButton cancelSearchButton = new JButton(View.getIcon("cancel16")); - cancelSearchButton.setMargin(new Insets(3, 3, 3, 3)); - cancelSearchButton.addActionListener(this::cancelButtonActionPerformed); - searchPos = new JLabel("0/0"); - searchForLabel = new JLabel(AppStrings.translate("search.info").replace("%text%", "")); - add(searchForLabel); - add(prevSearchButton); - add(new JLabel(AppStrings.translate("search.script") + " ")); - add(searchPos); - add(nextSearchButton); - add(cancelSearchButton); - setVisible(false); - } - - public void showQuickFindDialog(JTextComponent editor) { - DocumentSearchData dsd = DocumentSearchData.getFromEditor(editor); - dsd.setPattern(searchFor, searchRegexp, searchIgnoreCase); - dsd.showQuickFindDialogEx(editor, searchIgnoreCase, searchRegexp); - } - - public void setSearchText(String txt) { - searchFor = txt; - searchForLabel.setText(AppStrings.translate("search.info").replace("%text%", txt) + " "); - } - - public boolean setResults(List results) { - found = results; - if (found.isEmpty()) { - setVisible(false); - return false; - } else { - setPos(0); - setVisible(true); - return true; - } - } - - public void setOptions(boolean ignoreCase, boolean regExp) { - searchIgnoreCase = ignoreCase; - searchRegexp = regExp; - } - - public void setPos(int pos) { - foundPos = pos; - doUpdate(); - } - - public void clear() { - foundPos = 0; - found.clear(); - } - - private void doUpdate() { - View.execInEventDispatchLater(() -> { - searchPos.setText((foundPos + 1) + "/" + found.size()); - listener.updateSearchPos(found.get(foundPos)); - }); - } - - private void cancelButtonActionPerformed(ActionEvent evt) { - foundPos = 0; - setVisible(false); - found = new ArrayList<>(); - searchFor = null; - } - - private void prevButtonActionPerformed(ActionEvent evt) { - foundPos--; - if (foundPos < 0) { - foundPos += found.size(); - } - doUpdate(); - } - - private void nextButtonActionPerformed(ActionEvent evt) { - foundPos = (foundPos + 1) % found.size(); - doUpdate(); - } -} +/* + * Copyright (C) 2010-2016 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 java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.text.JTextComponent; +import jsyntaxpane.actions.DocumentSearchData; + +/** + * + * @author JPEXS + * @param Element to search + */ +public class SearchPanel extends JPanel { + + private final SearchListener listener; + + private final JLabel searchPos; + + private int foundPos = 0; + + private final JLabel searchForLabel; + + private String searchFor; + + private boolean searchIgnoreCase; + + private boolean searchRegexp; + + private List found = new ArrayList<>(); + + public SearchPanel(LayoutManager lm, SearchListener listener) { + super(lm); + + this.listener = listener; + + JButton prevSearchButton = new JButton(View.getIcon("prev16")); + prevSearchButton.setMargin(new Insets(3, 3, 3, 3)); + prevSearchButton.addActionListener(this::prevButtonActionPerformed); + JButton nextSearchButton = new JButton(View.getIcon("next16")); + nextSearchButton.setMargin(new Insets(3, 3, 3, 3)); + nextSearchButton.addActionListener(this::nextButtonActionPerformed); + JButton cancelSearchButton = new JButton(View.getIcon("cancel16")); + cancelSearchButton.setMargin(new Insets(3, 3, 3, 3)); + cancelSearchButton.addActionListener(this::cancelButtonActionPerformed); + searchPos = new JLabel("0/0"); + searchForLabel = new JLabel(AppStrings.translate("search.info").replace("%text%", "")); + add(searchForLabel); + add(prevSearchButton); + add(new JLabel(AppStrings.translate("search.script") + " ")); + add(searchPos); + add(nextSearchButton); + add(cancelSearchButton); + setVisible(false); + } + + public void showQuickFindDialog(JTextComponent editor) { + DocumentSearchData dsd = DocumentSearchData.getFromEditor(editor); + dsd.setPattern(searchFor, searchRegexp, searchIgnoreCase); + dsd.showQuickFindDialogEx(editor, searchIgnoreCase, searchRegexp); + } + + public void setSearchText(String txt) { + searchFor = txt; + searchForLabel.setText(AppStrings.translate("search.info").replace("%text%", txt) + " "); + } + + public boolean setResults(List results) { + found = results; + if (found.isEmpty()) { + setVisible(false); + return false; + } else { + setPos(0); + setVisible(true); + return true; + } + } + + public void setOptions(boolean ignoreCase, boolean regExp) { + searchIgnoreCase = ignoreCase; + searchRegexp = regExp; + } + + public void setPos(int pos) { + foundPos = pos; + doUpdate(); + } + + public void clear() { + foundPos = 0; + found.clear(); + } + + private void doUpdate() { + View.execInEventDispatchLater(() -> { + searchPos.setText((foundPos + 1) + "/" + found.size()); + listener.updateSearchPos(found.get(foundPos)); + }); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + foundPos = 0; + setVisible(false); + found = new ArrayList<>(); + searchFor = null; + } + + private void prevButtonActionPerformed(ActionEvent evt) { + foundPos--; + if (foundPos < 0) { + foundPos += found.size(); + } + doUpdate(); + } + + private void nextButtonActionPerformed(ActionEvent evt) { + foundPos = (foundPos + 1) % found.size(); + doUpdate(); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 44430615e..91184b9b8 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -1,728 +1,728 @@ -/* - * Copyright (C) 2010-2016 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.abc; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.CachedDecompilation; -import com.jpexs.decompiler.flash.abc.ScriptPack; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; -import com.jpexs.decompiler.flash.abc.types.ClassInfo; -import com.jpexs.decompiler.flash.abc.types.InstanceInfo; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.ScriptInfo; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; -import com.jpexs.decompiler.flash.gui.AppStrings; -import com.jpexs.decompiler.flash.gui.View; -import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.graph.DottedChain; -import java.awt.Point; -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import jsyntaxpane.SyntaxDocument; -import jsyntaxpane.Token; -import jsyntaxpane.TokenType; - -/** - * - * @author JPEXS - */ -public class DecompiledEditorPane extends DebuggableEditorPane implements CaretListener { - - private List highlights = new ArrayList<>(); - - private List specialHighlights = new ArrayList<>(); - - private List traitHighlights = new ArrayList<>(); - - private List methodHighlights = new ArrayList<>(); - - private List classHighlights = new ArrayList<>(); - - private Highlighting currentMethodHighlight; - - private Highlighting currentTraitHighlight; - - private ScriptPack script; - - public int lastTraitIndex = 0; - - public boolean ignoreCarret = false; - - private boolean reset = false; - - private final ABCPanel abcPanel; - - private int classIndex = -1; - - private boolean isStatic = false; - - private final List scriptListeners = new ArrayList<>(); - - public void addScriptListener(Runnable l) { - scriptListeners.add(l); - } - - public ABCPanel getAbcPanel() { - return abcPanel; - } - - public void removeScriptListener(Runnable l) { - scriptListeners.remove(l); - } - - public void fireScript() { - Runnable[] listeners = scriptListeners.toArray(new Runnable[scriptListeners.size()]); - for (Runnable scriptListener : listeners) { - scriptListener.run(); - } - } - - public Trait getCurrentTrait() { - return script.abc.findTraitByTraitId(classIndex, lastTraitIndex); - } - - public ScriptPack getScriptLeaf() { - return script; - } - - public boolean getIsStatic() { - return isStatic; - } - - public void setNoTrait() { - abcPanel.detailPanel.showCard(DetailPanel.UNSUPPORTED_TRAIT_CARD, null); - } - - public void hilightSpecial(HighlightSpecialType type, long index) { - int startPos; - int endPos; - if (currentMethodHighlight == null) { - if (currentTraitHighlight == null) { - return; - } - startPos = currentTraitHighlight.startPos; - endPos = currentTraitHighlight.startPos + currentTraitHighlight.len; - } else { - startPos = currentMethodHighlight.startPos; - endPos = currentMethodHighlight.startPos + currentMethodHighlight.len; - } - - List allh = new ArrayList<>(); - for (Highlighting h : traitHighlights) { - if (h.getProperties().index == lastTraitIndex) { - for (Highlighting sh : specialHighlights) { - if (sh.startPos >= h.startPos && (sh.startPos + sh.len < h.startPos + h.len)) { - allh.add(sh); - } - } - } - } - if (currentMethodHighlight != null) { - for (Highlighting h : specialHighlights) { - if (h.startPos >= startPos && (h.startPos + h.len < endPos)) { - allh.add(h); - } - } - } - for (Highlighting h : allh) { - if (h.getProperties().subtype.equals(type) && (h.getProperties().index == index)) { - ignoreCarret = true; - if (h.startPos <= getDocument().getLength()) { - setCaretPosition(h.startPos); - } - getCaret().setVisible(true); - ignoreCarret = false; - break; - } - } - } - - public void hilightOffset(long offset) { - if (currentMethodHighlight == null) { - return; - } - for (Highlighting h : traitHighlights) { - if (h.getProperties().index == lastTraitIndex) { - Highlighting h2 = Highlighting.searchOffset(highlights, offset, h.startPos, h.startPos + h.len); - if (h2 != null) { - ignoreCarret = true; - if (h2.startPos <= getDocument().getLength()) { - setCaretPosition(h2.startPos); - } - getCaret().setVisible(true); - ignoreCarret = false; - } - - } - } - } - - public void setClassIndex(int classIndex) { - this.classIndex = classIndex; - } - - private boolean displayMethod(int pos, int methodIndex, String name, Trait trait, boolean isStatic) { - ABC abc = getABC(); - if (abc == null) { - return false; - } - int bi = abc.findBodyIndex(methodIndex); - if (bi == -1) { - return false; - } - - //fix for inner functions: - if (trait instanceof TraitMethodGetterSetter) { - TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait; - if (tm.method_info != methodIndex) { - trait = null; - } - } - if (trait instanceof TraitFunction) { - TraitFunction tf = (TraitFunction) trait; - if (tf.method_info != methodIndex) { - trait = null; - } - } - abcPanel.detailPanel.showCard(DetailPanel.METHOD_TRAIT_CARD, trait); - MethodCodePanel methodCodePanel = abcPanel.detailPanel.methodTraitPanel.methodCodePanel; - if (reset || (methodCodePanel.getBodyIndex() != bi)) { - methodCodePanel.setBodyIndex(scriptName, bi, abc, name, trait, script.scriptIndex); - abcPanel.detailPanel.setEditMode(false); - this.isStatic = isStatic; - } - boolean success = false; - Highlighting h = Highlighting.searchPos(highlights, pos); - if (h != null) { - methodCodePanel.hilighOffset(h.getProperties().offset); - success = true; - } - Highlighting sh = Highlighting.searchPos(specialHighlights, pos); - if (sh != null) { - methodCodePanel.hilighSpecial(sh.getProperties().subtype, sh.getProperties().specialValue); - success = true; - } - return success; - } - - public void displayClass(int classIndex, int scriptIndex) { - if (abcPanel.navigator.getClassIndex() != classIndex) { - abcPanel.navigator.setClassIndex(classIndex, scriptIndex); - } - } - - public void resetEditing() { - reset = true; - caretUpdate(null); - reset = false; - } - - public int getMultinameUnderMouseCursor(Point pt) { - return getMultinameAtPos(viewToModel(pt)); - } - - public int getMultinameUnderCaret() { - return getMultinameAtPos(getCaretPosition()); - } - - public int getLocalDeclarationOfPos(int pos, Reference type) { - Highlighting sh = Highlighting.searchPos(specialHighlights, pos); - Highlighting h = Highlighting.searchPos(highlights, pos); - - if (h == null) { - return -1; - } - - List tms = Highlighting.searchAllPos(methodHighlights, pos); - if (tms.isEmpty()) { - return -1; - } - for (Highlighting tm : tms) { - - List tm_tms = Highlighting.searchAllIndexes(methodHighlights, tm.getProperties().index); - //is it already declaration? - if (h.getProperties().declaration || (sh != null && sh.getProperties().declaration)) { - return -1; //no jump - } - - String lname = h.getProperties().localName; - if ("this".equals(lname)) { - Highlighting ch = Highlighting.searchPos(classHighlights, pos); - int cindex = (int) ch.getProperties().index; - ABC abc = getABC(); - type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants)); - return ch.startPos; - } - - HighlightData hData = h.getProperties(); - HighlightData search = new HighlightData(); - search.declaration = hData.declaration; - search.declaredType = hData.declaredType; - search.localName = hData.localName; - search.specialValue = hData.specialValue; - if (search.isEmpty()) { - return -1; - } - search.declaration = true; - - for (Highlighting tm1 : tm_tms) { - Highlighting rh = Highlighting.search(highlights, search, tm1.startPos, tm1.startPos + tm1.len); - if (rh == null) { - rh = Highlighting.search(specialHighlights, search, tm1.startPos, tm1.startPos + tm1.len); - } - if (rh != null) { - type.setVal(rh.getProperties().declaredType); - return rh.startPos; - } - } - } - - return -1; - } - - public boolean getPropertyTypeAtPos(int pos, Reference abcIndex, Reference classIndex, Reference traitIndex, Reference classTrait, Reference multinameIndex) { - - int m = getMultinameAtPos(pos, true); - if (m <= 0) { - return false; - } - SyntaxDocument sd = (SyntaxDocument) getDocument(); - Token t = sd.getTokenAt(pos + 1); - Token lastToken = t; - Token prev; - while (t.type == TokenType.IDENTIFIER || t.type == TokenType.KEYWORD || t.type == TokenType.REGEX) { - prev = sd.getPrevToken(t); - if (prev != null) { - if (!".".equals(prev.getString(sd))) { - break; - } - t = sd.getPrevToken(prev); - } else { - break; - } - } - if (t.type != TokenType.IDENTIFIER && t.type != TokenType.KEYWORD || t.type == TokenType.REGEX) { - return false; - } - Reference locTypeRef = new Reference<>(DottedChain.EMPTY); - getLocalDeclarationOfPos(t.start, locTypeRef); - DottedChain currentType = locTypeRef.getVal(); - if (currentType.equals(DottedChain.ALL)) { - return false; - } - boolean found; - t = sd.getNextToken(t); - while (t != lastToken && !currentType.equals(DottedChain.ALL)) { - t = sd.getNextToken(t); - String ident = t.getString(sd); - found = false; - List abcList = getABC().getSwf().getAbcList(); - loopi: - for (int i = 0; i < abcList.size(); i++) { - ABC a = abcList.get(i).getABC(); - int cindex = a.findClassByName(currentType); - if (cindex > -1) { - InstanceInfo ii = a.instance_info.get(cindex); - for (int j = 0; j < ii.instance_traits.traits.size(); j++) { - Trait tr = ii.instance_traits.traits.get(j); - if (ident.equals(tr.getName(a).getName(a.constants, null, false /*NOT RAW!*/))) { - classIndex.setVal(cindex); - abcIndex.setVal(i); - traitIndex.setVal(j); - classTrait.setVal(false); - multinameIndex.setVal(tr.name_index); - currentType = ii.getName(a.constants).getNameWithNamespace(a.constants); - found = true; - break loopi; - } - } - - ClassInfo ci = a.class_info.get(cindex); - for (int j = 0; j < ci.static_traits.traits.size(); j++) { - Trait tr = ci.static_traits.traits.get(j); - if (ident.equals(tr.getName(a).getName(a.constants, null, false /*NOT RAW!*/))) { - classIndex.setVal(cindex); - abcIndex.setVal(i); - traitIndex.setVal(j); - classTrait.setVal(true); - multinameIndex.setVal(tr.name_index); - currentType = ii.getName(a.constants).getNameWithNamespace(a.constants); - found = true; - break loopi; - } - } - } - } - if (!found) { - return false; - } - - t = sd.getNextToken(t); - if (!".".equals(t.getString(sd))) { - break; - } - } - return true; - } - - public int getMultinameAtPos(int pos) { - return getMultinameAtPos(pos, false); - } - - private int getMultinameAtPos(int pos, boolean codeOnly) { - int multinameIndex = _getMultinameAtPos(pos, codeOnly); - if (multinameIndex > -1) { - ABC abc = getABC(); - multinameIndex = abc.constants.convertToQname(abc.constants, multinameIndex); - } - return multinameIndex; - } - - public int _getMultinameAtPos(int pos, boolean codeOnly) { - Highlighting tm = Highlighting.searchPos(methodHighlights, pos); - Trait currentTrait = null; - int currentMethod = -1; - ABC abc = getABC(); - if (tm != null) { - - int mi = (int) tm.getProperties().index; - currentMethod = mi; - int bi = abc.findBodyIndex(mi); - Highlighting h = Highlighting.searchPos(highlights, pos); - if (h != null) { - long highlightOffset = h.getProperties().offset; - List list = abc.bodies.get(bi).getCode().code; - AVM2Instruction lastIns = null; - AVM2Instruction selIns = null; - for (AVM2Instruction ins : list) { - if (highlightOffset == ins.getAddress()) { - selIns = ins; - break; - } - if (ins.getAddress() > highlightOffset) { - selIns = lastIns; - break; - } - lastIns = ins; - } - if (selIns != null) { - //long inspos = highlightOffset - selIns.offset; - if (!codeOnly && ((selIns.definition instanceof ConstructSuperIns) || (selIns.definition instanceof CallSuperIns) || (selIns.definition instanceof CallSuperVoidIns))) { - Highlighting tc = Highlighting.searchPos(classHighlights, pos); - if (tc != null) { - int cindex = (int) tc.getProperties().index; - if (cindex > -1) { - return abc.instance_info.get(cindex).super_index; - } - } - } else { - for (int i = 0; i < selIns.definition.operands.length; i++) { - if (selIns.definition.operands[i] == AVM2Code.DAT_MULTINAME_INDEX) { - return selIns.operands[i]; - } - } - } - } - } - - } - if (codeOnly) { - return -1; - } - - Highlighting ch = Highlighting.searchPos(classHighlights, pos); - if (ch != null) { - Highlighting th = Highlighting.searchPos(traitHighlights, pos); - if (th != null) { - currentTrait = abc.findTraitByTraitId((int) ch.getProperties().index, (int) th.getProperties().index); - } - } - - if (currentTrait instanceof TraitMethodGetterSetter) { - currentMethod = ((TraitMethodGetterSetter) currentTrait).method_info; - } - Highlighting sh = Highlighting.searchPos(specialHighlights, pos); - if (sh != null) { - switch (sh.getProperties().subtype) { - case TYPE_NAME: - String typeName = sh.getProperties().specialValue; - for (int i = 1; i < abc.constants.getMultinameCount(); i++) { - Multiname m = abc.constants.getMultiname(i); - if (m != null) { - if (typeName.equals(m.getNameWithNamespace(abc.constants).toRawString())) { - return i; - } - } - } - case TRAIT_TYPE_NAME: - if (currentTrait instanceof TraitSlotConst) { - TraitSlotConst ts = (TraitSlotConst) currentTrait; - return ts.type_index; - } - break; - case TRAIT_NAME: - if (currentTrait != null) { - //return currentTrait.name_index; - } - break; - case RETURNS: - if (currentMethod > -1) { - return abc.method_info.get(currentMethod).ret_type; - } - break; - case PARAM: - if (currentMethod > -1) { - return abc.method_info.get(currentMethod).param_types[(int) sh.getProperties().index]; - } - break; - } - } - return -1; - } - - @Override - public void caretUpdate(final CaretEvent e) { - ABC abc = getABC(); - if (abc == null) { - return; - } - if (ignoreCarret) { - return; - } - - getCaret().setVisible(true); - int pos = getCaretPosition(); - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setIgnoreCarret(true); - try { - classIndex = -1; - Highlighting cm = Highlighting.searchPos(classHighlights, pos); - if (cm != null) { - classIndex = (int) cm.getProperties().index; - } - displayClass(classIndex, script.scriptIndex); - Highlighting tm = Highlighting.searchPos(methodHighlights, pos); - if (tm != null) { - String name = ""; - if (classIndex > -1) { - name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(true); - } - - Trait currentTrait = null; - currentTraitHighlight = Highlighting.searchPos(traitHighlights, pos); - if (currentTraitHighlight != null) { - lastTraitIndex = (int) currentTraitHighlight.getProperties().index; - if (classIndex != -1) { - currentTrait = getCurrentTrait(); - isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex); - if (currentTrait != null) { - name += ":" + currentTrait.getName(abc).getName(abc.constants, null, false); - } - } - } - - displayMethod(pos, (int) tm.getProperties().index, name, currentTrait, isStatic); - currentMethodHighlight = tm; - return; - } - - if (classIndex == -1) { - abcPanel.navigator.setClassIndex(-1, script.scriptIndex); - setNoTrait(); - return; - } - Trait currentTrait; - currentTraitHighlight = Highlighting.searchPos(traitHighlights, pos); - if (currentTraitHighlight != null) { - lastTraitIndex = (int) currentTraitHighlight.getProperties().index; - currentTrait = getCurrentTrait(); - if (currentTrait != null) { - if (currentTrait instanceof TraitSlotConst) { - abcPanel.detailPanel.slotConstTraitPanel.load((TraitSlotConst) currentTrait, abc, - abc.isStaticTraitId(classIndex, lastTraitIndex)); - final Trait ftrait = currentTrait; - View.execInEventDispatch(() -> { - abcPanel.detailPanel.showCard(DetailPanel.SLOT_CONST_TRAIT_CARD, ftrait); - }); - abcPanel.detailPanel.setEditMode(false); - currentMethodHighlight = null; - Highlighting spec = Highlighting.searchPos(specialHighlights, pos, currentTraitHighlight.startPos, currentTraitHighlight.startPos + currentTraitHighlight.len); - if (spec != null) { - abcPanel.detailPanel.slotConstTraitPanel.hilightSpecial(spec); - } - - return; - } - } - currentMethodHighlight = null; - //currentTrait = null; - String name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(true); - currentTrait = getCurrentTrait(); - isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex); - if (currentTrait != null) { - name += ":" + currentTrait.getName(abc).getName(abc.constants, null, false); - } - - displayMethod(pos, abc.findMethodIdByTraitId(classIndex, lastTraitIndex), name, currentTrait, isStatic); - return; - } - setNoTrait(); - } finally { - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setIgnoreCarret(false); - } - } - - public void gotoLastTrait() { - gotoTrait(lastTraitIndex); - } - - public void gotoTrait(int traitId) { - boolean isScriptInit = traitId == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER; - - Highlighting tc = Highlighting.searchIndex(classHighlights, classIndex); - if (tc != null || isScriptInit) { - Highlighting th = Highlighting.searchIndex(traitHighlights, traitId, isScriptInit || tc == null ? 0 : tc.startPos, isScriptInit || tc == null ? -1 : tc.startPos + tc.len); - int pos = 0; - if (th != null) { - if (th.len > 1) { - ignoreCarret = true; - int startPos = th.startPos + th.len - 1; - if (startPos <= getDocument().getLength()) { - setCaretPosition(startPos); - } - ignoreCarret = false; - } - pos = th.startPos; - } else if (tc != null) { - pos = tc.startPos; - } - - final int fpos = pos; - new Timer().schedule(new TimerTask() { - @Override - public void run() { - if (fpos <= getDocument().getLength()) { - setCaretPosition(fpos); - } - } - }, 100); - } - } - - public DecompiledEditorPane(ABCPanel abcPanel) { - super(); - setEditable(false); - getCaret().setVisible(true); - addCaretListener(this); - this.abcPanel = abcPanel; - } - - public void clearScript() { - script = null; - } - - public void setScript(ScriptPack scriptLeaf, boolean force) { - if (!force && this.script == scriptLeaf) { - return; - } - String sn = scriptLeaf.getClassPath().toString(); - setScriptName(sn); - abcPanel.scriptNameLabel.setText(sn); - int scriptIndex = scriptLeaf.scriptIndex; - ScriptInfo nscript = null; - ABC abc = scriptLeaf.abc; - if (scriptIndex > -1) { - nscript = abc.script_info.get(scriptIndex); - } - if (nscript == null) { - highlights = new ArrayList<>(); - specialHighlights = new ArrayList<>(); - traitHighlights = new ArrayList<>(); - methodHighlights = new ArrayList<>(); - this.script = scriptLeaf; - return; - } - setText("// " + AppStrings.translate("pleasewait") + "..."); - - this.script = scriptLeaf; - CachedDecompilation cd = null; - try { - cd = SWF.getCached(scriptLeaf); - } catch (InterruptedException ex) { - } - - if (cd != null) { - String hilightedCode = cd.text; - highlights = cd.getInstructionHighlights(); - specialHighlights = cd.getSpecialHighligths(); - traitHighlights = cd.getTraitHighlights(); - methodHighlights = cd.getMethodHighlights(); - classHighlights = cd.getClassHighlights(); - setText(hilightedCode); - - if (classHighlights.size() > 0) { - try { - setCaretPosition(classHighlights.get(0).startPos); - } catch (Exception ex) { //sometimes happens - //ignore - } - } - } - fireScript(); - } - - public void reloadClass() { - int ci = classIndex; - SWF.uncache(script); - if (script != null && getABC() != null) { - setScript(script, true); - } - setNoTrait(); - setClassIndex(ci); - } - - public int getClassIndex() { - return classIndex; - } - - private ABC getABC() { - return script == null ? null : script.abc; - } - - @Override - public void setText(String t) { - super.setText(t); - setCaretPosition(0); - } -} +/* + * Copyright (C) 2010-2016 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.abc; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.CachedDecompilation; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperVoidIns; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.decompiler.flash.abc.types.ClassInfo; +import com.jpexs.decompiler.flash.abc.types.InstanceInfo; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; +import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; +import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; +import com.jpexs.decompiler.flash.gui.AppStrings; +import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.DottedChain; +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import jsyntaxpane.SyntaxDocument; +import jsyntaxpane.Token; +import jsyntaxpane.TokenType; + +/** + * + * @author JPEXS + */ +public class DecompiledEditorPane extends DebuggableEditorPane implements CaretListener { + + private List highlights = new ArrayList<>(); + + private List specialHighlights = new ArrayList<>(); + + private List traitHighlights = new ArrayList<>(); + + private List methodHighlights = new ArrayList<>(); + + private List classHighlights = new ArrayList<>(); + + private Highlighting currentMethodHighlight; + + private Highlighting currentTraitHighlight; + + private ScriptPack script; + + public int lastTraitIndex = 0; + + public boolean ignoreCarret = false; + + private boolean reset = false; + + private final ABCPanel abcPanel; + + private int classIndex = -1; + + private boolean isStatic = false; + + private final List scriptListeners = new ArrayList<>(); + + public void addScriptListener(Runnable l) { + scriptListeners.add(l); + } + + public ABCPanel getAbcPanel() { + return abcPanel; + } + + public void removeScriptListener(Runnable l) { + scriptListeners.remove(l); + } + + public void fireScript() { + Runnable[] listeners = scriptListeners.toArray(new Runnable[scriptListeners.size()]); + for (Runnable scriptListener : listeners) { + scriptListener.run(); + } + } + + public Trait getCurrentTrait() { + return script.abc.findTraitByTraitId(classIndex, lastTraitIndex); + } + + public ScriptPack getScriptLeaf() { + return script; + } + + public boolean getIsStatic() { + return isStatic; + } + + public void setNoTrait() { + abcPanel.detailPanel.showCard(DetailPanel.UNSUPPORTED_TRAIT_CARD, null); + } + + public void hilightSpecial(HighlightSpecialType type, long index) { + int startPos; + int endPos; + if (currentMethodHighlight == null) { + if (currentTraitHighlight == null) { + return; + } + startPos = currentTraitHighlight.startPos; + endPos = currentTraitHighlight.startPos + currentTraitHighlight.len; + } else { + startPos = currentMethodHighlight.startPos; + endPos = currentMethodHighlight.startPos + currentMethodHighlight.len; + } + + List allh = new ArrayList<>(); + for (Highlighting h : traitHighlights) { + if (h.getProperties().index == lastTraitIndex) { + for (Highlighting sh : specialHighlights) { + if (sh.startPos >= h.startPos && (sh.startPos + sh.len < h.startPos + h.len)) { + allh.add(sh); + } + } + } + } + if (currentMethodHighlight != null) { + for (Highlighting h : specialHighlights) { + if (h.startPos >= startPos && (h.startPos + h.len < endPos)) { + allh.add(h); + } + } + } + for (Highlighting h : allh) { + if (h.getProperties().subtype.equals(type) && (h.getProperties().index == index)) { + ignoreCarret = true; + if (h.startPos <= getDocument().getLength()) { + setCaretPosition(h.startPos); + } + getCaret().setVisible(true); + ignoreCarret = false; + break; + } + } + } + + public void hilightOffset(long offset) { + if (currentMethodHighlight == null) { + return; + } + for (Highlighting h : traitHighlights) { + if (h.getProperties().index == lastTraitIndex) { + Highlighting h2 = Highlighting.searchOffset(highlights, offset, h.startPos, h.startPos + h.len); + if (h2 != null) { + ignoreCarret = true; + if (h2.startPos <= getDocument().getLength()) { + setCaretPosition(h2.startPos); + } + getCaret().setVisible(true); + ignoreCarret = false; + } + + } + } + } + + public void setClassIndex(int classIndex) { + this.classIndex = classIndex; + } + + private boolean displayMethod(int pos, int methodIndex, String name, Trait trait, boolean isStatic) { + ABC abc = getABC(); + if (abc == null) { + return false; + } + int bi = abc.findBodyIndex(methodIndex); + if (bi == -1) { + return false; + } + + //fix for inner functions: + if (trait instanceof TraitMethodGetterSetter) { + TraitMethodGetterSetter tm = (TraitMethodGetterSetter) trait; + if (tm.method_info != methodIndex) { + trait = null; + } + } + if (trait instanceof TraitFunction) { + TraitFunction tf = (TraitFunction) trait; + if (tf.method_info != methodIndex) { + trait = null; + } + } + abcPanel.detailPanel.showCard(DetailPanel.METHOD_TRAIT_CARD, trait); + MethodCodePanel methodCodePanel = abcPanel.detailPanel.methodTraitPanel.methodCodePanel; + if (reset || (methodCodePanel.getBodyIndex() != bi)) { + methodCodePanel.setBodyIndex(scriptName, bi, abc, name, trait, script.scriptIndex); + abcPanel.detailPanel.setEditMode(false); + this.isStatic = isStatic; + } + boolean success = false; + Highlighting h = Highlighting.searchPos(highlights, pos); + if (h != null) { + methodCodePanel.hilighOffset(h.getProperties().offset); + success = true; + } + Highlighting sh = Highlighting.searchPos(specialHighlights, pos); + if (sh != null) { + methodCodePanel.hilighSpecial(sh.getProperties().subtype, sh.getProperties().specialValue); + success = true; + } + return success; + } + + public void displayClass(int classIndex, int scriptIndex) { + if (abcPanel.navigator.getClassIndex() != classIndex) { + abcPanel.navigator.setClassIndex(classIndex, scriptIndex); + } + } + + public void resetEditing() { + reset = true; + caretUpdate(null); + reset = false; + } + + public int getMultinameUnderMouseCursor(Point pt) { + return getMultinameAtPos(viewToModel(pt)); + } + + public int getMultinameUnderCaret() { + return getMultinameAtPos(getCaretPosition()); + } + + public int getLocalDeclarationOfPos(int pos, Reference type) { + Highlighting sh = Highlighting.searchPos(specialHighlights, pos); + Highlighting h = Highlighting.searchPos(highlights, pos); + + if (h == null) { + return -1; + } + + List tms = Highlighting.searchAllPos(methodHighlights, pos); + if (tms.isEmpty()) { + return -1; + } + for (Highlighting tm : tms) { + + List tm_tms = Highlighting.searchAllIndexes(methodHighlights, tm.getProperties().index); + //is it already declaration? + if (h.getProperties().declaration || (sh != null && sh.getProperties().declaration)) { + return -1; //no jump + } + + String lname = h.getProperties().localName; + if ("this".equals(lname)) { + Highlighting ch = Highlighting.searchPos(classHighlights, pos); + int cindex = (int) ch.getProperties().index; + ABC abc = getABC(); + type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants)); + return ch.startPos; + } + + HighlightData hData = h.getProperties(); + HighlightData search = new HighlightData(); + search.declaration = hData.declaration; + search.declaredType = hData.declaredType; + search.localName = hData.localName; + search.specialValue = hData.specialValue; + if (search.isEmpty()) { + return -1; + } + search.declaration = true; + + for (Highlighting tm1 : tm_tms) { + Highlighting rh = Highlighting.search(highlights, search, tm1.startPos, tm1.startPos + tm1.len); + if (rh == null) { + rh = Highlighting.search(specialHighlights, search, tm1.startPos, tm1.startPos + tm1.len); + } + if (rh != null) { + type.setVal(rh.getProperties().declaredType); + return rh.startPos; + } + } + } + + return -1; + } + + public boolean getPropertyTypeAtPos(int pos, Reference abcIndex, Reference classIndex, Reference traitIndex, Reference classTrait, Reference multinameIndex) { + + int m = getMultinameAtPos(pos, true); + if (m <= 0) { + return false; + } + SyntaxDocument sd = (SyntaxDocument) getDocument(); + Token t = sd.getTokenAt(pos + 1); + Token lastToken = t; + Token prev; + while (t.type == TokenType.IDENTIFIER || t.type == TokenType.KEYWORD || t.type == TokenType.REGEX) { + prev = sd.getPrevToken(t); + if (prev != null) { + if (!".".equals(prev.getString(sd))) { + break; + } + t = sd.getPrevToken(prev); + } else { + break; + } + } + if (t.type != TokenType.IDENTIFIER && t.type != TokenType.KEYWORD || t.type == TokenType.REGEX) { + return false; + } + Reference locTypeRef = new Reference<>(DottedChain.EMPTY); + getLocalDeclarationOfPos(t.start, locTypeRef); + DottedChain currentType = locTypeRef.getVal(); + if (currentType.equals(DottedChain.ALL)) { + return false; + } + boolean found; + t = sd.getNextToken(t); + while (t != lastToken && !currentType.equals(DottedChain.ALL)) { + t = sd.getNextToken(t); + String ident = t.getString(sd); + found = false; + List abcList = getABC().getSwf().getAbcList(); + loopi: + for (int i = 0; i < abcList.size(); i++) { + ABC a = abcList.get(i).getABC(); + int cindex = a.findClassByName(currentType); + if (cindex > -1) { + InstanceInfo ii = a.instance_info.get(cindex); + for (int j = 0; j < ii.instance_traits.traits.size(); j++) { + Trait tr = ii.instance_traits.traits.get(j); + if (ident.equals(tr.getName(a).getName(a.constants, null, false /*NOT RAW!*/))) { + classIndex.setVal(cindex); + abcIndex.setVal(i); + traitIndex.setVal(j); + classTrait.setVal(false); + multinameIndex.setVal(tr.name_index); + currentType = ii.getName(a.constants).getNameWithNamespace(a.constants); + found = true; + break loopi; + } + } + + ClassInfo ci = a.class_info.get(cindex); + for (int j = 0; j < ci.static_traits.traits.size(); j++) { + Trait tr = ci.static_traits.traits.get(j); + if (ident.equals(tr.getName(a).getName(a.constants, null, false /*NOT RAW!*/))) { + classIndex.setVal(cindex); + abcIndex.setVal(i); + traitIndex.setVal(j); + classTrait.setVal(true); + multinameIndex.setVal(tr.name_index); + currentType = ii.getName(a.constants).getNameWithNamespace(a.constants); + found = true; + break loopi; + } + } + } + } + if (!found) { + return false; + } + + t = sd.getNextToken(t); + if (!".".equals(t.getString(sd))) { + break; + } + } + return true; + } + + public int getMultinameAtPos(int pos) { + return getMultinameAtPos(pos, false); + } + + private int getMultinameAtPos(int pos, boolean codeOnly) { + int multinameIndex = _getMultinameAtPos(pos, codeOnly); + if (multinameIndex > -1) { + ABC abc = getABC(); + multinameIndex = abc.constants.convertToQname(abc.constants, multinameIndex); + } + return multinameIndex; + } + + public int _getMultinameAtPos(int pos, boolean codeOnly) { + Highlighting tm = Highlighting.searchPos(methodHighlights, pos); + Trait currentTrait = null; + int currentMethod = -1; + ABC abc = getABC(); + if (tm != null) { + + int mi = (int) tm.getProperties().index; + currentMethod = mi; + int bi = abc.findBodyIndex(mi); + Highlighting h = Highlighting.searchPos(highlights, pos); + if (h != null) { + long highlightOffset = h.getProperties().offset; + List list = abc.bodies.get(bi).getCode().code; + AVM2Instruction lastIns = null; + AVM2Instruction selIns = null; + for (AVM2Instruction ins : list) { + if (highlightOffset == ins.getAddress()) { + selIns = ins; + break; + } + if (ins.getAddress() > highlightOffset) { + selIns = lastIns; + break; + } + lastIns = ins; + } + if (selIns != null) { + //long inspos = highlightOffset - selIns.offset; + if (!codeOnly && ((selIns.definition instanceof ConstructSuperIns) || (selIns.definition instanceof CallSuperIns) || (selIns.definition instanceof CallSuperVoidIns))) { + Highlighting tc = Highlighting.searchPos(classHighlights, pos); + if (tc != null) { + int cindex = (int) tc.getProperties().index; + if (cindex > -1) { + return abc.instance_info.get(cindex).super_index; + } + } + } else { + for (int i = 0; i < selIns.definition.operands.length; i++) { + if (selIns.definition.operands[i] == AVM2Code.DAT_MULTINAME_INDEX) { + return selIns.operands[i]; + } + } + } + } + } + + } + if (codeOnly) { + return -1; + } + + Highlighting ch = Highlighting.searchPos(classHighlights, pos); + if (ch != null) { + Highlighting th = Highlighting.searchPos(traitHighlights, pos); + if (th != null) { + currentTrait = abc.findTraitByTraitId((int) ch.getProperties().index, (int) th.getProperties().index); + } + } + + if (currentTrait instanceof TraitMethodGetterSetter) { + currentMethod = ((TraitMethodGetterSetter) currentTrait).method_info; + } + Highlighting sh = Highlighting.searchPos(specialHighlights, pos); + if (sh != null) { + switch (sh.getProperties().subtype) { + case TYPE_NAME: + String typeName = sh.getProperties().specialValue; + for (int i = 1; i < abc.constants.getMultinameCount(); i++) { + Multiname m = abc.constants.getMultiname(i); + if (m != null) { + if (typeName.equals(m.getNameWithNamespace(abc.constants).toRawString())) { + return i; + } + } + } + case TRAIT_TYPE_NAME: + if (currentTrait instanceof TraitSlotConst) { + TraitSlotConst ts = (TraitSlotConst) currentTrait; + return ts.type_index; + } + break; + case TRAIT_NAME: + if (currentTrait != null) { + //return currentTrait.name_index; + } + break; + case RETURNS: + if (currentMethod > -1) { + return abc.method_info.get(currentMethod).ret_type; + } + break; + case PARAM: + if (currentMethod > -1) { + return abc.method_info.get(currentMethod).param_types[(int) sh.getProperties().index]; + } + break; + } + } + return -1; + } + + @Override + public void caretUpdate(final CaretEvent e) { + ABC abc = getABC(); + if (abc == null) { + return; + } + if (ignoreCarret) { + return; + } + + getCaret().setVisible(true); + int pos = getCaretPosition(); + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setIgnoreCarret(true); + try { + classIndex = -1; + Highlighting cm = Highlighting.searchPos(classHighlights, pos); + if (cm != null) { + classIndex = (int) cm.getProperties().index; + } + displayClass(classIndex, script.scriptIndex); + Highlighting tm = Highlighting.searchPos(methodHighlights, pos); + if (tm != null) { + String name = ""; + if (classIndex > -1) { + name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(true); + } + + Trait currentTrait = null; + currentTraitHighlight = Highlighting.searchPos(traitHighlights, pos); + if (currentTraitHighlight != null) { + lastTraitIndex = (int) currentTraitHighlight.getProperties().index; + if (classIndex != -1) { + currentTrait = getCurrentTrait(); + isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex); + if (currentTrait != null) { + name += ":" + currentTrait.getName(abc).getName(abc.constants, null, false); + } + } + } + + displayMethod(pos, (int) tm.getProperties().index, name, currentTrait, isStatic); + currentMethodHighlight = tm; + return; + } + + if (classIndex == -1) { + abcPanel.navigator.setClassIndex(-1, script.scriptIndex); + setNoTrait(); + return; + } + Trait currentTrait; + currentTraitHighlight = Highlighting.searchPos(traitHighlights, pos); + if (currentTraitHighlight != null) { + lastTraitIndex = (int) currentTraitHighlight.getProperties().index; + currentTrait = getCurrentTrait(); + if (currentTrait != null) { + if (currentTrait instanceof TraitSlotConst) { + abcPanel.detailPanel.slotConstTraitPanel.load((TraitSlotConst) currentTrait, abc, + abc.isStaticTraitId(classIndex, lastTraitIndex)); + final Trait ftrait = currentTrait; + View.execInEventDispatch(() -> { + abcPanel.detailPanel.showCard(DetailPanel.SLOT_CONST_TRAIT_CARD, ftrait); + }); + abcPanel.detailPanel.setEditMode(false); + currentMethodHighlight = null; + Highlighting spec = Highlighting.searchPos(specialHighlights, pos, currentTraitHighlight.startPos, currentTraitHighlight.startPos + currentTraitHighlight.len); + if (spec != null) { + abcPanel.detailPanel.slotConstTraitPanel.hilightSpecial(spec); + } + + return; + } + } + currentMethodHighlight = null; + //currentTrait = null; + String name = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants).toPrintableString(true); + currentTrait = getCurrentTrait(); + isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex); + if (currentTrait != null) { + name += ":" + currentTrait.getName(abc).getName(abc.constants, null, false); + } + + displayMethod(pos, abc.findMethodIdByTraitId(classIndex, lastTraitIndex), name, currentTrait, isStatic); + return; + } + setNoTrait(); + } finally { + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setIgnoreCarret(false); + } + } + + public void gotoLastTrait() { + gotoTrait(lastTraitIndex); + } + + public void gotoTrait(int traitId) { + boolean isScriptInit = traitId == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER; + + Highlighting tc = Highlighting.searchIndex(classHighlights, classIndex); + if (tc != null || isScriptInit) { + Highlighting th = Highlighting.searchIndex(traitHighlights, traitId, isScriptInit || tc == null ? 0 : tc.startPos, isScriptInit || tc == null ? -1 : tc.startPos + tc.len); + int pos = 0; + if (th != null) { + if (th.len > 1) { + ignoreCarret = true; + int startPos = th.startPos + th.len - 1; + if (startPos <= getDocument().getLength()) { + setCaretPosition(startPos); + } + ignoreCarret = false; + } + pos = th.startPos; + } else if (tc != null) { + pos = tc.startPos; + } + + final int fpos = pos; + new Timer().schedule(new TimerTask() { + @Override + public void run() { + if (fpos <= getDocument().getLength()) { + setCaretPosition(fpos); + } + } + }, 100); + } + } + + public DecompiledEditorPane(ABCPanel abcPanel) { + super(); + setEditable(false); + getCaret().setVisible(true); + addCaretListener(this); + this.abcPanel = abcPanel; + } + + public void clearScript() { + script = null; + } + + public void setScript(ScriptPack scriptLeaf, boolean force) { + if (!force && this.script == scriptLeaf) { + return; + } + String sn = scriptLeaf.getClassPath().toString(); + setScriptName(sn); + abcPanel.scriptNameLabel.setText(sn); + int scriptIndex = scriptLeaf.scriptIndex; + ScriptInfo nscript = null; + ABC abc = scriptLeaf.abc; + if (scriptIndex > -1) { + nscript = abc.script_info.get(scriptIndex); + } + if (nscript == null) { + highlights = new ArrayList<>(); + specialHighlights = new ArrayList<>(); + traitHighlights = new ArrayList<>(); + methodHighlights = new ArrayList<>(); + this.script = scriptLeaf; + return; + } + setText("// " + AppStrings.translate("pleasewait") + "..."); + + this.script = scriptLeaf; + CachedDecompilation cd = null; + try { + cd = SWF.getCached(scriptLeaf); + } catch (InterruptedException ex) { + } + + if (cd != null) { + String hilightedCode = cd.text; + highlights = cd.getInstructionHighlights(); + specialHighlights = cd.getSpecialHighligths(); + traitHighlights = cd.getTraitHighlights(); + methodHighlights = cd.getMethodHighlights(); + classHighlights = cd.getClassHighlights(); + setText(hilightedCode); + + if (classHighlights.size() > 0) { + try { + setCaretPosition(classHighlights.get(0).startPos); + } catch (Exception ex) { //sometimes happens + //ignore + } + } + } + fireScript(); + } + + public void reloadClass() { + int ci = classIndex; + SWF.uncache(script); + if (script != null && getABC() != null) { + setScript(script, true); + } + setNoTrait(); + setClassIndex(ci); + } + + public int getClassIndex() { + return classIndex; + } + + private ABC getABC() { + return script == null ? null : script.abc; + } + + @Override + public void setText(String t) { + super.setText(t); + setCaretPosition(0); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/abc/TraitsList.java b/src/com/jpexs/decompiler/flash/gui/abc/TraitsList.java index 64cddc25d..7c63a7498 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/TraitsList.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/TraitsList.java @@ -1,101 +1,101 @@ -/* - * Copyright (C) 2010-2016 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.abc; - -import com.jpexs.decompiler.flash.abc.ABC; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -/** - * - * @author JPEXS - */ -public class TraitsList extends JList implements ListSelectionListener { - - private ABC abc; - - private int classIndex = -1; - - private final ABCPanel abcPanel; - - private boolean sorted = false; - - public void setSorted(boolean sorted) { - if (getModel() instanceof TraitsListModel) { - ((TraitsListModel) getModel()).setSorted(sorted); - } - this.sorted = sorted; - } - - public int getClassIndex() { - return classIndex; - } - - public TraitsList(ABCPanel abcPanel) { - addListSelectionListener(this); - this.abcPanel = abcPanel; - setCellRenderer(new IconListRenderer()); - //setUI(new BasicListUI()); - setBackground(Color.white); - } - - public void clearAbc() { - this.abc = null; - setModel(new DefaultListModel<>()); - } - - public void setAbc(ABC abc) { - this.abc = abc; - setModel(new DefaultListModel<>()); - setClassIndex(-1, -1); - } - - public void setClassIndex(int classIndex, int scriptIndex) { - if (classIndex >= abc.instance_info.size()) { - return; - } - this.classIndex = classIndex; - setModel(new TraitsListModel(abc, classIndex, scriptIndex, sorted)); - - } - - private int lastSelected = -1; - - @Override - public void valueChanged(ListSelectionEvent e) { - if (getSelectedIndex() == lastSelected) { - return; - } - lastSelected = getSelectedIndex(); - TraitsListItem sel = (TraitsListItem) getSelectedValue(); - abcPanel.decompiledTextArea.gotoTrait(sel == null ? -1 : sel.getGlobalTraitId()); - - } - - @Override - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - g2d.setComposite(AlphaComposite.SrcOver); - super.paint(g); - } -} +/* + * Copyright (C) 2010-2016 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.abc; + +import com.jpexs.decompiler.flash.abc.ABC; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +/** + * + * @author JPEXS + */ +public class TraitsList extends JList implements ListSelectionListener { + + private ABC abc; + + private int classIndex = -1; + + private final ABCPanel abcPanel; + + private boolean sorted = false; + + public void setSorted(boolean sorted) { + if (getModel() instanceof TraitsListModel) { + ((TraitsListModel) getModel()).setSorted(sorted); + } + this.sorted = sorted; + } + + public int getClassIndex() { + return classIndex; + } + + public TraitsList(ABCPanel abcPanel) { + addListSelectionListener(this); + this.abcPanel = abcPanel; + setCellRenderer(new IconListRenderer()); + //setUI(new BasicListUI()); + setBackground(Color.white); + } + + public void clearAbc() { + this.abc = null; + setModel(new DefaultListModel<>()); + } + + public void setAbc(ABC abc) { + this.abc = abc; + setModel(new DefaultListModel<>()); + setClassIndex(-1, -1); + } + + public void setClassIndex(int classIndex, int scriptIndex) { + if (classIndex >= abc.instance_info.size()) { + return; + } + this.classIndex = classIndex; + setModel(new TraitsListModel(abc, classIndex, scriptIndex, sorted)); + + } + + private int lastSelected = -1; + + @Override + public void valueChanged(ListSelectionEvent e) { + if (getSelectedIndex() == lastSelected) { + return; + } + lastSelected = getSelectedIndex(); + TraitsListItem sel = (TraitsListItem) getSelectedValue(); + abcPanel.decompiledTextArea.gotoTrait(sel == null ? -1 : sel.getGlobalTraitId()); + + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setComposite(AlphaComposite.SrcOver); + super.paint(g); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index 7a0e5b9d7..85a9b09d1 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -1,1065 +1,1065 @@ -/* - * Copyright (C) 2010-2016 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.action; - -import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.ActionGraph; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.CachedScript; -import com.jpexs.decompiler.flash.action.ConstantPoolTooBigException; -import com.jpexs.decompiler.flash.action.parser.ActionParseException; -import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; -import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser; -import com.jpexs.decompiler.flash.action.parser.script.ActionScriptLexer; -import com.jpexs.decompiler.flash.action.parser.script.ParsedSymbol; -import com.jpexs.decompiler.flash.action.parser.script.SymbolType; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.gui.AppStrings; -import com.jpexs.decompiler.flash.gui.DebugPanel; -import com.jpexs.decompiler.flash.gui.DebuggerHandler; -import com.jpexs.decompiler.flash.gui.GraphDialog; -import com.jpexs.decompiler.flash.gui.HeaderLabel; -import com.jpexs.decompiler.flash.gui.Main; -import com.jpexs.decompiler.flash.gui.MainPanel; -import com.jpexs.decompiler.flash.gui.SearchListener; -import com.jpexs.decompiler.flash.gui.SearchPanel; -import com.jpexs.decompiler.flash.gui.TagEditorPanel; -import com.jpexs.decompiler.flash.gui.View; -import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; -import com.jpexs.decompiler.flash.gui.controls.NoneSelectedButtonGroup; -import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane; -import com.jpexs.decompiler.flash.gui.editor.LinkHandler; -import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel; -import com.jpexs.decompiler.flash.helpers.HighlightedText; -import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; -import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.CancellationException; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Pattern; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JToggleButton; -import javax.swing.SwingConstants; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.text.Highlighter; -import javax.swing.tree.TreePath; -import jsyntaxpane.SyntaxDocument; -import jsyntaxpane.Token; -import jsyntaxpane.TokenType; -import jsyntaxpane.actions.ActionUtils; - -/** - * - * @author JPEXS - */ -public class ActionPanel extends JPanel implements SearchListener, TagEditorPanel { - - private static final Logger logger = Logger.getLogger(ActionPanel.class.getName()); - - private MainPanel mainPanel; - - public DebuggableEditorPane editor; - - public DebuggableEditorPane decompiledEditor; - - public JPersistentSplitPane splitPane; - - public JButton saveButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); - - public JButton editButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); - - public JButton cancelButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); - - public JLabel experimentalLabel = new JLabel(AppStrings.translate("action.edit.experimental")); - - public JButton editDecompiledButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); - - public JButton saveDecompiledButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); - - public JButton cancelDecompiledButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); - - public JToggleButton hexButton; - - public JToggleButton hexOnlyButton; - - public JToggleButton constantsViewButton; - - public JToggleButton resolveConstantsButton; - - public JToggleButton showFileOffsetInPcodeHexButton; - - public JToggleButton showOriginalBytesInPcodeHexButton; - - public JLabel asmLabel = new HeaderLabel(AppStrings.translate("panel.disassembled")); - - public JLabel decLabel = new HeaderLabel(AppStrings.translate("panel.decompiled")); - - public List decompiledHilights = new ArrayList<>(); - - public List specialHighlights = new ArrayList<>(); - - public List classHighlights = new ArrayList<>(); - - public List methodHighlights = new ArrayList<>(); - - public List disassembledHilights = new ArrayList<>(); - - private boolean ignoreCarret = false; - - private boolean editMode = false; - - private boolean editDecompiledMode = false; - - private ActionList lastCode; - - private ASMSource src; - - public JPanel topButtonsPan; - - private HighlightedText srcWithHex; - - private HighlightedText srcNoHex; - - private HighlightedText srcHexOnly; - - private HighlightedText srcConstants; - - private String lastDecompiled = ""; - - private ASMSource lastASM; - - public SearchPanel searchPanel; - - private CancellableWorker setSourceWorker; - - public void clearSource() { - lastCode = null; - lastASM = null; - lastDecompiled = null; - searchPanel.clear(); - src = null; - srcWithHex = null; - srcNoHex = null; - srcHexOnly = null; - srcConstants = null; - } - - public String getStringUnderCursor() { - int pos = decompiledEditor.getCaretPosition(); - - SyntaxDocument sDoc = ActionUtils.getSyntaxDocument(decompiledEditor); - if (sDoc != null) { - Token t = sDoc.getTokenAt(pos + 1); - String ident = null; - //It should be identifier or obfuscated identifier - if (t != null && (t.type == TokenType.IDENTIFIER || t.type == TokenType.REGEX)) { - CharSequence tData = t.getText(sDoc); - ident = tData.toString(); - //We need to get unescaped identifier, so we use our Lexer - ActionScriptLexer lex = new ActionScriptLexer(new StringReader(ident)); - try { - ParsedSymbol symb = lex.lex(); - if (symb.type == SymbolType.IDENTIFIER) { - ident = (String) symb.value; - } else { - ident = null; - } - } catch (IOException | ActionParseException ex) { - ident = null; - } - } - if (ident == null) { - Highlighting h = Highlighting.searchPos(decompiledHilights, pos); - if (h != null) { - List list = lastCode; - Action lastIns = null; - int inspos = 0; - Action selIns = null; - for (Action ins : list) { - if (h.getProperties().offset == ins.getAddress()) { - selIns = ins; - break; - } - if (ins.getAddress() > h.getProperties().offset && lastIns != null) { - inspos = (int) (h.getProperties().offset - lastIns.getAddress()); - selIns = lastIns; - break; - } - lastIns = ins; - } - if (selIns != null) { - if (selIns instanceof ActionPush) { - ActionPush ap = (ActionPush) selIns; - Object var = ap.values.get(inspos - 1); - String identifier = null; - if (var instanceof String) { - identifier = (String) var; - } - if (var instanceof ConstantIndex) { - identifier = ap.constantPool.get(((ConstantIndex) var).index); - } - return identifier; - } - } - - } - } else { - return ident; - } - } - return null; - } - - public List search(SWF swf, final String txt, boolean ignoreCase, boolean regexp, CancellableWorker worker) { - if (txt != null && !txt.isEmpty()) { - searchPanel.setOptions(ignoreCase, regexp); - Map asms = swf.getASMs(false); - final List found = new ArrayList<>(); - Pattern pat; - if (regexp) { - pat = Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); - } else { - pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); - } - int pos = 0; - for (Entry item : asms.entrySet()) { - pos++; - String workText = AppStrings.translate("work.searching"); - String decAdd = ""; - ASMSource asm = item.getValue(); - if (!SWF.isCached(asm)) { - decAdd = ", " + AppStrings.translate("work.decompiling"); - } - - Main.startWork(workText + " \"" + txt + "\"" + decAdd + " - (" + pos + "/" + asms.size() + ") " + item.getKey() + "... ", worker); - try { - if (pat.matcher(SWF.getCached(asm, null).text).find()) { - found.add(new ActionSearchResult(asm, item.getKey())); - } - } catch (InterruptedException ex) { - break; - } - } - - return found; - } - - return null; - } - - private void setDecompiledText(final String scriptName, final String text) { - View.execInEventDispatch(() -> { - ignoreCarret = true; - decompiledEditor.setScriptName(scriptName); - decompiledEditor.setText(text); - ignoreCarret = false; - }); - } - - private void setEditorText(final String scriptName, final String text, final String contentType) { - View.execInEventDispatch(() -> { - ignoreCarret = true; - editor.setScriptName("#PCODE " + scriptName); - editor.changeContentType(contentType); - editor.setText(text); - ignoreCarret = false; - }); - } - - private void setText(final HighlightedText text, final String contentType, final String scriptName) { - View.execInEventDispatch(() -> { - int pos = editor.getCaretPosition(); - Highlighting lastH = null; - for (Highlighting h : disassembledHilights) { - if (pos < h.startPos) { - break; - } - lastH = h; - } - Long offset = lastH == null ? 0 : lastH.getProperties().offset; - disassembledHilights = text.instructionHilights; - String stripped = text.text; - setEditorText(scriptName, stripped, contentType); - Highlighting h = Highlighting.searchOffset(disassembledHilights, offset); - if (h != null) { - if (h.startPos <= editor.getDocument().getLength()) { - editor.setCaretPosition(h.startPos); - } - } - }); - } - - private HighlightedText getHighlightedText(ScriptExportMode exportMode) { - ASMSource asm = (ASMSource) src; - DisassemblyListener listener = getDisassemblyListener(); - asm.addDisassemblyListener(listener); - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); - try { - asm.getASMSource(exportMode, writer, lastCode); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - asm.removeDisassemblyListener(listener); - return new HighlightedText(writer); - } - - public void setHex(ScriptExportMode exportMode, String scriptName) { - switch (exportMode) { - case PCODE: - if (srcNoHex == null) { - srcNoHex = getHighlightedText(exportMode); - } - - setText(srcNoHex, "text/flasm", scriptName); - break; - case PCODE_HEX: - if (srcWithHex == null) { - srcWithHex = getHighlightedText(exportMode); - } - - setText(srcWithHex, "text/flasm", scriptName); - break; - case HEX: - if (srcHexOnly == null) { - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); - Helper.byteArrayToHexWithHeader(writer, src.getActionBytes().getRangeData()); - srcHexOnly = new HighlightedText(writer); - } - - setText(srcHexOnly, "text/plain", scriptName); - break; - case CONSTANTS: - if (srcConstants == null) { - srcConstants = getHighlightedText(exportMode); - } - - setText(srcConstants, "text/plain", scriptName); - break; - default: - throw new Error("Export mode not supported: " + exportMode); - } - } - - private DisassemblyListener getDisassemblyListener() { - DisassemblyListener listener = new DisassemblyListener() { - int percent = 0; - - String phase = ""; - - private void progress(String phase, long pos, long total) { - if (total < 1) { - return; - } - int newpercent = (int) (pos * 100 / total); - if (((newpercent > percent) || (!this.phase.equals(phase))) && newpercent <= 100) { - percent = newpercent; - this.phase = phase; - // todo: honfika: it is very slow to show every percent - setEditorText("-", "; " + AppStrings.translate("work.disassembling") + " - " + phase + " " + percent + "%...", "text/flasm"); - } - } - - @Override - public void progressReading(long pos, long total) { - progress(AppStrings.translate("disassemblingProgress.reading"), pos, total); - } - - @Override - public void progressToString(long pos, long total) { - progress(AppStrings.translate("disassemblingProgress.toString"), pos, total); - } - - @Override - public void progressDeobfuscating(long pos, long total) { - progress(AppStrings.translate("disassemblingProgress.deobfuscating"), pos, total); - } - }; - return listener; - } - - public void setSource(final ASMSource src, final boolean useCache) { - if (setSourceWorker != null) { - setSourceWorker.cancel(true); - setSourceWorker = null; - } - - clearSource(); - this.src = src; - final ASMSource asm = (ASMSource) src; - - if (!useCache) { - SWF.uncache(asm); - } - - boolean decompile = Configuration.decompile.get(); - if (!decompile) { - lastDecompiled = Helper.getDecompilationSkippedComment(); - setDecompiledText(asm.getScriptName(), lastDecompiled); - } else { - CachedScript sc = SWF.getFromCache(asm); - if (sc != null) { - decompile = false; - decompiledHilights = sc.hilights; - methodHighlights = sc.methodHilights; - classHighlights = sc.classHilights; - specialHighlights = sc.specialHilights; - lastDecompiled = sc.text; - lastASM = asm; - setDecompiledText(lastASM.getScriptName(), lastDecompiled); - } - } - - if (!decompile) { - setDecompiledEditMode(false); - } - - final boolean decompileNeeded = decompile; - - CancellableWorker worker = new CancellableWorker() { - - @Override - protected Void doInBackground() throws Exception { - - setEditorText(asm.getScriptName(), "; " + AppStrings.translate("work.disassembling") + "...", "text/flasm"); - if (decompileNeeded) { - setDecompiledText("-", "// " + AppStrings.translate("work.waitingfordissasembly") + "..."); - } - DisassemblyListener listener = getDisassemblyListener(); - asm.addDisassemblyListener(listener); - ActionList actions = asm.getActions(); - lastCode = actions; - asm.removeDisassemblyListener(listener); - setHex(getExportMode(), asm.getScriptName()); - if (decompileNeeded) { - setDecompiledText("-", "// " + AppStrings.translate("work.decompiling") + "..."); - - CachedScript sc = SWF.getCached(asm, actions); - decompiledHilights = sc.hilights; - methodHighlights = sc.methodHilights; - classHighlights = sc.classHilights; - specialHighlights = sc.specialHilights; - lastDecompiled = sc.text; - lastASM = asm; - setDecompiledText(lastASM.getScriptName(), lastDecompiled); - setDecompiledEditMode(false); - } - setEditMode(false); - - return null; - } - - @Override - protected void done() { - View.execInEventDispatch(() -> { - setSourceWorker = null; - if (!Main.isDebugging()) { - Main.stopWork(); - } - - try { - get(); - } catch (CancellationException ex) { - setEditorText("-", "; " + AppStrings.translate("work.canceled"), "text/flasm"); - } catch (Exception ex) { - setDecompiledText("-", "// " + AppStrings.translate("decompilationError") + ": " + ex); - } - }); - } - }; - worker.execute(); - setSourceWorker = worker; - if (!Main.isDebugging()) { - Main.startWork(AppStrings.translate("work.decompiling") + "...", worker); - } - } - - public void hilightOffset(long offset) { - } - - public int getLocalDeclarationOfPos(int pos) { - Highlighting sh = Highlighting.searchPos(specialHighlights, pos); - Highlighting h = Highlighting.searchPos(decompiledHilights, pos); - - if (h == null) { - return -1; - } - - List tms = Highlighting.searchAllPos(methodHighlights, pos); - if (tms.isEmpty()) { - return -1; - } - for (Highlighting tm : tms) { - - List tm_tms = Highlighting.searchAllLocalNames(methodHighlights, tm.getProperties().localName); - //is it already declaration? - if (h.getProperties().declaration || (sh != null && sh.getProperties().declaration)) { - return -1; //no jump - } - - String lname = h.getProperties().localName; - if ("this".equals(lname)) { - Highlighting ch = Highlighting.searchPos(classHighlights, pos); - // int cindex = (int) ch.getProperties().index; - return ch.startPos; - } - - HighlightData hData = h.getProperties(); - HighlightData search = new HighlightData(); - search.declaration = hData.declaration; - //search.declaredType = hData.declaredType; - search.localName = hData.localName; - //search.specialValue = hData.specialValue; - if (search.isEmpty()) { - return -1; - } - search.declaration = true; - - for (Highlighting tm1 : tm_tms) { - Highlighting rh = Highlighting.search(decompiledHilights, search, tm1.startPos, tm1.startPos + tm1.len); - if (rh != null) { - return rh.startPos; - } - } - } - - return -1; - } - - public ActionPanel(MainPanel mainPanel) { - this.mainPanel = mainPanel; - editor = new DebuggableEditorPane(); - editor.setEditable(false); - decompiledEditor = new DebuggableEditorPane(); - decompiledEditor.setEditable(false); - decompiledEditor.setLinkHandler(new LinkHandler() { - - @Override - public boolean isLink(Token token) { - int pos = token.start; - Highlighting h = Highlighting.searchPos(decompiledHilights, pos); - if (h != null) { - if (h.getProperties().localName != null && !h.getProperties().declaration) { - return getLocalDeclarationOfPos(pos) != -1; - } - } - return false; - } - - @Override - public void handleLink(Token token) { - int pos = token.start; - int tpos = getLocalDeclarationOfPos(pos); - if (tpos > -1) { - //System.err.println("goto " + tpos); - decompiledEditor.setCaretPosition(tpos); - } else { - //System.err.println("cannot handle"); - } - } - - @Override - public Highlighter.HighlightPainter linkPainter() { - return decompiledEditor.linkPainter(); - } - }); - - searchPanel = new SearchPanel<>(new FlowLayout(), this); - - JButton graphButton = new JButton(View.getIcon("graph16")); - graphButton.addActionListener(this::graphButtonActionPerformed); - graphButton.setToolTipText(AppStrings.translate("button.viewgraph")); - graphButton.setMargin(new Insets(3, 3, 3, 3)); - - hexButton = new JToggleButton(View.getIcon("hexas16")); - hexButton.addActionListener(this::hexButtonActionPerformed); - hexButton.setToolTipText(AppStrings.translate("button.viewhexpcode")); - hexButton.setMargin(new Insets(3, 3, 3, 3)); - - hexOnlyButton = new JToggleButton(View.getIcon("hex16")); - hexOnlyButton.addActionListener(this::hexOnlyButtonActionPerformed); - hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex")); - hexOnlyButton.setMargin(new Insets(3, 3, 3, 3)); - - constantsViewButton = new JToggleButton(View.getIcon("constantpool16")); - constantsViewButton.addActionListener(this::constantsViewButtonActionPerformed); - constantsViewButton.setToolTipText(AppStrings.translate("button.viewConstants")); - constantsViewButton.setMargin(new Insets(3, 3, 3, 3)); - - NoneSelectedButtonGroup exportModeButtonGroup = new NoneSelectedButtonGroup(); - exportModeButtonGroup.add(hexButton); - exportModeButtonGroup.add(hexOnlyButton); - exportModeButtonGroup.add(constantsViewButton); - - resolveConstantsButton = new JToggleButton(View.getIcon("resolveconst16")); - resolveConstantsButton.addActionListener(this::resolveConstantsButtonActionPerformed); - resolveConstantsButton.setToolTipText(AppStrings.translate("button.resolveConstants")); - resolveConstantsButton.setMargin(new Insets(3, 3, 3, 3)); - resolveConstantsButton.setSelected(Configuration.resolveConstants.get()); - - showFileOffsetInPcodeHexButton = new JToggleButton(View.getIcon("fileoffset16")); - showFileOffsetInPcodeHexButton.addActionListener(this::showFileOffsetInPcodeHexButtonActionPerformed); - showFileOffsetInPcodeHexButton.setToolTipText(AppStrings.translate("button.showFileOffsetInPcodeHex")); - showFileOffsetInPcodeHexButton.setMargin(new Insets(3, 3, 3, 3)); - showFileOffsetInPcodeHexButton.setSelected(Configuration.showFileOffsetInPcodeHex.get()); - - showOriginalBytesInPcodeHexButton = new JToggleButton(View.getIcon("originalbytes16")); - showOriginalBytesInPcodeHexButton.addActionListener(this::showOriginalBytesInPcodeHexButtonActionPerformed); - showOriginalBytesInPcodeHexButton.setToolTipText(AppStrings.translate("button.showOriginalBytesInPcodeHex")); - showOriginalBytesInPcodeHexButton.setMargin(new Insets(3, 3, 3, 3)); - showOriginalBytesInPcodeHexButton.setSelected(Configuration.showOriginalBytesInPcodeHex.get()); - - topButtonsPan = new JPanel(); - topButtonsPan.setLayout(new BoxLayout(topButtonsPan, BoxLayout.X_AXIS)); - topButtonsPan.add(graphButton); - topButtonsPan.add(Box.createRigidArea(new Dimension(10, 0))); - topButtonsPan.add(hexButton); - topButtonsPan.add(hexOnlyButton); - topButtonsPan.add(constantsViewButton); - topButtonsPan.add(Box.createRigidArea(new Dimension(10, 0))); - topButtonsPan.add(resolveConstantsButton); - topButtonsPan.add(showFileOffsetInPcodeHexButton); - topButtonsPan.add(showOriginalBytesInPcodeHexButton); - - JPanel panCode = new JPanel(new BorderLayout()); - panCode.add(new JScrollPane(editor), BorderLayout.CENTER); - panCode.add(topButtonsPan, BorderLayout.NORTH); - - JPanel panB = new JPanel(); - panB.setLayout(new BorderLayout()); - asmLabel.setHorizontalAlignment(SwingConstants.CENTER); - //asmLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); - panB.add(asmLabel, BorderLayout.NORTH); - panB.add(panCode, BorderLayout.CENTER); - - JPanel buttonsPan = new JPanel(); - buttonsPan.setLayout(new FlowLayout()); - buttonsPan.add(editButton); - buttonsPan.add(saveButton); - buttonsPan.add(cancelButton); - - editButton.setMargin(new Insets(3, 3, 3, 10)); - saveButton.setMargin(new Insets(3, 3, 3, 10)); - cancelButton.setMargin(new Insets(3, 3, 3, 10)); - - JPanel decButtonsPan = new JPanel(new FlowLayout()); - decButtonsPan.add(editDecompiledButton); - decButtonsPan.add(experimentalLabel); - decButtonsPan.add(saveDecompiledButton); - decButtonsPan.add(cancelDecompiledButton); - - editDecompiledButton.setMargin(new Insets(3, 3, 3, 10)); - saveDecompiledButton.setMargin(new Insets(3, 3, 3, 10)); - cancelDecompiledButton.setMargin(new Insets(3, 3, 3, 10)); - - //buttonsPan.add(saveHexButton); - //buttonsPan.add(loadHexButton); - panB.add(buttonsPan, BorderLayout.SOUTH); - - saveButton.addActionListener(this::saveActionButtonActionPerformed); - editButton.addActionListener(this::editActionButtonActionPerformed); - cancelButton.addActionListener(this::cancelActionButtonActionPerformed); - saveButton.setVisible(false); - cancelButton.setVisible(false); - - saveDecompiledButton.addActionListener(this::saveDecompiledButtonActionPerformed); - editDecompiledButton.addActionListener(this::editDecompiledButtonActionPerformed); - cancelDecompiledButton.addActionListener(this::cancelDecompiledButtonActionPerformed); - saveDecompiledButton.setVisible(false); - cancelDecompiledButton.setVisible(false); - - JPanel panA = new JPanel(new BorderLayout()); - - panA.add(decLabel, BorderLayout.NORTH); - - DebugPanel debugPanel = new DebugPanel(); - - panA.add(new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(decompiledEditor), debugPanel, Configuration.guiActionVarsSplitPaneDividerLocationPercent), BorderLayout.CENTER); - panA.add(decButtonsPan, BorderLayout.SOUTH); - - //decPanel.add(searchPanel, BorderLayout.NORTH); - Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener() { - - @Override - public void connected() { - decButtonsPan.setVisible(false); - } - - @Override - public void disconnected() { - decButtonsPan.setVisible(true); - } - }); - - //new JSplitPane(JSplitPane.VERTICAL_SPLIT, decompiledEditor, debugPanel) - //decPanel.add(decButtonsPan, BorderLayout.SOUTH); - //JPanel panBot = new JPanel(new BorderLayout()); - //panBot.add(decButtonsPan, BorderLayout.NORTH); - //panBot.add(debugPanel, BorderLayout.CENTER); - //panA.add(decButtonsPan, BorderLayout.SOUTH); - debugPanel.setVisible(false); - - decLabel.setHorizontalAlignment(SwingConstants.CENTER); - //decLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); - - setLayout(new BorderLayout()); - add(splitPane = new JPersistentSplitPane(JSplitPane.HORIZONTAL_SPLIT, panA, panB, Configuration.guiActionSplitPaneDividerLocationPercent), BorderLayout.CENTER); - - editor.setFont(new Font("Monospaced", Font.PLAIN, editor.getFont().getSize())); - decompiledEditor.setFont(new Font("Monospaced", Font.PLAIN, decompiledEditor.getFont().getSize())); - decompiledEditor.changeContentType("text/actionscript"); - - editor.addCaretListener(new CaretListener() { - @Override - public void caretUpdate(CaretEvent e) { - if (ignoreCarret) { - return; - } - if (editMode || editDecompiledMode) { - return; - } - editor.getCaret().setVisible(true); - int pos = editor.getCaretPosition(); - Highlighting lastH = null; - for (Highlighting h : disassembledHilights) { - if (pos < h.startPos) { - break; - } - lastH = h; - } - Long ofs = lastH == null ? 0 : lastH.getProperties().offset; - Highlighting h2 = Highlighting.searchOffset(decompiledHilights, ofs); - if (h2 != null) { - ignoreCarret = true; - if (h2.startPos <= decompiledEditor.getDocument().getLength()) { - decompiledEditor.setCaretPosition(h2.startPos); - } - decompiledEditor.getCaret().setVisible(true); - ignoreCarret = false; - - } - } - }); - - decompiledEditor.addCaretListener(new CaretListener() { - @Override - public void caretUpdate(CaretEvent e) { - if (ignoreCarret) { - return; - } - if (editMode || editDecompiledMode) { - return; - } - decompiledEditor.getCaret().setVisible(true); - int pos = decompiledEditor.getCaretPosition(); - Highlighting h = Highlighting.searchPos(decompiledHilights, pos); - if (h != null) { - Highlighting h2 = Highlighting.searchOffset(disassembledHilights, h.getProperties().offset); - if (h2 != null) { - ignoreCarret = true; - if (h2.startPos > 0 && h2.startPos < editor.getText().length()) { - editor.setCaretPosition(h2.startPos); - } - editor.getCaret().setVisible(true); - ignoreCarret = false; - } - } - } - }); - - editor.addTextChangedListener(this::editorTextChanged); - decompiledEditor.addTextChangedListener(this::decompiledEditorTextChanged); - } - - private void editorTextChanged() { - setModified(true); - } - - private void decompiledEditorTextChanged() { - setDecompiledModified(true); - } - - private boolean isModified() { - return saveButton.isVisible() && saveButton.isEnabled(); - } - - private void setModified(boolean value) { - saveButton.setEnabled(value); - cancelButton.setEnabled(value); - } - - private boolean isDecompiledModified() { - return saveDecompiledButton.isVisible() && saveDecompiledButton.isEnabled(); - } - - private void setDecompiledModified(boolean value) { - saveDecompiledButton.setEnabled(value); - cancelDecompiledButton.setEnabled(value); - } - - public void setEditMode(boolean val) { - View.execInEventDispatch(() -> { - if (val) { - if (hexOnlyButton.isSelected()) { - setHex(ScriptExportMode.HEX, src.getScriptName()); - } else if (constantsViewButton.isSelected()) { - setHex(ScriptExportMode.CONSTANTS, src.getScriptName()); - } else { - setHex(ScriptExportMode.PCODE, src.getScriptName()); - } - } - - editor.setEditable(val); - saveButton.setVisible(val); - saveButton.setEnabled(false); - editButton.setVisible(!val); - cancelButton.setVisible(val); - - editor.getCaret().setVisible(true); - asmLabel.setIcon(val ? View.getIcon("editing16") : null); // this line is not working - topButtonsPan.setVisible(!val); - editMode = val; - editor.requestFocusInWindow(); - }); - } - - public void setDecompiledEditMode(boolean val) { - if (lastASM == null) { - return; - } - View.execInEventDispatch(() -> { - int lastLine = decompiledEditor.getLine(); - int prefLines = lastASM.getPrefixLineCount(); - if (val) { - String newText = lastASM.removePrefixAndSuffix(lastDecompiled); - setDecompiledText(lastASM.getScriptName(), newText); - if (lastLine > -1) { - if (lastLine - prefLines >= 0) { - decompiledEditor.gotoLine(lastLine - prefLines + 1); - } - } - } else { - String newText = lastDecompiled; - setDecompiledText(lastASM.getScriptName(), newText); - if (lastLine > -1) { - decompiledEditor.gotoLine(lastLine + prefLines + 1); - } - } - - decompiledEditor.setEditable(val); - saveDecompiledButton.setVisible(val); - saveDecompiledButton.setEnabled(false); - editDecompiledButton.setVisible(!val); - experimentalLabel.setVisible(!val); - cancelDecompiledButton.setVisible(val); - - decompiledEditor.getCaret().setVisible(true); - decLabel.setIcon(val ? View.getIcon("editing16") : null); - editDecompiledMode = val; - decompiledEditor.requestFocusInWindow(); - }); - } - - private void graphButtonActionPerformed(ActionEvent evt) { - if (lastCode != null) { - try { - GraphDialog gf = new GraphDialog(mainPanel.getMainFrame().getWindow(), new ActionGraph(lastCode, new HashMap<>(), new HashMap<>(), new HashMap<>(), SWF.DEFAULT_VERSION), ""); - gf.setVisible(true); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - } - - private void editActionButtonActionPerformed(ActionEvent evt) { - setEditMode(true); - } - - private void hexButtonActionPerformed(ActionEvent evt) { - setHex(getExportMode(), src.getScriptName()); - } - - private void hexOnlyButtonActionPerformed(ActionEvent evt) { - setHex(getExportMode(), src.getScriptName()); - } - - private void constantsViewButtonActionPerformed(ActionEvent evt) { - setHex(getExportMode(), src.getScriptName()); - } - - private void resolveConstantsButtonActionPerformed(ActionEvent evt) { - boolean resolve = resolveConstantsButton.isSelected(); - Configuration.resolveConstants.set(resolve); - - srcWithHex = null; - srcNoHex = null; - // srcHexOnly = null; is not needed since it does not contains the resolved constant names - setHex(getExportMode(), src.getScriptName()); - } - - private void showFileOffsetInPcodeHexButtonActionPerformed(ActionEvent evt) { - boolean resolve = showFileOffsetInPcodeHexButton.isSelected(); - Configuration.showFileOffsetInPcodeHex.set(resolve); - - srcWithHex = null; - setHex(getExportMode(), src.getScriptName()); - } - - private void showOriginalBytesInPcodeHexButtonActionPerformed(ActionEvent evt) { - boolean resolve = showOriginalBytesInPcodeHexButton.isSelected(); - Configuration.showOriginalBytesInPcodeHex.set(resolve); - - srcWithHex = null; - setHex(getExportMode(), src.getScriptName()); - } - - private void cancelActionButtonActionPerformed(ActionEvent evt) { - setEditMode(false); - setHex(getExportMode(), src.getScriptName()); - } - - private void saveActionButtonActionPerformed(ActionEvent evt) { - try { - String text = editor.getText(); - String trimmed = text.trim(); - if (trimmed.startsWith(Helper.hexData)) { - src.setActionBytes(Helper.getBytesFromHexaText(text)); - } else if (trimmed.startsWith(Helper.constants)) { - List> constantPools = Helper.getConstantPoolsFromText(text); - try { - Action.setConstantPools(src, constantPools, true); - } catch (ConstantPoolTooBigException ex) { - View.showMessageDialog(this, AppStrings.translate("error.constantPoolTooBig").replace("%index%", Integer.toString(ex.index)).replace("%size%", Integer.toString(ex.size)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - } - } else { - src.setActions(ASMParser.parse(0, true, text, src.getSwf().version, false)); - } - - SWF.uncache(src); - src.setModified(); - setSource(this.src, false); - View.showMessageDialog(this, AppStrings.translate("message.action.saved"), AppStrings.translate("dialog.message.title"), JOptionPane.INFORMATION_MESSAGE, Configuration.showCodeSavedMessage); - saveButton.setVisible(false); - cancelButton.setVisible(false); - editButton.setVisible(true); - editor.setEditable(false); - editMode = false; - mainPanel.refreshTree(src.getSwf()); - } catch (IOException ex) { - } catch (ActionParseException ex) { - editor.gotoLine((int) ex.line); - editor.markError(); - View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - } catch (Throwable ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - private void editDecompiledButtonActionPerformed(ActionEvent evt) { - if (View.showConfirmDialog(null, AppStrings.translate("message.confirm.experimental.function"), AppStrings.translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, Configuration.warningExperimentalAS12Edit, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) { - setDecompiledEditMode(true); - } - } - - private void cancelDecompiledButtonActionPerformed(ActionEvent evt) { - setDecompiledEditMode(false); - } - - private void saveDecompiledButtonActionPerformed(ActionEvent evt) { - try { - ActionScript2Parser par = new ActionScript2Parser(mainPanel.getCurrentSwf().version); - src.setActions(par.actionsFromString(decompiledEditor.getText())); - SWF.uncache(src); - src.setModified(); - setSource(src, false); - - View.showMessageDialog(this, AppStrings.translate("message.action.saved"), AppStrings.translate("dialog.message.title"), JOptionPane.INFORMATION_MESSAGE, Configuration.showCodeSavedMessage); - setDecompiledEditMode(false); - } catch (IOException ex) { - logger.log(Level.SEVERE, "IOException during action compiling", ex); - } catch (ActionParseException ex) { - View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - } catch (CompilationException ex) { - View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); - } catch (Throwable ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - private ScriptExportMode getExportMode() { - ScriptExportMode exportMode = hexOnlyButton.isSelected() ? ScriptExportMode.HEX - : hexButton.isSelected() ? ScriptExportMode.PCODE_HEX - : constantsViewButton.isSelected() ? ScriptExportMode.CONSTANTS - : ScriptExportMode.PCODE; - return exportMode; - } - - @Override - public void updateSearchPos(ActionSearchResult item) { - TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel(); - TreePath tp = ttm.getTreePath(item.getSrc()); - mainPanel.tagTree.setSelectionPath(tp); - mainPanel.tagTree.scrollPathToVisible(tp); - decompiledEditor.setCaretPosition(0); - - View.execInEventDispatchLater(() -> { - searchPanel.showQuickFindDialog(decompiledEditor); - }); - } - - @Override - public boolean tryAutoSave() { - // todo: implement - return false; - } - - @Override - public boolean isEditing() { - return (saveButton.isVisible() && saveButton.isEnabled()) - || (saveDecompiledButton.isVisible() && saveDecompiledButton.isEnabled()); - } -} +/* + * Copyright (C) 2010-2016 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.action; + +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionGraph; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.CachedScript; +import com.jpexs.decompiler.flash.action.ConstantPoolTooBigException; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; +import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser; +import com.jpexs.decompiler.flash.action.parser.script.ActionScriptLexer; +import com.jpexs.decompiler.flash.action.parser.script.ParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.script.SymbolType; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.gui.AppStrings; +import com.jpexs.decompiler.flash.gui.DebugPanel; +import com.jpexs.decompiler.flash.gui.DebuggerHandler; +import com.jpexs.decompiler.flash.gui.GraphDialog; +import com.jpexs.decompiler.flash.gui.HeaderLabel; +import com.jpexs.decompiler.flash.gui.Main; +import com.jpexs.decompiler.flash.gui.MainPanel; +import com.jpexs.decompiler.flash.gui.SearchListener; +import com.jpexs.decompiler.flash.gui.SearchPanel; +import com.jpexs.decompiler.flash.gui.TagEditorPanel; +import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane; +import com.jpexs.decompiler.flash.gui.controls.NoneSelectedButtonGroup; +import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane; +import com.jpexs.decompiler.flash.gui.editor.LinkHandler; +import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel; +import com.jpexs.decompiler.flash.helpers.HighlightedText; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; +import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.CancellationException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JToggleButton; +import javax.swing.SwingConstants; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.Highlighter; +import javax.swing.tree.TreePath; +import jsyntaxpane.SyntaxDocument; +import jsyntaxpane.Token; +import jsyntaxpane.TokenType; +import jsyntaxpane.actions.ActionUtils; + +/** + * + * @author JPEXS + */ +public class ActionPanel extends JPanel implements SearchListener, TagEditorPanel { + + private static final Logger logger = Logger.getLogger(ActionPanel.class.getName()); + + private MainPanel mainPanel; + + public DebuggableEditorPane editor; + + public DebuggableEditorPane decompiledEditor; + + public JPersistentSplitPane splitPane; + + public JButton saveButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); + + public JButton editButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); + + public JButton cancelButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); + + public JLabel experimentalLabel = new JLabel(AppStrings.translate("action.edit.experimental")); + + public JButton editDecompiledButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); + + public JButton saveDecompiledButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); + + public JButton cancelDecompiledButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); + + public JToggleButton hexButton; + + public JToggleButton hexOnlyButton; + + public JToggleButton constantsViewButton; + + public JToggleButton resolveConstantsButton; + + public JToggleButton showFileOffsetInPcodeHexButton; + + public JToggleButton showOriginalBytesInPcodeHexButton; + + public JLabel asmLabel = new HeaderLabel(AppStrings.translate("panel.disassembled")); + + public JLabel decLabel = new HeaderLabel(AppStrings.translate("panel.decompiled")); + + public List decompiledHilights = new ArrayList<>(); + + public List specialHighlights = new ArrayList<>(); + + public List classHighlights = new ArrayList<>(); + + public List methodHighlights = new ArrayList<>(); + + public List disassembledHilights = new ArrayList<>(); + + private boolean ignoreCarret = false; + + private boolean editMode = false; + + private boolean editDecompiledMode = false; + + private ActionList lastCode; + + private ASMSource src; + + public JPanel topButtonsPan; + + private HighlightedText srcWithHex; + + private HighlightedText srcNoHex; + + private HighlightedText srcHexOnly; + + private HighlightedText srcConstants; + + private String lastDecompiled = ""; + + private ASMSource lastASM; + + public SearchPanel searchPanel; + + private CancellableWorker setSourceWorker; + + public void clearSource() { + lastCode = null; + lastASM = null; + lastDecompiled = null; + searchPanel.clear(); + src = null; + srcWithHex = null; + srcNoHex = null; + srcHexOnly = null; + srcConstants = null; + } + + public String getStringUnderCursor() { + int pos = decompiledEditor.getCaretPosition(); + + SyntaxDocument sDoc = ActionUtils.getSyntaxDocument(decompiledEditor); + if (sDoc != null) { + Token t = sDoc.getTokenAt(pos + 1); + String ident = null; + //It should be identifier or obfuscated identifier + if (t != null && (t.type == TokenType.IDENTIFIER || t.type == TokenType.REGEX)) { + CharSequence tData = t.getText(sDoc); + ident = tData.toString(); + //We need to get unescaped identifier, so we use our Lexer + ActionScriptLexer lex = new ActionScriptLexer(new StringReader(ident)); + try { + ParsedSymbol symb = lex.lex(); + if (symb.type == SymbolType.IDENTIFIER) { + ident = (String) symb.value; + } else { + ident = null; + } + } catch (IOException | ActionParseException ex) { + ident = null; + } + } + if (ident == null) { + Highlighting h = Highlighting.searchPos(decompiledHilights, pos); + if (h != null) { + List list = lastCode; + Action lastIns = null; + int inspos = 0; + Action selIns = null; + for (Action ins : list) { + if (h.getProperties().offset == ins.getAddress()) { + selIns = ins; + break; + } + if (ins.getAddress() > h.getProperties().offset && lastIns != null) { + inspos = (int) (h.getProperties().offset - lastIns.getAddress()); + selIns = lastIns; + break; + } + lastIns = ins; + } + if (selIns != null) { + if (selIns instanceof ActionPush) { + ActionPush ap = (ActionPush) selIns; + Object var = ap.values.get(inspos - 1); + String identifier = null; + if (var instanceof String) { + identifier = (String) var; + } + if (var instanceof ConstantIndex) { + identifier = ap.constantPool.get(((ConstantIndex) var).index); + } + return identifier; + } + } + + } + } else { + return ident; + } + } + return null; + } + + public List search(SWF swf, final String txt, boolean ignoreCase, boolean regexp, CancellableWorker worker) { + if (txt != null && !txt.isEmpty()) { + searchPanel.setOptions(ignoreCase, regexp); + Map asms = swf.getASMs(false); + final List found = new ArrayList<>(); + Pattern pat; + if (regexp) { + pat = Pattern.compile(txt, ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); + } else { + pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0); + } + int pos = 0; + for (Entry item : asms.entrySet()) { + pos++; + String workText = AppStrings.translate("work.searching"); + String decAdd = ""; + ASMSource asm = item.getValue(); + if (!SWF.isCached(asm)) { + decAdd = ", " + AppStrings.translate("work.decompiling"); + } + + Main.startWork(workText + " \"" + txt + "\"" + decAdd + " - (" + pos + "/" + asms.size() + ") " + item.getKey() + "... ", worker); + try { + if (pat.matcher(SWF.getCached(asm, null).text).find()) { + found.add(new ActionSearchResult(asm, item.getKey())); + } + } catch (InterruptedException ex) { + break; + } + } + + return found; + } + + return null; + } + + private void setDecompiledText(final String scriptName, final String text) { + View.execInEventDispatch(() -> { + ignoreCarret = true; + decompiledEditor.setScriptName(scriptName); + decompiledEditor.setText(text); + ignoreCarret = false; + }); + } + + private void setEditorText(final String scriptName, final String text, final String contentType) { + View.execInEventDispatch(() -> { + ignoreCarret = true; + editor.setScriptName("#PCODE " + scriptName); + editor.changeContentType(contentType); + editor.setText(text); + ignoreCarret = false; + }); + } + + private void setText(final HighlightedText text, final String contentType, final String scriptName) { + View.execInEventDispatch(() -> { + int pos = editor.getCaretPosition(); + Highlighting lastH = null; + for (Highlighting h : disassembledHilights) { + if (pos < h.startPos) { + break; + } + lastH = h; + } + Long offset = lastH == null ? 0 : lastH.getProperties().offset; + disassembledHilights = text.instructionHilights; + String stripped = text.text; + setEditorText(scriptName, stripped, contentType); + Highlighting h = Highlighting.searchOffset(disassembledHilights, offset); + if (h != null) { + if (h.startPos <= editor.getDocument().getLength()) { + editor.setCaretPosition(h.startPos); + } + } + }); + } + + private HighlightedText getHighlightedText(ScriptExportMode exportMode) { + ASMSource asm = (ASMSource) src; + DisassemblyListener listener = getDisassemblyListener(); + asm.addDisassemblyListener(listener); + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); + try { + asm.getASMSource(exportMode, writer, lastCode); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + asm.removeDisassemblyListener(listener); + return new HighlightedText(writer); + } + + public void setHex(ScriptExportMode exportMode, String scriptName) { + switch (exportMode) { + case PCODE: + if (srcNoHex == null) { + srcNoHex = getHighlightedText(exportMode); + } + + setText(srcNoHex, "text/flasm", scriptName); + break; + case PCODE_HEX: + if (srcWithHex == null) { + srcWithHex = getHighlightedText(exportMode); + } + + setText(srcWithHex, "text/flasm", scriptName); + break; + case HEX: + if (srcHexOnly == null) { + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); + Helper.byteArrayToHexWithHeader(writer, src.getActionBytes().getRangeData()); + srcHexOnly = new HighlightedText(writer); + } + + setText(srcHexOnly, "text/plain", scriptName); + break; + case CONSTANTS: + if (srcConstants == null) { + srcConstants = getHighlightedText(exportMode); + } + + setText(srcConstants, "text/plain", scriptName); + break; + default: + throw new Error("Export mode not supported: " + exportMode); + } + } + + private DisassemblyListener getDisassemblyListener() { + DisassemblyListener listener = new DisassemblyListener() { + int percent = 0; + + String phase = ""; + + private void progress(String phase, long pos, long total) { + if (total < 1) { + return; + } + int newpercent = (int) (pos * 100 / total); + if (((newpercent > percent) || (!this.phase.equals(phase))) && newpercent <= 100) { + percent = newpercent; + this.phase = phase; + // todo: honfika: it is very slow to show every percent + setEditorText("-", "; " + AppStrings.translate("work.disassembling") + " - " + phase + " " + percent + "%...", "text/flasm"); + } + } + + @Override + public void progressReading(long pos, long total) { + progress(AppStrings.translate("disassemblingProgress.reading"), pos, total); + } + + @Override + public void progressToString(long pos, long total) { + progress(AppStrings.translate("disassemblingProgress.toString"), pos, total); + } + + @Override + public void progressDeobfuscating(long pos, long total) { + progress(AppStrings.translate("disassemblingProgress.deobfuscating"), pos, total); + } + }; + return listener; + } + + public void setSource(final ASMSource src, final boolean useCache) { + if (setSourceWorker != null) { + setSourceWorker.cancel(true); + setSourceWorker = null; + } + + clearSource(); + this.src = src; + final ASMSource asm = (ASMSource) src; + + if (!useCache) { + SWF.uncache(asm); + } + + boolean decompile = Configuration.decompile.get(); + if (!decompile) { + lastDecompiled = Helper.getDecompilationSkippedComment(); + setDecompiledText(asm.getScriptName(), lastDecompiled); + } else { + CachedScript sc = SWF.getFromCache(asm); + if (sc != null) { + decompile = false; + decompiledHilights = sc.hilights; + methodHighlights = sc.methodHilights; + classHighlights = sc.classHilights; + specialHighlights = sc.specialHilights; + lastDecompiled = sc.text; + lastASM = asm; + setDecompiledText(lastASM.getScriptName(), lastDecompiled); + } + } + + if (!decompile) { + setDecompiledEditMode(false); + } + + final boolean decompileNeeded = decompile; + + CancellableWorker worker = new CancellableWorker() { + + @Override + protected Void doInBackground() throws Exception { + + setEditorText(asm.getScriptName(), "; " + AppStrings.translate("work.disassembling") + "...", "text/flasm"); + if (decompileNeeded) { + setDecompiledText("-", "// " + AppStrings.translate("work.waitingfordissasembly") + "..."); + } + DisassemblyListener listener = getDisassemblyListener(); + asm.addDisassemblyListener(listener); + ActionList actions = asm.getActions(); + lastCode = actions; + asm.removeDisassemblyListener(listener); + setHex(getExportMode(), asm.getScriptName()); + if (decompileNeeded) { + setDecompiledText("-", "// " + AppStrings.translate("work.decompiling") + "..."); + + CachedScript sc = SWF.getCached(asm, actions); + decompiledHilights = sc.hilights; + methodHighlights = sc.methodHilights; + classHighlights = sc.classHilights; + specialHighlights = sc.specialHilights; + lastDecompiled = sc.text; + lastASM = asm; + setDecompiledText(lastASM.getScriptName(), lastDecompiled); + setDecompiledEditMode(false); + } + setEditMode(false); + + return null; + } + + @Override + protected void done() { + View.execInEventDispatch(() -> { + setSourceWorker = null; + if (!Main.isDebugging()) { + Main.stopWork(); + } + + try { + get(); + } catch (CancellationException ex) { + setEditorText("-", "; " + AppStrings.translate("work.canceled"), "text/flasm"); + } catch (Exception ex) { + setDecompiledText("-", "// " + AppStrings.translate("decompilationError") + ": " + ex); + } + }); + } + }; + worker.execute(); + setSourceWorker = worker; + if (!Main.isDebugging()) { + Main.startWork(AppStrings.translate("work.decompiling") + "...", worker); + } + } + + public void hilightOffset(long offset) { + } + + public int getLocalDeclarationOfPos(int pos) { + Highlighting sh = Highlighting.searchPos(specialHighlights, pos); + Highlighting h = Highlighting.searchPos(decompiledHilights, pos); + + if (h == null) { + return -1; + } + + List tms = Highlighting.searchAllPos(methodHighlights, pos); + if (tms.isEmpty()) { + return -1; + } + for (Highlighting tm : tms) { + + List tm_tms = Highlighting.searchAllLocalNames(methodHighlights, tm.getProperties().localName); + //is it already declaration? + if (h.getProperties().declaration || (sh != null && sh.getProperties().declaration)) { + return -1; //no jump + } + + String lname = h.getProperties().localName; + if ("this".equals(lname)) { + Highlighting ch = Highlighting.searchPos(classHighlights, pos); + // int cindex = (int) ch.getProperties().index; + return ch.startPos; + } + + HighlightData hData = h.getProperties(); + HighlightData search = new HighlightData(); + search.declaration = hData.declaration; + //search.declaredType = hData.declaredType; + search.localName = hData.localName; + //search.specialValue = hData.specialValue; + if (search.isEmpty()) { + return -1; + } + search.declaration = true; + + for (Highlighting tm1 : tm_tms) { + Highlighting rh = Highlighting.search(decompiledHilights, search, tm1.startPos, tm1.startPos + tm1.len); + if (rh != null) { + return rh.startPos; + } + } + } + + return -1; + } + + public ActionPanel(MainPanel mainPanel) { + this.mainPanel = mainPanel; + editor = new DebuggableEditorPane(); + editor.setEditable(false); + decompiledEditor = new DebuggableEditorPane(); + decompiledEditor.setEditable(false); + decompiledEditor.setLinkHandler(new LinkHandler() { + + @Override + public boolean isLink(Token token) { + int pos = token.start; + Highlighting h = Highlighting.searchPos(decompiledHilights, pos); + if (h != null) { + if (h.getProperties().localName != null && !h.getProperties().declaration) { + return getLocalDeclarationOfPos(pos) != -1; + } + } + return false; + } + + @Override + public void handleLink(Token token) { + int pos = token.start; + int tpos = getLocalDeclarationOfPos(pos); + if (tpos > -1) { + //System.err.println("goto " + tpos); + decompiledEditor.setCaretPosition(tpos); + } else { + //System.err.println("cannot handle"); + } + } + + @Override + public Highlighter.HighlightPainter linkPainter() { + return decompiledEditor.linkPainter(); + } + }); + + searchPanel = new SearchPanel<>(new FlowLayout(), this); + + JButton graphButton = new JButton(View.getIcon("graph16")); + graphButton.addActionListener(this::graphButtonActionPerformed); + graphButton.setToolTipText(AppStrings.translate("button.viewgraph")); + graphButton.setMargin(new Insets(3, 3, 3, 3)); + + hexButton = new JToggleButton(View.getIcon("hexas16")); + hexButton.addActionListener(this::hexButtonActionPerformed); + hexButton.setToolTipText(AppStrings.translate("button.viewhexpcode")); + hexButton.setMargin(new Insets(3, 3, 3, 3)); + + hexOnlyButton = new JToggleButton(View.getIcon("hex16")); + hexOnlyButton.addActionListener(this::hexOnlyButtonActionPerformed); + hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex")); + hexOnlyButton.setMargin(new Insets(3, 3, 3, 3)); + + constantsViewButton = new JToggleButton(View.getIcon("constantpool16")); + constantsViewButton.addActionListener(this::constantsViewButtonActionPerformed); + constantsViewButton.setToolTipText(AppStrings.translate("button.viewConstants")); + constantsViewButton.setMargin(new Insets(3, 3, 3, 3)); + + NoneSelectedButtonGroup exportModeButtonGroup = new NoneSelectedButtonGroup(); + exportModeButtonGroup.add(hexButton); + exportModeButtonGroup.add(hexOnlyButton); + exportModeButtonGroup.add(constantsViewButton); + + resolveConstantsButton = new JToggleButton(View.getIcon("resolveconst16")); + resolveConstantsButton.addActionListener(this::resolveConstantsButtonActionPerformed); + resolveConstantsButton.setToolTipText(AppStrings.translate("button.resolveConstants")); + resolveConstantsButton.setMargin(new Insets(3, 3, 3, 3)); + resolveConstantsButton.setSelected(Configuration.resolveConstants.get()); + + showFileOffsetInPcodeHexButton = new JToggleButton(View.getIcon("fileoffset16")); + showFileOffsetInPcodeHexButton.addActionListener(this::showFileOffsetInPcodeHexButtonActionPerformed); + showFileOffsetInPcodeHexButton.setToolTipText(AppStrings.translate("button.showFileOffsetInPcodeHex")); + showFileOffsetInPcodeHexButton.setMargin(new Insets(3, 3, 3, 3)); + showFileOffsetInPcodeHexButton.setSelected(Configuration.showFileOffsetInPcodeHex.get()); + + showOriginalBytesInPcodeHexButton = new JToggleButton(View.getIcon("originalbytes16")); + showOriginalBytesInPcodeHexButton.addActionListener(this::showOriginalBytesInPcodeHexButtonActionPerformed); + showOriginalBytesInPcodeHexButton.setToolTipText(AppStrings.translate("button.showOriginalBytesInPcodeHex")); + showOriginalBytesInPcodeHexButton.setMargin(new Insets(3, 3, 3, 3)); + showOriginalBytesInPcodeHexButton.setSelected(Configuration.showOriginalBytesInPcodeHex.get()); + + topButtonsPan = new JPanel(); + topButtonsPan.setLayout(new BoxLayout(topButtonsPan, BoxLayout.X_AXIS)); + topButtonsPan.add(graphButton); + topButtonsPan.add(Box.createRigidArea(new Dimension(10, 0))); + topButtonsPan.add(hexButton); + topButtonsPan.add(hexOnlyButton); + topButtonsPan.add(constantsViewButton); + topButtonsPan.add(Box.createRigidArea(new Dimension(10, 0))); + topButtonsPan.add(resolveConstantsButton); + topButtonsPan.add(showFileOffsetInPcodeHexButton); + topButtonsPan.add(showOriginalBytesInPcodeHexButton); + + JPanel panCode = new JPanel(new BorderLayout()); + panCode.add(new JScrollPane(editor), BorderLayout.CENTER); + panCode.add(topButtonsPan, BorderLayout.NORTH); + + JPanel panB = new JPanel(); + panB.setLayout(new BorderLayout()); + asmLabel.setHorizontalAlignment(SwingConstants.CENTER); + //asmLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); + panB.add(asmLabel, BorderLayout.NORTH); + panB.add(panCode, BorderLayout.CENTER); + + JPanel buttonsPan = new JPanel(); + buttonsPan.setLayout(new FlowLayout()); + buttonsPan.add(editButton); + buttonsPan.add(saveButton); + buttonsPan.add(cancelButton); + + editButton.setMargin(new Insets(3, 3, 3, 10)); + saveButton.setMargin(new Insets(3, 3, 3, 10)); + cancelButton.setMargin(new Insets(3, 3, 3, 10)); + + JPanel decButtonsPan = new JPanel(new FlowLayout()); + decButtonsPan.add(editDecompiledButton); + decButtonsPan.add(experimentalLabel); + decButtonsPan.add(saveDecompiledButton); + decButtonsPan.add(cancelDecompiledButton); + + editDecompiledButton.setMargin(new Insets(3, 3, 3, 10)); + saveDecompiledButton.setMargin(new Insets(3, 3, 3, 10)); + cancelDecompiledButton.setMargin(new Insets(3, 3, 3, 10)); + + //buttonsPan.add(saveHexButton); + //buttonsPan.add(loadHexButton); + panB.add(buttonsPan, BorderLayout.SOUTH); + + saveButton.addActionListener(this::saveActionButtonActionPerformed); + editButton.addActionListener(this::editActionButtonActionPerformed); + cancelButton.addActionListener(this::cancelActionButtonActionPerformed); + saveButton.setVisible(false); + cancelButton.setVisible(false); + + saveDecompiledButton.addActionListener(this::saveDecompiledButtonActionPerformed); + editDecompiledButton.addActionListener(this::editDecompiledButtonActionPerformed); + cancelDecompiledButton.addActionListener(this::cancelDecompiledButtonActionPerformed); + saveDecompiledButton.setVisible(false); + cancelDecompiledButton.setVisible(false); + + JPanel panA = new JPanel(new BorderLayout()); + + panA.add(decLabel, BorderLayout.NORTH); + + DebugPanel debugPanel = new DebugPanel(); + + panA.add(new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(decompiledEditor), debugPanel, Configuration.guiActionVarsSplitPaneDividerLocationPercent), BorderLayout.CENTER); + panA.add(decButtonsPan, BorderLayout.SOUTH); + + //decPanel.add(searchPanel, BorderLayout.NORTH); + Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener() { + + @Override + public void connected() { + decButtonsPan.setVisible(false); + } + + @Override + public void disconnected() { + decButtonsPan.setVisible(true); + } + }); + + //new JSplitPane(JSplitPane.VERTICAL_SPLIT, decompiledEditor, debugPanel) + //decPanel.add(decButtonsPan, BorderLayout.SOUTH); + //JPanel panBot = new JPanel(new BorderLayout()); + //panBot.add(decButtonsPan, BorderLayout.NORTH); + //panBot.add(debugPanel, BorderLayout.CENTER); + //panA.add(decButtonsPan, BorderLayout.SOUTH); + debugPanel.setVisible(false); + + decLabel.setHorizontalAlignment(SwingConstants.CENTER); + //decLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); + + setLayout(new BorderLayout()); + add(splitPane = new JPersistentSplitPane(JSplitPane.HORIZONTAL_SPLIT, panA, panB, Configuration.guiActionSplitPaneDividerLocationPercent), BorderLayout.CENTER); + + editor.setFont(new Font("Monospaced", Font.PLAIN, editor.getFont().getSize())); + decompiledEditor.setFont(new Font("Monospaced", Font.PLAIN, decompiledEditor.getFont().getSize())); + decompiledEditor.changeContentType("text/actionscript"); + + editor.addCaretListener(new CaretListener() { + @Override + public void caretUpdate(CaretEvent e) { + if (ignoreCarret) { + return; + } + if (editMode || editDecompiledMode) { + return; + } + editor.getCaret().setVisible(true); + int pos = editor.getCaretPosition(); + Highlighting lastH = null; + for (Highlighting h : disassembledHilights) { + if (pos < h.startPos) { + break; + } + lastH = h; + } + Long ofs = lastH == null ? 0 : lastH.getProperties().offset; + Highlighting h2 = Highlighting.searchOffset(decompiledHilights, ofs); + if (h2 != null) { + ignoreCarret = true; + if (h2.startPos <= decompiledEditor.getDocument().getLength()) { + decompiledEditor.setCaretPosition(h2.startPos); + } + decompiledEditor.getCaret().setVisible(true); + ignoreCarret = false; + + } + } + }); + + decompiledEditor.addCaretListener(new CaretListener() { + @Override + public void caretUpdate(CaretEvent e) { + if (ignoreCarret) { + return; + } + if (editMode || editDecompiledMode) { + return; + } + decompiledEditor.getCaret().setVisible(true); + int pos = decompiledEditor.getCaretPosition(); + Highlighting h = Highlighting.searchPos(decompiledHilights, pos); + if (h != null) { + Highlighting h2 = Highlighting.searchOffset(disassembledHilights, h.getProperties().offset); + if (h2 != null) { + ignoreCarret = true; + if (h2.startPos > 0 && h2.startPos < editor.getText().length()) { + editor.setCaretPosition(h2.startPos); + } + editor.getCaret().setVisible(true); + ignoreCarret = false; + } + } + } + }); + + editor.addTextChangedListener(this::editorTextChanged); + decompiledEditor.addTextChangedListener(this::decompiledEditorTextChanged); + } + + private void editorTextChanged() { + setModified(true); + } + + private void decompiledEditorTextChanged() { + setDecompiledModified(true); + } + + private boolean isModified() { + return saveButton.isVisible() && saveButton.isEnabled(); + } + + private void setModified(boolean value) { + saveButton.setEnabled(value); + cancelButton.setEnabled(value); + } + + private boolean isDecompiledModified() { + return saveDecompiledButton.isVisible() && saveDecompiledButton.isEnabled(); + } + + private void setDecompiledModified(boolean value) { + saveDecompiledButton.setEnabled(value); + cancelDecompiledButton.setEnabled(value); + } + + public void setEditMode(boolean val) { + View.execInEventDispatch(() -> { + if (val) { + if (hexOnlyButton.isSelected()) { + setHex(ScriptExportMode.HEX, src.getScriptName()); + } else if (constantsViewButton.isSelected()) { + setHex(ScriptExportMode.CONSTANTS, src.getScriptName()); + } else { + setHex(ScriptExportMode.PCODE, src.getScriptName()); + } + } + + editor.setEditable(val); + saveButton.setVisible(val); + saveButton.setEnabled(false); + editButton.setVisible(!val); + cancelButton.setVisible(val); + + editor.getCaret().setVisible(true); + asmLabel.setIcon(val ? View.getIcon("editing16") : null); // this line is not working + topButtonsPan.setVisible(!val); + editMode = val; + editor.requestFocusInWindow(); + }); + } + + public void setDecompiledEditMode(boolean val) { + if (lastASM == null) { + return; + } + View.execInEventDispatch(() -> { + int lastLine = decompiledEditor.getLine(); + int prefLines = lastASM.getPrefixLineCount(); + if (val) { + String newText = lastASM.removePrefixAndSuffix(lastDecompiled); + setDecompiledText(lastASM.getScriptName(), newText); + if (lastLine > -1) { + if (lastLine - prefLines >= 0) { + decompiledEditor.gotoLine(lastLine - prefLines + 1); + } + } + } else { + String newText = lastDecompiled; + setDecompiledText(lastASM.getScriptName(), newText); + if (lastLine > -1) { + decompiledEditor.gotoLine(lastLine + prefLines + 1); + } + } + + decompiledEditor.setEditable(val); + saveDecompiledButton.setVisible(val); + saveDecompiledButton.setEnabled(false); + editDecompiledButton.setVisible(!val); + experimentalLabel.setVisible(!val); + cancelDecompiledButton.setVisible(val); + + decompiledEditor.getCaret().setVisible(true); + decLabel.setIcon(val ? View.getIcon("editing16") : null); + editDecompiledMode = val; + decompiledEditor.requestFocusInWindow(); + }); + } + + private void graphButtonActionPerformed(ActionEvent evt) { + if (lastCode != null) { + try { + GraphDialog gf = new GraphDialog(mainPanel.getMainFrame().getWindow(), new ActionGraph(lastCode, new HashMap<>(), new HashMap<>(), new HashMap<>(), SWF.DEFAULT_VERSION), ""); + gf.setVisible(true); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + + private void editActionButtonActionPerformed(ActionEvent evt) { + setEditMode(true); + } + + private void hexButtonActionPerformed(ActionEvent evt) { + setHex(getExportMode(), src.getScriptName()); + } + + private void hexOnlyButtonActionPerformed(ActionEvent evt) { + setHex(getExportMode(), src.getScriptName()); + } + + private void constantsViewButtonActionPerformed(ActionEvent evt) { + setHex(getExportMode(), src.getScriptName()); + } + + private void resolveConstantsButtonActionPerformed(ActionEvent evt) { + boolean resolve = resolveConstantsButton.isSelected(); + Configuration.resolveConstants.set(resolve); + + srcWithHex = null; + srcNoHex = null; + // srcHexOnly = null; is not needed since it does not contains the resolved constant names + setHex(getExportMode(), src.getScriptName()); + } + + private void showFileOffsetInPcodeHexButtonActionPerformed(ActionEvent evt) { + boolean resolve = showFileOffsetInPcodeHexButton.isSelected(); + Configuration.showFileOffsetInPcodeHex.set(resolve); + + srcWithHex = null; + setHex(getExportMode(), src.getScriptName()); + } + + private void showOriginalBytesInPcodeHexButtonActionPerformed(ActionEvent evt) { + boolean resolve = showOriginalBytesInPcodeHexButton.isSelected(); + Configuration.showOriginalBytesInPcodeHex.set(resolve); + + srcWithHex = null; + setHex(getExportMode(), src.getScriptName()); + } + + private void cancelActionButtonActionPerformed(ActionEvent evt) { + setEditMode(false); + setHex(getExportMode(), src.getScriptName()); + } + + private void saveActionButtonActionPerformed(ActionEvent evt) { + try { + String text = editor.getText(); + String trimmed = text.trim(); + if (trimmed.startsWith(Helper.hexData)) { + src.setActionBytes(Helper.getBytesFromHexaText(text)); + } else if (trimmed.startsWith(Helper.constants)) { + List> constantPools = Helper.getConstantPoolsFromText(text); + try { + Action.setConstantPools(src, constantPools, true); + } catch (ConstantPoolTooBigException ex) { + View.showMessageDialog(this, AppStrings.translate("error.constantPoolTooBig").replace("%index%", Integer.toString(ex.index)).replace("%size%", Integer.toString(ex.size)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + } + } else { + src.setActions(ASMParser.parse(0, true, text, src.getSwf().version, false)); + } + + SWF.uncache(src); + src.setModified(); + setSource(this.src, false); + View.showMessageDialog(this, AppStrings.translate("message.action.saved"), AppStrings.translate("dialog.message.title"), JOptionPane.INFORMATION_MESSAGE, Configuration.showCodeSavedMessage); + saveButton.setVisible(false); + cancelButton.setVisible(false); + editButton.setVisible(true); + editor.setEditable(false); + editMode = false; + mainPanel.refreshTree(src.getSwf()); + } catch (IOException ex) { + } catch (ActionParseException ex) { + editor.gotoLine((int) ex.line); + editor.markError(); + View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + } catch (Throwable ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + private void editDecompiledButtonActionPerformed(ActionEvent evt) { + if (View.showConfirmDialog(null, AppStrings.translate("message.confirm.experimental.function"), AppStrings.translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, Configuration.warningExperimentalAS12Edit, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) { + setDecompiledEditMode(true); + } + } + + private void cancelDecompiledButtonActionPerformed(ActionEvent evt) { + setDecompiledEditMode(false); + } + + private void saveDecompiledButtonActionPerformed(ActionEvent evt) { + try { + ActionScript2Parser par = new ActionScript2Parser(mainPanel.getCurrentSwf().version); + src.setActions(par.actionsFromString(decompiledEditor.getText())); + SWF.uncache(src); + src.setModified(); + setSource(src, false); + + View.showMessageDialog(this, AppStrings.translate("message.action.saved"), AppStrings.translate("dialog.message.title"), JOptionPane.INFORMATION_MESSAGE, Configuration.showCodeSavedMessage); + setDecompiledEditMode(false); + } catch (IOException ex) { + logger.log(Level.SEVERE, "IOException during action compiling", ex); + } catch (ActionParseException ex) { + View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + } catch (CompilationException ex) { + View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + } catch (Throwable ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + private ScriptExportMode getExportMode() { + ScriptExportMode exportMode = hexOnlyButton.isSelected() ? ScriptExportMode.HEX + : hexButton.isSelected() ? ScriptExportMode.PCODE_HEX + : constantsViewButton.isSelected() ? ScriptExportMode.CONSTANTS + : ScriptExportMode.PCODE; + return exportMode; + } + + @Override + public void updateSearchPos(ActionSearchResult item) { + TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel(); + TreePath tp = ttm.getTreePath(item.getSrc()); + mainPanel.tagTree.setSelectionPath(tp); + mainPanel.tagTree.scrollPathToVisible(tp); + decompiledEditor.setCaretPosition(0); + + View.execInEventDispatchLater(() -> { + searchPanel.showQuickFindDialog(decompiledEditor); + }); + } + + @Override + public boolean tryAutoSave() { + // todo: implement + return false; + } + + @Override + public boolean isEditing() { + return (saveButton.isVisible() && saveButton.isEnabled()) + || (saveDecompiledButton.isVisible() && saveDecompiledButton.isEnabled()); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog.properties index 65134b742..1db9944e5 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog.properties @@ -1,27 +1,27 @@ -# Copyright (C) 2010-2016 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 . - -version = version -by = by -button.ok = OK -dialog.title = About -contributors = Contributors: -#In the translation, replace "english" with target language name -translation.author.label = Author of english translation: -#In the translation, insert your name here -translation.author = JPEXS -developers = Developers: -developers.others = + others from GitHub and Google code -translators = Translators: +# Copyright (C) 2010-2016 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 . + +version = version +by = by +button.ok = OK +dialog.title = About +contributors = Contributors: +#In the translation, replace "english" with target language name +translation.author.label = Author of english translation: +#In the translation, insert your name here +translation.author = JPEXS +developers = Developers: +developers.others = + others from GitHub and Google code +translators = Translators: diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_es.properties b/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_es.properties index 5ff1527e5..7c5c198ae 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_es.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_es.properties @@ -1,27 +1,27 @@ -# Copyright (C) 2010-2016 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 . - -version = versi\u00f3n -by = por -button.ok = OK -dialog.title = Acerca de -contributors = Colaboradores: -#In the translation, replace "english" with target language name -translation.author.label = Autor de la traducci\u00f3n al espa\u00f1ol: -#In the translation, insert your name here -translation.author = poxyran -developers = Desarrolladores: -developers.others = + otros de GitHub y Google code -translators = Traductores: +# Copyright (C) 2010-2016 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 . + +version = versi\u00f3n +by = por +button.ok = OK +dialog.title = Acerca de +contributors = Colaboradores: +#In the translation, replace "english" with target language name +translation.author.label = Autor de la traducci\u00f3n al espa\u00f1ol: +#In the translation, insert your name here +translation.author = poxyran +developers = Desarrolladores: +developers.others = + otros de GitHub y Google code +translators = Traductores: diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_sv.properties b/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_sv.properties index ca3f77e85..00a0f47e9 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_sv.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AboutDialog_sv.properties @@ -1,27 +1,27 @@ -# Copyright (C) 2010-2016 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 . - -version = version -by = av -button.ok = Okej -dialog.title = Om -contributors = Bidragande: -#In the translation, replace "english" with target language name -translation.author.label = Skapare utav Svensk \u00f6vers\u00e4ttning: -#In the translation, insert your name here -translation.author = Capasha -developers = Utvecklare: -developers.others = + andra fr\u00e5n GitHub och Google code -translators = \u00d6vers\u00e4ttare: +# Copyright (C) 2010-2016 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 . + +version = version +by = av +button.ok = Okej +dialog.title = Om +contributors = Bidragande: +#In the translation, replace "english" with target language name +translation.author.label = Skapare utav Svensk \u00f6vers\u00e4ttning: +#In the translation, insert your name here +translation.author = Capasha +developers = Utvecklare: +developers.others = + andra fr\u00e5n GitHub och Google code +translators = \u00d6vers\u00e4ttare: diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties index c3f31e3e1..aec34d531 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties @@ -1,434 +1,434 @@ -# Copyright (C) 2010-2016 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 . - -advancedSettings.dialog.title = Param\u00e8tres avanc\u00e9s -advancedSettings.restartConfirmation = Vous devez red\u00e9marrer le programme pour que les changements prennent effet. Red\u00e9marrer maintenant ? -advancedSettings.columns.name = Nom -advancedSettings.columns.value = Valeur -advancedSettings.columns.description = Description -default = D\u00e9faut - -config.group.name.export = Export -config.group.description.export = Configuration de l'export - -config.group.name.script = Scripts -config.group.description.script = D\u00e9compilation ActionScript connexes - -config.group.name.update = Mises \u00e0 jour -config.group.description.update = Recherche de mises \u00e0 jour - -config.group.name.format = Mise en forme -config.group.description.format = Mise en forme du code ActionScript - -config.group.name.limit = Limites -config.group.description.limit = Limites de la d\u00e9compilation du code crypt\u00e9, etc. - -config.group.name.ui = Interface -config.group.description.ui = Configuration de l'interface utilisateur - -config.group.name.debug = D\u00e9boguage -config.group.description.debug = Param\u00e8tres de d\u00e9boguage - -config.group.name.display = Affichage -config.group.description.display = Affichage des objets Flash, etc. - -config.group.name.decompilation = D\u00e9compilation -config.group.description.decompilation = Fonctions relatives \u00e0 la d\u00e9compilation - -config.group.name.other = Autres -config.group.description.other = Autres configurations - -config.name.openMultipleFiles = Ouvrir plusieurs fichiers -config.description.openMultipleFiles = Autoriser l'ouverture de plusieurs fichiers dans une seule fen\u00eatre - -config.name.decompile = Afficher les sources ActionScript -config.description.decompile = Vous pouvez d\u00e9sactiver la d\u00e9compilation ActionScript, seul le code Assembleur sera affich\u00e9 - -config.name.dumpView = Donn\u00e9es brutes -config.description.dumpView = Voir les donn\u00e9es brutes - -config.name.useHexColorFormat = Format couleur hexad\u00e9cimal -config.description.useHexColorFormat = Afficher les couleurs au format hexad\u00e9cimal - -config.name.parallelSpeedUp = Acc\u00e9l\u00e9ration parall\u00e8le -config.description.parallelSpeedUp = Le parall\u00e9lisme augmente la vitesse de d\u00e9compilation - -config.name.parallelSpeedUpThreadCount = Nombre de canaux -config.description.parallelSpeedUpThreadCount = Nombre de canaux \u00e0 utiliser pour l'acc\u00e9l\u00e9ration parall\u00e8le - -config.name.autoDeobfuscate = D\u00e9sobfuscation automatique -config.description.autoDeobfuscate = D\u00e9marer la d\u00e9sobfuscation sur l'ensemble des fichiers avant la d\u00e9compilation ActionScript - -config.name.cacheOnDisk = Utilisation de la m\u00e9moire cache du disque -config.description.cacheOnDisk = Des parties sont d\u00e9j\u00e0 d\u00e9compil\u00e9s sur le disque dur \u00e0 la place de la m\u00e9moire - -config.name.internalFlashViewer = Utiliser la visionneuse Flash int\u00e9gr\u00e9e -config.description.internalFlashViewer = Utililser la visionneuse Flash JPEXS au lieu de la visionneuse Flash standard pour afficher les \u00e9l\u00e9ments - -config.name.gotoMainClassOnStartup = Aller \u00e0 la classe d'initialisation (AS3) -config.description.gotoMainClassOnStartup = Aller dans la classe de document \u00e0 l'ouverture du fichier AS3 - -config.name.autoRenameIdentifiers = Renommage automatique des identifiants -config.description.autoRenameIdentifiers = Renomme automatiquement les identifiants invalides en chargeant le fichier SWF - -config.name.offeredAssociation = (Interne) Association de fichiers SWF d\u00e9j\u00e0 ouvert -config.description.offeredAssociation = La boite de dialogue d'association de fichiers est d\u00e9j\u00e0 ouverte - -config.name.decimalAddress = Utiliser l'adressage d\u00e9cimale -config.description.decimalAddress = Utiliser l'adressage d\u00e9cimale au lieu de l'adressage hexad\u00e9cimal - -config.name.showAllAddresses = Afficher toutes les adresses -config.description.showAllAddresses = Afficher toutes les instructions ActionScript \u00e0 toutes les adresses - -config.name.useFrameCache = Utiliser la m\u00e9moire cache des images -config.description.useFrameCache = Mettre en cache les images avant le nouveau rendu - -config.name.useRibbonInterface = Interface Ruban -config.description.useRibbonInterface = D\u00e9cocher pour utiliser l'interface classique sans le menu-ruban - -config.name.openFolderAfterFlaExport = Ouvrir le dossier apr\u00e8s l'export FLA -config.description.openFolderAfterFlaExport = Afficher le dossier apr\u00e8s l'export de fichiers FLA - -config.name.useDetailedLogging = Journal d\u00e9taill\u00e9 -config.description.useDetailedLogging = Les messages d'erreurs et les informations de d\u00e9bogages sont renseign\u00e9s dans le journal d\u00e9taill\u00e9 - -config.name.debugMode = Mode -config.description.debugMode = Mode d\u00e9boggage. Affiche le menu de d\u00e9boggage. - -config.name.resolveConstants = R\u00e9soudre les constantes dans le code assembleur en AS1/2 -config.description.resolveConstants = Arr\u00eate d'afficher 'constantxx' au lieu des vraies valeurs dans la fen\u00eatre assembleur - -config.name.sublimiter = Limites du sous-programme -config.description.sublimiter = Limites du sous-programme pour du code crypt\u00e9 - -config.name.exportTimeout = Limite de temps \u00e9coul\u00e9e \u00e0 l'exportation (secondes) -config.description.exportTimeout = Le d\u00e9compileur arr\u00eatera l'exportation d\u00e8s que cette valeur sera atteinte - -config.name.decompilationTimeoutFile = Limite de temps pour d\u00e9compiler un fichier (secondes) -config.description.decompilationTimeoutFile = Le d\u00e9compileur arr\u00eatera la d\u00e9compilation ActionScript d\u00e8s que cette valeur sera atteinte pour un fichier - -config.name.paramNamesEnable = Activer les noms de param\u00e8tres en AS3 -config.description.paramNamesEnable = L'utilisation des noms de param\u00e8tres en d\u00e9compilant peut causer des probl\u00e8mes parce que le programme officiel CS 5.5 pr\u00e9f\u00e8re Flash ins\u00e8rer des mauvais indices de noms de param\u00e9tres - -config.name.displayFileName = Afficher le nom SWF dans la barre de titre -config.description.displayFileName = Afficher l'URL et le nom de fichier dans la barre de titre (Vous pouvez faire des captures d'\u00e9cran) - -config.name.debugCopy = Recompilation en mode debug -config.description.debugCopy = Tenter de compiler le fichier SWF \u00e0 nouveau apr\u00e8s son ouverture pour s'assurer qu'il produise le m\u00eame code binaire. \u00c0 utiliser uniquement pour le d\u00e9boguage ! - -config.name.dumpTags = Afficher les \u00e9tiquettes dans la console -config.description.dumpTags = Afficher les \u00e9tiquettes dans la console en jouant le fichier SWF - -config.name.decompilationTimeoutSingleMethod = AS3: Single method decompilation timeout (secondes) -config.description.decompilationTimeoutSingleMethod = Le d\u00e9compilateur arr\u00eatera la d\u00e9compilation du code ActionScript d\u00e8 que ce temps sera atteint dans la m\u00e9thode - -config.name.lastRenameType = (Interne) Dernier type renomm\u00e9 -config.description.lastRenameType = Dernier type d'identificateur renomm\u00e9 utilis\u00e9 - -config.name.lastSaveDir = (Interne) Dernier dossier de sauvegarde -config.description.lastSaveDir = Dernier dossier de sauvegarde utilis\u00e9 - -config.name.lastOpenDir = (Interne) Dernier dossier ouvert -config.description.lastOpenDir = Dernier dossier ouvert utilis\u00e9 - -config.name.lastExportDir = (Interne) Dernier dossier d'export -config.description.lastExportDir = Dernier dossier d'export utilis\u00e9 - -config.name.locale = Langues -config.description.locale = Param\u00e8tres r\u00e9gionaux - -config.name.registerNameFormat = Format du registre des variables -config.description.registerNameFormat = Format du registre local des noms de variables. Utilise %d pour le registre num\u00e9rique. - -config.name.maxRecentFileCount = Nb. max. de fichiers r\u00e9cents -config.description.maxRecentFileCount = Nombre maximal de fichiers r\u00e9cents - -config.name.recentFiles = (Interne) Fichiers r\u00e9cents -config.description.recentFiles = Fichiers r\u00e9cemment ouverts - -config.name.fontPairingMap = (Interne) Couplage des polices pour l'importation -config.description.fontPairingMap = Couplage des polices pour l'importation des nouveaux caract\u00e8res - -config.name.lastUpdatesCheckDate = (Interne) Date de derni\u00e8re mises \u00e0 jour -config.description.lastUpdatesCheckDate = Date de la derni\u00e8re v\u00e9rification des mises \u00e0 jour sur le serveur - -config.name.gui.window.width = (Interne) Derni\u00e8re largeur de fen\u00eatre -config.description.gui.window.width = Derni\u00e8re valeur enregistr\u00e9e de la largeur de la fen\u00eatre - -config.name.gui.window.height = (Interne) Derni\u00e8re hauteur de fen\u00eatre -config.description.gui.window.height = Derni\u00e8re valeur enregistr\u00e9e de la hauteur de la fen\u00eatre - -config.name.gui.window.maximized.horizontal = (Interne) Agrandissement horizontal de la fen\u00eatre -config.description.gui.window.maximized.horizontal = Dernier \u00e9tat de la fen\u00eatre - Agrandissement horizontal - -config.name.gui.window.maximized.vertical = (Interne) Agrandissement vertical de la fen\u00eatre -config.description.gui.window.maximized.vertical = Derni\u00e8r \u00e9tat de la fen\u00eatre - Agrandissement vertical - -config.name.gui.avm2.splitPane.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur AS3 -config.description.gui.avm2.splitPane.dividerLocationPercent = - -config.name.gui.actionSplitPane.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur AS1/2 -config.description.gui.actionSplitPane.dividerLocationPercent = - -config.name.gui.previewSplitPane.dividerLocationPercent = (Interne) Aper\u00e7u de l'emplacement du s\u00e9parateur -config.description.gui.previewSplitPane.dividerLocationPercent = - -config.name.gui.splitPane1.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur 1 -config.description.gui.splitPane1.dividerLocationPercent = - -config.name.gui.splitPane2.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur 2 -config.description.gui.splitPane2.dividerLocationPercent = - -config.name.saveAsExeScaleMode = Enregistrer en tant qu'\u00e9chelle de mode EXE -config.description.saveAsExeScaleMode = Mode de mise \u00e0 l'\u00e9chelle pour un export EXE - -config.name.syntaxHighlightLimit = Nb max de caract\u00e8res surlign\u00e9s -config.description.syntaxHighlightLimit = Nombre maximal de caract\u00e8res pour surligner - -config.name.guiFontPreviewSampleText = (Internal) Dernier aper\u00e7u texte de la police de caract\u00e8res -config.description.guiFontPreviewSampleText = Dernier aper\u00e7u texte de la police de caract\u00e8res - -config.name.gui.fontPreviewWindow.width = (Interne) Derni\u00e8re largeur de fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res -config.description.gui.fontPreviewWindow.width = - -config.name.gui.fontPreviewWindow.height = (Interne) Derni\u00e8re hauteur de fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res -config.description.gui.fontPreviewWindow.height = - -config.name.gui.fontPreviewWindow.posX = (Interne) Derni\u00e8re position X de la fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res -config.description.gui.fontPreviewWindow.posX = Il s'agit de la position de la fen\u00eatre sur l'axe des abscisses - -config.name.gui.fontPreviewWindow.posY = (Interne) Derni\u00e8re position Y de la fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res -config.description.gui.fontPreviewWindow.posY = Il s'agit de la position de la fen\u00eatre sur l'axe des ordonn\u00e9es - -config.name.formatting.indent.size = Nb de caract\u00e8res par indentation -config.description.formatting.indent.size = Nombre d'espaces (ou tabulations) pour une indentation - -config.name.formatting.indent.useTabs = Indentation -config.description.formatting.indent.useTabs = Utiliser les tabulations au lieu d'espaces pour l'indentation - -config.name.beginBlockOnNewLine = Accolades pour les nouvelle lignes -config.description.beginBlockOnNewLine = Commencer les blocs avec des accolades sur les nouvelles lignes - -config.name.check.updates.delay = Intervale de v\u00e9rification des mises \u00e0 jour -config.description.check.updates.delay = Intervale minimum entre chaque v\u00e9rification automatique des mises \u00e0 jour au d\u00e8marrage de l'application - -config.name.check.updates.stable = V\u00e9rification des versions stables -config.description.check.updates.stable = V\u00e9rification des mises \u00e0 jour des versions stables - -config.name.check.updates.nightly = V\u00e9rification des versions de tests -config.description.check.updates.nightly = V\u00e9rification des mises \u00e0 jour des versions de tests - -config.name.check.updates.enabled = V\u00e9rification automatique activ\u00e9e -config.description.check.updates.enabled = V\u00e9rification automatique des mises \u00e0 jour lorsque au d\u00e9marrage de l'application - -config.name.export.formats = (Interne) Formats d'export -config.description.export.formats = Derniers formats d'export utilis\u00e8 - -config.name.textExportSingleFile = Export de textes dans un seul fichier -config.description.textExportSingleFile = Exportation de textes dans un seul fichier plut\u00f4t que dans plusieurs fichiers - -config.name.textExportSingleFileSeparator = S\u00e9parateur de textes dans un fichier d'export de textes -config.description.textExportSingleFileSeparator = Texte \u00e0 ins\u00e9rer entre chaque texte dans un fichier d'export de textes - -config.name.textExportSingleFileRecordSeparator = S\u00e9parateur d'enregistrement dans un fichier d'export de textes -config.description.textExportSingleFileRecordSeparator = Texte \u00e0 ins\u00e9rer entre chaque enregistrement dans un fichier d'export de textes - -config.name.warning.experimental.as12edit = Alerte lors d'\u00e9dition en AS1/2 -config.description.warning.experimental.as12edit = Afficher l'avertissement lors de l'\u00e9dition exp\u00e9rimentale des scripts AS1/2 - -config.name.warning.experimental.as3edit = Alerte lors d'\u00e9dition en AS3 -config.description.warning.experimental.as3edit = Afficher l'avertissement lors de l'\u00e9dition exp\u00e9rimentale des scripts AS3 - -config.name.packJavaScripts = Paquet JavaScripts -config.description.packJavaScripts = D\u00e9marrer le paquet JavaScript sur des scripts cr\u00e9\u00e9s lors de l'exportation de dessins - -config.name.textExportExportFontFace = Utiliser le style de police de caract\u00e8res dans l'export SVG -config.description.textExportExportFontFace = Embarquer le style de police de caract\u00e8res dans l'export SVG au lieu des formes - -config.name.lzmaFastBytes = LZMA fast bytes (valeurs permises : 5-255) -config.description.lzmaFastBytes = Param\u00e8tre vitesse des octets de l'encodeur LZMA - -config.name.pluginPath = Chemin du Plugin -config.description.pluginPath = - - -config.name.showMethodBodyId = Afficher l'identifiant dans le corps de texte -config.description.showMethodBodyId = Afficher l'identifiant dans le corps de la m\u00e9thode lors de l'importation en ligne de commande - -config.name.export.zoom = (Interne) Export du zoom -config.description.export.zoom = Dernier export de zoom utilis\u00e9 - -config.name.debuggerPort = Port de d\u00e9boggage -config.description.debuggerPort = Port utilis\u00e9 pour le d\u00e9boggage du socket - -config.name.displayDebuggerInfo = (Interne) Afficher les informations du d\u00e9boggueur -config.description.displayDebuggerInfo = Afficher les informations concernant le d\u00e9boggueur avant sa mise en route - -config.name.randomDebuggerPackage = Utiliser un nom de paquet al\u00e9atoire pour le d\u00e9boggueur -config.description.randomDebuggerPackage = Renomme le paquet de d\u00e9boggueur en une chaine de texte al\u00e9atoire lequel sera plus difficile \u00e0 d\u00e9tecter par ActionScript - -config.name.lastDebuggerReplaceFunction = (Interne) Dernier remplacement de traces s\u00e9lectionn\u00e9 -config.description.lastDebuggerReplaceFunction = Function name which was last selected in replace trace function with debugger - -config.name.getLocalNamesFromDebugInfo = AS3: R\u00e9cup\u00e9rer les noms de variables \u00e0 partir des informations de d\u00e9boggage -config.description.getLocalNamesFromDebugInfo = Si les informations de d\u00e9boggage sont pr\u00e9sents, alors renommer les variables locales de types _loc_x_ en utilisant leurs noms r\u00e9els. Peut \u00eatre d\u00e9sactiv\u00e9 car certains obfuscateurs utilisent ici des noms de variables invalides - -config.name.tagTreeShowEmptyFolders = Afficher les dossiers vides -config.description.tagTreeShowEmptyFolders = Afficher les dossiers vides dans l'arborescence des balises - -config.name.autoLoadEmbeddedSwfs = Chargement automatique des SWFs incorpor\u00e9s -config.description.autoLoadEmbeddedSwfs = Charger automatiquement les SWF embarqu\u00e9s \u00e0 partir des balises DefineBinaryData - -config.name.overrideTextExportFileName = Remplacer le nom de fichier lors de l'export de texte -config.description.overrideTextExportFileName = Vous pouvez personaliser le nom de fichier du texte export\u00e9. Utilisez {filename} dans l'emplacement d\u00e9di\u00e9 pour utiliser le nom de fichier du SWF courant. - -config.name.showOldTextDuringTextEditing = Afficher le texte d'origine lors de l'\u00e9dition -config.description.showOldTextDuringTextEditing = Afficher l'original des textes des balises en couleur grise dans l'aper\u00e7u. - -config.group.name.import = Import -config.group.description.import = Configuration des imports - -config.name.textImportResizeTextBoundsMode = Limites du texte en mode redimensionnement -config.description.textImportResizeTextBoundsMode = Limites du texte en mode redimensionnement apr\u00e8s son \u00e9dition. - -config.name.showCloseConfirmation = Confimation de fermeture -config.description.showCloseConfirmation = Affiche la confirmation de fermeture du fichier SWF lorsque les fichiers sont modifi\u00e9s - -config.name.showCodeSavedMessage = Afficher un message d'avertissement lors de l'enregistrement du code -config.description.showCodeSavedMessage = Afficher un message d'avertissement lors de l'enregistrement du code - -config.description.showTraitSavedMessage = Afficher un message d'avertissement lors de l'enregistrement d'une caract\u00e9ristique -config.name.showTraitSavedMessage = Afficher un message lors de l'enregistrement de la caract\u00e9ristique - -config.name.updateProxyAddress = Adresse du Proxy http pour v\u00e9rifier les mises \u00e0 jour -config.description.updateProxyAddress = Adresse du Proxy http pour v\u00e9rifier les mises \u00e0 jour. Format : exemple.com:8080 - -config.name.editorMode = Mode \u00e9diteur -config.description.editorMode = Rend \u00e9ditable les zones de texte automatiquement lorsque vous s\u00e9lectionnez un texte ou un script - -config.name.autoSaveTagModifications = Enregistrement auto des \u00e9tiquettes modifi\u00e9es -config.description.autoSaveTagModifications = Enregistre les changements lorsque vous s\u00e9lectionnez une autre \u00e9tiquette dans l'arborescence - -config.name.saveSessionOnExit = Enregistrer la session en quittant -config.description.saveSessionOnExit = Enregistre la session courante et la r\u00e9tablira au red\u00e9marrage de FFDec (ne fonctionne qu'avec des fichiers physiquement pr\u00e9sents sur disque) - -config.name._showDebugMenu = Affiche le menu de d\u00e9boggage FFDec -config.description._showDebugMenu = Affiche le menu de d\u00e9boggage dans le ruban lorsque le d\u00e9compileur est en train de d\u00e9bogguer. - -config.name.allowOnlyOneInstance = Une seule instance FFDec (OS Windows uniquement) -config.description.allowOnlyOneInstance = FFDec peut d\u00e9marrer en une seule fois, tous les fichiers ouverts seront ajout\u00e9s dans une unique fen\u00eatre. Ne fonctionne que sous Windows uniquement. - -config.name.scriptExportSingleFile = Export des scripts dans un seul fichier -config.description.scriptExportSingleFile = Exportation des scripts dans un seul fichier au lieu de cr\u00e9er plusieurs fichiers - -config.name.setFFDecVersionInExportedFont = Indiquer la version de FFDec dans la police de caract\u00e8res export\u00e9es -config.description.setFFDecVersionInExportedFont = Lorsque cette option est decoch\u00e9es, FFDec n'ajoutera son num\u00e9ro de version dans la police de caract\u00e8res export\u00e9es. - -config.name.gui.skin = Personnalisation de l'interface utilisateur -config.description.gui.skin = Personnalisation de l'interface utilisateur - -config.name.lastSessionFiles = Fichiers de la derni\u00e8re session -config.description.lastSessionFiles = Contient les fichiers ouverts lors de la derni\u00e8re session - -config.name.lastSessionSelection = S\u00e9lection de la derni\u00e8re session -config.description.lastSessionSelection = Contient la s\u00e9lection lors de la derni\u00e8re session - -config.name.loopMedia = Rejouer les sons et les sprites -config.description.loopMedia = Rejoue automatiquement les sons et les sprites - -config.name.gui.timeLineSplitPane.dividerLocationPercent = (Internal) Position du s\u00e9parateur de la fen\u00eatre du chronogramme -config.description.gui.timeLineSplitPane.dividerLocationPercent = - -config.name.cacheImages = Images en m\u00e9moire cache -config.description.cacheImages = Met en m\u00e9moire cache les images-objets d\u00e9cod\u00e9es - -config.name.swfSpecificConfigs = Configuration avanc\u00e9es SWF -config.description.swfSpecificConfigs = Contient les configurations avanc\u00e9es SWF - -config.name.exeExportMode = Mode export EXE -config.description.exeExportMode = Mode export EXE - -config.name.ignoreCLikePackages = Ignorer les paquets FlashCC / Alchemy ou similaires -config.description.ignoreCLikePackages = Les paquets FlashCC/Alchemy ne sont pas d\u00e9compilables correctement. Vous pouvez les d\u00e9sactiver pour gagner en vitesse de d\u00e9compilation avec les autres paquets. - -config.name.overwriteExistingFiles = \u00c9craser les fichiers existants -config.description.overwriteExistingFiles = \u00c9craser les fichiers existants lors de l'export. Ne fonctionne que pour les scripts AS2/3. - -config.name.smartNumberFormatting = Utiliser le formattage num\u00e9rique intelligent -config.description.smartNumberFormatting = Formattage num\u00e9riques sp\u00e9ciaux (par exemple : les couleurs et les temps) - -config.name.enableScriptInitializerDisplay = Affiche l'initialisateur de script -config.description.enableScriptInitializerDisplay = Active l'affichage et l'\u00e9ditiion de l'initialisateur de script. Ce param\u00e8tre ajoute une nouvelle ligne en \u00e9vidence dans chaque classe. - -config.name.autoOpenLoadedSWFs = Ouvre les SWF charg\u00e9s lors de l'ex\u00e9cution (Lecteur externe = Windows seulement) -config.description.autoOpenLoadedSWFs = Ouvre automatiquement tous les SWF charg\u00e9s par la classe de chargement AS3 en lisant les SWF jou\u00e9s dans le lecteur externe FFDec. Cette option ne fonctionne que sous Windows. - -config.name.lastSessionFileTitles = Les titres de la derni\u00c8re session -config.description.lastSessionFileTitles = Comprend les titres des fichiers ouverts lors de la derni\u00c8re session (par exemple depuis une URL, etc.) - -config.group.name.paths = Chemins -config.group.description.paths = Location des fichiers demand\u00e9s -config.group.tip.paths = Vous pouvez t\u00e9l\u00e9charger ces fichiers depuis le site web d'Adobe -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html -config.group.linkText.paths = [visiter] - -config.name.playerLocation = 1) Chemin du lecteur Flash -config.description.playerLocation = Location du lecteur autonome de fichier ex\u00e9cutable Flash. Used for Run action. - -config.name.playerDebugLocation = 2) Chemin du d\u00e9boggeur du lecteur Flash -config.description.playerDebugLocation = Location du d\u00e9boggueur autonome du lecteur Flash. Utilis\u00e9 \u00e0 des fins de d\u00e9bogguage. - -config.name.playerLibLocation = 3) Chemin du fichier PlayerGlobal (.swc) -config.description.playerLibLocation = Location de la librairie du lecteur Flash playerglobal.swc. Utilis\u00e9 principalement pour la d\u00e9compilation du code AS3. - -config.name.debugHalt = Stoppe l'ex\u00e9cution lorsque le d\u00e9bogguage d\u00e9marre -config.description.debugHalt = G\u00e9n\u00e8re une pause du SWF lorsque le d\u00e9bogguage commence. - -config.name.gui.avm2.splitPane.vars.dividerLocationPercent = (Interne) Localisation du menu de debug -config.description.gui.avm2.splitPane.vars.dividerLocationPercent = - -tip = Tip:\u0020 - -config.name.gui.action.splitPane.vars.dividerLocationPercent = (Interne) Location du menu de debug AS1/2 -config.description.gui.action.splitPane.vars.dividerLocationPercent = - -config.name.setMovieDelay = D\u00e9lais en millisecondes avant de changer le SWF dans le lecteur externe -config.description.setMovieDelay = Ce n'est pas recommand\u00e9 de mettre une valeur en dessous de 1000 ms - -config.name.warning.svgImport = Alerte lors d'un import SVG -config.description.warning.svgImport = - -config.name.shapeImport.useNonSmoothedFill = Utiliser un remplissage non liss\u00e9 lorsque forme est remplac\u00e9e par une image -config.description.shapeImport.useNonSmoothedFill = - -config.name.internalFlashViewer.execute.as12 = Utiliser le lecteur flash propre \u00e0 AS1/2 (Exp\u00e9rimental) -config.description.internalFlashViewer.execute.as12 = Tente d'ex\u00e9cuter le code ActionScript 1/2 dans le lecteur externe FFDec - -config.name.warning.hexViewNotUpToDate = Afficher une vue, pas en temps r\u00e9el, des alertes en hexad\u00e9cimal -config.description.warning.hexViewNotUpToDate = - -config.name.displayDupInstructions = Afficher les instructions \u00a7\u00a7dup -config.description.displayDupInstructions = Affiche les instructions \u00a7\u00a7dup dans le code. Sans eux, le code peut \u00eatre compil\u00e9 facilement mais pourrait entra\u00eener un effet de doublon. - -config.name.useRegExprLiteral = D\u00e9compiler litt\u00e9ralement RegExp en tant que /pattern/mod. -config.description.useRegExprLiteral = Utilise la syntaxe /pattern/mod lors de la d\u00e9compilations d'expressions r\u00e9guli\u00c8res. Les nouveaux RegExp("pat","mod") sont utilis\u00e9s diff\u00e9remment - -config.name.handleSkinPartsAutomatically = Manipuler automatiquement les m\u00e9tadonn\u00e9es [SkinPart] -config.description.handleSkinPartsAutomatically = D\u00e9compile et \u00e9dite directement les m\u00e9tadonn\u00e9es [SkinPart]. Lorsque cette option est d\u00e9sactiv\u00e9e, les attributs et la m\u00e9thode de lecture des _skinParts sont modifiables manuellement. - -config.name.simplifyExpressions = Simplifier les expressions -config.description.simplifyExpressions = \u00c9value et simplifie les expressions pour rendre le code plus lisible - -config.name.resetLetterSpacingOnTextImport = R\u00e9nitialiser l'espace entre les lettres lors de l'import de texte -config.description.resetLetterSpacingOnTextImport = Adapte les caract\u00e9res de polices cyrilliques, parce qu'elles sont plus larges +# Copyright (C) 2010-2016 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 . + +advancedSettings.dialog.title = Param\u00e8tres avanc\u00e9s +advancedSettings.restartConfirmation = Vous devez red\u00e9marrer le programme pour que les changements prennent effet. Red\u00e9marrer maintenant ? +advancedSettings.columns.name = Nom +advancedSettings.columns.value = Valeur +advancedSettings.columns.description = Description +default = D\u00e9faut + +config.group.name.export = Export +config.group.description.export = Configuration de l'export + +config.group.name.script = Scripts +config.group.description.script = D\u00e9compilation ActionScript connexes + +config.group.name.update = Mises \u00e0 jour +config.group.description.update = Recherche de mises \u00e0 jour + +config.group.name.format = Mise en forme +config.group.description.format = Mise en forme du code ActionScript + +config.group.name.limit = Limites +config.group.description.limit = Limites de la d\u00e9compilation du code crypt\u00e9, etc. + +config.group.name.ui = Interface +config.group.description.ui = Configuration de l'interface utilisateur + +config.group.name.debug = D\u00e9boguage +config.group.description.debug = Param\u00e8tres de d\u00e9boguage + +config.group.name.display = Affichage +config.group.description.display = Affichage des objets Flash, etc. + +config.group.name.decompilation = D\u00e9compilation +config.group.description.decompilation = Fonctions relatives \u00e0 la d\u00e9compilation + +config.group.name.other = Autres +config.group.description.other = Autres configurations + +config.name.openMultipleFiles = Ouvrir plusieurs fichiers +config.description.openMultipleFiles = Autoriser l'ouverture de plusieurs fichiers dans une seule fen\u00eatre + +config.name.decompile = Afficher les sources ActionScript +config.description.decompile = Vous pouvez d\u00e9sactiver la d\u00e9compilation ActionScript, seul le code Assembleur sera affich\u00e9 + +config.name.dumpView = Donn\u00e9es brutes +config.description.dumpView = Voir les donn\u00e9es brutes + +config.name.useHexColorFormat = Format couleur hexad\u00e9cimal +config.description.useHexColorFormat = Afficher les couleurs au format hexad\u00e9cimal + +config.name.parallelSpeedUp = Acc\u00e9l\u00e9ration parall\u00e8le +config.description.parallelSpeedUp = Le parall\u00e9lisme augmente la vitesse de d\u00e9compilation + +config.name.parallelSpeedUpThreadCount = Nombre de canaux +config.description.parallelSpeedUpThreadCount = Nombre de canaux \u00e0 utiliser pour l'acc\u00e9l\u00e9ration parall\u00e8le + +config.name.autoDeobfuscate = D\u00e9sobfuscation automatique +config.description.autoDeobfuscate = D\u00e9marer la d\u00e9sobfuscation sur l'ensemble des fichiers avant la d\u00e9compilation ActionScript + +config.name.cacheOnDisk = Utilisation de la m\u00e9moire cache du disque +config.description.cacheOnDisk = Des parties sont d\u00e9j\u00e0 d\u00e9compil\u00e9s sur le disque dur \u00e0 la place de la m\u00e9moire + +config.name.internalFlashViewer = Utiliser la visionneuse Flash int\u00e9gr\u00e9e +config.description.internalFlashViewer = Utililser la visionneuse Flash JPEXS au lieu de la visionneuse Flash standard pour afficher les \u00e9l\u00e9ments + +config.name.gotoMainClassOnStartup = Aller \u00e0 la classe d'initialisation (AS3) +config.description.gotoMainClassOnStartup = Aller dans la classe de document \u00e0 l'ouverture du fichier AS3 + +config.name.autoRenameIdentifiers = Renommage automatique des identifiants +config.description.autoRenameIdentifiers = Renomme automatiquement les identifiants invalides en chargeant le fichier SWF + +config.name.offeredAssociation = (Interne) Association de fichiers SWF d\u00e9j\u00e0 ouvert +config.description.offeredAssociation = La boite de dialogue d'association de fichiers est d\u00e9j\u00e0 ouverte + +config.name.decimalAddress = Utiliser l'adressage d\u00e9cimale +config.description.decimalAddress = Utiliser l'adressage d\u00e9cimale au lieu de l'adressage hexad\u00e9cimal + +config.name.showAllAddresses = Afficher toutes les adresses +config.description.showAllAddresses = Afficher toutes les instructions ActionScript \u00e0 toutes les adresses + +config.name.useFrameCache = Utiliser la m\u00e9moire cache des images +config.description.useFrameCache = Mettre en cache les images avant le nouveau rendu + +config.name.useRibbonInterface = Interface Ruban +config.description.useRibbonInterface = D\u00e9cocher pour utiliser l'interface classique sans le menu-ruban + +config.name.openFolderAfterFlaExport = Ouvrir le dossier apr\u00e8s l'export FLA +config.description.openFolderAfterFlaExport = Afficher le dossier apr\u00e8s l'export de fichiers FLA + +config.name.useDetailedLogging = Journal d\u00e9taill\u00e9 +config.description.useDetailedLogging = Les messages d'erreurs et les informations de d\u00e9bogages sont renseign\u00e9s dans le journal d\u00e9taill\u00e9 + +config.name.debugMode = Mode +config.description.debugMode = Mode d\u00e9boggage. Affiche le menu de d\u00e9boggage. + +config.name.resolveConstants = R\u00e9soudre les constantes dans le code assembleur en AS1/2 +config.description.resolveConstants = Arr\u00eate d'afficher 'constantxx' au lieu des vraies valeurs dans la fen\u00eatre assembleur + +config.name.sublimiter = Limites du sous-programme +config.description.sublimiter = Limites du sous-programme pour du code crypt\u00e9 + +config.name.exportTimeout = Limite de temps \u00e9coul\u00e9e \u00e0 l'exportation (secondes) +config.description.exportTimeout = Le d\u00e9compileur arr\u00eatera l'exportation d\u00e8s que cette valeur sera atteinte + +config.name.decompilationTimeoutFile = Limite de temps pour d\u00e9compiler un fichier (secondes) +config.description.decompilationTimeoutFile = Le d\u00e9compileur arr\u00eatera la d\u00e9compilation ActionScript d\u00e8s que cette valeur sera atteinte pour un fichier + +config.name.paramNamesEnable = Activer les noms de param\u00e8tres en AS3 +config.description.paramNamesEnable = L'utilisation des noms de param\u00e8tres en d\u00e9compilant peut causer des probl\u00e8mes parce que le programme officiel CS 5.5 pr\u00e9f\u00e8re Flash ins\u00e8rer des mauvais indices de noms de param\u00e9tres + +config.name.displayFileName = Afficher le nom SWF dans la barre de titre +config.description.displayFileName = Afficher l'URL et le nom de fichier dans la barre de titre (Vous pouvez faire des captures d'\u00e9cran) + +config.name.debugCopy = Recompilation en mode debug +config.description.debugCopy = Tenter de compiler le fichier SWF \u00e0 nouveau apr\u00e8s son ouverture pour s'assurer qu'il produise le m\u00eame code binaire. \u00c0 utiliser uniquement pour le d\u00e9boguage ! + +config.name.dumpTags = Afficher les \u00e9tiquettes dans la console +config.description.dumpTags = Afficher les \u00e9tiquettes dans la console en jouant le fichier SWF + +config.name.decompilationTimeoutSingleMethod = AS3: Single method decompilation timeout (secondes) +config.description.decompilationTimeoutSingleMethod = Le d\u00e9compilateur arr\u00eatera la d\u00e9compilation du code ActionScript d\u00e8 que ce temps sera atteint dans la m\u00e9thode + +config.name.lastRenameType = (Interne) Dernier type renomm\u00e9 +config.description.lastRenameType = Dernier type d'identificateur renomm\u00e9 utilis\u00e9 + +config.name.lastSaveDir = (Interne) Dernier dossier de sauvegarde +config.description.lastSaveDir = Dernier dossier de sauvegarde utilis\u00e9 + +config.name.lastOpenDir = (Interne) Dernier dossier ouvert +config.description.lastOpenDir = Dernier dossier ouvert utilis\u00e9 + +config.name.lastExportDir = (Interne) Dernier dossier d'export +config.description.lastExportDir = Dernier dossier d'export utilis\u00e9 + +config.name.locale = Langues +config.description.locale = Param\u00e8tres r\u00e9gionaux + +config.name.registerNameFormat = Format du registre des variables +config.description.registerNameFormat = Format du registre local des noms de variables. Utilise %d pour le registre num\u00e9rique. + +config.name.maxRecentFileCount = Nb. max. de fichiers r\u00e9cents +config.description.maxRecentFileCount = Nombre maximal de fichiers r\u00e9cents + +config.name.recentFiles = (Interne) Fichiers r\u00e9cents +config.description.recentFiles = Fichiers r\u00e9cemment ouverts + +config.name.fontPairingMap = (Interne) Couplage des polices pour l'importation +config.description.fontPairingMap = Couplage des polices pour l'importation des nouveaux caract\u00e8res + +config.name.lastUpdatesCheckDate = (Interne) Date de derni\u00e8re mises \u00e0 jour +config.description.lastUpdatesCheckDate = Date de la derni\u00e8re v\u00e9rification des mises \u00e0 jour sur le serveur + +config.name.gui.window.width = (Interne) Derni\u00e8re largeur de fen\u00eatre +config.description.gui.window.width = Derni\u00e8re valeur enregistr\u00e9e de la largeur de la fen\u00eatre + +config.name.gui.window.height = (Interne) Derni\u00e8re hauteur de fen\u00eatre +config.description.gui.window.height = Derni\u00e8re valeur enregistr\u00e9e de la hauteur de la fen\u00eatre + +config.name.gui.window.maximized.horizontal = (Interne) Agrandissement horizontal de la fen\u00eatre +config.description.gui.window.maximized.horizontal = Dernier \u00e9tat de la fen\u00eatre - Agrandissement horizontal + +config.name.gui.window.maximized.vertical = (Interne) Agrandissement vertical de la fen\u00eatre +config.description.gui.window.maximized.vertical = Derni\u00e8r \u00e9tat de la fen\u00eatre - Agrandissement vertical + +config.name.gui.avm2.splitPane.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur AS3 +config.description.gui.avm2.splitPane.dividerLocationPercent = + +config.name.gui.actionSplitPane.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur AS1/2 +config.description.gui.actionSplitPane.dividerLocationPercent = + +config.name.gui.previewSplitPane.dividerLocationPercent = (Interne) Aper\u00e7u de l'emplacement du s\u00e9parateur +config.description.gui.previewSplitPane.dividerLocationPercent = + +config.name.gui.splitPane1.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur 1 +config.description.gui.splitPane1.dividerLocationPercent = + +config.name.gui.splitPane2.dividerLocationPercent = (Interne) Emplacement du s\u00e9parateur 2 +config.description.gui.splitPane2.dividerLocationPercent = + +config.name.saveAsExeScaleMode = Enregistrer en tant qu'\u00e9chelle de mode EXE +config.description.saveAsExeScaleMode = Mode de mise \u00e0 l'\u00e9chelle pour un export EXE + +config.name.syntaxHighlightLimit = Nb max de caract\u00e8res surlign\u00e9s +config.description.syntaxHighlightLimit = Nombre maximal de caract\u00e8res pour surligner + +config.name.guiFontPreviewSampleText = (Internal) Dernier aper\u00e7u texte de la police de caract\u00e8res +config.description.guiFontPreviewSampleText = Dernier aper\u00e7u texte de la police de caract\u00e8res + +config.name.gui.fontPreviewWindow.width = (Interne) Derni\u00e8re largeur de fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res +config.description.gui.fontPreviewWindow.width = + +config.name.gui.fontPreviewWindow.height = (Interne) Derni\u00e8re hauteur de fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res +config.description.gui.fontPreviewWindow.height = + +config.name.gui.fontPreviewWindow.posX = (Interne) Derni\u00e8re position X de la fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res +config.description.gui.fontPreviewWindow.posX = Il s'agit de la position de la fen\u00eatre sur l'axe des abscisses + +config.name.gui.fontPreviewWindow.posY = (Interne) Derni\u00e8re position Y de la fen\u00eatre d'aper\u00e7u des polices de caract\u00e8res +config.description.gui.fontPreviewWindow.posY = Il s'agit de la position de la fen\u00eatre sur l'axe des ordonn\u00e9es + +config.name.formatting.indent.size = Nb de caract\u00e8res par indentation +config.description.formatting.indent.size = Nombre d'espaces (ou tabulations) pour une indentation + +config.name.formatting.indent.useTabs = Indentation +config.description.formatting.indent.useTabs = Utiliser les tabulations au lieu d'espaces pour l'indentation + +config.name.beginBlockOnNewLine = Accolades pour les nouvelle lignes +config.description.beginBlockOnNewLine = Commencer les blocs avec des accolades sur les nouvelles lignes + +config.name.check.updates.delay = Intervale de v\u00e9rification des mises \u00e0 jour +config.description.check.updates.delay = Intervale minimum entre chaque v\u00e9rification automatique des mises \u00e0 jour au d\u00e8marrage de l'application + +config.name.check.updates.stable = V\u00e9rification des versions stables +config.description.check.updates.stable = V\u00e9rification des mises \u00e0 jour des versions stables + +config.name.check.updates.nightly = V\u00e9rification des versions de tests +config.description.check.updates.nightly = V\u00e9rification des mises \u00e0 jour des versions de tests + +config.name.check.updates.enabled = V\u00e9rification automatique activ\u00e9e +config.description.check.updates.enabled = V\u00e9rification automatique des mises \u00e0 jour lorsque au d\u00e9marrage de l'application + +config.name.export.formats = (Interne) Formats d'export +config.description.export.formats = Derniers formats d'export utilis\u00e8 + +config.name.textExportSingleFile = Export de textes dans un seul fichier +config.description.textExportSingleFile = Exportation de textes dans un seul fichier plut\u00f4t que dans plusieurs fichiers + +config.name.textExportSingleFileSeparator = S\u00e9parateur de textes dans un fichier d'export de textes +config.description.textExportSingleFileSeparator = Texte \u00e0 ins\u00e9rer entre chaque texte dans un fichier d'export de textes + +config.name.textExportSingleFileRecordSeparator = S\u00e9parateur d'enregistrement dans un fichier d'export de textes +config.description.textExportSingleFileRecordSeparator = Texte \u00e0 ins\u00e9rer entre chaque enregistrement dans un fichier d'export de textes + +config.name.warning.experimental.as12edit = Alerte lors d'\u00e9dition en AS1/2 +config.description.warning.experimental.as12edit = Afficher l'avertissement lors de l'\u00e9dition exp\u00e9rimentale des scripts AS1/2 + +config.name.warning.experimental.as3edit = Alerte lors d'\u00e9dition en AS3 +config.description.warning.experimental.as3edit = Afficher l'avertissement lors de l'\u00e9dition exp\u00e9rimentale des scripts AS3 + +config.name.packJavaScripts = Paquet JavaScripts +config.description.packJavaScripts = D\u00e9marrer le paquet JavaScript sur des scripts cr\u00e9\u00e9s lors de l'exportation de dessins + +config.name.textExportExportFontFace = Utiliser le style de police de caract\u00e8res dans l'export SVG +config.description.textExportExportFontFace = Embarquer le style de police de caract\u00e8res dans l'export SVG au lieu des formes + +config.name.lzmaFastBytes = LZMA fast bytes (valeurs permises : 5-255) +config.description.lzmaFastBytes = Param\u00e8tre vitesse des octets de l'encodeur LZMA + +config.name.pluginPath = Chemin du Plugin +config.description.pluginPath = - + +config.name.showMethodBodyId = Afficher l'identifiant dans le corps de texte +config.description.showMethodBodyId = Afficher l'identifiant dans le corps de la m\u00e9thode lors de l'importation en ligne de commande + +config.name.export.zoom = (Interne) Export du zoom +config.description.export.zoom = Dernier export de zoom utilis\u00e9 + +config.name.debuggerPort = Port de d\u00e9boggage +config.description.debuggerPort = Port utilis\u00e9 pour le d\u00e9boggage du socket + +config.name.displayDebuggerInfo = (Interne) Afficher les informations du d\u00e9boggueur +config.description.displayDebuggerInfo = Afficher les informations concernant le d\u00e9boggueur avant sa mise en route + +config.name.randomDebuggerPackage = Utiliser un nom de paquet al\u00e9atoire pour le d\u00e9boggueur +config.description.randomDebuggerPackage = Renomme le paquet de d\u00e9boggueur en une chaine de texte al\u00e9atoire lequel sera plus difficile \u00e0 d\u00e9tecter par ActionScript + +config.name.lastDebuggerReplaceFunction = (Interne) Dernier remplacement de traces s\u00e9lectionn\u00e9 +config.description.lastDebuggerReplaceFunction = Function name which was last selected in replace trace function with debugger + +config.name.getLocalNamesFromDebugInfo = AS3: R\u00e9cup\u00e9rer les noms de variables \u00e0 partir des informations de d\u00e9boggage +config.description.getLocalNamesFromDebugInfo = Si les informations de d\u00e9boggage sont pr\u00e9sents, alors renommer les variables locales de types _loc_x_ en utilisant leurs noms r\u00e9els. Peut \u00eatre d\u00e9sactiv\u00e9 car certains obfuscateurs utilisent ici des noms de variables invalides + +config.name.tagTreeShowEmptyFolders = Afficher les dossiers vides +config.description.tagTreeShowEmptyFolders = Afficher les dossiers vides dans l'arborescence des balises + +config.name.autoLoadEmbeddedSwfs = Chargement automatique des SWFs incorpor\u00e9s +config.description.autoLoadEmbeddedSwfs = Charger automatiquement les SWF embarqu\u00e9s \u00e0 partir des balises DefineBinaryData + +config.name.overrideTextExportFileName = Remplacer le nom de fichier lors de l'export de texte +config.description.overrideTextExportFileName = Vous pouvez personaliser le nom de fichier du texte export\u00e9. Utilisez {filename} dans l'emplacement d\u00e9di\u00e9 pour utiliser le nom de fichier du SWF courant. + +config.name.showOldTextDuringTextEditing = Afficher le texte d'origine lors de l'\u00e9dition +config.description.showOldTextDuringTextEditing = Afficher l'original des textes des balises en couleur grise dans l'aper\u00e7u. + +config.group.name.import = Import +config.group.description.import = Configuration des imports + +config.name.textImportResizeTextBoundsMode = Limites du texte en mode redimensionnement +config.description.textImportResizeTextBoundsMode = Limites du texte en mode redimensionnement apr\u00e8s son \u00e9dition. + +config.name.showCloseConfirmation = Confimation de fermeture +config.description.showCloseConfirmation = Affiche la confirmation de fermeture du fichier SWF lorsque les fichiers sont modifi\u00e9s + +config.name.showCodeSavedMessage = Afficher un message d'avertissement lors de l'enregistrement du code +config.description.showCodeSavedMessage = Afficher un message d'avertissement lors de l'enregistrement du code + +config.description.showTraitSavedMessage = Afficher un message d'avertissement lors de l'enregistrement d'une caract\u00e9ristique +config.name.showTraitSavedMessage = Afficher un message lors de l'enregistrement de la caract\u00e9ristique + +config.name.updateProxyAddress = Adresse du Proxy http pour v\u00e9rifier les mises \u00e0 jour +config.description.updateProxyAddress = Adresse du Proxy http pour v\u00e9rifier les mises \u00e0 jour. Format : exemple.com:8080 + +config.name.editorMode = Mode \u00e9diteur +config.description.editorMode = Rend \u00e9ditable les zones de texte automatiquement lorsque vous s\u00e9lectionnez un texte ou un script + +config.name.autoSaveTagModifications = Enregistrement auto des \u00e9tiquettes modifi\u00e9es +config.description.autoSaveTagModifications = Enregistre les changements lorsque vous s\u00e9lectionnez une autre \u00e9tiquette dans l'arborescence + +config.name.saveSessionOnExit = Enregistrer la session en quittant +config.description.saveSessionOnExit = Enregistre la session courante et la r\u00e9tablira au red\u00e9marrage de FFDec (ne fonctionne qu'avec des fichiers physiquement pr\u00e9sents sur disque) + +config.name._showDebugMenu = Affiche le menu de d\u00e9boggage FFDec +config.description._showDebugMenu = Affiche le menu de d\u00e9boggage dans le ruban lorsque le d\u00e9compileur est en train de d\u00e9bogguer. + +config.name.allowOnlyOneInstance = Une seule instance FFDec (OS Windows uniquement) +config.description.allowOnlyOneInstance = FFDec peut d\u00e9marrer en une seule fois, tous les fichiers ouverts seront ajout\u00e9s dans une unique fen\u00eatre. Ne fonctionne que sous Windows uniquement. + +config.name.scriptExportSingleFile = Export des scripts dans un seul fichier +config.description.scriptExportSingleFile = Exportation des scripts dans un seul fichier au lieu de cr\u00e9er plusieurs fichiers + +config.name.setFFDecVersionInExportedFont = Indiquer la version de FFDec dans la police de caract\u00e8res export\u00e9es +config.description.setFFDecVersionInExportedFont = Lorsque cette option est decoch\u00e9es, FFDec n'ajoutera son num\u00e9ro de version dans la police de caract\u00e8res export\u00e9es. + +config.name.gui.skin = Personnalisation de l'interface utilisateur +config.description.gui.skin = Personnalisation de l'interface utilisateur + +config.name.lastSessionFiles = Fichiers de la derni\u00e8re session +config.description.lastSessionFiles = Contient les fichiers ouverts lors de la derni\u00e8re session + +config.name.lastSessionSelection = S\u00e9lection de la derni\u00e8re session +config.description.lastSessionSelection = Contient la s\u00e9lection lors de la derni\u00e8re session + +config.name.loopMedia = Rejouer les sons et les sprites +config.description.loopMedia = Rejoue automatiquement les sons et les sprites + +config.name.gui.timeLineSplitPane.dividerLocationPercent = (Internal) Position du s\u00e9parateur de la fen\u00eatre du chronogramme +config.description.gui.timeLineSplitPane.dividerLocationPercent = + +config.name.cacheImages = Images en m\u00e9moire cache +config.description.cacheImages = Met en m\u00e9moire cache les images-objets d\u00e9cod\u00e9es + +config.name.swfSpecificConfigs = Configuration avanc\u00e9es SWF +config.description.swfSpecificConfigs = Contient les configurations avanc\u00e9es SWF + +config.name.exeExportMode = Mode export EXE +config.description.exeExportMode = Mode export EXE + +config.name.ignoreCLikePackages = Ignorer les paquets FlashCC / Alchemy ou similaires +config.description.ignoreCLikePackages = Les paquets FlashCC/Alchemy ne sont pas d\u00e9compilables correctement. Vous pouvez les d\u00e9sactiver pour gagner en vitesse de d\u00e9compilation avec les autres paquets. + +config.name.overwriteExistingFiles = \u00c9craser les fichiers existants +config.description.overwriteExistingFiles = \u00c9craser les fichiers existants lors de l'export. Ne fonctionne que pour les scripts AS2/3. + +config.name.smartNumberFormatting = Utiliser le formattage num\u00e9rique intelligent +config.description.smartNumberFormatting = Formattage num\u00e9riques sp\u00e9ciaux (par exemple : les couleurs et les temps) + +config.name.enableScriptInitializerDisplay = Affiche l'initialisateur de script +config.description.enableScriptInitializerDisplay = Active l'affichage et l'\u00e9ditiion de l'initialisateur de script. Ce param\u00e8tre ajoute une nouvelle ligne en \u00e9vidence dans chaque classe. + +config.name.autoOpenLoadedSWFs = Ouvre les SWF charg\u00e9s lors de l'ex\u00e9cution (Lecteur externe = Windows seulement) +config.description.autoOpenLoadedSWFs = Ouvre automatiquement tous les SWF charg\u00e9s par la classe de chargement AS3 en lisant les SWF jou\u00e9s dans le lecteur externe FFDec. Cette option ne fonctionne que sous Windows. + +config.name.lastSessionFileTitles = Les titres de la derni\u00c8re session +config.description.lastSessionFileTitles = Comprend les titres des fichiers ouverts lors de la derni\u00c8re session (par exemple depuis une URL, etc.) + +config.group.name.paths = Chemins +config.group.description.paths = Location des fichiers demand\u00e9s +config.group.tip.paths = Vous pouvez t\u00e9l\u00e9charger ces fichiers depuis le site web d'Adobe +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html +config.group.linkText.paths = [visiter] + +config.name.playerLocation = 1) Chemin du lecteur Flash +config.description.playerLocation = Location du lecteur autonome de fichier ex\u00e9cutable Flash. Used for Run action. + +config.name.playerDebugLocation = 2) Chemin du d\u00e9boggeur du lecteur Flash +config.description.playerDebugLocation = Location du d\u00e9boggueur autonome du lecteur Flash. Utilis\u00e9 \u00e0 des fins de d\u00e9bogguage. + +config.name.playerLibLocation = 3) Chemin du fichier PlayerGlobal (.swc) +config.description.playerLibLocation = Location de la librairie du lecteur Flash playerglobal.swc. Utilis\u00e9 principalement pour la d\u00e9compilation du code AS3. + +config.name.debugHalt = Stoppe l'ex\u00e9cution lorsque le d\u00e9bogguage d\u00e9marre +config.description.debugHalt = G\u00e9n\u00e8re une pause du SWF lorsque le d\u00e9bogguage commence. + +config.name.gui.avm2.splitPane.vars.dividerLocationPercent = (Interne) Localisation du menu de debug +config.description.gui.avm2.splitPane.vars.dividerLocationPercent = + +tip = Tip:\u0020 + +config.name.gui.action.splitPane.vars.dividerLocationPercent = (Interne) Location du menu de debug AS1/2 +config.description.gui.action.splitPane.vars.dividerLocationPercent = + +config.name.setMovieDelay = D\u00e9lais en millisecondes avant de changer le SWF dans le lecteur externe +config.description.setMovieDelay = Ce n'est pas recommand\u00e9 de mettre une valeur en dessous de 1000 ms + +config.name.warning.svgImport = Alerte lors d'un import SVG +config.description.warning.svgImport = + +config.name.shapeImport.useNonSmoothedFill = Utiliser un remplissage non liss\u00e9 lorsque forme est remplac\u00e9e par une image +config.description.shapeImport.useNonSmoothedFill = + +config.name.internalFlashViewer.execute.as12 = Utiliser le lecteur flash propre \u00e0 AS1/2 (Exp\u00e9rimental) +config.description.internalFlashViewer.execute.as12 = Tente d'ex\u00e9cuter le code ActionScript 1/2 dans le lecteur externe FFDec + +config.name.warning.hexViewNotUpToDate = Afficher une vue, pas en temps r\u00e9el, des alertes en hexad\u00e9cimal +config.description.warning.hexViewNotUpToDate = + +config.name.displayDupInstructions = Afficher les instructions \u00a7\u00a7dup +config.description.displayDupInstructions = Affiche les instructions \u00a7\u00a7dup dans le code. Sans eux, le code peut \u00eatre compil\u00e9 facilement mais pourrait entra\u00eener un effet de doublon. + +config.name.useRegExprLiteral = D\u00e9compiler litt\u00e9ralement RegExp en tant que /pattern/mod. +config.description.useRegExprLiteral = Utilise la syntaxe /pattern/mod lors de la d\u00e9compilations d'expressions r\u00e9guli\u00c8res. Les nouveaux RegExp("pat","mod") sont utilis\u00e9s diff\u00e9remment + +config.name.handleSkinPartsAutomatically = Manipuler automatiquement les m\u00e9tadonn\u00e9es [SkinPart] +config.description.handleSkinPartsAutomatically = D\u00e9compile et \u00e9dite directement les m\u00e9tadonn\u00e9es [SkinPart]. Lorsque cette option est d\u00e9sactiv\u00e9e, les attributs et la m\u00e9thode de lecture des _skinParts sont modifiables manuellement. + +config.name.simplifyExpressions = Simplifier les expressions +config.description.simplifyExpressions = \u00c9value et simplifie les expressions pour rendre le code plus lisible + +config.name.resetLetterSpacingOnTextImport = R\u00e9nitialiser l'espace entre les lettres lors de l'import de texte +config.description.resetLetterSpacingOnTextImport = Adapte les caract\u00e9res de polices cyrilliques, parce qu'elles sont plus larges diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties index 6678009cf..7dfb6ca68 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties @@ -1,434 +1,434 @@ -# Copyright (C) 2010-2016 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 . - -advancedSettings.dialog.title = Impostazioni avanzate -advancedSettings.restartConfirmation = Occorre riavviare il programma perch\u00e9 alcune modifiche abbiano effetto. Riavviare ora? -advancedSettings.columns.name = Nome -advancedSettings.columns.value = Valore -advancedSettings.columns.description = Descrizione -default = predefinito - -config.group.name.export = Esportazione -config.group.description.export = Impostazioni di esportazione - -config.group.name.script = Script -config.group.description.script = Relativi alla decompilazione ActionScript - -config.group.name.update = Aggiornamenti -config.group.description.update = Controllo aggiornamenti - -config.group.name.format = Formattazione -config.group.description.format = Formattazione del codice ActionScript - -config.group.name.limit = Limiti -config.group.description.limit = Limiti nella decompilazione di codice offuscato, ecc. - -config.group.name.ui = Interfaccia -config.group.description.ui = Configurazione interfaccia utente - -config.group.name.debug = Debug -config.group.description.debug = Opzioni di debug - -config.group.name.display = Visualizzazione -config.group.description.display = Visualizzazione oggetti Flash, ecc. - -config.group.name.decompilation = Decompilazione -config.group.description.decompilation = Funzioni globali legate alla decompilazione - -config.group.name.other = Varie -config.group.description.other = Altre impostazioni - -config.name.openMultipleFiles = Apertura file multipli -config.description.openMultipleFiles = Permette di aprire pi\u00f9 file contemporaneamente nella stessa finestra - -config.name.decompile = Visualizza sorgenti ActionScript -config.description.decompile = Disattivando la decompilazione AS viene visualizzato solo il P-code - -config.name.dumpView = Visualizza hex dump -config.description.dumpView = Mostra listato esadecimale dei byte nel file - -config.name.useHexColorFormat = Formato esadecimale per i colori -config.description.useHexColorFormat = Presenta i colori in formato esadecimale - -config.name.parallelSpeedUp = Elaborazione in parallelo -config.description.parallelSpeedUp = Il parallelismo pu\u00f2 ridurre i tempi di decompilazione - -config.name.parallelSpeedUpThreadCount = Numero di thread -config.description.parallelSpeedUpThreadCount = Numero di thread in esecuzione parallela - -config.name.autoDeobfuscate = Deoffuscamento automatico -config.description.autoDeobfuscate = Tenta il deoffuscamento su ogni file prima della decompilazione ActionScript - -config.name.cacheOnDisk = Utilizza cache su disco -config.description.cacheOnDisk = Memorizza le parti decompilate su disco anzich\u00e9 in memoria - -config.name.internalFlashViewer = Utilizza visualizzatore Flash incorporato -config.description.internalFlashViewer = Utilizza JPEXS Flash Viewer invece del Flash Player standard per visualizzare le parti in Flash - -config.name.gotoMainClassOnStartup = Vai alla classe principale all'avvio (AS3) -config.description.gotoMainClassOnStartup = Passa alla classe documento del file AS3 all'apertura del SWF - -config.name.autoRenameIdentifiers = Autorinomina degli identificatori -config.description.autoRenameIdentifiers = Rinomina identificatori non validi al caricamento del SWF - -config.name.offeredAssociation = (Interno) Associazione con file SWF visualizzato -config.description.offeredAssociation = Finestra di dialogo gi\u00e0 visualizzata - -config.name.decimalAddress = Mostra indirizzi in decimale -config.description.decimalAddress = Usa indirizzi in base 10 (dec) invece che in base 16 (hex) - -config.name.showAllAddresses = Mostra tutti gli indirizzi -config.description.showAllAddresses = Visualizza tutti gli indirizzi di istruzioni ActionScript - -config.name.useFrameCache = Usa frame cache -config.description.useFrameCache = Fare caching dei frame prima di ridisegnarli - -config.name.useRibbonInterface = Interfaccia con menu multifunzione (Ribbon) -config.description.useRibbonInterface = Deselezionare per usare la GUI classica - -config.name.openFolderAfterFlaExport = Apri cartella dopo l'esportazione FLA -config.description.openFolderAfterFlaExport = Visualizza cartella di output dopo l'esportazione FLA - -config.name.useDetailedLogging = Log dettagliato -config.description.useDetailedLogging = Log dettagliato dei messaggi di errore e di informazioni a scopo diagnostico - -config.name._debugMode = FFDec in modalit\u00e0 diagnostica -config.description._debugMode = Modalit\u00e0 diagnostica per FFDec. Attiva il menu Debug. Non riguarda la funzionalita di debug - -config.name.resolveConstants = Risolvere le costanti nel P-code AS1/2 -config.description.resolveConstants = Disattivare per mostrare 'constantxx' invece dei valori effettivi nella vista P-code - -config.name.sublimiter = Limite su subroutine -config.description.sublimiter = Limite su subroutine per codice offuscato. - -config.name.exportTimeout = Tempo massimo di esportazione (secondi) -config.description.exportTimeout = Il decompilatore interromper\u00e0 l'esportazione dopo questo tempo - -config.name.decompilationTimeoutFile = Tempo massimo di decompilazione per file (secondi) -config.description.decompilationTimeoutFile = Il decompilatore interromper\u00e0 la decompilazione ActionScript dopo questo tempo per un singolo file - -config.name.paramNamesEnable = Abilita nomi di parametro in AS3 -config.description.paramNamesEnable = Utilizzare i nomi di parametro nella decompilazione pu\u00f2 causare problemi poich\u00e9 programmi ufficiali come Flash CS 5.5 generano indici di nome errati - -config.name.displayFileName = Mostra nome SWF nel titolo della finestra -config.description.displayFileName = Visualizza nome/URL del file SWF nel titolo (\u00e8 possibile fare screenshot) - -config.name._debugCopy = Diagnostica ricompilazione FFDec -config.description._debugCopy = Prova a ricompilare il file SWF subito dopo l'apertura per garantire che generi lo stesso codice binario. Da usare SOLO per la diagnostica di FFDec! - -config.name.dumpTags = Dump dei tag su console -config.description.dumpTags = Scrive i tag su console alla lettura del file SWF - -config.name.decompilationTimeoutSingleMethod = AS3: Tempo massimo di decompilazione per singolo metodo (secondi) -config.description.decompilationTimeoutSingleMethod = Il decompilatore interromper\u00e0 la decompilazione ActionScript dopo questo tempo per un singolo metodo - -config.name.lastRenameType = (Interno) Ultimo tipo di rinomina -config.description.lastRenameType = Ultimo tipo di rinomina identificatore utilizzato - -config.name.lastSaveDir = (Interno) Ultima cartella di salvataggio -config.description.lastSaveDir = Ultima directory di salvataggio usata - -config.name.lastOpenDir = (Interno) Ultima cartella aperta -config.description.lastOpenDir = Ultima directory aperta utilizzata - -config.name.lastExportDir = (Interno) Ultima cartella di esportazione -config.description.lastExportDir = Ultima directory di esportazione usata - -config.name.locale = Lingua -config.description.locale = Identificatore per la localizzazione - -config.name.registerNameFormat = Formato delle variabili di registro -config.description.registerNameFormat = Formato nome delle variabili registro locali. Utilizzare %d per specificare il numero di registro. - -config.name.maxRecentFileCount = Limite elenco file recenti -config.description.maxRecentFileCount = Numero massimo di file recenti - -config.name.recentFiles = (Interno) File recenti -config.description.recentFiles = File aperti di recente - -config.name.fontPairingMap = (Interno) Coppie di font per l'importazione -config.description.fontPairingMap = Coppie di font per l'importazione di nuovi caratteri - -config.name.lastUpdatesCheckDate = (Interno) Data ultimo controllo aggiornamenti -config.description.lastUpdatesCheckDate = Data ultimo controllo aggiornamenti su server - -config.name.gui.window.width = (Interno) Ultima larghezza finestra -config.description.gui.window.width = Ultima larghezza salvata della finestra - -config.name.gui.window.height = (Interno) Ultima altezza della finestra -config.description.gui.window.height = Ultima altezza della finestra salvata - -config.name.gui.window.maximized.horizontal = (Interno) Finestra ingrandita orizzontalmente -config.description.gui.window.maximized.horizontal = Ultima stato della finestra - massimizzata orizzontalmente - -config.name.gui.window.maximized.vertical = (Interno) Finestra ingrandita verticalmente -config.description.gui.window.maximized.vertical = Ultima stato della finestra - massimizzata verticalmente - -config.name.gui.avm2.splitPane.dividerLocationPercent = (Interno) Posizione divisorio AS3 -config.description.gui.avm2.splitPane.dividerLocationPercent = - -config.name.gui.actionSplitPane.dividerLocationPercent = (Interno) Posizione divisorio AS1/2 -config.description.gui.actionSplitPane.dividerLocationPercent = - -config.name.gui.previewSplitPane.dividerLocationPercent = (Interno) Posizione divisorio dell'anteprima -config.description.gui.previewSplitPane.dividerLocationPercent = - -config.name.gui.splitPane1.dividerLocationPercent = (Interno) Posizione 1 divisorio -config.description.gui.splitPane1.dividerLocationPercent = - -config.name.gui.splitPane2.dividerLocationPercent = (Interno) Posizione 2 divisorio -config.description.gui.splitPane2.dividerLocationPercent = - -config.name.saveAsExeScaleMode = Modalit\u00e0 scala per creazione EXE -config.description.saveAsExeScaleMode = Modalit\u00e0 di scala per esportazione EXE - -config.name.syntaxHighlightLimit = Numero massimo caratteri evidenziamento sintassi -config.description.syntaxHighlightLimit = Numero massimo di caratteri su cui eseguire evidenziamento sintattico - -config.name.guiFontPreviewSampleText = (Interno) Ultimo testo di esempio per anteprima font -config.description.guiFontPreviewSampleText = Indice lista ultimo testo di esempio per anteprima font - -config.name.gui.fontPreviewWindow.width = (Interno) Ultima larghezza finestra di anteprima font -config.description.gui.fontPreviewWindow.width = - -config.name.gui.fontPreviewWindow.height = (Interno) Ultima altezza finestra di anteprima font -config.description.gui.fontPreviewWindow.height = - -config.name.gui.fontPreviewWindow.posX = (Interno) Ultima ascissa X finestra di anteprima font -config.description.gui.fontPreviewWindow.posX = - -config.name.gui.fontPreviewWindow.posY = (Interno) Ultima ordinata Y finestra di anteprima font -config.description.gui.fontPreviewWindow.posY = - -config.name.formatting.indent.size = Numero caratteri per indentazione -config.description.formatting.indent.size = Numero di spazi (o tab) per un rientro - -config.name.formatting.indent.useTabs = Indentare con tab -config.description.formatting.indent.useTabs = Utilizzare tab invece degli spazi per l'indentazione - -config.name.beginBlockOnNewLine = Parentesi graffa su riga successiva -config.description.beginBlockOnNewLine = Iniziare un blocco di parentesi graffe dopo un a-capo - -config.name.check.updates.delay = Intervallo tra controllo aggiornamenti -config.description.check.updates.delay = Tempo minimo tra controlli automatici per aggiornamenti all'avvio - -config.name.check.updates.stable = Cercare versioni stabili -config.description.check.updates.stable = Cercare aggiornamenti di versione stabili - -config.name.check.updates.nightly = Cercare versioni di sviluppo (nightly) -config.description.check.updates.nightly = Controllo aggiornamenti per versioni di sviluppo - -config.name.check.updates.enabled = Attiva controllo aggiornamenti -config.description.check.updates.enabled = Controllo aggiornamenti automatico all'avvio - -config.name.export.formats = (Interno) Formati di esportazione -config.description.export.formats = Ultimi formati di esportazione utilizzati - -config.name.textExportSingleFile = Esportare i testi in un file unico -config.description.textExportSingleFile = Esporta testi verso un file unico invece che diversi - -config.name.textExportSingleFileSeparator = Separatore di testo per esportazione test verso file unico -config.description.textExportSingleFileSeparator = Stringa da inserire tra i testi nel file di esportazione - -config.name.textExportSingleFileRecordSeparator = Separatore di record nel file unico di esportazione testo -config.description.textExportSingleFileRecordSeparator = Stringa da inserire tra i record di testo nel file di esportazione - -config.name.warning.experimental.as12edit = Avvisa su modifiche dirette AS1/2 -config.description.warning.experimental.as12edit = Mostra avviso su modifica diretta sperimentale ad AS1/2 - -config.name.warning.experimental.as3edit = Avvisa su modifiche dirette AS3 -config.description.warning.experimental.as3edit = Mostra avviso su modifica diretta sperimentale AS3 - -config.name.packJavaScripts = Compatta il codice JavaScript -config.description.packJavaScripts = Esegue il JavaScript packer su script creati su esportazione del canvas. - -config.name.textExportExportFontFace = Utilizzare font-face nell'esportazione SVG -config.description.textExportExportFontFace = Incorpora font in SVG utilizzando font-face invece che le forme - -config.name.lzmaFastBytes = Byte LZMA veloci (valori validi: 5-255) -config.description.lzmaFastBytes = Parametro byte veloci del codificatore LZMA - -config.name.pluginPath = Percorso Plugin -config.description.pluginPath = - - -config.name.showMethodBodyId = Mostra id corpo del metodo -config.description.showMethodBodyId = Mostra id del corpo del metodo per importazione da riga di comando - -config.name.export.zoom = (Interno) Zoom per esportazione -config.description.export.zoom = Ultimo zoom usato per l'esportazione - -config.name.debuggerPort = Porta del debugger -config.description.debuggerPort = Numero di porta usato per il socket debugging - -config.name.displayDebuggerInfo = (Interno) Mostra info debugger -config.description.displayDebuggerInfo = Visualizzare informazioni sul debugger prima di attivarlo - -config.name.randomDebuggerPackage = Utilizzare un nome package casuale per il Debugger -config.description.randomDebuggerPackage = Rinomina casualmente il package del Debugger per meglio occultare la sua presenza al codice ActionScript - -config.name.lastDebuggerReplaceFunction = (Interno) Ultima sostituzione di trace selezionata -config.description.lastDebuggerReplaceFunction = Nome dell'ultima funzione selezionata per sostituire la funzione di trace con debugger - -config.name.getLocalNamesFromDebugInfo = AS3: Prendere i nomi di registro locali dalle informazioni di debug -config.description.getLocalNamesFromDebugInfo = Se sono presenti informazioni di debug, rinomina i registri locali da _loc_x_ ai nomi reali.\r\nQuesto pu\u00f2 essere disattivato perch\u00e9 alcuni offuscatori usano nomi di registro non validi. - -config.name.tagTreeShowEmptyFolders = Visualizza cartelle vuote -config.description.tagTreeShowEmptyFolders = Visualizza cartelle vuote nell'albero dei tag - -config.name.autoLoadEmbeddedSwfs = Caricamento automatico SWF incorporati -config.description.autoLoadEmbeddedSwfs = Carica in automatico i file SWF incorporati con i tag DefineBinaryData - -config.name.overrideTextExportFileName = Personalizza nome file di esportazione testo -config.description.overrideTextExportFileName = \u00c8 possibile personalizzare il nome del file di testo esportato.\r\nUsare il segnaposto {filename} per indicare il nome del file SWF corrente - -config.name.showOldTextDuringTextEditing = Mostra vecchio testo durante la modifica -config.description.showOldTextDuringTextEditing = Mostra il testo originale della variabile in grigio nell'area di anteprima - -config.group.name.import = Importazione -config.group.description.import = Impostazioni di importazione - -config.name.textImportResizeTextBoundsMode = Modalit\u00e0 ridimensionamento margini di testo -config.description.textImportResizeTextBoundsMode = Modalit\u00e0 ridimensionamento limiti di testo dopo la modifica del testo - -config.name.showCloseConfirmation = Mostra conferma chiusura SWF -config.description.showCloseConfirmation = Mostra conferma chiusura SWF per i file modificati. - -config.name.showCodeSavedMessage = Mostra avviso salvataggio codice -config.description.showCodeSavedMessage = Mostra avviso salvataggio codice - -config.name.showTraitSavedMessage = Mostra avviso salvataggio trait -config.description.showTraitSavedMessage = Mostra avviso salvataggio trait - -config.name.updateProxyAddress = Indirizzo http proxy per il controllo degli aggiornamenti -config.description.updateProxyAddress = Indirizzo http proxy per il controllo degli aggiornamenti. Formato: example.com:8080 - -config.name.editorMode = Modalit\u00e0 editor -config.description.editorMode = Rende modificabili le aree di testo in automatico alla selezione di un nodo text o script - -config.name.autoSaveTagModifications = Salvataggio automatico modifiche ai tag -config.description.autoSaveTagModifications = Salva le modifiche quando si seleziona un nuovo tag nella struttura - -config.name.saveSessionOnExit = Salva sessione in uscita -config.description.saveSessionOnExit = Salva la sessione corrente e la riapre dopo il riavvio di FFDec (funziona solo con file reali) - -config.name._showDebugMenu = Mostra il menu diagnostico di FFDec -config.description._showDebugMenu = Mostra il menu Debug nel Ribbon per la diagnostica del decompilatore. - -config.name.allowOnlyOneInstance = Permetti una sola istanza di FFDec (sotto Windows) -config.description.allowOnlyOneInstance = FFDec pu\u00f2 essere avviato solo una volta, tutti i file aperti verranno aggiunti alla stessa finestra.\nFunziona solo sotto sistema operativo Windows - -config.name.scriptExportSingleFile = Esporta script verso un unico file -config.description.scriptExportSingleFile = Esportazione script verso un unico file invece che file multipli - -config.name.setFFDecVersionInExportedFont = Imposta il numero di versione di FFDec nel font esportato -config.description.setFFDecVersionInExportedFont = Disattivando questa impostazione FFDec non aggiunge il numero di versione di FFDec al font esportato. - -config.name.gui.skin = Aspetto interfaccia utente -config.description.gui.skin = Aspetto - -config.name.lastSessionFiles = File ultima sessione -config.description.lastSessionFiles = Contiene i file aperti nell'ultima sessione - -config.name.lastSessionSelection = Selezione ultima sessione -config.description.lastSessionSelection = Contiene la selezione dell'ultima sessione - -config.name.loopMedia = Riproduzione ciclica suoni e sprite -config.description.loopMedia = Riproduce ciclicamente audio e animazioni - -config.name.gui.timeLineSplitPane.dividerLocationPercent = (Interno) Posizione divisorio del timeline -config.description.gui.timeLineSplitPane.dividerLocationPercent = - -config.name.cacheImages = Cache immagini -config.description.cacheImages = Caching degli oggetti immagine decodificati - -config.name.swfSpecificConfigs = Configurazioni specifiche SWF -config.description.swfSpecificConfigs = Contiene le configurazioni specifiche agli SWF - -config.name.exeExportMode = Modalit\u00e0 di esportazione EXE -config.description.exeExportMode = Modalit\u00e0 di esportazione EXE - -config.name.ignoreCLikePackages = Ignora FlashCC / Alchemy o package simili -config.description.ignoreCLikePackages = I package FlashCC / Alchemy non possono solitamente essere decompilati correttamente.\r\n\u00c8 possibile disattivarli per velocizzare la decompilazione di altri package. - -config.name.overwriteExistingFiles = Sovrascrivere i file esistenti -config.description.overwriteExistingFiles = Sovrascrivere i file esistenti durante l'esportazione. Attualmente solo per script AS2/3 - -config.name.smartNumberFormatting = Usa formattazione intelligente dei numeri -config.description.smartNumberFormatting = Formatta numeri speciali (ad esempio colori e istanti temporali) - -config.name.enableScriptInitializerDisplay = Visualizza inizializzatori script -config.description.enableScriptInitializerDisplay = Abilita inizializzatori script e modifiche. Questa impostazione pu\u00f2 aggiungere un accapo a ciascuna classe per evidenziare. - -config.name.autoOpenLoadedSWFs = Apri SWF caricati durante l'esecuzione (visualizzatore esterno = solo su Windows) -config.description.autoOpenLoadedSWFs = Apri in automatico tutti gli SWF caricati dalla classe AS3 Loader eseguendo lo SWF quando riprodotto nel player esterno di FFDec. Disponibile solo su Windows. - -config.name.lastSessionFileTitles = Titoli file ultima sessione -config.description.lastSessionFileTitles = Contiene i titoli dei file aperti nell'ultima sessione (ad es. quelli caricati da URL ecc.) - -config.group.name.paths = Percorsi -config.group.description.paths = Ubicazione dei file richiesti -config.group.tip.paths = \ufffd possibile ottenere questi file dal sito Adobe -config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html -config.group.linkText.paths = [apri] - -config.name.playerLocation = 1) Percorso Flash Player -config.description.playerLocation = Posizione eseguibile Flash Player. Utilizzato per l'azione Esegui. - -config.name.playerDebugLocation = 2) Percorso Flash Player per il debug -config.description.playerDebugLocation = Posizione eseguibile Flash Player per il debug. Utilizzato per l'azione Debug. - -config.name.playerLibLocation = 3) Percorso PlayerGlobal (.swc) -config.description.playerLibLocation = Posizione della libreria playerglobal.swc utilizzata perlopi\u00f9 per compilare AS3. - -config.name.debugHalt = Pausa esecuzione all'avvio del debug -config.description.debugHalt = Pausa SWF all'avvio del debug. - -config.name.gui.avm2.splitPane.vars.dividerLocationPercent = (Interno) Posizione divisorio del menu Debug -config.description.gui.avm2.splitPane.vars.dividerLocationPercent = - -tip = Suggerimento:\u0020 - -config.name.gui.action.splitPane.vars.dividerLocationPercent = (Interno) Posizione divisorio del menu Debug AS1/2 -config.description.gui.action.splitPane.vars.dividerLocationPercent = - -config.name.setMovieDelay = Ritardo in ms prima di cambiare il file SWF nel riproduttore esterno -config.description.setMovieDelay = Si sconsigliano valori inferiori a 1000ms - -config.name.warning.svgImport = Avvisa all'importazione SVG -config.description.warning.svgImport = - -config.name.shapeImport.useNonSmoothedFill = Utilizza riempimento non smussato nel sostituire una forma con un'immagine -config.description.shapeImport.useNonSmoothedFill = - -config.name.internalFlashViewer.execute.as12 = AS1/2 nel visualizzatore Flash interno (Sperimentale) -config.description.internalFlashViewer.execute.as12 = Tenta esecuzione codice ActionScript 1/2 nella riproduzione di SWF utilizzando il visualizzatore Flash FFDec - -config.name.warning.hexViewNotUpToDate = Avvisa se Hex View non aggiornata -config.description.warning.hexViewNotUpToDate = - -config.name.displayDupInstructions = Mostra istruzioni \u00a7\u00a7dup -config.description.displayDupInstructions = Visualizza istruzioni \u00a7\u00a7dup nel codice. In loro assenza il codice pu\u00f2 essere facilmente compilato ma i dup con effetti collaterali potrebbero essere eseguiti due volte. - -config.name.useRegExprLiteral = Decompila RegExp nella forma /pattern/mod. -config.description.useRegExprLiteral = Usa la sintassi /pattern/mod nella decompilazione di espressioni regolari. Altrimenti, utilizza new RegExp(\"pat\",\"mod\") - -config.name.handleSkinPartsAutomatically = Gestisce metadati [SkinPart] in automatico -config.description.handleSkinPartsAutomatically = Decompila e modifica direttamente i metadati [SkinPart] in automatico. Se disattivato, l'attributo _skinParts ed il suo metodo getter sono visibili e modificabili dall'utente. - -config.name.simplifyExpressions = Semplifica le espressioni -config.description.simplifyExpressions = Valuta and semplifica le espressioni per rendere il codice piu leggibile - -config.name.resetLetterSpacingOnTextImport = Ripristina spaziatura lettere all'importazione di testo -config.description.resetLetterSpacingOnTextImport = Utile per i font cirillici, essendo piu ampi +# Copyright (C) 2010-2016 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 . + +advancedSettings.dialog.title = Impostazioni avanzate +advancedSettings.restartConfirmation = Occorre riavviare il programma perch\u00e9 alcune modifiche abbiano effetto. Riavviare ora? +advancedSettings.columns.name = Nome +advancedSettings.columns.value = Valore +advancedSettings.columns.description = Descrizione +default = predefinito + +config.group.name.export = Esportazione +config.group.description.export = Impostazioni di esportazione + +config.group.name.script = Script +config.group.description.script = Relativi alla decompilazione ActionScript + +config.group.name.update = Aggiornamenti +config.group.description.update = Controllo aggiornamenti + +config.group.name.format = Formattazione +config.group.description.format = Formattazione del codice ActionScript + +config.group.name.limit = Limiti +config.group.description.limit = Limiti nella decompilazione di codice offuscato, ecc. + +config.group.name.ui = Interfaccia +config.group.description.ui = Configurazione interfaccia utente + +config.group.name.debug = Debug +config.group.description.debug = Opzioni di debug + +config.group.name.display = Visualizzazione +config.group.description.display = Visualizzazione oggetti Flash, ecc. + +config.group.name.decompilation = Decompilazione +config.group.description.decompilation = Funzioni globali legate alla decompilazione + +config.group.name.other = Varie +config.group.description.other = Altre impostazioni + +config.name.openMultipleFiles = Apertura file multipli +config.description.openMultipleFiles = Permette di aprire pi\u00f9 file contemporaneamente nella stessa finestra + +config.name.decompile = Visualizza sorgenti ActionScript +config.description.decompile = Disattivando la decompilazione AS viene visualizzato solo il P-code + +config.name.dumpView = Visualizza hex dump +config.description.dumpView = Mostra listato esadecimale dei byte nel file + +config.name.useHexColorFormat = Formato esadecimale per i colori +config.description.useHexColorFormat = Presenta i colori in formato esadecimale + +config.name.parallelSpeedUp = Elaborazione in parallelo +config.description.parallelSpeedUp = Il parallelismo pu\u00f2 ridurre i tempi di decompilazione + +config.name.parallelSpeedUpThreadCount = Numero di thread +config.description.parallelSpeedUpThreadCount = Numero di thread in esecuzione parallela + +config.name.autoDeobfuscate = Deoffuscamento automatico +config.description.autoDeobfuscate = Tenta il deoffuscamento su ogni file prima della decompilazione ActionScript + +config.name.cacheOnDisk = Utilizza cache su disco +config.description.cacheOnDisk = Memorizza le parti decompilate su disco anzich\u00e9 in memoria + +config.name.internalFlashViewer = Utilizza visualizzatore Flash incorporato +config.description.internalFlashViewer = Utilizza JPEXS Flash Viewer invece del Flash Player standard per visualizzare le parti in Flash + +config.name.gotoMainClassOnStartup = Vai alla classe principale all'avvio (AS3) +config.description.gotoMainClassOnStartup = Passa alla classe documento del file AS3 all'apertura del SWF + +config.name.autoRenameIdentifiers = Autorinomina degli identificatori +config.description.autoRenameIdentifiers = Rinomina identificatori non validi al caricamento del SWF + +config.name.offeredAssociation = (Interno) Associazione con file SWF visualizzato +config.description.offeredAssociation = Finestra di dialogo gi\u00e0 visualizzata + +config.name.decimalAddress = Mostra indirizzi in decimale +config.description.decimalAddress = Usa indirizzi in base 10 (dec) invece che in base 16 (hex) + +config.name.showAllAddresses = Mostra tutti gli indirizzi +config.description.showAllAddresses = Visualizza tutti gli indirizzi di istruzioni ActionScript + +config.name.useFrameCache = Usa frame cache +config.description.useFrameCache = Fare caching dei frame prima di ridisegnarli + +config.name.useRibbonInterface = Interfaccia con menu multifunzione (Ribbon) +config.description.useRibbonInterface = Deselezionare per usare la GUI classica + +config.name.openFolderAfterFlaExport = Apri cartella dopo l'esportazione FLA +config.description.openFolderAfterFlaExport = Visualizza cartella di output dopo l'esportazione FLA + +config.name.useDetailedLogging = Log dettagliato +config.description.useDetailedLogging = Log dettagliato dei messaggi di errore e di informazioni a scopo diagnostico + +config.name._debugMode = FFDec in modalit\u00e0 diagnostica +config.description._debugMode = Modalit\u00e0 diagnostica per FFDec. Attiva il menu Debug. Non riguarda la funzionalita di debug + +config.name.resolveConstants = Risolvere le costanti nel P-code AS1/2 +config.description.resolveConstants = Disattivare per mostrare 'constantxx' invece dei valori effettivi nella vista P-code + +config.name.sublimiter = Limite su subroutine +config.description.sublimiter = Limite su subroutine per codice offuscato. + +config.name.exportTimeout = Tempo massimo di esportazione (secondi) +config.description.exportTimeout = Il decompilatore interromper\u00e0 l'esportazione dopo questo tempo + +config.name.decompilationTimeoutFile = Tempo massimo di decompilazione per file (secondi) +config.description.decompilationTimeoutFile = Il decompilatore interromper\u00e0 la decompilazione ActionScript dopo questo tempo per un singolo file + +config.name.paramNamesEnable = Abilita nomi di parametro in AS3 +config.description.paramNamesEnable = Utilizzare i nomi di parametro nella decompilazione pu\u00f2 causare problemi poich\u00e9 programmi ufficiali come Flash CS 5.5 generano indici di nome errati + +config.name.displayFileName = Mostra nome SWF nel titolo della finestra +config.description.displayFileName = Visualizza nome/URL del file SWF nel titolo (\u00e8 possibile fare screenshot) + +config.name._debugCopy = Diagnostica ricompilazione FFDec +config.description._debugCopy = Prova a ricompilare il file SWF subito dopo l'apertura per garantire che generi lo stesso codice binario. Da usare SOLO per la diagnostica di FFDec! + +config.name.dumpTags = Dump dei tag su console +config.description.dumpTags = Scrive i tag su console alla lettura del file SWF + +config.name.decompilationTimeoutSingleMethod = AS3: Tempo massimo di decompilazione per singolo metodo (secondi) +config.description.decompilationTimeoutSingleMethod = Il decompilatore interromper\u00e0 la decompilazione ActionScript dopo questo tempo per un singolo metodo + +config.name.lastRenameType = (Interno) Ultimo tipo di rinomina +config.description.lastRenameType = Ultimo tipo di rinomina identificatore utilizzato + +config.name.lastSaveDir = (Interno) Ultima cartella di salvataggio +config.description.lastSaveDir = Ultima directory di salvataggio usata + +config.name.lastOpenDir = (Interno) Ultima cartella aperta +config.description.lastOpenDir = Ultima directory aperta utilizzata + +config.name.lastExportDir = (Interno) Ultima cartella di esportazione +config.description.lastExportDir = Ultima directory di esportazione usata + +config.name.locale = Lingua +config.description.locale = Identificatore per la localizzazione + +config.name.registerNameFormat = Formato delle variabili di registro +config.description.registerNameFormat = Formato nome delle variabili registro locali. Utilizzare %d per specificare il numero di registro. + +config.name.maxRecentFileCount = Limite elenco file recenti +config.description.maxRecentFileCount = Numero massimo di file recenti + +config.name.recentFiles = (Interno) File recenti +config.description.recentFiles = File aperti di recente + +config.name.fontPairingMap = (Interno) Coppie di font per l'importazione +config.description.fontPairingMap = Coppie di font per l'importazione di nuovi caratteri + +config.name.lastUpdatesCheckDate = (Interno) Data ultimo controllo aggiornamenti +config.description.lastUpdatesCheckDate = Data ultimo controllo aggiornamenti su server + +config.name.gui.window.width = (Interno) Ultima larghezza finestra +config.description.gui.window.width = Ultima larghezza salvata della finestra + +config.name.gui.window.height = (Interno) Ultima altezza della finestra +config.description.gui.window.height = Ultima altezza della finestra salvata + +config.name.gui.window.maximized.horizontal = (Interno) Finestra ingrandita orizzontalmente +config.description.gui.window.maximized.horizontal = Ultima stato della finestra - massimizzata orizzontalmente + +config.name.gui.window.maximized.vertical = (Interno) Finestra ingrandita verticalmente +config.description.gui.window.maximized.vertical = Ultima stato della finestra - massimizzata verticalmente + +config.name.gui.avm2.splitPane.dividerLocationPercent = (Interno) Posizione divisorio AS3 +config.description.gui.avm2.splitPane.dividerLocationPercent = + +config.name.gui.actionSplitPane.dividerLocationPercent = (Interno) Posizione divisorio AS1/2 +config.description.gui.actionSplitPane.dividerLocationPercent = + +config.name.gui.previewSplitPane.dividerLocationPercent = (Interno) Posizione divisorio dell'anteprima +config.description.gui.previewSplitPane.dividerLocationPercent = + +config.name.gui.splitPane1.dividerLocationPercent = (Interno) Posizione 1 divisorio +config.description.gui.splitPane1.dividerLocationPercent = + +config.name.gui.splitPane2.dividerLocationPercent = (Interno) Posizione 2 divisorio +config.description.gui.splitPane2.dividerLocationPercent = + +config.name.saveAsExeScaleMode = Modalit\u00e0 scala per creazione EXE +config.description.saveAsExeScaleMode = Modalit\u00e0 di scala per esportazione EXE + +config.name.syntaxHighlightLimit = Numero massimo caratteri evidenziamento sintassi +config.description.syntaxHighlightLimit = Numero massimo di caratteri su cui eseguire evidenziamento sintattico + +config.name.guiFontPreviewSampleText = (Interno) Ultimo testo di esempio per anteprima font +config.description.guiFontPreviewSampleText = Indice lista ultimo testo di esempio per anteprima font + +config.name.gui.fontPreviewWindow.width = (Interno) Ultima larghezza finestra di anteprima font +config.description.gui.fontPreviewWindow.width = + +config.name.gui.fontPreviewWindow.height = (Interno) Ultima altezza finestra di anteprima font +config.description.gui.fontPreviewWindow.height = + +config.name.gui.fontPreviewWindow.posX = (Interno) Ultima ascissa X finestra di anteprima font +config.description.gui.fontPreviewWindow.posX = + +config.name.gui.fontPreviewWindow.posY = (Interno) Ultima ordinata Y finestra di anteprima font +config.description.gui.fontPreviewWindow.posY = + +config.name.formatting.indent.size = Numero caratteri per indentazione +config.description.formatting.indent.size = Numero di spazi (o tab) per un rientro + +config.name.formatting.indent.useTabs = Indentare con tab +config.description.formatting.indent.useTabs = Utilizzare tab invece degli spazi per l'indentazione + +config.name.beginBlockOnNewLine = Parentesi graffa su riga successiva +config.description.beginBlockOnNewLine = Iniziare un blocco di parentesi graffe dopo un a-capo + +config.name.check.updates.delay = Intervallo tra controllo aggiornamenti +config.description.check.updates.delay = Tempo minimo tra controlli automatici per aggiornamenti all'avvio + +config.name.check.updates.stable = Cercare versioni stabili +config.description.check.updates.stable = Cercare aggiornamenti di versione stabili + +config.name.check.updates.nightly = Cercare versioni di sviluppo (nightly) +config.description.check.updates.nightly = Controllo aggiornamenti per versioni di sviluppo + +config.name.check.updates.enabled = Attiva controllo aggiornamenti +config.description.check.updates.enabled = Controllo aggiornamenti automatico all'avvio + +config.name.export.formats = (Interno) Formati di esportazione +config.description.export.formats = Ultimi formati di esportazione utilizzati + +config.name.textExportSingleFile = Esportare i testi in un file unico +config.description.textExportSingleFile = Esporta testi verso un file unico invece che diversi + +config.name.textExportSingleFileSeparator = Separatore di testo per esportazione test verso file unico +config.description.textExportSingleFileSeparator = Stringa da inserire tra i testi nel file di esportazione + +config.name.textExportSingleFileRecordSeparator = Separatore di record nel file unico di esportazione testo +config.description.textExportSingleFileRecordSeparator = Stringa da inserire tra i record di testo nel file di esportazione + +config.name.warning.experimental.as12edit = Avvisa su modifiche dirette AS1/2 +config.description.warning.experimental.as12edit = Mostra avviso su modifica diretta sperimentale ad AS1/2 + +config.name.warning.experimental.as3edit = Avvisa su modifiche dirette AS3 +config.description.warning.experimental.as3edit = Mostra avviso su modifica diretta sperimentale AS3 + +config.name.packJavaScripts = Compatta il codice JavaScript +config.description.packJavaScripts = Esegue il JavaScript packer su script creati su esportazione del canvas. + +config.name.textExportExportFontFace = Utilizzare font-face nell'esportazione SVG +config.description.textExportExportFontFace = Incorpora font in SVG utilizzando font-face invece che le forme + +config.name.lzmaFastBytes = Byte LZMA veloci (valori validi: 5-255) +config.description.lzmaFastBytes = Parametro byte veloci del codificatore LZMA + +config.name.pluginPath = Percorso Plugin +config.description.pluginPath = - + +config.name.showMethodBodyId = Mostra id corpo del metodo +config.description.showMethodBodyId = Mostra id del corpo del metodo per importazione da riga di comando + +config.name.export.zoom = (Interno) Zoom per esportazione +config.description.export.zoom = Ultimo zoom usato per l'esportazione + +config.name.debuggerPort = Porta del debugger +config.description.debuggerPort = Numero di porta usato per il socket debugging + +config.name.displayDebuggerInfo = (Interno) Mostra info debugger +config.description.displayDebuggerInfo = Visualizzare informazioni sul debugger prima di attivarlo + +config.name.randomDebuggerPackage = Utilizzare un nome package casuale per il Debugger +config.description.randomDebuggerPackage = Rinomina casualmente il package del Debugger per meglio occultare la sua presenza al codice ActionScript + +config.name.lastDebuggerReplaceFunction = (Interno) Ultima sostituzione di trace selezionata +config.description.lastDebuggerReplaceFunction = Nome dell'ultima funzione selezionata per sostituire la funzione di trace con debugger + +config.name.getLocalNamesFromDebugInfo = AS3: Prendere i nomi di registro locali dalle informazioni di debug +config.description.getLocalNamesFromDebugInfo = Se sono presenti informazioni di debug, rinomina i registri locali da _loc_x_ ai nomi reali.\r\nQuesto pu\u00f2 essere disattivato perch\u00e9 alcuni offuscatori usano nomi di registro non validi. + +config.name.tagTreeShowEmptyFolders = Visualizza cartelle vuote +config.description.tagTreeShowEmptyFolders = Visualizza cartelle vuote nell'albero dei tag + +config.name.autoLoadEmbeddedSwfs = Caricamento automatico SWF incorporati +config.description.autoLoadEmbeddedSwfs = Carica in automatico i file SWF incorporati con i tag DefineBinaryData + +config.name.overrideTextExportFileName = Personalizza nome file di esportazione testo +config.description.overrideTextExportFileName = \u00c8 possibile personalizzare il nome del file di testo esportato.\r\nUsare il segnaposto {filename} per indicare il nome del file SWF corrente + +config.name.showOldTextDuringTextEditing = Mostra vecchio testo durante la modifica +config.description.showOldTextDuringTextEditing = Mostra il testo originale della variabile in grigio nell'area di anteprima + +config.group.name.import = Importazione +config.group.description.import = Impostazioni di importazione + +config.name.textImportResizeTextBoundsMode = Modalit\u00e0 ridimensionamento margini di testo +config.description.textImportResizeTextBoundsMode = Modalit\u00e0 ridimensionamento limiti di testo dopo la modifica del testo + +config.name.showCloseConfirmation = Mostra conferma chiusura SWF +config.description.showCloseConfirmation = Mostra conferma chiusura SWF per i file modificati. + +config.name.showCodeSavedMessage = Mostra avviso salvataggio codice +config.description.showCodeSavedMessage = Mostra avviso salvataggio codice + +config.name.showTraitSavedMessage = Mostra avviso salvataggio trait +config.description.showTraitSavedMessage = Mostra avviso salvataggio trait + +config.name.updateProxyAddress = Indirizzo http proxy per il controllo degli aggiornamenti +config.description.updateProxyAddress = Indirizzo http proxy per il controllo degli aggiornamenti. Formato: example.com:8080 + +config.name.editorMode = Modalit\u00e0 editor +config.description.editorMode = Rende modificabili le aree di testo in automatico alla selezione di un nodo text o script + +config.name.autoSaveTagModifications = Salvataggio automatico modifiche ai tag +config.description.autoSaveTagModifications = Salva le modifiche quando si seleziona un nuovo tag nella struttura + +config.name.saveSessionOnExit = Salva sessione in uscita +config.description.saveSessionOnExit = Salva la sessione corrente e la riapre dopo il riavvio di FFDec (funziona solo con file reali) + +config.name._showDebugMenu = Mostra il menu diagnostico di FFDec +config.description._showDebugMenu = Mostra il menu Debug nel Ribbon per la diagnostica del decompilatore. + +config.name.allowOnlyOneInstance = Permetti una sola istanza di FFDec (sotto Windows) +config.description.allowOnlyOneInstance = FFDec pu\u00f2 essere avviato solo una volta, tutti i file aperti verranno aggiunti alla stessa finestra.\nFunziona solo sotto sistema operativo Windows + +config.name.scriptExportSingleFile = Esporta script verso un unico file +config.description.scriptExportSingleFile = Esportazione script verso un unico file invece che file multipli + +config.name.setFFDecVersionInExportedFont = Imposta il numero di versione di FFDec nel font esportato +config.description.setFFDecVersionInExportedFont = Disattivando questa impostazione FFDec non aggiunge il numero di versione di FFDec al font esportato. + +config.name.gui.skin = Aspetto interfaccia utente +config.description.gui.skin = Aspetto + +config.name.lastSessionFiles = File ultima sessione +config.description.lastSessionFiles = Contiene i file aperti nell'ultima sessione + +config.name.lastSessionSelection = Selezione ultima sessione +config.description.lastSessionSelection = Contiene la selezione dell'ultima sessione + +config.name.loopMedia = Riproduzione ciclica suoni e sprite +config.description.loopMedia = Riproduce ciclicamente audio e animazioni + +config.name.gui.timeLineSplitPane.dividerLocationPercent = (Interno) Posizione divisorio del timeline +config.description.gui.timeLineSplitPane.dividerLocationPercent = + +config.name.cacheImages = Cache immagini +config.description.cacheImages = Caching degli oggetti immagine decodificati + +config.name.swfSpecificConfigs = Configurazioni specifiche SWF +config.description.swfSpecificConfigs = Contiene le configurazioni specifiche agli SWF + +config.name.exeExportMode = Modalit\u00e0 di esportazione EXE +config.description.exeExportMode = Modalit\u00e0 di esportazione EXE + +config.name.ignoreCLikePackages = Ignora FlashCC / Alchemy o package simili +config.description.ignoreCLikePackages = I package FlashCC / Alchemy non possono solitamente essere decompilati correttamente.\r\n\u00c8 possibile disattivarli per velocizzare la decompilazione di altri package. + +config.name.overwriteExistingFiles = Sovrascrivere i file esistenti +config.description.overwriteExistingFiles = Sovrascrivere i file esistenti durante l'esportazione. Attualmente solo per script AS2/3 + +config.name.smartNumberFormatting = Usa formattazione intelligente dei numeri +config.description.smartNumberFormatting = Formatta numeri speciali (ad esempio colori e istanti temporali) + +config.name.enableScriptInitializerDisplay = Visualizza inizializzatori script +config.description.enableScriptInitializerDisplay = Abilita inizializzatori script e modifiche. Questa impostazione pu\u00f2 aggiungere un accapo a ciascuna classe per evidenziare. + +config.name.autoOpenLoadedSWFs = Apri SWF caricati durante l'esecuzione (visualizzatore esterno = solo su Windows) +config.description.autoOpenLoadedSWFs = Apri in automatico tutti gli SWF caricati dalla classe AS3 Loader eseguendo lo SWF quando riprodotto nel player esterno di FFDec. Disponibile solo su Windows. + +config.name.lastSessionFileTitles = Titoli file ultima sessione +config.description.lastSessionFileTitles = Contiene i titoli dei file aperti nell'ultima sessione (ad es. quelli caricati da URL ecc.) + +config.group.name.paths = Percorsi +config.group.description.paths = Ubicazione dei file richiesti +config.group.tip.paths = \ufffd possibile ottenere questi file dal sito Adobe +config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html +config.group.linkText.paths = [apri] + +config.name.playerLocation = 1) Percorso Flash Player +config.description.playerLocation = Posizione eseguibile Flash Player. Utilizzato per l'azione Esegui. + +config.name.playerDebugLocation = 2) Percorso Flash Player per il debug +config.description.playerDebugLocation = Posizione eseguibile Flash Player per il debug. Utilizzato per l'azione Debug. + +config.name.playerLibLocation = 3) Percorso PlayerGlobal (.swc) +config.description.playerLibLocation = Posizione della libreria playerglobal.swc utilizzata perlopi\u00f9 per compilare AS3. + +config.name.debugHalt = Pausa esecuzione all'avvio del debug +config.description.debugHalt = Pausa SWF all'avvio del debug. + +config.name.gui.avm2.splitPane.vars.dividerLocationPercent = (Interno) Posizione divisorio del menu Debug +config.description.gui.avm2.splitPane.vars.dividerLocationPercent = + +tip = Suggerimento:\u0020 + +config.name.gui.action.splitPane.vars.dividerLocationPercent = (Interno) Posizione divisorio del menu Debug AS1/2 +config.description.gui.action.splitPane.vars.dividerLocationPercent = + +config.name.setMovieDelay = Ritardo in ms prima di cambiare il file SWF nel riproduttore esterno +config.description.setMovieDelay = Si sconsigliano valori inferiori a 1000ms + +config.name.warning.svgImport = Avvisa all'importazione SVG +config.description.warning.svgImport = + +config.name.shapeImport.useNonSmoothedFill = Utilizza riempimento non smussato nel sostituire una forma con un'immagine +config.description.shapeImport.useNonSmoothedFill = + +config.name.internalFlashViewer.execute.as12 = AS1/2 nel visualizzatore Flash interno (Sperimentale) +config.description.internalFlashViewer.execute.as12 = Tenta esecuzione codice ActionScript 1/2 nella riproduzione di SWF utilizzando il visualizzatore Flash FFDec + +config.name.warning.hexViewNotUpToDate = Avvisa se Hex View non aggiornata +config.description.warning.hexViewNotUpToDate = + +config.name.displayDupInstructions = Mostra istruzioni \u00a7\u00a7dup +config.description.displayDupInstructions = Visualizza istruzioni \u00a7\u00a7dup nel codice. In loro assenza il codice pu\u00f2 essere facilmente compilato ma i dup con effetti collaterali potrebbero essere eseguiti due volte. + +config.name.useRegExprLiteral = Decompila RegExp nella forma /pattern/mod. +config.description.useRegExprLiteral = Usa la sintassi /pattern/mod nella decompilazione di espressioni regolari. Altrimenti, utilizza new RegExp(\"pat\",\"mod\") + +config.name.handleSkinPartsAutomatically = Gestisce metadati [SkinPart] in automatico +config.description.handleSkinPartsAutomatically = Decompila e modifica direttamente i metadati [SkinPart] in automatico. Se disattivato, l'attributo _skinParts ed il suo metodo getter sono visibili e modificabili dall'utente. + +config.name.simplifyExpressions = Semplifica le espressioni +config.description.simplifyExpressions = Valuta and semplifica le espressioni per rendere il codice piu leggibile + +config.name.resetLetterSpacingOnTextImport = Ripristina spaziatura lettere all'importazione di testo +config.description.resetLetterSpacingOnTextImport = Utile per i font cirillici, essendo piu ampi diff --git a/src/com/jpexs/decompiler/flash/gui/locales/LoadFromCacheFrame_fr.properties b/src/com/jpexs/decompiler/flash/gui/locales/LoadFromCacheFrame_fr.properties index 0bd5307a7..622d225e5 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/LoadFromCacheFrame_fr.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/LoadFromCacheFrame_fr.properties @@ -1,21 +1,21 @@ -# Copyright (C) 2010-2016 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 . - -button.open = Ouvrir -button.save = Enregistrer -button.refresh = Rafra\u00eechir la liste -dialog.title = Rechercher dans la m\u00e9moire cache des navigateurs -supported.browsers = Navigateurs support\u00e9s : -info.closed = *Ce navigateur conserve les donn\u00e9es sur le disque en cache apr\u00e8s fermeture. +# Copyright (C) 2010-2016 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 . + +button.open = Ouvrir +button.save = Enregistrer +button.refresh = Rafra\u00eechir la liste +dialog.title = Rechercher dans la m\u00e9moire cache des navigateurs +supported.browsers = Navigateurs support\u00e9s : +info.closed = *Ce navigateur conserve les donn\u00e9es sur le disque en cache apr\u00e8s fermeture. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/LoadFromMemoryFrame_it.properties b/src/com/jpexs/decompiler/flash/gui/locales/LoadFromMemoryFrame_it.properties index 678b48167..0f0dc79ac 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/LoadFromMemoryFrame_it.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/LoadFromMemoryFrame_it.properties @@ -1,32 +1,32 @@ -# Copyright (C) 2010-2016 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 . - -dialog.title = Cerca SWF in memoria -button.open = Apri -button.select = Seleziona -button.refresh = Aggiorna elenco -noprocess = Nessun processo selezionato -searching = Ricerca in corso... -swfitem = [SWF versione %version% dimensione %size%] -notfound = Nessun SWF trovato - -#after version 1.7.1: -button.save = Salva - -column.version = Versione -column.fileSize = Dimensione file -column.pid = PID -column.processName = Nome processo -column.address = Indirizzo +# Copyright (C) 2010-2016 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 . + +dialog.title = Cerca SWF in memoria +button.open = Apri +button.select = Seleziona +button.refresh = Aggiorna elenco +noprocess = Nessun processo selezionato +searching = Ricerca in corso... +swfitem = [SWF versione %version% dimensione %size%] +notfound = Nessun SWF trovato + +#after version 1.7.1: +button.save = Salva + +column.version = Versione +column.fileSize = Dimensione file +column.pid = PID +column.processName = Nome processo +column.address = Indirizzo diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties index 0d84fc17b..761277e4a 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_es.properties @@ -1,722 +1,722 @@ -# Copyright (C) 2010-2016 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 . - -menu.file = Archivo -menu.file.open = Abrir... -menu.file.save = Guardar -menu.file.saveas = Guardar como... -menu.file.export.fla = Exportar a FLA -menu.file.export.all = Exportar todas las partes -menu.file.export.selection = Exportar selecci\u00f3n -menu.file.exit = Salir - -menu.tools = Herramientas -menu.tools.searchas = Buscar todo el ActionScript... -menu.tools.proxy = Proxy -menu.tools.deobfuscation = Desofuscaci\u00f3n -menu.tools.deobfuscation.pcode = Desofuscaci\u00f3n de PCode... -menu.tools.deobfuscation.globalrename = Renombrar identificador globalmente -menu.tools.deobfuscation.renameinvalid = Renombrar identificadores inv\u00e1lidos -menu.tools.gotoDocumentClass = Ir al document class - -menu.settings = Ajustes -menu.settings.autodeobfuscation = Desofuscaci\u00f3n autom\u00e1tica -menu.settings.internalflashviewer = Usar un visor de flash propio -menu.settings.parallelspeedup = Aceleraci\u00f3n en paralelo -menu.settings.disabledecompilation = Inhabilitar decompilaci\u00f3n (solo desensamblado) -menu.settings.addtocontextmenu = Agregar FFDec al men\u00fa contextual de archivos SWF -menu.settings.language = Cambiar lenguaje -menu.settings.cacheOnDisk = Usar almacenamiento de cach\u00e9 en disco -menu.settings.gotoMainClassOnStartup = Resaltar el document class al iniciar - -menu.help = Ayuda -menu.help.checkupdates = Comprobar actualizaciones... -menu.help.helpus = Ayudanos! -menu.help.homepage = Visitar la p\u00e1gina principal -menu.help.about = Acerca de... - -contextmenu.remove = Remover - -button.save = Guardar -button.edit = Editar -button.cancel = Cancelar -button.replace = Reemplazar... - -notavailonthisplatform = La vista previa de este objeto no est\u00e1 disponible en esta plataforma. (solo Windows) - -swfpreview = Vista previa del SWF -swfpreview.internal = Vista previa del SWF (Visor interno) - -parameters = Par\u00e1metros - -rename.enternew = Ingresar nuevo nombre: - -rename.finished.identifier = Identificador renombrado. -rename.finished.multiname = %count% multinombres(s) renombrado. - -node.texts = textos -node.images = im\u00e1genes -node.movies = pel\u00edculas -node.sounds = sonidos -node.binaryData = datosbinarios -node.fonts = fuentes -node.sprites = sprites -node.shapes = formas -node.morphshapes = morphshapes -node.buttons = botones -node.frames = marcos -node.scripts = scripts - -message.warning = Cuidado -message.confirm.experimental = El siguiente procedimiento puede da\u00f1ar el archivo SWF e inutilizar su reproducci\u00f3n.\r\nUSESE BAJO SU PROPIO RIESGO. Desea continuar? -message.confirm.parallel = El paralelismo puede acelerar la carga y la descompilaci\u00f3n pero requerir m\u00e1s memoria. -message.confirm.on = Desea encenderlo? -message.confirm.off = Desea apagarlo? -message.confirm = Confirmar - -message.confirm.autodeobfuscate = La desofuscaci\u00f3n autom\u00e1tica es una manera de descompilar el c\u00f3digo ofuscado.\r\nLa desofuscaci\u00f3n conduce a una descompilaci\u00f3n m\u00e1s lenta y a eliminar algo de c\u00f3digo muerto.\r\nSi el c\u00f3digo no est\u00e1 ofuscado, es mejor deshabilitar la autodesofuscaci\u00f3n. - -message.parallel = Paralelismo -message.trait.saved = Rasgo guardado existosamente - -message.constant.new.string = La cadena "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarla? -message.constant.new.string.title = Agregar cadena -message.constant.new.integer = El entero "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarlo? -message.constant.new.integer.title = Agregar entero -message.constant.new.unsignedinteger = El entero no signado "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarlo? -message.constant.new.unsignedinteger.title = Agregar entero no signado -message.constant.new.double = El entero doble "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarlo? -message.constant.new.double.title = Agregar entero doble - -work.buffering = Buffering -work.waitingfordissasembly = Esperando el desensamblado -work.gettinghilights = Adquiriendo resaltadores -work.disassembling = Desensamblando -work.exporting = Exportando -work.searching = Buscando -work.renaming = Renombrando -work.exporting.fla = Exportando FLA -work.renaming.identifiers = Renombrando identificadores -work.deobfuscating = Desofuscando -work.decompiling = Decompilando -work.gettingvariables = Adquiriendo variables -work.reading.swf = Leyendo SWF -work.creatingwindow = Creando ventana -work.buildingscripttree = Generando \u00e1rbol de script Building script tree - -work.deobfuscating.complete = Desofuscaci\u00f3n completada - -message.search.notfound = Cadena "%searchtext%" no encontrada. -message.search.notfound.title = No encontrado - -message.rename.notfound.multiname = No se encontr\u00f3 ning\u00fan multiname bajo el cursor -message.rename.notfound.identifier = No se encontr\u00f3 ning\u00fan identificador bajo el cursor -message.rename.notfound.title = No encontrado -message.rename.renamed = Identificadores renombrados: %count% - -filter.images = Im\u00e1genes (%extensions%) -filter.fla = Documento %version% (*.fla) -filter.xfl = Documento no comprimido %version% (*.xfl) -filter.swf = Archivos SWF (*.swf) - -error = Error -error.image.invalid = Im\u00e1gen inv\u00e1lida. - -error.text.invalid = Texto inv\u00e1lido: %text% en la l\u00ednea %line% -error.file.save = No se puede guardar el archivo -error.file.write = No se puede escribir al archivo -error.export = Error durante la exportaci\u00f3n - -export.select.directory = Seleccione directorio para exportar -export.finishedin = Exportado en %time% - -update.check.title = Chequeo de actualizaci\u00f3n -update.check.nonewversion = No hay versi\u00f3n nueva disponible. - -message.helpus = Por favor, visite\r\n%url%\r\npara m\u00e1s detalles. -message.homepage = Visite la p\u00e1gina principal en: \r\n%url% - -proxy = Proxy -proxy.start = Comenzar proxy -proxy.stop = Detener proxy -proxy.show = Mostrar proxy -exit = Salir - -panel.disassembled = Fuente P-code -panel.decompiled = Fuente ActionScript - -search.info = Buscar por "%text%" : -search.script = Script - -constants = Constantes -traits = Rasgos - -pleasewait = Espere por favor - -abc.detail.methodtrait = M\u00e9todo/Getter/Setter Rasgo -abc.detail.unsupported = - -abc.detail.slotconsttrait = Slot/Const Rasgo -abc.detail.traitname = Nombre: - -abc.detail.body.params.maxstack = Pila m\u00e1xima: -abc.detail.body.params.localregcount = Contador de registros locales: -abc.detail.body.params.minscope = Profundidad de alcance m\u00ednima: -abc.detail.body.params.maxscope = Profundidad de alcance m\u00e1xima: -abc.detail.body.params.autofill = Auto rellenado al salvar c\u00f3dig (AJUSTE GLOBAL) -abc.detail.body.params.autofill.experimental = ...EXPERIMENTAL - -abc.detail.methodinfo.methodindex = Indice de m\u00e9todo: -abc.detail.methodinfo.parameters = Par\u00e1metros: -abc.detail.methodinfo.returnvalue = Tipo de valor de retorno: - -error.methodinfo.params = Error de pa\u0155ametro MethodInfo -error.methodinfo.returnvalue = Error de retorno de tipo MethodInfo - -abc.detail.methodinfo = MethodInfo -abc.detail.body.code = C\u00f3digo de MethodBody -abc.detail.body.params = Par\u00e1metros de MethodBody - -abc.detail.slotconst.typevalue = Tipo y valor: - -error.slotconst.typevalue = Error de valor de tipo SlotConst - -message.autofill.failed = No se puede obtener las estad\u00edsticas de c\u00f3digo para los par\u00e1metros de cuerpo autom\u00e1ticos.\r\nDestilde auto-llenado para evitar este mensaje. -info.selecttrait = Seleccione la clase y clickee un atributo en el c\u00f3digo Actionscript para editarlo. - -button.viewgraph = Ver grafo -button.viewhex = Ver en hexa - -abc.traitslist.instanceinitializer = inicializador de instancia -abc.traitslist.classinitializer = inicializador de clase - -action.edit.experimental = (Experimental) - -message.action.saved = C\u00f3digo guardado exitosamente - -error.action.save = %error% en la l\u00ednea %line% - -message.confirm.remove = Est\u00e1 seguro que desea remover %item% \n y todos los objetos que dependen de \u00e9l? - -#after version 1.6.5u1: - -button.ok = OK -button.cancel = Cancelar - -font.name = Nombre de fuente: -font.isbold = Es negrita: -font.isitalic = Es it\u00e1lica: -font.ascent = Ascendente: -font.descent = Descendente: -font.leading = Destacado: -font.characters = Caract\u00e9r: -font.characters.add = Agregar caracteres: -value.unknown = ? - -yes = si -no = no - -errors.present = Hay ERRORES en el log. Clickear para ver. -errors.none = No hay errores en el log - -#after version 1.6.6: - -dialog.message.title = Mensaje -dialog.select.title = Seleccione una opci\u00f3n - -button.yes = Si -button.no = No - -FileChooser.openButtonText = Abrir -FileChooser.openButtonToolTipText = Abrir -FileChooser.lookInLabelText = Mirar en: -FileChooser.acceptAllFileFilterText = Todos los archivos -FileChooser.filesOfTypeLabelText = Archivos de tipo: -FileChooser.fileNameLabelText = Nombre de archivo: -FileChooser.listViewButtonToolTipText = Lista -FileChooser.listViewButtonAccessibleName = Lista -FileChooser.detailsViewButtonToolTipText = Detales -FileChooser.detailsViewButtonAccessibleName = Detalles -FileChooser.upFolderToolTipText = Subir un nivel -FileChooser.upFolderAccessibleName = Subir un nivel -FileChooser.homeFolderToolTipText = Home -FileChooser.homeFolderAccessibleName = Home -FileChooser.fileNameHeaderText = Nombre -FileChooser.fileSizeHeaderText = Tama\u00f1o -FileChooser.fileTypeHeaderText = Tipo -FileChooser.fileDateHeaderText = Fecha -FileChooser.fileAttrHeaderText = Atributos -FileChooser.openDialogTitleText = Abrir -FileChooser.directoryDescriptionText = Directorio -FileChooser.directoryOpenButtonText = Abrir -FileChooser.directoryOpenButtonToolTipText = Abrir el directorio seleccionado -FileChooser.fileDescriptionText = Archivo gen\u00e9rico -FileChooser.helpButtonText = Ayuda -FileChooser.helpButtonToolTipText = Ayuda de FileChooser -FileChooser.newFolderAccessibleName = Nueva carpeta -FileChooser.newFolderErrorText = Error creando nueva carpeta -FileChooser.newFolderToolTipText = Crear nueva carpeta -FileChooser.other.newFolder = NuevaCarpeta -FileChooser.other.newFolder.subsequent = NuevaCarpeta.{0} -FileChooser.win32.newFolder = Nueva Carpeta -FileChooser.win32.newFolder.subsequent = Nueva Carpeta ({0}) -FileChooser.saveButtonText = Guarda -FileChooser.saveButtonToolTipText = Guardar archivo seleccionado -FileChooser.saveDialogTitleText = Guardar -FileChooser.saveInLabelText = Guardar en: -FileChooser.updateButtonText = Actualizar -FileChooser.updateButtonToolTipText = Actualizar listado de directorio - -#after version 1.6.6u2: - -FileChooser.detailsViewActionLabel.textAndMnemonic = Detalles -FileChooser.detailsViewButtonToolTip.textAndMnemonic = Detalles -FileChooser.fileAttrHeader.textAndMnemonic = Atributos -FileChooser.fileDateHeader.textAndMnemonic = Modificado -FileChooser.fileNameHeader.textAndMnemonic = Nombre -FileChooser.fileNameLabel.textAndMnemonic = Nombre de archivo: -FileChooser.fileSizeHeader.textAndMnemonic = Tama\u00f1o -FileChooser.fileTypeHeader.textAndMnemonic = Tipo -FileChooser.filesOfTypeLabel.textAndMnemonic = Archivos de tipo: -FileChooser.folderNameLabel.textAndMnemonic = Nombre de carpeta: -FileChooser.homeFolderToolTip.textAndMnemonic = Home -FileChooser.listViewActionLabel.textAndMnemonic = Lista -FileChooser.listViewButtonToolTip.textAndMnemonic = Lista -FileChooser.lookInLabel.textAndMnemonic = Mirar en: -FileChooser.newFolderActionLabel.textAndMnemonic = Nueva Carpeta -FileChooser.newFolderToolTip.textAndMnemonic = Crear Nueva Carpeta -FileChooser.refreshActionLabel.textAndMnemonic = Refrescar -FileChooser.saveInLabel.textAndMnemonic = Guardar en: -FileChooser.upFolderToolTip.textAndMnemonic = Subir un nivel -FileChooser.viewMenuButtonAccessibleName = Ver men\u00fa -FileChooser.viewMenuButtonToolTipText = Ver men\u00fa -FileChooser.viewMenuLabel.textAndMnemonic = Ver -FileChooser.newFolderActionLabelText = Nueva Carpeta -FileChooser.listViewActionLabelText = Lista -FileChooser.detailsViewActionLabelText = Detalles -FileChooser.refreshActionLabelText = Refrescar -FileChooser.sortMenuLabelText = Ordenar \u00edconos por -FileChooser.viewMenuLabelText = Ver -FileChooser.fileSizeKiloBytes = {0} KB -FileChooser.fileSizeMegaBytes = {0} MB -FileChooser.fileSizeGigaBytes = {0} GB -FileChooser.folderNameLabelText = Nombre de carpeta: - -error.occured = Ocurri\u00f3 un error : %error% -button.abort = Abortar -button.retry = Reintentar -button.ignore = Ignorar - -font.source = Origen de la fuente: - -#after version 1.6.7: - -menu.export = Exportar -menu.general = General -menu.language = Lenguaje - -startup.welcometo = Bienvenido a -startup.selectopen = Clickee en el \u00edcono del panel superior o arrastre el archivo SWF a esta ventana para comenzar. - -error.font.nocharacter = Fuente de origen seleccionado no contiene caracteres "%char%". - -warning.initializers = Los campos est\u00e1ticos y constantes son a menudo inicializados en el inicializador.\nEditar el valor aqu\u00ed usualmente no es suficiente! - -#after version 1.7.0u1: - -menu.tools.searchMemory = Buscar SWFs en memoria -menu.file.reload = Recargar -message.confirm.reload = Esta acci\u00f3n eliminar\u00e1 todos lo cambios no guardados y recargar\u00e1 el archivo SWF otra vez.\nDesea continuar? - -dialog.selectbkcolor.title = Seleccionar color de fondo para la visualizaci\u00f3n del SWF -button.selectbkcolor.hint = Seleccionar color de fondo - -ColorChooser.okText = OK -ColorChooser.cancelText = Cancelar -ColorChooser.resetText = Reiniciar -ColorChooser.previewText = Vista previa -ColorChooser.swatchesNameText = Muestras -ColorChooser.swatchesRecentText = Reciente: -ColorChooser.sampleText = Texto de muestra Texto de muestra - -#after version 1.7.1: - -preview.play = Reproducir -preview.pause = Pausar -preview.stop = Detener - -message.confirm.removemultiple = Est\u00e1 seguro que desea eliminar %count% art\u00edculos\n y todos los objetos que dependen de el? - -menu.tools.searchCache = Buscar cache del navegador - -#after version 1.7.2u2 - -error.trait.exists = La caracter\u00edstica con nombre "%name%" ya existe. -button.addtrait = Agregar caracter\u00edstica -button.font.embed = Incrustar... -button.yes.all = Si a todo -button.no.all = No a todo -message.font.add.exists = El caracter %char% ya existe en la etiqueta de la fuente.\nDesea reemplazarlo? - -filter.gfx = Archivos ScaleForm GFx (*.gfx) -filter.supported = Todos los tipos de archivo soportados -work.canceled = Cancelado -work.restoringControlFlow = Restaurando control de flujo -menu.advancedsettings.advancedsettings = Opciones Avanzadas -menu.recentFiles = Archivos recientes - -#after version 1.7.4 -work.restoringControlFlow.complete = Control de Flujo restaurado -message.confirm.recentFileNotFound = Archivo no encontrado. Desea removerlo de la lista de archivos recientes? -contextmenu.closeSwf = Cerrar SWF -menu.settings.autoRenameIdentifiers = Auto renombrar identificadores -menu.file.saveasexe = Guardar como ejecutable... -filter.exe = Archivos ejecutables (*.exe) - -#after version 1.8.0 -font.updateTexts = Actualizar textos - -#after version 1.8.0u1 -menu.file.close = Cerrar -menu.file.closeAll = Cerrar todos -menu.tools.otherTools = Otros -menu.tools.otherTools.clearRecentFiles = Limpiar archivos recientes -fontName.name = Nombre de fuentes para mostrar: -fontName.copyright = Derechos de autor de la fuente: -button.preview = Vista previa -button.reset = Reiniciar -errors.info = Hay INFORMATIONS en el log. Clickear para ver. -errors.warning = Hay WARNINGS en el log. Clickear para ver. - -decompilationError = Error de decompilaci\u00f3n - -disassemblingProgress.toString = toString -disassemblingProgress.reading = Leyendo -disassemblingProgress.deobfuscating = Desofuscando - -contextmenu.moveTag = Mover etiqueta a - -filter.swc = Archivo de componente SWC (*.swc) -filter.zip = Archivo comprimido ZIP (*.zip) -filter.binary = B\u00fasqueda binaria - todos los archivos (*.*) - -open.error = Error -open.error.fileNotFound = Archivo no encontrado -open.error.cannotOpen = No se puede abrir el archivo - -node.others = otros - -#after version 1.8.1 -menu.tools.search = B\u00fasqueda de texto - -#after version 1.8.1u1 -menu.tools.timeline = L\u00ednea de tiempo - -dialog.selectcolor.title = Seleccionar color -button.selectcolor.hint = Click para seleccionar color - -#default item name, will be used in following sentences -generictag.array.item = item -generictag.array.insertbeginning = Insertar %item% al comienzo -generictag.array.insertbefore = Insertar %item% antes -generictag.array.remove = Remover %item% -generictag.array.insertafter = Insertar %item% despu\u00e9s -generictag.array.insertend = Insertar %item% al final - -#after version 2.0.0 -contextmenu.expandAll = Expandir todo -binaryData.truncateWarning = %count% bytes truncados. -filter.sounds = Formatos de sonido soportados (*.wav, *.mp3) -filter.sounds.wav = Formato de archivo Wave (*.wav) -filter.sounds.mp3 = Formato comprimido MP3 (*.mp3) - -error.sound.invalid = Sonido Invalido. - -button.prev = Previo -button.next = Siguiente - -#after version 2.1.0 -message.action.playerglobal.title = Libreria necesitada PlayerGlobal -message.action.playerglobal.needed = Para la edicion directa de ActionScript 3, necesita descargar la libreria llamada "PlayerGlobal.swc" desde la pagina principal de Adobe.\r\n%adobehomepage%\r\nPresione OK para ir a la pagina de descarga. -message.action.playerglobal.place = Descargue la libreria llamada PlayerGlobal(.swc), y coloquela en el directorio\r\n%libpath%\r\n Presione OK para continuar. - -message.confirm.experimental.function = Esta funci\u00f3n es EXPERIMENTAL. Significa que no debe de confiar en los resultados y el archivo SWF puede ser no fucnional luego de guardarlo. -message.confirm.donotshowagain = No mostrar otra vez menu.import = Importar - -menu.import = Importar -menu.file.import.text = Importar texto -import.select.directory = Seleccionar directorio para importar -error.text.import = Error durante la importaci\u00f3n del texto. \u00bfDesea continuar? - -#after version 2.1.1 -contextmenu.removeWithDependencies = Remover con dependencias - -abc.action.find-usages = Buscar usos -abc.action.find-declaration = Buscar declaraciones - -contextmenu.rawEdit = Edici\u00f3n cruda -contextmenu.jumpToCharacter = Ir a caracter - -menu.settings.dumpView = Volcar view - -menu.view = Ver -menu.file.view.resources = Recursos -menu.file.view.hex = Volcado Hex - -node.header = header - -header.signature = Firma: -header.compression = Compresi\u00f3n: -header.compression.lzma = LZMA -header.compression.zlib = ZLIB -header.compression.none = Sin compresi\u00f3n -header.version = Versi\u00f3n del SWF: -header.gfx = GFX: -header.filesize = Tama\u00f1o del archivo: -header.framerate = Velocidad de fotogramas: -header.framecount = Recuento de fotogramas: -header.displayrect = Mostrar rect: -header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% twips -header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% pixels - -#after version 2.1.2 -contextmenu.saveToFile = Guardar en un archivo -contextmenu.parseActions = Analizar actions -contextmenu.parseABC = Analizar ABC -contextmenu.parseInstructions = Analizar instrucciones AVM2 - -#after version 2.1.3 -menu.deobfuscation = Desofuscaci\u00f3n -menu.file.deobfuscation.old = Estilo viejo -menu.file.deobfuscation.new = Estilo nuevo - -#after version 2.1.4 -contextmenu.openswfinside = Abrir SWF inside -binarydata.swfInside = Parece que hay un SWF dentro de la etiqueta de datos binarios. Click aqu\u00ed para cargarlo como un sub-\u00e1rbol. - -#after version 3.0.0 -button.zoomin.hint = Acercar -button.zoomout.hint = Alejar -button.zoomfit.hint = Ampliar para adaptarse -button.zoomnone.hint = Ampliar hasta 1:1 -button.snapshot.hint = Tomar captura en el portapapeles - -editorTruncateWarning = Texto truncado en la posici\u00f3n %chars% en modo depuraci\u00f3n. - -#Font name which is presented in the SWF Font tag -font.name.intag = Nombre de fuente en etiqueta: - -menu.debugger = Depurador -menu.debugger.switch = Depurador -menu.debugger.replacetrace = Reemplazar llamadas de seguimiento -menu.debugger.showlog = Mostrar registro - -message.debugger = Este depurador de SWF solo puede ser utilizado para imprimir mensajes a la ventana de registro, la consola del navegador o mediante alertas. No est\u00e1 dise\u00f1ado para caracter\u00edsticas como step code, puntos de ruptura, etc. - -contextmenu.addTag = Agregar etiqueta - -deobfuscation.comment.tryenable = Consejo: Puede intentar activando "Desofuscaci\u00f3n Autom\u00e1tica" en Ajustes -deobfuscation.comment.failed = La desofuscaci\u00f3n est\u00e1 activada pero la decompilaci\u00f3n a\u00fan falla. Si el archivo NO est\u00e1 ofuscado, desactive "Desofuscaci\u00f3n autom\u00e1tica" para obtener mejores resultados. - -#after version 4.0.2 -preview.nextframe = Siguiente marco -preview.prevframe = Marco previo -preview.gotoframe = Ir a marco... - -preview.gotoframe.dialog.title = Ir a marco -preview.gotoframe.dialog.message = Ingresar n\u00famero de marco (%min% - %max%) -preview.gotoframe.dialog.frame.error = N\u00famero de marco inv\u00e1lido. Debe ser un n\u00famero entre %min% y %max%. - -error.text.invalid.continue = Texto inv\u00e1lido: %text% en l\u00ednea %line%. Desea continuar? - -#after version 4.0.5 -contextmenu.copyTag = Copiar etiqueta a -fit = encajar -button.setAdvanceValues = Establecer valores por anticipado - -menu.tools.replace = Reemplazo de texto - -message.confirm.close = Hay cambios sin guardar. De verdad quiere cerrar {swfName}? -message.confirm.closeAll = Hay cambios sin guardar. De verdad quiere cerrar todos los archivos SWFs? - -contextmenu.exportJavaSource = Exportar c\u00f3digo Java -contextmenu.exportSwfXml = Exportar SWF como XML -contextmenu.importSwfXml = Importar SWF XML - -filter.xml = XML - -#after version 4.1.0 -contextmenu.undo = Deshacer - -text.align.left = Alineaci\u00f3n izquierda -text.align.right = Alineaci\u00f3n derecha -text.align.center = Alineaci\u00f3n centrada -text.align.justify = Justificar alineaci\u00f3n - -text.undo = Deshacer cambios - -menu.file.import.xml = Importar SWF XML -menu.file.export.xml = Exportar SWF XML - -#after version 4.1.1 -text.align.translatex.decrease = Decrementar TranslateX -text.align.translatex.increase = Incrementar TranslateX -selectPreviousTag = Seleccionar etiqueta previa -selectNextTag = Seleccionar siguiente etiqueta -button.ignoreAll = Ignorar todo -menu.file.import.symbolClass = Clase Symbol -text.toggleCase = Conmutar may\u00fasculas y min\u00fasculas - -#after version 5.0.2 -preview.loop = Bucle -menu.file.import.script = Importar scripts -contextmenu.copyTagWithDependencies = Copiar etiqueta con dependencias a -button.replaceWithTag = Reemplazar con otro caracter de etiqueta -button.resolveConstants = Resolver constantes - -#after version 5.1.0 -button.viewConstants = Ver constantes -work.exported = Exportado -button.replaceAlphaChannel = Reemplazar canal alpha... - -tagInfo.header.name = Nombre -tagInfo.header.value = Valor -tagInfo.tagType = Tipo de etiqueta -tagInfo.characterId = Identificador de caracter -tagInfo.offset = Desplazamiento -tagInfo.length = Longitud -tagInfo.bounds = L\u00edmites -tagInfo.width = Anchura -tagInfo.height = Altura -tagInfo.neededCharacters = Caracteres necesarios - -button.viewhexpcode = Ver hexadecimal con instrucciones -taginfo.header = Informaci\u00f3n b\u00e1sica de etiqueta - -tagInfo.dependentCharacters = Caracteres dependientes - -#after version 5.3.0 -header.uncompressed = Descomprimido -header.warning.unsupportedGfxCompression = GFX soporta solo contenido descomprimido o comprimido con Zlib. -header.warning.minimumZlibVersion = Compresi\u00f3n con Zlib necesita versi\u00f3n 6 o mayor de SWF. -header.warning.minimumLzmaVersion = Compresi\u00f3n con LZMA necesita versi\u00f3n 13 o mayor de SWF. - -tagInfo.codecName = Nombre del Codec -tagInfo.exportFormat = Exportar formato -tagInfo.samplingRate = Tasa de muestreo -tagInfo.stereo = Est\u00e9reo -tagInfo.sampleCount = Recuento de muestra - -filter.dmg = Archivos ejecutables Mac (*.dmg) -filter.linuxExe = Archivos ejecutables Linux - -import.script.result = %count% fueron importados. -import.script.as12warning = Importar script solo puede importar scripts AS1/2. - -error.constantPoolTooBig = La Constant pool es demasiado grande. \u00edndice=%index%, tama\u00f1o=%size% -error.image.alpha.invalid = Datos de canal alpha no v\u00e1lidos - -#after version 6.0.2 -contextmenu.saveUncompressedToFile = Guardar en archivo no comprimido -abc.traitslist.scriptinitializer = inicializador de script -menu.settings.autoOpenLoadedSWFs = Abrir los SWFs cargados mientras se reproducen - -#after version 6.1.1 -menu.file.start = Comenzar -menu.file.start.run = Ejecutar -menu.file.start.stop = Detener -menu.file.start.debug = Depurar -menu.debugging = Depurando -menu.debugging.debug = Depurar -menu.debugging.debug.stop = Detener -menu.debugging.debug.pause = Pausar -menu.debugging.debug.stepOver = Pasar por encima -menu.debugging.debug.stepInto = Entrar en -menu.debugging.debug.stepOut = Pasar por encima -menu.debugging.debug.continue = Continuar -menu.debugging.debug.stack = Pila... -menu.debugging.debug.watch = Nueva vigilancia... - -message.playerpath.notset = Proyector de Flash Player no encontrado. Por favor, configure la ruta en Configuraciones Avanzadas / Rutas (1). -message.playerpath.debug.notset = Depurador de contenido Flash Player no encontrado. Por favor, configure la ruta en Configuraciones Avanzadas / Rutas (2). -message.playerpath.lib.notset = PlayerGlobal (.SWC) no encontrado. Por favor, configure su ruta en Configuraciones Avanzadas / Rutas (3). - -debugpanel.header = Depurando - -variables.header.registers = Registros -variables.header.locals = Locales -variables.header.arguments = Argumentos -variables.header.scopeChain = Cadena de alcance -variables.column.name = Nombre -variables.column.type = Tipo -variables.column.value = Valor - -callStack.header = Pila de llamadas -callStack.header.file = Archivo -callStack.header.line = L\u00ednea - -stack.header = Pila -stack.header.item = Item - -constantpool.header = Agrupaci\u00f3n de constantes -constantpool.header.id = Identificaci\u00f3n -constantpool.header.value = Valor - -work.running = Ejecutando -work.debugging = Depurando -work.debugging.instrumenting = Preparando SWF para depuraci\u00f3n -work.breakat = Detenerse a\u0020 -work.halted = Depuraci\u00f3n iniciada, ejecuci\u00f3n interrumpida. Agregue puntos de ruptura y haga click en Continuar (F5) para resumir la ejecuci\u00f3n. - -debuglog.header = Registro -debuglog.button.clear = Despejar - -#after 7.0.1 -work.debugging.wait = Esperando por la conecci\u00f3n del proyector de depuraci\u00f3n de Flash - -error.debug.listen = No se puede escuchar en el puerto %port%. Puede haber otro depurador de Flash ejecutandose. - -debug.break.reason.unknown = (Desconocido) -debug.break.reason.breakpoint = (Punto de ruptura) -debug.break.reason.watch = (Vigilante) -debug.break.reason.fault = (Falla) -debug.break.reason.stopRequest = (Detener pedido) -debug.break.reason.step = (Paso) -debug.break.reason.halt = (Interrumpir) -debug.break.reason.scriptLoaded = (Script cargado) - -menu.file.start.debugpcode = Depurar P-code - -#after 7.1.2 -button.replaceNoFill = Replace - L\u00edmites de actualizaci\u00f3n... -message.warning.svgImportExperimental = No todas las catacter\u00edsticas de SVG est\u00e1n soportadas. Solo el modo de llenado de color s\u00f3lido es soportado. Por favor, compruebe la anotaciones despu\u00e9s de importar. - -message.imported.swf = El archivo utiliza recursos de un archivo SWF importado: %url% Quiere que los recursos sean cargados desde dicha URL? -message.imported.swf.manually = No se puede cargar el SWF importado %url% El archivo o URL no existe. Desea seleccionar un archivo local? - -message.warning.hexViewNotUpToDate = Vista Hexadecimal no al d\u00eda. Por favor, guarde y recargue el archivo para actualizar Vista Hexadecimal. -message.font.replace.updateTexts = Algunos caracteres fueron reemplazados. Desea actualizar los textos existentes? - -menu.settings.simplifyExpressions = Simplificar expresiones - -#after 8.0.1 -menu.recentFiles.empty = La lista de archivos recientes est\u00e1 vac\u00eda -message.warning.outOfMemory32BitJre = Un error de Memoria insuficiente a sucedido. Usted est\u00e1 utilizando una versi\u00f3n de Java de 32 bit en un sistema de 64 bit. Por favor, utilice Java de 64 bit. - -menu.file.reloadAll = Recargar todo -message.confirm.reloadAll = Esta acci\u00f3n cancela todos los cambios no guardados en todos los archivos SWF y recarga toda la aplicaci\u00f3n nuevamente. Desea continuar? -export.script.singleFilePallelModeWarning = La exportaci\u00f3n de escritura de una sola fila no est\u00e1 soportada con la aceleraci\u00f3n permitida en paralelo - -button.showOriginalBytesInPcodeHex = Mostrar bytes originales -button.remove = Remover +# Copyright (C) 2010-2016 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 . + +menu.file = Archivo +menu.file.open = Abrir... +menu.file.save = Guardar +menu.file.saveas = Guardar como... +menu.file.export.fla = Exportar a FLA +menu.file.export.all = Exportar todas las partes +menu.file.export.selection = Exportar selecci\u00f3n +menu.file.exit = Salir + +menu.tools = Herramientas +menu.tools.searchas = Buscar todo el ActionScript... +menu.tools.proxy = Proxy +menu.tools.deobfuscation = Desofuscaci\u00f3n +menu.tools.deobfuscation.pcode = Desofuscaci\u00f3n de PCode... +menu.tools.deobfuscation.globalrename = Renombrar identificador globalmente +menu.tools.deobfuscation.renameinvalid = Renombrar identificadores inv\u00e1lidos +menu.tools.gotoDocumentClass = Ir al document class + +menu.settings = Ajustes +menu.settings.autodeobfuscation = Desofuscaci\u00f3n autom\u00e1tica +menu.settings.internalflashviewer = Usar un visor de flash propio +menu.settings.parallelspeedup = Aceleraci\u00f3n en paralelo +menu.settings.disabledecompilation = Inhabilitar decompilaci\u00f3n (solo desensamblado) +menu.settings.addtocontextmenu = Agregar FFDec al men\u00fa contextual de archivos SWF +menu.settings.language = Cambiar lenguaje +menu.settings.cacheOnDisk = Usar almacenamiento de cach\u00e9 en disco +menu.settings.gotoMainClassOnStartup = Resaltar el document class al iniciar + +menu.help = Ayuda +menu.help.checkupdates = Comprobar actualizaciones... +menu.help.helpus = Ayudanos! +menu.help.homepage = Visitar la p\u00e1gina principal +menu.help.about = Acerca de... + +contextmenu.remove = Remover + +button.save = Guardar +button.edit = Editar +button.cancel = Cancelar +button.replace = Reemplazar... + +notavailonthisplatform = La vista previa de este objeto no est\u00e1 disponible en esta plataforma. (solo Windows) + +swfpreview = Vista previa del SWF +swfpreview.internal = Vista previa del SWF (Visor interno) + +parameters = Par\u00e1metros + +rename.enternew = Ingresar nuevo nombre: + +rename.finished.identifier = Identificador renombrado. +rename.finished.multiname = %count% multinombres(s) renombrado. + +node.texts = textos +node.images = im\u00e1genes +node.movies = pel\u00edculas +node.sounds = sonidos +node.binaryData = datosbinarios +node.fonts = fuentes +node.sprites = sprites +node.shapes = formas +node.morphshapes = morphshapes +node.buttons = botones +node.frames = marcos +node.scripts = scripts + +message.warning = Cuidado +message.confirm.experimental = El siguiente procedimiento puede da\u00f1ar el archivo SWF e inutilizar su reproducci\u00f3n.\r\nUSESE BAJO SU PROPIO RIESGO. Desea continuar? +message.confirm.parallel = El paralelismo puede acelerar la carga y la descompilaci\u00f3n pero requerir m\u00e1s memoria. +message.confirm.on = Desea encenderlo? +message.confirm.off = Desea apagarlo? +message.confirm = Confirmar + +message.confirm.autodeobfuscate = La desofuscaci\u00f3n autom\u00e1tica es una manera de descompilar el c\u00f3digo ofuscado.\r\nLa desofuscaci\u00f3n conduce a una descompilaci\u00f3n m\u00e1s lenta y a eliminar algo de c\u00f3digo muerto.\r\nSi el c\u00f3digo no est\u00e1 ofuscado, es mejor deshabilitar la autodesofuscaci\u00f3n. + +message.parallel = Paralelismo +message.trait.saved = Rasgo guardado existosamente + +message.constant.new.string = La cadena "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarla? +message.constant.new.string.title = Agregar cadena +message.constant.new.integer = El entero "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarlo? +message.constant.new.integer.title = Agregar entero +message.constant.new.unsignedinteger = El entero no signado "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarlo? +message.constant.new.unsignedinteger.title = Agregar entero no signado +message.constant.new.double = El entero doble "%value%" no est\u00e1 presente en la tabla de constantes. Desea agregarlo? +message.constant.new.double.title = Agregar entero doble + +work.buffering = Buffering +work.waitingfordissasembly = Esperando el desensamblado +work.gettinghilights = Adquiriendo resaltadores +work.disassembling = Desensamblando +work.exporting = Exportando +work.searching = Buscando +work.renaming = Renombrando +work.exporting.fla = Exportando FLA +work.renaming.identifiers = Renombrando identificadores +work.deobfuscating = Desofuscando +work.decompiling = Decompilando +work.gettingvariables = Adquiriendo variables +work.reading.swf = Leyendo SWF +work.creatingwindow = Creando ventana +work.buildingscripttree = Generando \u00e1rbol de script Building script tree + +work.deobfuscating.complete = Desofuscaci\u00f3n completada + +message.search.notfound = Cadena "%searchtext%" no encontrada. +message.search.notfound.title = No encontrado + +message.rename.notfound.multiname = No se encontr\u00f3 ning\u00fan multiname bajo el cursor +message.rename.notfound.identifier = No se encontr\u00f3 ning\u00fan identificador bajo el cursor +message.rename.notfound.title = No encontrado +message.rename.renamed = Identificadores renombrados: %count% + +filter.images = Im\u00e1genes (%extensions%) +filter.fla = Documento %version% (*.fla) +filter.xfl = Documento no comprimido %version% (*.xfl) +filter.swf = Archivos SWF (*.swf) + +error = Error +error.image.invalid = Im\u00e1gen inv\u00e1lida. + +error.text.invalid = Texto inv\u00e1lido: %text% en la l\u00ednea %line% +error.file.save = No se puede guardar el archivo +error.file.write = No se puede escribir al archivo +error.export = Error durante la exportaci\u00f3n + +export.select.directory = Seleccione directorio para exportar +export.finishedin = Exportado en %time% + +update.check.title = Chequeo de actualizaci\u00f3n +update.check.nonewversion = No hay versi\u00f3n nueva disponible. + +message.helpus = Por favor, visite\r\n%url%\r\npara m\u00e1s detalles. +message.homepage = Visite la p\u00e1gina principal en: \r\n%url% + +proxy = Proxy +proxy.start = Comenzar proxy +proxy.stop = Detener proxy +proxy.show = Mostrar proxy +exit = Salir + +panel.disassembled = Fuente P-code +panel.decompiled = Fuente ActionScript + +search.info = Buscar por "%text%" : +search.script = Script + +constants = Constantes +traits = Rasgos + +pleasewait = Espere por favor + +abc.detail.methodtrait = M\u00e9todo/Getter/Setter Rasgo +abc.detail.unsupported = - +abc.detail.slotconsttrait = Slot/Const Rasgo +abc.detail.traitname = Nombre: + +abc.detail.body.params.maxstack = Pila m\u00e1xima: +abc.detail.body.params.localregcount = Contador de registros locales: +abc.detail.body.params.minscope = Profundidad de alcance m\u00ednima: +abc.detail.body.params.maxscope = Profundidad de alcance m\u00e1xima: +abc.detail.body.params.autofill = Auto rellenado al salvar c\u00f3dig (AJUSTE GLOBAL) +abc.detail.body.params.autofill.experimental = ...EXPERIMENTAL + +abc.detail.methodinfo.methodindex = Indice de m\u00e9todo: +abc.detail.methodinfo.parameters = Par\u00e1metros: +abc.detail.methodinfo.returnvalue = Tipo de valor de retorno: + +error.methodinfo.params = Error de pa\u0155ametro MethodInfo +error.methodinfo.returnvalue = Error de retorno de tipo MethodInfo + +abc.detail.methodinfo = MethodInfo +abc.detail.body.code = C\u00f3digo de MethodBody +abc.detail.body.params = Par\u00e1metros de MethodBody + +abc.detail.slotconst.typevalue = Tipo y valor: + +error.slotconst.typevalue = Error de valor de tipo SlotConst + +message.autofill.failed = No se puede obtener las estad\u00edsticas de c\u00f3digo para los par\u00e1metros de cuerpo autom\u00e1ticos.\r\nDestilde auto-llenado para evitar este mensaje. +info.selecttrait = Seleccione la clase y clickee un atributo en el c\u00f3digo Actionscript para editarlo. + +button.viewgraph = Ver grafo +button.viewhex = Ver en hexa + +abc.traitslist.instanceinitializer = inicializador de instancia +abc.traitslist.classinitializer = inicializador de clase + +action.edit.experimental = (Experimental) + +message.action.saved = C\u00f3digo guardado exitosamente + +error.action.save = %error% en la l\u00ednea %line% + +message.confirm.remove = Est\u00e1 seguro que desea remover %item% \n y todos los objetos que dependen de \u00e9l? + +#after version 1.6.5u1: + +button.ok = OK +button.cancel = Cancelar + +font.name = Nombre de fuente: +font.isbold = Es negrita: +font.isitalic = Es it\u00e1lica: +font.ascent = Ascendente: +font.descent = Descendente: +font.leading = Destacado: +font.characters = Caract\u00e9r: +font.characters.add = Agregar caracteres: +value.unknown = ? + +yes = si +no = no + +errors.present = Hay ERRORES en el log. Clickear para ver. +errors.none = No hay errores en el log + +#after version 1.6.6: + +dialog.message.title = Mensaje +dialog.select.title = Seleccione una opci\u00f3n + +button.yes = Si +button.no = No + +FileChooser.openButtonText = Abrir +FileChooser.openButtonToolTipText = Abrir +FileChooser.lookInLabelText = Mirar en: +FileChooser.acceptAllFileFilterText = Todos los archivos +FileChooser.filesOfTypeLabelText = Archivos de tipo: +FileChooser.fileNameLabelText = Nombre de archivo: +FileChooser.listViewButtonToolTipText = Lista +FileChooser.listViewButtonAccessibleName = Lista +FileChooser.detailsViewButtonToolTipText = Detales +FileChooser.detailsViewButtonAccessibleName = Detalles +FileChooser.upFolderToolTipText = Subir un nivel +FileChooser.upFolderAccessibleName = Subir un nivel +FileChooser.homeFolderToolTipText = Home +FileChooser.homeFolderAccessibleName = Home +FileChooser.fileNameHeaderText = Nombre +FileChooser.fileSizeHeaderText = Tama\u00f1o +FileChooser.fileTypeHeaderText = Tipo +FileChooser.fileDateHeaderText = Fecha +FileChooser.fileAttrHeaderText = Atributos +FileChooser.openDialogTitleText = Abrir +FileChooser.directoryDescriptionText = Directorio +FileChooser.directoryOpenButtonText = Abrir +FileChooser.directoryOpenButtonToolTipText = Abrir el directorio seleccionado +FileChooser.fileDescriptionText = Archivo gen\u00e9rico +FileChooser.helpButtonText = Ayuda +FileChooser.helpButtonToolTipText = Ayuda de FileChooser +FileChooser.newFolderAccessibleName = Nueva carpeta +FileChooser.newFolderErrorText = Error creando nueva carpeta +FileChooser.newFolderToolTipText = Crear nueva carpeta +FileChooser.other.newFolder = NuevaCarpeta +FileChooser.other.newFolder.subsequent = NuevaCarpeta.{0} +FileChooser.win32.newFolder = Nueva Carpeta +FileChooser.win32.newFolder.subsequent = Nueva Carpeta ({0}) +FileChooser.saveButtonText = Guarda +FileChooser.saveButtonToolTipText = Guardar archivo seleccionado +FileChooser.saveDialogTitleText = Guardar +FileChooser.saveInLabelText = Guardar en: +FileChooser.updateButtonText = Actualizar +FileChooser.updateButtonToolTipText = Actualizar listado de directorio + +#after version 1.6.6u2: + +FileChooser.detailsViewActionLabel.textAndMnemonic = Detalles +FileChooser.detailsViewButtonToolTip.textAndMnemonic = Detalles +FileChooser.fileAttrHeader.textAndMnemonic = Atributos +FileChooser.fileDateHeader.textAndMnemonic = Modificado +FileChooser.fileNameHeader.textAndMnemonic = Nombre +FileChooser.fileNameLabel.textAndMnemonic = Nombre de archivo: +FileChooser.fileSizeHeader.textAndMnemonic = Tama\u00f1o +FileChooser.fileTypeHeader.textAndMnemonic = Tipo +FileChooser.filesOfTypeLabel.textAndMnemonic = Archivos de tipo: +FileChooser.folderNameLabel.textAndMnemonic = Nombre de carpeta: +FileChooser.homeFolderToolTip.textAndMnemonic = Home +FileChooser.listViewActionLabel.textAndMnemonic = Lista +FileChooser.listViewButtonToolTip.textAndMnemonic = Lista +FileChooser.lookInLabel.textAndMnemonic = Mirar en: +FileChooser.newFolderActionLabel.textAndMnemonic = Nueva Carpeta +FileChooser.newFolderToolTip.textAndMnemonic = Crear Nueva Carpeta +FileChooser.refreshActionLabel.textAndMnemonic = Refrescar +FileChooser.saveInLabel.textAndMnemonic = Guardar en: +FileChooser.upFolderToolTip.textAndMnemonic = Subir un nivel +FileChooser.viewMenuButtonAccessibleName = Ver men\u00fa +FileChooser.viewMenuButtonToolTipText = Ver men\u00fa +FileChooser.viewMenuLabel.textAndMnemonic = Ver +FileChooser.newFolderActionLabelText = Nueva Carpeta +FileChooser.listViewActionLabelText = Lista +FileChooser.detailsViewActionLabelText = Detalles +FileChooser.refreshActionLabelText = Refrescar +FileChooser.sortMenuLabelText = Ordenar \u00edconos por +FileChooser.viewMenuLabelText = Ver +FileChooser.fileSizeKiloBytes = {0} KB +FileChooser.fileSizeMegaBytes = {0} MB +FileChooser.fileSizeGigaBytes = {0} GB +FileChooser.folderNameLabelText = Nombre de carpeta: + +error.occured = Ocurri\u00f3 un error : %error% +button.abort = Abortar +button.retry = Reintentar +button.ignore = Ignorar + +font.source = Origen de la fuente: + +#after version 1.6.7: + +menu.export = Exportar +menu.general = General +menu.language = Lenguaje + +startup.welcometo = Bienvenido a +startup.selectopen = Clickee en el \u00edcono del panel superior o arrastre el archivo SWF a esta ventana para comenzar. + +error.font.nocharacter = Fuente de origen seleccionado no contiene caracteres "%char%". + +warning.initializers = Los campos est\u00e1ticos y constantes son a menudo inicializados en el inicializador.\nEditar el valor aqu\u00ed usualmente no es suficiente! + +#after version 1.7.0u1: + +menu.tools.searchMemory = Buscar SWFs en memoria +menu.file.reload = Recargar +message.confirm.reload = Esta acci\u00f3n eliminar\u00e1 todos lo cambios no guardados y recargar\u00e1 el archivo SWF otra vez.\nDesea continuar? + +dialog.selectbkcolor.title = Seleccionar color de fondo para la visualizaci\u00f3n del SWF +button.selectbkcolor.hint = Seleccionar color de fondo + +ColorChooser.okText = OK +ColorChooser.cancelText = Cancelar +ColorChooser.resetText = Reiniciar +ColorChooser.previewText = Vista previa +ColorChooser.swatchesNameText = Muestras +ColorChooser.swatchesRecentText = Reciente: +ColorChooser.sampleText = Texto de muestra Texto de muestra + +#after version 1.7.1: + +preview.play = Reproducir +preview.pause = Pausar +preview.stop = Detener + +message.confirm.removemultiple = Est\u00e1 seguro que desea eliminar %count% art\u00edculos\n y todos los objetos que dependen de el? + +menu.tools.searchCache = Buscar cache del navegador + +#after version 1.7.2u2 + +error.trait.exists = La caracter\u00edstica con nombre "%name%" ya existe. +button.addtrait = Agregar caracter\u00edstica +button.font.embed = Incrustar... +button.yes.all = Si a todo +button.no.all = No a todo +message.font.add.exists = El caracter %char% ya existe en la etiqueta de la fuente.\nDesea reemplazarlo? + +filter.gfx = Archivos ScaleForm GFx (*.gfx) +filter.supported = Todos los tipos de archivo soportados +work.canceled = Cancelado +work.restoringControlFlow = Restaurando control de flujo +menu.advancedsettings.advancedsettings = Opciones Avanzadas +menu.recentFiles = Archivos recientes + +#after version 1.7.4 +work.restoringControlFlow.complete = Control de Flujo restaurado +message.confirm.recentFileNotFound = Archivo no encontrado. Desea removerlo de la lista de archivos recientes? +contextmenu.closeSwf = Cerrar SWF +menu.settings.autoRenameIdentifiers = Auto renombrar identificadores +menu.file.saveasexe = Guardar como ejecutable... +filter.exe = Archivos ejecutables (*.exe) + +#after version 1.8.0 +font.updateTexts = Actualizar textos + +#after version 1.8.0u1 +menu.file.close = Cerrar +menu.file.closeAll = Cerrar todos +menu.tools.otherTools = Otros +menu.tools.otherTools.clearRecentFiles = Limpiar archivos recientes +fontName.name = Nombre de fuentes para mostrar: +fontName.copyright = Derechos de autor de la fuente: +button.preview = Vista previa +button.reset = Reiniciar +errors.info = Hay INFORMATIONS en el log. Clickear para ver. +errors.warning = Hay WARNINGS en el log. Clickear para ver. + +decompilationError = Error de decompilaci\u00f3n + +disassemblingProgress.toString = toString +disassemblingProgress.reading = Leyendo +disassemblingProgress.deobfuscating = Desofuscando + +contextmenu.moveTag = Mover etiqueta a + +filter.swc = Archivo de componente SWC (*.swc) +filter.zip = Archivo comprimido ZIP (*.zip) +filter.binary = B\u00fasqueda binaria - todos los archivos (*.*) + +open.error = Error +open.error.fileNotFound = Archivo no encontrado +open.error.cannotOpen = No se puede abrir el archivo + +node.others = otros + +#after version 1.8.1 +menu.tools.search = B\u00fasqueda de texto + +#after version 1.8.1u1 +menu.tools.timeline = L\u00ednea de tiempo + +dialog.selectcolor.title = Seleccionar color +button.selectcolor.hint = Click para seleccionar color + +#default item name, will be used in following sentences +generictag.array.item = item +generictag.array.insertbeginning = Insertar %item% al comienzo +generictag.array.insertbefore = Insertar %item% antes +generictag.array.remove = Remover %item% +generictag.array.insertafter = Insertar %item% despu\u00e9s +generictag.array.insertend = Insertar %item% al final + +#after version 2.0.0 +contextmenu.expandAll = Expandir todo +binaryData.truncateWarning = %count% bytes truncados. +filter.sounds = Formatos de sonido soportados (*.wav, *.mp3) +filter.sounds.wav = Formato de archivo Wave (*.wav) +filter.sounds.mp3 = Formato comprimido MP3 (*.mp3) + +error.sound.invalid = Sonido Invalido. + +button.prev = Previo +button.next = Siguiente + +#after version 2.1.0 +message.action.playerglobal.title = Libreria necesitada PlayerGlobal +message.action.playerglobal.needed = Para la edicion directa de ActionScript 3, necesita descargar la libreria llamada "PlayerGlobal.swc" desde la pagina principal de Adobe.\r\n%adobehomepage%\r\nPresione OK para ir a la pagina de descarga. +message.action.playerglobal.place = Descargue la libreria llamada PlayerGlobal(.swc), y coloquela en el directorio\r\n%libpath%\r\n Presione OK para continuar. + +message.confirm.experimental.function = Esta funci\u00f3n es EXPERIMENTAL. Significa que no debe de confiar en los resultados y el archivo SWF puede ser no fucnional luego de guardarlo. +message.confirm.donotshowagain = No mostrar otra vez menu.import = Importar + +menu.import = Importar +menu.file.import.text = Importar texto +import.select.directory = Seleccionar directorio para importar +error.text.import = Error durante la importaci\u00f3n del texto. \u00bfDesea continuar? + +#after version 2.1.1 +contextmenu.removeWithDependencies = Remover con dependencias + +abc.action.find-usages = Buscar usos +abc.action.find-declaration = Buscar declaraciones + +contextmenu.rawEdit = Edici\u00f3n cruda +contextmenu.jumpToCharacter = Ir a caracter + +menu.settings.dumpView = Volcar view + +menu.view = Ver +menu.file.view.resources = Recursos +menu.file.view.hex = Volcado Hex + +node.header = header + +header.signature = Firma: +header.compression = Compresi\u00f3n: +header.compression.lzma = LZMA +header.compression.zlib = ZLIB +header.compression.none = Sin compresi\u00f3n +header.version = Versi\u00f3n del SWF: +header.gfx = GFX: +header.filesize = Tama\u00f1o del archivo: +header.framerate = Velocidad de fotogramas: +header.framecount = Recuento de fotogramas: +header.displayrect = Mostrar rect: +header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% twips +header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% pixels + +#after version 2.1.2 +contextmenu.saveToFile = Guardar en un archivo +contextmenu.parseActions = Analizar actions +contextmenu.parseABC = Analizar ABC +contextmenu.parseInstructions = Analizar instrucciones AVM2 + +#after version 2.1.3 +menu.deobfuscation = Desofuscaci\u00f3n +menu.file.deobfuscation.old = Estilo viejo +menu.file.deobfuscation.new = Estilo nuevo + +#after version 2.1.4 +contextmenu.openswfinside = Abrir SWF inside +binarydata.swfInside = Parece que hay un SWF dentro de la etiqueta de datos binarios. Click aqu\u00ed para cargarlo como un sub-\u00e1rbol. + +#after version 3.0.0 +button.zoomin.hint = Acercar +button.zoomout.hint = Alejar +button.zoomfit.hint = Ampliar para adaptarse +button.zoomnone.hint = Ampliar hasta 1:1 +button.snapshot.hint = Tomar captura en el portapapeles + +editorTruncateWarning = Texto truncado en la posici\u00f3n %chars% en modo depuraci\u00f3n. + +#Font name which is presented in the SWF Font tag +font.name.intag = Nombre de fuente en etiqueta: + +menu.debugger = Depurador +menu.debugger.switch = Depurador +menu.debugger.replacetrace = Reemplazar llamadas de seguimiento +menu.debugger.showlog = Mostrar registro + +message.debugger = Este depurador de SWF solo puede ser utilizado para imprimir mensajes a la ventana de registro, la consola del navegador o mediante alertas. No est\u00e1 dise\u00f1ado para caracter\u00edsticas como step code, puntos de ruptura, etc. + +contextmenu.addTag = Agregar etiqueta + +deobfuscation.comment.tryenable = Consejo: Puede intentar activando "Desofuscaci\u00f3n Autom\u00e1tica" en Ajustes +deobfuscation.comment.failed = La desofuscaci\u00f3n est\u00e1 activada pero la decompilaci\u00f3n a\u00fan falla. Si el archivo NO est\u00e1 ofuscado, desactive "Desofuscaci\u00f3n autom\u00e1tica" para obtener mejores resultados. + +#after version 4.0.2 +preview.nextframe = Siguiente marco +preview.prevframe = Marco previo +preview.gotoframe = Ir a marco... + +preview.gotoframe.dialog.title = Ir a marco +preview.gotoframe.dialog.message = Ingresar n\u00famero de marco (%min% - %max%) +preview.gotoframe.dialog.frame.error = N\u00famero de marco inv\u00e1lido. Debe ser un n\u00famero entre %min% y %max%. + +error.text.invalid.continue = Texto inv\u00e1lido: %text% en l\u00ednea %line%. Desea continuar? + +#after version 4.0.5 +contextmenu.copyTag = Copiar etiqueta a +fit = encajar +button.setAdvanceValues = Establecer valores por anticipado + +menu.tools.replace = Reemplazo de texto + +message.confirm.close = Hay cambios sin guardar. De verdad quiere cerrar {swfName}? +message.confirm.closeAll = Hay cambios sin guardar. De verdad quiere cerrar todos los archivos SWFs? + +contextmenu.exportJavaSource = Exportar c\u00f3digo Java +contextmenu.exportSwfXml = Exportar SWF como XML +contextmenu.importSwfXml = Importar SWF XML + +filter.xml = XML + +#after version 4.1.0 +contextmenu.undo = Deshacer + +text.align.left = Alineaci\u00f3n izquierda +text.align.right = Alineaci\u00f3n derecha +text.align.center = Alineaci\u00f3n centrada +text.align.justify = Justificar alineaci\u00f3n + +text.undo = Deshacer cambios + +menu.file.import.xml = Importar SWF XML +menu.file.export.xml = Exportar SWF XML + +#after version 4.1.1 +text.align.translatex.decrease = Decrementar TranslateX +text.align.translatex.increase = Incrementar TranslateX +selectPreviousTag = Seleccionar etiqueta previa +selectNextTag = Seleccionar siguiente etiqueta +button.ignoreAll = Ignorar todo +menu.file.import.symbolClass = Clase Symbol +text.toggleCase = Conmutar may\u00fasculas y min\u00fasculas + +#after version 5.0.2 +preview.loop = Bucle +menu.file.import.script = Importar scripts +contextmenu.copyTagWithDependencies = Copiar etiqueta con dependencias a +button.replaceWithTag = Reemplazar con otro caracter de etiqueta +button.resolveConstants = Resolver constantes + +#after version 5.1.0 +button.viewConstants = Ver constantes +work.exported = Exportado +button.replaceAlphaChannel = Reemplazar canal alpha... + +tagInfo.header.name = Nombre +tagInfo.header.value = Valor +tagInfo.tagType = Tipo de etiqueta +tagInfo.characterId = Identificador de caracter +tagInfo.offset = Desplazamiento +tagInfo.length = Longitud +tagInfo.bounds = L\u00edmites +tagInfo.width = Anchura +tagInfo.height = Altura +tagInfo.neededCharacters = Caracteres necesarios + +button.viewhexpcode = Ver hexadecimal con instrucciones +taginfo.header = Informaci\u00f3n b\u00e1sica de etiqueta + +tagInfo.dependentCharacters = Caracteres dependientes + +#after version 5.3.0 +header.uncompressed = Descomprimido +header.warning.unsupportedGfxCompression = GFX soporta solo contenido descomprimido o comprimido con Zlib. +header.warning.minimumZlibVersion = Compresi\u00f3n con Zlib necesita versi\u00f3n 6 o mayor de SWF. +header.warning.minimumLzmaVersion = Compresi\u00f3n con LZMA necesita versi\u00f3n 13 o mayor de SWF. + +tagInfo.codecName = Nombre del Codec +tagInfo.exportFormat = Exportar formato +tagInfo.samplingRate = Tasa de muestreo +tagInfo.stereo = Est\u00e9reo +tagInfo.sampleCount = Recuento de muestra + +filter.dmg = Archivos ejecutables Mac (*.dmg) +filter.linuxExe = Archivos ejecutables Linux + +import.script.result = %count% fueron importados. +import.script.as12warning = Importar script solo puede importar scripts AS1/2. + +error.constantPoolTooBig = La Constant pool es demasiado grande. \u00edndice=%index%, tama\u00f1o=%size% +error.image.alpha.invalid = Datos de canal alpha no v\u00e1lidos + +#after version 6.0.2 +contextmenu.saveUncompressedToFile = Guardar en archivo no comprimido +abc.traitslist.scriptinitializer = inicializador de script +menu.settings.autoOpenLoadedSWFs = Abrir los SWFs cargados mientras se reproducen + +#after version 6.1.1 +menu.file.start = Comenzar +menu.file.start.run = Ejecutar +menu.file.start.stop = Detener +menu.file.start.debug = Depurar +menu.debugging = Depurando +menu.debugging.debug = Depurar +menu.debugging.debug.stop = Detener +menu.debugging.debug.pause = Pausar +menu.debugging.debug.stepOver = Pasar por encima +menu.debugging.debug.stepInto = Entrar en +menu.debugging.debug.stepOut = Pasar por encima +menu.debugging.debug.continue = Continuar +menu.debugging.debug.stack = Pila... +menu.debugging.debug.watch = Nueva vigilancia... + +message.playerpath.notset = Proyector de Flash Player no encontrado. Por favor, configure la ruta en Configuraciones Avanzadas / Rutas (1). +message.playerpath.debug.notset = Depurador de contenido Flash Player no encontrado. Por favor, configure la ruta en Configuraciones Avanzadas / Rutas (2). +message.playerpath.lib.notset = PlayerGlobal (.SWC) no encontrado. Por favor, configure su ruta en Configuraciones Avanzadas / Rutas (3). + +debugpanel.header = Depurando + +variables.header.registers = Registros +variables.header.locals = Locales +variables.header.arguments = Argumentos +variables.header.scopeChain = Cadena de alcance +variables.column.name = Nombre +variables.column.type = Tipo +variables.column.value = Valor + +callStack.header = Pila de llamadas +callStack.header.file = Archivo +callStack.header.line = L\u00ednea + +stack.header = Pila +stack.header.item = Item + +constantpool.header = Agrupaci\u00f3n de constantes +constantpool.header.id = Identificaci\u00f3n +constantpool.header.value = Valor + +work.running = Ejecutando +work.debugging = Depurando +work.debugging.instrumenting = Preparando SWF para depuraci\u00f3n +work.breakat = Detenerse a\u0020 +work.halted = Depuraci\u00f3n iniciada, ejecuci\u00f3n interrumpida. Agregue puntos de ruptura y haga click en Continuar (F5) para resumir la ejecuci\u00f3n. + +debuglog.header = Registro +debuglog.button.clear = Despejar + +#after 7.0.1 +work.debugging.wait = Esperando por la conecci\u00f3n del proyector de depuraci\u00f3n de Flash + +error.debug.listen = No se puede escuchar en el puerto %port%. Puede haber otro depurador de Flash ejecutandose. + +debug.break.reason.unknown = (Desconocido) +debug.break.reason.breakpoint = (Punto de ruptura) +debug.break.reason.watch = (Vigilante) +debug.break.reason.fault = (Falla) +debug.break.reason.stopRequest = (Detener pedido) +debug.break.reason.step = (Paso) +debug.break.reason.halt = (Interrumpir) +debug.break.reason.scriptLoaded = (Script cargado) + +menu.file.start.debugpcode = Depurar P-code + +#after 7.1.2 +button.replaceNoFill = Replace - L\u00edmites de actualizaci\u00f3n... +message.warning.svgImportExperimental = No todas las catacter\u00edsticas de SVG est\u00e1n soportadas. Solo el modo de llenado de color s\u00f3lido es soportado. Por favor, compruebe la anotaciones despu\u00e9s de importar. + +message.imported.swf = El archivo utiliza recursos de un archivo SWF importado: %url% Quiere que los recursos sean cargados desde dicha URL? +message.imported.swf.manually = No se puede cargar el SWF importado %url% El archivo o URL no existe. Desea seleccionar un archivo local? + +message.warning.hexViewNotUpToDate = Vista Hexadecimal no al d\u00eda. Por favor, guarde y recargue el archivo para actualizar Vista Hexadecimal. +message.font.replace.updateTexts = Algunos caracteres fueron reemplazados. Desea actualizar los textos existentes? + +menu.settings.simplifyExpressions = Simplificar expresiones + +#after 8.0.1 +menu.recentFiles.empty = La lista de archivos recientes est\u00e1 vac\u00eda +message.warning.outOfMemory32BitJre = Un error de Memoria insuficiente a sucedido. Usted est\u00e1 utilizando una versi\u00f3n de Java de 32 bit en un sistema de 64 bit. Por favor, utilice Java de 64 bit. + +menu.file.reloadAll = Recargar todo +message.confirm.reloadAll = Esta acci\u00f3n cancela todos los cambios no guardados en todos los archivos SWF y recarga toda la aplicaci\u00f3n nuevamente. Desea continuar? +export.script.singleFilePallelModeWarning = La exportaci\u00f3n de escritura de una sola fila no est\u00e1 soportada con la aceleraci\u00f3n permitida en paralelo + +button.showOriginalBytesInPcodeHex = Mostrar bytes originales +button.remove = Remover diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_it.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_it.properties index 83f1fd874..d37651c6e 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_it.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_it.properties @@ -1,722 +1,722 @@ -# Copyright (C) 2010-2016 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 . - -menu.file = File -menu.file.open = Apri... -menu.file.save = Salva -menu.file.saveas = Salva come... -menu.file.export.fla = Esporta come FLA -menu.file.export.all = Esporta tutte le parti -menu.file.export.selection = Esporta selezione -menu.file.exit = Esci - -menu.tools = Strumenti -menu.tools.searchas = Cerca in tutti gli ActionScript... -menu.tools.proxy = Proxy -menu.tools.deobfuscation = Deoffuscamento -menu.tools.deobfuscation.pcode = Deoffuscamento P-code... -menu.tools.deobfuscation.globalrename = Rinomina identificatore globalmente -menu.tools.deobfuscation.renameinvalid = Rinomina identificatori non validi -menu.tools.gotoDocumentClass = Vai a document class - -menu.settings = Impostazioni -menu.settings.autodeobfuscation = Deoffuscamento automatico -menu.settings.internalflashviewer = Usa visualizzatore Flash incorporato -menu.settings.parallelspeedup = Accelerazione parallela -menu.settings.disabledecompilation = Disattiva la decompilazione (solo disassembly) -menu.settings.addtocontextmenu = Mostra FFDec nel menu contestuale per file SWF -menu.settings.language = Cambia la lingua -menu.settings.cacheOnDisk = Utilizza la cache su disco -menu.settings.gotoMainClassOnStartup = Evidenzia la document class all'avvio - -menu.help = Aiuto -menu.help.checkupdates = Controllo aggiornamenti... -menu.help.helpus = Dateci una mano! -menu.help.homepage = Visita il sito web -menu.help.about = Informazioni su... - -contextmenu.remove = Rimuovi - -button.save = Salva -button.edit = Modifica -button.cancel = Annulla -button.replace = Sostituisci... - -notavailonthisplatform = L'anteprima di questo oggetto \u00e8 disponibile solo su sistema operativo Windows. - -swfpreview = Anteprima SWF -swfpreview.internal = Anteprima SWF (visualizzatore incorporato) - -parameters = Parametri - -rename.enternew = Nuovo nome: - -rename.finished.identifier = Identificatore rinominato con successo. -rename.finished.multiname = %count% multiname rinominati. - -node.texts = text -node.images = image -node.movies = movie -node.sounds = sound -node.binaryData = BinaryData -node.fonts = font -node.sprites = sprite -node.shapes = shape -node.morphshapes = morphshape -node.buttons = button -node.frames = frame -node.scripts = script - -message.warning = Avvertenza -message.confirm.experimental = Questa procedura pu\u00f2 danneggiare il file SWF e renderlo irriproducibile.\r\nUSARE\u00a0A\u00a0PROPRIO\u00a0RISCHIO. Si desidera abilitare comunque? -message.confirm.parallel = L'esecuzione parallela velocizza il caricamento e la decompilazione ma usa pi\u00f9 memoria. -message.confirm.on = ABILITARE\u00a0questa opzione? -message.confirm.off = DISABILITARE\u00a0questa opzione? -message.confirm = Conferma - -message.confirm.autodeobfuscate = Il deoffuscamento automatico permette di decompilare codice offuscato.\r\nQuesto rallenta la decompilazione e pu\u00f2 comportare l'eliminazione di codice morto.\r\nSe il codice non \u00e8 offuscato, \u00e8 preferibile disattivare il deoffuscamento. - -message.parallel = Parallelismo -message.trait.saved = Trait salvato con successo - -message.constant.new.string = Stringa di caratteri "%value%" non presente nella tabella delle costanti. Aggiungere? -message.constant.new.string.title = Aggiunto String -message.constant.new.integer = Valore intero "%value%" not presente nella tabella delle costanti. Aggiungere? -message.constant.new.integer.title = Aggiunto Integer -message.constant.new.unsignedinteger = Valore intero senza segno "%value%" not presente nella tabella delle costanti. Aggiungere? -message.constant.new.unsignedinteger.title = Aggiunto Integer senza segno -message.constant.new.double = Valore a doppia precisione "%value%" not presente nella tabella delle costanti. Aggiungere? -message.constant.new.double.title = Aggiunto Double - -work.buffering = Buffering in corso -work.waitingfordissasembly = In attesa del disassembly -work.gettinghilights = Recupero degli highlight -work.disassembling = Disassembly in corso -work.exporting = Esportazione in corso -work.searching = Ricerca in corso -work.renaming = Rinomina in corso -work.exporting.fla = Esportazione FLA -work.renaming.identifiers = Rinomina identificatori -work.deobfuscating = Deoffuscamento -work.decompiling = Decompilazione in corso -work.gettingvariables = Lettura variabili -work.reading.swf = Lettura SWF -work.creatingwindow = Creazione finestra -work.buildingscripttree = Creazione gerarchia degli script - -work.deobfuscating.complete = Deoffuscamento completato - -message.search.notfound = Stringa "%searchtext%" non trovata. -message.search.notfound.title = Non trovato - -message.rename.notfound.multiname = Nessun multiname alla posizione corrente -message.rename.notfound.identifier = Nessun identificatore alla posizione corrente -message.rename.notfound.title = Non trovato -message.rename.renamed = %count% identificatori renominati. - -filter.images = Immagini (%extensions%) -filter.fla = Documento %version% (*.fla) -filter.xfl = Documento non compresso %version%(*.xfl) -filter.swf = File SWF (*.swf) - -error = Errore -error.image.invalid = Immagine non valida. - -error.text.invalid = Testo non valido alla riga %line%: %text% -error.file.save = Impossibile salvare il file -error.file.write = Impossibile scrivere su file -error.export = Errore durante l'esportazione - -export.select.directory = Selezionare la cartella di esportazione -export.finishedin = Esportato in %time% - -update.check.title = Controllo aggiornamenti -update.check.nonewversion = Nessuna nuova versione disponibile. - -message.helpus = Per maggiori dettagli si prega di visitare\r\n%url%\r\n -message.homepage = Visita la homepage:\r\n%url% - -proxy = Proxy -proxy.start = Avvio proxy -proxy.stop = Arresta proxy -proxy.show = Mostra proxy -exit = Esci - -panel.disassembled = Sorgente P-code -panel.decompiled = Sorgente ActionScript - -search.info = Cerca "%text%": -search.script = Script - -constants = Costanti -traits = Trait - -pleasewait = Attendere prego - -abc.detail.methodtrait = Trait di Metodo/Getter/Setter -abc.detail.unsupported = - -abc.detail.slotconsttrait = Trait Slot/Const -abc.detail.traitname = Nome: - -abc.detail.body.params.maxstack = Max stack: -abc.detail.body.params.localregcount = Conteggio registri locali: -abc.detail.body.params.minscope = Profondit\u00e0 minima dello scope: -abc.detail.body.params.maxscope = Profondit\u00e0 massima dello scope: -abc.detail.body.params.autofill = Autocompletamento a salvataggio codice (IMPOSTAZIONE\u00a0GLOBALE) -abc.detail.body.params.autofill.experimental = ...SPERIMENTALE - -abc.detail.methodinfo.methodindex = Indice del metodo: -abc.detail.methodinfo.parameters = Parametri: -abc.detail.methodinfo.returnvalue = Tipo del valore di ritorno: - -error.methodinfo.params = Errore parametri MethodInfo -error.methodinfo.returnvalue = Errore tipo valore di ritorno MethodInfo - -abc.detail.methodinfo = MethodInfo -abc.detail.body.code = Codice MethodBody -abc.detail.body.params = Parametri MethodBody - -abc.detail.slotconst.typevalue = Tipo e valore: - -error.slotconst.typevalue = Errore tipo valore SlotConst - -message.autofill.failed = Impossibile ottenere statistiche codice per i parametri automatici nel corpo.\r\nDeselezionare Autocompletamento per evitare questo messaggio. - -info.selecttrait = Selezionare una classe e fare clic su un trait nel sorgente ActionScript per modifiche. - -button.viewgraph = Visualizza grafo -button.viewhex = Visualizza listato - -abc.traitslist.instanceinitializer = instance initializer -abc.traitslist.classinitializer = class initializer - -action.edit.experimental = (Sperimentale) - -message.action.saved = Codice salvato con successo - -error.action.save = %error% alla riga %line% - -message.confirm.remove = Sicuro di voler remuovere %item%\n e tutti gli oggetti che dipendono da esso? - -#after version 1.6.5u1: - -button.ok = OK -button.cancel = Annulla - -font.name = Nome font: -font.isbold = Grassetto: -font.isitalic = Corsivo: -font.ascent = Ascendente: -font.descent = Discendente: -font.leading = Interlinea: -font.characters = Caratteri: -font.characters.add = Aggiunta caratteri: -value.unknown = ? - -yes = s\u00ec -no = no - -errors.present = Ci sono ERRORI nel registro. Fare clic per visualizzare. -errors.none = Non ci sono errori nel registro. - -#after version 1.6.6: - -dialog.message.title = Messaggio -dialog.select.title = Selezionare un'opzione - -button.yes = S\u00ec -button.no = No - -FileChooser.openButtonText = Apri -FileChooser.openButtonToolTipText = Apri -FileChooser.lookInLabelText = Cerca in: -FileChooser.acceptAllFileFilterText = Tutti i file -FileChooser.filesOfTypeLabelText = Tipo file: -FileChooser.fileNameLabelText = Nome del file: -FileChooser.listViewButtonToolTipText = Elenco -FileChooser.listViewButtonAccessibleName = Elenco -FileChooser.detailsViewButtonToolTipText = Dettagli -FileChooser.detailsViewButtonAccessibleName = Dettagli -FileChooser.upFolderToolTipText = Su di un livello -FileChooser.upFolderAccessibleName = Su di un livello -FileChooser.homeFolderToolTipText = Home -FileChooser.homeFolderAccessibleName = Home -FileChooser.fileNameHeaderText = Nome -FileChooser.fileSizeHeaderText = Dimensione -FileChooser.fileTypeHeaderText = Tipo -FileChooser.fileDateHeaderText = Data -FileChooser.fileAttrHeaderText = Attributi -FileChooser.openDialogTitleText = Apri -FileChooser.directoryDescriptionText = Directory -FileChooser.directoryOpenButtonText = Apri -FileChooser.directoryOpenButtonToolTipText = Apri cartella selezionata -FileChooser.fileDescriptionText = File generico -FileChooser.helpButtonText = Guida -FileChooser.helpButtonToolTipText = Guida su selettore file -FileChooser.newFolderAccessibleName = Nuova cartella -FileChooser.newFolderErrorText = Errore nella creazione della cartella -FileChooser.newFolderToolTipText = Crea nuova cartella -FileChooser.other.newFolder = NuovaCartella -FileChooser.other.newFolder.subsequent = NuovaCartella.{0} -FileChooser.win32.newFolder = Nuova cartella -FileChooser.win32.newFolder.subsequent = Nuova cartella ({0}) -FileChooser.saveButtonText = Salva -FileChooser.saveButtonToolTipText = Salva file selezionato -FileChooser.saveDialogTitleText = Salva -FileChooser.saveInLabelText = Salva in: -FileChooser.updateButtonText = Aggiorna -FileChooser.updateButtonToolTipText = Aggiorna elenco cartelle - -#after version 1.6.6u2: - -FileChooser.detailsViewActionLabel.textAndMnemonic = Dettagli -FileChooser.detailsViewButtonToolTip.textAndMnemonic = Dettagli -FileChooser.fileAttrHeader.textAndMnemonic = Attributi -FileChooser.fileDateHeader.textAndMnemonic = Ultima modifica -FileChooser.fileNameHeader.textAndMnemonic = Nome -FileChooser.fileNameLabel.textAndMnemonic = Nome del file: -FileChooser.fileSizeHeader.textAndMnemonic = Dimensione -FileChooser.fileTypeHeader.textAndMnemonic = Tipo -FileChooser.filesOfTypeLabel.textAndMnemonic = Tipo file: -FileChooser.folderNameLabel.textAndMnemonic = Nome cartella: -FileChooser.homeFolderToolTip.textAndMnemonic = Home -FileChooser.listViewActionLabel.textAndMnemonic = Elenco -FileChooser.listViewButtonToolTip.textAndMnemonic = Elenco -FileChooser.lookInLabel.textAndMnemonic = Guarda in: -FileChooser.newFolderActionLabel.textAndMnemonic = Nuova cartella -FileChooser.newFolderToolTip.textAndMnemonic = Crea nuova cartella -FileChooser.refreshActionLabel.textAndMnemonic = Aggiorna -FileChooser.saveInLabel.textAndMnemonic = Salva in: -FileChooser.upFolderToolTip.textAndMnemonic = Su di un livello -FileChooser.viewMenuButtonAccessibleName = Menu visuale -FileChooser.viewMenuButtonToolTipText = Layout -FileChooser.viewMenuLabel.textAndMnemonic = Layout -FileChooser.newFolderActionLabelText = Nuova cartella -FileChooser.listViewActionLabelText = Elenco -FileChooser.detailsViewActionLabelText = Dettagli -FileChooser.refreshActionLabelText = Aggiorna -FileChooser.sortMenuLabelText = Disponi icone per -FileChooser.viewMenuLabelText = Visualizza -FileChooser.fileSizeKiloBytes = {0} KB -FileChooser.fileSizeMegaBytes = {0} MB -FileChooser.fileSizeGigaBytes = {0} GB -FileChooser.folderNameLabelText = Nome cartella: - -error.occured = Si \u00e8 verificato un errore: %error% -button.abort = Annulla -button.retry = Riprova -button.ignore = Tralascia - -font.source = Font per i sorgenti: - -#after version 1.6.7: - -menu.export = Esporta -menu.general = Generale -menu.language = Lingua - -startup.welcometo = Benvenuto a -startup.selectopen = Per iniziare fare clic su Apri nel menu oppure trascinare un file SWF su questa finestra. -menu.file.reload = Ricarica -message.confirm.reload = Questa azione annulla tutte le modifiche non salvate e carica nuovamente il file SWF.\nConfermare? - -dialog.selectbkcolor.title = Scelta colore di sfondo - - -error.font.nocharacter = Il font sorgente selezionato non contiene il carattere "%char%". - -warning.initializers = I campi statici e le costanti sono spesso valorizzati negli initializer.\nLa modifica del valore qui spesso non \u00e8 sufficiente! - - -#after version 1.7.0u1: - -menu.tools.searchMemory = Cerca SWF in memoria -button.selectbkcolor.hint = Scelta colore di sfondo per lo SWF - -ColorChooser.okText = OK -ColorChooser.cancelText = Annulla -ColorChooser.resetText = Risetta -ColorChooser.previewText = Anteprima -ColorChooser.swatchesNameText = Palette -ColorChooser.swatchesRecentText = Recente: -ColorChooser.sampleText=Testo Campione Testo Campione - -#after version 1.7.1: - -preview.play = Riproduci -preview.pause = Pausa -preview.stop = Stop - -message.confirm.removemultiple = Confermare la rimozione di %count% elementi\n e tutti gli oggetti che ne dipendono? -menu.tools.searchCache = Cerca nella cache del browser - -#after version 1.7.2u2 - -error.trait.exists = Trait con nome "%name%" gi\u00e0 presente. -button.addtrait = Aggiungi trait -button.font.embed = Incorpora... -button.yes.all = S\u00ec a tutto -button.no.all = No a tutto -message.font.add.exists = Il carattere %char% esiste gi\u00e0 nel font tag.\nSostituirlo? - -filter.gfx = File ScaleForm GFX (*.gfx) -filter.supported = Tutti i formati supportati -work.canceled = Annullato -work.restoringControlFlow = Ripristino controllo di flusso in corso -menu.advancedsettings.advancedsettings = Impostazioni avanzate -menu.recentFiles = File recenti - -#after version 1.7.4 -work.restoringControlFlow.complete = Controllo di flusso ripristinato -message.confirm.recentFileNotFound = File non trovato. Rimuovere dalla lista dei file recenti? -contextmenu.closeSwf = Chiudi SWF -menu.settings.autoRenameIdentifiers = Autorinomina identificatori -menu.file.saveasexe = Crea eseguibile... -filter.exe = File eseguibile (*.exe) - -#after version 1.8.0 -font.updateTexts = Aggiorna testi - -#after version 1.8.0u1 -menu.file.close = Chiudi -menu.file.closeAll = Chiudi tutto -menu.tools.otherTools = Altro -menu.tools.otherTools.clearRecentFiles = Pulisci file recenti -fontName.name = Nome font visualizzato: -fontName.copyright = Copyright del font: -button.preview = Anteprima -button.reset = Risetta -errors.info = Ci sono INFORMAZIONI nel log. Fare clic per visualizzare. -errors.warning = Ci sono AVVISI nel log. Fare clic per visualizzare. - -decompilationError = Errore di decompilazione - -disassemblingProgress.toString = toString -disassemblingProgress.reading = Lettura -disassemblingProgress.deobfuscating = Deoffuscamento - -contextmenu.moveTag = Sposta tag - -filter.swc = File componente SWC (*.swc) -filter.zip = File compressi (*.zip) -filter.binary = Ricerca binaria - tutti i file (*.*) - -open.error = Errore -open.error.fileNotFound = File non trovato -open.error.cannotOpen = Non \u00e8 possibile aprire il file - -node.others = altro - -#after version 1.8.1 -menu.tools.search = Ricerca testuale - -#after version 1.8.1u1 -menu.tools.timeline = Timeline - -dialog.selectcolor.title = Seleziona il colore -button.selectcolor.hint = Fare clic per selezionare il colore - -#default item name, will be used in following sentences -generictag.array.item = elemento -generictag.array.insertbeginning = Inserire %item% all'inizio -generictag.array.insertbefore = Inserire %item% prima -generictag.array.remove = Rimuovi %item% -generictag.array.insertafter = Inserire %item% dopo -generictag.array.insertend = Inserire %item% alla fine - -#after version 2.0.0 -contextmenu.expandAll = Espandi tutto - -filter.sounds = Formati audio supportati (*.wav, *.mp3) -filter.sounds.wav = Formato file Wave (*.wav) -filter.sounds.mp3 = Formato MP3 compresso (*.mp3) - -error.sound.invalid = Audio non valido. - -button.prev = Precedente -button.next = Successivo - -#after version 2.1.0 -message.action.playerglobal.title = Libreria PlayerGlobal.swc mancante -message.action.playerglobal.needed = Per effettuare modifiche immediate in AS3 la libreria "PlayerGlobal.swc" deve essere scaricato dal sito di Adobe.\r\n%adobehomepage%\r\nPremere OK per visitare la pagina di download. -message.action.playerglobal.place = Scarica la libreria PlayerGlobal(.swc) e posizionala nella cartella \r\n%libpath%\r\nScegliere OK per continuare. - -message.confirm.experimental.function = Questa funzione \u00e8 SPERIMENTALE. Ci\u00f2 significa che non \u00e8 garantito il risultato ed il file SWF pu\u00f2 essere non funzionale dopo il salvataggio. -message.confirm.donotshowagain = Non mostrare pi\u00f9 il messaggio - -menu.import = Importa -menu.file.import.text = Importa testo -import.select.directory = Selezionare cartella di importazione -error.text.import = Errore durante l'importazione del testo. Continuare? - -#after version 2.1.1 -contextmenu.removeWithDependencies = Rimuovere assieme alle dipendenze - -abc.action.find-usages = Trova invocazioni -abc.action.find-declaration = Trova dichiarazione - -contextmenu.rawEdit = Modifica raw -contextmenu.jumpToCharacter = Vai al carattere - -menu.settings.dumpView = Visualizza Dump - -menu.view = Visualizza -menu.file.view.resources = Risorse -menu.file.view.hex = Hex dump - -node.header = header - -header.signature = Firma: -header.compression = Compressione: -header.compression.lzma = LZMA -header.compression.zlib = ZLIB -header.compression.none = Nessuna compressione -header.version = Versione SWF: -header.gfx = GFX: -header.filesize = Dimensione file: -header.framerate = Frequenza frame: -header.framecount = Conteggio frame: -header.displayrect = Rect di visualizzazione: -header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% twip -header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% pixel - -#after version 2.1.2 -contextmenu.saveToFile = Salva su file -contextmenu.parseActions = Analizza azioni -contextmenu.parseABC = Analizza ABC -contextmenu.parseInstructions = Analizza istruzioni AVM2 - -#after version 2.1.3 -menu.deobfuscation = Deoffuscamento -menu.file.deobfuscation.old = Vecchio stile -menu.file.deobfuscation.new = Nuovo stile - -#after version 2.1.4 -contextmenu.openswfinside = Apri SWF incorporato -binarydata.swfInside = Rilevato SWF all'interno di questo tag di dati binari. Fare clic qui per caricarlo come sottostruttura. - -#after version 3.0.0 -button.zoomin.hint = Ingrandisci -button.zoomout.hint = Riduci -button.zoomfit.hint = Mostra tutto -button.zoomnone.hint = Scala 1:1 -button.snapshot.hint = Crea istantanea negli Appunti - -editorTruncateWarning = Testo troncato alla posizione %chars% in modalit\u00e0 debug. - -#Font name which is presented in the SWF Font tag -font.name.intag = Nome font nel tag: - -menu.debugger = Debugger -menu.debugger.switch = Debugger -menu.debugger.replacetrace = Sostituisci invocazioni di trace -menu.debugger.showlog = Visualizza log - -message.debugger = Questo debugger SWF pu\u00f2 essere utilizzato solo per stampare messaggi nella finestra di log della console del browser o alert.\r\nNon offre caratteristiche come esecuzione passo-passo, breakpoint ecc. -contextmenu.addTag = Aggiungi tag -deobfuscation.comment.tryenable = Suggerimento: \u00e8 possibile provare ad abilitare il "deoffuscamento automatico" sotto Impostazioni -deobfuscation.comment.failed = Il deoffuscamento \u00e8 attivo ma la decompilazione non \u00e8 riuscita. Se il file non \u00e8 offuscato, disattivare "Deoffuscamento automatico" potrebbe dare risultati migliori. - -#after version 4.0.2 -preview.nextframe = Frame successivo -preview.prevframe = Frame precedente -preview.gotoframe = Vai a frame... - -preview.gotoframe.dialog.title = Vai a frame -preview.gotoframe.dialog.message = Inserire il numero del frame (%min% - %max%) -preview.gotoframe.dialog.frame.error = Numero del frame non valido. Deve essere tra %min% e %max%. - -error.text.invalid.continue = Testo non valido alla riga %line%: %text% . Si desidera continuare? - -#after version 4.0.5 -contextmenu.copyTag = Copia tag -fit = adattamento -button.setAdvanceValues = Impostare i valori di avanzamento - -menu.tools.replace = Sostituzione testo - -message.confirm.close = Vi sono modifiche non salvate. Chiudere {swfName} senza salvare? -message.confirm.closeAll = Vi sono modifiche non salvate. Vuoi davvero chiudere tutti i file SWF? - -contextmenu.exportJavaSource = Esporta sorgente Java -contextmenu.exportSwfXml = Esporta SWF come XML -contextmenu.importSwfXml = Importa SWF da XML - -filter.xml = File XML (*.xml) - -#after version 4.1.0 -contextmenu.undo = Annulla - -text.align.left = Allinea a sinistra -text.align.right = Allinea a destra -text.align.center = Centrato -text.align.justify = Giustificato - -text.undo = Annulla le modifiche - -menu.file.import.xml = Importa SWF da XML -menu.file.export.xml = Esporta SWF come XML - -#after version 4.1.1 -text.align.translatex.decrease = Riduci TranslateX -text.align.translatex.increase = Incementa TranslateX -selectPreviousTag = Selezionare tag precedente -selectNextTag = Selezionare tag successivo -button.ignoreAll = Ignora tutto -menu.file.import.symbolClass = Importa classe di simbolo -text.toggleCase = Alterna maiuscole/minuscole - -#after version 5.0.2 -preview.loop = Cicla -menu.file.import.script = Importa script -contextmenu.copyTagWithDependencies = Copia tag con le dipendenze -button.replaceWithTag = Sostituisci con altro tag di carattere -button.resolveConstants = Risolvi le costanti - -#after version 5.1.0 -button.viewConstants = Visualizza le costanti -work.exported = Esportato -button.replaceAlphaChannel = Sostituire canale alfa... - -tagInfo.header.name = Nome -tagInfo.header.value = Valore -tagInfo.tagType = Tipo tag -tagInfo.characterId = Id carattere -tagInfo.offset = Offset -tagInfo.length = Lunghezza -tagInfo.bounds = Limiti -tagInfo.width = Larghezza -tagInfo.height = Altezza -tagInfo.neededCharacters = Caratteri necessari - -button.viewhexpcode = Mostra valori byte assieme alle istruzioni -taginfo.header = Informazioni tag di base - -tagInfo.dependentCharacters = Caratteri dipendenti - -#after version 5.3.0 -header.uncompressed = Non compresso -header.warning.unsupportedGfxCompression = GFX supporta solo contenuto non compresso o compresso con Zlib. -header.warning.minimumZlibVersion = La compressione zlib richiede SWF versione 6 o superiore. -header.warning.minimumLzmaVersion = la compressione LZMA richiede SWF versione 13 o superiore. - -tagInfo.codecName = Nome codec -tagInfo.exportFormat = Formato di esportazione -tagInfo.samplingRate = Frequenza di campionamento -tagInfo.stereo = Stereo -tagInfo.sampleCount = Conteggio campioni - -filter.dmg = Eseguibili Mac (*.dmg) -filter.linuxExe = Eseguibili Linux - -import.script.result = Importati %count% script. -import.script.as12warning = Importa script pu\u00f2 importare solo script AS1/2. - -error.constantPoolTooBig = Constant pool troppo grande. indice=%index%, dimensioni=%size% -error.image.alpha.invalid = Valori canale alfa non validi. - -#after version 6.0.2 -contextmenu.saveUncompressedToFile = Salva su file senza compressione -abc.traitslist.scriptinitializer = Inizializzatore script -menu.settings.autoOpenLoadedSWFs = Apri SWF caricati durante la riproduzione - -#after version 6.1.1 -menu.file.start = Avvio -menu.file.start.run = Esegui -menu.file.start.stop = Arresta -menu.file.start.debug = Debug -menu.debugging = Debug -menu.debugging.debug = Debug -menu.debugging.debug.stop = Ferma -menu.debugging.debug.pause = Pausa -menu.debugging.debug.stepOver = Passo successivo -menu.debugging.debug.stepInto = Entra nel metodo -menu.debugging.debug.stepOut = Risali dal metodo -menu.debugging.debug.continue = Continua -menu.debugging.debug.stack = Stack... -menu.debugging.debug.watch = Nuovo osservatore... - - -message.playerpath.notset = Proiettore Flash Player non trovato. Si prega di configurarne il percorso in Impostazioni avanzate / Percorsi (1). -message.playerpath.debug.notset = Proiettore Flash Player debugger di contenuto non trovato. Si prega di configurarne il percorso in Impostazioni avanzate / Percorsi (2). -message.playerpath.lib.notset = PlayerGlobal (.swc) non trovato. Si prega di configurarne il percorso in Impostazioni avanzate / Percorsi (3). - -debugpanel.header = Debug - -variables.header.registers = Registri -variables.header.locals = Variabili locali -variables.header.arguments = Argomenti -variables.header.scopeChain = Catena visibilit\u00e0 delle variabili -variables.column.name = Nome -variables.column.type = Tipo -variables.column.value = Valore - -callStack.header = Stack chiamate di funzione -callStack.header.file = File -callStack.header.line = Riga - -stack.header = Stack -stack.header.item = Voce - -constantpool.header = Pool delle costanti -constantpool.header.id = Id -constantpool.header.value = Valore - -work.running = In esecuzione -work.debugging = Debug in corso -work.debugging.instrumenting = Preparazione SWF per il debug -work.breakat = Interrompi a -work.halted = Debug iniziato, esecuzione sospesa. Aggiungi i breakpoint e scegli Continua (F5) per riprendere l'esecuzione. - -debuglog.header = Log -debuglog.button.clear = Pulisci - -# after 7.0.1 -work.debugging.wait = In attesa di connessione proiettore Flash debugger - -error.debug.listen = Impossibile ascoltare la porta %porta%. Potrebbe esserci un altro debugger in esecuzione. - -debug.break.reason.unknown = (Sconosciuto) -debug.break.reason.breakpoint = (Breakpoint) -debug.break.reason.watch = (Watch) -debug.break.reason.fault = (Fault) -debug.break.reason.stopRequest = (Richiesta di stop) -debug.break.reason.step = (Passo) -debug.break.reason.halt = (Halt) -debug.break.reason.scriptLoaded = (Script caricato) - -menu.file.start.debugpcode = Debug P-code - -# after 7.1.2 -button.replaceNoFill = Sostituisci - Aggiorna limiti... -message.warning.svgImportExperimental = Non tutte le funzioni SVG sono supportate. Controllare il registro dopo l'importazione. -message.imported.swf = Il file SWF utilizza asset da un file SWF importato:\n%url%\nCaricare gli asset da quell'indirizzo? -message.imported.swf.manually = Impossibile caricare SWF importato\n%url%\nFile o URL non esistente.\nSelezionare un file locale? - -message.warning.hexViewNotUpToDate = Hex View non aggiornato. Si prega di salvare e ricaricare il file per aggiornare la visuale. -message.font.replace.updateTexts = Sono stati sostituiti alcuni caratteri. Aggiornare i testi esistenti? - -menu.settings.simplifyExpressions = Semplifica espressioni - -#after 8.0.1 -menu.recentFiles.empty = Lista file recenti vuota -message.warning.outOfMemory32BitJre = Errore di memoria esaurita. Stai eseguendo Java a 32bit su sistema operativo a 64bit. Prova con Java a 64bit. - -menu.file.reloadAll = Ricarica tutto -message.confirm.reloadAll = Questa azione annulla le modifiche non salvate in tutti i file SWF e ricarica l'intera applicazione.\nDesideri continuare? -export.script.singleFilePallelModeWarning = L'esportazione di script su singolo file non \u00e8 supportata con accelerazione parallela abilitata - -button.showOriginalBytesInPcodeHex = Mostra byte originali -button.remove = Rimuovi +# Copyright (C) 2010-2016 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 . + +menu.file = File +menu.file.open = Apri... +menu.file.save = Salva +menu.file.saveas = Salva come... +menu.file.export.fla = Esporta come FLA +menu.file.export.all = Esporta tutte le parti +menu.file.export.selection = Esporta selezione +menu.file.exit = Esci + +menu.tools = Strumenti +menu.tools.searchas = Cerca in tutti gli ActionScript... +menu.tools.proxy = Proxy +menu.tools.deobfuscation = Deoffuscamento +menu.tools.deobfuscation.pcode = Deoffuscamento P-code... +menu.tools.deobfuscation.globalrename = Rinomina identificatore globalmente +menu.tools.deobfuscation.renameinvalid = Rinomina identificatori non validi +menu.tools.gotoDocumentClass = Vai a document class + +menu.settings = Impostazioni +menu.settings.autodeobfuscation = Deoffuscamento automatico +menu.settings.internalflashviewer = Usa visualizzatore Flash incorporato +menu.settings.parallelspeedup = Accelerazione parallela +menu.settings.disabledecompilation = Disattiva la decompilazione (solo disassembly) +menu.settings.addtocontextmenu = Mostra FFDec nel menu contestuale per file SWF +menu.settings.language = Cambia la lingua +menu.settings.cacheOnDisk = Utilizza la cache su disco +menu.settings.gotoMainClassOnStartup = Evidenzia la document class all'avvio + +menu.help = Aiuto +menu.help.checkupdates = Controllo aggiornamenti... +menu.help.helpus = Dateci una mano! +menu.help.homepage = Visita il sito web +menu.help.about = Informazioni su... + +contextmenu.remove = Rimuovi + +button.save = Salva +button.edit = Modifica +button.cancel = Annulla +button.replace = Sostituisci... + +notavailonthisplatform = L'anteprima di questo oggetto \u00e8 disponibile solo su sistema operativo Windows. + +swfpreview = Anteprima SWF +swfpreview.internal = Anteprima SWF (visualizzatore incorporato) + +parameters = Parametri + +rename.enternew = Nuovo nome: + +rename.finished.identifier = Identificatore rinominato con successo. +rename.finished.multiname = %count% multiname rinominati. + +node.texts = text +node.images = image +node.movies = movie +node.sounds = sound +node.binaryData = BinaryData +node.fonts = font +node.sprites = sprite +node.shapes = shape +node.morphshapes = morphshape +node.buttons = button +node.frames = frame +node.scripts = script + +message.warning = Avvertenza +message.confirm.experimental = Questa procedura pu\u00f2 danneggiare il file SWF e renderlo irriproducibile.\r\nUSARE\u00a0A\u00a0PROPRIO\u00a0RISCHIO. Si desidera abilitare comunque? +message.confirm.parallel = L'esecuzione parallela velocizza il caricamento e la decompilazione ma usa pi\u00f9 memoria. +message.confirm.on = ABILITARE\u00a0questa opzione? +message.confirm.off = DISABILITARE\u00a0questa opzione? +message.confirm = Conferma + +message.confirm.autodeobfuscate = Il deoffuscamento automatico permette di decompilare codice offuscato.\r\nQuesto rallenta la decompilazione e pu\u00f2 comportare l'eliminazione di codice morto.\r\nSe il codice non \u00e8 offuscato, \u00e8 preferibile disattivare il deoffuscamento. + +message.parallel = Parallelismo +message.trait.saved = Trait salvato con successo + +message.constant.new.string = Stringa di caratteri "%value%" non presente nella tabella delle costanti. Aggiungere? +message.constant.new.string.title = Aggiunto String +message.constant.new.integer = Valore intero "%value%" not presente nella tabella delle costanti. Aggiungere? +message.constant.new.integer.title = Aggiunto Integer +message.constant.new.unsignedinteger = Valore intero senza segno "%value%" not presente nella tabella delle costanti. Aggiungere? +message.constant.new.unsignedinteger.title = Aggiunto Integer senza segno +message.constant.new.double = Valore a doppia precisione "%value%" not presente nella tabella delle costanti. Aggiungere? +message.constant.new.double.title = Aggiunto Double + +work.buffering = Buffering in corso +work.waitingfordissasembly = In attesa del disassembly +work.gettinghilights = Recupero degli highlight +work.disassembling = Disassembly in corso +work.exporting = Esportazione in corso +work.searching = Ricerca in corso +work.renaming = Rinomina in corso +work.exporting.fla = Esportazione FLA +work.renaming.identifiers = Rinomina identificatori +work.deobfuscating = Deoffuscamento +work.decompiling = Decompilazione in corso +work.gettingvariables = Lettura variabili +work.reading.swf = Lettura SWF +work.creatingwindow = Creazione finestra +work.buildingscripttree = Creazione gerarchia degli script + +work.deobfuscating.complete = Deoffuscamento completato + +message.search.notfound = Stringa "%searchtext%" non trovata. +message.search.notfound.title = Non trovato + +message.rename.notfound.multiname = Nessun multiname alla posizione corrente +message.rename.notfound.identifier = Nessun identificatore alla posizione corrente +message.rename.notfound.title = Non trovato +message.rename.renamed = %count% identificatori renominati. + +filter.images = Immagini (%extensions%) +filter.fla = Documento %version% (*.fla) +filter.xfl = Documento non compresso %version%(*.xfl) +filter.swf = File SWF (*.swf) + +error = Errore +error.image.invalid = Immagine non valida. + +error.text.invalid = Testo non valido alla riga %line%: %text% +error.file.save = Impossibile salvare il file +error.file.write = Impossibile scrivere su file +error.export = Errore durante l'esportazione + +export.select.directory = Selezionare la cartella di esportazione +export.finishedin = Esportato in %time% + +update.check.title = Controllo aggiornamenti +update.check.nonewversion = Nessuna nuova versione disponibile. + +message.helpus = Per maggiori dettagli si prega di visitare\r\n%url%\r\n +message.homepage = Visita la homepage:\r\n%url% + +proxy = Proxy +proxy.start = Avvio proxy +proxy.stop = Arresta proxy +proxy.show = Mostra proxy +exit = Esci + +panel.disassembled = Sorgente P-code +panel.decompiled = Sorgente ActionScript + +search.info = Cerca "%text%": +search.script = Script + +constants = Costanti +traits = Trait + +pleasewait = Attendere prego + +abc.detail.methodtrait = Trait di Metodo/Getter/Setter +abc.detail.unsupported = - +abc.detail.slotconsttrait = Trait Slot/Const +abc.detail.traitname = Nome: + +abc.detail.body.params.maxstack = Max stack: +abc.detail.body.params.localregcount = Conteggio registri locali: +abc.detail.body.params.minscope = Profondit\u00e0 minima dello scope: +abc.detail.body.params.maxscope = Profondit\u00e0 massima dello scope: +abc.detail.body.params.autofill = Autocompletamento a salvataggio codice (IMPOSTAZIONE\u00a0GLOBALE) +abc.detail.body.params.autofill.experimental = ...SPERIMENTALE + +abc.detail.methodinfo.methodindex = Indice del metodo: +abc.detail.methodinfo.parameters = Parametri: +abc.detail.methodinfo.returnvalue = Tipo del valore di ritorno: + +error.methodinfo.params = Errore parametri MethodInfo +error.methodinfo.returnvalue = Errore tipo valore di ritorno MethodInfo + +abc.detail.methodinfo = MethodInfo +abc.detail.body.code = Codice MethodBody +abc.detail.body.params = Parametri MethodBody + +abc.detail.slotconst.typevalue = Tipo e valore: + +error.slotconst.typevalue = Errore tipo valore SlotConst + +message.autofill.failed = Impossibile ottenere statistiche codice per i parametri automatici nel corpo.\r\nDeselezionare Autocompletamento per evitare questo messaggio. + +info.selecttrait = Selezionare una classe e fare clic su un trait nel sorgente ActionScript per modifiche. + +button.viewgraph = Visualizza grafo +button.viewhex = Visualizza listato + +abc.traitslist.instanceinitializer = instance initializer +abc.traitslist.classinitializer = class initializer + +action.edit.experimental = (Sperimentale) + +message.action.saved = Codice salvato con successo + +error.action.save = %error% alla riga %line% + +message.confirm.remove = Sicuro di voler remuovere %item%\n e tutti gli oggetti che dipendono da esso? + +#after version 1.6.5u1: + +button.ok = OK +button.cancel = Annulla + +font.name = Nome font: +font.isbold = Grassetto: +font.isitalic = Corsivo: +font.ascent = Ascendente: +font.descent = Discendente: +font.leading = Interlinea: +font.characters = Caratteri: +font.characters.add = Aggiunta caratteri: +value.unknown = ? + +yes = s\u00ec +no = no + +errors.present = Ci sono ERRORI nel registro. Fare clic per visualizzare. +errors.none = Non ci sono errori nel registro. + +#after version 1.6.6: + +dialog.message.title = Messaggio +dialog.select.title = Selezionare un'opzione + +button.yes = S\u00ec +button.no = No + +FileChooser.openButtonText = Apri +FileChooser.openButtonToolTipText = Apri +FileChooser.lookInLabelText = Cerca in: +FileChooser.acceptAllFileFilterText = Tutti i file +FileChooser.filesOfTypeLabelText = Tipo file: +FileChooser.fileNameLabelText = Nome del file: +FileChooser.listViewButtonToolTipText = Elenco +FileChooser.listViewButtonAccessibleName = Elenco +FileChooser.detailsViewButtonToolTipText = Dettagli +FileChooser.detailsViewButtonAccessibleName = Dettagli +FileChooser.upFolderToolTipText = Su di un livello +FileChooser.upFolderAccessibleName = Su di un livello +FileChooser.homeFolderToolTipText = Home +FileChooser.homeFolderAccessibleName = Home +FileChooser.fileNameHeaderText = Nome +FileChooser.fileSizeHeaderText = Dimensione +FileChooser.fileTypeHeaderText = Tipo +FileChooser.fileDateHeaderText = Data +FileChooser.fileAttrHeaderText = Attributi +FileChooser.openDialogTitleText = Apri +FileChooser.directoryDescriptionText = Directory +FileChooser.directoryOpenButtonText = Apri +FileChooser.directoryOpenButtonToolTipText = Apri cartella selezionata +FileChooser.fileDescriptionText = File generico +FileChooser.helpButtonText = Guida +FileChooser.helpButtonToolTipText = Guida su selettore file +FileChooser.newFolderAccessibleName = Nuova cartella +FileChooser.newFolderErrorText = Errore nella creazione della cartella +FileChooser.newFolderToolTipText = Crea nuova cartella +FileChooser.other.newFolder = NuovaCartella +FileChooser.other.newFolder.subsequent = NuovaCartella.{0} +FileChooser.win32.newFolder = Nuova cartella +FileChooser.win32.newFolder.subsequent = Nuova cartella ({0}) +FileChooser.saveButtonText = Salva +FileChooser.saveButtonToolTipText = Salva file selezionato +FileChooser.saveDialogTitleText = Salva +FileChooser.saveInLabelText = Salva in: +FileChooser.updateButtonText = Aggiorna +FileChooser.updateButtonToolTipText = Aggiorna elenco cartelle + +#after version 1.6.6u2: + +FileChooser.detailsViewActionLabel.textAndMnemonic = Dettagli +FileChooser.detailsViewButtonToolTip.textAndMnemonic = Dettagli +FileChooser.fileAttrHeader.textAndMnemonic = Attributi +FileChooser.fileDateHeader.textAndMnemonic = Ultima modifica +FileChooser.fileNameHeader.textAndMnemonic = Nome +FileChooser.fileNameLabel.textAndMnemonic = Nome del file: +FileChooser.fileSizeHeader.textAndMnemonic = Dimensione +FileChooser.fileTypeHeader.textAndMnemonic = Tipo +FileChooser.filesOfTypeLabel.textAndMnemonic = Tipo file: +FileChooser.folderNameLabel.textAndMnemonic = Nome cartella: +FileChooser.homeFolderToolTip.textAndMnemonic = Home +FileChooser.listViewActionLabel.textAndMnemonic = Elenco +FileChooser.listViewButtonToolTip.textAndMnemonic = Elenco +FileChooser.lookInLabel.textAndMnemonic = Guarda in: +FileChooser.newFolderActionLabel.textAndMnemonic = Nuova cartella +FileChooser.newFolderToolTip.textAndMnemonic = Crea nuova cartella +FileChooser.refreshActionLabel.textAndMnemonic = Aggiorna +FileChooser.saveInLabel.textAndMnemonic = Salva in: +FileChooser.upFolderToolTip.textAndMnemonic = Su di un livello +FileChooser.viewMenuButtonAccessibleName = Menu visuale +FileChooser.viewMenuButtonToolTipText = Layout +FileChooser.viewMenuLabel.textAndMnemonic = Layout +FileChooser.newFolderActionLabelText = Nuova cartella +FileChooser.listViewActionLabelText = Elenco +FileChooser.detailsViewActionLabelText = Dettagli +FileChooser.refreshActionLabelText = Aggiorna +FileChooser.sortMenuLabelText = Disponi icone per +FileChooser.viewMenuLabelText = Visualizza +FileChooser.fileSizeKiloBytes = {0} KB +FileChooser.fileSizeMegaBytes = {0} MB +FileChooser.fileSizeGigaBytes = {0} GB +FileChooser.folderNameLabelText = Nome cartella: + +error.occured = Si \u00e8 verificato un errore: %error% +button.abort = Annulla +button.retry = Riprova +button.ignore = Tralascia + +font.source = Font per i sorgenti: + +#after version 1.6.7: + +menu.export = Esporta +menu.general = Generale +menu.language = Lingua + +startup.welcometo = Benvenuto a +startup.selectopen = Per iniziare fare clic su Apri nel menu oppure trascinare un file SWF su questa finestra. +menu.file.reload = Ricarica +message.confirm.reload = Questa azione annulla tutte le modifiche non salvate e carica nuovamente il file SWF.\nConfermare? + +dialog.selectbkcolor.title = Scelta colore di sfondo + + +error.font.nocharacter = Il font sorgente selezionato non contiene il carattere "%char%". + +warning.initializers = I campi statici e le costanti sono spesso valorizzati negli initializer.\nLa modifica del valore qui spesso non \u00e8 sufficiente! + + +#after version 1.7.0u1: + +menu.tools.searchMemory = Cerca SWF in memoria +button.selectbkcolor.hint = Scelta colore di sfondo per lo SWF + +ColorChooser.okText = OK +ColorChooser.cancelText = Annulla +ColorChooser.resetText = Risetta +ColorChooser.previewText = Anteprima +ColorChooser.swatchesNameText = Palette +ColorChooser.swatchesRecentText = Recente: +ColorChooser.sampleText=Testo Campione Testo Campione + +#after version 1.7.1: + +preview.play = Riproduci +preview.pause = Pausa +preview.stop = Stop + +message.confirm.removemultiple = Confermare la rimozione di %count% elementi\n e tutti gli oggetti che ne dipendono? +menu.tools.searchCache = Cerca nella cache del browser + +#after version 1.7.2u2 + +error.trait.exists = Trait con nome "%name%" gi\u00e0 presente. +button.addtrait = Aggiungi trait +button.font.embed = Incorpora... +button.yes.all = S\u00ec a tutto +button.no.all = No a tutto +message.font.add.exists = Il carattere %char% esiste gi\u00e0 nel font tag.\nSostituirlo? + +filter.gfx = File ScaleForm GFX (*.gfx) +filter.supported = Tutti i formati supportati +work.canceled = Annullato +work.restoringControlFlow = Ripristino controllo di flusso in corso +menu.advancedsettings.advancedsettings = Impostazioni avanzate +menu.recentFiles = File recenti + +#after version 1.7.4 +work.restoringControlFlow.complete = Controllo di flusso ripristinato +message.confirm.recentFileNotFound = File non trovato. Rimuovere dalla lista dei file recenti? +contextmenu.closeSwf = Chiudi SWF +menu.settings.autoRenameIdentifiers = Autorinomina identificatori +menu.file.saveasexe = Crea eseguibile... +filter.exe = File eseguibile (*.exe) + +#after version 1.8.0 +font.updateTexts = Aggiorna testi + +#after version 1.8.0u1 +menu.file.close = Chiudi +menu.file.closeAll = Chiudi tutto +menu.tools.otherTools = Altro +menu.tools.otherTools.clearRecentFiles = Pulisci file recenti +fontName.name = Nome font visualizzato: +fontName.copyright = Copyright del font: +button.preview = Anteprima +button.reset = Risetta +errors.info = Ci sono INFORMAZIONI nel log. Fare clic per visualizzare. +errors.warning = Ci sono AVVISI nel log. Fare clic per visualizzare. + +decompilationError = Errore di decompilazione + +disassemblingProgress.toString = toString +disassemblingProgress.reading = Lettura +disassemblingProgress.deobfuscating = Deoffuscamento + +contextmenu.moveTag = Sposta tag + +filter.swc = File componente SWC (*.swc) +filter.zip = File compressi (*.zip) +filter.binary = Ricerca binaria - tutti i file (*.*) + +open.error = Errore +open.error.fileNotFound = File non trovato +open.error.cannotOpen = Non \u00e8 possibile aprire il file + +node.others = altro + +#after version 1.8.1 +menu.tools.search = Ricerca testuale + +#after version 1.8.1u1 +menu.tools.timeline = Timeline + +dialog.selectcolor.title = Seleziona il colore +button.selectcolor.hint = Fare clic per selezionare il colore + +#default item name, will be used in following sentences +generictag.array.item = elemento +generictag.array.insertbeginning = Inserire %item% all'inizio +generictag.array.insertbefore = Inserire %item% prima +generictag.array.remove = Rimuovi %item% +generictag.array.insertafter = Inserire %item% dopo +generictag.array.insertend = Inserire %item% alla fine + +#after version 2.0.0 +contextmenu.expandAll = Espandi tutto + +filter.sounds = Formati audio supportati (*.wav, *.mp3) +filter.sounds.wav = Formato file Wave (*.wav) +filter.sounds.mp3 = Formato MP3 compresso (*.mp3) + +error.sound.invalid = Audio non valido. + +button.prev = Precedente +button.next = Successivo + +#after version 2.1.0 +message.action.playerglobal.title = Libreria PlayerGlobal.swc mancante +message.action.playerglobal.needed = Per effettuare modifiche immediate in AS3 la libreria "PlayerGlobal.swc" deve essere scaricato dal sito di Adobe.\r\n%adobehomepage%\r\nPremere OK per visitare la pagina di download. +message.action.playerglobal.place = Scarica la libreria PlayerGlobal(.swc) e posizionala nella cartella \r\n%libpath%\r\nScegliere OK per continuare. + +message.confirm.experimental.function = Questa funzione \u00e8 SPERIMENTALE. Ci\u00f2 significa che non \u00e8 garantito il risultato ed il file SWF pu\u00f2 essere non funzionale dopo il salvataggio. +message.confirm.donotshowagain = Non mostrare pi\u00f9 il messaggio + +menu.import = Importa +menu.file.import.text = Importa testo +import.select.directory = Selezionare cartella di importazione +error.text.import = Errore durante l'importazione del testo. Continuare? + +#after version 2.1.1 +contextmenu.removeWithDependencies = Rimuovere assieme alle dipendenze + +abc.action.find-usages = Trova invocazioni +abc.action.find-declaration = Trova dichiarazione + +contextmenu.rawEdit = Modifica raw +contextmenu.jumpToCharacter = Vai al carattere + +menu.settings.dumpView = Visualizza Dump + +menu.view = Visualizza +menu.file.view.resources = Risorse +menu.file.view.hex = Hex dump + +node.header = header + +header.signature = Firma: +header.compression = Compressione: +header.compression.lzma = LZMA +header.compression.zlib = ZLIB +header.compression.none = Nessuna compressione +header.version = Versione SWF: +header.gfx = GFX: +header.filesize = Dimensione file: +header.framerate = Frequenza frame: +header.framecount = Conteggio frame: +header.displayrect = Rect di visualizzazione: +header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% twip +header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% pixel + +#after version 2.1.2 +contextmenu.saveToFile = Salva su file +contextmenu.parseActions = Analizza azioni +contextmenu.parseABC = Analizza ABC +contextmenu.parseInstructions = Analizza istruzioni AVM2 + +#after version 2.1.3 +menu.deobfuscation = Deoffuscamento +menu.file.deobfuscation.old = Vecchio stile +menu.file.deobfuscation.new = Nuovo stile + +#after version 2.1.4 +contextmenu.openswfinside = Apri SWF incorporato +binarydata.swfInside = Rilevato SWF all'interno di questo tag di dati binari. Fare clic qui per caricarlo come sottostruttura. + +#after version 3.0.0 +button.zoomin.hint = Ingrandisci +button.zoomout.hint = Riduci +button.zoomfit.hint = Mostra tutto +button.zoomnone.hint = Scala 1:1 +button.snapshot.hint = Crea istantanea negli Appunti + +editorTruncateWarning = Testo troncato alla posizione %chars% in modalit\u00e0 debug. + +#Font name which is presented in the SWF Font tag +font.name.intag = Nome font nel tag: + +menu.debugger = Debugger +menu.debugger.switch = Debugger +menu.debugger.replacetrace = Sostituisci invocazioni di trace +menu.debugger.showlog = Visualizza log + +message.debugger = Questo debugger SWF pu\u00f2 essere utilizzato solo per stampare messaggi nella finestra di log della console del browser o alert.\r\nNon offre caratteristiche come esecuzione passo-passo, breakpoint ecc. +contextmenu.addTag = Aggiungi tag +deobfuscation.comment.tryenable = Suggerimento: \u00e8 possibile provare ad abilitare il "deoffuscamento automatico" sotto Impostazioni +deobfuscation.comment.failed = Il deoffuscamento \u00e8 attivo ma la decompilazione non \u00e8 riuscita. Se il file non \u00e8 offuscato, disattivare "Deoffuscamento automatico" potrebbe dare risultati migliori. + +#after version 4.0.2 +preview.nextframe = Frame successivo +preview.prevframe = Frame precedente +preview.gotoframe = Vai a frame... + +preview.gotoframe.dialog.title = Vai a frame +preview.gotoframe.dialog.message = Inserire il numero del frame (%min% - %max%) +preview.gotoframe.dialog.frame.error = Numero del frame non valido. Deve essere tra %min% e %max%. + +error.text.invalid.continue = Testo non valido alla riga %line%: %text% . Si desidera continuare? + +#after version 4.0.5 +contextmenu.copyTag = Copia tag +fit = adattamento +button.setAdvanceValues = Impostare i valori di avanzamento + +menu.tools.replace = Sostituzione testo + +message.confirm.close = Vi sono modifiche non salvate. Chiudere {swfName} senza salvare? +message.confirm.closeAll = Vi sono modifiche non salvate. Vuoi davvero chiudere tutti i file SWF? + +contextmenu.exportJavaSource = Esporta sorgente Java +contextmenu.exportSwfXml = Esporta SWF come XML +contextmenu.importSwfXml = Importa SWF da XML + +filter.xml = File XML (*.xml) + +#after version 4.1.0 +contextmenu.undo = Annulla + +text.align.left = Allinea a sinistra +text.align.right = Allinea a destra +text.align.center = Centrato +text.align.justify = Giustificato + +text.undo = Annulla le modifiche + +menu.file.import.xml = Importa SWF da XML +menu.file.export.xml = Esporta SWF come XML + +#after version 4.1.1 +text.align.translatex.decrease = Riduci TranslateX +text.align.translatex.increase = Incementa TranslateX +selectPreviousTag = Selezionare tag precedente +selectNextTag = Selezionare tag successivo +button.ignoreAll = Ignora tutto +menu.file.import.symbolClass = Importa classe di simbolo +text.toggleCase = Alterna maiuscole/minuscole + +#after version 5.0.2 +preview.loop = Cicla +menu.file.import.script = Importa script +contextmenu.copyTagWithDependencies = Copia tag con le dipendenze +button.replaceWithTag = Sostituisci con altro tag di carattere +button.resolveConstants = Risolvi le costanti + +#after version 5.1.0 +button.viewConstants = Visualizza le costanti +work.exported = Esportato +button.replaceAlphaChannel = Sostituire canale alfa... + +tagInfo.header.name = Nome +tagInfo.header.value = Valore +tagInfo.tagType = Tipo tag +tagInfo.characterId = Id carattere +tagInfo.offset = Offset +tagInfo.length = Lunghezza +tagInfo.bounds = Limiti +tagInfo.width = Larghezza +tagInfo.height = Altezza +tagInfo.neededCharacters = Caratteri necessari + +button.viewhexpcode = Mostra valori byte assieme alle istruzioni +taginfo.header = Informazioni tag di base + +tagInfo.dependentCharacters = Caratteri dipendenti + +#after version 5.3.0 +header.uncompressed = Non compresso +header.warning.unsupportedGfxCompression = GFX supporta solo contenuto non compresso o compresso con Zlib. +header.warning.minimumZlibVersion = La compressione zlib richiede SWF versione 6 o superiore. +header.warning.minimumLzmaVersion = la compressione LZMA richiede SWF versione 13 o superiore. + +tagInfo.codecName = Nome codec +tagInfo.exportFormat = Formato di esportazione +tagInfo.samplingRate = Frequenza di campionamento +tagInfo.stereo = Stereo +tagInfo.sampleCount = Conteggio campioni + +filter.dmg = Eseguibili Mac (*.dmg) +filter.linuxExe = Eseguibili Linux + +import.script.result = Importati %count% script. +import.script.as12warning = Importa script pu\u00f2 importare solo script AS1/2. + +error.constantPoolTooBig = Constant pool troppo grande. indice=%index%, dimensioni=%size% +error.image.alpha.invalid = Valori canale alfa non validi. + +#after version 6.0.2 +contextmenu.saveUncompressedToFile = Salva su file senza compressione +abc.traitslist.scriptinitializer = Inizializzatore script +menu.settings.autoOpenLoadedSWFs = Apri SWF caricati durante la riproduzione + +#after version 6.1.1 +menu.file.start = Avvio +menu.file.start.run = Esegui +menu.file.start.stop = Arresta +menu.file.start.debug = Debug +menu.debugging = Debug +menu.debugging.debug = Debug +menu.debugging.debug.stop = Ferma +menu.debugging.debug.pause = Pausa +menu.debugging.debug.stepOver = Passo successivo +menu.debugging.debug.stepInto = Entra nel metodo +menu.debugging.debug.stepOut = Risali dal metodo +menu.debugging.debug.continue = Continua +menu.debugging.debug.stack = Stack... +menu.debugging.debug.watch = Nuovo osservatore... + + +message.playerpath.notset = Proiettore Flash Player non trovato. Si prega di configurarne il percorso in Impostazioni avanzate / Percorsi (1). +message.playerpath.debug.notset = Proiettore Flash Player debugger di contenuto non trovato. Si prega di configurarne il percorso in Impostazioni avanzate / Percorsi (2). +message.playerpath.lib.notset = PlayerGlobal (.swc) non trovato. Si prega di configurarne il percorso in Impostazioni avanzate / Percorsi (3). + +debugpanel.header = Debug + +variables.header.registers = Registri +variables.header.locals = Variabili locali +variables.header.arguments = Argomenti +variables.header.scopeChain = Catena visibilit\u00e0 delle variabili +variables.column.name = Nome +variables.column.type = Tipo +variables.column.value = Valore + +callStack.header = Stack chiamate di funzione +callStack.header.file = File +callStack.header.line = Riga + +stack.header = Stack +stack.header.item = Voce + +constantpool.header = Pool delle costanti +constantpool.header.id = Id +constantpool.header.value = Valore + +work.running = In esecuzione +work.debugging = Debug in corso +work.debugging.instrumenting = Preparazione SWF per il debug +work.breakat = Interrompi a +work.halted = Debug iniziato, esecuzione sospesa. Aggiungi i breakpoint e scegli Continua (F5) per riprendere l'esecuzione. + +debuglog.header = Log +debuglog.button.clear = Pulisci + +# after 7.0.1 +work.debugging.wait = In attesa di connessione proiettore Flash debugger + +error.debug.listen = Impossibile ascoltare la porta %porta%. Potrebbe esserci un altro debugger in esecuzione. + +debug.break.reason.unknown = (Sconosciuto) +debug.break.reason.breakpoint = (Breakpoint) +debug.break.reason.watch = (Watch) +debug.break.reason.fault = (Fault) +debug.break.reason.stopRequest = (Richiesta di stop) +debug.break.reason.step = (Passo) +debug.break.reason.halt = (Halt) +debug.break.reason.scriptLoaded = (Script caricato) + +menu.file.start.debugpcode = Debug P-code + +# after 7.1.2 +button.replaceNoFill = Sostituisci - Aggiorna limiti... +message.warning.svgImportExperimental = Non tutte le funzioni SVG sono supportate. Controllare il registro dopo l'importazione. +message.imported.swf = Il file SWF utilizza asset da un file SWF importato:\n%url%\nCaricare gli asset da quell'indirizzo? +message.imported.swf.manually = Impossibile caricare SWF importato\n%url%\nFile o URL non esistente.\nSelezionare un file locale? + +message.warning.hexViewNotUpToDate = Hex View non aggiornato. Si prega di salvare e ricaricare il file per aggiornare la visuale. +message.font.replace.updateTexts = Sono stati sostituiti alcuni caratteri. Aggiornare i testi esistenti? + +menu.settings.simplifyExpressions = Semplifica espressioni + +#after 8.0.1 +menu.recentFiles.empty = Lista file recenti vuota +message.warning.outOfMemory32BitJre = Errore di memoria esaurita. Stai eseguendo Java a 32bit su sistema operativo a 64bit. Prova con Java a 64bit. + +menu.file.reloadAll = Ricarica tutto +message.confirm.reloadAll = Questa azione annulla le modifiche non salvate in tutti i file SWF e ricarica l'intera applicazione.\nDesideri continuare? +export.script.singleFilePallelModeWarning = L'esportazione di script su singolo file non \u00e8 supportata con accelerazione parallela abilitata + +button.showOriginalBytesInPcodeHex = Mostra byte originali +button.remove = Rimuovi