/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file is part of libxls -- A multiplatform, C/C++ library * for parsing Excel(TM) files. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY David Hoerl ''AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David Hoerl OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2004 Komarov Valery * Copyright 2006 Christophe Leitienne * Copyright 2013 Bob Colbert * Copyright 2008-2013 David Hoerl * */ #include "config.h" #include #include #include #include #ifdef HAVE_ICONV #include #else #include #endif #include #include #include #include //#include "xls.h" #include "libxls/xlstypes.h" #include "libxls/xlsstruct.h" #include "libxls/xlstool.h" #include "libxls/brdb.h" #include "libxls/endian.h" extern int xls_debug; static void xls_showBOUNDSHEET(void* bsheet); static const DWORD colors[] = { 0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0x800000, 0x008000, 0x000080, 0x808000, 0x800080, 0x008080, 0xC0C0C0, 0x808080, 0x9999FF, 0x993366, 0xFFFFCC, 0xCCFFFF, 0x660066, 0xFF8080, 0x0066CC, 0xCCCCFF, 0x000080, 0xFF00FF, 0xFFFF00, 0x00FFFF, 0x800080, 0x800000, 0x008080, 0x0000FF, 0x00CCFF, 0xCCFFFF, 0xCCFFCC, 0xFFFF99, 0x99CCFF, 0xFF99CC, 0xCC99FF, 0xFFCC99, 0x3366FF, 0x33CCCC, 0x99CC00, 0xFFCC00, 0xFF9900, 0xFF6600, 0x666699, 0x969696, 0x003366, 0x339966, 0x003300, 0x333300, 0x993300, 0x993366, 0x333399, 0x333333 }; #if HAVE_ASPRINTF != 1 #include #ifdef MSDN static int asprintf(char **ret, const char *format, ...) { int i, size=100; char *p, *np; va_list ap; if ((p = (char *)malloc(size)) == NULL) return -1; while (1) { va_start(ap, format); i = _vsnprintf(p, size, format, ap); va_end(ap); if (i > -1 && i < size) { i++; break; } if (i > -1) /* glibc 2.1 */ size = i+1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ if ((np = realloc (p, size)) == NULL) { free(p); return -1; } else { p = np; } } *ret = p; return i > 255 ? 255 : i; } #else static int asprintf(char **ret, const char *format, ...) { int i; char *str; va_list ap; va_start(ap, format); i = vsnprintf(NULL, 0, format, ap) + 1; str = (char *)malloc(i); i = vsnprintf(str, i, format, ap); va_end(ap); *ret = str; return i > 255 ? 255 : i; } #endif #endif void dumpbuf(BYTE* fname,long size,BYTE* buf) { FILE *f = fopen((char *)fname, "wb"); fwrite (buf, 1, size, f); fclose(f); } // Display string if in debug mode void verbose(char* str) { if (xls_debug) printf("libxls : %s\n",str); } BYTE *utf8_decode(BYTE *str, DWORD len, char *encoding) { int utf8_chars = 0; BYTE *ret; DWORD i; for(i=0; i> 6); *out++ = (BYTE)0x80 | (c & 0x3F); } else { *out++ = c; } } *out = 0; } return ret; } // Convert unicode string to to_enc encoding BYTE* unicode_decode(const BYTE *s, int len, size_t *newlen, const char* to_enc) { #ifdef HAVE_ICONV // Do iconv conversion #ifdef AIX const char *from_enc = "UTF-16le"; #else const char *from_enc = "UTF-16LE"; #endif BYTE* outbuf = 0; if(s && len && from_enc && to_enc) { size_t outlenleft = len; int outlen = len; size_t inlenleft = len; iconv_t ic = iconv_open(to_enc, from_enc); BYTE* src_ptr = (BYTE*) s; BYTE* out_ptr = 0; if(ic == (iconv_t)-1) { // Something went wrong. if (errno == EINVAL) { if (!strcmp(to_enc, "ASCII")) { ic = iconv_open("UTF-8", from_enc); if(ic == (iconv_t)-1) { printf("conversion from '%s' to '%s' not available", from_enc, to_enc); return outbuf; } } } else { printf ("iconv_open: error=%d", errno); return outbuf; } } size_t st; outbuf = (BYTE*)malloc(outlen + 1); if(outbuf) { out_ptr = (BYTE*)outbuf; while(inlenleft) { st = iconv(ic, (char **)&src_ptr, &inlenleft, (char **)&out_ptr,(size_t *) &outlenleft); if(st == (size_t)(-1)) { if(errno == E2BIG) { size_t diff = out_ptr - outbuf; outlen += inlenleft; outlenleft += inlenleft; outbuf = (BYTE*)realloc(outbuf, outlen + 1); if(!outbuf) { break; } out_ptr = outbuf + diff; } else { free(outbuf), outbuf = NULL; break; } } } } iconv_close(ic); outlen -= outlenleft; if (newlen) { *newlen = outbuf ? outlen : 0; } if(outbuf) { outbuf[outlen] = 0; } } return outbuf; #else // Do wcstombs conversion char *converted = NULL; int count, count2, i; wchar_t *w; short *x; if (setlocale(LC_CTYPE, "") == NULL) { printf("setlocale failed: %d\n", errno); return "*null*"; } x=(short *)s; w = (wchar_t*)malloc((len+1)*sizeof(wchar_t)); for(i=0; i= cor) idx -= cor; if( idx < max ) { return colors[idx]; } else return colors[def]; } void xls_showBookInfo(xlsWorkBook* pWB) { verbose("BookInfo"); printf(" is5ver: %i\n",pWB->is5ver); printf("codepage: %i\n",pWB->codepage); printf(" type: %.4X ",pWB->type); switch (pWB->type) { case 0x5: printf("Workbook globals\n"); break; case 0x6: printf("Visual Basic module\n"); break; case 0x10: printf("Worksheet\n"); break; case 0x20: printf("Chart\n"); break; case 0x40: printf("BIFF4 Macro sheet\n"); break; case 0x100: printf("BIFF4W Workbook globals\n"); break; } printf("------------------- END BOOK INFO---------------------------\n"); } void xls_showBOF(BOF* bof) { printf("----------------------------------------------\n"); verbose("BOF"); printf(" ID: %.4Xh %s (%s)\n",bof->id,brdb[get_brbdnum(bof->id)].name,brdb[get_brbdnum(bof->id)].desc); printf(" Size: %i\n",bof->size); } #if 0 static void xls_showBOUNDSHEET(BOUNDSHEET* bsheet) { switch (bsheet->type & 0x000f) { case 0x0000: /* worksheet or dialog sheet */ verbose ("85: Worksheet or dialog sheet"); break; case 0x0001: /* Microsoft Excel 4.0 macro sheet */ verbose ("85: Microsoft Excel 4.0 macro sheet"); break; case 0x0002: /* Chart */ verbose ("85: Chart sheet"); break; case 0x0006: /* Visual Basic module */ verbose ("85: Visual Basic sheet"); break; default: break; } printf(" Pos: %Xh\n",bsheet->filepos); printf(" flags: %.4Xh\n",bsheet->type); // printf(" Name: [%i] %s\n",bsheet->len,bsheet->name); } #endif void xls_showROW(struct st_row_data* row) { verbose("ROW"); printf(" Index: %i \n",row->index); printf("First col: %i \n",row->fcell); printf(" Last col: %i \n",row->lcell); printf(" Height: %i (1/20 px)\n",row->height); printf(" Flags: %.4X \n",row->flags); printf(" xf: %i \n",row->xf); printf("----------------------------------------------\n"); } void xls_showColinfo(struct st_colinfo_data* col) { verbose("COLINFO"); printf("First col: %i \n",col->first); printf(" Last col: %i \n",col->last); printf(" Width: %i (1/256 px)\n",col->width); printf(" XF: %i \n",col->xf); printf(" Flags: %i (",col->flags); if (col->flags & 0x1) printf("hidden "); if (col->flags & 0x700) printf("outline "); if (col->flags & 0x1000) printf("collapsed "); printf(")\n"); printf("----------------------------------------------\n"); } void xls_showCell(struct st_cell_data* cell) { printf(" -----------\n"); printf(" ID: %.4Xh %s (%s)\n",cell->id, brdb[get_brbdnum(cell->id)].name, brdb[get_brbdnum(cell->id)].desc); printf(" Cell: %c:%u [%u:%u]\n",cell->col+'A',cell->row+1,cell->col,cell->row); // printf(" Cell: %u:%u\n",cell->col+1,cell->row+1); printf(" xf: %i\n",cell->xf); if(cell->id == XLS_RECORD_BLANK) { //printf("BLANK_CELL!\n"); return; } printf(" double: %f\n",cell->d); printf(" int: %d\n",cell->l); if (cell->str!=NULL) printf(" str: %s\n",cell->str); } void xls_showFont(struct st_font_data* font) { printf(" name: %s\n",font->name); printf(" height: %i\n",font->height); printf(" flag: %.4X\n",font->flag); printf(" color: %.6X\n",font->color); printf(" bold: %i\n",font->bold); printf("escapement: %i\n",font->escapement); printf(" underline: %i\n",font->underline); printf(" family: %i\n",font->family); printf(" charset: %i\n",font->charset); } #if 0 typedef struct st_format { long count; //Count of FORMAT's struct st_format_data { WORD index; char *value; } * format; } st_format; #endif void xls_showFormat(struct st_format_data* frmt) { printf(" index : %u\n", frmt->index); printf(" value: %s\n", frmt->value); } void xls_showXF(XF8* xf) { static int idx; printf(" Index: %u\n",idx++); printf(" Font: %u\n",xf->font); printf(" Format: %u\n",xf->format); printf(" Type: 0x%x\n",xf->type); printf(" Align: 0x%x\n",xf->align); printf(" Rotation: 0x%x\n",xf->rotation); printf(" Ident: 0x%x\n",xf->ident); printf(" UsedAttr: 0x%x\n",xf->usedattr); printf(" LineStyle: 0x%x\n",xf->linestyle); printf(" Linecolor: 0x%x\n",xf->linecolor); printf("GroundColor: 0x%x\n",xf->groundcolor); } BYTE *xls_getfcell(xlsWorkBook* pWB,struct st_cell_data* cell,WORD *label) { struct st_xf_data *xf; WORD len; char *ret = NULL; xf=&pWB->xfs.xf[cell->xf]; switch (cell->id) { case XLS_RECORD_LABELSST: //printf("WORD: %u short: %u str: %s\n", *label, xlsShortVal(*label), pWB->sst.string[xlsShortVal(*label)].str ); asprintf(&ret,"%s",pWB->sst.string[xlsShortVal(*label)].str); break; case XLS_RECORD_BLANK: case XLS_RECORD_MULBLANK: asprintf(&ret, ""); break; case XLS_RECORD_LABEL: len = xlsShortVal(*label); label++; if(pWB->is5ver) { asprintf(&ret,"%.*s", len, (char *)label); //printf("Found BIFF5 string of len=%d \"%s\"\n", len, ret); } else if ((*(BYTE *)label & 0x01) == 0) { ret = (char *)utf8_decode((BYTE *)label + 1, len, pWB->charset); } else { size_t newlen; ret = (char *)unicode_decode((BYTE *)label + 1, len*2, &newlen, pWB->charset); } break; case XLS_RECORD_RK: case XLS_RECORD_NUMBER: asprintf(&ret,"%lf", cell->d); break; // if( RK || MULRK || NUMBER || FORMULA) // if (cell->id==0x27e || cell->id==0x0BD || cell->id==0x203 || 6 (formula)) default: switch (xf->format) { case 0: asprintf(&ret,"%d",(int)cell->d); break; case 1: asprintf(&ret,"%d",(int)cell->d); break; case 2: asprintf(&ret,"%.1f",cell->d); break; case 9: asprintf(&ret,"%d",(int)cell->d); break; case 10: asprintf(&ret,"%.2f",cell->d); break; case 11: asprintf(&ret,"%.1e",cell->d); break; case 14: //ret=ctime(cell->d); asprintf(&ret,"%.0f",cell->d); break; default: // asprintf(&ret,"%.4.2f (%i)",cell->d,xf->format);break; asprintf(&ret,"%.2f",cell->d); break; } break; } return (BYTE *)ret; } char* xls_getCSS(xlsWorkBook* pWB) { char color[255]; char* align; char* valign; char borderleft[255]; char borderright[255]; char bordertop[255]; char borderbottom[255]; char italic[255]; char underline[255]; char bold[255]; WORD size; char fontname[255]; struct st_xf_data* xf; DWORD background; DWORD i; char *ret = malloc(65535); char *buf = malloc(4096); ret[0] = '\0'; for (i=0;ixfs.count;i++) { xf=&pWB->xfs.xf[i]; switch ((xf->align & 0x70)>>4) { case 0: valign=(char*)"top"; break; case 1: valign=(char*)"middle"; break; case 2: valign=(char*)"bottom"; break; // case 3: valign=(char*)"right"; break; // case 4: valign=(char*)"right"; break; default: valign=(char*)"middle"; break; } switch (xf->align & 0x07) { case 1: align=(char*)"left"; break; case 2: align=(char*)"center"; break; case 3: align=(char*)"right"; break; default: align=(char*)"left"; break; } switch (xf->linestyle & 0x0f) { case 0: sprintf(borderleft,"%s", ""); break; default: sprintf(borderleft,"border-left: 1px solid black;"); break; } switch (xf->linestyle & 0x0f0) { case 0: sprintf(borderright,"%s", ""); break; default: sprintf(borderright,"border-right: 1px solid black;"); break; } switch (xf->linestyle & 0x0f00) { case 0: sprintf(bordertop,"%s", ""); break; default: sprintf(bordertop,"border-top: 1px solid black;"); break; } switch (xf->linestyle & 0x0f000) { case 0: sprintf(borderbottom,"%s", ""); break; default: sprintf(borderbottom,"border-bottom: 1px solid Black;"); break; } if (xf->font) sprintf(color,"color:#%.6X;",xls_getColor(pWB->fonts.font[xf->font-1].color,0)); else sprintf(color,"%s", ""); if (xf->font && (pWB->fonts.font[xf->font-1].flag & 2)) sprintf(italic,"font-style: italic;"); else sprintf(italic,"%s", ""); if (xf->font && (pWB->fonts.font[xf->font-1].bold>400)) sprintf(bold,"font-weight: bold;"); else sprintf(bold,"%s", ""); if (xf->font && (pWB->fonts.font[xf->font-1].underline)) sprintf(underline,"text-decoration: underline;"); else sprintf(underline,"%s", ""); if (xf->font) size=pWB->fonts.font[xf->font-1].height/20; else size=10; if (xf->font) sprintf(fontname,"%s",pWB->fonts.font[xf->font-1].name); else sprintf(fontname,"Arial"); background=xls_getColor((WORD)(xf->groundcolor & 0x7f),1); sprintf(buf,".xf%i{ font-size:%ipt;font-family: \"%s\";background:#%.6X;text-align:%s;vertical-align:%s;%s%s%s%s%s%s%s%s}\n", i,size,fontname,background,align,valign,borderleft,borderright,bordertop,borderbottom,color,italic,bold,underline); strcat(ret,buf); } ret = realloc(ret, strlen(ret)+1); free(buf); return ret; }