// Open logical file contained in physical OLE file
OLE2Stream*  ole2_fopen(OLE2* ole,BYTE* file)
{
    OLE2Stream* olest;
    int i;

#ifdef OLE_DEBUG
    printf("----------------------------------------------\n");
    printf("ole2_fopen %s\n", file);
#endif

    for (i=0;i<ole->files.count;i++) {
		BYTE *str = ole->files.file[i].name;
        if (str && strcmp((char *)str,(char *)file)==0)	// newer versions of Excel don't write the "Root Entry" string for the first set of data
        {
            olest=ole2_sopen(ole,ole->files.file[i].start,ole->files.file[i].size);
            return(olest);
        }
	}
    return(NULL);
}
Exemple #2
0
// Open physical file
OLE2* ole2_open(const BYTE *file)
{
    //BYTE buf[1024];
    OLE2Header* oleh;
    OLE2* ole;
    OLE2Stream* olest;
    PSS*	pss;
    BYTE* name = NULL;

#ifdef OLE_DEBUG
    printf("----------------------------------------------\n");
    printf("ole2_open %s\n", file);
#endif

	if(xls_debug) printf("ole2_open: %s\n", file);
    ole=(OLE2*)calloc(1, sizeof(OLE2));
    if (!(ole->file=fopen((char *)file,"rb")))
    {
        if(xls_debug) printf("File not found\n");
        free(ole);
        return(NULL);
    }
    // read header and check magic numbers
    oleh=(OLE2Header*)malloc(512);
    fread(oleh,1,512,ole->file);
    xlsConvertHeader(oleh);

	// make sure the file looks good. Note: this code only works on Little Endian machines
	if(oleh->id[0] != 0xE011CFD0 || oleh->id[1] != 0xE11AB1A1 || oleh->byteorder != 0xFFFE) {
		fclose(ole->file);
        printf("Not an excel file\n");
		free(ole);
		return NULL;
	}

    //ole->lsector=(WORD)pow(2,oleh->lsector);
    //ole->lssector=(WORD)pow(2,oleh->lssector);
	ole->lsector=512;
    ole->lssector=64;
	assert(oleh->lsectorB==9);	// 2**9 == 512
	assert(oleh->lssectorB==6);	// 2**6 == 64
	
    ole->cfat=oleh->cfat;
    ole->dirstart=oleh->dirstart;
    ole->sectorcutoff=oleh->sectorcutoff;
    ole->sfatstart=oleh->sfatstart;
    ole->csfat=oleh->csfat;
    ole->difstart=oleh->difstart;
    ole->cdif=oleh->cdif;
    ole->files.count=0;

#ifdef OLE_DEBUG
		printf("==== OLE HEADER ====\n");
		//printf ("Header Size:   %i \n", sizeof(OLE2Header));
		//printf ("id[0]-id[1]:   %X-%X \n", oleh->id[0], oleh->id[1]);
		printf ("verminor:      %X \n",oleh->verminor);
		printf ("verdll:        %X \n",oleh->verdll);
		//printf ("Byte order:    %X \n",oleh->byteorder);
		printf ("sect len:      %X (%i)\n",ole->lsector,ole->lsector);		// ole
		printf ("mini len:      %X (%i)\n",ole->lssector,ole->lssector);	// ole
		printf ("Fat sect.:     %i \n",oleh->cfat);
		printf ("Dir Start:     %i \n",oleh->dirstart);
		
		printf ("Mini Cutoff:   %i \n",oleh->sectorcutoff);
		printf ("MiniFat Start: %X \n",oleh->sfatstart);
		printf ("Count MFat:    %i \n",oleh->csfat);
		printf ("Dif start:     %X \n",oleh->difstart);
		printf ("Count Dif:     %i \n",oleh->cdif);
		printf ("Fat Size:      %u (0x%X) \n",oleh->cfat*ole->lsector,oleh->cfat*ole->lsector);
#endif
    // read directory entries
    read_MSAT(ole, oleh);

	// reuse this buffer
    pss = (PSS*)oleh;
	// oleh = (void *)NULL; // Not needed as oleh not used from here on
	
    olest=ole2_sopen(ole,ole->dirstart, -1);
    do
    {
        ole2_read(pss,1,sizeof(PSS),olest);
        xlsConvertPss(pss);
        name=unicode_decode(pss->name, pss->bsize, 0, "UTF-8");
#ifdef OLE_DEBUG	
		printf("OLE NAME: %s count=%d\n", name, ole->files.count);
#endif
        if (pss->type == PS_USER_ROOT || pss->type == PS_USER_STREAM) // (name!=NULL) // 
        {

#ifdef OLE_DEBUG		
			printf("OLE TYPE: %s file=%d \n", pss->type == PS_USER_ROOT ? "root" : "user", ole->files.count);
#endif		
            if (ole->files.count==0)
            {
                ole->files.file=malloc(sizeof(struct st_olefiles_data));
            } else {
                ole->files.file=realloc(ole->files.file,(ole->files.count+1)*sizeof(struct st_olefiles_data));
            }
            ole->files.file[ole->files.count].name=name;
            ole->files.file[ole->files.count].start=pss->sstart;
            ole->files.file[ole->files.count].size=pss->size;
            ole->files.count++;
			
			if(pss->sstart == ENDOFCHAIN) {
				if (xls_debug) verbose("END OF CHAIN\n");
			} else
			if(pss->type == PS_USER_STREAM) {
#ifdef OLE_DEBUG
					printf("----------------------------------------------\n");
					printf("name: %s (size=%d [c=%c])\n", name, pss->bsize, name ? name[0]:' ');
					printf("bsize %i\n",pss->bsize);
					printf("type %i\n",pss->type);
					printf("flag %i\n",pss->flag);
					printf("left %X\n",pss->left);
					printf("right %X\n",pss->right);
					printf("child %X\n",pss->child);
					printf("guid %.4X-%.4X-%.4X-%.4X %.4X-%.4X-%.4X-%.4X\n",pss->guid[0],pss->guid[1],pss->guid[2],pss->guid[3],
						pss->guid[4],pss->guid[5],pss->guid[6],pss->guid[7]);
					printf("user flag %.4X\n",pss->userflags);
					printf("sstart %.4d\n",pss->sstart);
					printf("size %.4d\n",pss->size);
#endif
			} else
			if(pss->type == PS_USER_ROOT) {
				DWORD sector, k, blocks;
				BYTE *wptr;
				
				blocks = (pss->size + (ole->lsector - 1)) / ole->lsector;	// count partial
				ole->SSAT = (BYTE *)malloc(blocks*ole->lsector);
				// printf("blocks %d\n", blocks);

				assert(ole->SSecID);
				
				sector = pss->sstart;
				wptr=(BYTE*)ole->SSAT;
				for(k=0; k<blocks; ++k) {
					// printf("block %d sector %d\n", k, sector);
					assert(sector != ENDOFCHAIN);
					fseek(ole->file,sector*ole->lsector+512,0);
					fread(wptr,1,ole->lsector,ole->file);
					wptr += ole->lsector;
					sector = xlsIntVal(ole->SecID[sector]);
				}
			}	
		} else {
			free(name);
		}
    }
    while (!olest->eof);

	ole2_fclose(olest);
    free(pss);

    return ole;
}