+++ /dev/null
-/*
- miniunz.c
- Version 1.01e, February 12th, 2005
-
- Copyright (C) 1998-2005 Gilles Vollant
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef _WIN32_WCE
-#include <errno.h>
-#include <fcntl.h>
-
-#ifdef WIN32
-# include <direct.h>
-# include <io.h>
-#else
-# include <unistd.h>
-# include <utime.h>
-# include <sys/stat.h>
-#endif
-
-#endif
-
-#include "unzip.h"
-#include <gpac/tools.h>
-
-
-
-/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
-
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-
-voidpf ZCALLBACK fopen_file_func OF((
- voidpf opaque,
- const char* filename,
- int mode));
-
-uLong ZCALLBACK fread_file_func OF((
- voidpf opaque,
- voidpf stream,
- void* buf,
- uLong size));
-
-uLong ZCALLBACK fwrite_file_func OF((
- voidpf opaque,
- voidpf stream,
- const void* buf,
- uLong size));
-
-long ZCALLBACK ftell_file_func OF((
- voidpf opaque,
- voidpf stream));
-
-long ZCALLBACK fseek_file_func OF((
- voidpf opaque,
- voidpf stream,
- uLong offset,
- int origin));
-
-int ZCALLBACK fclose_file_func OF((
- voidpf opaque,
- voidpf stream));
-
-int ZCALLBACK ferror_file_func OF((
- voidpf opaque,
- voidpf stream));
-
-
-voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
- voidpf opaque;
- const char* filename;
- int mode;
-{
- FILE* file = NULL;
- const char* mode_fopen = NULL;
- if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
- mode_fopen = "rb";
- else
- if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
- mode_fopen = "r+b";
- else
- if (mode & ZLIB_FILEFUNC_MODE_CREATE)
- mode_fopen = "wb";
-
- if ((filename!=NULL) && (mode_fopen != NULL))
- file = fopen(filename, mode_fopen);
- return file;
-}
-
-
-uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
- voidpf opaque;
- voidpf stream;
- void* buf;
- uLong size;
-{
- uLong ret;
- ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
- return ret;
-}
-
-
-uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
- voidpf opaque;
- voidpf stream;
- const void* buf;
- uLong size;
-{
- uLong ret;
- ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
- return ret;
-}
-
-long ZCALLBACK ftell_file_func (opaque, stream)
- voidpf opaque;
- voidpf stream;
-{
- long ret;
- ret = ftell((FILE *)stream);
- return ret;
-}
-
-long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
- voidpf opaque;
- voidpf stream;
- uLong offset;
- int origin;
-{
- int fseek_origin=0;
- long ret;
- switch (origin)
- {
- case ZLIB_FILEFUNC_SEEK_CUR :
- fseek_origin = SEEK_CUR;
- break;
- case ZLIB_FILEFUNC_SEEK_END :
- fseek_origin = SEEK_END;
- break;
- case ZLIB_FILEFUNC_SEEK_SET :
- fseek_origin = SEEK_SET;
- break;
- default: return -1;
- }
- ret = 0;
- fseek((FILE *)stream, offset, fseek_origin);
- return ret;
-}
-
-int ZCALLBACK fclose_file_func (opaque, stream)
- voidpf opaque;
- voidpf stream;
-{
- int ret;
- ret = fclose((FILE *)stream);
- return ret;
-}
-
-int ZCALLBACK ferror_file_func (opaque, stream)
- voidpf opaque;
- voidpf stream;
-{
- int ret;
- ret = ferror((FILE *)stream);
- return ret;
-}
-
-void fill_fopen_filefunc (pzlib_filefunc_def)
- zlib_filefunc_def* pzlib_filefunc_def;
-{
- pzlib_filefunc_def->zopen_file = fopen_file_func;
- pzlib_filefunc_def->zread_file = fread_file_func;
- pzlib_filefunc_def->zwrite_file = fwrite_file_func;
- pzlib_filefunc_def->ztell_file = ftell_file_func;
- pzlib_filefunc_def->zseek_file = fseek_file_func;
- pzlib_filefunc_def->zclose_file = fclose_file_func;
- pzlib_filefunc_def->zerror_file = ferror_file_func;
- pzlib_filefunc_def->opaque = NULL;
-}
-
-static int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
- const zlib_filefunc_def* pzlib_filefunc_def;
- voidpf filestream;
- int *pi;
-{
- unsigned char c;
- int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
- if (err==1)
- {
- *pi = (int)c;
- return UNZ_OK;
- }
- else
- {
- if (ZERROR(*pzlib_filefunc_def,filestream))
- return UNZ_ERRNO;
- else
- return UNZ_EOF;
- }
-}
-
-static int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
- const zlib_filefunc_def* pzlib_filefunc_def;
- voidpf filestream;
- uLong *pX;
-{
- uLong x ;
- int err;
- int i = 0;
-
- err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
- x = (uLong)i;
-
- if (err==UNZ_OK)
- err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
- x += ((uLong)i)<<8;
-
- if (err==UNZ_OK)
- *pX = x;
- else
- *pX = 0;
- return err;
-}
-
-static int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
- const zlib_filefunc_def* pzlib_filefunc_def;
- voidpf filestream;
- uLong *pX;
-{
- uLong x ;
- int err;
- int i = 0;
-
- err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
- x = (uLong)i;
-
- if (err==UNZ_OK)
- err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
- x += ((uLong)i)<<8;
-
- if (err==UNZ_OK)
- err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
- x += ((uLong)i)<<16;
-
- if (err==UNZ_OK)
- err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
- x += ((uLong)i)<<24;
-
- if (err==UNZ_OK)
- *pX = x;
- else
- *pX = 0;
- return err;
-}
-
-static uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
- const zlib_filefunc_def* pzlib_filefunc_def;
- voidpf filestream;
-{
- unsigned char* buf;
- uLong uSizeFile;
- uLong uBackRead;
- uLong uMaxBack=0xffff; /* maximum size of global comment */
- uLong uPosFound=0;
-
- if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
- return 0;
-
-
- uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
-
- if (uMaxBack>uSizeFile)
- uMaxBack = uSizeFile;
-
- buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
- if (buf==NULL)
- return 0;
-
- uBackRead = 4;
- while (uBackRead<uMaxBack)
- {
- uLong uReadSize,uReadPos ;
- int i;
- if (uBackRead+BUFREADCOMMENT>uMaxBack)
- uBackRead = uMaxBack;
- else
- uBackRead+=BUFREADCOMMENT;
- uReadPos = uSizeFile-uBackRead ;
-
- uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
- (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
- if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
- break;
-
- if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
- break;
-
- for (i=(int)uReadSize-3; (i--)>0;)
- if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
- ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
- {
- uPosFound = uReadPos+i;
- break;
- }
-
- if (uPosFound!=0)
- break;
- }
- TRYFREE(buf);
- return uPosFound;
-}
-
-
-/*
- Translate date/time from Dos format to tm_unz (readable more easilty)
-*/
-void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
- uLong ulDosDate;
- tm_unz* ptm;
-{
- uLong uDate;
- uDate = (uLong)(ulDosDate>>16);
- ptm->tm_mday = (uInt)(uDate&0x1f) ;
- ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
- ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
-
- ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
- ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
- ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
-}
-
-static int unzlocal_GetCurrentFileInfoInternal (file,
- pfile_info,
- pfile_info_internal,
- szFileName, fileNameBufferSize,
- extraField, extraFieldBufferSize,
- szComment, commentBufferSize)
- unzFile file;
- unz_file_info *pfile_info;
- unz_file_info_internal *pfile_info_internal;
- char *szFileName;
- uLong fileNameBufferSize;
- void *extraField;
- uLong extraFieldBufferSize;
- char *szComment;
- uLong commentBufferSize;
-{
- unz_s* s;
- unz_file_info file_info;
- unz_file_info_internal file_info_internal;
- int err=UNZ_OK;
- uLong uMagic;
- long lSeek=0;
-
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (ZSEEK(s->z_filefunc, s->filestream,
- s->pos_in_central_dir+s->byte_before_the_zipfile,
- ZLIB_FILEFUNC_SEEK_SET)!=0)
- err=UNZ_ERRNO;
-
-
- /* we check the magic */
- if (err==UNZ_OK){
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
- err=UNZ_ERRNO;
- else if (uMagic!=0x02014b50)
- err=UNZ_BADZIPFILE;
- }
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
- err=UNZ_ERRNO;
-
- unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
- err=UNZ_ERRNO;
-
- lSeek+=file_info.size_filename;
- if ((err==UNZ_OK) && (szFileName!=NULL))
- {
- uLong uSizeRead ;
- if (file_info.size_filename<fileNameBufferSize)
- {
- *(szFileName+file_info.size_filename)='\0';
- uSizeRead = file_info.size_filename;
- }
- else
- uSizeRead = fileNameBufferSize;
-
- if ((file_info.size_filename>0) && (fileNameBufferSize>0))
- if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
- err=UNZ_ERRNO;
- lSeek -= uSizeRead;
- }
-
-
- if ((err==UNZ_OK) && (extraField!=NULL))
- {
- uLong uSizeRead ;
- if (file_info.size_file_extra<extraFieldBufferSize)
- uSizeRead = file_info.size_file_extra;
- else
- uSizeRead = extraFieldBufferSize;
-
- if (lSeek!=0){
- if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
- lSeek=0;
- else
- err=UNZ_ERRNO;
- }
- if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
- if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
- err=UNZ_ERRNO;
- lSeek += file_info.size_file_extra - uSizeRead;
- }
- else
- lSeek+=file_info.size_file_extra;
-
-
- if ((err==UNZ_OK) && (szComment!=NULL))
- {
- uLong uSizeRead ;
- if (file_info.size_file_comment<commentBufferSize)
- {
- *(szComment+file_info.size_file_comment)='\0';
- uSizeRead = file_info.size_file_comment;
- }
- else
- uSizeRead = commentBufferSize;
-
- if (lSeek!=0){
- if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
- lSeek=0;
- else
- err=UNZ_ERRNO;
- }
- if ((file_info.size_file_comment>0) && (commentBufferSize>0))
- if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
- err=UNZ_ERRNO;
- lSeek+=file_info.size_file_comment - uSizeRead;
- }
- else
- lSeek+=file_info.size_file_comment;
-
- if ((err==UNZ_OK) && (pfile_info!=NULL))
- *pfile_info=file_info;
-
- if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
- *pfile_info_internal=file_info_internal;
-
- return err;
-}
-
-int unzGetCurrentFileInfo(unzFile file,
- unz_file_info *pfile_info,
- char *szFileName,
- uLong fileNameBufferSize,
- void *extraField,
- uLong extraFieldBufferSize,
- char *szComment,
- uLong commentBufferSize)
-{
- return unzlocal_GetCurrentFileInfoInternal(file, pfile_info, NULL, szFileName, fileNameBufferSize, extraField, extraFieldBufferSize, szComment, commentBufferSize);
-}
-
-/*
- Set the current file of the zipfile to the next file.
- return UNZ_OK if there is no problem
- return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-int unzGoToNextFile (file)
- unzFile file;
-{
- unz_s* s;
- int err;
-
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (!s->current_file_ok)
- return UNZ_END_OF_LIST_OF_FILE;
- if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
- if (s->num_file+1==s->gi.number_entry)
- return UNZ_END_OF_LIST_OF_FILE;
-
- s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
- s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
- s->num_file++;
- err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
- &s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
- s->current_file_ok = (err == UNZ_OK);
- return err;
-}
-
-/*
- Set the current file of the zipfile to the first file.
- return UNZ_OK if there is no problem
-*/
-int unzGoToFirstFile (file)
- unzFile file;
-{
- int err=UNZ_OK;
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- s->pos_in_central_dir=s->offset_central_dir;
- s->num_file=0;
- err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
- &s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
- s->current_file_ok = (err == UNZ_OK);
- return err;
-}
-
-int unzGetGlobalInfo (file,pglobal_info)
- unzFile file;
- unz_global_info *pglobal_info;
-{
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- *pglobal_info=s->gi;
- return UNZ_OK;
-}
-
-/*
- Close the file in zip opened with unzipOpenCurrentFile
- Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-int unzCloseCurrentFile (file)
- unzFile file;
-{
- int err=UNZ_OK;
-
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
-
-
- if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
- (!pfile_in_zip_read_info->raw))
- {
- if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
- err=UNZ_CRCERROR;
- }
-
-
- TRYFREE(pfile_in_zip_read_info->read_buffer);
- pfile_in_zip_read_info->read_buffer = NULL;
- if (pfile_in_zip_read_info->stream_initialised)
- inflateEnd(&pfile_in_zip_read_info->stream);
-
- pfile_in_zip_read_info->stream_initialised = 0;
- TRYFREE(pfile_in_zip_read_info);
-
- s->pfile_in_zip_read=NULL;
-
- return err;
-}
-
-
-/*
- Open a Zip file. path contain the full pathname (by example,
- on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
- "zlib/zlib114.zip".
- If the zipfile cannot be opened (file doesn't exist or in not valid), the
- return value is NULL.
- Else, the return value is a unzFile Handle, usable with other function
- of this unzip package.
-*/
-extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
- const char *path;
- zlib_filefunc_def* pzlib_filefunc_def;
-{
- unz_s us;
- unz_s *s;
- uLong central_pos,uL;
-
- uLong number_disk; /* number of the current dist, used for
- spaning ZIP, unsupported, always 0*/
- uLong number_disk_with_CD; /* number the the disk with central dir, used
- for spaning ZIP, unsupported, always 0*/
- uLong number_entry_CD; /* total number of entries in
- the central dir
- (same than number_entry on nospan) */
-
- int err=UNZ_OK;
-
- if (pzlib_filefunc_def==NULL)
- fill_fopen_filefunc(&us.z_filefunc);
- else
- us.z_filefunc = *pzlib_filefunc_def;
-
- us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
- path,
- ZLIB_FILEFUNC_MODE_READ |
- ZLIB_FILEFUNC_MODE_EXISTING);
- if (us.filestream==NULL)
- return NULL;
-
- central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
- if (central_pos==0)
- err=UNZ_ERRNO;
-
- if (ZSEEK(us.z_filefunc, us.filestream,
- central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
- err=UNZ_ERRNO;
-
- /* the signature, already checked */
- if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- /* number of this disk */
- if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- /* number of the disk with the start of the central directory */
- if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- /* total number of entries in the central dir on this disk */
- if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- /* total number of entries in the central dir */
- if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- if ((number_entry_CD!=us.gi.number_entry) ||
- (number_disk_with_CD!=0) ||
- (number_disk!=0))
- err=UNZ_BADZIPFILE;
-
- /* size of the central directory */
- if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- /* offset of start of central directory with respect to the
- starting disk number */
- if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- /* zipfile comment length */
- if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
- err=UNZ_ERRNO;
-
- if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
- (err==UNZ_OK))
- err=UNZ_BADZIPFILE;
-
- if (err!=UNZ_OK)
- {
- ZCLOSE(us.z_filefunc, us.filestream);
- return NULL;
- }
-
- us.byte_before_the_zipfile = central_pos -
- (us.offset_central_dir+us.size_central_dir);
- us.central_pos = central_pos;
- us.pfile_in_zip_read = NULL;
- us.encrypted = 0;
-
-
- s=(unz_s*)ALLOC(sizeof(unz_s));
- *s=us;
- unzGoToFirstFile((unzFile)s);
- return (unzFile)s;
-}
-
-
-/*
- Read bytes from the current file.
- buf contain buffer where data must be copied
- len the size of buf.
-
- return the number of byte copied if somes bytes are copied
- return 0 if the end of file was reached
- return <0 with error code if there is an error
- (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-int unzReadCurrentFile (file, buf, len)
- unzFile file;
- voidp buf;
- unsigned len;
-{
- int err=UNZ_OK;
- uInt iRead = 0;
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
-
-
- if ((pfile_in_zip_read_info->read_buffer == NULL))
- return UNZ_END_OF_LIST_OF_FILE;
- if (len==0)
- return 0;
-
- pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
-
- pfile_in_zip_read_info->stream.avail_out = (uInt)len;
-
- if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
- (!(pfile_in_zip_read_info->raw)))
- pfile_in_zip_read_info->stream.avail_out =
- (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
-
- if ((len>pfile_in_zip_read_info->rest_read_compressed+
- pfile_in_zip_read_info->stream.avail_in) &&
- (pfile_in_zip_read_info->raw))
- pfile_in_zip_read_info->stream.avail_out =
- (uInt)pfile_in_zip_read_info->rest_read_compressed+
- pfile_in_zip_read_info->stream.avail_in;
-
- while (pfile_in_zip_read_info->stream.avail_out>0)
- {
- if ((pfile_in_zip_read_info->stream.avail_in==0) &&
- (pfile_in_zip_read_info->rest_read_compressed>0))
- {
- uInt uReadThis = UNZ_BUFSIZE;
- if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
- uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
- if (uReadThis == 0)
- return UNZ_EOF;
- if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
- pfile_in_zip_read_info->filestream,
- pfile_in_zip_read_info->pos_in_zipfile +
- pfile_in_zip_read_info->byte_before_the_zipfile,
- ZLIB_FILEFUNC_SEEK_SET)!=0)
- return UNZ_ERRNO;
- if (ZREAD(pfile_in_zip_read_info->z_filefunc,
- pfile_in_zip_read_info->filestream,
- pfile_in_zip_read_info->read_buffer,
- uReadThis)!=uReadThis)
- return UNZ_ERRNO;
-
- pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
-
- pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
-
- pfile_in_zip_read_info->stream.next_in =
- (Bytef*)pfile_in_zip_read_info->read_buffer;
- pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
- }
-
- if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
- {
- uInt uDoCopy,i ;
-
- if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
- (pfile_in_zip_read_info->rest_read_compressed == 0))
- return (iRead==0) ? UNZ_EOF : iRead;
-
- if (pfile_in_zip_read_info->stream.avail_out <
- pfile_in_zip_read_info->stream.avail_in)
- uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
- else
- uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
-
- for (i=0;i<uDoCopy;i++)
- *(pfile_in_zip_read_info->stream.next_out+i) =
- *(pfile_in_zip_read_info->stream.next_in+i);
-
- pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
- pfile_in_zip_read_info->stream.next_out,
- uDoCopy);
- pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
- pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
- pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
- pfile_in_zip_read_info->stream.next_out += uDoCopy;
- pfile_in_zip_read_info->stream.next_in += uDoCopy;
- pfile_in_zip_read_info->stream.total_out += uDoCopy;
- iRead += uDoCopy;
- }
- else
- {
- uLong uTotalOutBefore,uTotalOutAfter;
- const Bytef *bufBefore;
- uLong uOutThis;
- int flush=Z_SYNC_FLUSH;
-
- uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
- bufBefore = pfile_in_zip_read_info->stream.next_out;
-
- /*
- if ((pfile_in_zip_read_info->rest_read_uncompressed ==
- pfile_in_zip_read_info->stream.avail_out) &&
- (pfile_in_zip_read_info->rest_read_compressed == 0))
- flush = Z_FINISH;
- */
- err=inflate(&pfile_in_zip_read_info->stream,flush);
-
- if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
- err = Z_DATA_ERROR;
-
- uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
- uOutThis = uTotalOutAfter-uTotalOutBefore;
-
- pfile_in_zip_read_info->crc32 =
- crc32(pfile_in_zip_read_info->crc32,bufBefore,
- (uInt)(uOutThis));
-
- pfile_in_zip_read_info->rest_read_uncompressed -=
- uOutThis;
-
- iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
-
- if (err==Z_STREAM_END)
- return (iRead==0) ? UNZ_EOF : iRead;
- if (err!=Z_OK)
- break;
- }
- }
-
- if (err==Z_OK)
- return iRead;
- return err;
-}
-
-/*
- Read the local header of the current zipfile
- Check the coherency of the local header and info in the end of central
- directory about this file
- store in *piSizeVar the size of extra info in local header
- (filename and size of extra field data)
-*/
-int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
- poffset_local_extrafield,
- psize_local_extrafield)
- unz_s* s;
- uInt* piSizeVar;
- uLong *poffset_local_extrafield;
- uInt *psize_local_extrafield;
-{
- uLong uMagic,uData,uFlags;
- uLong size_filename;
- uLong size_extra_field;
- int err=UNZ_OK;
-
- *piSizeVar = 0;
- *poffset_local_extrafield = 0;
- *psize_local_extrafield = 0;
-
- if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
- s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
- return UNZ_ERRNO;
-
-
- if (err==UNZ_OK){
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
- err=UNZ_ERRNO;
- else if (uMagic!=0x04034b50)
- err=UNZ_BADZIPFILE;
- }
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
- err=UNZ_ERRNO;
-/*
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
- err=UNZ_BADZIPFILE;
-*/
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
- err=UNZ_ERRNO;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
- err=UNZ_BADZIPFILE;
-
- if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
- (s->cur_file_info.compression_method!=Z_DEFLATED))
- err=UNZ_BADZIPFILE;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
- err=UNZ_ERRNO;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
- ((uFlags & 8)==0))
- err=UNZ_BADZIPFILE;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
- ((uFlags & 8)==0))
- err=UNZ_BADZIPFILE;
-
- if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
- ((uFlags & 8)==0))
- err=UNZ_BADZIPFILE;
-
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
- err=UNZ_BADZIPFILE;
-
- *piSizeVar += (uInt)size_filename;
-
- if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
- err=UNZ_ERRNO;
- *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
- SIZEZIPLOCALHEADER + size_filename;
- *psize_local_extrafield = (uInt)size_extra_field;
-
- *piSizeVar += (uInt)size_extra_field;
-
- return err;
-}
-
-/*
- Open for reading data the current file in the zipfile.
- If there is no error and the file is opened, the return value is UNZ_OK.
-*/
-int unzOpenCurrentFile3 (file, method, level, raw, password)
- unzFile file;
- int* method;
- int* level;
- int raw;
- const char* password;
-{
- int err=UNZ_OK;
- uInt iSizeVar;
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- uLong offset_local_extrafield; /* offset of the local extra field */
- uInt size_local_extrafield; /* size of the local extra field */
-
- if (password != NULL)
- return UNZ_PARAMERROR;
-
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (!s->current_file_ok)
- return UNZ_PARAMERROR;
-
- if (s->pfile_in_zip_read != NULL)
- unzCloseCurrentFile(file);
-
- if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
- &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
- return UNZ_BADZIPFILE;
-
- pfile_in_zip_read_info = (file_in_zip_read_info_s*)
- ALLOC(sizeof(file_in_zip_read_info_s));
- if (pfile_in_zip_read_info==NULL)
- return UNZ_INTERNALERROR;
-
- pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
- pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
- pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
- pfile_in_zip_read_info->pos_local_extrafield=0;
- pfile_in_zip_read_info->raw=raw;
-
- if (pfile_in_zip_read_info->read_buffer==NULL)
- {
- TRYFREE(pfile_in_zip_read_info);
- return UNZ_INTERNALERROR;
- }
-
- pfile_in_zip_read_info->stream_initialised=0;
-
- if (method!=NULL)
- *method = (int)s->cur_file_info.compression_method;
-
- if (level!=NULL)
- {
- *level = 6;
- switch (s->cur_file_info.flag & 0x06)
- {
- case 6 : *level = 1; break;
- case 4 : *level = 2; break;
- case 2 : *level = 9; break;
- }
- }
-
- if ((s->cur_file_info.compression_method!=0) &&
- (s->cur_file_info.compression_method!=Z_DEFLATED))
- err=UNZ_BADZIPFILE;
-
- pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
- pfile_in_zip_read_info->crc32=0;
- pfile_in_zip_read_info->compression_method =
- s->cur_file_info.compression_method;
- pfile_in_zip_read_info->filestream=s->filestream;
- pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
- pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
-
- pfile_in_zip_read_info->stream.total_out = 0;
-
- if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
- (!raw))
- {
- pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
- pfile_in_zip_read_info->stream.zfree = (free_func)0;
- pfile_in_zip_read_info->stream.opaque = (voidpf)0;
- pfile_in_zip_read_info->stream.next_in = (voidpf)0;
- pfile_in_zip_read_info->stream.avail_in = 0;
-
- err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
- if (err == Z_OK)
- pfile_in_zip_read_info->stream_initialised=1;
- else
- {
- TRYFREE(pfile_in_zip_read_info);
- return err;
- }
- /* windowBits is passed < 0 to tell that there is no zlib header.
- * Note that in this case inflate *requires* an extra "dummy" byte
- * after the compressed stream in order to complete decompression and
- * return Z_STREAM_END.
- * In unzip, i don't wait absolutely Z_STREAM_END because I known the
- * size of both compressed and uncompressed data
- */
- }
- pfile_in_zip_read_info->rest_read_compressed =
- s->cur_file_info.compressed_size ;
- pfile_in_zip_read_info->rest_read_uncompressed =
- s->cur_file_info.uncompressed_size ;
-
-
- pfile_in_zip_read_info->pos_in_zipfile =
- s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
- iSizeVar;
-
- pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-
- s->pfile_in_zip_read = pfile_in_zip_read_info;
-
- return UNZ_OK;
-}
-
-/*
- Close a ZipFile opened with unzipOpen.
- If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
- these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
- return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzClose (file)
- unzFile file;
-{
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
-
- if (s->pfile_in_zip_read!=NULL)
- unzCloseCurrentFile(file);
-
- ZCLOSE(s->z_filefunc, s->filestream);
- TRYFREE(s);
- return UNZ_OK;
-}
-
-#ifndef _WIN32_WCE
-
-/* mymkdir and change_file_date are not 100 % portable
- As I don't know well Unix, I wait feedback for the unix portion */
-
-int mymkdir(dirname)
- const char* dirname;
-{
- int ret=0;
-#if defined(WIN32) || defined(_WIN32_WCE)
- return mkdir(dirname);
-#else
- return mkdir (dirname, 700);
-#endif
- return ret;
-}
-
-int makedir (newdir)
- char *newdir;
-{
- char *buffer ;
- char *p;
- int len = (int)strlen(newdir);
-
- if (len <= 0)
- return 0;
-
- buffer = (char*)gf_malloc(len+1);
- strcpy(buffer,newdir);
-
- if (buffer[len-1] == '/') {
- buffer[len-1] = '\0';
- }
- if (mymkdir(buffer) == 0)
- {
- gf_free(buffer);
- return 1;
- }
-
- p = buffer+1;
- while (1)
- {
- char hold;
-
- while(*p && *p != '\\' && *p != '/')
- p++;
- hold = *p;
- *p = 0;
- if ((mymkdir(buffer) == -1) && (errno == ENOENT))
- {
- printf("couldn't create directory %s\n",buffer);
- gf_free(buffer);
- return 0;
- }
- if (hold == 0)
- break;
- *p++ = hold;
- }
- gf_free(buffer);
- return 1;
-}
-#else
-int makedir (newdir)
-{
- return 0;
-}
-#endif
-
-
-int do_extract_currentfile(uf)
- unzFile uf;
-{
- char filename_inzip[256];
- char* filename_withoutpath;
- char* p;
- int err=UNZ_OK;
- FILE *fout=NULL;
- void* buf;
- uInt size_buf;
-
- unz_file_info file_info;
- err = unzlocal_GetCurrentFileInfoInternal(uf,&file_info,NULL,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
-
- if (err!=UNZ_OK)
- {
- printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
- return err;
- }
-
- size_buf = WRITEBUFFERSIZE;
- buf = (void*)gf_malloc(size_buf);
- if (buf==NULL)
- {
- printf("Error allocating memory\n");
- return UNZ_INTERNALERROR;
- }
-
- p = filename_withoutpath = filename_inzip;
- while ((*p) != '\0')
- {
- if (((*p)=='/') || ((*p)=='\\'))
- filename_withoutpath = p+1;
- p++;
- }
-
- if ((*filename_withoutpath)=='\0')
- {
-#ifndef _WIN32_WCE
- printf("creating directory: %s\n",filename_inzip);
- mymkdir(filename_inzip);
-#endif
- }
- else
- {
- const char* write_filename;
- int skip=0;
-
- write_filename = filename_inzip;
-
- err = unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/);
- if (err!=UNZ_OK)
- {
- printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
- }
-
- if ((skip==0) && (err==UNZ_OK))
- {
- fout=fopen(write_filename,"wb");
-
- /* some zipfile don't contain directory alone before file */
- if ((fout==NULL) && (filename_withoutpath!=(char*)filename_inzip))
- {
- char c=*(filename_withoutpath-1);
- *(filename_withoutpath-1)='\0';
- makedir(write_filename);
- *(filename_withoutpath-1)=c;
- fout=fopen(write_filename,"wb");
- }
-
- if (fout==NULL)
- {
- printf("error opening %s\n",write_filename);
- }
- }
-
- if (fout!=NULL)
- {
- printf(" extracting: %s\n",write_filename);
-
- do
- {
- err = unzReadCurrentFile(uf,buf,size_buf);
- if (err<0)
- {
- printf("error %d with zipfile in unzReadCurrentFile\n",err);
- break;
- }
- if (err>0)
- if (fwrite(buf,err,1,fout)!=1)
- {
- printf("error in writing extracted file\n");
- err=UNZ_ERRNO;
- break;
- }
- }
- while (err>0);
- if (fout)
- fclose(fout);
- }
-
- if (err==UNZ_OK)
- {
- err = unzCloseCurrentFile (uf);
- if (err!=UNZ_OK)
- {
- printf("error %d with zipfile in unzCloseCurrentFile\n",err);
- }
- }
- else
- unzCloseCurrentFile(uf); /* don't lose the error */
- }
-
- gf_free(buf);
- return err;
-}
-
-
-int gf_unzip_archive(const char *zipfilename, const char *dirname)
-{
- uLong i;
- unz_global_info gi;
- int err;
-
- unzFile uf=NULL;
-
- uf = unzOpen2(zipfilename, NULL);
- if (uf==NULL)
- {
- printf("Cannot open %s\n", zipfilename);
- return 1;
- }
-#ifndef _WIN32_WCE
- if (chdir(dirname))
- {
- printf("Error changing into %s, aborting\n", dirname);
- exit(-1);
- }
-#endif
-
- err = unzGetGlobalInfo (uf,&gi);
- if (err!=UNZ_OK)
- printf("error %d with zipfile in unzGetGlobalInfo \n",err);
-
- for (i=0;i<gi.number_entry;i++)
- {
- if (do_extract_currentfile(uf) != UNZ_OK)
- break;
-
- if ((i+1)<gi.number_entry)
- {
- err = unzGoToNextFile(uf);
- if (err!=UNZ_OK)
- {
- printf("error %d with zipfile in unzGoToNextFile\n",err);
- break;
- }
- }
- }
- unzClose(uf);
-
- return 0;
-}
-
-int gf_unzip_probe(const char *zipfilename)
-{
- int ret = 0;
- FILE *f = fopen(zipfilename, "r");
- if (!f) return 0;
- if (fgetc(f)=='P')
- if (fgetc(f)=='K')
- if (fgetc(f)==3)
- if (fgetc(f)==4)
- ret = 1;
- fclose(f);
- return ret;
-}
+++ /dev/null
-//This software module was originally developed by TelecomParisTech in the
-//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard.
-//
-//This software module is an implementation of a part of one or
-//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets
-//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets
-//(ISO/IEC 23007-1) free license to this software module or modifications
-//thereof for use in hardware or software products claiming conformance to
-//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software
-//module in hardware or software products are advised that its use may
-//infringe existing patents.
-//The original developer of this software module and his/her company, the
-//subsequent editors and their companies, and ISO/IEC have no liability
-//for use of this software module or modifications thereof in an implementation.
-//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming
-//products.
-//Telecom ParisTech retains full right to use the code for his/her own purpose,
-//assign or donate the code to a third party and to inhibit third parties from
-//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products.
-//
-//This copyright notice must be included in all copies or derivative works.
-//
-//Copyright (c) 2009.
-//
-/////////////////////////////////////////////////////////////////////////////////
-
-/////////////////////////////////////////////////////////////////////////////////
-//
-// Authors:
-// Jean Le Feuvre, Telecom ParisTech
-// Cyril Concolato, Telecom ParisTech
-//
-/////////////////////////////////////////////////////////////////////////////////
-
-#include "widgetman.h"
-
-#ifdef GPAC_HAS_SPIDERMONKEY
-
-#if !defined(__GNUC__)
-# pragma comment(lib, "js32")
-#endif
-
-
-JSBool gf_sg_js_event_add_listener(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, GF_Node *vrml_node);
-JSBool gf_sg_js_event_remove_listener(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, GF_Node *vrml_node);
-
-
-
-static Bool is_same_path(const char *p1, const char *p2, u32 len)
-{
- char c1, c2;
- u32 i=0;
- do {
- if (len && (i==len))
- break;
- c1 = p1[i];
- c2 = p2[i];
- if (p1[i] != p2[i]) {
- if ((c1=='/') && (c2=='\\')) {}
- else if ((c1=='\\') && (c2=='/')) {}
- else return 0;
- }
- i++;
- } while (c1);
- return 1;
-}
-
-static void widget_package_extract_file(GF_WidgetPackage *wpack, GF_WidgetPackageResource *res)
-{
- u32 i, count;
-
- if (wpack->is_zip) {
- unz_global_info gi;
- unzFile uf = unzOpen2(wpack->package_path, NULL);
- if (!uf) return;
-
- unzGetGlobalInfo(uf, &gi);
- for (i=0; i<gi.number_entry; i++) {
- char buf[8192];
- int err;
- FILE *fout;
- char filename_inzip[256];
-
- unz_file_info file_info;
- unzGetCurrentFileInfo(uf, &file_info, filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
-
- if (strcmp(res->inner_path, filename_inzip)) {
- if ((i+1)<gi.number_entry)
- unzGoToNextFile(uf);
- continue;
- }
-
- unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/);
-
- fout=gf_f64_open(res->extracted_path, "wb");
- if (!fout) break;
- do {
- err = unzReadCurrentFile(uf,buf,8192);
- if (err<0) break;
- if (err>0)
- if (fwrite(buf,err,1,fout)!=1) {
- err=UNZ_ERRNO;
- break;
- }
- } while (err>0);
- if (fout) fclose(fout);
-
- res->extracted = 1;
- break;
- }
- unzClose(uf);
- } else {
- GF_ISOFile *isom = gf_isom_open(wpack->package_path, GF_ISOM_OPEN_READ, 0);
- if (!isom ) return;
-
- count = gf_isom_get_meta_item_count(isom, 1, 0);
- for (i=0; i<count; i++) {
- u32 ID;
- const char *url, *urn, *enc;
- Bool self_ref;
- const char *item_name;
-
- gf_isom_get_meta_item_info(isom, 1, 0, i+1, &ID, NULL, &self_ref, &item_name, NULL, &enc, &url, &urn);
- if (strcmp(res->inner_path, item_name)) continue;
-
- gf_isom_extract_meta_item(isom, 1, 0, ID, res->extracted_path);
- res->extracted = 1;
- break;
- }
- gf_isom_close(isom);
- }
-
-}
-
-static Bool package_find_res(GF_WidgetPackage *wpack, char *res_path, char *relocated_path, char *localized_rel_path)
-{
- u32 count, i;
- count = gf_list_count(wpack->resources);
- for (i=0;i<count;i++) {
- GF_WidgetPackageResource *pack_res = gf_list_get(wpack->resources, i);
- if (is_same_path(res_path, pack_res->inner_path, 0)) {
- strcpy(localized_rel_path, res_path);
- strcpy(relocated_path, pack_res->extracted_path);
- if (!pack_res->extracted) widget_package_extract_file(wpack, pack_res);
- return 1;
- }
- }
- return 0;
-}
-
-/* Checks if a resource in the package has the given rel_path, potentially in a localized sub-folder */
-static Bool widget_package_relocate_uri(void *__self, const char *parent_uri, const char *rel_path, char *relocated_path, char *localized_rel_path)
-{
- char path[GF_MAX_PATH];
- const char *opt;
- GF_WidgetPackage *wpack = (GF_WidgetPackage *)__self;
-
- assert(parent_uri);
- /*resource belongs to our archive*/
- if (strstr(rel_path, wpack->archive_id)) {
- rel_path = strstr(rel_path, wpack->archive_id) + strlen(wpack->archive_id);
- }
- /*parent resource belongs to our archive*/
- else if (strstr(parent_uri, wpack->archive_id)) {
- }
- /*resource doesn't belong to our archive*/
- else {
- return 0;
- }
-
- /* First try to locate the resource in the locales folder */
- opt = gf_cfg_get_key(wpack->wm->term->user->config, "Systems", "Language2CC");
- if (opt) {
- if (!strcmp(opt, "*") || !strcmp(opt, "un") )
- opt = NULL;
- }
-
- while (opt) {
- char lan[100];
- char *sep;
- char *sep_lang = strchr(opt, ';');
- if (sep_lang) sep_lang[0] = 0;
-
- while (strchr(" \t", opt[0]))
- opt++;
- strcpy(lan, opt);
-
- if (sep_lang) {
- sep_lang[0] = ';';
- opt = sep_lang+1;
- } else {
- opt = NULL;
- }
-
- while (1) {
- sep = strstr(lan, "-*");
- if (!sep) break;
- strncpy(sep, sep+2, strlen(sep)-2);
- }
-
- sprintf(path, "locales/%s/%s", lan, rel_path);
- if (package_find_res(wpack, path, relocated_path, localized_rel_path))
- return 1;
-
- /*recursively remove region (sub)tags*/
- while (1) {
- sep = strrchr(lan, '-');
- if (!sep) break;
- sep[0] = 0;
- sprintf(path, "locales/%s/%s", lan, rel_path);
- if (package_find_res(wpack, path, relocated_path, localized_rel_path))
- return 1;
- }
- }
-
- /*no locale*/
- if (package_find_res(wpack, (char*)rel_path, relocated_path, localized_rel_path))
- return 1;
-
- strcpy(localized_rel_path, "");
- strcpy(relocated_path, "");
- return 0;
-}
-
-static GF_WidgetPackage *widget_isom_new(GF_WidgetManager *wm, const char *path)
-{
- GF_WidgetPackageResource *pack_res;
- char szPath[GF_MAX_PATH];
- const char *dir;
- GF_WidgetPackage *wzip;
- u32 brand = 0;
- u32 i, count;
- GF_ISOFile *isom = gf_isom_open(path, GF_ISOM_OPEN_READ, 0);
- if (!isom ) return NULL;
-
- brand = gf_isom_get_meta_type(isom, 1, 0);
- if ((brand!=GF_4CC('m','w','g','t') ) || !gf_isom_has_meta_xml(isom, 1, 0) ) {
- gf_isom_close(isom);
- return NULL;
- }
-
- GF_SAFEALLOC(wzip, GF_WidgetPackage);
-
- wzip->wm = wm;
- wzip->relocate_uri = widget_package_relocate_uri;
- wzip->resources = gf_list_new();
- dir = gf_cfg_get_key(wm->term->user->config, "General", "CacheDirectory");
- /* create the extracted path for the package root using:
- the cache dir + a CRC of the file path and the instance*/
- sprintf(wzip->root_extracted_path, "%s%08X", path, (unsigned int)((unsigned long) wzip));
- i = gf_crc_32((char *)wzip->root_extracted_path, strlen(wzip->root_extracted_path));
- sprintf(wzip->archive_id, "GWM_%08X_", i);
- sprintf(wzip->root_extracted_path, "%s/%s", dir, wzip->archive_id);
-
-
- strcpy(szPath, wzip->root_extracted_path);
- strcat(szPath, "config.xml");
- if (gf_isom_extract_meta_xml(isom, 1, 0, szPath, NULL) != GF_OK) {
- gf_list_del(wzip->resources);
- gf_free(wzip);
- gf_isom_close(isom);
- return NULL;
- }
-
- wzip->package_path = gf_strdup(path);
-
- GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
- pack_res->extracted_path = gf_strdup(szPath);
- pack_res->inner_path = gf_strdup("config.xml");
- pack_res->extracted = 1;
- gf_list_add(wzip->resources, pack_res);
-
-
- count = gf_isom_get_meta_item_count(isom, 1, 0);
- for (i=0; i<count; i++) {
- u32 ID;
- const char *url, *urn, *enc;
- Bool self_ref;
- char *sep;
- const char *item_name;
-
- gf_isom_get_meta_item_info(isom, 1, 0, i+1, &ID, NULL, &self_ref, &item_name, NULL, &enc, &url, &urn);
-
- sep = strrchr(item_name, '/');
- if (!sep) sep = strrchr(item_name, '\\');
- if (sep) {
- sep[0] = 0;
- sprintf(szPath, "%s_%08X_%s", wzip->root_extracted_path, gf_crc_32((char*)item_name, strlen(item_name)), sep+1);
- sep[0] = '/';
- } else {
- strcpy(szPath, wzip->root_extracted_path);
- strcat(szPath, item_name);
- }
- GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
- pack_res->extracted_path = gf_strdup(szPath);
- pack_res->inner_path = gf_strdup(item_name);
- pack_res->extracted = 0;
- gf_list_add(wzip->resources, pack_res);
- }
- gf_isom_close(isom);
-
-
- /* register this widget package as a relocator to enable localization of resources inside this package */
- gf_mx_p(wm->term->net_mx);
- gf_list_add(wm->term->uri_relocators, wzip);
- gf_mx_v(wm->term->net_mx);
- return wzip;
-}
-
-static GF_WidgetPackage *widget_zip_new(GF_WidgetManager *wm, const char *path)
-{
- unz_global_info gi;
- const char *dir;
- u32 i;
- GF_WidgetPackage *wzip;
- unzFile uf = unzOpen2(path, NULL);
- if (!uf) return NULL;
-
- GF_SAFEALLOC(wzip, GF_WidgetPackage);
-
- wzip->wm = wm;
- wzip->is_zip = 1;
- wzip->relocate_uri = widget_package_relocate_uri;
- wzip->resources = gf_list_new();
- wzip->package_path = gf_strdup(path);
- dir = gf_cfg_get_key(wm->term->user->config, "General", "CacheDirectory");
- /* create the extracted path for the package root using:
- the cache dir + a CRC of the file path and the instance*/
- sprintf(wzip->root_extracted_path, "%s%08X", path, (unsigned int)((unsigned long) wzip));
- i = gf_crc_32((char *)wzip->root_extracted_path, strlen(wzip->root_extracted_path));
- sprintf(wzip->archive_id, "GWM_%08X_", i);
- sprintf(wzip->root_extracted_path, "%s/%s", dir, wzip->archive_id);
-
- unzGetGlobalInfo(uf, &gi);
- for (i=0; i<gi.number_entry; i++) {
- char szPath[GF_MAX_PATH];
- char *sep;
- GF_WidgetPackageResource *pack_res;
- char filename_inzip[256];
- unz_file_info file_info;
- unzGetCurrentFileInfo(uf, &file_info, filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
-
- sep = strrchr(filename_inzip, '/');
- if (!sep) sep = strrchr(filename_inzip, '\\');
- if (sep) {
- sep[0] = 0;
- sprintf(szPath, "%s_%08X_%s", wzip->root_extracted_path, gf_crc_32(filename_inzip, strlen(filename_inzip)), sep+1);
- sep[0] = '/';
- } else {
- strcpy(szPath, wzip->root_extracted_path);
- strcat(szPath, filename_inzip);
- }
-
-
- if (!strcmp(filename_inzip, "config.xml")) {
- int err;
- char buf[8192];
- FILE *fout;
- unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/);
-
- fout=gf_f64_open(szPath,"wb");
- if (!fout) return NULL;
-
- do {
- err = unzReadCurrentFile(uf,buf,8192);
- if (err<0) break;
-
- if (err>0)
- if (fwrite(buf,err,1,fout)!=1) {
- err=UNZ_ERRNO;
- break;
- }
- } while (err>0);
- if (fout) fclose(fout);
- if (err==0) {
- GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
- pack_res->extracted_path = gf_strdup(szPath);
- pack_res->inner_path = gf_strdup(filename_inzip);
- pack_res->extracted = 1;
- gf_list_add(wzip->resources, pack_res);
- }
- } else {
- GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
- pack_res->extracted_path = gf_strdup(szPath);
- pack_res->inner_path = gf_strdup(filename_inzip);
- pack_res->extracted = 0;
- gf_list_add(wzip->resources, pack_res);
- }
-
- if ((i+1)<gi.number_entry)
- unzGoToNextFile(uf);
- }
- unzClose(uf);
-
- /* register this widget package as a relocator to enable localization of resources inside this package */
- gf_mx_p(wm->term->net_mx);
- gf_list_add(wm->term->uri_relocators, wzip);
- gf_mx_v(wm->term->net_mx);
- return wzip;
-}
-
-GF_WidgetPackage *widget_package_new(GF_WidgetManager *wm, const char *path)
-{
- if (gf_unzip_probe(path)) {
- return widget_zip_new(wm, path);
- }
- /*ISOFF-based packaged widget */
- else if (gf_isom_probe_file(path)) {
- return widget_isom_new(wm, path);
- }
- return NULL;
-}
-
-static void widget_package_del(GF_WidgetManager *wm, GF_WidgetPackage *wpackage)
-{
- gf_mx_p(wm->term->net_mx);
- gf_list_del_item(wm->term->uri_relocators, wpackage);
- gf_mx_v(wm->term->net_mx);
-
- while (gf_list_count(wpackage->resources)) {
- GF_WidgetPackageResource *wu = gf_list_get(wpackage->resources, 0);
- gf_list_rem(wpackage->resources, 0);
- gf_delete_file(wu->extracted_path);
- gf_free(wu->extracted_path);
- gf_free(wu->inner_path);
- gf_free(wu);
- }
- gf_list_del(wpackage->resources);
- if (wpackage->sess) gf_dm_sess_del(wpackage->sess);
- gf_free(wpackage->package_path);
- gf_free(wpackage);
-}
-
-
-
-static void wm_delete_message_param(GF_WidgetPin *mp)
-{
- if (!mp) return;
- if (mp->node) gf_free(mp->node);
- if (mp->attribute) gf_free(mp->attribute);
- if (mp->default_value) gf_free(mp->default_value);
- if (mp->name) gf_free(mp->name);
- gf_free(mp);
-}
-
-static void wm_delete_widget_content(GF_WidgetContent *content)
-{
- if (!content) return;
-
- while (gf_list_count(content->interfaces)) {
- GF_WidgetInterface*ifce = gf_list_last(content->interfaces);
- gf_list_rem_last(content->interfaces);
-
- while (gf_list_count(ifce->messages)) {
- GF_WidgetMessage *msg = gf_list_last(ifce->messages);
- gf_list_rem_last(ifce->messages);
-
- while (gf_list_count(msg->params)) {
- GF_WidgetPin *par = gf_list_last(msg->params);
- gf_list_rem_last(msg->params);
- wm_delete_message_param(par);
- }
- gf_list_del(msg->params);
-
- wm_delete_message_param(msg->input_action);
- wm_delete_message_param(msg->output_trigger);
- gf_free(msg->name);
- gf_free(msg);
- }
- gf_list_del(ifce->messages);
- wm_delete_message_param(ifce->bind_action);
- wm_delete_message_param(ifce->unbind_action);
- if (ifce->obj) gf_js_remove_root(ifce->content->widget->wm->ctx, &ifce->obj, GF_JSGC_OBJECT);
-
- if (ifce->connectTo) gf_free(ifce->connectTo);
- gf_free(ifce->type);
- gf_free(ifce);
- }
- gf_list_del(content->interfaces);
-
- while (gf_list_count(content->components)) {
- GF_WidgetComponent *comp = gf_list_last(content->components);
- gf_list_rem_last(content->components);
-
- wm_delete_message_param(comp->activateTrigger);
- wm_delete_message_param(comp->deactivateTrigger);
-
- while (gf_list_count(comp->required_interfaces)) {
- char *type = gf_list_last(comp->required_interfaces);
- gf_list_rem_last(comp->required_interfaces);
- if (type) gf_free(type);
- }
- gf_list_del(comp->required_interfaces);
- if (comp->id) gf_free(comp->id);
- if (comp->src) gf_free(comp->src);
- gf_free(comp);
- }
- gf_list_del(content->components);
-
- while (gf_list_count(content->preferences)) {
- GF_WidgetPreference *pref = gf_list_last(content->preferences);
- gf_list_rem_last(content->preferences);
-
- wm_delete_message_param(pref->connectTo);
- if (pref->value) gf_free(pref->value);
- gf_free(pref->name);
- gf_free(pref);
- }
- gf_list_del(content->preferences);
-
- wm_delete_message_param(content->saveTrigger);
- wm_delete_message_param(content->restoreTrigger);
- wm_delete_message_param(content->savedAction);
- wm_delete_message_param(content->restoredAction);
-
- gf_free(content->src);
- gf_free(content->relocated_src);
- gf_free(content->mimetype);
- gf_free(content->encoding);
- gf_free(content);
-}
-
-static void wm_delete_widget(GF_WidgetManager *wm, GF_Widget *wid)
-{
- gf_list_del_item(wm->widgets, wid);
-
- if (wid->url) gf_free(wid->url);
- if (wid->manifest_path) gf_free(wid->manifest_path);
- wm_delete_widget_content(wid->main);
- if (wid->local_path) gf_free(wid->local_path);
- if (wid->name) gf_free(wid->name);
- if (wid->shortname) gf_free(wid->shortname);
- if (wid->identifier) gf_free(wid->identifier);
- if (wid->authorName) gf_free(wid->authorName);
- if (wid->authorEmail) gf_free(wid->authorEmail);
- if (wid->authorHref) gf_free(wid->authorHref);
- if (wid->description) gf_free(wid->description);
- if (wid->license) gf_free(wid->license);
- if (wid->licenseHref) gf_free(wid->licenseHref);
- if (wid->viewmodes) gf_free(wid->viewmodes);
- if (wid->version) gf_free(wid->version);
- if (wid->uuid) gf_free(wid->uuid);
-
-
- while (gf_list_count(wid->icons)) {
- GF_WidgetContent *icon = gf_list_get(wid->icons, 0);
- gf_list_rem(wid->icons, 0);
- wm_delete_widget_content(icon);
- }
- gf_list_del(wid->icons);
-
- while (gf_list_count(wid->features)) {
- GF_WidgetFeature *f = gf_list_get(wid->features, 0);
- gf_list_rem(wid->features, 0);
- if (f->name) gf_free(f->name);
- while (gf_list_count(f->params)) {
- GF_WidgetFeatureParam *p = gf_list_get(f->params, 0);
- gf_list_rem(f->params, 0);
- if (p->name) gf_free(p->name);
- if (p->value) gf_free(p->value);
- gf_free(p);
- }
- gf_free(f);
- }
- gf_list_del(wid->features);
-
- if (wid->wpack) widget_package_del(wm, wid->wpack);
- gf_free(wid);
-}
-
-static void wm_delete_interface_instance(GF_WidgetManager *wm, GF_WidgetInterfaceInstance *bifce)
-{
- if (bifce->hostname) gf_free(bifce->hostname);
- if (bifce->obj) {
- JS_SetPrivate(wm->ctx, bifce->obj, NULL);
- gf_js_remove_root(wm->ctx, &bifce->obj, GF_JSGC_OBJECT);
- }
- gf_free(bifce);
-}
-
-static void wm_delete_widget_instance(GF_WidgetManager *wm, GF_WidgetInstance *widg)
-{
-
- while (gf_list_count(widg->components)) {
- GF_WidgetComponentInstance *comp = gf_list_get(widg->components, 0);
- gf_list_rem(widg->components, 0);
- if (comp->wid) wm_delete_widget_instance(wm, comp->wid);
- gf_free(comp);
- }
- gf_list_del(widg->components);
-
- while (gf_list_count(widg->bound_ifces)) {
- GF_WidgetInterfaceInstance *bifce = gf_list_get(widg->bound_ifces, 0);
- gf_list_rem(widg->bound_ifces, 0);
- wm_delete_interface_instance(wm, bifce);
- }
- gf_list_del(widg->bound_ifces);
-
- gf_list_del(widg->output_triggers);
-
- if (widg->obj) {
- JS_SetPrivate(wm->ctx, widg->obj, NULL);
- gf_js_remove_root(wm->ctx, &widg->obj, GF_JSGC_OBJECT);
- }
- gf_list_del_item(wm->widget_instances, widg);
- widg->widget->nb_instances--;
- if (!widg->widget->nb_instances) wm_delete_widget(wm, widg->widget);
-
- if (!widg->permanent) {
- gf_cfg_del_section(wm->term->user->config, widg->secname);
- gf_cfg_set_key(wm->term->user->config, "Widgets", widg->secname, NULL);
- }
- if (widg->mpegu_context) gf_xml_dom_del(widg->mpegu_context);
-
- gf_free(widg);
-}
-
-
-
-static JSBool wm_widget_call_script(GF_WidgetInstance *wid, GF_WidgetPin *pin, uintN argc, jsval *argv, jsval *rval)
-{
- jsval fval;
- if (!wid->scene_context || !wid->scene_global) return JS_FALSE;
-
- /*if on_load property is assigned to this widget, add an event listener on the root.*/
- JS_LookupProperty(wid->scene_context, wid->scene_global, pin->node, &fval);
- if (JSVAL_IS_OBJECT(fval)) {
- JS_CallFunctionValue(wid->scene_context, wid->scene_global, fval, argc, argv, rval);
- }
- return JS_TRUE;
-}
-
-static JSBool wm_widget_set_scene_input_value(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, u32 type, GF_WidgetInstance *wid, GF_WidgetPin *param, const char *value)
-{
- char *str_val;
- GF_Node *n;
- GF_FieldInfo info;
- GF_WidgetMessage *msg;
- GF_WidgetInterface *ifce;
-
- if (!wid && obj) wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid) return JS_FALSE;
- if (!wid->scene) return JS_TRUE;
-
- if (!param) {
- if (!JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
-
- switch (type) {
- /*set_input*/
- case 0:
- if (argc!=2) return JS_FALSE;
- param = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- break;
- /*call_input_action*/
- case 1:
- msg = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- param = msg ? msg->input_action : NULL;
- break;
- /*bind_interface*/
- case 2:
- ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- param = ifce ? ifce->bind_action : NULL;
- break;
- /*unbind_interface*/
- case 3:
- ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- param = ifce ? ifce->unbind_action : NULL;
- break;
- }
- }
-
- if (!param || !param->node) return JS_TRUE;
- /*this is a script call*/
- if (!param->attribute) {
- return wm_widget_call_script(wid, param, 0, NULL, rval);
- }
-
- n = gf_sg_find_node_by_name(wid->scene, param->node);
- if (!n) return JS_TRUE;
-
- if (param->in_action) return JS_TRUE;
-
- param->in_action = 1;
-
-#ifndef GPAC_DISABLE_SVG
- if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
- u32 evt_type;
- if (!type) {
- char *_str_val = NULL;
- if (value) {
- str_val = (char *)value;
- } else {
- if (!JSVAL_IS_STRING(argv[1])) goto exit;
- str_val = _str_val = SMJS_CHARS(c, argv[1]);
- }
-
- /* first check if the set_input refers to an attribute name or to an event name */
- evt_type = gf_dom_event_type_by_name(param->attribute);
-
- /*events are not allowed for <input> and <output>*/
- if (evt_type == GF_EVENT_UNKNOWN) {
- /* modify an attribute */
- if (!strcmp(param->attribute, "textContent")) {
- gf_dom_set_textContent(n, (char *)str_val);
- gf_node_changed(n, NULL);
- }
- else {
- if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
- gf_svg_parse_attribute(n, &info, (char *)str_val, 0);
- if (info.fieldType==XMLRI_datatype) gf_node_dirty_set(n, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
- gf_node_changed(n, &info);
- }
- }
- }
- SMJS_FREE(c, _str_val);
-
- } else {
- GF_DOM_Event evt;
- memset(&evt, 0, sizeof(GF_DOM_Event));
- /* first check if the set_input refers to an attribute name or to an event name */
- evt_type = gf_dom_event_type_by_name(param->attribute);
- /* launch an event */
- if (evt_type != GF_EVENT_UNKNOWN) {
- evt.type = evt_type;
- gf_dom_event_fire(n, &evt);
- } else {
- /*should we fire a DOMAttrModified event ? to clarify in the spec*/
-
- if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
- evt.bubbles = 1;
- evt.type = GF_EVENT_ATTR_MODIFIED;
- evt.attr = &info;
- gf_dom_event_fire(n, &evt);
- }
- }
- }
- } else
-#endif
-
-
-#ifndef GPAC_DISABLE_VRML
- {
- if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK) return JS_TRUE;
-
- if (!type) {
- char *_str_val = NULL;
- jsdouble val;
-
- switch (info.fieldType) {
- case GF_SG_VRML_SFSTRING:
- if (value) {
- str_val = (char *)value;
- } else {
- if (!JSVAL_IS_STRING(argv[1]))goto exit;
- str_val = SMJS_CHARS(c, argv[1]);
- }
- if ( ((SFString*)info.far_ptr)->buffer) gf_free(((SFString*)info.far_ptr)->buffer);
- ((SFString*)info.far_ptr)->buffer = str_val ? gf_strdup(str_val) : NULL;
- break;
- case GF_SG_VRML_SFBOOL:
- if (value) *((SFBool*)info.far_ptr) = (!strcmp(value, "true")) ? 1 : 0;
- else if (JSVAL_IS_BOOLEAN(argv[1])) *((SFBool*)info.far_ptr) = JSVAL_TO_BOOLEAN(argv[1]);
- else if (JSVAL_IS_INT(argv[1])) *((SFBool*)info.far_ptr) = JSVAL_TO_INT(argv[1]);
- else if (JSVAL_IS_STRING(argv[1])) {
- str_val = SMJS_CHARS(c, argv[1]);
- *((SFBool*)info.far_ptr) = (str_val && !strcmp(str_val, "true")) ? 1 : 0;
- SMJS_FREE(c, str_val);
- } else
- goto exit;
- break;
- case GF_SG_VRML_SFINT32:
- if (value) *((SFInt32*)info.far_ptr) = (s32) atof(value);
- else if (JSVAL_IS_INT(argv[1])) *((SFInt32*)info.far_ptr) = JSVAL_TO_INT(argv[1]);
- else if (JSVAL_IS_NUMBER(argv[1])) {
- JS_ValueToNumber(c, argv[1], &val);
- *((SFInt32*)info.far_ptr) = (s32) val;
- } else if (JSVAL_IS_STRING(argv[1])) {
- Double a_val;
- str_val = SMJS_CHARS(c, argv[1]);
- a_val = str_val ? atof(str_val) : 0;
- *((SFInt32*)info.far_ptr) = (s32) a_val;
- SMJS_FREE(c, str_val);
- } else
- goto exit;
- break;
- case GF_SG_VRML_SFFLOAT:
- if (value) *((SFFloat*)info.far_ptr) = FLT2FIX(atof(value));
- else if (JSVAL_IS_INT(argv[1])) *((SFFloat *)info.far_ptr) = INT2FIX( JSVAL_TO_INT(argv[1]) );
- else if (JSVAL_IS_NUMBER(argv[1])) {
- JS_ValueToNumber(c, argv[1], &val);
- *((SFFloat *)info.far_ptr) = FLT2FIX( val );
- } else if (JSVAL_IS_STRING(argv[1])) {
- Double a_val;
- str_val = SMJS_CHARS(c, argv[1]);
- a_val = str_val ? atof(str_val) : 0;
- *((SFFloat*)info.far_ptr) = FLT2FIX(a_val);
- SMJS_FREE(c, str_val);
- } else
- goto exit;
- break;
- case GF_SG_VRML_SFTIME:
- if (value) *((SFTime*)info.far_ptr) = atof(value);
- else if (JSVAL_IS_INT(argv[1])) *((SFTime *)info.far_ptr) = JSVAL_TO_INT(argv[1]);
- else if (JSVAL_IS_NUMBER(argv[1])) {
- JS_ValueToNumber(c, argv[1], &val);
- *((SFTime *)info.far_ptr) = val;
- } else if (JSVAL_IS_STRING(argv[1])) {
- Double a_val;
- str_val = SMJS_CHARS(c, argv[1]);
- a_val = str_val ? atof(str_val) : 0;
- *((SFTime *)info.far_ptr) = a_val;
- SMJS_FREE(c, str_val);
- } else
- goto exit;
- break;
- case GF_SG_VRML_MFSTRING:
- if (value) {
- str_val = (char *)value;
- } else {
- if (!JSVAL_IS_STRING(argv[1])) goto exit;
- str_val = _str_val = SMJS_CHARS(c, argv[1]);
- }
- if ( ((GenMFField *)info.far_ptr)->count != 1) {
- gf_sg_vrml_mf_reset(info.far_ptr, GF_SG_VRML_MFSTRING);
- gf_sg_vrml_mf_alloc(info.far_ptr, GF_SG_VRML_MFSTRING, 1);
- }
- if ( ((MFString*)info.far_ptr)->vals[0]) gf_free( ((MFString*)info.far_ptr)->vals[0] );
- ((MFString*)info.far_ptr)->vals[0] = str_val ? gf_strdup(str_val) : NULL;
-
- SMJS_FREE(c, _str_val);
- break;
- }
- }
-
- //if this is a script eventIn call directly script
- if ((n->sgprivate->tag==TAG_MPEG4_Script) || (n->sgprivate->tag==TAG_X3D_Script) )
- gf_sg_script_event_in(n, &info);
-
- gf_node_changed(n, &info);
-
- /*if this is an exposedField, route it*/
- if (info.eventType==GF_SG_EVENT_EXPOSED_FIELD) {
- gf_node_event_out(n, info.fieldIndex);
- }
- }
-#endif /*GPAC_DISABLE_VRML*/
-
-exit:
- param->in_action = 0;
- return JS_TRUE;
-}
-
-
-static JSBool SMJS_FUNCTION(wm_widget_set_input)
-{
- SMJS_OBJ
- SMJS_ARGS
- SMJS_DECL_RVAL
- return wm_widget_set_scene_input_value(c, obj, argc, argv, rval, 0, NULL, NULL, NULL);
-}
-static JSBool SMJS_FUNCTION(wm_widget_call_input_action)
-{
- SMJS_OBJ
- SMJS_ARGS
- SMJS_DECL_RVAL
- return wm_widget_set_scene_input_value(c, obj, 1, argv, rval, 1, NULL, NULL, NULL);
-}
-
-
-static JSBool SMJS_FUNCTION(wm_widget_call_input_script)
-{
- GF_WidgetMessage *msg;
- GF_WidgetPin *param;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || (argc!=2) ) return JS_FALSE;
- if (!wid->scene) return JS_TRUE;
-
- if (!JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
- msg = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- param = msg ? msg->input_action : NULL;
- if (!param || !param->node || param->attribute) return JS_FALSE;
-
- if (JSVAL_IS_OBJECT(argv[1])) {
- jsval *args;
- JSObject *list = JSVAL_TO_OBJECT(argv[1]);
- u32 i, count;
- JS_GetArrayLength(c, list, (jsuint*) &count);
- args = gf_malloc(sizeof(jsval)*count);
- for (i=0; i<count; i++) {
- JS_GetElement(c, list, (jsint) i, &args[i] );
- }
-
- wm_widget_call_script(wid, param, count, args, SMJS_GET_RVAL);
-
- gf_free(args);
- }
- return JS_TRUE;
-}
-
-
-static void wm_handler_destroy(GF_Node *node, void *rs, Bool is_destroy)
-{
- if (is_destroy) {
- SVG_handlerElement *handler = (SVG_handlerElement *)node;
- if (handler->js_fun_val) {
- gf_js_remove_root(handler->js_context, &handler->js_fun_val, GF_JSGC_VAL);
- handler->js_fun_val=0;
- }
- }
-}
-
-static SVG_handlerElement *wm_create_scene_listener(GF_WidgetInstance *wid, GF_WidgetPin *param)
-{
- /*FIXME - we need to split SVG and base DOM !!*/
-#ifdef GPAC_DISABLE_SVG
- return NULL;
-#else
- u32 evt_type, att_name;
- GF_Node *listener;
- GF_FieldInfo info;
- GF_Node *n = NULL;
- SVG_handlerElement *handler;
-
- evt_type = GF_EVENT_ATTR_MODIFIED;
- n = gf_sg_find_node_by_name(wid->scene, param->node);
- if (!n) return NULL;
-
- att_name = 0;
-
-#ifndef GPAC_DISABLE_SVG
- if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
- /* first check if the set_input refers to an attribute name or to an event name */
- evt_type = gf_dom_event_type_by_name(param->attribute);
- if (evt_type == GF_EVENT_UNKNOWN) {
- evt_type = GF_EVENT_ATTR_MODIFIED;
-
- /* modify textContent */
- if (!strcmp(param->attribute, "textContent")) {
- att_name = (u32) -1;
- }
- /* modify an attribute */
- else if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
- att_name = info.fieldIndex;
- }
- else {
- return NULL;
- }
- }
- } else
-#endif
- {
- if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK)
- return NULL;
- att_name = info.fieldIndex;
- }
-
- listener = gf_node_new(wid->scene, TAG_SVG_listener);
-
- handler = (SVG_handlerElement *) gf_node_new(wid->scene, TAG_SVG_handler);
- /*we register the handler with the listener node to avoid modifying the DOM*/
- gf_node_register((GF_Node *)handler, listener);
- gf_node_list_add_child(& ((GF_ParentNode *)listener)->children, (GF_Node*)handler);
- handler->sgprivate->UserCallback = wm_handler_destroy;
-
- /*create attributes if needed*/
- gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_event, 1, 0, &info);
- ((XMLEV_Event*)info.far_ptr)->type = evt_type;
- ((XMLEV_Event*)info.far_ptr)->parameter = att_name;
- gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_handler, 1, 0, &info);
- ((XMLRI*)info.far_ptr)->target = (GF_Node*)handler;
- gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_target, 1, 0, &info);
- ((XMLRI*)info.far_ptr)->target = n;
-
- gf_node_get_attribute_by_tag((GF_Node*)handler, TAG_XMLEV_ATT_event, 1, 0, &info);
- ((XMLEV_Event*)info.far_ptr)->type = evt_type;
- ((XMLEV_Event*)info.far_ptr)->parameter = att_name;
-
- gf_node_dom_listener_add((GF_Node *) n, listener);
-
- return handler;
-#endif
-}
-
-static void wm_component_activation_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer, Bool unload)
-{
- JSObject *obj;
- JSContext *c;
- GF_WidgetInstance *wid;
- GF_WidgetComponent *comp;
- SVG_handlerElement *handler = (SVG_handlerElement *)hdl;
-
- c = handler->js_context;
- obj = handler->evt_listen_obj;
- if (!c || !obj) return;
- wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid) return;
-
- comp = (GF_WidgetComponent *)handler->js_fun;
- if (unload) {
- wm_deactivate_component(c, wid, comp, NULL);
- } else {
- wm_activate_component(c, wid, comp, 0);
- }
-}
-static void wm_component_activate_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
-{
- wm_component_activation_event(hdl, evt, observer, 0);
-}
-static void wm_component_deactivate_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
-{
- wm_component_activation_event(hdl, evt, observer, 1);
-}
-
-static void wm_widget_set_pref_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
-{
- char *att;
- SVG_handlerElement *handler = (SVG_handlerElement *)hdl;
- GF_WidgetInstance *wid = (GF_WidgetInstance *) handler->evt_listen_obj;
- GF_WidgetPreference *pref = (GF_WidgetPreference *) handler->js_fun;
-
- if (evt->type != GF_EVENT_ATTR_MODIFIED) return;
-
- if (evt->detail == (u32) -1) {
- att = gf_dom_flatten_textContent(evt->target);
- } else {
- att = gf_node_dump_attribute(evt->target, evt->attr);
- if (!att) return;
- }
- gf_cfg_set_key(wid->widget->wm->term->user->config, wid->secname, pref->name, att);
- gf_free(att);
-}
-
-static void on_widget_activated(JSContext *c, JSObject *obj)
-{
- jsval funval, rval;
- u32 i, count;
- GF_XMLNode *context = NULL;
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || wid->activated) return;
-
- /*widget is now activated*/
- wid->activated = 1;
-
- /*for all components, setup bindings on activateTrigger & deactivateTrigger*/
- count = gf_list_count(wid->widget->main->components);
- for (i=0; i<count; i++) {
- GF_WidgetComponent *comp = gf_list_get(wid->widget->main->components, i);
- /*setup listener*/
- if (comp->activateTrigger && comp->activateTrigger->attribute) {
- SVG_handlerElement *a_hdl = wm_create_scene_listener(wid, comp->activateTrigger);
- if (!a_hdl) return;
- a_hdl->evt_listen_obj = obj;
- a_hdl->js_context = c;
- a_hdl->js_fun = comp;
- a_hdl->handle_event = wm_component_activate_event;
- }
- /*setup listener*/
- if (comp->deactivateTrigger && comp->deactivateTrigger->attribute) {
- SVG_handlerElement *a_hdl = wm_create_scene_listener(wid, comp->deactivateTrigger);
- if (!a_hdl) continue;
- a_hdl->evt_listen_obj = obj;
- a_hdl->js_context = c;
- a_hdl->js_fun = comp;
- a_hdl->handle_event = wm_component_deactivate_event;
- }
- }
-
- if (wid->mpegu_context)
- context = gf_xml_dom_get_root(wid->mpegu_context);
-
- /*load preferences*/
- count = gf_list_count(wid->widget->main->preferences);
- for (i=0; i<count; i++) {
- const char *value;
- GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i);
-
-
- /*get stored value for this preference*/
- value = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, pref->name);
- /*if none found, use preference*/
- if (!value) value = pref->value;
-
- /*and overload with migrated context*/
- if (context) {
- GF_XMLNode *pref_node;
- u32 j=0;
- while ((pref_node = gf_list_enum(context->content, &j))) {
- const char *att;
- if (pref_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(pref_node->name, "preference")) continue;
- att = wm_xml_get_attr(pref_node, "name");
- if (!att) continue;
- if (strcmp(att, pref->name)) continue;
-
- att = wm_xml_get_attr(pref_node, "value");
- if (att) value = att;
- break;
- }
- }
-
- if (pref->connectTo) {
- SVG_handlerElement *hdl;
-
- if (value)
- wm_widget_set_scene_input_value(NULL, NULL, 0, 0, 0, 0, wid, pref->connectTo, value);
-
- /*preference is read only, do not setup listener*/
- if (pref->flags & GF_WM_PREF_READONLY) continue;
- /*preference is migratable only, do not setup listener*/
- if (!(pref->flags & GF_WM_PREF_SAVE)) continue;
-
- /*create the listener*/
- hdl = wm_create_scene_listener(wid, pref->connectTo);
- if (!hdl) continue;
-
- hdl->evt_listen_obj = wid;
- hdl->js_fun = pref;
- hdl->handle_event = wm_widget_set_pref_event;
-
- }
- }
- if (count && wid->widget->main->restoredAction) {
- wm_widget_set_scene_input_value(wid->widget->wm->ctx, wid->obj, 0, NULL, &rval, 0, wid, wid->widget->main->restoredAction, NULL);
- }
-
- if (wid->mpegu_context) {
- gf_xml_dom_del(wid->mpegu_context);
- wid->mpegu_context = NULL;
- }
-
- gf_sg_lock_javascript(wid->widget->wm->ctx, 1);
- /*refresh all interface bindings*/
- JS_LookupProperty(wid->widget->wm->ctx, wid->widget->wm->obj, "check_bindings", &funval);
- if (JSVAL_IS_OBJECT(funval)) {
- JS_CallFunctionValue(wid->widget->wm->ctx, wid->widget->wm->obj, funval, 0, 0, &rval);
- }
-
- /*if on_load property is assigned to this widget, call it.*/
- JS_LookupProperty(c, obj, "on_load", &funval);
- if (JSVAL_IS_OBJECT(funval)) {
- JS_CallFunctionValue(wid->widget->wm->ctx, wid->obj, funval, 0, 0, &rval);
- }
- gf_sg_lock_javascript(wid->widget->wm->ctx, 0);
-}
-
-
-static void wm_widget_load_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
-{
- JSObject *obj;
- JSContext *c;
- SVG_handlerElement *handler = (SVG_handlerElement *)hdl;
-
- c = handler->js_context;
- obj = handler->evt_listen_obj;
- if (!c || !obj) return;
-
- on_widget_activated(c, obj);
-}
-
-
-static JSBool SMJS_FUNCTION(wm_widget_activate)
-{
- SVG_handlerElement *handler;
- GF_MediaObject *mo;
- Bool direct_trigger = 0;
- MFURL url;
- SFURL _url;
- GF_Node *inl;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !argc) return JS_FALSE;
-
- if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
-
- inl = gf_sg_js_get_node(c, JSVAL_TO_OBJECT(argv[0]) );
- if (!inl) return JS_FALSE;
-
- _url.OD_ID = 0;
- _url.url = gf_url_concatenate(wid->widget->url, wid->widget->main->relocated_src);
- url.count = 1;
- url.vals = &_url;
- mo = gf_mo_register(inl, &url, 0, 1);
- if (mo) {
- wid->scene = gf_mo_get_scenegraph(mo);
- if (wid->scene && gf_sg_get_root_node(wid->scene)) direct_trigger = 1;
- }
- if (_url.url) gf_free(_url.url);
-
- wid->anchor = inl;
-
- if (direct_trigger) {
- on_widget_activated(c, obj);
- } else {
-#ifndef GPAC_DISABLE_SVG
- handler = gf_dom_listener_build(inl, GF_EVENT_SCENE_ATTACHED, 0);
- handler->handle_event = wm_widget_load_event;
- handler->js_context = c;
- handler->evt_listen_obj = obj;
-#endif
- }
-
- return JS_TRUE;
-}
-
-
-static void wm_handle_dom_event(GF_Node *hdl, GF_DOM_Event *event, GF_Node *observer)
-{
- JSBool ret;
- GF_FieldInfo info;
- GF_Node *n;
- jsval argv[1], rval, jsfun;
- SVG_handlerElement *handler = (SVG_handlerElement *) hdl;
- GF_WidgetPin *param = handler->js_fun;
- GF_WidgetInstance *wid = (GF_WidgetInstance *)handler->evt_listen_obj;
-
- if (!wid->scene)
- return;
-
- n = gf_sg_find_node_by_name(wid->scene, param->node);
- if (!n) return;
-
- /*this is a regular event output*/
- if (event->type != GF_EVENT_ATTR_MODIFIED) {
- jsfun = (jsval) handler->js_fun_val;
- if (JSVAL_IS_OBJECT(jsfun))
- ret = JS_CallFunctionValue(handler->js_context, wid->obj, (jsval) handler->js_fun_val, 0, 0, &rval);
- return;
- }
-
- /*otherwise this is a node.attr output through DOMAttributeModified*/
- argv[0] = JSVAL_NULL;
-
-#ifndef GPAC_DISABLE_SVG
- if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
- if (!strcmp(param->attribute, "textContent")) {
- char *txt = gf_dom_flatten_textContent(n);
- argv[0] = STRING_TO_JSVAL( JS_NewStringCopyZ(handler->js_context, txt ? txt : "") );
- if (txt) gf_free(txt);
- } else if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
- char *attValue;
- if (event->attr->fieldIndex != info.fieldIndex) return;
-
- attValue = gf_node_dump_attribute(n, &info);
- argv[0] = STRING_TO_JSVAL( JS_NewStringCopyZ(handler->js_context, attValue) );
- if (attValue) gf_free(attValue);
- } else {
- return;
- }
- } else
-#endif
- {
- if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK) return;
- if (event->attr->fieldIndex != info.fieldIndex) return;
-
- switch (info.fieldType) {
- case GF_SG_VRML_SFSTRING:
- argv[0] = STRING_TO_JSVAL( JS_NewStringCopyZ(handler->js_context, ((SFString*)info.far_ptr)->buffer ) );
- break;
- case GF_SG_VRML_SFINT32:
- argv[0] = INT_TO_JSVAL( *((SFInt32*)info.far_ptr) );
- break;
- case GF_SG_VRML_SFBOOL:
- argv[0] = BOOLEAN_TO_JSVAL( *((SFBool*)info.far_ptr) );
- break;
- case GF_SG_VRML_SFFLOAT:
- argv[0] = DOUBLE_TO_JSVAL( JS_NewDouble(handler->js_context, FIX2FLT( *((SFFloat*)info.far_ptr) ) ) );
- break;
- case GF_SG_VRML_SFTIME:
- argv[0] = DOUBLE_TO_JSVAL( JS_NewDouble(handler->js_context, *((SFTime *)info.far_ptr) ) );
- break;
- }
- }
-
- jsfun = (jsval) handler->js_fun_val;
- if (JSVAL_IS_OBJECT(jsfun))
- ret = JS_CallFunctionValue(handler->js_context, wid->obj, (jsval) handler->js_fun_val, 1, argv, &rval);
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_get_param_value)
-{
- GF_Node *n;
- GF_FieldInfo info;
- GF_WidgetPin *param;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !wid->scene || !argc || !JSVAL_IS_OBJECT(argv[0]) ) return JS_FALSE;
-
- param = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- if (!param) return JS_FALSE;
-
- if (!param->node) {
- if (param->default_value) {
- SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->default_value) ) );
- return JS_TRUE;
- }
- return JS_FALSE;
- }
-
- n = gf_sg_find_node_by_name(wid->scene, param->node);
- if (!n) return JS_FALSE;
-
-#ifndef GPAC_DISABLE_SVG
- if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
- if (!strcmp(param->attribute, "textContent")) {
- char *txt = gf_dom_flatten_textContent(n);
- SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, txt ? txt : "") ));
- if (txt) gf_free(txt);
- } else if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
- char *attValue = gf_node_dump_attribute(n, &info);
- SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, attValue) ));
- if (attValue) gf_free(attValue);
- } else {
- return JS_FALSE;
- }
- } else
-#endif
- {
- if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK) return JS_FALSE;
-
- switch (info.fieldType) {
- case GF_SG_VRML_SFSTRING:
- SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, ((SFString*)info.far_ptr)->buffer ) ) );
- break;
- case GF_SG_VRML_SFINT32:
- SMJS_SET_RVAL( INT_TO_JSVAL( *((SFInt32*)info.far_ptr) ));
- break;
- case GF_SG_VRML_SFBOOL:
- SMJS_SET_RVAL(BOOLEAN_TO_JSVAL( *((SFBool*)info.far_ptr) ));
- break;
- case GF_SG_VRML_SFFLOAT:
- SMJS_SET_RVAL( DOUBLE_TO_JSVAL( JS_NewDouble(c, FIX2FLT( *((SFFloat*)info.far_ptr) ) ) ));
- break;
- case GF_SG_VRML_SFTIME:
- SMJS_SET_RVAL( DOUBLE_TO_JSVAL( JS_NewDouble(c, *((SFTime *)info.far_ptr) ) ));
- break;
- }
- }
-
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_get_message_param)
-{
- GF_WidgetPin *par = NULL;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetMessage *msg = (GF_WidgetMessage *)JS_GetPrivate(c, obj);
- if (!msg || !argc ) return JS_FALSE;
-
- if (JSVAL_IS_INT(argv[0])) {
- u32 idx = JSVAL_TO_INT(argv[0]);
- par = gf_list_get(msg->params, idx);
- } else if (JSVAL_IS_STRING(argv[0])) {
- u32 i, count = gf_list_count(msg->params);
- char *name = SMJS_CHARS(c, argv[0]);
- for (i=0; i<count; i++) {
- par = gf_list_get(msg->params, i);
- if (!strcmp(par->name, name)) break;
- par = NULL;
- }
- SMJS_FREE(c, name);
- }
-
- if (par) {
- JSObject *obj = JS_NewObject(c, &msg->ifce->content->widget->wm->widgetAnyClass, 0, 0);
- JS_SetPrivate(c, obj, par);
- JS_DefineProperty(c, obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, par->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, obj, "is_input", BOOLEAN_TO_JSVAL( (par->type == GF_WM_PARAM_OUTPUT) ? JS_FALSE : JS_TRUE), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- switch (par->script_type) {
- case GF_WM_PARAM_SCRIPT_BOOL:
- JS_DefineProperty(c, obj, "script_type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, "boolean") ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- break;
- case GF_WM_PARAM_SCRIPT_NUMBER:
- JS_DefineProperty(c, obj, "script_type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, "number") ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- break;
- case GF_WM_PARAM_SCRIPT_STRING:
- default:
- JS_DefineProperty(c, obj, "script_type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, "string") ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- break;
- }
- SMJS_SET_RVAL( OBJECT_TO_JSVAL(obj) );
- }
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_get_message)
-{
- GF_WidgetMessage *msg;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInterface *ifce = (GF_WidgetInterface*)JS_GetPrivate(c, obj);
- if (!ifce || !argc) return JS_FALSE;
- msg = NULL;
-
- if (JSVAL_IS_INT(argv[0])) {
- u32 idx;
- idx = JSVAL_TO_INT(argv[0]);
- msg = gf_list_get(ifce->messages, idx);
- } else if (JSVAL_IS_STRING(argv[0])) {
- u32 i, count = gf_list_count(ifce->messages);
- char *name = SMJS_CHARS(c, argv[0]);
- for (i=0; i<count; i++) {
- msg = gf_list_get(ifce->messages, i);
- if (!strcmp(msg->name, name)) break;
- msg = NULL;
- }
- SMJS_FREE(c, name);
- }
- if (msg) {
- JSObject *obj = JS_NewObject(c, &ifce->content->widget->wm->widgetAnyClass, 0, 0);
- JS_SetPrivate(c, obj, msg);
- JS_DefineProperty(c, obj, "num_params", INT_TO_JSVAL( gf_list_count(msg->params) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, msg->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, obj, "is_input", BOOLEAN_TO_JSVAL( msg->is_output ? JS_FALSE : JS_TRUE ) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, obj, "has_output_trigger", BOOLEAN_TO_JSVAL( msg->output_trigger ? JS_TRUE : JS_FALSE) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, obj, "has_input_action", BOOLEAN_TO_JSVAL( (msg->input_action && msg->input_action->attribute) ? JS_TRUE : JS_FALSE) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, obj, "has_script_input", BOOLEAN_TO_JSVAL( (msg->input_action && !msg->input_action->attribute) ? JS_TRUE : JS_FALSE) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineFunction(c, obj, "get_param", wm_widget_get_message_param, 1, 0);
-
- SMJS_SET_RVAL( OBJECT_TO_JSVAL(obj) );
- }
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_get_component)
-{
- char *comp_id;
- u32 i, count;
- GF_WidgetComponentInstance *comp_inst;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !argc || !JSVAL_IS_STRING(argv[0]) ) return JS_FALSE;
-
- comp_id = SMJS_CHARS(c, argv[0]);
- count = gf_list_count(wid->components);
- for (i=0; i<count;i++) {
- comp_inst = gf_list_get(wid->components, i);
- if (comp_inst->comp->id && !strcmp(comp_inst->comp->id, comp_id)) {
- SMJS_SET_RVAL( OBJECT_TO_JSVAL(comp_inst->wid->obj) );
- SMJS_FREE(c, comp_id);
- return JS_TRUE;
- }
- }
- /*if requested load the component*/
- if ((argc==2) && JSVAL_IS_BOOLEAN(argv[1]) && (JSVAL_TO_BOOLEAN(argv[1])==JS_TRUE) ) {
- count = gf_list_count(wid->widget->main->components);
- for (i=0; i<count; i++) {
- GF_WidgetComponent *comp = gf_list_get(wid->widget->main->components, i);
- if (!comp->id || strcmp(comp->id, comp_id)) continue;
-
- comp_inst = wm_activate_component(c, wid, comp, 1);
- if (comp_inst) {
- SMJS_SET_RVAL( OBJECT_TO_JSVAL(comp_inst->wid->obj) );
- SMJS_FREE(c, comp_id);
- return JS_TRUE;
- }
- SMJS_FREE(c, comp_id);
- return JS_TRUE;
- }
- }
-
- SMJS_FREE(c, comp_id);
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_get_interface)
-{
- u32 idx;
- GF_WidgetInterface *ifce;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !argc || !JSVAL_IS_INT(argv[0]) ) return JS_FALSE;
-
- idx = JSVAL_TO_INT(argv[0]);
- ifce = gf_list_get(wid->widget->main->interfaces, idx);
-
- if (ifce) {
- if (!ifce->obj) {
- ifce->obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
- JS_SetPrivate(c, ifce->obj, ifce);
- JS_DefineProperty(c, ifce->obj, "num_messages", INT_TO_JSVAL( gf_list_count(ifce->messages) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, ifce->obj, "type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ifce->type) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, ifce->obj, "serviceProvider", BOOLEAN_TO_JSVAL( ifce->provider ? JS_TRUE : JS_FALSE ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, ifce->obj, "multipleBinding", BOOLEAN_TO_JSVAL( ifce->multiple_binding ? JS_TRUE : JS_FALSE ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineFunction(c, ifce->obj, "get_message", wm_widget_get_message, 1, 0);
- gf_js_add_root(c, &ifce->obj, GF_JSGC_OBJECT);
- }
- SMJS_SET_RVAL( OBJECT_TO_JSVAL(ifce->obj) );
- }
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_bind_output_trigger)
-{
- GF_WidgetMessage *msg;
- GF_WidgetPin *param;
- SVG_handlerElement *handler;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !wid->scene || (argc!=3)) return JS_FALSE;
-
- if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
- if (!JSVAL_IS_OBJECT(argv[1])) return JS_FALSE;
- if (!JSVAL_IS_OBJECT(argv[2])) return JS_FALSE;
-
- msg = (GF_WidgetMessage *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]));
- if (!msg) return JS_FALSE;
- param = msg->output_trigger;
- if (!param) return JS_FALSE;
-
-
- handler = wm_create_scene_listener(wid, param);
- if (!handler) return JS_FALSE;
- handler->js_fun_val = argv[1];
- gf_js_add_root(c, &handler->js_fun_val, GF_JSGC_VAL);
- handler->evt_listen_obj = wid;
- handler->js_fun = param;
- handler->js_context = c;
- handler->handle_event = wm_handle_dom_event;
- handler->sgprivate->UserPrivate = JSVAL_TO_OBJECT(argv[2]);
-
- gf_list_add(wid->output_triggers, handler);
-
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_get_context)
-{
- GF_BitStream *bs;
- u32 i, count;
- const char *str;
- char *att;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid) return JS_FALSE;
- if (!wid->scene) {
- SMJS_SET_RVAL(JSVAL_NULL);
- return JS_TRUE;
- }
-
- bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
- str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<contextInformation xmlns=\"urn:mpeg:mpegu:schema:widgets:contextinfo:2010\">\n";
- gf_bs_write_data(bs, (u8 *) str, strlen(str) );
-
- count = gf_list_count(wid->widget->main->preferences);
- for (i=0; i<count; i++) {
- GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i);
-
- /*preference is read only, do not include in context*/
- if (pref->flags & GF_WM_PREF_READONLY) continue;
- /*preference is not migratable, do not include in context*/
- if (!(pref->flags & GF_WM_PREF_MIGRATE)) continue;
-
- str = " <preference name=\"";
- gf_bs_write_data(bs, (u8 *) str, strlen(str) );
-
- gf_bs_write_data(bs, (u8 *) pref->name, strlen(pref->name) );
-
- str = "\" value=\"";
- gf_bs_write_data(bs, (u8 *) str, strlen(str) );
-
- /*read from node*/
- if (pref->connectTo && pref->connectTo->attribute) {
- GF_FieldInfo info;
- GF_Node *n = gf_sg_find_node_by_name(wid->scene, pref->connectTo->node);
- if (n) {
-
-#ifndef GPAC_DISABLE_SVG
- if ((n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) && !strcmp(pref->connectTo->attribute, "textContent")) {
- char *txt = gf_dom_flatten_textContent(n);
- gf_bs_write_data(bs, (u8 *) txt, strlen(txt) );
- } else
-#endif
- if (gf_node_get_field_by_name(n, pref->connectTo->attribute, &info)==GF_OK) {
- att = gf_node_dump_attribute(n, &info);
- if (att) {
- gf_bs_write_data(bs, (u8 *) att, strlen(att) );
- gf_free(att);
- }
- }
- }
- }
- /*read from config*/
- else {
- att = (char *)gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, pref->name);
- if (!att) att = pref->value;
-
- if (att) gf_bs_write_data(bs, (u8 *) att, strlen(att) );
- }
-
- str = "\"/>\n";
- gf_bs_write_data(bs, (u8 *) str, strlen(str) );
- }
- str = "</contextInformation>\n";
- gf_bs_write_data(bs, (u8 *) str, strlen(str) );
-
- gf_bs_write_u8(bs, 0);
- att = NULL;
- gf_bs_get_content(bs, &att, &count);
- gf_bs_del(bs);
-
- SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, att) ) );
- gf_free(att);
-
- return JS_TRUE;
-}
-
-
-static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp)
-{
- JSString *s;
- char *prop_name;
- const char *opt;
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid) return JS_FALSE;
-
- if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
- prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
- if (!prop_name) return JS_FALSE;
-
- /*
- Manifest properties
- */
- if (!strcmp(prop_name, "manifest")) {
- s = JS_NewStringCopyZ(c, wid->widget->manifest_path);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "url")) {
- s = JS_NewStringCopyZ(c, wid->widget->local_path ? wid->widget->local_path : wid->widget->url);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "main")) {
- s = JS_NewStringCopyZ(c, wid->widget->main->relocated_src);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "localizedSrc")) {
- s = JS_NewStringCopyZ(c, wid->widget->main->src);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "mainEncoding")) {
- s = JS_NewStringCopyZ(c, wid->widget->main->encoding);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "mainMimeType")) {
- s = JS_NewStringCopyZ(c, wid->widget->main->mimetype);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "defaultWidth")) {
- *vp = INT_TO_JSVAL(wid->widget->width);
- }
- else if (!strcmp(prop_name, "defaultHeight")) {
- *vp = INT_TO_JSVAL(wid->widget->height);
- }
- else if (!strcmp(prop_name, "icons")) {
- u32 i, count;
- JSObject *arr;
- count = gf_list_count(wid->widget->icons);
- arr = JS_NewArrayObject(c, count, NULL);
- for (i = 0; i<count; i++) {
- GF_WidgetContent *icon = gf_list_get(wid->widget->icons, i);
- if (icon) {
- char *abs_reloc_url;
- jsval icon_obj_val;
- JSObject *icon_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
- JS_SetPrivate(c, icon_obj, icon);
- JS_DefineProperty(c, icon_obj, "src", STRING_TO_JSVAL( JS_NewStringCopyZ(c, icon->src) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- if (strlen(icon->relocated_src)) abs_reloc_url = gf_url_concatenate(wid->widget->url, icon->relocated_src);
- else abs_reloc_url = gf_strdup("");
- JS_DefineProperty(c, icon_obj, "relocated_src", STRING_TO_JSVAL( JS_NewStringCopyZ(c, abs_reloc_url) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, icon_obj, "width", INT_TO_JSVAL( icon->width ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, icon_obj, "height", INT_TO_JSVAL( icon->height ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- icon_obj_val = OBJECT_TO_JSVAL(icon_obj);
- JS_SetElement(c, arr, i, &icon_obj_val);
- gf_free(abs_reloc_url);
- }
- }
- *vp = OBJECT_TO_JSVAL(arr);
- }
- else if (!strcmp(prop_name, "preferences")) {
- u32 i, count;
- JSObject *arr;
- count = gf_list_count(wid->widget->main->preferences);
- arr = JS_NewArrayObject(c, count, NULL);
- for (i = 0; i<count; i++) {
- GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i);
- if (pref) {
- jsval pref_obj_val;
- JSObject *pref_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
- JS_SetPrivate(c, pref_obj, pref);
- JS_DefineProperty(c, pref_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, pref->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, pref_obj, "value", STRING_TO_JSVAL( JS_NewStringCopyZ(c, pref->value) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, pref_obj, "readonly", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ((pref->flags & GF_WM_PREF_READONLY)?"true":"false")) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- pref_obj_val = OBJECT_TO_JSVAL(pref_obj);
- JS_SetElement(c, arr, i, &pref_obj_val);
- }
- }
- *vp = OBJECT_TO_JSVAL(arr);
- }
- else if (!strcmp(prop_name, "features")) {
- u32 i, count;
- JSObject *arr;
- count = gf_list_count(wid->widget->features);
- arr = JS_NewArrayObject(c, count, NULL);
- for (i = 0; i<count; i++) {
- GF_WidgetFeature *feat = gf_list_get(wid->widget->features, i);
- if (feat) {
- jsval feat_obj_val;
- JSObject *feat_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
- JS_SetPrivate(c, feat_obj, feat);
- JS_DefineProperty(c, feat_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, feat->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, feat_obj, "required", BOOLEAN_TO_JSVAL( (feat->required? JS_TRUE : JS_FALSE) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- {
- u32 j, pcount;
- JSObject *params_arr;
- pcount = gf_list_count(feat->params);
- params_arr = JS_NewArrayObject(c, pcount, NULL);
- for (j=0; j < pcount; j++) {
- GF_WidgetFeatureParam *param = gf_list_get(feat->params, j);
- JSObject *param_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
- jsval param_obj_val;
- JS_SetPrivate(c, param_obj, param);
- JS_DefineProperty(c, param_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- JS_DefineProperty(c, param_obj, "value", STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->value) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- param_obj_val = OBJECT_TO_JSVAL(param_obj);
- JS_SetElement(c, params_arr, j, ¶m_obj_val);
- }
- JS_DefineProperty(c, feat_obj, "params", OBJECT_TO_JSVAL(params_arr), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
- }
- feat_obj_val = OBJECT_TO_JSVAL(feat_obj);
- JS_SetElement(c, arr, i, &feat_obj_val);
- }
- }
- *vp = OBJECT_TO_JSVAL(arr);
- }
-
- else if (!strcmp(prop_name, "components")) {
- u32 i, count;
- jsval val;
- JSObject *arr;
- count = gf_list_count(wid->components);
- arr = JS_NewArrayObject(c, count, NULL);
- for (i = 0; i<count; i++) {
- GF_WidgetComponentInstance *comp = gf_list_get(wid->components, i);
- val = OBJECT_TO_JSVAL(comp->wid->obj);
- JS_SetElement(c, arr, i, &val);
- }
- *vp = OBJECT_TO_JSVAL(arr);
- }
- else if (!strcmp(prop_name, "identifier")) {
- s = JS_NewStringCopyZ(c, wid->widget->identifier);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "name")) {
- s = JS_NewStringCopyZ(c, wid->widget->name);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "shortName")) {
- s = JS_NewStringCopyZ(c, wid->widget->shortname);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "authorName")) {
- s = JS_NewStringCopyZ(c, wid->widget->authorName);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "authorEmail")) {
- s = JS_NewStringCopyZ(c, wid->widget->authorEmail);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "authorHref")) {
- s = JS_NewStringCopyZ(c, wid->widget->authorHref);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "description")) {
- s = JS_NewStringCopyZ(c, wid->widget->description);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "viewmodes")) {
- if (wid->widget->viewmodes) s = JS_NewStringCopyZ(c, wid->widget->viewmodes);
- else s = JS_NewStringCopyZ(c, "");
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "license")) {
- s = JS_NewStringCopyZ(c, wid->widget->license);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "licenseHref")) {
- s = JS_NewStringCopyZ(c, wid->widget->licenseHref);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "version")) {
- s = JS_NewStringCopyZ(c, wid->widget->version);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "uuid")) {
- s = JS_NewStringCopyZ(c, wid->widget->uuid);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "discardable")) {
- *vp = BOOLEAN_TO_JSVAL( wid->widget->discardable ? JS_TRUE : JS_FALSE);
- }
- else if (!strcmp(prop_name, "multipleInstances")) {
- *vp = BOOLEAN_TO_JSVAL( wid->widget->multipleInstance ? JS_TRUE : JS_FALSE);
- }
-
- /*
- Widget Manager special properties (common to all implementations)
- */
- else if (!strcmp(prop_name, "permanent")) {
- *vp = BOOLEAN_TO_JSVAL( wid->permanent ? JS_TRUE : JS_FALSE);
- }
- else if (!strcmp(prop_name, "is_component")) {
- *vp = BOOLEAN_TO_JSVAL( wid->parent ? JS_TRUE : JS_FALSE);
- }
- else if (!strcmp(prop_name, "parent")) {
- *vp = wid->parent ? OBJECT_TO_JSVAL(wid->parent->obj) : JSVAL_NULL;
- }
- else if (!strcmp(prop_name, "activated")) {
- *vp = BOOLEAN_TO_JSVAL( wid->activated ? JS_TRUE : JS_FALSE);
- }
- else if (!strcmp(prop_name, "section")) {
- s = JS_NewStringCopyZ(c, wid->secname);
- *vp = STRING_TO_JSVAL(s);
- }
- else if (!strcmp(prop_name, "num_instances")) {
- *vp = INT_TO_JSVAL( wid->widget->nb_instances);
- }
- else if (!strcmp(prop_name, "num_interfaces")) {
- *vp = INT_TO_JSVAL( gf_list_count(wid->widget->main->interfaces));
- }
- else if (!strcmp(prop_name, "num_components")) {
- *vp = INT_TO_JSVAL( gf_list_count(wid->components));
- }
- else if (!strcmp(prop_name, "num_bound_interfaces")) {
- *vp = INT_TO_JSVAL( gf_list_count(wid->bound_ifces));
- }
- /*all variables used by the WidgetManager script but not stored*/
- else if (!strcmp(prop_name, "originating_device_ip")
- || !strcmp(prop_name, "originating_device")
- || !strcmp(prop_name, "device")
- ) {
- }
- /*
- Widget properties, common to each implementation
- */
- else {
- char szName[1024];
- sprintf(szName, "WM:%s", prop_name);
- opt = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, szName);
- if (opt) {
- Double val=0;
- if (!strcmp(opt, "true")) *vp = BOOLEAN_TO_JSVAL(JS_TRUE);
- else if (!strcmp(opt, "false")) *vp = BOOLEAN_TO_JSVAL(JS_FALSE);
- else if (sscanf(opt, "%lf", &val)==1) {
- *vp = DOUBLE_TO_JSVAL( JS_NewDouble(c, val) );
- } else {
- s = JS_NewStringCopyZ(c, opt);
- *vp = STRING_TO_JSVAL(s);
- }
- }
- }
- SMJS_FREE(c, prop_name);
- return JS_TRUE;
-}
-static JSBool wm_widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp)
-{
- char szVal[32];
- jsdouble val;
- char *prop_name;
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid) return JS_FALSE;
-
- if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
- prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
-
- /*internal to WidgetManager, never stored*/
- if (!strcmp(prop_name, "permanent")) {
- wid->permanent = (JSVAL_TO_BOOLEAN(*vp)==JS_TRUE) ? 1 : 0;
- }
-
- /*any widget properties*/
- else {
- char szName[1024], *value, *_val = NULL;
-
- if (JSVAL_IS_STRING(*vp)) {
- value = _val = SMJS_CHARS(c, *vp);
- if (!value) value = "";
- }
- else if (JSVAL_IS_BOOLEAN(*vp)) {
- strcpy(szVal, (JSVAL_TO_BOOLEAN(*vp)==JS_TRUE) ? "true" : "false");
- value = szVal;
- }
- else if (JSVAL_IS_NUMBER(*vp)) {
- JS_ValueToNumber(c, *vp, &val);
- sprintf(szVal, "%f", val);
- value = szVal;
- } else {
- SMJS_FREE(c, prop_name);
- return JS_TRUE;
- }
-
- sprintf(szName, "WM:%s", prop_name);
- gf_cfg_set_key(wid->widget->wm->term->user->config, wid->secname, szName, value);
- SMJS_FREE(c, _val);
- }
-
- SMJS_FREE(c, prop_name);
- return JS_TRUE;
-}
-
-
-
-static JSBool wm_widget_bind_interface_ex(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, Bool is_unbind)
-{
- u32 i, count;
- GF_WidgetInterfaceInstance *bifce;
- GF_WidgetInterface *ifce;
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !wid->scene) return JS_FALSE;
-
- ifce = NULL;
- if (argc) {
- if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
- ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- if (!ifce) return JS_FALSE;
- }
-
- if (!is_unbind) {
- char *hostname;
- JSObject *cookie;
- if ((argc<3) || !JSVAL_IS_OBJECT(argv[1]) || !JSVAL_IS_STRING(argv[2])) return JS_FALSE;
-
- cookie = JSVAL_TO_OBJECT(argv[1]);
- hostname = SMJS_CHARS(c, argv[2]);
- count = gf_list_count(wid->bound_ifces);
- for (i=0; i<count; i++) {
- bifce = gf_list_get(wid->bound_ifces, i);
- if (!strcmp(bifce->ifce->type, ifce->type) && (bifce->cookie==cookie) ) {
- SMJS_FREE(c, hostname);
- return JS_TRUE;
- }
- }
- GF_SAFEALLOC(bifce, GF_WidgetInterfaceInstance);
- bifce->wid = wid;
- bifce->ifce = ifce;
- bifce->cookie = cookie;
- bifce->hostname = gf_strdup(hostname);
- SMJS_FREE(c, hostname);
- gf_list_add(wid->bound_ifces, bifce);
-
- if (ifce->bind_action) {
- return wm_widget_set_scene_input_value(c, obj, 1, argv, rval, 2, NULL, NULL, NULL);
- } else {
- widget_on_interface_bind(bifce, 0);
- }
- } else {
- JSObject *cookie = NULL;
- if ((argc==2) && JSVAL_IS_OBJECT(argv[1])) cookie = JSVAL_TO_OBJECT(argv[1]);
-
- count = gf_list_count(wid->bound_ifces);
- for (i=0; i<count; i++) {
- bifce = gf_list_get(wid->bound_ifces, i);
- if (!ifce || ( !strcmp(bifce->ifce->type, ifce->type) && (bifce->cookie==cookie)) ) {
- gf_list_rem(wid->bound_ifces, i);
- if (bifce->ifce->unbind_action) {
- wm_widget_set_scene_input_value(c, NULL, 0, NULL, rval, 3, wid, bifce->ifce->unbind_action, NULL);
- } else {
- widget_on_interface_bind(bifce, 1);
- }
- if (ifce) {
- /*unregister our message handlers*/
- count = gf_list_count(wid->output_triggers);
- for (i=0; i<count; i++) {
- u32 j, c2, found;
- GF_DOMHandler *handler = gf_list_get(wid->output_triggers, i);
- GF_WidgetPin *param = handler->js_fun;
-
- if (handler->sgprivate->UserPrivate != cookie) continue;
- found = 0;
- c2 = gf_list_count(bifce->ifce->messages);
- for (j=0; j<c2; j++) {
- GF_WidgetMessage *msg = gf_list_get(bifce->ifce->messages, j);
- if (msg->output_trigger == param) {
- found = 1;
- break;
- }
- }
- if (found) {
- GF_Node *listener = handler->sgprivate->parents->node;
- gf_dom_listener_del(listener, listener->sgprivate->UserPrivate);
- gf_list_rem(wid->output_triggers, i);
- i--;
- count--;
- }
- }
- }
- wm_delete_interface_instance(wid->widget->wm, bifce);
- if (ifce) return JS_TRUE;
- i--;
- count--;
- }
- }
- }
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_bind_interface)
-{
- SMJS_OBJ
- SMJS_ARGS
- SMJS_DECL_RVAL
- return wm_widget_bind_interface_ex(c, obj, argc, argv, rval, 0);
-}
-static JSBool SMJS_FUNCTION(wm_widget_unbind_interface)
-{
- SMJS_OBJ
- SMJS_ARGS
- SMJS_DECL_RVAL
- return wm_widget_bind_interface_ex(c, obj, argc, argv, rval, 1);
-}
-
-
-static JSBool SMJS_FUNCTION(wm_widget_deactivate)
-{
- u32 i, count;
- jsval funval;
- SMJS_OBJ
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid) return JS_FALSE;
-
- /*widget is a component of another widget, unregister*/
- if (wid->parent) {
- GF_WidgetInstance *par_wid = wid->parent;
- count = gf_list_count(par_wid->components);
- for (i=0; i<count; i++) {
- GF_WidgetComponentInstance *comp = gf_list_get(par_wid->components, i);
- if (comp->wid == wid) {
- gf_list_rem(par_wid->components, i);
- gf_free(comp);
- break;
- }
- }
- wid->parent = NULL;
- }
-
- /*remove all components*/
- while (gf_list_count(wid->components)) {
- GF_WidgetComponentInstance *comp = gf_list_get(wid->components, 0);
- wm_deactivate_component(c, wid, NULL, comp);
- gf_list_rem(wid->components, 0);
- }
-
- /*mark the widget as deactivated, so it is no longer valid when checking all widgets bindings*/
- wid->activated = 0;
-
- /*unbind existing widgets*/
- JS_LookupProperty(wid->widget->wm->ctx, wid->widget->wm->obj, "unbind_widget", &funval);
- if (JSVAL_IS_OBJECT(funval)) {
- jsval an_argv[1];
- an_argv[0] = OBJECT_TO_JSVAL(obj);
- JS_CallFunctionValue(wid->widget->wm->ctx, wid->widget->wm->obj, funval, 1, an_argv, SMJS_GET_RVAL );
- }
-
- /*unbind all interfaces of this widget*/
- wm_widget_bind_interface_ex(c, obj, 0, NULL, SMJS_GET_RVAL, 1);
-
- /*detach scene now that all unbind events have been sent*/
- wid->scene = NULL;
- return JS_TRUE;
-}
-
-
-static void wm_widget_jsbind(GF_WidgetManager *wm, GF_WidgetInstance *wid)
-{
- if (wid->obj)
- return;
- wid->obj = JS_NewObject(wm->ctx, &wm->wmWidgetClass, 0, 0);
- JS_SetPrivate(wm->ctx, wid->obj, wid);
- /*protect from GC*/
- gf_js_add_root(wm->ctx, &wid->obj, GF_JSGC_OBJECT);
-}
-
-void wm_deactivate_component(JSContext *c, GF_WidgetInstance *wid, GF_WidgetComponent *comp, GF_WidgetComponentInstance *comp_inst)
-{
- jsval fval, rval;
-
- if (!comp_inst) {
- u32 i=0;
- while ((comp_inst = gf_list_enum(wid->components, &i))) {
- if (comp_inst->comp == comp) break;
- comp_inst = NULL;
- }
- }
- if (!comp_inst) return;
-
- if ((JS_LookupProperty(c, wid->widget->wm->obj, "on_widget_remove", &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
- jsval argv[1];
- argv[0] = OBJECT_TO_JSVAL(comp_inst->wid->obj);
- JS_CallFunctionValue(wid->widget->wm->ctx, wid->obj, fval, 1, argv, &rval);
- }
-}
-
-GF_WidgetComponentInstance *wm_activate_component(JSContext *c, GF_WidgetInstance *wid, GF_WidgetComponent *comp, Bool skip_wm_notification)
-{
- u32 i, count;
- const char *fun_name = NULL;
- jsval fval, rval;
- GF_WidgetComponentInstance *comp_inst;
- GF_WidgetInstance *comp_wid;
-
- comp_wid = NULL;
- if (comp->src) {
- char *url = gf_url_concatenate(wid->widget->url, comp->src);
-
- count = gf_list_count(wid->widget->wm->widget_instances);
- for (i=0; i<count; i++) {
- comp_wid = gf_list_get(wid->widget->wm->widget_instances, i);
- if (!strcmp(comp_wid->widget->url, url) && !comp_wid->parent) break;
- comp_wid = NULL;
- }
- if (!comp_wid) {
- comp_wid = wm_load_widget(wid->widget->wm, url, 0);
- if (comp_wid) comp_wid->permanent = 0;
- }
- gf_free(url);
- }
- if (!comp_wid) return NULL;
-
- if (!comp_wid->activated)
- fun_name = "on_widget_add";
-
- GF_SAFEALLOC(comp_inst, GF_WidgetComponentInstance);
- comp_inst->comp = comp;
- comp_inst->wid = comp_wid;
- comp_wid->parent = wid;
-
- gf_list_add(wid->components, comp_inst);
-
- if (!comp_inst->wid->obj) wm_widget_jsbind(wid->widget->wm, comp_inst->wid);
-
- if (!skip_wm_notification && fun_name && (JS_LookupProperty(c, wid->widget->wm->obj, fun_name, &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
- jsval argv[1];
- argv[0] = OBJECT_TO_JSVAL(comp_inst->wid->obj);
- JS_CallFunctionValue(wid->widget->wm->ctx, wid->obj, fval, 1, argv, &rval);
- }
- if (comp_inst) return comp_inst;
- return NULL;
-}
-
-static JSBool SMJS_FUNCTION(wm_widget_is_interface_bound)
-{
- u32 i, count;
- Bool check_fake_bind = 0;
- JSObject *cookie;
- GF_WidgetInterface *ifce;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
- if (!wid || !wid->scene || (argc<1) || !JSVAL_IS_OBJECT(argv[0]) ) return JS_FALSE;
-
- ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- if (!ifce) return JS_FALSE;
- cookie = NULL;
- if ((argc==2) && JSVAL_IS_OBJECT(argv[1]) )
- cookie = JSVAL_TO_OBJECT(argv[1]);
-
- if ((argc==3) && JSVAL_IS_BOOLEAN(argv[2]) )
- check_fake_bind = JSVAL_TO_BOOLEAN(argv[2])==JS_TRUE ? 1 : 0;
-
-
- SMJS_SET_RVAL(BOOLEAN_TO_JSVAL(JS_FALSE));
- count = gf_list_count(wid->bound_ifces);
- for (i=0; i<count; i++) {
- GF_WidgetInterfaceInstance *bifce = gf_list_get(wid->bound_ifces, i);
- if (!strcmp(bifce->ifce->type, ifce->type) && (!cookie || (bifce->cookie==cookie))) {
- SMJS_SET_RVAL( BOOLEAN_TO_JSVAL(JS_TRUE) );
- break;
- }
- }
- return JS_TRUE;
-}
-
-
-static JSBool SMJS_FUNCTION(wm_load)
-{
- u32 i, count;
- char *manifest;
- GF_WidgetInstance *wid;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
- if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
-
- manifest = SMJS_CHARS(c, argv[0]);
-
- wid=NULL;
- count = gf_list_count(wm->widget_instances);
- for (i=0; i<count; i++) {
- wid = gf_list_get(wm->widget_instances, i);
- if (!strcmp(wid->widget->url, manifest) && !wid->activated) break;
- wid = NULL;
- }
- if (!wid) {
- wid = wm_load_widget(wm, manifest, 0);
- }
- if (wid) {
- wm_widget_jsbind(wm, wid);
- SMJS_SET_RVAL(OBJECT_TO_JSVAL(wid->obj));
- }
- SMJS_FREE(c, manifest);
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_unload)
-{
- GF_WidgetInstance *wid;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
- if (!argc || !JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
-
- if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &wm->wmWidgetClass, NULL) ) return JS_FALSE;
- wid = (GF_WidgetInstance *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
- if (!wid) return JS_TRUE;
-
- /*unless explecetely requested, remove the section*/
- if ((argc!=2) || !JSVAL_IS_BOOLEAN(argv[1]) || (JSVAL_TO_BOOLEAN(argv[1])==JS_TRUE) ) {
- /*create section*/
- gf_cfg_del_section(wm->term->user->config, wid->secname);
- gf_cfg_set_key(wm->term->user->config, "Widgets", wid->secname, NULL);
- }
- wm_delete_widget_instance(wm, wid);
- return JS_TRUE;
-}
-
-
-
-static JSBool wm_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp)
-{
- char *prop_name;
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
- if (!wm) return JS_FALSE;
-
- if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
- prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
- if (!prop_name) return JS_FALSE;
-
- if (!strcmp(prop_name, "num_widgets")) {
- *vp = INT_TO_JSVAL(gf_list_count(wm->widget_instances));
- }
- else if (!strcmp(prop_name, "last_widget_dir")) {
- const char *opt = gf_cfg_get_key(wm->term->user->config, "Widgets", "last_widget_dir");
- if (!opt) opt = "/";
- *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(c, opt));
- }
- SMJS_FREE(c, prop_name);
- return JS_TRUE;
-}
-static JSBool wm_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp)
-{
- char *prop_name;
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
- if (!wm) return JS_FALSE;
-
- if (!JSVAL_IS_STRING(*vp)) return JS_TRUE;
- if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
- prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
-
- if (!strcmp(prop_name, "last_widget_dir")) {
- char *v = SMJS_CHARS(c, *vp);
- gf_cfg_set_key(wm->term->user->config, "Widgets", "last_widget_dir", v);
- SMJS_FREE(c, v);
- }
- SMJS_FREE(c, prop_name);
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_get)
-{
- u32 i;
- GF_WidgetInstance *wid;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
- if (!argc || !JSVAL_IS_INT(argv[0])) return JS_TRUE;
-
- i = JSVAL_TO_INT(argv[0]);
- wid = gf_list_get(wm->widget_instances, i);
- if (wid) SMJS_SET_RVAL( OBJECT_TO_JSVAL(wid->obj) );
- return JS_TRUE;
-}
-
-static JSBool SMJS_FUNCTION(wm_find_interface)
-{
- char *ifce_name;
- u32 i;
- GF_WidgetInstance *wid;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
- if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
-
- ifce_name = SMJS_CHARS(c, argv[0]);
- i=0;
- while ( (wid = gf_list_enum(wm->widget_instances, &i) )) {
- u32 j=0;
- GF_WidgetInterface *wid_ifce;
- while ((wid_ifce = gf_list_enum(wid->widget->main->interfaces, &j))) {
- if (!strcmp(wid_ifce->type, ifce_name)) {
- SMJS_SET_RVAL( OBJECT_TO_JSVAL(wid->obj) );
- SMJS_FREE(c, ifce_name);
- return JS_TRUE;
- }
- }
- }
- SMJS_FREE(c, ifce_name);
- return JS_TRUE;
-}
-
-
-const char *wm_xml_get_attr(GF_XMLNode *root, const char *name)
-{
-
- u32 i, count;
- count = gf_list_count(root->attributes);
- for (i=0; i<count; i++) {
- char *sep;
- GF_XMLAttribute *att = gf_list_get(root->attributes, i);
- if (!att->name) continue;
- if (!strcmp(att->name, name)) return att->value;
- sep = strchr(att->name, ':');
- if (sep && !strcmp(sep+1, name)) return att->value;
- }
- return NULL;
-}
-
-/* TODO Implement real language check according to BCP 47*/
-static Bool wm_check_language(const char *xml_lang_value, const char *user_locale)
-{
- Bool ret = 0;
- char *sep, *val;
- val = (char*)xml_lang_value;
- while (!ret) {
- sep = strchr(val, ';');
- if (sep) sep[0] = 0;
- if (strstr(user_locale, val)) ret = 1;
- if (sep) {
- sep[0] = ';';
- val = sep+1;
- } else {
- break;
- }
- }
- return ret;
-}
-
-static GF_XMLNode *wm_xml_find(GF_XMLNode *root, const char *ns_prefix, const char *name, const char *user_locale)
-{
- GF_XMLNode *localized = NULL;
- GF_XMLNode *non_localized = NULL;
- u32 i, count;
-
- if (!root) return NULL;
-
- count = gf_list_count(root->content);
- for (i=0; i<count; i++) {
- GF_XMLNode *n = gf_list_get(root->content, i);
- if (n->type==GF_XML_NODE_TYPE && n->name && !strcmp(n->name, name) && ((!ns_prefix && !n->ns) || (ns_prefix && n->ns && !strcmp(ns_prefix, n->ns)))) {
- const char *lang = wm_xml_get_attr(n, "xml:lang");
- if (!lang) {
- if (!non_localized) non_localized = n;
- } else {
- if (user_locale && wm_check_language(lang, user_locale) && !localized) localized = n;
- }
- }
- }
- if (localized) return localized;
- else return non_localized;
-}
-
-static GF_WidgetPin *wm_parse_pin(const char *value, u16 type, const char *pin_name, const char *scriptType, const char *default_value)
-{
- GF_WidgetPin *pin;
- char *sep;
-
- if (!value && !scriptType && !default_value) return NULL;
-
- GF_SAFEALLOC(pin, GF_WidgetPin);
- pin->type = type;
- if (pin_name) pin->name = gf_strdup(pin_name);
-
- if (value) {
- sep = strrchr(value, '.');
- if (!sep && (type==GF_WM_PREF_CONNECT)) {
- gf_free(pin);
- return NULL;
- }
-
- /*node.event || node.attribute*/
- if (sep) {
- sep[0] = 0;
- pin->node = gf_strdup(value);
- pin->attribute = gf_strdup(sep+1);
- sep[0] = '.';
- }
- /*script function*/
- else {
- pin->node = gf_strdup(value);
- }
- }
-
- if (scriptType) {
- if (!strcmp(scriptType, "boolean")) pin->script_type = GF_WM_PARAM_SCRIPT_BOOL;
- else if (!strcmp(scriptType, "number")) pin->script_type = GF_WM_PARAM_SCRIPT_NUMBER;
- } else if (default_value) {
- pin->default_value = gf_strdup(default_value);
- }
- return pin;
-}
-
-static void wm_parse_mpegu_content_element(GF_WidgetContent *content, GF_XMLNode *root, const char *ns_prefix, GF_List *global_prefs)
-{
- GF_XMLNode *ifces, *context, *pref_node;
- GF_WidgetMessage *msg;
- GF_WidgetInterface *ifce;
- GF_XMLNode *ifce_node;
- GF_WidgetPreference *pref;
- const char *att;
- u32 i = 0;
-
- ifces = wm_xml_find(root, ns_prefix, "interfaces", NULL);
- if (ifces) {
-
- /*get all interface element*/
- while ((ifce_node = gf_list_enum(ifces->content, &i))) {
- GF_XMLNode *msg_node;
- u32 j;
- const char *ifce_type, *act;
- if (ifce_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(ifce_node->name, "interface")) continue;
- ifce_type = wm_xml_get_attr(ifce_node, "type");
- if (!ifce_type) continue;
-
- GF_SAFEALLOC(ifce, GF_WidgetInterface);
- ifce->type = gf_strdup(ifce_type);
- ifce->messages = gf_list_new();
- ifce->content = content;
- gf_list_add(content->interfaces, ifce);
-
- act = wm_xml_get_attr(ifce_node, "serviceProvider");
- if (act && !strcmp(act, "true")) ifce->provider = 1;
-
- act = wm_xml_get_attr(ifce_node, "multipleBindings");
- if (act && !strcmp(act, "true")) ifce->multiple_binding = 1;
-
- act = wm_xml_get_attr(ifce_node, "required");
- if (act && !strcmp(act, "true")) ifce->required = 1;
-
- act = wm_xml_get_attr(ifce_node, "connectTo");
- if (act) ifce->connectTo = gf_strdup(act);
-
- act = wm_xml_get_attr(ifce_node, "bindAction");
- if (act) {
- ifce->bind_action = wm_parse_pin(act, GF_WM_BIND_ACTION, NULL, NULL, NULL);
- }
- act = wm_xml_get_attr(ifce_node, "unbindAction");
- if (act) {
- ifce->unbind_action = wm_parse_pin(act, GF_WM_UNBIND_ACTION, NULL, NULL, NULL);
- }
-
- j=0;
- while ((msg_node = gf_list_enum(ifce_node->content, &j))) {
- u32 k;
- GF_XMLNode *par_node;
- const char *msg_name, *action;
- if (msg_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(msg_node->name, "messageIn") && strcmp(msg_node->name, "messageOut")) continue;
-
- msg_name = wm_xml_get_attr(msg_node, "name");
- if (!msg_name) continue;
- GF_SAFEALLOC(msg, GF_WidgetMessage);
- msg->name = gf_strdup(msg_name);
- msg->params = gf_list_new();
- msg->ifce = ifce;
- if (!strcmp(msg_node->name, "messageOut")) msg->is_output = 1;
-
- gf_list_add(ifce->messages, msg);
-
- /*get inputAction*/
- action = wm_xml_get_attr(msg_node, "inputAction");
- if (action) {
- msg->input_action = wm_parse_pin(action, GF_WM_INPUT_ACTION, NULL, NULL, NULL);
- }
-
- /*get outputTrigger*/
- action = wm_xml_get_attr(msg_node, "outputTrigger");
- if (action) {
- msg->output_trigger = wm_parse_pin(action, GF_WM_OUTPUT_TRIGGER, NULL, NULL, NULL);
- }
-
- /*get params*/
- k=0;
- while ((par_node=gf_list_enum(msg_node->content, &k))) {
- GF_WidgetPin *wpin;
- u16 type;
- const char *par_name, *att_name;
- if (par_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(par_node->name, "input") && strcmp(par_node->name, "output")) continue;
-
-
- par_name = wm_xml_get_attr(par_node, "name");
- /*invalid param, discard message*/
- if (!par_name) {
- gf_list_del_item(ifce->messages, msg);
- gf_list_del(msg->params);
- gf_free(msg->name);
- gf_free(msg);
- break;
- }
-
- if (!strcmp(par_node->name, "output")) {
- type = GF_WM_PARAM_OUTPUT;
- att_name = wm_xml_get_attr(par_node, "attributeModified");
- } else {
- type = GF_WM_PARAM_INPUT;
- att_name = wm_xml_get_attr(par_node, "setAttribute");
- }
- wpin = wm_parse_pin(att_name, type, par_name, wm_xml_get_attr(par_node, "scriptParamType"), wm_xml_get_attr(par_node, "default"));
- if (!wpin) continue;
- wpin->msg = msg;
-
- gf_list_add(msg->params, wpin);
- }
- }
- }
- }
-
- /*get all component elements*/
- i=0;
- while (root && (ifce_node = gf_list_enum(root->content, &i))) {
- GF_XMLNode *req_node;
- u32 j;
- const char *src, *id, *act;
- GF_WidgetComponent *comp;
- if (ifce_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(ifce_node->name, "component")) continue;
- src = wm_xml_get_attr(ifce_node, "src");
- id = wm_xml_get_attr(ifce_node, "id");
-
- GF_SAFEALLOC(comp, GF_WidgetComponent);
- comp->required_interfaces = gf_list_new();
- comp->content = content;
- if (id) comp->id = gf_strdup(id);
- if (src) comp->src = gf_strdup(src);
- j=0;
- while ((req_node=gf_list_enum(ifce_node->content, &j))) {
- const char *ifce_type;
- if (req_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(req_node->name, "requiredInterface")) continue;
- ifce_type = wm_xml_get_attr(req_node, "type");
- if (!ifce_type) continue;
- gf_list_add(comp->required_interfaces, gf_strdup(ifce_type));
- }
-
- act = wm_xml_get_attr(ifce_node, "activateTrigger");
- if (act) comp->activateTrigger = wm_parse_pin(act, GF_WM_ACTIVATE_TRIGGER, NULL, NULL, NULL);
- act = wm_xml_get_attr(ifce_node, "deactivateTrigger");
- if (act) comp->deactivateTrigger = wm_parse_pin(act, GF_WM_DEACTIVATE_TRIGGER, NULL, NULL, NULL);
-
- gf_list_add(content->components, comp);
- }
-
- /*clone global prefs for this content*/
- i=0;
- while ((pref = gf_list_enum(global_prefs, &i))) {
- GF_WidgetPreference *apref;
- GF_SAFEALLOC(apref, GF_WidgetPreference);
- apref->name = gf_strdup(pref->name);
- if (pref->value) apref->value = gf_strdup(pref->value);
- apref->flags = pref->flags;
- gf_list_add(content->preferences, apref);
- }
-
- context = wm_xml_find(root, ns_prefix, "contextConfiguration", NULL);
- if (context) {
- u32 j;
- /*get all preference elements*/
- i=0;
- while ((pref_node = gf_list_enum(context->content, &i))) {
- const char *att;
- if (pref_node->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(pref_node->name, "preferenceConnect")) continue;
- att = wm_xml_get_attr(pref_node, "name");
- if (!att) continue;
-
- j=0;
- while ((pref = gf_list_enum(content->preferences, &j))) {
- if (!strcmp(pref->name, att) && !pref->connectTo) break;
- }
-
- if (!pref) {
- GF_SAFEALLOC(pref, GF_WidgetPreference);
- pref->name = gf_strdup(att);
- gf_list_add(content->preferences, pref);
- }
- att = wm_xml_get_attr(pref_node, "value");
- if (att) {
- if (pref->value) gf_free(pref->value);
- pref->value = gf_strdup(att);
- }
- att = wm_xml_get_attr(pref_node, "readOnly");
- if (att && !strcmp(att, "true")) pref->flags |= GF_WM_PREF_READONLY;
- att = wm_xml_get_attr(pref_node, "migratable");
- if (att && !strcmp(att, "saveOnly")) pref->flags |= GF_WM_PREF_SAVE;
- else if (att && !strcmp(att, "migrateOnly")) pref->flags |= GF_WM_PREF_MIGRATE;
- else pref->flags |= GF_WM_PREF_SAVE | GF_WM_PREF_MIGRATE;
-
- att = wm_xml_get_attr(pref_node, "connectTo");
- if (att) pref->connectTo = wm_parse_pin(att, GF_WM_PREF_CONNECT, NULL, NULL, NULL);
- }
-
- att = wm_xml_get_attr(context, "savedAction");
- if (att) content->savedAction = wm_parse_pin(att, GF_WM_PREF_SAVEDACTION, NULL, NULL, NULL);
- att = wm_xml_get_attr(context, "restoredAction");
- if (att) content->restoredAction = wm_parse_pin(att, GF_WM_PREF_RESTOREDACTION, NULL, NULL, NULL);
- att = wm_xml_get_attr(context, "saveTrigger");
- if (att) content->saveTrigger = wm_parse_pin(att, GF_WM_PREF_SAVETRIGGER, NULL, NULL, NULL);
- att = wm_xml_get_attr(context, "restoreTrigger");
- if (att) content->restoreTrigger = wm_parse_pin(att, GF_WM_PREF_RESTORETRIGGER, NULL, NULL, NULL);
- }
-}
-
-/* Implements the W3C P&C rule for getting a single attribute value
- see http://www.w3.org/TR/widgets/#rule-for-getting-a-single-attribute-valu0
- should be different from getting normalized text but for now it's ok
- */
-static char *wm_get_single_attribute(const char *input) {
- u32 i, j, len;
- char *output;
- Bool first_space_copied;
-
- if (!input) return gf_strdup("");
-
- len = strlen(input);
- output = gf_malloc(len+1);
-
- first_space_copied = 1;
- j = 0;
- for (i = 0; i<len; i++) {
- switch (input[i]) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- if (!first_space_copied) {
- output[j] = ' ';
- j++;
- first_space_copied = 1;
- }
- break;
- default:
- output[j] = input[i];
- j++;
- first_space_copied = 0;
- }
- }
- if (j && output[j-1] == ' ') output[j-1] = 0;
- output[j] = 0;
- return output;
-}
-
-/* Implements the W3C P&C rule for getting a single attribute value
- see http://www.w3.org/TR/widgets/#rule-for-getting-a-single-attribute-valu0 */
-static u32 wm_parse_non_neg(const char *input) {
- u32 result = 0;
- if (strlen(input) && !strchr(input, '-')) {
- if (sscanf(input, "%u", &result) != 1) result = 0;
- }
- return result;
-}
-
-/* returns the localized concatenated text content
-see http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent
-and http://www.w3.org/TR/widgets/#rule-for-getting-text-content0
-*/
-static char *wm_get_text_content(GF_XMLNode *node, char *inherited_locale, const char *user_locale) {
- if (node->type == GF_XML_TEXT_TYPE) {
- if (node->name) return gf_strdup(node->name);
- else return gf_strdup("");
- } else {
- char *xml_lang = (char *)wm_xml_get_attr(node, "xml:lang");
- if (!xml_lang) xml_lang = inherited_locale;
- /*
- if (xml_lang && user_locale && wm_check_language(xml_lang, user_locale))
- */
- {
- u32 i, count;
- char *text_content;
- u32 text_content_len = 0;
- text_content = gf_strdup("");
- count = gf_list_count(node->content);
- for (i=0; i<count; i++) {
- GF_XMLNode *child = (GF_XMLNode *)gf_list_get(node->content, i);
- char *child_content = wm_get_text_content(child, xml_lang, user_locale);
- u32 child_content_len = strlen(child_content);
- text_content = gf_realloc(text_content, text_content_len+child_content_len+1);
- memcpy(text_content+text_content_len, child_content, child_content_len);
- text_content[text_content_len+child_content_len] = 0;
- text_content_len+=child_content_len;
- gf_free(child_content);
- }
- return text_content;
- }
- /*
- } else {
- return gf_strdup("");
- */
- }
-}
-
-static char *wm_get_normalized_text_content(GF_XMLNode *node, char *inherited_locale, const char *user_locale) {
- char *text_content, *result;
- /* first aggregate text content */
- text_content = wm_get_text_content(node, inherited_locale, user_locale);
- /* calling normalization of text content */
- result = wm_get_single_attribute(text_content);
- gf_free(text_content);
- return result;
-}
-
-/* When relocating resources over HTTP, we check if the resources for a given locale exists
- on the server by sending a HEAD message with an Accept-Language header. */
-void wm_relocate_proc(void *usr_cbk, GF_NETIO_Parameter *parameter)
-{
- switch (parameter->msg_type) {
- case GF_NETIO_GET_METHOD:
- parameter->name = "HEAD";
- break;
- }
-}
-
-/* relocate the given resource name (res_name) using registered relocators (e.g. locales, package folder)
- The result is the path of the file, possibly uncompressed, possibly localized.
- The parameter widget_path provides the path for converting relative resource paths into absolute paths.*/
-static Bool wm_relocate_url(GF_WidgetManager *wm, const char *widget_path, const char *res_name, char *relocated_name, char *localized_res_name)
-{
- Bool ok = 0;
- char *res_url;
- Bool result = gf_term_relocate_url(wm->term, res_name, widget_path, relocated_name, localized_res_name);
- if (result) return result;
-
- res_url = gf_url_concatenate(widget_path, res_name);
-
- /*try with HTTP HEAD */
- if (!strnicmp(widget_path, "http", 4)) {
- GF_Err e;
- /*fetch the remote widget manifest synchronously and load it */
- GF_DownloadSession *sess = gf_dm_sess_new(wm->term->downloader, (char *)res_url, GF_NETIO_SESSION_NOT_THREADED, wm_relocate_proc, NULL, &e);
- if (sess) {
- e = gf_dm_sess_process(sess);
- gf_dm_sess_del(sess);
- if (e==GF_OK) {
- const char *opt = gf_cfg_get_key(wm->term->user->config, "Systems", "Language2CC");
- strcpy(relocated_name, res_url);
- if (opt)
- sprintf(localized_res_name, "%s/%s", opt, res_name);
- else
- strcpy(localized_res_name, res_name);
- ok = 1;
- }
- }
- }
- gf_free(res_url);
- return ok;
-}
-
-/* function that checks if the default start file exists in the widget (package or folder)
- according to the default start files table from the W3C P&C spec.
- The widget path attribute is used to get the associated relocator from the registered relocators */
-static void wm_set_default_start_file(GF_WidgetManager *wm, GF_WidgetContent *content, const char *widget_path) {
- Bool result;
- char localized_path[GF_MAX_PATH], relocated_path[GF_MAX_PATH];
- char *mimetype = "text/html";
- result = wm_relocate_url(wm, widget_path, "index.htm", relocated_path, localized_path);
- if (result) {
- mimetype = "text/html";
- } else {
- result = wm_relocate_url(wm, widget_path, "index.html", relocated_path, localized_path);
- if (result) {
- mimetype = "text/html";
- } else {
- result = wm_relocate_url(wm, widget_path, "index.svg", relocated_path, localized_path);
- if (result) {
- mimetype = "image/svg+xml";
- } else {
- result = wm_relocate_url(wm, widget_path, "index.xhtml", relocated_path, localized_path);
- if (result) {
- mimetype = "application/xhtml+xml";
- } else {
- result = wm_relocate_url(wm, widget_path, "index.xht", relocated_path, localized_path);
- if (result) mimetype = "application/xhtml+xml";
- }
- }
- }
- }
- if (content->src) gf_free(content->src);
- content->src = gf_strdup(localized_path);
- if (content->relocated_src) gf_free(content->relocated_src);
- content->relocated_src = gf_strdup(relocated_path);
- if (content->mimetype) gf_free(content->mimetype);
- content->mimetype = gf_strdup(mimetype);
- if (content->encoding) gf_free(content->encoding);
- content->encoding = gf_strdup("utf-8");
-}
-
-static GF_WidgetContent *wm_add_icon(GF_Widget *widget, const char *icon_relocated_path, const char *icon_localized_path)
-{
- GF_WidgetContent *icon;
- u32 i, count;
- Bool already_in = 0;
-
- count = gf_list_count(widget->icons);
- for (i =0; i<count; i++) {
- GF_WidgetContent *in_icon = gf_list_get(widget->icons, i);
- if (!strcmp(icon_localized_path, in_icon->src)) {
- already_in = 1;
- break;
- }
- }
- if (already_in) return NULL;
-
- GF_SAFEALLOC(icon, GF_WidgetContent);
- icon->src = gf_strdup(icon_localized_path);
- icon->relocated_src = gf_strdup(icon_relocated_path);
- icon->interfaces = gf_list_new();
- icon->components = gf_list_new();
- icon->preferences = gf_list_new();
- icon->widget = widget;
- gf_list_add(widget->icons, icon);
- return icon;
-}
-
-/* Scans the W3C default icons table and add each icon */
-static void wm_set_default_icon_files(GF_WidgetManager *wm, const char *widget_path, GF_Widget *widget) {
- char relocated_path[GF_MAX_PATH], localized_path[GF_MAX_PATH];
- Bool result;
-
- result = wm_relocate_url(wm, widget_path, "icon.svg", relocated_path, localized_path);
- if (result) wm_add_icon(widget, relocated_path, localized_path);
-
- result = wm_relocate_url(wm, widget_path, "icon.ico", relocated_path, localized_path);
- if (result) wm_add_icon(widget, relocated_path, localized_path);
-
- result = wm_relocate_url(wm, widget_path, "icon.png", relocated_path, localized_path);
- if (result) wm_add_icon(widget, relocated_path, localized_path);
-
- result = wm_relocate_url(wm, widget_path, "icon.gif", relocated_path, localized_path);
- if (result) wm_add_icon(widget, relocated_path, localized_path);
-
- result = wm_relocate_url(wm, widget_path, "icon.jpg", relocated_path, localized_path);
- if (result) wm_add_icon(widget, relocated_path, localized_path);
-}
-
-GF_WidgetInstance *wm_load_widget(GF_WidgetManager *wm, const char *path, u32 InstanceID)
-{
- char szName[GF_MAX_PATH];
- u32 i, count;
- GF_Widget *widget = NULL;
- GF_WidgetInstance *wi = NULL;
- GF_XMLNode *root, *icon, *nmain, *name, *xml_node;
- GF_Err e;
- GF_DOMParser *dom = NULL;
- GF_WidgetPackage *wpackage = NULL;
-
- GF_DownloadSession *sess = NULL;
- const char *widget_ns_prefix = NULL;
- const char *mpegu_ns_prefix = NULL;
- const char *user_locale = gf_cfg_get_key(wm->term->user->config, "Systems", "Language2CC");
-
- /* Try to see if this widget is already loaded */
- e = GF_OK;
- count = gf_list_count(wm->widgets);
- for (i=0; i<count; i++) {
- widget = gf_list_get(wm->widgets, i);
- if (!strcmp(widget->url, path)) break;
- widget = NULL;
- }
-
- /*not found, retrieve the widget (if http), check the package if needed and parse the configuration document/widget manifest*/
- if (!widget) {
- Bool isDownloadedPackage = 0;
-
- /* path used to locate the widget (config.xml if unpackaged or zip/isoff package), potentially after download */
- const char *szLocalPath = path;
- /* used to locate the config document/widget manifest potentially after unzipping */
- const char *szManifestPath = path;
- /* */
- const char *szWidgetPath = path;
- const char *desc;
- GF_WidgetPreference *pref;
- GF_List *global_prefs;
- GF_WidgetContent *content;
- Bool correct_ns = 0;
-
- if (strstr(path, "http://")) {
- /*fetch the remote widget manifest synchronously and load it */
- sess = gf_dm_sess_new(wm->term->downloader, (char *)path, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e);
- if (sess) {
- e = gf_dm_sess_process(sess);
- if (e==GF_OK) {
- szLocalPath = gf_dm_sess_get_cache_name(sess);
-
- if (gf_unzip_probe(szLocalPath)) {
- isDownloadedPackage = 1;
- } else {
- /* TODO ISOFF-based packaged widget */
- }
- }
- }
- if (!sess || (e!=GF_OK) || !szLocalPath) goto exit;
- }
-
- /* Check if the widget package is a valid package and if it contains a config.xml file */
- szManifestPath = szLocalPath;
-
- wpackage = widget_package_new(wm, szLocalPath);
- if (wpackage) {
- count = gf_list_count(wpackage->resources);
- for (i=0; i<count; i++) {
- GF_WidgetPackageResource *wu = gf_list_get(wpackage->resources, i);
- /* According to W3C WPC, the config.xml file (lower case) shall only be located
- at the root of the package
- see http://www.w3.org/TR/widgets/#ta-dxzVDWpaWg */
- if (!strcmp(wu->inner_path, "config.xml")) {
- szManifestPath = wu->extracted_path;
- break;
- }
- }
- szWidgetPath = szManifestPath;
- }
-
-
- /* Parse the Widget Config Document as a DOM */
- dom = gf_xml_dom_new();
- e = gf_xml_dom_parse(dom, szManifestPath, NULL, NULL);
- if (e) goto exit;
-
- root = gf_xml_dom_get_root(dom);
- if (!root) goto exit;
-
- correct_ns = 0;
- count = gf_list_count(root->attributes);
- for (i=0; i<count; i++) {
- GF_XMLAttribute *att = gf_list_get(root->attributes, i);
- if (att->name) {
- if (!strcmp(att->name, "xmlns")) {
- if (!strcmp(att->value, "http://www.w3.org/ns/widgets")) {
- correct_ns = 1;
- }
- } else if (!strnicmp(att->name, "xmlns:", 6)) {
- if (!strcmp(att->value, "http://www.w3.org/ns/widgets")) {
- widget_ns_prefix = att->name+6;
- correct_ns = 1;
- } else if (!strcmp(att->value, "urn:mpeg:mpegu:schema:widgets:manifest:2010")) {
- mpegu_ns_prefix = att->name+6;
- }
- }
- }
- }
- /* According to the spec, wrong or no namespace means invalid widget
- see http://www.w3.org/TR/widgets/#ta-ACCJfDGwDQ */
- if (!correct_ns) goto exit;
-
- /* see http://www.w3.org/TR/widgets/#ta-ACCJfDGwDQ */
- if ((root->ns && (!widget_ns_prefix || strcmp(root->ns, widget_ns_prefix) || strcmp(root->name, "widget"))) ||
- (!root->ns && (widget_ns_prefix || strcmp(root->name, "widget"))))
- goto exit;
-
-
- /*pre-parse the root-level preference for use when parsing MPEG-U elements */
- global_prefs = gf_list_new();
- i=0;
- while ((nmain = gf_list_enum(root->content, &i))) {
- const char *pname, *pvalue;
- /* 'normalized' preference name and readonly*/
- char *npname, *npro;
- u32 i, count;
- Bool pref_exists = 0;
- Bool readOnly = 0;
- if (nmain->type != GF_XML_NODE_TYPE) continue;
- if (strcmp(nmain->name, "preference")) continue;
- pname = wm_xml_get_attr(nmain, "name");
- npname = wm_get_single_attribute(pname);
- if (!npname || !strlen(npname)) continue;
-
- count = gf_list_count(global_prefs);
- for (i = 0; i < count; i++) {
- GF_WidgetPreference *tmp_pref = gf_list_get(global_prefs, i);
- if (!strcmp(tmp_pref->name, npname)) {
- pref_exists = 1;
- break;
- }
- }
- if (pref_exists) continue;
-
- pvalue = wm_xml_get_attr(nmain, "readonly");
- npro = wm_get_single_attribute(pvalue);
- if (npro && strlen(npro) && !strcmp(npro, "true")) readOnly=1;
- if (npro) gf_free(npro);
-
- pvalue = wm_xml_get_attr(nmain, "value");
-
- GF_SAFEALLOC(pref, GF_WidgetPreference);
- pref->name = npname;
- if (pvalue) pref->value = wm_get_single_attribute(pvalue);
- /*global preferences are save and migratable*/
- pref->flags = GF_WM_PREF_SAVE | GF_WM_PREF_MIGRATE;
- if (readOnly) pref->flags |= GF_WM_PREF_READONLY;
- gf_list_add(global_prefs, pref);
- }
-
- /* get the content element from the XML Config document */
- GF_SAFEALLOC(content, GF_WidgetContent);
- content->interfaces = gf_list_new();
- content->components = gf_list_new();
- content->preferences = gf_list_new();
- nmain = wm_xml_find(root, widget_ns_prefix, "content", NULL);
- if (!nmain) {
- /* if not found, use the default table of start files */
- wm_set_default_start_file(wm, content, szWidgetPath);
- } else {
- const char *src, *encoding, *mimetype;
- src = wm_xml_get_attr(nmain, "src");
-
- /*check the resource exists*/
- if (src) {
- Bool result;
- char relocated_path[GF_MAX_PATH], localized_path[GF_MAX_PATH];
- /*remove any existing fragment*/
- char *sep = strchr(src, '#');
- if (sep) sep[0] = 0;
- result = wm_relocate_url(wm, szWidgetPath, src, relocated_path, localized_path);
- if (sep) sep[0] = '#';
- if (result) {
- content->relocated_src = gf_strdup(relocated_path);
- content->src = gf_strdup(localized_path);
- }
- }
-
- encoding = wm_xml_get_attr(nmain, "encoding");
- if (encoding && strlen(encoding)) content->encoding = wm_get_single_attribute(encoding);
- else content->encoding = gf_strdup("utf-8");
-
- mimetype = wm_xml_get_attr(nmain, "type");
- if (mimetype && strlen(mimetype)) {
- char *sep = strchr(mimetype, ';');
- if (sep) sep[0] = 0;
- content->mimetype = wm_get_single_attribute(mimetype);
- if (sep) sep[0] = ';';
- }
- else content->mimetype = gf_strdup("text/html");
-
- if (!content->relocated_src) wm_set_default_start_file(wm, content, szWidgetPath);
- }
- if (strlen(content->relocated_src) == 0) {
- gf_list_del(content->interfaces);
- gf_list_del(content->components);
- gf_list_del(content->preferences);
- gf_free(content);
- content = NULL;
- goto exit;
- }
- /* We need to call the parse of the MPEG-U elements to clone the global preferences into widget preferences,
- this should probably be changed to extract the clone from that function */
- wm_parse_mpegu_content_element(content, nmain, mpegu_ns_prefix, global_prefs);
-
- GF_SAFEALLOC(widget, GF_Widget);
- widget->url = gf_strdup(path);
- widget->manifest_path = gf_strdup(szManifestPath);
- if (isDownloadedPackage) widget->local_path = gf_strdup(szLocalPath);
- widget->wm = wm;
- widget->main = content;
- content->widget = widget;
- widget->icons = gf_list_new();
- widget->features = gf_list_new();
- if (wpackage) {
- widget->wpack = wpackage;
- wpackage->widget = widget;
- /*attach downloader to our package to avoid destroying the cache file*/
- wpackage->sess = sess;
- sess = NULL;
- }
-
- /*check for icon - can be optional*/
- i=0;
- while ((icon = gf_list_enum(root->content, &i))) {
- if (icon->type==GF_XML_NODE_TYPE &&
- icon->name && !strcmp(icon->name, "icon") &&
- ((!widget_ns_prefix && !icon->ns) || !strcmp(widget_ns_prefix, icon->ns))) {
- char *sep;
- char relocated[GF_MAX_PATH], localized_path[GF_MAX_PATH];
- char *icon_width, *icon_height;
- GF_WidgetContent *iconic;
- Bool result;
-
- char *pname = (char *)wm_xml_get_attr(icon, "src");
- if (!pname || !strlen(pname)) continue;
-
- /*remove any existing fragment*/
- sep = strchr(pname, '#');
- if (sep) sep[0] = 0;
- result = wm_relocate_url(wm, szWidgetPath, pname, relocated, localized_path);
- if (sep) sep[0] = '#';
- if (!result) continue;
-
- iconic = wm_add_icon(widget, relocated, localized_path);
- if (iconic) {
- wm_parse_mpegu_content_element(iconic, icon, mpegu_ns_prefix, global_prefs);
- icon_width = (char *)wm_xml_get_attr(icon, "width");
- if (icon_width) iconic->width = wm_parse_non_neg(icon_width);
- icon_height = (char *)wm_xml_get_attr(icon, "height");
- if (icon_height) iconic->height = wm_parse_non_neg(icon_height);
- }
- }
- }
- /* after processing the icon elements (wether there are valid icons or not), we use the default icon table
- see http://dev.w3.org/2006/waf/widgets/test-suite/test-cases/ta-FAFYMEGELU/004/ */
- wm_set_default_icon_files(wm, szWidgetPath, widget);
-
- /*delete the root-level preference*/
- i=0;
- while ((pref = gf_list_enum(global_prefs , &i))) {
- if (pref->value) gf_free(pref->value);
- gf_free(pref->name);
- gf_free(pref);
- }
- gf_list_del(global_prefs);
-
- /*check for optionnal meta data*/
- name = wm_xml_find(root, widget_ns_prefix, "name", user_locale);
- if (name) {
- const char *shortname = wm_xml_get_attr(name, "short");
- widget->shortname = wm_get_single_attribute(shortname);
-
- widget->name = wm_get_normalized_text_content(name, NULL, user_locale);
- }
-
- desc = wm_xml_get_attr(root, "id");
- if (desc) {
- /* TODO check if this is a valid IRI, for the moment, just hack to pass the test, check for ':'
- see http://dev.w3.org/2006/waf/widgets/test-suite/test-cases/ta-RawAIWHoMs/ */
- if (strchr(desc, ':'))
- widget->identifier = wm_get_single_attribute(desc);
- }
-
- desc = wm_xml_get_attr(root, "width");
- if (desc) {
- widget->width = wm_parse_non_neg(desc);
- }
- desc = wm_xml_get_attr(root, "height");
- if (desc) {
- widget->height = wm_parse_non_neg(desc);
- }
-
- name = wm_xml_find(root, widget_ns_prefix, "description", user_locale);
- if (name) {
- widget->description = wm_get_normalized_text_content(name, NULL, user_locale);
- }
-
- name = wm_xml_find(root, widget_ns_prefix, "license", user_locale);
- if (name) {
- const char *href = wm_xml_get_attr(name, "href");
- widget->licenseHref = wm_get_single_attribute(href);
-
- /* Warning the license text content should not be normalized */
- widget->license = wm_get_text_content(name, NULL, user_locale);
- }
-
- desc = wm_xml_get_attr(root, "version");
- if (desc) widget->version = wm_get_single_attribute(desc);
-
- desc = wm_xml_get_attr(root, "uuid");
- if (desc) widget->uuid = gf_strdup(desc);
-
- desc = wm_xml_get_attr(root, "discardable");
- if (desc) widget->discardable = !strcmp(desc, "true") ? 1 : 0;
-
- desc = wm_xml_get_attr(root, "multipleInstances");
- if (desc) widget->multipleInstance = !strcmp(desc, "true") ? 1 : 0;
-
- name = wm_xml_find(root, widget_ns_prefix, "author", NULL);
- if (name) {
- desc = wm_xml_get_attr(name, "href");
- if (desc && strchr(desc, ':')) widget->authorHref = wm_get_single_attribute(desc);
-
- desc = wm_xml_get_attr(name, "email");
- widget->authorEmail = wm_get_single_attribute(desc);
-
- widget->authorName = wm_get_normalized_text_content(name, NULL, user_locale);
- }
-
- i=0;
- while ((xml_node = gf_list_enum(root->content, &i))) {
- if (xml_node->type==GF_XML_NODE_TYPE &&
- xml_node->name && !strcmp(xml_node->name, "feature") &&
- ((!widget_ns_prefix && !xml_node->ns) || !strcmp(widget_ns_prefix, xml_node->ns))) {
-
- u32 i, count;
- Bool already_in = 0;
- GF_WidgetFeature *feat;
- const char *feature_name, *req_att;
- char *nfname;
- Bool required = 1;
- u32 j;
- GF_XMLNode *param_node;
-
- feature_name = (char *)wm_xml_get_attr(xml_node, "name");
- if (!feature_name || !strlen(feature_name) || !strchr(feature_name, ':')) continue;
- nfname = wm_get_single_attribute(feature_name);
-
- req_att = (char *)wm_xml_get_attr(xml_node, "required");
- if (req_att && !strcmp(req_att, "false")) required = 0;
-
- count = gf_list_count(widget->features);
- for (i = 0; i<count; i++) {
- GF_WidgetFeature *tmp = gf_list_get(widget->features, i);
- if (!strcmp(nfname, tmp->name)) {
- already_in = 1;
- break;
- }
- }
- if (already_in) continue;
-
- GF_SAFEALLOC(feat, GF_WidgetFeature);
- feat->name = nfname;
- feat->required = required;
- feat->params = gf_list_new();
- gf_list_add(widget->features, feat);
-
- j = 0;
- while ((param_node = gf_list_enum(xml_node->content, &j))) {
- if (param_node->type==GF_XML_NODE_TYPE &&
- param_node->name && !strcmp(param_node->name, "param") &&
- ((!widget_ns_prefix && !param_node->ns) || !strcmp(widget_ns_prefix, param_node->ns))) {
- GF_WidgetFeatureParam *wfp;
- const char *param_name, *param_value;
- char *npname, *npvalue;
-
- param_name = (char *)wm_xml_get_attr(param_node, "name");
- npname = wm_get_single_attribute(param_name);
- if (!strlen(npname)) continue;
-
- param_value = (char *)wm_xml_get_attr(param_node, "value");
- npvalue = wm_get_single_attribute(param_value);
- if (!strlen(npvalue)) {
- gf_free(npname);
- continue;
- }
-
- GF_SAFEALLOC(wfp, GF_WidgetFeatureParam);
- wfp->name = npname;
- wfp->value = npvalue;
- gf_list_add(feat->params, wfp);
-
- }
- }
-
- }
- }
-
- gf_list_add(wm->widgets, widget);
- }
-
- GF_SAFEALLOC(wi, GF_WidgetInstance);
- wi->widget = widget;
- wi->bound_ifces = gf_list_new();
- wi->output_triggers = gf_list_new();
- wi->components = gf_list_new();
- widget->nb_instances++;
- wi->instance_id = InstanceID;
- wi->permanent = 1;
-
- if (!InstanceID) {
- char szInst[20];
-
- count = gf_list_count(wm->widget_instances);
- for (i=0; i<count; i++) {
- GF_WidgetInstance *awi = gf_list_get(wm->widget_instances, i);
- if (awi->widget == wi->widget)
- wi->instance_id = awi->instance_id;
- }
- wi->instance_id ++;
-
- sprintf(szName, "%s#%s#Instance%d", path, wi->widget->name, wi->instance_id);
- sprintf(wi->secname, "Widget#%08X", gf_crc_32(szName, strlen(szName)));
-
- /*create section*/
- gf_cfg_set_key(wm->term->user->config, "Widgets", wi->secname, " ");
- gf_cfg_set_key(wm->term->user->config, wi->secname, "WM:Manifest", wi->widget->url);
- sprintf(szInst, "%d", wi->instance_id);
- gf_cfg_set_key(wm->term->user->config, wi->secname, "WM:InstanceID", szInst);
- }
- gf_list_add(wm->widget_instances, wi);
-
-
- if (strstr(path, "http://")) {
- GF_XMLNode *context;
- GF_DownloadSession *ctx_sess = NULL;
- char *ctxPath;
- context = NULL;
-
- /*fetch the remote widget context synchronously and load it */
- ctxPath = gf_malloc(sizeof(char) * (strlen(path) + 1 + 15/*?mpeg-u-context*/));
- strcpy(ctxPath, path);
- if ((strchr(path, '?') == NULL) && (strstr(path, "%3f")==NULL) && (strstr(path, "%3F")==NULL) ) {
- strcat(ctxPath, "?mpeg-u-context");
- } else {
- strcat(ctxPath, "&mpeg-u-context");
- }
-
- /*try to fetch the associated context*/
- ctx_sess = gf_dm_sess_new(wm->term->downloader, (char *)ctxPath, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e);
- if (ctx_sess) {
- e = gf_dm_sess_process(ctx_sess);
- if (e==GF_OK) {
- wi->mpegu_context = gf_xml_dom_new();
- e = gf_xml_dom_parse(wi->mpegu_context , gf_dm_sess_get_cache_name(ctx_sess), NULL, NULL);
- if (!e) {
- context = gf_xml_dom_get_root(wi->mpegu_context);
- if (strcmp(context->name, "contextInformation")) context = NULL;
- }
- }
- gf_dm_sess_del(ctx_sess);
- e = GF_OK;
- }
- gf_free(ctxPath);
- ctxPath = NULL;
-
- if (!context && wi->mpegu_context) {
- gf_xml_dom_del(wi->mpegu_context);
- wi->mpegu_context = NULL;
- }
-
- }
-
-exit:
- if (dom) gf_xml_dom_del(dom);
- if (sess) gf_dm_sess_del(sess);
- if (e || !wi) {
- if (wi) wm_delete_widget_instance(wm, wi);
- else {
- if (wpackage) widget_package_del(wm, wpackage);
- }
- return NULL;
- }
- return wi;
-}
-
-
-static Bool wm_enum_widget(void *cbk, char *file_name, char *file_path)
-{
- GF_WidgetInstance *wid;
- GF_WidgetManager *wm = (GF_WidgetManager *)cbk;
- wid = wm_load_widget(wm, file_path, 0);
- if (wid) {
- wm_widget_jsbind(wm, wid);
- /*remove section info*/
- gf_cfg_del_section(wm->term->user->config, wid->secname);
- gf_cfg_set_key(wm->term->user->config, "Widgets", wid->secname, NULL);
- }
- return 0;
-}
-
-static Bool wm_enum_dir(void *cbk, char *file_name, char *file_path)
-{
- return gf_enum_directory(file_path, 0, wm_enum_widget, cbk, "mgt");
-}
-
-
-static JSBool SMJS_FUNCTION(wm_initialize)
-{
- u32 i, count;
- const char*opt;
- SMJS_OBJ
- SMJS_ARGS
- GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
-
- count = gf_cfg_get_key_count(wm->term->user->config, "Widgets");
- for (i=0; i<count; i++) {
- const char *name = gf_cfg_get_key_name(wm->term->user->config, "Widgets", i);
- /*this is a previously loaded widgets - reload it*/
- if (!strnicmp(name, "Widget#", 7)) {
- const char *manifest = gf_cfg_get_key(wm->term->user->config, name, "WM:Manifest");
- if (manifest) {
- const char *ID = gf_cfg_get_key(wm->term->user->config, name, "WM:InstanceID");
- u32 instID = ID ? atoi(ID) : 0;
- GF_WidgetInstance *wi = wm_load_widget(wm, manifest, instID);
- if (wi) {
- strcpy(wi->secname, name);
- wm_widget_jsbind(wm, wi);
- }
- }
- }
- }
-
- opt = gf_cfg_get_key(wm->term->user->config, "Widgets", "WidgetStore");
- if (opt) gf_enum_directory(opt, 1, wm_enum_dir, wm, NULL);
-
- return JS_TRUE;
-}
-
-static void widgetmanager_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext *c, JSObject *global, Bool unload)
-{
- GF_WidgetManager *wm;
-
- GF_JSAPIParam par;
- JSPropertySpec wmClassProps[] = {
- {0, 0, 0, 0, 0}
- };
- JSFunctionSpec wmClassFuncs[] = {
- SMJS_FUNCTION_SPEC("initialize", wm_initialize, 0),
- SMJS_FUNCTION_SPEC("load", wm_load, 1),
- SMJS_FUNCTION_SPEC("unload", wm_unload, 1),
- SMJS_FUNCTION_SPEC("get", wm_get, 1),
- SMJS_FUNCTION_SPEC("findByInterface", wm_find_interface, 1),
- SMJS_FUNCTION_SPEC(0, 0, 0)
- };
-
- wm = jsext->udta;
- /*widget manager is only loaded once*/
- if (wm->ctx && (wm->ctx != c)) {
- /*load the 'Widget' object in the global scope*/
- widget_load(wm, scene, c, global, unload);
- return;
- }
-
- /*unload widgets*/
- if (unload) {
- if (wm->obj) {
- gf_js_remove_root(wm->ctx, &wm->obj, GF_JSGC_OBJECT);
- wm->obj = NULL;
- }
-
- while (gf_list_count(wm->widget_instances)) {
- GF_WidgetInstance *widg = gf_list_get(wm->widget_instances, 0);
- wm_delete_widget_instance(wm, widg);
- }
- wm->ctx = NULL;
- return;
- }
- wm->ctx = c;
-
- if (!scene) return;
-
- /*setup JS bindings*/
- JS_SETUP_CLASS(wm->widmanClass, "WIDGETMANAGER", JSCLASS_HAS_PRIVATE, wm_getProperty, wm_setProperty, JS_FinalizeStub);
-
- JS_InitClass(c, global, 0, &wm->widmanClass, 0, 0, wmClassProps, wmClassFuncs, 0, 0);
- wm->obj = JS_DefineObject(c, global, "WidgetManager", &wm->widmanClass, 0, 0);
- JS_SetPrivate(c, wm->obj, wm);
- gf_js_add_root(c, &wm->obj, GF_JSGC_OBJECT);
-
-
- {
- JSPropertySpec wmWidgetClassProps[] = {
- {0, 0, 0, 0, 0}
- };
- JSFunctionSpec wmWidgetClassFuncs[] = {
- SMJS_FUNCTION_SPEC("activate", wm_widget_activate, 1),
- SMJS_FUNCTION_SPEC("deactivate", wm_widget_deactivate, 0),
- SMJS_FUNCTION_SPEC("get_interface", wm_widget_get_interface, 1),
- SMJS_FUNCTION_SPEC("bind_output_trigger", wm_widget_bind_output_trigger, 2),
- SMJS_FUNCTION_SPEC("set_input", wm_widget_set_input, 2),
- SMJS_FUNCTION_SPEC("bind_interface", wm_widget_bind_interface, 2),
- SMJS_FUNCTION_SPEC("unbind_interface", wm_widget_unbind_interface, 1),
- SMJS_FUNCTION_SPEC("call_input_action", wm_widget_call_input_action, 1),
- SMJS_FUNCTION_SPEC("call_input_script", wm_widget_call_input_script, 2),
- SMJS_FUNCTION_SPEC("is_interface_bound", wm_widget_is_interface_bound, 1),
- SMJS_FUNCTION_SPEC("get_param_value", wm_widget_get_param_value, 1),
- SMJS_FUNCTION_SPEC("get_context", wm_widget_get_context, 0),
- SMJS_FUNCTION_SPEC("get_component", wm_widget_get_component, 2),
-
- SMJS_FUNCTION_SPEC(0, 0, 0)
- };
- /*setup JS bindings*/
- JS_SETUP_CLASS(wm->wmWidgetClass, "WMWIDGET", JSCLASS_HAS_PRIVATE, wm_widget_getProperty, wm_widget_setProperty, JS_FinalizeStub);
- JS_InitClass(c, global, 0, &wm->wmWidgetClass, 0, 0, wmWidgetClassProps, wmWidgetClassFuncs, 0, 0);
-
- JS_SETUP_CLASS(wm->widgetAnyClass, "WIDGETANY", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub);
- JS_InitClass(c, global, 0, &wm->widgetAnyClass, 0, 0, 0, 0, 0, 0);
- }
-
- JS_SETUP_CLASS(wm->widgetClass, "MPEGWidget", JSCLASS_HAS_PRIVATE, widget_getProperty, widget_setProperty, JS_FinalizeStub);
-
- if (scene->script_action) {
- if (!scene->script_action(scene->script_action_cbck, GF_JSAPI_OP_GET_TERM, scene->RootNode, &par))
- return;
- wm->term = par.term;
- }
-
-}
-
-
-static GF_JSUserExtension *gwm_new()
-{
- GF_JSUserExtension *dr;
- GF_WidgetManager *wm;
- dr = gf_malloc(sizeof(GF_JSUserExtension));
- memset(dr, 0, sizeof(GF_JSUserExtension));
- GF_REGISTER_MODULE_INTERFACE(dr, GF_JS_USER_EXT_INTERFACE, "WidgetManager JavaScript Bindings", "gpac distribution");
-
- GF_SAFEALLOC(wm, GF_WidgetManager);
- wm->widget_instances = gf_list_new();
- wm->widgets = gf_list_new();
- dr->load = widgetmanager_load;
- dr->udta = wm;
- return dr;
-}
-
-
-static void gwm_delete(GF_BaseInterface *ifce)
-{
- GF_WidgetManager *wm;
- GF_JSUserExtension *dr = (GF_JSUserExtension *) ifce;
- if (!dr)
- return;
- wm = dr->udta;
- if (!wm)
- return;
- if (wm->widget_instances)
- gf_list_del(wm->widget_instances);
- wm->widget_instances = NULL;
- if (wm->widgets)
- gf_list_del(wm->widgets);
- wm->widgets = NULL;
- gf_free(wm);
- dr->udta = NULL;
- gf_free(dr);
-}
-#endif
-
-
-GF_EXPORT
-const u32 *QueryInterfaces()
-{
- static u32 si [] = {
-#ifdef GPAC_HAS_SPIDERMONKEY
- GF_JS_USER_EXT_INTERFACE,
- GF_SCENE_DECODER_INTERFACE,
-#endif
- 0
- };
- return si;
-}
-
-GF_EXPORT
-GF_BaseInterface *LoadInterface(u32 InterfaceType)
-{
-#ifdef GPAC_HAS_SPIDERMONKEY
- if (InterfaceType == GF_JS_USER_EXT_INTERFACE) return (GF_BaseInterface *)gwm_new();
- else if (InterfaceType == GF_SCENE_DECODER_INTERFACE) return (GF_BaseInterface *)LoadWidgetReader();
-#endif
- return NULL;
-}
-
-GF_EXPORT
-void ShutdownInterface(GF_BaseInterface *ifce)
-{
- switch (ifce->InterfaceType) {
-#ifdef GPAC_HAS_SPIDERMONKEY
- case GF_JS_USER_EXT_INTERFACE:
- gwm_delete(ifce);
- break;
- case GF_SCENE_DECODER_INTERFACE:
- ShutdownWidgetReader(ifce);
- break;
-#endif
- }
-}
-