@@ -58,7 +58,6 @@ FREObject InsertABCToSWF(FREContext, void*, uint32_t argc, FREObject argv[])
5858 DO_OR_FAIL (" Failed to acquire SWF bytearray" , FREAcquireByteArray (swf, &swfData));
5959 tags = SWF::SWFFile::getTagsFrom ({swfData.bytes , swfLength});
6060
61- static_assert (std::endian::native == std::endian::little);
6261 swfData.bytes [4 ] = uint8_t (finalSize);
6362 swfData.bytes [5 ] = uint8_t (finalSize >> 8 );
6463 swfData.bytes [6 ] = uint8_t (finalSize >> 16 );
@@ -67,101 +66,96 @@ FREObject InsertABCToSWF(FREContext, void*, uint32_t argc, FREObject argv[])
6766 FREByteArray abcData;
6867 DO_OR_FAIL (" Failed to acquire ABC bytearray" , FREAcquireByteArray (abc, &abcData));
6968
70- size_t currentTag = 0 ;
71- while (currentTag < tags.size () && tags[currentTag].type != TagType::DoABC2 &&
72- tags[currentTag].type != TagType::End)
73- {
74- currentTag++;
75- }
76-
77- if (currentTag == tags.size ())
69+ auto shiftTags = [&tags, &swfData](size_t currentTag, ptrdiff_t shiftBy,
70+ std::optional<TagType> excludeType = std::nullopt )
7871 {
79- DO_OR_FAIL (" Failed to release swf bytearray" , FREReleaseByteArray (swf));
80- DO_OR_FAIL (" Failed to release abc bytearray" , FREReleaseByteArray (abc));
81- FAIL (" No ABC or end tag in this SWF. Is it really an SWF?" );
82- }
72+ std::vector<ptrdiff_t > localOffsets (tags.size ());
8373
84- if (tags[currentTag].type == TagType::End)
85- {
86- std::copy (abcData.bytes , abcData.bytes + abcData.length ,
87- swfData.bytes + std::distance ((const uint8_t *)swfData.bytes ,
88- getTagOrigStart (tags[currentTag])));
89-
90- swfData.bytes [finalSize - 2 ] = 0 ;
91- swfData.bytes [finalSize - 1 ] = 0 ;
92- }
93- else if (currentTag < tags.size () - 1 )
94- {
95- std::vector<ptrdiff_t > localOffsets (tags.size () - currentTag - 1 );
74+ // Get the offsets for all the tags we need to copy
75+ for (size_t i = currentTag; i < tags.size (); i++)
9676 {
97- ptrdiff_t globalOffset = std::distance ((const uint8_t *)swfData.bytes ,
98- getTagOrigStart (tags[currentTag])) +
99- abcLength;
100-
101- // Get the offsets for all the tags we need to copy
102- for (size_t i = currentTag + 1 ; i < tags.size (); i++)
77+ localOffsets[i] = shiftBy;
78+ if (tags[i].type == excludeType)
10379 {
104- localOffsets[i - currentTag - 1 ] =
105- globalOffset -
106- std::distance ((const uint8_t *)swfData.bytes , getTagOrigStart (tags[i]));
107- if (tags[i].type != TagType::DoABC2)
108- {
109- globalOffset += getTagTotalSize (tags[i]);
110- }
80+ shiftBy -= getTagTotalSize (tags[i]);
11181 }
11282 }
11383
11484 // Then copy them, forwards if they go backwards and backwards if they go forwards
11585 // - This ensures that you don't copy copied data
116- for (size_t i = 0 ; i < localOffsets .size (); i++)
86+ for (size_t i = currentTag ; i < tags .size (); i++)
11787 {
118- const auto & tag = tags[currentTag + 1 + i];
88+ auto & tag = tags[i];
11989 if (localOffsets[i] < 0 )
12090 {
121- if (tag.type != TagType::DoABC2 )
91+ if (tag.type != excludeType )
12292 {
12393 tag.writeTo (
12494 swfData.bytes +
12595 std::distance ((const uint8_t *)swfData.bytes , getTagOrigStart (tag)) +
12696 localOffsets[i]);
97+ tag.data += localOffsets[i];
12798 }
12899 }
129- else
130- {
131- break ;
132- }
133100 }
134- for (size_t i = localOffsets .size (); i > 0 ; i--)
101+ for (size_t i = tags .size (); i > currentTag ; i--)
135102 {
136- const auto & tag = tags[currentTag + 1 + i - 1 ];
103+ auto & tag = tags[i - 1 ];
137104 if (localOffsets[i - 1 ] > 0 )
138105 {
139- if (tag.type != TagType::DoABC2 )
106+ if (tag.type != excludeType )
140107 {
141108 tag.writeToBackwards (
142109 swfData.bytes +
143110 std::distance ((const uint8_t *)swfData.bytes , getTagOrigStart (tag)) +
144111 localOffsets[i - 1 ]);
112+ tag.data += localOffsets[i - 1 ];
145113 }
146114 }
147- else
148- {
149- break ;
150- }
151115 }
116+ };
117+
118+ auto overwriteData = [&](FREByteArray copyIn, ptrdiff_t offset)
119+ {
120+ // And add the actual new data in
121+ std::copy (copyIn.bytes , copyIn.bytes + copyIn.length , swfData.bytes + offset);
122+ };
152123
153- // And add the actual new ABC data in
154- std::copy (abcData.bytes , abcData.bytes + abcLength,
155- swfData.bytes + std::distance ((const uint8_t *)swfData.bytes ,
156- getTagOrigStart (tags[currentTag])));
124+ bool doneABC = false ;
125+ int doneSymbolClass = 0 ;
126+
127+ size_t currentTag = 0 ;
128+ while (currentTag < tags.size () && tags[currentTag].type != TagType::End)
129+ {
130+ if (!doneABC && tags[currentTag].type == TagType::DoABC2)
131+ {
132+ shiftTags (currentTag + 1 ,
133+ ptrdiff_t (abcLength) - ptrdiff_t (getTagTotalSize (tags[currentTag])),
134+ TagType::DoABC2);
135+ overwriteData (abcData, std::distance ((const uint8_t *)swfData.bytes ,
136+ getTagOrigStart (tags[currentTag])));
137+ doneABC = true ;
138+ }
139+ currentTag++;
157140 }
158- else
141+
142+ if (currentTag == tags.size ())
159143 {
160144 DO_OR_FAIL (" Failed to release swf bytearray" , FREReleaseByteArray (swf));
161145 DO_OR_FAIL (" Failed to release abc bytearray" , FREReleaseByteArray (abc));
162- FAIL (" End tag is missing " );
146+ FAIL (" No end tag in this SWF. Is it really an SWF? " );
163147 }
164148
149+ if (!doneABC)
150+ {
151+ DO_OR_FAIL (" Failed to release swf bytearray" , FREReleaseByteArray (swf));
152+ DO_OR_FAIL (" Failed to release abc bytearray" , FREReleaseByteArray (abc));
153+ FAIL (" No ABC tag present in this SWF." );
154+ }
155+
156+ swfData.bytes [finalSize - 2 ] = 0 ;
157+ swfData.bytes [finalSize - 1 ] = 0 ;
158+
165159 DO_OR_FAIL (" Failed to release swf bytearray" , FREReleaseByteArray (swf));
166160 DO_OR_FAIL (" Failed to release abc bytearray" , FREReleaseByteArray (abc));
167161
0 commit comments