1 /* vi: set sts=2 sw=2 :*/
4 Library for creating and reading SWF files or parts of it.
5 There's a module directory which provides some extended functionality.
6 Most modules are included at the bottom of this file.
8 Part of the swftools package.
10 Copyright (c) 2000-2003 Rainer Böhme <rfxswf@reflex-studio.de>
11 Copyright (c) 2003 Matthias Kramm <kramm@quiss.org>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
32 #endif // HAVE_JPEGLIB
38 #ifndef RFXSWF_DISABLESOUND
40 #include "lame/lame.h"
53 #define MALLOC_SIZE 128
54 #define INSERT_RFX_TAG
56 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
59 // inline wrapper functions
61 TAG
* swf_NextTag(TAG
* t
) { return t
->next
; }
62 TAG
* swf_PrevTag(TAG
* t
) { return t
->prev
; }
63 U16
swf_GetTagID(TAG
* t
) { return t
->id
; }
64 U32
swf_GetTagLen(TAG
* t
) { return t
->len
; }
65 U8
* swf_GetTagLenPtr(TAG
* t
) { return &(t
->data
[t
->len
]); }
66 U32
swf_GetTagPos(TAG
* t
) { return t
->pos
; }
68 // for future purpose: avoid high level lib functions to change tagpos/bitpos
70 #define swf_SaveTagPos(tag)
71 #define swf_RestoreTagPos(tag)
73 void swf_SetTagPos(TAG
* t
,U32 pos
)
74 { swf_ResetReadBits(t
);
75 if (pos
<=t
->len
) t
->pos
= pos
;
78 fprintf(stderr
,"SetTagPos(%d) out of bounds: TagID = %i\n",pos
, t
->id
);
83 char* swf_GetString(TAG
*t
)
85 char* str
= ((char*)(&(t
)->data
[(t
)->pos
]));
91 { swf_ResetReadBits(t
);
94 { fprintf(stderr
,"GetU8() out of bounds: TagID = %i\n",t
->id
);
98 return t
->data
[t
->pos
++];
101 U16
swf_GetU16(TAG
* t
)
103 swf_ResetReadBits(t
);
105 if (t
->pos
>(t
->len
-2))
106 { fprintf(stderr
,"GetU16() out of bounds: TagID = %i\n",t
->id
);
110 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8);
115 U32
swf_GetU32(TAG
* t
)
117 swf_ResetReadBits(t
);
119 if (t
->pos
>(t
->len
-4))
120 { fprintf(stderr
,"GetU32() out of bounds: TagID = %i\n",t
->id
);
124 res
= t
->data
[t
->pos
] | (t
->data
[t
->pos
+1]<<8) |
125 (t
->data
[t
->pos
+2]<<16) | (t
->data
[t
->pos
+3]<<24);
130 int swf_GetBlock(TAG
* t
,U8
* b
,int l
)
131 // returns number of bytes written (<=l)
132 // b = NULL -> skip data
133 { swf_ResetReadBits(t
);
134 if ((t
->len
-t
->pos
)<l
) l
=t
->len
-t
->pos
;
135 if (b
&& l
) memcpy(b
,&t
->data
[t
->pos
],l
);
140 int swf_SetBlock(TAG
* t
,U8
* b
,int l
)
141 // Appends Block to the end of Tagdata, returns size
142 { U32 newlen
= t
->len
+ l
;
143 swf_ResetWriteBits(t
);
144 if (newlen
>t
->memsize
)
145 { U32 newmem
= MEMSIZE(newlen
);
146 U8
* newdata
= (U8
*)((t
->data
)?realloc(t
->data
,newmem
):malloc(newmem
));
150 fprintf(stderr
,"Fatal Error: malloc()/realloc() failed (1). (%d bytes)\n", newmem
);
158 if (b
) memcpy(&t
->data
[t
->len
],b
,l
);
159 else memset(&t
->data
[t
->len
],0x00,l
);
164 int swf_SetU8(TAG
* t
,U8 v
)
165 { swf_ResetWriteBits(t
);
166 if ((t
->len
+1)>t
->memsize
) return (swf_SetBlock(t
,&v
,1)==1)?0:-1;
167 t
->data
[t
->len
++] = v
;
171 int swf_SetU16(TAG
* t
,U16 v
)
176 swf_ResetWriteBits(t
);
177 if ((t
->len
+2)>t
->memsize
) return (swf_SetBlock(t
,a
,2)==2)?0:-1;
178 t
->data
[t
->len
++] = a
[0];
179 t
->data
[t
->len
++] = a
[1];
183 int swf_SetU32(TAG
* t
,U32 v
)
185 a
[0] = v
&0xff; // to ensure correct handling of non-intel byteorder
190 swf_ResetWriteBits(t
);
191 if ((t
->len
+4)>t
->memsize
) return (swf_SetBlock(t
,a
,4)==4)?0:-1;
192 t
->data
[t
->len
++] = a
[0];
193 t
->data
[t
->len
++] = a
[1];
194 t
->data
[t
->len
++] = a
[2];
195 t
->data
[t
->len
++] = a
[3];
199 U32
swf_GetBits(TAG
* t
,int nbits
)
201 if (!nbits
) return 0;
202 if (!t
->readBit
) t
->readBit
= 0x80;
205 if (t
->data
[t
->pos
]&t
->readBit
) res
|=1;
209 { if (nbits
) t
->readBit
= 0x80;
212 { fprintf(stderr
,"GetBits() out of bounds: TagID = %i\n",t
->id
);
222 S32
swf_GetSBits(TAG
* t
,int nbits
)
223 { U32 res
= swf_GetBits(t
,nbits
);
224 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
228 U32
reader_GetBits(struct reader_t
*reader
, int nbits
)
229 { return reader_readbits(reader
, nbits
);
231 S32
reader_GetSBits(struct reader_t
*reader
, int nbits
)
232 { U32 res
= reader_readbits(reader
, nbits
);
233 if (res
&(1<<(nbits
-1))) res
|=(0xffffffff<<nbits
);
237 int swf_SetBits(TAG
* t
,U32 v
,int nbits
)
238 { U32 bm
= 1<<(nbits
-1);
242 { if (FAILED(swf_SetU8(t
,0))) return -1;
245 if (v
&bm
) t
->data
[t
->len
-1] |= t
->writeBit
;
253 // Advanced Data Access Functions
255 int swf_SetRGB(TAG
* t
,RGBA
* col
)
258 { swf_SetU8(t
,col
->r
);
261 } else swf_SetBlock(t
,NULL
,3);
264 void swf_GetRGB(TAG
* t
, RGBA
* col
)
269 col
->r
= swf_GetU8(t
);
270 col
->g
= swf_GetU8(t
);
271 col
->b
= swf_GetU8(t
);
275 int swf_SetRGBA(TAG
* t
,RGBA
* col
)
278 { swf_SetU8(t
,col
->r
);
282 } else swf_SetBlock(t
,NULL
,4);
285 void swf_GetRGBA(TAG
* t
, RGBA
* col
)
290 col
->r
= swf_GetU8(t
);
291 col
->g
= swf_GetU8(t
);
292 col
->b
= swf_GetU8(t
);
293 col
->a
= swf_GetU8(t
);
296 void swf_GetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
301 memset(gradient
, 0, sizeof(GRADIENT
));
306 gradient
->num
= swf_GetU8(tag
);
307 for(t
=0;t
<gradient
->num
;t
++)
312 gradient
->ratios
[t
] = swf_GetU8(tag
);
314 swf_GetRGB(tag
, &gradient
->rgba
[t
]);
316 swf_GetRGBA(tag
, &gradient
->rgba
[t
]);
320 void swf_SetGradient(TAG
* tag
, GRADIENT
* gradient
, char alpha
)
324 memset(gradient
, 0, sizeof(GRADIENT
));
327 swf_SetU8(tag
, gradient
->num
);
328 for(t
=0; t
<8 && t
<gradient
->num
; t
++)
330 swf_SetU8(tag
, gradient
->ratios
[t
]);
332 swf_SetRGB(tag
, &gradient
->rgba
[t
]);
334 swf_SetRGBA(tag
, &gradient
->rgba
[t
]);
338 int swf_CountUBits(U32 v
,int nbits
)
341 if(v
== 0x00000000) n
= 0;
347 return (n
>nbits
)?n
:nbits
;
350 int swf_CountBits(U32 v
,int nbits
)
354 { if(v
== 0xffffffff) n
= 1;
362 { if(v
== 0x00000000) n
= 0;
369 return (n
>nbits
)?n
:nbits
;
372 int swf_GetRect(TAG
* t
,SRECT
* r
)
375 if(!t
) {r
->xmin
=r
->xmax
=r
->ymin
=r
->ymax
=0;return 0;}
377 nbits
= (int) swf_GetBits(t
,5);
378 r
->xmin
= swf_GetSBits(t
,nbits
);
379 r
->xmax
= swf_GetSBits(t
,nbits
);
380 r
->ymin
= swf_GetSBits(t
,nbits
);
381 r
->ymax
= swf_GetSBits(t
,nbits
);
385 int reader_GetRect(struct reader_t
*reader
,SRECT
* r
)
389 nbits
= (int) reader_GetBits(reader
,5);
390 r
->xmin
= reader_GetSBits(reader
,nbits
);
391 r
->xmax
= reader_GetSBits(reader
,nbits
);
392 r
->ymin
= reader_GetSBits(reader
,nbits
);
393 r
->ymax
= reader_GetSBits(reader
,nbits
);
397 int swf_SetRect(TAG
* t
,SRECT
* r
)
400 nbits
= swf_CountBits(r
->xmin
,0);
401 nbits
= swf_CountBits(r
->xmax
,nbits
);
402 nbits
= swf_CountBits(r
->ymin
,nbits
);
403 nbits
= swf_CountBits(r
->ymax
,nbits
);
405 fprintf(stderr
, "rfxswf: Warning: num_bits overflow in swf_SetRect\n");
409 swf_SetBits(t
,nbits
,5);
410 swf_SetBits(t
,r
->xmin
,nbits
);
411 swf_SetBits(t
,r
->xmax
,nbits
);
412 swf_SetBits(t
,r
->ymin
,nbits
);
413 swf_SetBits(t
,r
->ymax
,nbits
);
418 void swf_ExpandRect(SRECT
*src
, SPOINT add
)
420 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
425 if((add
.x
|add
.y
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
428 if(add
.x
< src
->xmin
)
430 if(add
.x
> src
->xmax
)
432 if(add
.y
< src
->ymin
)
434 if(add
.y
> src
->ymax
)
437 void swf_ExpandRect2(SRECT
*src
, SRECT
*add
)
439 if((add
->xmin
| add
->ymin
| add
->xmax
| add
->ymax
)==0)
441 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0)
443 if(add
->xmin
< src
->xmin
)
444 src
->xmin
= add
->xmin
;
445 if(add
->ymin
< src
->ymin
)
446 src
->ymin
= add
->ymin
;
447 if(add
->xmax
> src
->xmax
)
448 src
->xmax
= add
->xmax
;
449 if(add
->ymax
> src
->ymax
)
450 src
->ymax
= add
->ymax
;
452 void swf_ExpandRect3(SRECT
*src
, SPOINT center
, int radius
)
454 if((src
->xmin
| src
->ymin
| src
->xmax
| src
->ymax
)==0) {
455 src
->xmin
= center
.x
-radius
;
456 src
->ymin
= center
.y
-radius
;
457 src
->xmax
= center
.x
+radius
;
458 src
->ymax
= center
.y
+radius
;
459 if((center
.x
|center
.y
|radius
) == 0) src
->xmax
++; //make sure the bbox is not NULL anymore
462 if(center
.x
- radius
< src
->xmin
)
463 src
->xmin
= center
.x
- radius
;
464 if(center
.x
+ radius
> src
->xmax
)
465 src
->xmax
= center
.x
- radius
;
466 if(center
.y
- radius
< src
->ymin
)
467 src
->ymin
= center
.y
- radius
;
468 if(center
.y
+ radius
> src
->ymax
)
469 src
->ymax
= center
.y
- radius
;
471 SPOINT
swf_TurnPoint(SPOINT p
, MATRIX
* m
)
474 r
.x
= (int)(m
->sx
*(1/65536.0)*p
.x
+ m
->r1
*(1/65536.0)*p
.y
+ 0.5) + m
->tx
;
475 r
.y
= (int)(m
->r0
*(1/65536.0)*p
.x
+ m
->sy
*(1/65536.0)*p
.y
+ 0.5) + m
->ty
;
478 SRECT
swf_TurnRect(SRECT r
, MATRIX
* m
)
481 SPOINT p1
,p2
,p3
,p4
,pp1
,pp2
,pp3
,pp4
;
482 p1
.x
= r
.xmin
;p1
.y
= r
.ymin
;
483 p2
.x
= r
.xmax
;p2
.y
= r
.ymin
;
484 p3
.x
= r
.xmin
;p3
.y
= r
.ymax
;
485 p4
.x
= r
.xmax
;p4
.y
= r
.ymax
;
486 pp1
= swf_TurnPoint(p1
, m
);
487 pp2
= swf_TurnPoint(p2
, m
);
488 pp3
= swf_TurnPoint(p3
, m
);
489 pp4
= swf_TurnPoint(p4
, m
);
490 g
.xmin
= g
.xmax
= pp1
.x
;
491 g
.ymin
= g
.ymax
= pp1
.y
;
492 swf_ExpandRect(&g
, pp2
);
493 swf_ExpandRect(&g
, pp3
);
494 swf_ExpandRect(&g
, pp4
);
499 int swf_GetMatrix(TAG
* t
,MATRIX
* m
)
506 { m
->sx
= m
->sy
= 0x10000;
512 swf_ResetReadBits(t
);
514 if (swf_GetBits(t
,1))
515 { nbits
= swf_GetBits(t
,5);
516 m
->sx
= swf_GetSBits(t
,nbits
);
517 m
->sy
= swf_GetSBits(t
,nbits
);
519 else m
->sx
= m
->sy
= 0x10000;
521 if (swf_GetBits(t
,1))
522 { nbits
= swf_GetBits(t
,5);
523 m
->r0
= swf_GetSBits(t
,nbits
);
524 m
->r1
= swf_GetSBits(t
,nbits
);
526 else m
->r0
= m
->r1
= 0x0;
528 nbits
= swf_GetBits(t
,5);
529 m
->tx
= swf_GetSBits(t
,nbits
);
530 m
->ty
= swf_GetSBits(t
,nbits
);
535 int swf_SetMatrix(TAG
* t
,MATRIX
* m
)
541 ma
.sx
= ma
.sy
= 0x10000;
546 swf_ResetWriteBits(t
);
548 if ((m
->sx
==0x10000)&&(m
->sy
==0x10000)) swf_SetBits(t
,0,1);
550 { swf_SetBits(t
,1,1);
551 nbits
= swf_CountBits(m
->sx
,0);
552 nbits
= swf_CountBits(m
->sy
,nbits
);
554 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
557 swf_SetBits(t
,nbits
,5);
558 swf_SetBits(t
,m
->sx
,nbits
);
559 swf_SetBits(t
,m
->sy
,nbits
);
562 if ((!m
->r0
)&&(!m
->r1
)) swf_SetBits(t
,0,1);
564 { swf_SetBits(t
,1,1);
565 nbits
= swf_CountBits(m
->r0
,0);
566 nbits
= swf_CountBits(m
->r1
,nbits
);
568 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
571 swf_SetBits(t
,nbits
,5);
572 swf_SetBits(t
,m
->r0
,nbits
);
573 swf_SetBits(t
,m
->r1
,nbits
);
576 nbits
= swf_CountBits(m
->tx
,0);
577 nbits
= swf_CountBits(m
->ty
,nbits
);
579 fprintf(stderr
,"rfxswf: Error: matrix values too large\n");
582 swf_SetBits(t
,nbits
,5);
583 swf_SetBits(t
,m
->tx
,nbits
);
584 swf_SetBits(t
,m
->ty
,nbits
);
589 int swf_GetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
) //FIXME: alpha should be type bool
597 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
598 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
602 swf_ResetReadBits(t
);
603 hasadd
= swf_GetBits(t
,1);
604 hasmul
= swf_GetBits(t
,1);
605 nbits
= swf_GetBits(t
,4);
608 { cx
->r0
= (S16
)swf_GetSBits(t
,nbits
);
609 cx
->g0
= (S16
)swf_GetSBits(t
,nbits
);
610 cx
->b0
= (S16
)swf_GetSBits(t
,nbits
);
612 cx
->a0
= (S16
)swf_GetSBits(t
,nbits
);
616 { cx
->r1
= (S16
)swf_GetSBits(t
,nbits
);
617 cx
->g1
= (S16
)swf_GetSBits(t
,nbits
);
618 cx
->b1
= (S16
)swf_GetSBits(t
,nbits
);
620 cx
->a1
= (S16
)swf_GetSBits(t
,nbits
);
626 int swf_SetCXForm(TAG
* t
,CXFORM
* cx
,U8 alpha
)
634 cx
->a0
= cx
->r0
= cx
->g0
= cx
->b0
= 256;
635 cx
->a1
= cx
->r1
= cx
->g1
= cx
->b1
= 0;
645 hasmul
= (cx
->a0
!=256)||(cx
->r0
!=256)||(cx
->g0
!=256)||(cx
->b0
!=256);
646 hasadd
= cx
->a1
|cx
->r1
|cx
->g1
|cx
->b1
;
649 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a0
,nbits
);
650 nbits
= swf_CountBits((S32
)cx
->r0
,nbits
);
651 nbits
= swf_CountBits((S32
)cx
->g0
,nbits
);
652 nbits
= swf_CountBits((S32
)cx
->b0
,nbits
);
656 { if (alpha
) nbits
= swf_CountBits((S32
)cx
->a1
,nbits
);
657 nbits
= swf_CountBits((S32
)cx
->r1
,nbits
);
658 nbits
= swf_CountBits((S32
)cx
->g1
,nbits
);
659 nbits
= swf_CountBits((S32
)cx
->b1
,nbits
);
662 swf_ResetWriteBits(t
);
663 swf_SetBits(t
,hasadd
?1:0,1);
664 swf_SetBits(t
,hasmul
?1:0,1);
665 swf_SetBits(t
,nbits
,4);
668 { swf_SetBits(t
,cx
->r0
,nbits
);
669 swf_SetBits(t
,cx
->g0
,nbits
);
670 swf_SetBits(t
,cx
->b0
,nbits
);
671 if (alpha
) swf_SetBits(t
,cx
->a0
,nbits
);
675 { swf_SetBits(t
,cx
->r1
,nbits
);
676 swf_SetBits(t
,cx
->g1
,nbits
);
677 swf_SetBits(t
,cx
->b1
,nbits
);
678 if (alpha
) swf_SetBits(t
,cx
->a1
,nbits
);
684 //int swf_GetPoint(TAG * t,SPOINT * p) { return 0; }
685 //int swf_SetPoint(TAG * t,SPOINT * p) { return 0; }
687 void swf_SetPassword(TAG
* t
, const char * password
)
689 /* WARNING: crypt_md5 is not reentrant */
693 #if defined(HAVE_LRAND48) && defined(HAVE_SRAND48) && defined(HAVE_TIME_H) && defined(HAVE_TIME)
695 salt
[0] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
696 salt
[1] = "abcdefghijklmnopqrstuvwxyz0123456789"[lrand48()%36];
700 fprintf(stderr
, "rfxswf: Warning- no usable random generator found\n");
701 fprintf(stderr
, "Your password will be vulnerable to dictionary attacks\n");
704 md5string
= crypt_md5(password
, salt
);
707 swf_SetString(t
, md5string
);
710 int swf_VerifyPassword(TAG
* t
, const char * password
)
712 char*md5string1
, *md5string2
;
717 if(t
->len
>= 5 && t
->pos
==0 &&
722 printf("%d %d %d %d\n", t
->len
, t
->pos
, t
->data
[0], t
->data
[1]);
725 md5string1
= swf_GetString(t
);
727 if(strncmp(md5string1
, "$1$",3 )) {
728 fprintf(stderr
, "rfxswf: no salt in pw string\n");
731 x
= strchr(md5string1
+3, '$');
733 fprintf(stderr
, "rfxswf: invalid salt format in pw string\n");
736 n
= x
-(md5string1
+3);
737 salt
= (char*)malloc(n
+1);
738 memcpy(salt
, md5string1
+3, n
);
741 md5string2
= crypt_md5(password
, salt
);
743 if(strcmp(md5string1
, md5string2
) != 0)
748 // Tag List Manipulating Functions
750 TAG
* swf_InsertTag(TAG
* after
,U16 id
)
753 t
= (TAG
*)malloc(sizeof(TAG
));
755 { memset(t
,0x00,sizeof(TAG
));
761 t
->next
= after
->next
;
763 if (t
->next
) t
->next
->prev
= t
;
769 TAG
* swf_InsertTagBefore(SWF
* swf
, TAG
* before
,U16 id
)
772 t
= (TAG
*)malloc(sizeof(TAG
));
774 { memset(t
,0x00,sizeof(TAG
));
780 t
->prev
= before
->prev
;
782 if (t
->prev
) t
->prev
->next
= t
;
785 if(swf
&& swf
->firstTag
== before
) {
791 void swf_ClearTag(TAG
* t
)
793 if (t
->data
) free(t
->data
);
802 void swf_ResetTag(TAG
*tag
, U16 id
)
804 tag
->len
= tag
->pos
= tag
->readBit
= tag
->writeBit
= 0;
808 int swf_DeleteTag(TAG
* t
)
811 if (t
->prev
) t
->prev
->next
= t
->next
;
812 if (t
->next
) t
->next
->prev
= t
->prev
;
814 if (t
->data
) free(t
->data
);
819 TAG
* swf_ReadTag(struct reader_t
*reader
, TAG
* prev
)
825 if (reader
->read(reader
, &raw
, 2) !=2 ) return NULL
;
833 if (reader
->read(reader
, &len
, 4) != 4) return NULL
;
837 if (id
==ST_DEFINESPRITE
) len
= 2*sizeof(U16
);
838 // Sprite handling fix: Flatten sprite tree
840 t
= (TAG
*)malloc(sizeof(TAG
));
845 fprintf(stderr
,"Fatal Error: malloc()/realloc() failed (2). (%d bytes)\n", sizeof(TAG
));
850 memset(t
,0x00,sizeof(TAG
));
856 { t
->data
= (U8
*)malloc(t
->len
);
860 fprintf(stderr
,"Fatal Error: malloc()/realloc() failed (3). (%d bytes)\n", t
->len
);
865 if (reader
->read(reader
, t
->data
, t
->len
) != t
->len
) return NULL
;
877 int swf_DefineSprite_GetRealSize(TAG
* t
);
879 int swf_WriteTag2(struct writer_t
*writer
, TAG
* t
)
880 // returns tag length in bytes (incl. Header), -1 = Error
881 // writer = 0 -> no output
888 len
= (t
->id
==ST_DEFINESPRITE
)?swf_DefineSprite_GetRealSize(t
):t
->len
;
890 short_tag
= len
<0x3f&&(t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
);
894 { raw
[0] = SWAP16(len
|((t
->id
&0x3ff)<<6));
895 if (writer
->write(writer
,raw
,2)!=2)
898 fprintf(stderr
,"WriteTag() failed: Short Header.\n");
905 raw
[0] = SWAP16((t
->id
<<6)|0x3f);
906 if (writer
->write(writer
,raw
,2)!=2)
909 fprintf(stderr
,"WriteTag() failed: Long Header (1).\n");
915 if (writer
->write(writer
,&len
,4)!=4)
918 fprintf(stderr
,"WriteTag() failed: Long Header (2).\n");
925 { if (writer
->write(writer
,t
->data
,t
->len
)!=t
->len
)
928 fprintf(stderr
,"WriteTag() failed: Data.\n");
934 else if (t
->len
) fprintf(stderr
,"WriteTag(): Tag Data Error, id=%i\n",t
->id
);
938 return t
->len
+(short_tag
?2:6);
941 int swf_WriteTag(int handle
, TAG
* t
)
943 struct writer_t writer
;
946 return swf_WriteTag2(0, t
);
947 writer_init_filewriter(&writer
, handle
);
948 len
= swf_WriteTag2(&writer
, t
);
949 writer
.finish(&writer
);
953 int swf_DefineSprite_GetRealSize(TAG
* t
)
954 // Sprite Handling: Helper function to pack DefineSprite-Tag
956 if(len
>4) { // folded sprite
960 { t
= swf_NextTag(t
);
961 if (t
&& t
->id
!=ST_DEFINESPRITE
) len
+= swf_WriteTag(-1, t
);
963 } while (t
&&(t
->id
!=ST_END
));
967 void swf_UnFoldSprite(TAG
* t
)
972 U16 spriteid
,spriteframes
;
974 if(t
->id
!=ST_DEFINESPRITE
)
976 if(t
->len
<=4) // not folded
981 spriteid
= swf_GetU16(t
); //id
982 spriteframes
= swf_GetU16(t
); //frames
994 if(id
== ST_DEFINESPRITE
&& len
<=4)
999 it
= swf_InsertTag(next
, id
);
1004 { it
->data
= (U8
*)malloc(it
->len
);
1005 it
->memsize
= it
->len
;
1006 swf_GetBlock(t
, it
->data
, it
->len
);
1013 free(t
->data
); t
->data
= 0;
1014 t
->memsize
= t
->len
= t
->pos
= 0;
1016 swf_SetU16(t
, spriteid
);
1017 swf_SetU16(t
, spriteframes
);
1020 void swf_FoldSprite(TAG
* t
)
1023 U16 id
,frames
,tmpid
;
1025 if(t
->id
!=ST_DEFINESPRITE
)
1028 fprintf(stderr
, "Error: Sprite has no ID!");
1032 /* sprite is already folded */
1039 t
->len
= t
->pos
= t
->memsize
= 0;
1044 t
= swf_NextTag(sprtag
);
1049 if(t
->id
==ST_SHOWFRAME
) frames
++;
1050 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1055 } while(t
&& level
);
1057 fprintf(stderr
, "rfxswf error: sprite doesn't end(1)\n");
1059 swf_SetU16(sprtag
, id
);
1060 swf_SetU16(sprtag
, frames
);
1062 t
= swf_NextTag(sprtag
);
1067 if(t
->len
<0x3f&&t
->id
!=ST_DEFINEBITSLOSSLESS
&&t
->id
!=ST_DEFINEBITSLOSSLESS2
) {
1068 swf_SetU16(sprtag
,t
->len
|(t
->id
<<6));
1070 swf_SetU16(sprtag
,0x3f|(t
->id
<<6));
1071 swf_SetU32(sprtag
,t
->len
);
1074 swf_SetBlock(sprtag
,t
->data
, t
->len
);
1076 if(t
->id
== ST_DEFINESPRITE
&& t
->len
<=4)
1085 fprintf(stderr
, "rfxswf error: sprite doesn't end(2)\n");
1087 // sprtag->next = t;
1088 // t->prev = sprtag;
1091 int swf_IsFolded(TAG
* t
)
1093 return (t
->id
== ST_DEFINESPRITE
&& t
->len
>4);
1096 void swf_FoldAll(SWF
*swf
)
1098 TAG
*tag
= swf
->firstTag
;
1099 //swf_DumpSWF(stdout, swf);
1101 if(tag
->id
== ST_DEFINESPRITE
) {
1102 swf_FoldSprite(tag
);
1103 //swf_DumpSWF(stdout, swf);
1105 tag
= swf_NextTag(tag
);
1109 void swf_UnFoldAll(SWF
*swf
)
1111 TAG
*tag
= swf
->firstTag
;
1113 if(tag
->id
== ST_DEFINESPRITE
)
1114 swf_UnFoldSprite(tag
);
1119 void swf_OptimizeTagOrder(SWF
*swf
)
1126 /* at the moment, we don't actually do optimizing,
1127 only fixing of non-spec-conformant things like
1134 tag
= swf
->firstTag
;
1137 if(tag
->id
== ST_DEFINESPRITE
) {
1139 /* ??? all sprites are supposed to be unfolded */
1140 fprintf(stderr
, "librfxswf error - internal error in OptimizeTagOrder/UnfoldAll\n");
1150 /* move non-sprite tags out of sprite */
1151 if(!swf_isAllowedSpriteTag(tag
) || level
>=2) {
1152 /* remove tag from current position */
1153 tag
->prev
->next
= tag
->next
;
1155 tag
->next
->prev
= tag
->prev
;
1157 /* insert before tag level0 */
1159 tag
->prev
= level0
->prev
;
1161 tag
->prev
->next
= tag
;
1165 if(tag
->id
== ST_END
) {
1176 int swf_ReadSWF2(struct reader_t
*reader
, SWF
* swf
) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
1178 if (!swf
) return -1;
1179 memset(swf
,0x00,sizeof(SWF
));
1181 { char b
[32]; // read Header
1185 struct reader_t zreader
;
1187 if ((len
= reader
->read(reader
,b
,8))<8) return -1;
1189 if (b
[0]!='F' && b
[0]!='C') return -1;
1190 if (b
[1]!='W') return -1;
1191 if (b
[2]!='S') return -1;
1192 swf
->fileVersion
= b
[3];
1193 swf
->compressed
= (b
[0]=='C')?1:0;
1194 swf
->fileSize
= GET32(&b
[4]);
1196 if(swf
->compressed
) {
1197 reader_init_zlibinflate(&zreader
, reader
);
1201 reader_GetRect(reader
, &swf
->movieSize
);
1202 reader
->read(reader
, &swf
->frameRate
, 2);
1203 swf
->frameRate
= SWAP16(swf
->frameRate
);
1204 reader
->read(reader
, &swf
->frameCount
, 2);
1205 swf
->frameCount
= SWAP16(swf
->frameCount
);
1207 /* read tags and connect to list */
1209 while (t
) t
= swf_ReadTag(reader
,t
);
1210 swf
->firstTag
= t1
.next
;
1211 t1
.next
->prev
= NULL
;
1217 int swf_ReadSWF(int handle
, SWF
* swf
)
1219 struct reader_t reader
;
1220 reader_init_filereader(&reader
, handle
);
1221 return swf_ReadSWF2(&reader
, swf
);
1224 int swf_WriteSWF2(struct writer_t
*writer
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1228 struct writer_t zwriter
;
1231 int writer_lastpos
= 0;
1234 if (!swf
) return -1;
1235 if (!writer
) return -1; // the caller should provide a nullwriter, not 0, for querying SWF size
1237 if(writer
) writer_lastpos
= writer
->pos
;
1239 // Insert REFLEX Tag
1241 #ifdef INSERT_RFX_TAG
1243 if (swf
->firstTag
&& swf_NextTag(swf
->firstTag
))
1244 if (swf_GetTagID(swf_NextTag(swf
->firstTag
))!=ST_REFLEX
)
1245 swf_SetBlock(swf_InsertTagBefore(swf
, swf
->firstTag
,ST_REFLEX
),"rfx",3);
1247 #endif // INSERT_RFX_TAG
1249 // Count Frames + File Size
1256 len
+= swf_WriteTag(-1,t
);
1257 if(t
->id
== ST_DEFINESPRITE
) inSprite
++;
1258 else if(t
->id
== ST_END
&& inSprite
) inSprite
--;
1259 else if(t
->id
== ST_SHOWFRAME
&& !inSprite
) frameCount
++;
1267 memset(&t1
,0x00,sizeof(TAG
));
1271 { // measure header file size
1274 memset(&t2
,0x00,sizeof(TAG
));
1277 swf_SetRect(&t2
, &swf
->movieSize
);
1278 swf_SetU16(&t2
, swf
->frameRate
);
1279 swf_SetU16(&t2
, swf
->frameCount
);
1280 l
= swf_GetTagLen(&t2
)+8;
1282 if(swf
->compressed
== 8) {
1287 if(len
) {// don't touch headers without tags
1288 swf
->fileSize
= fileSize
;
1289 swf
->frameCount
= frameCount
;
1292 if(swf
->compressed
!= 8) {
1293 /* compressed flag set to 8 means "skip first 8
1294 header bytes". This is necessary if the caller wants to
1295 create compressed SWFs himself .
1296 It also means that we don't initialize our own zlib
1297 writer, but assume the caller provided one.
1299 if(swf
->compressed
) {
1301 writer
->write(writer
, id
, 3);
1305 writer
->write(writer
, id
, 3);
1308 writer
->write(writer
, &swf
->fileVersion
, 1);
1309 PUT32(b4
, swf
->fileSize
);
1310 writer
->write(writer
, b4
, 4);
1312 if(swf
->compressed
) {
1313 writer_init_zlibdeflate(&zwriter
, writer
);
1318 swf_SetRect(&t1
,&swf
->movieSize
);
1319 swf_SetU16(&t1
,swf
->frameRate
);
1320 swf_SetU16(&t1
,swf
->frameCount
);
1322 ret
= writer
->write(writer
,b
,swf_GetTagLen(&t1
));
1323 if (ret
!=swf_GetTagLen(&t1
))
1326 fprintf(stderr
, "ret:%d\n",ret
);
1328 fprintf(stderr
,"WriteSWF() failed: Header.\n");
1335 { if (swf_WriteTag2(writer
, t
)<0) return -1;
1338 if(swf
->compressed
) {
1339 if(swf
->compressed
!= 8) {
1340 zwriter
.finish(&zwriter
);
1341 return writer
->pos
- writer_lastpos
;
1343 return (int)fileSize
;
1345 return (int)fileSize
;
1350 int swf_WriteSWF(int handle
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1352 struct writer_t writer
;
1354 swf
->compressed
= 0;
1357 writer_init_nullwriter(&writer
);
1358 len
= swf_WriteSWF2(&writer
, swf
);
1360 writer_init_filewriter(&writer
, handle
);
1361 len
= swf_WriteSWF2(&writer
, swf
);
1362 writer
.finish(&writer
);
1366 int swf_WriteSWC(int handle
, SWF
* swf
) // Writes SWF to file, returns length or <0 if fails
1368 struct writer_t writer
;
1370 swf
->compressed
= 1;
1373 writer_init_nullwriter(&writer
);
1374 len
= swf_WriteSWF2(&writer
, swf
);
1376 writer_init_filewriter(&writer
, handle
);
1377 len
= swf_WriteSWF2(&writer
, swf
);
1378 writer
.finish(&writer
);
1382 int swf_WriteHeader2(struct writer_t
*writer
,SWF
* swf
)
1385 memcpy(&myswf
,swf
,sizeof(SWF
));
1387 return swf_WriteSWF2(writer
, &myswf
);
1390 int swf_WriteHeader(int handle
,SWF
* swf
)
1393 memcpy(&myswf
,swf
,sizeof(SWF
));
1395 return swf_WriteSWF(handle
, &myswf
);
1398 int swf_WriteCGI(SWF
* swf
)
1402 len
= swf_WriteSWF(-1,swf
);
1404 if (len
<0) return -1;
1406 sprintf(s
,"Content-type: application/x-shockwave-flash\n"
1407 "Accept-Ranges: bytes\n"
1408 "Content-Length: %lu\n"
1409 "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
1412 write(fileno(stdout
),s
,strlen(s
));
1413 return swf_WriteSWF(fileno(stdout
),swf
);
1416 void swf_FreeTags(SWF
* swf
) // Frees all malloc'ed memory for tags
1417 { TAG
* t
= swf
->firstTag
;
1420 { TAG
* tnew
= t
->next
;
1421 if (t
->data
) free(t
->data
);
1428 // include advanced functions
1430 #include "modules/swfdump.c"
1431 #include "modules/swfshape.c"
1432 #include "modules/swftext.c"
1433 #include "modules/swffont.c"
1434 #include "modules/swfobject.c"
1435 #include "modules/swfbutton.c"
1436 #include "modules/swftools.c"
1437 #include "modules/swfcgi.c"
1438 #include "modules/swfbits.c"
1439 #include "modules/swfaction.c"
1440 #include "modules/swfsound.c"
1441 #include "modules/swfdraw.c"