Added: Allow obfuscated DefineEditText variable identifiers

This commit is contained in:
Jindra Petřík
2025-07-02 22:59:16 +02:00
parent e317551d57
commit 603a7dce49
4 changed files with 241 additions and 109 deletions
@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -55,10 +56,12 @@ import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.DottedIdentifier;
import com.jpexs.decompiler.flash.types.annotations.EnumValue;
import com.jpexs.decompiler.flash.types.annotations.Multiline;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import com.jpexs.helpers.utf8.Utf8Helper;
@@ -175,6 +178,7 @@ public class DefineEditTextTag extends TextTag {
@Conditional("hasLayout")
public int leading;
@DottedIdentifier
public String variableName;
@Conditional("hasText")
@@ -656,7 +660,7 @@ public class DefineEditTextTag extends TextTag {
writer.append("leading ").append(leading).newLine();
}
if (!variableName.isEmpty()) {
writer.append("variablename ").append(variableName).newLine();
writer.append("variablename ").append(DottedChain.parseNoSuffix(variableName).toPrintableString(false)).newLine();
}
writer.append("]");
if (hasText) {
@@ -1,5 +1,7 @@
/* The following code was generated by JFlex 1.6.0 */
/*
* Copyright (C) 2010-2025 JPEXS, All rights reserved.
* 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
@@ -35,7 +37,8 @@ public final class TextLexer {
public static final int YYINITIAL = 0;
public static final int PARAMETER = 2;
public static final int VALUE = 4;
public static final int STRING = 6;
public static final int OIDENTIFIER = 6;
public static final int STRING = 8;
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
@@ -44,18 +47,18 @@ public final class TextLexer {
* l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2, 3, 3
0, 0, 1, 1, 2, 2, 3, 3, 4, 4
};
/**
* Translates characters to character classes
*/
private static final String ZZ_CMAP_PACKED =
"\12\0\1\11\1\22\1\22\1\11\22\0\1\4\1\0\1\10\4\0"+
"\1\20\10\0\12\2\7\0\6\5\24\0\1\12\1\7\1\3\1\0"+
"\1\1\1\0\1\6\1\13\3\6\1\16\7\1\1\15\3\1\1\17"+
"\1\1\1\14\1\23\2\1\1\21\2\1\12\0\1\22\u1fa2\0\1\22"+
"\1\22\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\udfe6\0";
"\12\0\1\11\1\26\1\26\1\15\22\0\1\4\1\0\1\10\4\0"+
"\1\24\10\0\1\13\11\2\7\0\6\5\24\0\1\16\1\7\1\3"+
"\1\0\1\1\1\0\1\6\1\17\3\6\1\22\2\1\1\14\4\1"+
"\1\21\3\1\1\23\1\1\1\20\1\27\2\1\1\25\2\1\1\30"+
"\1\0\1\31\7\0\1\26\41\0\1\12\u1f80\0\1\26\1\26\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\uffff\0\udfe6\0";
/**
* Translates characters to character classes
@@ -68,14 +71,16 @@ public final class TextLexer {
private static final int [] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\4\0\2\1\1\2\1\3\1\4\1\5\1\6\1\7"+
"\1\10\1\11\1\12\1\2\1\13\1\14\1\15\1\16"+
"\1\17\1\20\1\21\1\22\1\23\1\24\1\25\1\26"+
"\1\14\1\27\1\30\1\31\1\32\1\33\1\34\1\35"+
"\1\36\1\37\2\27\2\0\1\40\1\0";
"\5\0\2\1\1\2\1\3\1\4\1\5\1\6\1\7"+
"\1\10\1\11\1\12\1\13\1\2\1\14\1\15\1\14"+
"\1\16\1\2\1\17\1\20\1\21\1\22\1\23\1\24"+
"\1\25\1\26\1\27\1\30\1\31\1\32\1\20\1\33"+
"\1\34\1\35\1\36\1\37\1\40\1\41\3\20\1\42"+
"\1\43\1\44\1\45\1\46\1\47\1\50\1\51\1\52"+
"\2\42\6\0\1\53\1\54\2\0\1\55\1\0";
private static int [] zzUnpackAction() {
int [] result = new int[44];
int [] result = new int[69];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@@ -100,15 +105,18 @@ public final class TextLexer {
private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\24\0\50\0\74\0\120\0\144\0\120\0\120"+
"\0\170\0\120\0\214\0\240\0\264\0\120\0\310\0\334"+
"\0\120\0\120\0\120\0\120\0\120\0\120\0\120\0\120"+
"\0\120\0\120\0\120\0\120\0\360\0\120\0\120\0\120"+
"\0\120\0\120\0\120\0\120\0\120\0\120\0\360\0\u0104"+
"\0\u0118\0\u012c\0\120\0\360";
"\0\0\0\32\0\64\0\116\0\150\0\202\0\234\0\202"+
"\0\202\0\266\0\202\0\320\0\352\0\u0104\0\202\0\202"+
"\0\202\0\u011e\0\202\0\202\0\u0138\0\u0152\0\u016c\0\202"+
"\0\202\0\202\0\202\0\202\0\202\0\202\0\202\0\202"+
"\0\202\0\202\0\202\0\u0186\0\202\0\202\0\202\0\202"+
"\0\202\0\202\0\202\0\u01a0\0\u01ba\0\u01d4\0\202\0\202"+
"\0\202\0\202\0\202\0\202\0\202\0\202\0\202\0\u0186"+
"\0\u01ee\0\u0208\0\u0222\0\u023c\0\u0256\0\u0270\0\u028a\0\202"+
"\0\202\0\u01a0\0\u02a4\0\202\0\u0186";
private static int [] zzUnpackRowMap() {
int [] result = new int[44];
int [] result = new int[69];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@@ -131,27 +139,43 @@ public final class TextLexer {
private static final int [] ZZ_TRANS = zzUnpackTrans();
private static final String ZZ_TRANS_PACKED_0 =
"\7\5\1\6\1\5\1\7\1\10\7\5\1\7\1\5"+
"\1\7\1\11\1\7\1\12\1\13\1\7\1\11\2\7"+
"\1\13\1\7\5\11\1\7\1\11\1\7\1\11\1\14"+
"\1\15\1\14\1\12\1\13\1\14\1\15\1\14\1\16"+
"\1\13\1\14\5\15\1\14\1\15\1\14\1\15\7\17"+
"\1\20\1\21\1\7\12\17\24\0\3\22\1\23\3\22"+
"\1\24\1\25\1\0\1\26\1\27\1\30\1\31\1\32"+
"\1\33\1\34\1\35\1\0\1\22\1\0\2\11\3\0"+
"\1\11\4\0\5\11\1\0\1\11\1\0\1\11\4\0"+
"\1\13\4\0\1\13\12\0\3\14\2\0\3\14\2\0"+
"\13\14\2\15\2\0\1\14\1\15\1\14\2\0\1\14"+
"\5\15\1\14\1\15\1\14\1\15\7\17\3\0\12\17"+
"\7\36\1\37\1\40\1\0\1\36\1\41\1\42\1\43"+
"\1\44\1\45\1\46\1\47\1\0\1\50\2\0\1\51"+
"\2\0\2\51\4\0\1\51\2\0\1\51\7\0\1\52"+
"\2\0\2\52\4\0\1\52\2\0\1\52\7\0\1\53"+
"\2\0\2\53\4\0\1\53\2\0\1\53\7\0\1\54"+
"\2\0\2\54\4\0\1\54\2\0\1\54\5\0";
"\7\6\1\7\1\6\1\10\3\6\1\10\1\11\7\6"+
"\1\10\3\6\1\10\1\12\1\10\1\13\1\14\1\10"+
"\1\12\2\10\1\14\2\10\1\12\1\14\1\10\5\12"+
"\1\10\1\12\1\10\1\12\2\10\1\15\1\16\1\15"+
"\1\13\1\14\1\15\1\16\1\15\1\17\1\14\1\20"+
"\1\15\1\16\1\14\1\15\5\16\1\15\1\16\1\15"+
"\1\16\2\15\7\21\1\22\1\21\1\23\1\24\2\21"+
"\1\25\14\21\7\26\1\27\1\30\1\10\3\26\1\10"+
"\14\26\32\0\3\31\1\32\3\31\1\33\1\34\1\0"+
"\3\31\1\0\1\35\1\36\1\37\1\40\1\41\1\42"+
"\1\43\1\44\1\0\3\31\1\0\2\12\3\0\1\12"+
"\4\0\2\12\2\0\5\12\1\0\1\12\1\0\1\12"+
"\6\0\1\14\4\0\1\14\3\0\1\14\14\0\3\15"+
"\2\0\3\15\3\0\2\15\1\0\15\15\2\16\2\0"+
"\1\15\1\16\1\15\3\0\2\16\1\0\1\15\5\16"+
"\1\15\1\16\1\15\1\16\2\15\7\31\1\45\1\31"+
"\1\0\1\46\2\31\1\0\1\31\1\47\1\50\1\51"+
"\1\52\1\53\1\31\1\54\1\0\1\55\1\56\1\31"+
"\11\0\1\23\20\0\7\26\3\0\3\26\1\0\14\26"+
"\7\57\1\60\1\61\1\0\3\57\1\0\1\57\1\62"+
"\1\63\1\64\1\65\1\66\1\67\1\70\1\0\1\71"+
"\2\57\2\0\1\72\2\0\2\72\4\0\1\72\3\0"+
"\1\72\2\0\1\72\11\0\1\73\2\0\2\73\4\0"+
"\1\73\3\0\1\73\2\0\1\73\11\0\1\74\2\0"+
"\2\74\4\0\1\74\3\0\1\74\2\0\1\74\11\0"+
"\1\75\10\0\1\76\20\0\1\77\2\0\2\77\4\0"+
"\1\77\3\0\1\77\2\0\1\77\11\0\1\100\2\0"+
"\2\100\4\0\1\100\3\0\1\100\2\0\1\100\11\0"+
"\1\101\2\0\2\101\4\0\1\101\3\0\1\101\2\0"+
"\1\101\11\0\1\102\2\0\2\102\4\0\1\102\3\0"+
"\1\102\2\0\1\102\11\0\1\75\10\0\1\75\1\103"+
"\12\0\1\103\1\0\1\104\14\0\1\103\12\0\1\103"+
"\1\0\1\104\2\0\1\105\2\0\2\105\4\0\1\105"+
"\3\0\1\105\2\0\1\105\40\0\1\104";
private static int [] zzUnpackTrans() {
int [] result = new int[320];
int [] result = new int[702];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
@@ -189,11 +213,12 @@ public final class TextLexer {
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\4\0\1\11\1\1\2\11\1\1\1\11\3\1\1\11"+
"\2\1\14\11\1\1\11\11\2\1\2\0\1\11\1\0";
"\5\0\1\11\1\1\2\11\1\1\1\11\3\1\3\11"+
"\1\1\2\11\3\1\14\11\1\1\7\11\3\1\11\11"+
"\2\1\6\0\2\11\2\0\1\11\1\0";
private static int [] zzUnpackAttribute() {
int [] result = new int[44];
int [] result = new int[69];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@@ -270,10 +295,12 @@ public final class TextLexer {
/* user code: */
boolean finish = false;
boolean parameter = false;
private boolean finish = false;
private boolean parameter = false;
StringBuilder string = null;
private StringBuilder string = null;
private int repeatNum = 1;
/**
* Create an empty lexer, yyrset will be called later to reset and assign
@@ -313,7 +340,7 @@ public final class TextLexer {
char [] map = new char[0x110000];
int i = 0; /* index in packed string */
int j = 0; /* index in unpacked array */
while (i < 116) {
while (i < 132) {
int count = packed.charAt(i++);
char value = packed.charAt(i++);
do map[j++] = value; while (--count > 0);
@@ -662,11 +689,11 @@ public final class TextLexer {
case 1:
{ if (string == null) string = new StringBuilder(); string.append(yytext());
}
case 33: break;
case 46: break;
case 2:
{ if (!parameter) { if (string == null) string = new StringBuilder(); string.append(yytext()); }
}
case 34: break;
case 47: break;
case 3:
{ parameter = true;
yybegin(PARAMETER);
@@ -676,131 +703,190 @@ public final class TextLexer {
return new ParsedSymbol(SymbolType.TEXT, ret);
}
}
case 35: break;
case 48: break;
case 4:
{ yybegin(VALUE);
return new ParsedSymbol(SymbolType.PARAMETER_IDENTIFIER, yytext());
}
case 36: break;
case 49: break;
case 5:
{ yybegin(YYINITIAL);
parameter = false;
}
case 37: break;
case 50: break;
case 6:
{
}
case 38: break;
case 51: break;
case 7:
{ return new ParsedSymbol(SymbolType.PARAMETER_VALUE, yytext());
}
case 39: break;
case 52: break;
case 8:
{ return new ParsedSymbol(SymbolType.PARAMETER_IDENTIFIER, yytext());
}
case 40: break;
case 53: break;
case 9:
{ string = new StringBuilder();
yybegin(STRING);
}
case 41: break;
case 54: break;
case 10:
{ string = new StringBuilder();
yybegin(OIDENTIFIER);
}
case 55: break;
case 11:
{ for(int r=0;r<repeatNum;r++) string.append(yytext()); repeatNum = 1;
}
case 56: break;
case 12:
{ yybegin(VALUE); yyline++;
}
case 57: break;
case 13:
{ yybegin(VALUE);
repeatNum = 1;
// length also includes the trailing quote
String ret = string.toString();
string = null;
return new ParsedSymbol(SymbolType.PARAMETER_VALUE, ret);
}
case 58: break;
case 14:
{ string.append(yytext());
}
case 42: break;
case 11:
case 59: break;
case 15:
{ yybegin(VALUE);
// length also includes the trailing quote
String tos = string.toString();
string = null;
return new ParsedSymbol(SymbolType.PARAMETER_VALUE, tos);
}
case 43: break;
case 12:
case 60: break;
case 16:
{ throw new TextParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1);
}
case 44: break;
case 13:
case 61: break;
case 17:
{ if (string == null) string = new StringBuilder(); string.append(']');
}
case 45: break;
case 14:
case 62: break;
case 18:
{ if (string == null) string = new StringBuilder(); string.append('\\');
}
case 46: break;
case 15:
case 63: break;
case 19:
{ if (string == null) string = new StringBuilder(); string.append('\"');
}
case 47: break;
case 16:
case 64: break;
case 20:
{ if (string == null) string = new StringBuilder(); string.append('[');
}
case 48: break;
case 17:
case 65: break;
case 21:
{ if (string == null) string = new StringBuilder(); string.append('\b');
}
case 49: break;
case 18:
case 66: break;
case 22:
{ if (string == null) string = new StringBuilder(); string.append('\t');
}
case 50: break;
case 19:
case 67: break;
case 23:
{ if (string == null) string = new StringBuilder(); string.append('\n');
}
case 51: break;
case 20:
case 68: break;
case 24:
{ if (string == null) string = new StringBuilder(); string.append('\f');
}
case 52: break;
case 21:
case 69: break;
case 25:
{ if (string == null) string = new StringBuilder(); string.append('\r');
}
case 53: break;
case 22:
case 70: break;
case 26:
{ if (string == null) string = new StringBuilder(); string.append('\'');
}
case 54: break;
case 23:
case 71: break;
case 27:
{ for(int r=0;r<repeatNum;r++) string.append('\\'); repeatNum = 1;
}
case 72: break;
case 28:
{ for(int r=0;r<repeatNum;r++) string.append('\u00A7'); repeatNum = 1;
}
case 73: break;
case 29:
{ for(int r=0;r<repeatNum;r++) string.append('\b'); repeatNum = 1;
}
case 74: break;
case 30:
{ for(int r=0;r<repeatNum;r++) string.append('\t'); repeatNum = 1;
}
case 75: break;
case 31:
{ for(int r=0;r<repeatNum;r++) string.append('\n'); repeatNum = 1;
}
case 76: break;
case 32:
{ for(int r=0;r<repeatNum;r++) string.append('\f'); repeatNum = 1;
}
case 77: break;
case 33:
{ for(int r=0;r<repeatNum;r++) string.append('\r'); repeatNum = 1;
}
case 78: break;
case 34:
{ /* ignore illegal character escape */
}
case 55: break;
case 24:
case 79: break;
case 35:
{ string.append('\\');
}
case 56: break;
case 25:
case 80: break;
case 36:
{ string.append('\"');
}
case 57: break;
case 26:
case 81: break;
case 37:
{ string.append('\b');
}
case 58: break;
case 27:
case 82: break;
case 38:
{ string.append('\t');
}
case 59: break;
case 28:
case 83: break;
case 39:
{ string.append('\n');
}
case 60: break;
case 29:
case 84: break;
case 40:
{ string.append('\f');
}
case 61: break;
case 30:
case 85: break;
case 41:
{ string.append('\r');
}
case 62: break;
case 31:
case 86: break;
case 42:
{ string.append('\'');
}
case 63: break;
case 32:
case 87: break;
case 43:
{ char val = (char) Integer.parseInt(yytext().substring(2), 16);
string.append(val);
}
case 64: break;
case 88: break;
case 44:
{ char val = (char) Integer.parseInt(yytext().substring(2), 16);
for(int r=0;r<repeatNum;r++) string.append(val); repeatNum = 1;
}
case 89: break;
case 45:
{ repeatNum = Integer.parseInt(yytext().substring(2, yytext().length()-1));
}
case 90: break;
default:
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;
@@ -808,7 +894,7 @@ public final class TextLexer {
case YYINITIAL: {
if (finish) {return null;} else {finish=true; return new ParsedSymbol(SymbolType.TEXT, string == null ? null : string.toString());}
}
case 45: break;
case 70: break;
default:
{
return null;