001: /* *****************************************************************************
002: extract tags from swf file
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2006 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.test;
011:
012: import java.io.*;
013: import java.util.zip.*;
014:
015: public class etag {
016:
017: /* usage:
018: etag tagid [nth]
019: reads from stdin, writes to stdout
020:
021: */
022:
023: public static int BUFFER_SIZE = 10240;
024:
025: public static int send(InputStream input, OutputStream output,
026: int size) throws IOException {
027: int c = 0;
028: byte[] buffer = new byte[size];
029: int b = 0;
030: while ((b = input.read(buffer)) > 0) {
031: c += b;
032: output.write(buffer, 0, b);
033: }
034: return c;
035: }
036:
037: public static int send(InputStream input, OutputStream output)
038: throws IOException {
039:
040: int available = input.available();
041: int bsize;
042: if (available == 0) {
043: bsize = BUFFER_SIZE;
044: } else {
045: bsize = Math.min(input.available(), BUFFER_SIZE);
046: }
047: return send(input, output, bsize);
048: }
049:
050: public static byte[] readFileBytes(InputStream istr, int skip)
051: throws IOException {
052: byte bytes[] = new byte[istr.available()];
053: System.err.println("read " + istr.available()
054: + " bytes from input stream");
055: istr.read(bytes);
056: istr.close();
057:
058: byte bytes2[] = new byte[bytes.length - skip];
059:
060: System.arraycopy(bytes, skip, bytes2, 0, bytes2.length);
061: return bytes2;
062: }
063:
064: /* Compute the number of bytes occupied by a RECT record, which starts
065: * at OFFSET in DATA.
066: */
067: public static int findRectLength(byte data[], int offset) {
068: int bsize = data[offset] >> 3;
069: //System.out.println("rect bits = "+bsize);
070: int nbits = bsize * 4;
071: int nbytes = (int) Math.ceil((5 + nbits) / 8.0);
072: //System.out.println("nbytes = "+nbytes);
073: return nbytes;
074:
075: }
076:
077: /*
078:
079: This header has been stripped:
080: Signature UI8 Signature byte: C
081: Signature UI8 Signature byte always “W”
082: Signature UI8 Signature byte always “S”
083: Version UI8 Single byte file version (for example, 0x06 for SWF 6)
084: FileLength UI32 Length of entire file in bytes
085:
086:
087:
088: xmin xmax ymin ymax
089:
090: 0 500 0 375
091: 1f4 177
092:
093: We get:
094: FrameSize RECT Frame size in twips
095: FrameRate UI16 Frame delay in 8.8 fixed number of frames per second
096: FrameCount UI16 Total number of frames in movie
097:
098: 2 frames , 24 fps ,500 x 375
099:
100: ================
101: RECT [5] n n n n
102: pad to byte boundary
103: ================
104:
105: TAG = UI16 :=
106:
107: upper 10 bits = code
108:
109: TagID = Code >> 6;
110: Length = Code & 0x3f;
111:
112: if length = 3f, LENGTH = UI32
113:
114: UI16 code/len=3f
115: UI32 length
116: */
117:
118: static class TagNotFoundException extends RuntimeException {
119:
120: }
121:
122: /** Scan for the nth tag matching TAG, return the contents **/
123: static byte[] getTag(int tag, int nth, byte data[], int offset)
124: throws TagNotFoundException {
125: int nth1 = nth;
126: int index = offset;
127: System.err.println("searching for " + Integer.toString(tag, 16)
128: + " [" + nth + "]");
129: while (index < data.length) {
130: int ptag = (data[index] & 0xff)
131: | ((data[index + 1] << 8) & 0xff00);
132: int tagid = ((ptag & 0xffc0) >> 6);
133: int taglen = (ptag & 0x3f);
134:
135: int oindex = index;
136: index += 2;
137:
138: if (taglen == 0x3f) {
139: // it's a long tag, get length from following UI32
140: taglen = (data[index] & 0xff)
141: | ((data[index + 1] << 8) & 0xff00)
142: | ((data[index + 2] << 16) & 0xff0000)
143: | ((data[index + 3] << 24) & 0xff000000);
144: index += 4;
145: }
146:
147: // System.err.println("tagid = "+Integer.toString(tagid, 16)+", length = "+taglen);
148:
149: if (tagid == tag) {
150: if (nth == 0) {
151: byte bytes2[] = new byte[taglen];
152: System.arraycopy(data, index, bytes2, 0,
153: bytes2.length);
154: System.err.println("match found for occurence "
155: + nth1 + " length=" + bytes2.length);
156: return bytes2;
157: } else {
158: nth--;
159: }
160: }
161:
162: index += taglen;
163: }
164: throw new TagNotFoundException();
165: }
166:
167: static void printTag(byte data[], OutputStream os)
168: throws IOException {
169: System.err.println("writing " + data.length
170: + " bytes to output");
171: for (int i = 0; i < data.length; i++) {
172: os.write(data[i]);
173: }
174: }
175:
176: static public void main(String args[]) {
177: try {
178: byte data[] = readFileBytes(System.in, 0);
179: int nbytes = findRectLength(data, 0);
180: int offset = nbytes + 4; // skip rect + speed + nframes
181:
182: int tag = Integer.parseInt(args[0], 16);
183: int nth = 0;
184: if (args.length > 1) {
185: nth = Integer.parseInt(args[1]);
186: }
187: try {
188: byte contents[] = getTag(tag, nth, data, offset);
189: printTag(contents, System.out);
190: System.out.close();
191: } catch (TagNotFoundException ex) {
192: System.err.println("Tag " + Integer.toString(tag, 16)
193: + " [" + nth + "] not found.");
194: }
195:
196: } catch (Exception e) {
197: e.printStackTrace();
198: }
199: }
200: }
|