xls 0.1.1 → 0.1.2
raw patch · 19 files changed
+2915/−3072 lines, 19 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.Xls: instance GHC.Exception.Exception Data.Xls.XlsException
+ Data.Xls: instance GHC.Exception.Type.Exception Data.Xls.XlsException
Files
- Changelog.md +4/−0
- README.md +2/−7
- lib/libxls-wrapper.c +1/−1
- lib/libxls/config/config.h +2/−1
- lib/libxls/include/libxls/brdb.c.h +25/−21
- lib/libxls/include/libxls/brdb.h +26/−22
- lib/libxls/include/libxls/endian.h +23/−24
- lib/libxls/include/libxls/ole.h +53/−36
- lib/libxls/include/libxls/xls.h +0/−73
- lib/libxls/include/libxls/xlsstruct.h +46/−39
- lib/libxls/include/libxls/xlstool.h +41/−39
- lib/libxls/include/libxls/xlstypes.h +31/−45
- lib/libxls/include/xls.h +91/−0
- lib/libxls/src/endian.c +36/−63
- lib/libxls/src/ole.c +566/−296
- lib/libxls/src/xls.c +1773/−2182
- lib/libxls/src/xlstool.c +191/−220
- stack.yaml +1/−1
- xls.cabal +3/−2
Changelog.md view
@@ -1,3 +1,7 @@+## 0.1.2++* Upgrade libxls upstream package version from 1.4.0 to 1.5.1+ ## 0.1.1 * Upgrade dependencies
README.md view
@@ -1,9 +1,5 @@ ## Haskell xls Parsing -[](https://hackage.haskell.org/package/xls)-[](https://travis-ci.org/harendra-kumar/xls)-[](https://ci.appveyor.com/project/harendra-kumar/xls)- `xls` is a Haskell library to parse Microsoft Excel spreadsheet files. It parses the xls file format (extension `.xls`) more specifically known as `BIFF/Excel 97-2004`.@@ -26,9 +22,8 @@ See the haddock documentation for API details. ## Under the hood-The library is based on the C library libxls, see-[sourceforge](https://sourceforge.net/projects/libxls/) or-[github](https://github.com/svn2github/libxls).+The library is based on the C library +[libxls](https://github.com/libxls/libxls). ## See Also
lib/libxls-wrapper.c view
@@ -1,4 +1,4 @@-#include "libxls/xls.h"+#include "xls.h" DWORD xls_wb_sheetcount (xlsWorkBook* pWB) { return pWB->sheets.count;
lib/libxls/config/config.h view
@@ -4,7 +4,8 @@ /* Define if you have the iconv() function. */ #if (!defined(__MINGW32__) && !defined(mingw32_HOST_OS)) || defined (FORCE_HAS_ICONV) #define HAVE_ICONV 1+#define ICONV_CONST #endif /* Define to the version of this package. */-#define PACKAGE_VERSION "1.4.0"+#define PACKAGE_VERSION "1.5.1"
lib/libxls/include/libxls/brdb.c.h view
@@ -1,31 +1,35 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2008-2012 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */
lib/libxls/include/libxls/brdb.h view
@@ -1,31 +1,35 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2008-2012 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ @@ -39,7 +43,7 @@ record_brdb brdb[] = {-#include <libxls/brdb.c.h>+#include "../libxls/brdb.c.h" }; static int get_brbdnum(int id)
lib/libxls/include/libxls/endian.h view
@@ -1,35 +1,37 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2013 Bob Colbert *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2013 Bob Colbert+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ -#include <libxls/xlsstruct.h>+#include "../libxls/xlsstruct.h" -int xls_is_bigendian();+int xls_is_bigendian(void); DWORD xlsIntVal (DWORD i); unsigned short xlsShortVal (short s); @@ -54,9 +56,6 @@ void xlsConvertFormulaArray(FARRAY *f); void xlsConvertHeader(OLE2Header *h); void xlsConvertPss(PSS* pss);-#if 0 // unused-void xlsConvertUnicode(wchar_t *w, char *s, int len);-#endif #define W_ENDIAN(a) a=xlsShortVal(a) #define D_ENDIAN(a) a=xlsIntVal(a)
lib/libxls/include/libxls/ole.h view
@@ -1,43 +1,50 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2013 Bob Colbert- * Copyright 2008-2013 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ #ifndef OLE_INCLUDE #define OLE_INCLUDE +#ifdef __cplusplus+#include <cstdio> // FILE *+#else #include <stdio.h> // FILE *+#endif -#include "libxls/xlstypes.h"+#include "../libxls/xlstypes.h" -#ifdef AIX+#if defined(_AIX) || defined(__sun) #pragma pack(1) #else #pragma pack(push, 1)@@ -86,7 +93,7 @@ long count; struct st_olefiles_data {- BYTE* name;+ char* name; DWORD start; DWORD size; }@@ -97,6 +104,10 @@ typedef struct OLE2 { FILE* file;+ const void *buffer;+ size_t buffer_len;+ size_t buffer_pos;+ WORD lsector; WORD lssector; DWORD cfat;@@ -107,9 +118,16 @@ DWORD csfat; DWORD difstart; DWORD cdif;+ DWORD* SecID; // regular sector data+ DWORD SecIDCount;+ DWORD* SSecID; // short sector data+ DWORD SSecIDCount;+ BYTE* SSAT; // directory of short sectors+ DWORD SSATCount;+ st_olefiles files; } OLE2;@@ -129,7 +147,7 @@ } OLE2Stream; -#ifdef AIX+#if defined(_AIX) || defined(__sun) #pragma pack(1) #else #pragma pack(push, 1)@@ -137,7 +155,7 @@ typedef struct PSS {- BYTE name[64];+ char name[64]; WORD bsize; BYTE type; //STGTY #define PS_EMPTY 00@@ -160,14 +178,13 @@ #pragma pack(pop) -extern size_t ole2_read(void* buf,size_t size,size_t count,OLE2Stream* olest);-extern OLE2Stream* ole2_sopen(OLE2* ole,DWORD start, size_t size);-extern void ole2_seek(OLE2Stream* olest,DWORD ofs);-extern OLE2Stream* ole2_fopen(OLE2* ole,BYTE* file);-extern void ole2_fclose(OLE2Stream* ole2st);-extern OLE2* ole2_open(const BYTE *file);-extern void ole2_close(OLE2* ole2);-extern void ole2_bufread(OLE2Stream* olest);-+ssize_t ole2_read(void* buf,size_t size,size_t count,OLE2Stream* olest);+OLE2Stream* ole2_sopen(OLE2* ole,DWORD start, size_t size);+int ole2_seek(OLE2Stream* olest,DWORD ofs);+OLE2Stream* ole2_fopen(OLE2* ole, const char *file);+void ole2_fclose(OLE2Stream* ole2st);+OLE2* ole2_open_file(const char *file);+OLE2* ole2_open_buffer(const void *buffer, size_t len);+void ole2_close(OLE2* ole2); #endif
− lib/libxls/include/libxls/xls.h
@@ -1,73 +0,0 @@-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- *- * 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 2008-2012 David Hoerl- *- */--#ifndef XLS_INCLUDE-#define XLS_INCLUDE- -#ifdef __cplusplus-namespace xls {-extern "C" {-#endif--#include "libxls/xlstypes.h"-#include "libxls/xlsstruct.h"-#include "libxls/xlstool.h"---extern const char* xls_getVersion(void);--extern int xls(int debug); // Set debug. Force library to load?-extern void xls_set_formula_hander(xls_formula_handler handler);--extern void xls_parseWorkBook(xlsWorkBook* pWB);-extern void xls_parseWorkSheet(xlsWorkSheet* pWS);--extern xlsWorkBook* xls_open(const char *file,const char *charset); // convert 16bit strings within the spread sheet to this 8-bit encoding (UTF-8 default)-#define xls_close xls_close_WB // historical-extern void xls_close_WB(xlsWorkBook* pWB); // preferred name--extern xlsWorkSheet * xls_getWorkSheet(xlsWorkBook* pWB,int num);-extern void xls_close_WS(xlsWorkSheet* pWS);--extern xlsSummaryInfo *xls_summaryInfo(xlsWorkBook* pWB);-extern void xls_close_summaryInfo(xlsSummaryInfo *pSI);--// utility function-xlsRow *xls_row(xlsWorkSheet* pWS, WORD cellRow);-xlsCell *xls_cell(xlsWorkSheet* pWS, WORD cellRow, WORD cellCol);--#ifdef __cplusplus-} // extern c block-} // namespace-#endif--#endif-
lib/libxls/include/libxls/xlsstruct.h view
@@ -1,39 +1,42 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2013 Bob Colbert- * Copyright 2008-2013 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ #ifndef XLS_STRUCT_INC #define XLS_STRUCT_INC -#include "libxls/ole.h"+#include "../libxls/ole.h" #define XLS_RECORD_EOF 0x000A #define XLS_RECORD_DEFINEDNAME 0x0018@@ -80,7 +83,7 @@ #define BLANK_CELL XLS_RECORD_BLANK // compat -#ifdef AIX+#if defined(_AIX) || defined(__sun) #pragma pack(1) #else #pragma pack(push, 1)@@ -101,7 +104,6 @@ WORD year; DWORD flags; DWORD min_ver;- BYTE buf[100]; } BIFF; @@ -124,7 +126,7 @@ DWORD filepos; BYTE type; BYTE visible;- BYTE name[];+ char name[1]; } BOUNDSHEET; @@ -184,7 +186,7 @@ WORD row; WORD col; WORD xf;- DWORD_UA value;+ DWORD value; } RK; @@ -194,8 +196,8 @@ WORD col; struct { WORD xf;- DWORD_UA value;- } rk[];+ DWORD value;+ } rk[1]; //WORD last_col; } MULRK;@@ -204,7 +206,7 @@ { WORD row; WORD col;- WORD xf[];+ WORD xf[1]; //WORD last_col; } MULBLANK;@@ -241,7 +243,7 @@ { DWORD num; DWORD numofstr;- BYTE strings;+ BYTE strings[1]; } SST; @@ -289,7 +291,12 @@ WORD width; WORD xf; WORD flags;- WORD notused;+/* There should be an unused WORD field at the end here. However, some files in+ * the wild report it as a BYTE, which results in a boundary-check parse error.+ * Since the value is ignored anyway, we'll just pretend it was never there.+ *+ * See issue https://github.com/evanmiller/libxls/issues/27+ */ } COLINFO; @@ -313,14 +320,14 @@ BYTE family; BYTE charset; BYTE notused;- BYTE name;+ char name[1]; } FONT; typedef struct FORMAT { WORD index;- BYTE value[0];+ char value[1]; } FORMAT; @@ -336,7 +343,7 @@ DWORD filepos; BYTE visibility; BYTE type;- BYTE* name;+ char * name; } * sheet; }@@ -355,7 +362,7 @@ BYTE underline; BYTE family; BYTE charset;- BYTE* name;+ char * name; } * font; }@@ -367,7 +374,7 @@ struct st_format_data { WORD index;- BYTE *value;+ char *value; } * format; }@@ -405,7 +412,7 @@ DWORD lastsz; struct str_sst_string {- BYTE* str;+ char * str; } * string; }@@ -421,7 +428,7 @@ WORD row; WORD col; WORD xf;- BYTE* str; // String value;+ char * str; // String value; double d; int32_t l; WORD width; // Width of col
lib/libxls/include/libxls/xlstool.h view
@@ -1,52 +1,54 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2013 Bob Colbert- * Copyright 2008-2013 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ -#include "libxls/xlsstruct.h"+#include "../libxls/xlsstruct.h" -extern void dumpbuf(BYTE* fname,long size,BYTE* buf);-extern void verbose(char* str);+void verbose(char* str); -extern BYTE *utf8_decode(BYTE *str, DWORD len, char *encoding);-extern BYTE* unicode_decode(const BYTE *s, int len, size_t *newlen, const char* encoding);-extern BYTE* get_string(BYTE *s,BYTE is2, BYTE isUnicode, char *charset);-extern DWORD xls_getColor(const WORD color,WORD def);+char *utf8_decode(const char *str, DWORD len, char *encoding);+char *unicode_decode(const char *s, size_t len, size_t *newlen, const char* encoding);+char *get_string(const char *s, size_t len, BYTE is2, BYTE isUnicode, char *charset);+DWORD xls_getColor(const WORD color,WORD def); -extern void xls_showBookInfo(xlsWorkBook* pWB);-extern void xls_showROW(struct st_row_data* row);-extern void xls_showColinfo(struct st_colinfo_data* col);-extern void xls_showCell(struct st_cell_data* cell);-extern void xls_showFont(struct st_font_data* font);-extern void xls_showXF(XF8* xf);-extern void xls_showFormat(struct st_format_data* format);-extern BYTE* xls_getfcell(xlsWorkBook* pWB,struct st_cell_data* cell,WORD *label);-extern char* xls_getCSS(xlsWorkBook* pWB);-extern void xls_showBOF(BOF* bof);+void xls_showBookInfo(xlsWorkBook* pWB);+void xls_showROW(struct st_row_data* row);+void xls_showColinfo(struct st_colinfo_data* col);+void xls_showCell(struct st_cell_data* cell);+void xls_showFont(struct st_font_data* font);+void xls_showXF(XF8* xf);+void xls_showFormat(struct st_format_data* format);+char* xls_getfcell(xlsWorkBook* pWB, struct st_cell_data* cell, BYTE *label);+char* xls_getCSS(xlsWorkBook* pWB);+void xls_showBOF(BOF* bof);
lib/libxls/include/libxls/xlstypes.h view
@@ -1,70 +1,56 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2013 Bob Colbert- * Copyright 2008-2013 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ #ifndef XLS_TYPES_INC #define XLS_TYPES_INC +#ifdef __cplusplus+#include <cstdint>+#else #include <stdint.h>+#endif+#include <sys/types.h> typedef unsigned char BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; -#ifdef NO_ALIGN-typedef uint16_t WORD_UA;-typedef uint32_t DWORD_UA;-#else-typedef uint16_t WORD_UA __attribute__ ((aligned (1))); // 2 bytes-typedef uint32_t DWORD_UA __attribute__ ((aligned (1))); // 4 bytes-#endif--// Windows-#if defined(_MSC_VER) && defined(WIN32)-+#ifdef _WIN32 typedef unsigned __int64 unsigned64_t;--// not windows #else--#if defined(_UINT64_T)- typedef uint64_t unsigned64_t;--#else--typedef unsigned long long unsigned64_t;--// _UINT64_T-#endif #endif #endif
+ lib/libxls/include/xls.h view
@@ -0,0 +1,91 @@+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *+ *+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013-2018 Evan Miller+ *+ * 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 Evan Miller ''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 THE COPYRIGHT HOLDERS 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.+ *+ */++#ifndef XLS_INCLUDE+#define XLS_INCLUDE+ +#ifdef __cplusplus+namespace xls {+extern "C" {+#endif++#include "libxls/xlstypes.h"+#include "libxls/xlsstruct.h"+#include "libxls/xlstool.h"++typedef enum {+ LIBXLS_OK,+ LIBXLS_ERROR_OPEN,+ LIBXLS_ERROR_SEEK,+ LIBXLS_ERROR_READ,+ LIBXLS_ERROR_PARSE,+ LIBXLS_ERROR_MALLOC+} xls_error_t;++const char* xls_getVersion(void);+const char* xls_getError(xls_error_t code);++int xls(int debug); // Set debug. Force library to load?+void xls_set_formula_hander(xls_formula_handler handler);++xls_error_t xls_parseWorkBook(xlsWorkBook* pWB);+xls_error_t xls_parseWorkSheet(xlsWorkSheet* pWS);++// Preferred API+// charset - convert 16bit strings within the spread sheet to this 8-bit encoding (UTF-8 default)+xlsWorkBook *xls_open_file(const char *file, const char *charset, xls_error_t *outError);+xlsWorkBook *xls_open_buffer(const unsigned char *data, size_t data_len,+ const char *charset, xls_error_t *outError);+void xls_close_WB(xlsWorkBook* pWB);++// Historical API+xlsWorkBook* xls_open(const char *file,const char *charset);+#define xls_close xls_close_WB++xlsWorkSheet * xls_getWorkSheet(xlsWorkBook* pWB,int num);+void xls_close_WS(xlsWorkSheet* pWS);++xlsSummaryInfo *xls_summaryInfo(xlsWorkBook* pWB);+void xls_close_summaryInfo(xlsSummaryInfo *pSI);++// utility function+xlsRow *xls_row(xlsWorkSheet* pWS, WORD cellRow);+xlsCell *xls_cell(xlsWorkSheet* pWS, WORD cellRow, WORD cellCol);++#ifdef __cplusplus+} // extern c block+} // namespace+#endif++#endif+
lib/libxls/src/endian.c view
@@ -1,37 +1,39 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2013 Bob Colbert *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2013 Bob Colbert+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS''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 THE COPYRIGHT HOLDERS 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. * */ #include <stdlib.h> -#include "libxls/xlstypes.h"-#include "libxls/endian.h"-#include "libxls/ole.h"+#include "../include/libxls/xlstypes.h"+#include "../include/libxls/endian.h"+#include "../include/libxls/ole.h" int xls_is_bigendian() {@@ -40,17 +42,9 @@ #elif defined (__LITTLE_ENDIAN__) return 0; #else-#warning NO ENDIAN static int n = 1; - if (*(char *)&n == 1)- {- return 0;- }- else- {- return 1;- }+ return (*(char *)&n == 0); #endif } @@ -93,7 +87,7 @@ for (i=0; i<4; i++) { t = d[7-i];- d[8-i] = d[i];+ d[7-i] = d[i]; d[i] = t; } }@@ -130,8 +124,8 @@ void xlsConvertSst(SST *s) {- s->num=xlsIntVal(s->num);- s->num=xlsIntVal(s->numofstr);+ s->num = xlsIntVal(s->num);+ s->numofstr = xlsIntVal(s->numofstr); } void xlsConvertXf5(XF5 *x)@@ -182,7 +176,6 @@ W_ENDIAN(c->width); W_ENDIAN(c->xf); W_ENDIAN(c->flags);- W_ENDIAN(c->notused); } void xlsConvertRow(ROW *r)@@ -219,12 +212,10 @@ W_ENDIAN(f->xf); if(f->res == 0xFFFF) { switch(f->resid) {- case 0:- case 3:- break;- case 1:- case 2:- W_ENDIAN(*(WORD *)&f->resdata[1]);+ case 0: // string+ case 1: // bool+ case 2: // error+ case 3: // empty string break; default: xlsConvertDouble(&f->resid);@@ -251,10 +242,10 @@ void xlsConvertHeader(OLE2Header *h) {- int i;- for (i=0; i<2; i++)+ unsigned long i;+ for (i=0; i<sizeof(h->id)/sizeof(h->id[0]); i++) h->id[i] = xlsIntVal(h->id[i]);- for (i=0; i<4; i++)+ for (i=0; i<sizeof(h->clid)/sizeof(h->clid[0]); i++) h->clid[i] = xlsIntVal(h->clid[i]); h->verminor = xlsShortVal(h->verminor); h->verdll = xlsShortVal(h->verdll);@@ -275,7 +266,7 @@ h->csfat = xlsIntVal(h->csfat); h->difstart = xlsIntVal(h->difstart); h->cdif = xlsIntVal(h->cdif);- for (i=0; i<109; i++)+ for (i=0; i<sizeof(h->MSAT)/sizeof(h->MSAT[0]); i++) h->MSAT[i] = xlsIntVal(h->MSAT[i]); } @@ -295,21 +286,3 @@ pss->size = xlsIntVal(pss->size); pss->proptype = xlsIntVal(pss->proptype); }--#if 0 // not used?-void xlsConvertUnicode(wchar_t *w, char *s, int len)-{- short *x;- int i;-- x=(short *)s;- w = (wchar_t*)malloc((len+1)*sizeof(wchar_t));-- for(i=0; i<len; i++)- {- w[i]=xlsShortVal(x[i]);- }- w[len] = '\0';-}-#endif-
lib/libxls/src/ole.c view
@@ -1,32 +1,35 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2013 Bob Colbert- * Copyright 2008-2013 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ @@ -38,11 +41,9 @@ #include <stdio.h> #include <stdlib.h> -#include <assert.h>--#include "libxls/ole.h"-#include "libxls/xlstool.h"-#include "libxls/endian.h"+#include "../include/libxls/ole.h"+#include "../include/libxls/xlstool.h"+#include "../include/libxls/endian.h" extern int xls_debug; @@ -53,60 +54,114 @@ static const DWORD ENDOFCHAIN = 0xFFFFFFFE; // -2 static const DWORD FREESECT = 0xFFFFFFFF; // -1 -static size_t sector_pos(OLE2* ole2, size_t sid);-static int sector_read(OLE2* ole2, BYTE *buffer, size_t sid);-static size_t read_MSAT(OLE2* ole2, OLE2Header *oleh);+static size_t sector_pos(OLE2* ole2, DWORD sid);+static ssize_t sector_read(OLE2* ole2, void *buffer, size_t buffer_len, DWORD sid);+static ssize_t read_MSAT(OLE2* ole2, OLE2Header *oleh);+static void *ole_malloc(size_t len);+static void *ole_realloc(void *ptr, size_t len); +static void *ole_malloc(size_t len) {+ if (len > (1<<24) || len == 0) {+ return NULL;+ }+ return malloc(len);+}++static void *ole_realloc(void *ptr, size_t len) {+ if (len > (1<<24) || len == 0) {+ free(ptr);+ return NULL;+ }+ return realloc(ptr, len);+}++static int ole2_validate_sector_chain(DWORD *chain, DWORD chain_count, DWORD chain_start) {+ DWORD count = 0;+ DWORD sector = chain_start;+ while (sector != ENDOFCHAIN) {+ if (sector >= chain_count)+ return 0;+ + if (++count >= chain_count)+ return 0;++ sector = xlsIntVal(chain[sector]);+ }+ return 1;+}++static int ole2_validate_sector(DWORD sector, OLE2 *ole) {+ if (sector >= ole->SecIDCount) {+ if (xls_debug) fprintf(stderr, "Error: fatpos %d out-of-bounds for SecID[%d]\n",+ (int)sector, ole->SecIDCount);+ return 0;+ }++ if (sector == xlsIntVal(ole->SecID[sector])) {+ if (xls_debug) fprintf(stderr, "Error: Sector loop detected, SecID[%d] = %d\n",+ (int)sector, (int)sector);+ return 0;+ }++ return 1;+}+ // Read next sector of stream-void ole2_bufread(OLE2Stream* olest) +static int ole2_bufread(OLE2Stream* olest) { BYTE *ptr; - assert(olest);- assert(olest->ole);+ if (olest == NULL || olest->ole == NULL)+ return -1; if ((DWORD)olest->fatpos!=ENDOFCHAIN) { if(olest->sfat) {- assert(olest->ole->SSAT);- assert(olest->buf);- assert(olest->ole->SSecID);+ if (olest->ole->SSAT == NULL || olest->buf == NULL || olest->ole->SSecID == NULL)+ return -1; + if (olest->fatpos*olest->ole->lssector + olest->bufsize > olest->ole->SSATCount) {+ if (xls_debug) fprintf(stderr, "Error: fatpos %d out-of-bounds for SSAT\n", (int)olest->fatpos);+ return -1;+ }+ ptr = olest->ole->SSAT + olest->fatpos*olest->ole->lssector; memcpy(olest->buf, ptr, olest->bufsize); + if (olest->fatpos >= olest->ole->SSecIDCount) {+ if (xls_debug) fprintf(stderr, "Error: fatpos %d out-of-bounds for SSecID[%d]\n",+ (int)olest->fatpos, olest->ole->SSecIDCount);+ return -1;+ }+ olest->fatpos=xlsIntVal(olest->ole->SSecID[olest->fatpos]); olest->pos=0; olest->cfat++; } else {-- assert(olest->fatpos >= 0);+ if ((int)olest->fatpos < 0 ||+ sector_read(olest->ole, olest->buf, olest->bufsize, olest->fatpos) == -1) {+ if (xls_debug) fprintf(stderr, "Error: Unable to read sector #%d\n", (int)olest->fatpos);+ return -1;+ } - //printf("fatpos: %d max=%u\n",olest->fatpos, (olest->ole->cfat*olest->ole->lsector)/4);- if(olest->fatpos > (olest->ole->cfat*olest->ole->lsector)/4) exit(-1);+ if (!ole2_validate_sector(olest->fatpos, olest->ole)) {+ return -1;+ } -#if 0 // TODO: remove- fseek(olest->ole->file,olest->fatpos*olest->ole->lsector+512,0);- ret = fread(olest->buf,1,olest->bufsize,olest->ole->file);- assert(ret == olest->bufsize);-#endif- assert((int)olest->fatpos >= 0);- sector_read(olest->ole, olest->buf, olest->fatpos);- //printf("Fat val: %d[0x%X]\n",olest->fatpos,olest->ole->SecID[olest->fatpos], olest->ole->SecID[olest->fatpos]);- olest->fatpos=xlsIntVal(olest->ole->SecID[olest->fatpos]);+ olest->fatpos = xlsIntVal(olest->ole->SecID[olest->fatpos]); olest->pos=0; olest->cfat++; } } // else printf("ENDOFCHAIN!!!\n");+ return 0; } // Read part of stream-size_t ole2_read(void* buf,size_t size,size_t count,OLE2Stream* olest)+ssize_t ole2_read(void* buf, size_t size, size_t count, OLE2Stream* olest) { size_t didReadCount=0; size_t totalReadCount;- size_t needToReadCount; totalReadCount=size*count; @@ -124,191 +179,239 @@ //printf(" totalReadCount=%d (rem=%d size*count=%ld)\n", totalReadCount, rem, size*count); } - while ((!olest->eof) && (didReadCount!=totalReadCount))+ while ((!olest->eof) && (didReadCount < totalReadCount)) { unsigned long remainingBytes;+ size_t needToReadCount; needToReadCount = totalReadCount - didReadCount; remainingBytes = olest->bufsize - olest->pos;- //printf(" test: (totalReadCount-didReadCount)=%d (olest->bufsize-olest->pos)=%d\n", (totalReadCount-didReadCount), (olest->bufsize-olest->pos) ); - if (needToReadCount < remainingBytes) // does the current sector contain all the data I need?- {- // printf(" had %d bytes of memory, copy=%d\n", (olest->bufsize-olest->pos), needToReadCount);+ if (needToReadCount < remainingBytes) { // does the current sector contain all the data I need? memcpy((BYTE*)buf + didReadCount, olest->buf + olest->pos, needToReadCount); olest->pos += needToReadCount; didReadCount += needToReadCount; } else {- // printf(" had %d bytes of memory, copy=%d\n", remainingBytes, remainingBytes); memcpy((BYTE*)buf + didReadCount, olest->buf + olest->pos, remainingBytes); olest->pos += remainingBytes; didReadCount += remainingBytes;- ole2_bufread(olest);+ if (ole2_bufread(olest) == -1)+ return -1; }- assert(didReadCount <= totalReadCount);- //printf(" if(fatpos=0x%X==EOC=0x%X) && (pos=%d >= bufsize=%d)\n", olest->fatpos, ENDOFCHAIN, olest->pos, olest->bufsize);- if (((DWORD)olest->fatpos == ENDOFCHAIN) && (olest->pos >= olest->bufsize))- {+ if (((DWORD)olest->fatpos == ENDOFCHAIN) && (olest->pos >= olest->bufsize)) { olest->eof=1; }-- //printf(" eof=%d (didReadCount=%ld != totalReadCount=%ld)\n", olest->eof, didReadCount, totalReadCount); }+ if (didReadCount > totalReadCount)+ return -1;+ // printf(" didReadCount=%ld EOF=%d\n", didReadCount, olest->eof); // printf("=====\n"); #ifdef OLE_DEBUG- printf("----------------------------------------------\n");- printf("ole2_read (end)\n");- printf("start: %li \n",olest->start);- printf("pos: %li \n",olest->pos);- printf("cfat: %d \n",olest->cfat);- printf("size: %d \n",olest->size);- printf("fatpos: %li \n",olest->fatpos);- printf("bufsize: %li \n",olest->bufsize);- printf("eof: %d \n",olest->eof);+ fprintf(stderr, "----------------------------------------------\n");+ fprintf(stderr, "ole2_read (end)\n");+ fprintf(stderr, "start: %d \n",olest->start);+ fprintf(stderr, "pos: %d \n",(int)olest->pos);+ fprintf(stderr, "cfat: %d \n",(int)olest->cfat);+ fprintf(stderr, "size: %d \n",(int)olest->size);+ fprintf(stderr, "fatpos: %d \n",(int)olest->fatpos);+ fprintf(stderr, "bufsize: %d \n",(int)olest->bufsize);+ fprintf(stderr, "eof: %d \n",olest->eof); #endif - return(didReadCount);+ return didReadCount; } // Open stream in logical ole file OLE2Stream* ole2_sopen(OLE2* ole,DWORD start, size_t size) { OLE2Stream* olest=NULL;+ int success = 1; #ifdef OLE_DEBUG- printf("----------------------------------------------\n");- printf("ole2_sopen start=%lXh\n", start);+ fprintf(stderr, "----------------------------------------------\n");+ fprintf(stderr, "ole2_sopen start=%Xh\n", start); #endif - olest=(OLE2Stream*)calloc(1, sizeof(OLE2Stream));- olest->ole=ole;- olest->size=size;- olest->fatpos=start;- olest->start=start;- olest->pos=0;- olest->eof=0;- olest->cfat=-1;- if((long)size > 0 && size < (size_t)ole->sectorcutoff) {- olest->bufsize=ole->lssector;- olest->sfat = 1;- } else {- olest->bufsize=ole->lsector;- }- olest->buf=malloc(olest->bufsize);- ole2_bufread(olest);+ olest = calloc(1, sizeof(OLE2Stream));+ olest->ole=ole;+ olest->size=size;+ olest->fatpos=start;+ olest->start=start;+ olest->cfat=-1;+ if((long)size > 0 && size < (size_t)ole->sectorcutoff) {+ olest->bufsize=ole->lssector;+ olest->sfat = 1;+ } else {+ olest->bufsize=ole->lsector;+ }+ if ((olest->buf = ole_malloc(olest->bufsize)) == NULL) {+ success = 0;+ goto cleanup;+ } + if (olest->sfat) {+ if (!ole2_validate_sector_chain(ole->SSecID, ole->SSecIDCount, start)) {+ success = 0;+ goto cleanup;+ }+ } else {+ if (!ole2_validate_sector_chain(ole->SecID, ole->SecIDCount, start)) {+ success = 0;+ goto cleanup;+ }+ }++ if (ole2_bufread(olest) == -1) {+ success = 0;+ goto cleanup;+ }++cleanup:+ if (!success) {+ ole2_fclose(olest);+ olest = NULL;+ }+ // if(xls_debug) printf("sopen: sector=%d next=%d\n", start, olest->fatpos); return olest; } // Move in stream-void ole2_seek(OLE2Stream* olest,DWORD ofs)+int ole2_seek(OLE2Stream* olest,DWORD ofs) {+#ifdef OLE_DEBUG+ fprintf(stderr, "SEEK %x\n", ofs);+#endif if(olest->sfat) { ldiv_t div_rez=ldiv(ofs,olest->ole->lssector); int i; olest->fatpos=olest->start; - if (div_rez.quot!=0)- {- for (i=0;i<div_rez.quot;i++)- olest->fatpos=xlsIntVal(olest->ole->SSecID[olest->fatpos]);- }+ if (div_rez.quot!=0)+ {+ for (i=0;i<div_rez.quot;i++) {+ if (olest->fatpos >= olest->ole->SSecIDCount)+ return -1;+ olest->fatpos=xlsIntVal(olest->ole->SSecID[olest->fatpos]);+ }+ } - ole2_bufread(olest);- olest->pos=div_rez.rem;- olest->eof=0;- olest->cfat=div_rez.quot;+ if (ole2_bufread(olest) == -1)+ return -1;++ olest->pos=div_rez.rem;+ olest->eof=0;+ olest->cfat=div_rez.quot; //printf("%i=%i %i\n",ofs,div_rez.quot,div_rez.rem); } else { ldiv_t div_rez=ldiv(ofs,olest->ole->lsector); int i;+#ifdef OLE_DEBUG+ fprintf(stderr, "seeking fatpos%lu start %u\n", olest->fatpos, olest->start);+#endif olest->fatpos=olest->start; - if (div_rez.quot!=0)- {- for (i=0;i<div_rez.quot;i++)- olest->fatpos=xlsIntVal(olest->ole->SecID[olest->fatpos]);- }+ if (div_rez.quot!=0)+ {+ for (i=0;i<div_rez.quot;i++) {+ if (!ole2_validate_sector(olest->fatpos, olest->ole))+ return -1;+ olest->fatpos=xlsIntVal(olest->ole->SecID[olest->fatpos]);+ }+ } - ole2_bufread(olest);+ if (ole2_bufread(olest) == -1)+ return -1;+ olest->pos=div_rez.rem; olest->eof=0; olest->cfat=div_rez.quot; //printf("%i=%i %i\n",ofs,div_rez.quot,div_rez.rem); }+ return 0; } // Open logical file contained in physical OLE file-OLE2Stream* ole2_fopen(OLE2* ole,BYTE* file)+OLE2Stream* ole2_fopen(OLE2* ole, const char *file) {- OLE2Stream* olest; int i; #ifdef OLE_DEBUG- printf("----------------------------------------------\n");- printf("ole2_fopen %s\n", file);+ fprintf(stderr, "----------------------------------------------\n");+ fprintf(stderr, "ole2_fopen %s\n", file); #endif for (i=0;i<ole->files.count;i++) {- BYTE *str = ole->files.file[i].name;+ char *str = ole->files.file[i].name; #ifdef OLE_DEBUG- printf("----------------------------------------------\n");- printf("ole2_fopen found %s\n", str);+ fprintf(stderr, "----------------------------------------------\n");+ fprintf(stderr, "ole2_fopen found %s\n", str); #endif- 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+ if (str && strcmp(str,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 ole2_sopen(ole,ole->files.file[i].start,ole->files.file[i].size); } }- return(NULL);+ return NULL; } -// Open physical file-OLE2* ole2_open(const BYTE *file)-{- //BYTE buf[1024];- OLE2Header* oleh;- OLE2* ole;- OLE2Stream* olest;- PSS* pss;- BYTE* name = NULL;+static int ole2_fseek(OLE2 *ole2, size_t pos) {+ if (ole2->file)+ return fseek(ole2->file, pos, SEEK_SET); -#ifdef OLE_DEBUG- printf("----------------------------------------------\n");- printf("ole2_open %s\n", file);-#endif+ if (pos > ole2->buffer_len)+ return -1; - 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);+ ole2->buffer_pos = pos;+ return 0;+}++static size_t ole2_fread(OLE2 *ole2, void *buffer, size_t buffer_len, size_t size) {+ if (size > buffer_len)+ return 0;++ if (ole2->file)+ return fread(buffer, size, 1, ole2->file);++ if (ole2->buffer_pos + size > ole2->buffer_len)+ return 0;++ memcpy(buffer, (const char *)ole2->buffer + ole2->buffer_pos, size);+ ole2->buffer_pos += size;++ return 1;+}++// read header and check magic numbers+static ssize_t ole2_read_header(OLE2 *ole) {+ ssize_t bytes_read = 0, total_bytes_read = 0;+ OLE2Header *oleh = malloc(sizeof(OLE2Header));+ if (ole2_fread(ole, oleh, sizeof(OLE2Header), sizeof(OLE2Header)) != 1) {+ total_bytes_read = -1;+ goto cleanup; }- // read header and check magic numbers- oleh=(OLE2Header*)malloc(512);- fread(oleh,1,512,ole->file);+ total_bytes_read += sizeof(OLE2Header); 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;+ if (xls_debug) fprintf(stderr, "Not an excel file\n");+ total_bytes_read = -1;+ goto cleanup; } //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++ if (oleh->lsectorB != 9 || oleh->lssectorB != 6) { // 2**9 == 512, 2**6 == 64+ if (xls_debug) fprintf(stderr, "Unexpected sector size\n");+ total_bytes_read = -1;+ goto cleanup;+ } ole->cfat=oleh->cfat; ole->dirstart=oleh->dirstart;@@ -320,52 +423,71 @@ ole->files.count=0; #ifdef OLE_DEBUG- printf("==== OLE HEADER ====\n");+ fprintf(stderr, "==== 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);+ fprintf(stderr, "verminor: %X \n",oleh->verminor);+ fprintf(stderr, "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);+ fprintf(stderr, "sect len: %X (%i)\n",ole->lsector,ole->lsector); // ole+ fprintf(stderr, "mini len: %X (%i)\n",ole->lssector,ole->lssector); // ole+ fprintf(stderr, "Fat sect.: %i \n",oleh->cfat);+ fprintf(stderr, "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);+ fprintf(stderr, "Mini Cutoff: %i \n",oleh->sectorcutoff);+ fprintf(stderr, "MiniFat Start: %X \n",oleh->sfatstart);+ fprintf(stderr, "Count MFat: %i \n",oleh->csfat);+ fprintf(stderr, "Dif start: %X \n",oleh->difstart);+ fprintf(stderr, "Count Dif: %i \n",oleh->cdif);+ fprintf(stderr, "Fat Size: %u (0x%X) \n",oleh->cfat*ole->lsector,oleh->cfat*ole->lsector); #endif // read directory entries- read_MSAT(ole, oleh);+ if ((bytes_read = read_MSAT(ole, oleh)) == -1) {+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += bytes_read; +cleanup:+ free(oleh);++ return total_bytes_read;+}++static ssize_t ole2_read_body(OLE2 *ole) { // 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);+ PSS *pss = NULL;+ OLE2Stream *olest = NULL;+ char* name = NULL;+ ssize_t bytes_read = 0, total_bytes_read = 0;++ if ((olest = ole2_sopen(ole,ole->dirstart, -1)) == NULL) {+ total_bytes_read = -1;+ goto cleanup;+ }+ pss = malloc(sizeof(PSS));+ do {+ if ((bytes_read = ole2_read(pss,1,sizeof(PSS),olest)) == -1) {+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += bytes_read; xlsConvertPss(pss);+ if (pss->bsize > sizeof(pss->name)) {+ total_bytes_read = -1;+ goto cleanup;+ } name=unicode_decode(pss->name, pss->bsize, 0, "UTF-8"); #ifdef OLE_DEBUG - printf("OLE NAME: %s count=%d\n", name, ole->files.count);+ fprintf(stderr, "OLE NAME: %s count=%d\n", name, (int)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);+ fprintf(stderr, "OLE TYPE: %s file=%d \n", pss->type == PS_USER_ROOT ? "root" : "user", (int)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 = 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;@@ -373,70 +495,130 @@ if(pss->sstart == ENDOFCHAIN) { if (xls_debug) verbose("END OF CHAIN\n");- } else- if(pss->type == PS_USER_STREAM) {+ } 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],+ fprintf(stderr, "----------------------------------------------\n");+ fprintf(stderr, "name: %s (size=%d [c=%c])\n", name, pss->bsize, name ? name[0]:' ');+ fprintf(stderr, "bsize %i\n",pss->bsize);+ fprintf(stderr, "type %i\n",pss->type);+ fprintf(stderr, "flag %i\n",pss->flag);+ fprintf(stderr, "left %X\n",pss->left);+ fprintf(stderr, "right %X\n",pss->right);+ fprintf(stderr, "child %X\n",pss->child);+ fprintf(stderr, "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);+ fprintf(stderr, "user flag %.4X\n",pss->userflags);+ fprintf(stderr, "sstart %.4d\n",pss->sstart);+ fprintf(stderr, "size %.4d\n",pss->size); #endif- } else- if(pss->type == PS_USER_ROOT) {+ } else if(pss->type == PS_USER_ROOT) { DWORD sector, k, blocks; BYTE *wptr;+ size_t bytes_left; blocks = (pss->size + (ole->lsector - 1)) / ole->lsector; // count partial- ole->SSAT = (BYTE *)malloc(blocks*ole->lsector);+ if ((ole->SSAT = ole_realloc(ole->SSAT, blocks*ole->lsector)) == NULL) {+ total_bytes_read = -1;+ goto cleanup;+ }+ ole->SSATCount = blocks*ole->lsector; // printf("blocks %d\n", blocks); - assert(ole->SSecID);- sector = pss->sstart;- wptr=(BYTE*)ole->SSAT;+ wptr = (BYTE*)ole->SSAT;+ bytes_left = blocks*ole->lsector; 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);+ if (sector == ENDOFCHAIN || sector_read(ole, wptr, bytes_left, sector) == -1) {+ if (xls_debug) fprintf(stderr, "Unable to read sector #%d\n", sector);+ total_bytes_read = -1;+ goto cleanup;+ }+ if (!ole2_validate_sector(sector, ole)) {+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += ole->lsector; wptr += ole->lsector;+ bytes_left -= ole->lsector; sector = xlsIntVal(ole->SecID[sector]); } } } else { free(name); }+ } while (!olest->eof);++cleanup:+ if (olest)+ ole2_fclose(olest);+ if (pss)+ free(pss);++ return total_bytes_read;+}++OLE2 *ole2_read_header_and_body(OLE2 *ole) {+ if (ole2_read_header(ole) == -1) {+ ole2_close(ole);+ return NULL; }- while (!olest->eof); - ole2_fclose(olest);- free(pss);+ if (ole2_read_body(ole) == -1) {+ ole2_close(ole);+ return NULL;+ } return ole; } +// Open in-memory buffer+OLE2 *ole2_open_buffer(const void *buffer, size_t len) {+ OLE2 *ole = calloc(1, sizeof(OLE2));++ ole->buffer = buffer;+ ole->buffer_len = len;++ return ole2_read_header_and_body(ole);+}++// Open physical file+OLE2* ole2_open_file(const char *file)+{+ OLE2* ole = NULL;++#ifdef OLE_DEBUG+ fprintf(stderr, "----------------------------------------------\n");+ fprintf(stderr, "ole2_open_file %s\n", file);+#endif++ if(xls_debug) printf("ole2_open: %s\n", file);+ ole = calloc(1, sizeof(OLE2));++ if (!(ole->file=fopen(file, "rb"))) {+ if(xls_debug) fprintf(stderr, "File not found\n");+ free(ole);+ return NULL;+ }++ return ole2_read_header_and_body(ole);+}+ void ole2_close(OLE2* ole2) { int i;- fclose(ole2->file);+ if (ole2->file)+ fclose(ole2->file); - for(i=0; i<ole2->files.count; ++i) {- free(ole2->files.file[i].name);- }- free(ole2->files.file);- free(ole2->SecID);- free(ole2->SSecID);- free(ole2->SSAT);- free(ole2);+ for(i=0; i<ole2->files.count; ++i) {+ free(ole2->files.file[i].name);+ }+ free(ole2->files.file);+ free(ole2->SecID);+ free(ole2->SSecID);+ free(ole2->SSAT);+ free(ole2); } void ole2_fclose(OLE2Stream* ole2st)@@ -446,117 +628,205 @@ } // Return offset in bytes of a sector from its sid-static size_t sector_pos(OLE2* ole2, size_t sid)+static size_t sector_pos(OLE2* ole2, DWORD sid) { return 512 + sid * ole2->lsector; } // Read one sector from its sid-static int sector_read(OLE2* ole2, BYTE *buffer, size_t sid)+static ssize_t sector_read(OLE2* ole2, void *buffer, size_t buffer_len, DWORD sid) { size_t num; size_t seeked; - //printf("sector_read: sid=%zu (0x%zx) lsector=%u sector_pos=%zu\n", sid, sid, ole2->lsector, sector_pos(ole2, sid) );- seeked = fseek(ole2->file, sector_pos(ole2, sid), SEEK_SET);- if(seeked != 0) {- printf("seek: wanted to seek to sector %zu (0x%zx) loc=%zu\n", sid, sid, sector_pos(ole2, sid));- }- assert(seeked == 0);- - num = fread(buffer, ole2->lsector, 1, ole2->file);- if(num != 1) {- fprintf(stderr, "fread: wanted 1 got %zu loc=%zu\n", num, sector_pos(ole2, sid));- }- assert(num == 1);+ if ((seeked = ole2_fseek(ole2, sector_pos(ole2, sid))) != 0) {+ if (xls_debug) fprintf(stderr, "Error: wanted to seek to sector %u (0x%x) loc=%u\n", sid, sid,+ (unsigned int)sector_pos(ole2, sid));+ return -1;+ } - return 0;-}+ if ((num = ole2_fread(ole2, buffer, buffer_len, ole2->lsector)) != 1) {+ if (xls_debug) fprintf(stderr, "Error: fread wanted 1 got %lu loc=%u\n", (unsigned long)num,+ (unsigned int)sector_pos(ole2, sid));+ return -1;+ } -// Read MSAT-static size_t read_MSAT(OLE2* ole2, OLE2Header* oleh)-{- int sectorNum;+ return ole2->lsector;+} - // reconstitution of the MSAT- ole2->SecID=malloc(ole2->cfat*ole2->lsector);+// read first 109 sectors of MSAT from header+static ssize_t read_MSAT_header(OLE2* ole2, OLE2Header* oleh, DWORD sectorCount) {+ BYTE *sector = (BYTE*)ole2->SecID;+ ssize_t bytes_read = 0, total_bytes_read = 0;+ size_t bytes_left = ole2->SecIDCount * sizeof(DWORD);+ DWORD sectorNum; - // read first 109 sectors of MSAT from header+ for (sectorNum = 0; sectorNum < sectorCount && sectorNum < 109; sectorNum++) {- int count;- count = (ole2->cfat < 109) ? ole2->cfat : 109;- for (sectorNum = 0; sectorNum < count; sectorNum++)- {- assert(sectorNum >= 0);- sector_read(ole2, (BYTE*)(ole2->SecID)+sectorNum*ole2->lsector, oleh->MSAT[sectorNum]);+ if ((bytes_read = sector_read(ole2, sector, bytes_left, oleh->MSAT[sectorNum])) == -1) {+ if (xls_debug) fprintf(stderr, "Error: Unable to read sector #%d\n", oleh->MSAT[sectorNum]);+ return -1; }+ sector += ole2->lsector;+ bytes_left -= ole2->lsector;+ total_bytes_read += bytes_read; }+ return total_bytes_read;+} - // Add additionnal sectors of the MSAT- {- DWORD sid = ole2->difstart;+// Add additional sectors of the MSAT+static ssize_t read_MSAT_body(OLE2 *ole2, DWORD sectorOffset, DWORD sectorCount) {+ DWORD sid = ole2->difstart;+ ssize_t bytes_read = 0, total_bytes_read = 0;+ DWORD sectorNum = sectorOffset; - BYTE *sector = malloc(ole2->lsector);- //printf("sid=%u (0x%x) sector=%u\n", sid, sid, ole2->lsector);- while (sid != ENDOFCHAIN && sid != FREESECT) // FREESECT only here due to an actual file that requires it (old Apple Numbers bug)- {- int posInSector;- // read MSAT sector- sector_read(ole2, sector, sid);+ DWORD *sector = ole_malloc(ole2->lsector);+ //printf("sid=%u (0x%x) sector=%u\n", sid, sid, ole2->lsector);+ while (sid != ENDOFCHAIN && sid != FREESECT) // FREESECT only here due to an actual file that requires it (old Apple Numbers bug)+ {+ int posInSector;+ // read MSAT sector+ if ((bytes_read = sector_read(ole2, sector, ole2->lsector, sid)) == -1) {+ total_bytes_read = -1;+ if (xls_debug) fprintf(stderr, "Error: Unable to read sector #%d\n", sid);+ goto cleanup;+ }+ total_bytes_read += bytes_read; - // read content- for (posInSector = 0; posInSector < (ole2->lsector-4)/4; posInSector++)- {- DWORD s = *(DWORD_UA *)(sector + posInSector*4);- //printf(" s[%d]=%d (0x%x)\n", posInSector, s, s);+ // read content+ for (posInSector = 0; posInSector < (ole2->lsector-4)/4; posInSector++)+ {+ DWORD s = sector[posInSector];+ //printf(" s[%d]=%d (0x%x)\n", posInSector, s, s); - if (s != FREESECT)- {- sector_read(ole2, (BYTE*)(ole2->SecID)+sectorNum*ole2->lsector, s);- sectorNum++;+ if (s != ENDOFCHAIN && s != FREESECT) // see patch in Bug 31. For very large files+ {+ if (sectorNum == sectorCount) {+ if (xls_debug) fprintf(stderr, "Error: Unable to seek to sector #%d\n", s);+ total_bytes_read = -1;+ goto cleanup; }- }- sid = *(DWORD_UA *)(sector + posInSector*4);- //printf(" s[%d]=%d (0x%x)\n", posInSector, sid, sid);- }- free(sector);+ if ((bytes_read = sector_read(ole2, (BYTE*)(ole2->SecID)+sectorNum*ole2->lsector,+ (ole2->SecIDCount * sizeof(DWORD) - sectorNum*ole2->lsector), s)) == -1) {+ if (xls_debug) fprintf(stderr, "Error: Unable to read sector #%d\n", s);+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += bytes_read;+ sectorNum++;+ }+ }+ sid = sector[posInSector];+ //printf(" s[%d]=%d (0x%x)\n", posInSector, sid, sid); } #ifdef OLE_DEBUG- if(xls_debug) {- //printf("==== READ IN SECTORS FOR MSAT TABLE====\n");- int i;- for(i=0; i<512/4; ++i) { // just the first block- if(ole2->SecID[i] != FREESECT) printf("SecID[%d]=%d\n", i, ole2->SecID[i]);- }- }- //exit(0);+ if(xls_debug) {+ //printf("==== READ IN SECTORS FOR MSAT TABLE====\n");+ int i;+ for(i=0; i<512/4; ++i) { // just the first block+ if(ole2->SecID[i] != FREESECT) printf("SecID[%d]=%d\n", i, ole2->SecID[i]);+ }+ }+ //exit(0); #endif - // read in short table- if(ole2->sfatstart != ENDOFCHAIN) {- DWORD sector, k;- BYTE *wptr;- - ole2->SSecID = (DWORD *)malloc(ole2->csfat*ole2->lsector);- sector = ole2->sfatstart;- wptr=(BYTE*)ole2->SSecID;- for(k=0; k<ole2->csfat; ++k) {- assert(sector != ENDOFCHAIN);- fseek(ole2->file,sector*ole2->lsector+512,0);- fread(wptr,1,ole2->lsector,ole2->file);- wptr += ole2->lsector;- sector = ole2->SecID[sector];- }+cleanup:+ free(sector);+ return total_bytes_read;+}++// read in short table+static ssize_t read_MSAT_trailer(OLE2 *ole2) {+ ssize_t total_bytes_read = 0;+ DWORD sector, k;+ BYTE *wptr;+ size_t bytes_left;++ if(ole2->sfatstart == ENDOFCHAIN)+ return 0;++ if ((ole2->SSecID = ole_malloc(ole2->csfat*(size_t)ole2->lsector)) == NULL) {+ return -1;+ }+ ole2->SSecIDCount = ole2->csfat*(size_t)ole2->lsector/4;+ sector = ole2->sfatstart;+ wptr=(BYTE*)ole2->SSecID;+ bytes_left = ole2->SSecIDCount * sizeof(DWORD);+ for(k=0; k<ole2->csfat; ++k) {+ if (sector == ENDOFCHAIN || sector_read(ole2, wptr, bytes_left, sector) == -1) {+ total_bytes_read = -1;+ goto cleanup;+ }+ if (!ole2_validate_sector(sector, ole2)) {+ total_bytes_read = -1;+ goto cleanup;+ }+ wptr += ole2->lsector;+ bytes_left -= ole2->lsector;+ total_bytes_read += ole2->lsector;+ sector = xlsIntVal(ole2->SecID[sector]);+ } #ifdef OLE_DEBUG- if(xls_debug) {- int i;- for(i=0; i<512/4; ++i) {- if(ole2->SSecID[i] != FREESECT) printf("SSecID[%d]=%d\n", i, ole2->SSecID[i]);- }- }+ if(xls_debug) {+ int i;+ for(i=0; i<ole2->csfat; ++i) {+ if(ole2->SSecID[i] != FREESECT) fprintf(stderr, "SSecID[%d]=%d\n", i, ole2->SSecID[i]);+ }+ } #endif- } - return 0;+cleanup:+ return total_bytes_read; } +// Read MSAT+static ssize_t read_MSAT(OLE2* ole2, OLE2Header* oleh)+{+ // reconstitution of the MSAT+ DWORD count = ole2->cfat;+ if(count == 0 || count > (1 << 24)) {+ if (xls_debug) fprintf(stderr, "Error: MSAT count %u out-of-bounds\n", count);+ return -1;+ }++ ssize_t total_bytes_read = 0;+ ssize_t bytes_read = 0;++ ole2->SecIDCount = count*ole2->lsector/4;+ if ((ole2->SecID = ole_malloc(ole2->SecIDCount * sizeof(DWORD))) == NULL) {+ total_bytes_read = -1;+ goto cleanup;+ }++ if ((bytes_read = read_MSAT_header(ole2, oleh, count)) == -1) {+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += bytes_read;++ if ((bytes_read = read_MSAT_body(ole2, total_bytes_read / ole2->lsector, count)) == -1) {+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += bytes_read;++ if ((bytes_read = read_MSAT_trailer(ole2)) == -1) {+ total_bytes_read = -1;+ goto cleanup;+ }+ total_bytes_read += bytes_read;++cleanup:+ if (total_bytes_read == -1) {+ if (ole2->SecID) {+ free(ole2->SecID);+ ole2->SecID = NULL;+ }+ if (ole2->SSecID) {+ free(ole2->SSecID);+ ole2->SSecID = NULL;+ }+ }++ return total_bytes_read;+}
lib/libxls/src/xls.c view
@@ -1,2184 +1,1775 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * 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 <stdio.h>-#include <stdlib.h>-#include <errno.h>--#include <memory.h>-#include <math.h>-#include <sys/types.h>-#include <string.h>-#include <wchar.h>-#include <assert.h>--#include "libxls/endian.h"-#include "libxls/xls.h"--#ifndef min-#define min(a,b) ((a) < (b) ? (a) : (b))-#endif--/* #define DEBUG_DRAWINGS */-int xls_debug = 0;--static double NumFromRk(DWORD_UA drk);-static xls_formula_handler formula_handler;--extern void xls_addSST(xlsWorkBook* pWB,SST* sst,DWORD size);-extern void xls_appendSST(xlsWorkBook* pWB,BYTE* buf,DWORD size);-extern void xls_addFormat(xlsWorkBook* pWB,FORMAT* format);-extern BYTE* xls_addSheet(xlsWorkBook* pWB,BOUNDSHEET* bs);-extern void xls_addRow(xlsWorkSheet* pWS,ROW* row);-extern void xls_makeTable(xlsWorkSheet* pWS);-extern struct st_cell_data *xls_addCell(xlsWorkSheet* pWS,BOF* bof,BYTE* buf);-extern BYTE *xls_addFont(xlsWorkBook* pWB,FONT* font);-extern void xls_addXF8(xlsWorkBook* pWB,XF8* xf);-extern void xls_addXF5(xlsWorkBook* pWB,XF5* xf);-extern void xls_addColinfo(xlsWorkSheet* pWS,COLINFO* colinfo);-extern void xls_mergedCells(xlsWorkSheet* pWS,BOF* bof,BYTE* buf);-extern void xls_parseWorkBook(xlsWorkBook* pWB);-extern void xls_preparseWorkSheet(xlsWorkSheet* pWS);-extern void xls_formatColumn(xlsWorkSheet* pWS);-extern void xls_parseWorkSheet(xlsWorkSheet* pWS);-extern void xls_dumpSummary(char *buf,int isSummary,xlsSummaryInfo *pSI);--#ifdef AIX-#pragma pack(1)-#else-#pragma pack(push, 1)-#endif--typedef struct {- uint32_t format[4];- uint32_t offset;-} sectionList;--typedef struct {- uint16_t sig;- uint16_t _empty;- uint32_t os;- uint32_t format[4];- uint32_t count;- sectionList secList[0];-} header;--typedef struct {- uint32_t propertyID;- uint32_t sectionOffset;-} propertyList;--typedef struct {- uint32_t length;- uint32_t numProperties;- propertyList properties[0];-} sectionHeader;--typedef struct {- uint32_t propertyID;- uint32_t data[0];-} property;--#ifdef DEBUG_DRAWINGS-struct drawHeader {- unsigned int rec : 4;- unsigned int instance : 12;- unsigned int type : 16;- unsigned int len : 32;-};--static char *formData;-static char *formFunc;-static struct drawHeader drawProc(uint8_t *buf, uint32_t maxLen, uint32_t *off, int level);-static void dumpRec(char *comment, struct drawHeader *h, int len, uint8_t *buf);-static int finder(uint8_t *buf, uint32_t len, uint16_t pattern);-static uint32_t sheetOffset;-#endif--#pragma pack(pop)--int xls(int debug)-{- xls_debug = debug;- return 1;-}--void xls_addSST(xlsWorkBook* pWB,SST* sst,DWORD size)-{- verbose("xls_addSST");-- pWB->sst.continued=0;- pWB->sst.lastln=0;- pWB->sst.lastid=0;- pWB->sst.lastrt=0;- pWB->sst.lastsz=0;-- pWB->sst.count = sst->num;- pWB->sst.string =(struct str_sst_string *)calloc(pWB->sst.count, sizeof(struct str_sst_string));- xls_appendSST(pWB,&sst->strings,size-8);-}--void xls_appendSST(xlsWorkBook* pWB,BYTE* buf,DWORD size)-{- DWORD ln; // String character count- DWORD ofs; // Current offset in SST buffer- DWORD rt; // Count of rich text formatting runs- DWORD sz; // Size of asian phonetic settings block- BYTE flag; // String flags- BYTE* ret;-- if (xls_debug) {- printf("xls_appendSST %u\n", size);- }-- sz = rt = ln = 0; // kch- ofs=0;-- while(ofs<size)- {- int ln_toread;-- // Restore state when we're in a continue record- // or read string length- if (pWB->sst.continued)- {- ln=pWB->sst.lastln;- rt=pWB->sst.lastrt;- sz=pWB->sst.lastsz;- }- else- {- ln=xlsShortVal(*(WORD_UA *)(buf+ofs));- rt = 0;- sz = 0;-- ofs+=2;- }-- if (xls_debug) {- printf("ln=%u\n", ln);- }-- // Read flags- if ( (!pWB->sst.continued) || ( (pWB->sst.continued) && (ln != 0) ) )- {- flag=*(BYTE *)(buf+ofs);- ofs++;-- // Count of rich text formatting runs- if (flag & 0x8)- {- rt=xlsShortVal(*(WORD_UA *)(buf+ofs));- ofs+=2;- }-- // Size of asian phonetic settings block- if (flag & 0x4)- {- sz=xlsIntVal(*(DWORD_UA *)(buf+ofs));- ofs+=4;-- if (xls_debug) {- printf("sz=%u\n", sz);- }- }- }- else- {- flag = 0;- }-- // Read characters (compressed or not)- ln_toread = 0;- if (ln > 0)- {- if (flag & 0x1)- {- size_t new_len = 0;- ln_toread = min((size-ofs)/2, ln);- ret=unicode_decode(buf+ofs,ln_toread*2,&new_len,pWB->charset);-- if (ret == NULL)- {- ret = (BYTE *)strdup("*failed to decode utf16*");- new_len = strlen((char *)ret);- }-- ret = (BYTE *)realloc(ret,new_len+1);- *(BYTE*)(ret+new_len)=0;-- ln -= ln_toread;- ofs+=ln_toread*2;-- if (xls_debug) {- printf("String16SST: %s(%zd)\n",ret,new_len);- }- }- else- {- ln_toread = min((size-ofs), ln);-- ret = utf8_decode((buf+ofs), ln_toread, pWB->charset);-- ln -= ln_toread;- ofs +=ln_toread;-- if (xls_debug) {- printf("String8SST: %s(%u) \n",ret,ln);- }- }- }- else- {- ret = (BYTE *)strdup("");- }-- if ( (ln_toread > 0)- ||(!pWB->sst.continued) )- {- // Concat string if it's a continue, or add string in table- if (!pWB->sst.continued)- {- pWB->sst.lastid++;- pWB->sst.string[pWB->sst.lastid-1].str=ret;- }- else- {- BYTE *tmp;- tmp=pWB->sst.string[pWB->sst.lastid-1].str;- tmp=(BYTE *)realloc(tmp,strlen((char *)tmp)+strlen((char *)ret)+1);- pWB->sst.string[pWB->sst.lastid-1].str=tmp;- memcpy(tmp+strlen((char *)tmp),ret,strlen((char *)ret)+1);- free(ret);- }-- if (xls_debug) {- printf("String %4u: %s<end>\n", pWB->sst.lastid-1, pWB->sst.string[pWB->sst.lastid-1].str);- }- }-- // Jump list of rich text formatting runs- if ( (ofs < size)- &&(rt > 0) )- {- int rt_toread = min((size-ofs)/4, rt);- rt -= rt_toread;- ofs += rt_toread*4;- }-- // Jump asian phonetic settings block- if ( (ofs < size)- &&(sz > 0) )- {- int sz_toread = min((size-ofs), sz);- sz -= sz_toread;- ofs += sz_toread;- }-- pWB->sst.continued=0;- }-- // Save current character count and count of rich text formatting runs and size of asian phonetic settings block- if (ln > 0 || rt > 0 || sz > 0) {- pWB->sst.continued = 1;- pWB->sst.lastln = ln;- pWB->sst.lastrt = rt;- pWB->sst.lastsz = sz;-- if (xls_debug) {- printf("continued: ln=%u, rt=%u, sz=%u\n", ln, rt, sz);- }- }-}--static double NumFromRk(DWORD_UA drk)-{- double ret;-- // What kind of value is this ?- if (drk & 0x02) {- // Integer value- int tmp = (int)drk >> 2; // cast to keep it negative in < 0- ret = (double)tmp;- } else {- // Floating point value;- unsigned64_t tmp = drk & 0xfffffffc;- tmp <<= 32;- memcpy(&ret, &tmp, sizeof(unsigned64_t));- }- // Is value multiplied by 100 ?- if (drk & 0x01) {- ret /= 100.0;- }- return ret;-}--BYTE* xls_addSheet(xlsWorkBook* pWB, BOUNDSHEET *bs)-{- BYTE* name;- DWORD filepos;- BYTE visible, type;-- filepos = bs->filepos;- visible = bs->visible;- type = bs->type;-- // printf("charset=%s uni=%d\n", pWB->charset, unicode);- // printf("bs name %.*s\n", bs->name[0], bs->name+1);- name=get_string(bs->name, 0, pWB->is5ver, pWB->charset);- // printf("name=%s\n", name);-- if(xls_debug) {- printf ("xls_addSheet[0x%x]\n", type);- switch (type & 0x0f)- {- case 0x00:- /* worksheet or dialog sheet */- printf ("85: Worksheet or dialog sheet\n");- break;- case 0x01:- /* Microsoft Excel 4.0 macro sheet */- printf ("85: Microsoft Excel 4.0 macro sheet\n");- break;- case 0x02:- /* Chart */- printf ("85: Chart sheet\n");- break;- case 0x06:- /* Visual Basic module */- printf ("85: Visual Basic sheet\n");- break;- default:- printf ("???\n");- break;- }- printf("visible: %x\n", visible);- printf(" Pos: %Xh\n",filepos);- printf(" type: %.4Xh\n",type);- printf(" name: %s\n", name);- }-- if (pWB->sheets.count==0)- {- pWB->sheets.sheet=(struct st_sheet_data *) malloc(sizeof (struct st_sheet_data));- }- else- {- pWB->sheets.sheet=(struct st_sheet_data *) realloc(pWB->sheets.sheet,(pWB->sheets.count+1)*sizeof (struct st_sheet_data));- }- pWB->sheets.sheet[pWB->sheets.count].name=name;- pWB->sheets.sheet[pWB->sheets.count].filepos=filepos;- pWB->sheets.sheet[pWB->sheets.count].visibility=visible;- pWB->sheets.sheet[pWB->sheets.count].type=type;- pWB->sheets.count++;-- return name;-}---void xls_addRow(xlsWorkSheet* pWS,ROW* row)-{- struct st_row_data* tmp;-- //verbose ("xls_addRow");-- tmp=&pWS->rows.row[row->index];- tmp->height=row->height;- tmp->fcell=row->fcell;- tmp->lcell=row->lcell;- tmp->flags=row->flags;- tmp->xf=row->xf&0xfff;- tmp->xfflags=(row->xf >> 8)&0xf0;- if(xls_debug) xls_showROW(tmp);-}--void xls_makeTable(xlsWorkSheet* pWS)-{- DWORD i,t;- struct st_row_data* tmp;- verbose ("xls_makeTable");-- pWS->rows.row=(struct st_row_data *)calloc((pWS->rows.lastrow+1),sizeof(struct st_row_data));-- // printf("ALLOC: rows=%d cols=%d\n", pWS->rows.lastrow, pWS->rows.lastcol);- for (t=0;t<=pWS->rows.lastrow;t++)- {- tmp=&pWS->rows.row[t];- tmp->index=t;- tmp->fcell=0;- tmp->lcell=pWS->rows.lastcol;-- tmp->cells.count = pWS->rows.lastcol+1;- tmp->cells.cell=(struct st_cell_data *)calloc(tmp->cells.count,sizeof(struct st_cell_data));-- for (i=0;i<=pWS->rows.lastcol;i++)- {- tmp->cells.cell[i].col=i;- tmp->cells.cell[i].row=t;- tmp->cells.cell[i].width=pWS->defcolwidth;- tmp->cells.cell[i].xf=0;- tmp->cells.cell[i].str=NULL;- tmp->cells.cell[i].d=0;- tmp->cells.cell[i].l=0;- tmp->cells.cell[i].isHidden=0;- tmp->cells.cell[i].colspan=0;- tmp->cells.cell[i].rowspan=0;- tmp->cells.cell[i].id=XLS_RECORD_BLANK;- tmp->cells.cell[i].str=NULL;- }- }-}--struct st_cell_data *xls_addCell(xlsWorkSheet* pWS,BOF* bof,BYTE* buf)-{- struct st_cell_data* cell;- struct st_row_data* row;- int i;-- verbose ("xls_addCell");-- // printf("ROW: %u COL: %u\n", xlsShortVal(((COL*)buf)->row), xlsShortVal(((COL*)buf)->col));- row=&pWS->rows.row[xlsShortVal(((COL*)buf)->row)];- //cell=&row->cells.cell[((COL*)buf)->col - row->fcell]; DFH - inconsistent- cell=&row->cells.cell[xlsShortVal(((COL*)buf)->col)];- cell->id=bof->id;- cell->xf=xlsShortVal(((COL*)buf)->xf);-- switch (bof->id)- {- case XLS_RECORD_FORMULA:- case XLS_RECORD_FORMULA_ALT:- // test for formula, if- xlsConvertFormula((FORMULA *)buf);- cell->id=XLS_RECORD_FORMULA;- if (((FORMULA*)buf)->res!=0xffff) {- // if a double, then set double and clear l- cell->l=0;- memcpy(&cell->d, &((FORMULA*)buf)->resid, sizeof(double)); // Required for ARM- cell->str=xls_getfcell(pWS->workbook,cell, NULL);- } else {- cell->l = 0xFFFF;- double d = ((FORMULA*)buf)->resdata[1];- switch(((FORMULA*)buf)->resid) {- case 0: // String- break; // cell is half complete, get the STRING next record- case 1: // Boolean- memcpy(&cell->d, &d, sizeof(double)); // Required for ARM- sprintf((char *)(cell->str = malloc(sizeof("bool"))), "bool");- break;- case 2: // error- memcpy(&cell->d, &d, sizeof(double)); // Required for ARM- sprintf((char *)(cell->str = malloc(sizeof("error"))), "error");- break;- case 3: // empty string- cell->str = calloc(1,1);- break;- }- }- if(formula_handler) formula_handler(bof->id, bof->size, buf);- break;- case XLS_RECORD_MULRK:-printf("MULRK: %d\n", bof->size);- for (i = 0; i < (bof->size - 6)/6; i++) // 6 == 2 row + 2 col + 2 trailing index- {- cell=&row->cells.cell[xlsShortVal(((MULRK*)buf)->col + i)];- // printf("i=%d col=%d\n", i, xlsShortVal(((MULRK*)buf)->col + i) );- cell->id=XLS_RECORD_RK;- cell->xf=xlsShortVal(((MULRK*)buf)->rk[i].xf);- cell->d=NumFromRk(xlsIntVal(((MULRK*)buf)->rk[i].value));- cell->str=xls_getfcell(pWS->workbook,cell, NULL);- }- break;- case XLS_RECORD_MULBLANK:- for (i = 0; i < (bof->size - 6)/2; i++) // 6 == 2 row + 2 col + 2 trailing index- {- cell=&row->cells.cell[xlsShortVal(((MULBLANK*)buf)->col) + i];- cell->id=XLS_RECORD_BLANK;- cell->xf=xlsShortVal(((MULBLANK*)buf)->xf[i]);- cell->str=xls_getfcell(pWS->workbook,cell, NULL);- }- break;- case XLS_RECORD_LABELSST:- case XLS_RECORD_LABEL:- cell->str=xls_getfcell(pWS->workbook,cell,(WORD_UA *)&((LABEL*)buf)->value);- sscanf((char *)cell->str, "%d", &cell->l);- sscanf((char *)cell->str, "%lf", &cell->d);- break;- case XLS_RECORD_RK:- cell->d=NumFromRk(xlsIntVal(((RK*)buf)->value));- cell->str=xls_getfcell(pWS->workbook,cell, NULL);- break;- case XLS_RECORD_BLANK:- break;- case XLS_RECORD_NUMBER:- xlsConvertDouble((BYTE *)&((BR_NUMBER*)buf)->value);- memcpy(&cell->d, &((BR_NUMBER*)buf)->value, sizeof(double)); // Required for ARM- cell->str=xls_getfcell(pWS->workbook,cell, NULL);- break;- case XLS_RECORD_BOOLERR:- cell->d = ((BOOLERR *)buf)->value;- if (((BOOLERR *)buf)->iserror) {- sprintf((char *)(cell->str = malloc(sizeof("error"))), "error");- } else {- sprintf((char *)(cell->str = malloc(sizeof("bool"))), "bool");- }- break;- default:- cell->str=xls_getfcell(pWS->workbook,cell, NULL);- break;- }- if (xls_debug) xls_showCell(cell);-- return cell;-}--BYTE *xls_addFont(xlsWorkBook* pWB, FONT* font)-{- struct st_font_data* tmp;-- verbose("xls_addFont");- if (pWB->fonts.count==0)- {- pWB->fonts.font=(struct st_font_data *) malloc(sizeof(struct st_font_data));- } else {- pWB->fonts.font=(struct st_font_data *) realloc(pWB->fonts.font,(pWB->fonts.count+1)*sizeof(struct st_font_data));- }-- tmp=&pWB->fonts.font[pWB->fonts.count];-- tmp->name=get_string((BYTE*)&font->name, 0, pWB->is5ver, pWB->charset);-- tmp->height=font->height;- tmp->flag=font->flag;- tmp->color=font->color;- tmp->bold=font->bold;- tmp->escapement=font->escapement;- tmp->underline=font->underline;- tmp->family=font->family;- tmp->charset=font->charset;-- // xls_showFont(tmp);- pWB->fonts.count++;-- return tmp->name;-}--void xls_addFormat(xlsWorkBook* pWB, FORMAT* format)-{- struct st_format_data* tmp;-- verbose("xls_addFormat");- if (pWB->formats.count==0)- {- pWB->formats.format=(struct st_format_data *) malloc(sizeof(struct st_format_data));- } else {- pWB->formats.format=(struct st_format_data *) realloc(pWB->formats.format,(pWB->formats.count+1)*sizeof(struct st_format_data));- }-- tmp=&pWB->formats.format[pWB->formats.count];- tmp->index=format->index;- tmp->value=get_string(format->value, (BYTE)!pWB->is5ver, (BYTE)pWB->is5ver, pWB->charset);- if(xls_debug) xls_showFormat(tmp);- pWB->formats.count++;-}--void xls_addXF8(xlsWorkBook* pWB,XF8* xf)-{- struct st_xf_data* tmp;-- verbose("xls_addXF");- if (pWB->xfs.count==0)- {- pWB->xfs.xf=(struct st_xf_data *) malloc(sizeof(struct st_xf_data));- }- else- {- pWB->xfs.xf=(struct st_xf_data *) realloc(pWB->xfs.xf,(pWB->xfs.count+1)*sizeof(struct st_xf_data));- }-- tmp=&pWB->xfs.xf[pWB->xfs.count];-- tmp->font=xf->font;- tmp->format=xf->format;- tmp->type=xf->type;- tmp->align=xf->align;- tmp->rotation=xf->rotation;- tmp->ident=xf->ident;- tmp->usedattr=xf->usedattr;- tmp->linestyle=xf->linestyle;- tmp->linecolor=xf->linecolor;- tmp->groundcolor=xf->groundcolor;-- // xls_showXF(tmp);- pWB->xfs.count++;-}-void xls_addXF5(xlsWorkBook* pWB,XF5* xf)-{- struct st_xf_data* tmp;-- verbose("xls_addXF");- if (pWB->xfs.count==0)- {- pWB->xfs.xf=(struct st_xf_data *) malloc(sizeof(struct st_xf_data));- }- else- {- pWB->xfs.xf=(struct st_xf_data *) realloc(pWB->xfs.xf,(pWB->xfs.count+1)*sizeof(struct st_xf_data));- }-- tmp=&pWB->xfs.xf[pWB->xfs.count];-- tmp->font=xf->font;- tmp->format=xf->format;- tmp->type=xf->type;- tmp->align=(BYTE)xf->align;-/*- tmp->rotation=xf->rotation;- tmp->ident=xf->ident;- tmp->usedattr=xf->usedattr;- tmp->linestyle=xf->linestyle;- tmp->linecolor=xf->linecolor;- tmp->groundcolor=xf->groundcolor;-*/-- // xls_showXF(tmp);- pWB->xfs.count++;-}--void xls_addColinfo(xlsWorkSheet* pWS,COLINFO* colinfo)-{- struct st_colinfo_data* tmp;-- verbose("xls_addColinfo");- if (pWS->colinfo.count==0)- {- pWS->colinfo.col=(struct st_colinfo_data *) malloc(sizeof(struct st_colinfo_data));- }- else- {- pWS->colinfo.col=(struct st_colinfo_data *) realloc(pWS->colinfo.col,(pWS->colinfo.count+1)*sizeof(struct st_colinfo_data));- }-- tmp=&pWS->colinfo.col[pWS->colinfo.count];- tmp->first=colinfo->first;- tmp->last=colinfo->last;- tmp->width=colinfo->width;- tmp->xf=colinfo->xf;- tmp->flags=colinfo->flags;-- if(xls_debug) xls_showColinfo(tmp);- pWS->colinfo.count++;-}--void xls_mergedCells(xlsWorkSheet* pWS,BOF* bof,BYTE* buf)-{- int count=xlsShortVal(*((WORD_UA *)buf));- int i,c,r;- struct MERGEDCELLS* span;- verbose("Merged Cells");- for (i=0;i<count;i++)- {- span=(struct MERGEDCELLS*)(buf+(2+i*sizeof(struct MERGEDCELLS)));- xlsConvertMergedcells(span);- // printf("Merged Cells: [%i,%i] [%i,%i] \n",span->colf,span->rowf,span->coll,span->rowl);- for (r=span->rowf;r<=span->rowl;r++)- for (c=span->colf;c<=span->coll;c++)- pWS->rows.row[r].cells.cell[c].isHidden=1;- pWS->rows.row[span->rowf].cells.cell[span->colf].colspan=(span->coll-span->colf+1);- pWS->rows.row[span->rowf].cells.cell[span->colf].rowspan=(span->rowl-span->rowf+1);- pWS->rows.row[span->rowf].cells.cell[span->colf].isHidden=0;- }-}--void xls_parseWorkBook(xlsWorkBook* pWB)-{- BOF bof1;- BOF bof2;- BYTE* buf;- BYTE once;-- // this to prevent compiler warnings- once=0;- bof2.size = 0;- bof2.id = 0;- verbose ("xls_parseWorkBook");- do- {- if(xls_debug > 10) {- printf("READ WORKBOOK filePos=%ld\n", (long)pWB->filepos);- printf(" OLE: start=%d pos=%zd size=%zd fatPos=%zu\n", pWB->olestr->start, pWB->olestr->pos, pWB->olestr->size, pWB->olestr->fatpos); - }-- ole2_read(&bof1, 1, 4, pWB->olestr);- xlsConvertBof(&bof1);- if(xls_debug) xls_showBOF(&bof1);-- buf=(BYTE *)malloc(bof1.size);- ole2_read(buf, 1, bof1.size, pWB->olestr);-- switch (bof1.id) {- case XLS_RECORD_EOF:- //verbose("EOF");- break;- case XLS_RECORD_BOF: // BIFF5-8- {- BIFF *b = (BIFF*)buf;- xlsConvertBiff(b);- if (b->ver==0x600)- pWB->is5ver=0;- else- pWB->is5ver=1;- pWB->type=b->type;-- if(xls_debug) {- printf("version: %s\n", pWB->is5ver ? "BIFF5" : "BIFF8" );- printf(" type: %.2X\n", pWB->type);- }- }- break;-- case XLS_RECORD_CODEPAGE:- pWB->codepage=xlsShortVal(*(WORD_UA *)buf);- if(xls_debug) printf("codepage=%x\n", pWB->codepage);- break;-- case XLS_RECORD_CONTINUE:- if(once) {- if (bof2.id==XLS_RECORD_SST)- xls_appendSST(pWB,buf,bof1.size);- bof1=bof2;- }- break;-- case XLS_RECORD_WINDOW1:- {- WIND1 *w = (WIND1*)buf;- xlsConvertWindow(w);- pWB->activeSheetIdx = w->itabCur;- if(xls_debug) {- printf("WINDOW1: ");- printf("xWn : %d\n", w->xWn/20);- printf("yWn : %d\n", w->yWn/20);- printf("dxWn : %d\n", w->dxWn/20);- printf("dyWn : %d\n", w->dyWn/20);- printf("grbit : %d\n", w->grbit);- printf("itabCur: %d\n", w->itabCur);- printf("itabFi : %d\n", w->itabFirst);- printf("ctabSel: %d\n", w->ctabSel);- printf("wTabRat: %d\n", w->wTabRatio);- }- }- break;-- case XLS_RECORD_SST:- //printf("ADD SST\n");- //if(xls_debug) dumpbuf((BYTE *)"/tmp/SST",bof1.size,buf);- xlsConvertSst((SST *)buf);- xls_addSST(pWB,(SST*)buf,bof1.size);- break;-- case XLS_RECORD_EXTSST:- //if(xls_debug > 1000) dumpbuf((BYTE *)"/tmp/EXTSST",bof1.size,buf);- break;-- case XLS_RECORD_BOUNDSHEET:- {- //printf("ADD SHEET\n");- BOUNDSHEET *bs = (BOUNDSHEET *)buf;- xlsConvertBoundsheet(bs);- //char *s;- // different for BIFF5 and BIFF8- /*s = */ xls_addSheet(pWB,bs);- }- break;-- case XLS_RECORD_XF:- if(pWB->is5ver) {- XF5 *xf;- xf = (XF5 *)buf;- xlsConvertXf5(xf);-- xls_addXF5(pWB,xf);- if(xls_debug) {- printf(" font: %d\n", xf->font);- printf(" format: %d\n", xf->format);- printf(" type: %.4x\n", xf->type);- printf(" align: %.4x\n", xf->align);- printf("rotatio: %.4x\n", xf->color);- printf(" ident: %.4x\n", xf->fill);- printf("usedatt: %.4x\n", xf->border);- printf("linesty: %.4x\n", xf->linestyle);- }- } else {- XF8 *xf;- xf = (XF8 *)buf;- xlsConvertXf8(xf);-- xls_addXF8(pWB,xf);- if(xls_debug) {- xls_showXF(xf);- }- }- break;-- case XLS_RECORD_FONT:- case XLS_RECORD_FONT_ALT:- {- BYTE *s;- FONT *f = (FONT*)buf;- xlsConvertFont(f);- s = xls_addFont(pWB,f);- if(xls_debug) {- printf(" height: %d\n", f->height);- printf(" flag: 0x%x\n", f->flag);- printf(" color: 0x%x\n", f->color);- printf(" weight: %d\n", f->bold);- printf("escapem: 0x%x\n", f->escapement);- printf("underln: 0x%x\n", f->underline);- printf(" family: 0x%x\n", f->family);- printf("charset: 0x%x\n", f->charset);- if(s) printf(" name: %s\n", s);- }- }- break;-- case XLS_RECORD_FORMAT:- xlsConvertFormat((FORMAT *)buf);- xls_addFormat(pWB,(FORMAT*)buf);- break;-- case XLS_RECORD_STYLE:- if(xls_debug) {- struct { unsigned short idx; unsigned char ident; unsigned char lvl; } *styl;- styl = (void *)buf;-- printf(" idx: 0x%x\n", styl->idx & 0x07FF);- if(styl->idx & 0x8000) {- printf(" ident: 0x%x\n", styl->ident);- printf(" level: 0x%x\n", styl->lvl);- } else {- BYTE *s = get_string(&buf[2], 1, pWB->is5ver, pWB->charset);- printf(" name=%s\n", s);- }- }- break;-- case XLS_RECORD_PALETTE:- if(xls_debug > 10) {- unsigned char *p = buf + 2;- int idx, len;-- len = *(WORD_UA *)buf;- for(idx=0; idx<len; ++idx) {- printf(" Index=0x%2.2x %2.2x%2.2x%2.2x\n", idx+8, p[0], p[1], p[2] );- p += 4;- }- }- break;-- case XLS_RECORD_1904:- pWB->is1904 = *(BYTE *)buf; // the field is a short, but with little endian the first byte is 0 or 1- if(xls_debug) {- printf(" mode: 0x%x\n", pWB->is1904);- }- break;- - case XLS_RECORD_DEFINEDNAME:- printf("DEFINEDNAME: ");- for(int i=0; i<bof1.size; ++i) printf("%2.2x ", buf[i]);- printf("\n");- break;- -#ifdef DEBUG_DRAWINGS- case XLS_RECORD_MSODRAWINGGROUP:- {- printf("DRAWING GROUP size=%d\n", bof1.size);- unsigned int total = bof1.size;- unsigned int off = 0;-- while(off < total) {- struct drawHeader fooper = drawProc(buf, total, &off, 0);- (void)fooper;- }- printf("Total=%d off=%d\n", total, off);- - if(formData) printf("%s\n", formData);- if(formFunc) printf("%s\n", formFunc);- free(formData), formData = NULL;- free(formFunc), formFunc = NULL;-- } break;-#endif- default:- if(xls_debug)- {- //xls_showBOF(&bof1);- printf(" Not Processed in parseWoorkBook(): BOF=0x%4.4X size=%d\n", bof1.id, bof1.size);- }- break;- }- free(buf);-- bof2=bof1;- once=1;- }- while ((!pWB->olestr->eof)&&(bof1.id!=XLS_RECORD_EOF));-}---void xls_preparseWorkSheet(xlsWorkSheet* pWS)-{- BOF tmp;- BYTE* buf;-- verbose ("xls_preparseWorkSheet");-- ole2_seek(pWS->workbook->olestr,pWS->filepos);- do- {- size_t read;- read = ole2_read(&tmp, 1,4,pWS->workbook->olestr);- assert(read == 4);- xlsConvertBof(&tmp);- buf=(BYTE *)malloc(tmp.size);- read = ole2_read(buf, 1,tmp.size,pWS->workbook->olestr);- assert(read == tmp.size);- switch (tmp.id)- {- case XLS_RECORD_DEFCOLWIDTH:- pWS->defcolwidth=xlsShortVal(*(WORD_UA *)buf)*256;- break;- case XLS_RECORD_COLINFO:- xlsConvertColinfo((COLINFO*)buf);- xls_addColinfo(pWS,(COLINFO*)buf);- break;- case XLS_RECORD_ROW:- xlsConvertRow((ROW*)buf);- if (pWS->rows.lastcol<((ROW*)buf)->lcell)- pWS->rows.lastcol=((ROW*)buf)->lcell;- if (pWS->rows.lastrow<((ROW*)buf)->index)- pWS->rows.lastrow=((ROW*)buf)->index;- break;- /* If the ROW record is incorrect or missing, infer the information from- * cell data. */- case XLS_RECORD_MULRK:- if (pWS->rows.lastcol<xlsShortVal(((MULRK*)buf)->col) + (tmp.size - 6)/6 - 1)- pWS->rows.lastcol=xlsShortVal(((MULRK*)buf)->col) + (tmp.size - 6)/6 - 1;- if (pWS->rows.lastrow<xlsShortVal(((MULRK*)buf)->row))- pWS->rows.lastrow=xlsShortVal(((MULRK*)buf)->row);- break;- case XLS_RECORD_MULBLANK:- if (pWS->rows.lastcol<xlsShortVal(((MULBLANK*)buf)->col) + (tmp.size - 6)/2 - 1)- pWS->rows.lastcol=xlsShortVal(((MULBLANK*)buf)->col) + (tmp.size - 6)/2 - 1;- if (pWS->rows.lastrow<xlsShortVal(((MULBLANK*)buf)->row))- pWS->rows.lastrow=xlsShortVal(((MULBLANK*)buf)->row);- break;- case XLS_RECORD_NUMBER:- case XLS_RECORD_RK:- case XLS_RECORD_LABELSST:- case XLS_RECORD_BLANK:- case XLS_RECORD_LABEL:- case XLS_RECORD_FORMULA:- case XLS_RECORD_FORMULA_ALT:- case XLS_RECORD_BOOLERR:- if (pWS->rows.lastcol<xlsShortVal(((COL*)buf)->col))- pWS->rows.lastcol=xlsShortVal(((COL*)buf)->col);- if (pWS->rows.lastrow<xlsShortVal(((COL*)buf)->row))- pWS->rows.lastrow=xlsShortVal(((COL*)buf)->row);- break;- }- free(buf);- }- while ((!pWS->workbook->olestr->eof)&&(tmp.id!=XLS_RECORD_EOF));-}--void xls_formatColumn(xlsWorkSheet* pWS)-{- DWORD i,t,ii;- DWORD fcol,lcol;-- for (i=0;i<pWS->colinfo.count;i++)- {- if (pWS->colinfo.col[i].first<=pWS->rows.lastcol)- fcol=pWS->colinfo.col[i].first;- else- fcol=pWS->rows.lastcol;-- if (pWS->colinfo.col[i].last<=pWS->rows.lastcol)- lcol=pWS->colinfo.col[i].last;- else- lcol=pWS->rows.lastcol;-- for (t=fcol;t<=lcol;t++) {- for (ii=0;ii<=pWS->rows.lastrow;ii++)- {- if (pWS->colinfo.col[i].flags&1)- pWS->rows.row[ii].cells.cell[t].isHidden=1;- pWS->rows.row[ii].cells.cell[t].width=pWS->colinfo.col[i].width;- }- }- }-}--void xls_parseWorkSheet(xlsWorkSheet* pWS)-{- BOF tmp;- BYTE* buf;- long offset = pWS->filepos;- int continueRec = 0;-- struct st_cell_data *cell;- xlsWorkBook *pWB = pWS->workbook;-- verbose ("xls_parseWorkSheet");-- xls_preparseWorkSheet(pWS);- // printf("size=%d fatpos=%d)\n", pWS->workbook->olestr->size, pWS->workbook->olestr->fatpos);-- xls_makeTable(pWS);- xls_formatColumn(pWS);-- cell = (void *)0;- ole2_seek(pWS->workbook->olestr,pWS->filepos);- do- {- long lastPos = offset;-- if(xls_debug > 10) {- printf("LASTPOS=%ld pos=%zd filePos=%d filePos=%d\n", lastPos, pWB->olestr->pos, pWS->filepos, pWB->filepos);- }- ole2_read(&tmp, 1,4,pWS->workbook->olestr);- xlsConvertBof((BOF *)&tmp);- buf=(BYTE *)malloc(tmp.size);- ole2_read(buf, 1,tmp.size,pWS->workbook->olestr);- offset += 4 + tmp.size;-- if(xls_debug)- xls_showBOF(&tmp);-- switch (tmp.id)- {- case XLS_RECORD_EOF:- break;- case XLS_RECORD_MERGEDCELLS:- xls_mergedCells(pWS,&tmp,buf);- break;- case XLS_RECORD_ROW:- if(xls_debug > 10) printf("ROW: %x at pos=%ld\n", tmp.id, lastPos);- xlsConvertRow((ROW *)buf);- xls_addRow(pWS,(ROW*)buf);- break;- case XLS_RECORD_DEFCOLWIDTH:- if(xls_debug > 10) printf("DEFAULT COL WIDTH: %d\n", *(WORD_UA *)buf);- break;- case XLS_RECORD_DEFAULTROWHEIGHT:- if(xls_debug > 10) printf("DEFAULT ROW Height: 0x%x %d\n", ((WORD_UA *)buf)[0], ((WORD_UA *)buf)[1]);- break;- case XLS_RECORD_DBCELL:- if(xls_debug > 10) {- DWORD *foo = (DWORD_UA *)buf;- WORD *goo;- int i;- printf("DBCELL: size %d\n", tmp.size);- printf("DBCELL OFFSET=%4.4u -> ROW %ld\n", foo[0], lastPos-foo[0]);- ++foo;- goo = (WORD *)foo;- for(i=0; i<5; ++i) printf("goo[%d]=%4.4x %u\n", i, goo[i], goo[i]);- }- break;- case XLS_RECORD_INDEX:- if(xls_debug > 10) {- DWORD *foo = (DWORD_UA *)buf;- int i;- printf("INDEX: size %d\n", tmp.size);- for(i=0; i<5; ++i) printf("FOO[%d]=%4.4x %u\n", i, foo[i], foo[i]);- }-#if 0- 0 4 4 4 8 4- 12 4 16 4∙nm- Not used Index to first used row (rf, 0-based) Index to first row of unused tail of sheet (rl, last used row + 1, 0-based)- Absolute stream position of the DEFCOLWIDTH record (➜5.32) of the current sheet. If this record does not exist, the offset points to the record at the position where the DEFCOLWIDTH record would occur.- Array of nm absolute stream positions to the DBCELL record (➜5.29) of each Row Block-#endif- break;- case XLS_RECORD_MULRK:- case XLS_RECORD_MULBLANK:- case XLS_RECORD_NUMBER:- case XLS_RECORD_BOOLERR:- case XLS_RECORD_RK:- case XLS_RECORD_LABELSST:- case XLS_RECORD_BLANK:- case XLS_RECORD_LABEL:- case XLS_RECORD_FORMULA:- case XLS_RECORD_FORMULA_ALT:- cell = xls_addCell(pWS,&tmp,buf);- break;- case XLS_RECORD_ARRAY:- if(formula_handler) formula_handler(tmp.id, tmp.size, buf);- break;-- case XLS_RECORD_STRING:- if(cell && (cell->id == XLS_RECORD_FORMULA || cell->id == XLS_RECORD_FORMULA_ALT)) {- cell->str = get_string(buf, (BYTE)!pWB->is5ver, pWB->is5ver, pWB->charset);- if (xls_debug) xls_showCell(cell);- }- break;-#if 0 // debugging- case XLS_RECORD_HYPERREF:- if(xls_debug) {- printf("HYPERREF: ");- unsigned char xx, *foo = (void *)buf;-- for(xx=0; xx<tmp.size; ++xx, ++foo) {- printf("%2.2x ", *foo);- }- printf("\n");- }- break;- case XLS_RECORD_WINDOW2:- if(xls_debug) {- printf("WINDOW2: ");- unsigned short xx, *foo = (void *)buf;-- for(xx=0; xx<7; ++xx, ++foo) {- printf("0x%4.4x ", *foo);- }- printf("\n");- }- break;-#endif--#ifdef DEBUG_DRAWINGS-#ifdef AIX-#pragma pack(1)-#else-#pragma pack(push, 1)-#endif- case XLS_RECORD_MSODRAWING: // MSDRAWING- {- printf("DRAWING size=%d\n", tmp.size);- sheetOffset = 100;- unsigned int total = tmp.size;- unsigned int off = 0;- - while(off < total) {- struct drawHeader fooper = drawProc(buf, total, &off, 0);- (void)fooper;- printf("---------------Total=%d off=%d\n", total, off);- }-- if(formData) printf("%s\n", formData);- if(formFunc) printf("%s\n", formFunc);- free(formData), formData = NULL;- free(formFunc), formFunc = NULL;- - } break;- - case XLS_RECORD_TXO:- {- struct {- uint16_t grbit;- uint16_t rot;- char reserved1[6];- uint16_t cchText;- uint16_t cbRuns;- uint16_t ifntEmpty;- uint16_t reserved2;- } foo;- memcpy(&foo, buf, 18);- printf("TXO: grbit=0x%4.4X rot=0x%4.4X chText=0x%4.4X cbRuns=0x%4.4X ifntEmpty=0x%X reserved2=0x%X\n", foo.grbit, foo.rot, foo.cchText, foo.cbRuns, foo.ifntEmpty, foo.reserved2);- - printf("Res1: ");- for(int i=0; i<6; ++i) printf("%2.2x ", foo.reserved1[i]);- printf("\n");- - continueRec = 1;- goto printBOF;- } break;- - case XLS_RECORD_CONTINUE:- {- if(continueRec == 1) {- continueRec = 2;- - printf("TEXT: ");- for(int i=0; i<tmp.size; ++i) printf("%2.2x ", buf[i]);- printf("\n");- printf("\"%.*s\"\n", tmp.size-1, buf+1);- } else- if(continueRec == 2) {- continueRec = 0;- int off = 0;-- struct {- uint16_t ichFirst;- uint16_t ifnt;- char reserved[4];- } foo;- - for(int i=0; i<tmp.size/8; ++i) {- memcpy(&foo, buf+off, 8);- printf("TXORUN: %d 0x%x\n", foo.ichFirst, foo.ifnt);- off += 8;- }- }- goto printBOF;- } break;- - case XLS_RECORD_OBJ:- xls_showBOF(&tmp);- {- struct {- uint16_t ft;- uint16_t cb;- uint16_t ot;- uint16_t idx;- uint16_t flags;- uint16_t unused[6];- } foo;- memcpy(&foo, buf, sizeof(foo));- - int len = (int)(tmp.size - sizeof(foo));- int off = sizeof(foo);- - printf("OBJ ft=0x%X cb=0x%X ot=0x%X idx=0x%X flags=0x%X len=%d ", foo.ft, foo.cb, foo.ot, foo.idx, foo.flags, (int)(tmp.size - sizeof(foo)) );- //for(int i=0; i<6; ++i) printf(" 0x%02.2x", foo.unused[i]);- printf("\n");- - if(foo.ot == 0x08) {- struct {- uint16_t ft;- uint16_t cb;- uint16_t flags;- } ftcf;- memcpy(&ftcf, buf+off, sizeof(ftcf));- printf(" ft=%x cb=%x flags=%4.4x\n", ftcf.ft, ftcf.cb, ftcf.flags);- off += sizeof(ftcf);-- struct {- uint16_t ft;- uint16_t cb;- uint16_t flags;- } FtPioGrbit;- memcpy(&FtPioGrbit, buf+off, sizeof(FtPioGrbit));- printf(" ft=%x cb=%x flags=%4.4x\n", FtPioGrbit.ft, FtPioGrbit.cb, FtPioGrbit.flags);- off += sizeof(FtPioGrbit);- } else {- printf("Extra: ");- for(int i=0; i<len; ++i) printf("%2.2x ", buf[i+off]);- printf("\n");- }--#if 0- struct {- uint16_t ft;- uint16_t cb;- uint8_t guid[16];- uint16_t fSharedNote;- uint32_t unused;- } FtNts;- memcpy(&FtNts, buf+off, sizeof(FtNts));- off += sizeof(FtNts);- printf(" ft=%X cb=%X fSharedNote=0x%X guid: ", FtNts.ft, FtNts.cb, FtNts.fSharedNote);- for(int i=0; i<16; ++i) printf("%2.2x ", FtNts.guid[i]);- printf("\n");- - uint32_t last;- memcpy(&last, buf+off, 4);- printf(" LAST 0x%8.8X off=%d s1=%ld s2=%ld\n", last, off+4, sizeof(foo), sizeof(FtNts) );-#endif- goto printBOF;- } break;- - case XLS_RECORD_NOTE:- {- struct {- uint16_t row;- uint16_t col;- uint16_t flags;- uint16_t idx;- uint16_t strLen;- uint8_t strType;- } note;- memcpy(¬e, buf, sizeof(note));- printf("NOTE: row=%d col=%d flags=0x%x idx=%d strLen=%d strType=%d : ", note.row, note.col, note.flags, note.idx, note.strLen, note.strType);- for(int i=0; i<note.strLen; ++i) printf("%2.2x ", buf[i+sizeof(note)]);- printf("\n %.*s now at %ld len=%d\n", note.strLen, buf + sizeof(note), sizeof(note)+note.strLen, tmp.size);-- goto printBOF;- } break;-#pragma pack(pop)-#endif-- default:- printBOF:- if(xls_debug)- {- //xls_showBOF(&tmp);- printf(" [%d:%d]: 0x%X at pos=%lu size=%u\n", xlsShortVal(((COL*)buf)->row), xlsShortVal(((COL*)buf)->col), tmp.id, lastPos, tmp.size);- }- break;- }- free(buf);- }- while ((!pWS->workbook->olestr->eof)&&(tmp.id!=XLS_RECORD_EOF));-}--xlsWorkSheet * xls_getWorkSheet(xlsWorkBook* pWB,int num)-{- xlsWorkSheet * pWS;- verbose ("xls_getWorkSheet");- pWS=(xlsWorkSheet *)calloc(1, sizeof(xlsWorkSheet));- if (pWS != NULL) {- pWS->filepos=pWB->sheets.sheet[num].filepos;- pWS->workbook=pWB;- pWS->rows.lastcol=0;- pWS->rows.lastrow=0;- pWS->colinfo.count=0;- }- return(pWS);-}--xlsWorkBook* xls_open(const char *file,const char* charset)-{- xlsWorkBook* pWB;- OLE2* ole;-- pWB=(xlsWorkBook*)calloc(1, sizeof(xlsWorkBook));- verbose ("xls_open");-- if (pWB == NULL) {- return NULL;- }-- // open excel file- if (!(ole=ole2_open((BYTE *)file)))- {- if(xls_debug) printf("File \"%s\" not found\n",file);- free(pWB);- return(NULL);- }-- if ((pWB->olestr=ole2_fopen(ole, (BYTE *)"\005SummaryInformation")))- {- pWB->summary = calloc(1,4096);- ole2_read(pWB->summary, 4096, 1, pWB->olestr);- ole2_fclose(pWB->olestr);- }-- if ((pWB->olestr=ole2_fopen(ole, (BYTE *)"\005DocumentSummaryInformation")))- {- pWB->docSummary = calloc(1,4096);- ole2_read(pWB->docSummary, 4096, 1, pWB->olestr);- ole2_fclose(pWB->olestr);- }--#if 0- if(xls_debug) {- printf("summary=%d docsummary=%d\n", pWB->summary ? 1 : 0, pWB->docSummary ? 1 : 0);- xlsSummaryInfo *si = xls_summaryInfo(pWB);- printf("title=%s\n", si->title);- printf("subject=%s\n", si->subject);- printf("author=%s\n", si->author);- printf("keywords=%s\n", si->keywords);- printf("comment=%s\n", si->comment);- printf("lastAuthor=%s\n", si->lastAuthor);- printf("appName=%s\n", si->appName);- printf("category=%s\n", si->category);- printf("manager=%s\n", si->manager);- printf("company=%s\n", si->company);- }-#endif-- // open Workbook- if (!(pWB->olestr=ole2_fopen(ole,(BYTE *)"Workbook")) && !(pWB->olestr=ole2_fopen(ole,(BYTE *)"Book")))- {- if(xls_debug) printf("Workbook not found\n");- ole2_close(ole);- free(pWB);- return(NULL);- }--- pWB->sheets.count=0;- pWB->xfs.count=0;- pWB->fonts.count=0;- pWB->charset = (char *)malloc(strlen(charset) * sizeof(char)+1);- strcpy(pWB->charset, charset);- xls_parseWorkBook(pWB);-- return(pWB);-}--xlsRow *xls_row(xlsWorkSheet* pWS, WORD cellRow)-{- struct st_row_data *row;-- if(cellRow > pWS->rows.lastrow) return NULL;- row = &pWS->rows.row[cellRow];-- return row;-}--xlsCell *xls_cell(xlsWorkSheet* pWS, WORD cellRow, WORD cellCol)-{- struct st_row_data *row;-- if(cellRow > pWS->rows.lastrow) return NULL;- row = &pWS->rows.row[cellRow];- if(cellCol >= row->lcell) return NULL;-- return &row->cells.cell[cellCol];-}--void xls_close_WB(xlsWorkBook* pWB)-{- OLE2* ole;-- verbose ("xls_close");-- if(!pWB) return;-- // OLE first- ole=pWB->olestr->ole;- - ole2_fclose(pWB->olestr);-- ole2_close(ole);-- // WorkBook- free(pWB->charset);-- // Sheets- {- DWORD i;- for(i=0; i<pWB->sheets.count; ++i) {- free(pWB->sheets.sheet[i].name);- }- free(pWB->sheets.sheet);- }-- // SST- {- DWORD i;- for(i=0; i<pWB->sst.count; ++i) {- free(pWB->sst.string[i].str);- }- free(pWB->sst.string);- }-- // xfs- {- free(pWB->xfs.xf);- }-- // fonts- {- DWORD i;- for(i=0; i<pWB->fonts.count; ++i) {- free(pWB->fonts.font[i].name);- }- free(pWB->fonts.font);- }-- // formats- {- DWORD i;- for(i=0; i<pWB->formats.count; ++i) {- free(pWB->formats.format[i].value);- }- free(pWB->formats.format);- }-- // buffers- if(pWB->summary) free(pWB->summary);- if(pWB->docSummary) free(pWB->docSummary);-- // TODO - free other dynamically allocated objects like string table??- free(pWB);-}--void xls_close_WS(xlsWorkSheet* pWS)-{- if(!pWS) return;-- // ROWS- {- DWORD i, j;- for(j=0; j<=pWS->rows.lastrow; ++j) {- struct st_row_data *row = &pWS->rows.row[j];- for(i=0; i<row->cells.count; ++i) {- free(row->cells.cell[i].str);- }- free(row->cells.cell);- }- free(pWS->rows.row);-- }-- // COLINFO- {- free(pWS->colinfo.col);- }- free(pWS);-}--const char* xls_getVersion(void)-{- return PACKAGE_VERSION;-}--//-// http://poi.apache.org/hpsf/internals.html-// or google "DocumentSummaryInformation and UserDefined Property Sets" and look for MSDN hits-//--xlsSummaryInfo *xls_summaryInfo(xlsWorkBook* pWB)-{- xlsSummaryInfo *pSI;-- pSI = (xlsSummaryInfo *)calloc(1, sizeof(xlsSummaryInfo));- xls_dumpSummary(pWB->summary, 1, pSI);- xls_dumpSummary(pWB->docSummary, 0, pSI);-- return pSI;-}--void xls_close_summaryInfo(xlsSummaryInfo *pSI)-{- if(!pSI) return;-- if(pSI->title) free(pSI->title);- if(pSI->subject) free(pSI->subject);- if(pSI->author) free(pSI->author);- if(pSI->keywords) free(pSI->keywords);- if(pSI->comment) free(pSI->comment);- if(pSI->lastAuthor) free(pSI->lastAuthor);- if(pSI->appName) free(pSI->appName);- if(pSI->category) free(pSI->category);- if(pSI->manager) free(pSI->manager);- if(pSI->company) free(pSI->company);-- free(pSI);-}--void xls_dumpSummary(char *buf,int isSummary,xlsSummaryInfo *pSI) {- header *head;- sectionList *secList;- propertyList *plist;- sectionHeader *secHead;- property *prop;- uint32_t i, j;-- if(!buf) return; // perhaps the document was missing??-- head = (header *)buf;- //printf("header: \n");- //printf(" sig=%x\n", head->sig);- //printf(" os=%x\n", head->os >> 16);- //printf(" class=%8.8x%8.8x%8.8x%8.8x\n", head->format[0], head->format[1], head->format[2], head->format[3]);- //printf(" count=%x\n", head->count);-- for(i=0; i<head->count; ++i) {- secList = &head->secList[i];- //printf("Section %d:\n", i);- //printf(" class=%8.8x%8.8x%8.8x%8.8x\n", secList->format[0], secList->format[1], secList->format[2], secList->format[3]);- //printf(" offset=%d (now at %ld\n", secList->offset, (char *)secList - (char *)buf + sizeof(sectionList));--- secHead = (sectionHeader *)((char *)head + secList->offset);- //printf(" len=%d\n", secHead->length);- //printf(" properties=%d\n", secHead->numProperties);- for(j=0; j<secHead->numProperties; ++j) {- BYTE **s;-- plist = &secHead->properties[j];- //printf(" ---------\n");- //printf(" propID=%d offset=%d\n", plist->propertyID, plist->sectionOffset);- prop = (property *)((char *)secHead + plist->sectionOffset);- //printf(" propType=%d\n", prop->propertyID);-- switch(prop->propertyID) {- case 2:- //printf(" xlsShortVal=%x\n", *(uint16_t *)prop->data);- break;- case 3:- //printf(" wordVal=%x\n", *(uint32_t *)prop->data);- break;- case 30:- //printf(" longVal=%llx\n", *(uint64_t *)prop->data);- //printf(" s[%u]=%s\n", *(uint32_t *)prop->data, (char *)prop->data + 4);- if(isSummary) {- switch(plist->propertyID) {- case 2: s = &pSI->title; break;- case 3: s = &pSI->subject; break;- case 4: s = &pSI->author; break;- case 5: s = &pSI->keywords; break;- case 6: s = &pSI->comment; break;- case 8: s = &pSI->lastAuthor; break;- case 18: s = &pSI->appName; break;- default: s = NULL; break;- }- } else {- switch(plist->propertyID) {- case 2: s = &pSI->category; break;- case 14: s = &pSI->manager; break;- case 15: s = &pSI->company; break;- default: s = NULL; break;- }- }- if(s) *s = (BYTE *)strdup((char *)prop->data + 4);- break;- case 64:- //printf(" longVal=%llx\n", *(uint64_t *)prop->data);- break;- case 65:-#if 0- {- uint32_t k;- for(k=0; k<*(uint32_t *)prop->data; ++k) {- unsigned char *t = (unsigned char *)prop->data + 4 + k;- printf(" %2.2x(%c)", *t, *t);- }- printf("\n");- }-#endif- break;- default:- //printf(" UNKNOWN!\n");- break;- }- }- }-}--void xls_set_formula_hander(xls_formula_handler handler)-{- formula_handler = handler;-}--#ifdef DEBUG_DRAWINGS--#ifdef AIX-#pragma pack(1)-#else-#pragma pack(push, 1)-#endif--static char spaces[] = " ";--static struct drawHeader drawProc(uint8_t *buf, uint32_t maxLen, uint32_t *off_p, int level)-{- struct drawHeader head = { 0, 0, 0, 0 };- uint32_t off = off_p ? *off_p : 0;- memcpy(&head, buf+off, sizeof(head));-#if 0 // rec is the lower 4 bits- {- uint16_t foo0, foo1;- uint32_t foo2;- memcpy(&foo0, buf+off, 2);- memcpy(&foo1, buf+off+2, 2);- memcpy(&foo2, buf+off+4, 4);- printf("-----------------------------[%4.4x %4.4x %x] rec=%x instance=%x type=%x len=%x\n", foo0, foo1, foo2, head.rec, head.instance, head.type, head.len);- }-#endif- off += sizeof(head);-- printf("%.*s", level*3, spaces);- printf("type=%x rec=%x instance=%x len=%d ", head.type, head.rec, head.instance, head.len);- - switch(head.type) {- case 0xF000: // OfficeArtDggContainer - F000 - overall header- {- printf("OfficeArtDggContainer\n");- dumpRec("OfficeArtDggContainer", &head, 0, NULL);-- int startOff = off;- while( (off - startOff) < head.len && off < maxLen) {- struct drawHeader fooper2 = drawProc(buf, maxLen, &off, level+1);- (void)fooper2;- }- - printf("%.*s", level*3, spaces);- printf("Total=%d off=%d ObjectSize=%d\n", maxLen, off, off-startOff);- - } break;--#if 0- DRAWING 0xf002 208- rec=0 instance=1 type=f008 len=8- csp=4 spidCur=1027- rec=f instance=0 type=f003 len=462- Total=208 off=486- OBJ id=1 ot=0x19 flags=0x4011 check=0x0 len=30- ft=D cb=16 fSharedNote=0x0 guid: 8e 2e 69 ed f2 7d e3 11 99 7f 00 16 cb 93 e7 b5 - LAST 0x00000000- type=f00d rec=0 instance=0 len=0 WTF ?!?!?!--#endif- case 0xF002:- {- printf("OfficeArtDgContainer\n");- dumpRec("OfficeArtDgContainer", &head, 0, NULL);-- int startOff = off;- while( (off - startOff) < head.len && off < maxLen) {- struct drawHeader fooper2 = drawProc(buf, maxLen, &off, level+1);- (void)fooper2;- }- - printf("%.*s", level*3, spaces);- printf("Total=%d off=%d ObjectSize=%d\n", maxLen, off, off-startOff);-- } break;-- case 0xF003:- {- printf("OfficeArtSpgrContainer\n");- dumpRec("OfficeArtSpgrContainer", &head, 0, NULL);-- int startOff = off;- while( (off - startOff) < head.len && off < maxLen) {- struct drawHeader fooper2 = drawProc(buf, maxLen, &off, level+1);- (void)fooper2;- }- - printf("%.*s", level*3, spaces);- printf("Total=%d off=%d ObjectSize=%d FIXME FIXME FIXME\n", maxLen, off, off-startOff);- } break;-- case 0xF001:- {- printf("OfficeArtBStoreContainer\n");- dumpRec("OfficeArtBStoreContainer", &head, 0, NULL);-- int startOff = off;- while( (off - startOff) < head.len && off < maxLen) {- struct drawHeader fooper2 = drawProc(buf, maxLen, &off, level+1);- (void)fooper2;- }- - printf("%.*s", level*3, spaces);- printf("Total=%d off=%d ObjectSize=%d\n", maxLen, off, off-startOff);- } break;- case 0xF004:- {- printf("OfficeArtSpContainer\n");- dumpRec("OfficeArtSpContainer", &head, 0, NULL);-- int startOff = off;- while( (off - startOff) < head.len && off < maxLen) {- struct drawHeader fooper2 = drawProc(buf, maxLen, &off, level+1);- (void)fooper2;- }- - printf("%.*s", level*3, spaces);- printf("Total=%d off=%d ObjectSize=%d\n", maxLen, off, off-startOff);- } break;- case 0xF006:- {- // A value that MUST be 0x00000010 + ((head.cidcl - 1) * 0x00000008)- unsigned int count = (head.len - 0x10) / 0x8;- printf("OfficeArtFDGGBlock count=%d\n", count);- dumpRec("OfficeArtFDGGBlock - needs to be set", &head, 0, NULL);-- // OfficeArtFDGG- struct {- uint32_t spidMax;- uint32_t cidcl;- uint32_t cspSaved;- uint32_t cdgSaved;- } fog;- memcpy(&fog, buf+off, 16); // OfficeArtRecordHeader F001 - specified BLIP - this is the image- off += 16;- printf("%.*s", level*3, spaces);- printf(" spidMax=%d cidcl=%d cspSaved=%d cdgSaved=%d\n", fog.spidMax, fog.cidcl, fog.cspSaved, fog.cdgSaved);-#if 0- spidMax (4 bytes): An MSOSPID structure, as defined in section 2.1.2, specifying the current maximum shape identifier that is used in any drawing. This value MUST be less than 0x03FFD7FF.- cidcl (4 bytes): An unsigned integer that specifies the number of OfficeArtIDCL records, as defined in section 2.2.46, + 1. This value MUST be less than 0x0FFFFFFF.- cspSaved (4 bytes): An unsigned integer specifying the total number of shapes that have been saved in all of the drawings.- cdgSaved (4 bytes): An unsigned integer specifying the total number of drawings that have been saved in the file.-#endif- // OfficeArtIDCL - clusters- for(int i=0; i<count; ++i) {- struct {- uint32_t dgid;- uint32_t cspidCur;-#if 0- dgid (4 bytes): An MSODGID structure, as defined in section 2.1.1, specifying the drawing identifier that owns this identifier cluster.- cspidCur (4 bytes): An unsigned integer that, if less than 0x00000400, specifies the largest shape identifier that is currently assigned in this cluster, or that otherwise specifies that no shapes can be added to the drawing.-#endif- } foo1;- memcpy(&foo1, buf+off, 8); // OfficeArtIDCL- off += 8;- - printf("%.*s", level*3, spaces);- printf(" dgid=%d cspid=%d\n", foo1.dgid, foo1.cspidCur);- }- //for(int i=0; i<16; ++i) printf(" %2.2x", *(BYTE *)(buf+off+i));- //printf("\n");- } break;-- case 0xF007:- {- printf("OfficeArtFBSE\n");- //dumpRec("OfficeArtFBSE", &head, 0, NULL);- struct {- uint8_t btWin32;- uint8_t btMacOS;- uint8_t rgbUid[16];- uint16_t tag;- uint32_t size;- uint32_t cRef;- uint32_t foDelay;- uint8_t unused1;- uint8_t cbName;- uint8_t unused2;- uint8_t unused3;- } fooper1;- memcpy(&fooper1, buf+off, sizeof(fooper1));- off += sizeof(fooper1);- printf("%.*s", level*3, spaces);- printf(" rgbUid: ");- for(int i=0; i<16; ++i) {- printf(" %2.2x", fooper1.rgbUid[i]);- }- printf("\n");- - printf("%.*s", level*3, spaces);- printf(" w=%d mac=%d tag=0x%x size=%d cRef=%d foDelay=%x cbName=%x", fooper1.btWin32, fooper1.btMacOS, fooper1.tag , fooper1.size , fooper1.cRef , fooper1.foDelay, fooper1.cbName);- if(fooper1.cbName) printf("name:");- for(int i=0; i<fooper1.cbName; ++i) {- printf(" %2.2x", *(BYTE *)(buf+off+i));- }- printf("\n");- off += fooper1.cbName;- - printf(" dataLen=%ld\n", head.len - sizeof(fooper1) - fooper1.cbName);- drawProc(buf, maxLen, &off, level+1);-- - } break;---#if 0- rgbUid (16 bytes): An MD4 message digest, as specified in [RFC1320], that specifies the unique identifier of the pixel data in the BLIP.- tag (2 bytes): An unsigned integer that specifies an application-defined internal resource tag. This value MUST be 0xFF for external files.- size (4 bytes): An unsigned integer that specifies the size, in bytes, of the BLIP in the stream.- cRef (4 bytes): An unsigned integer that specifies the number of references to the BLIP. A value of 0x00000000 specifies an empty slot in the OfficeArtBStoreContainer record, as defined in section 2.2.20.- foDelay (4 bytes): An MSOFO structure, as defined in section 2.1.4, that specifies the file offset into the associated OfficeArtBStoreDelay record, as defined in section 2.2.21, (delay stream). A value of 0xFFFFFFFF specifies that the file is not in the delay stream, and in this case, cRef MUST be 0x00000000.- unused1 (1 byte): A value that is undefined and MUST be ignored.- cbName (1 byte): An unsigned integer that specifies the length, in bytes, of the nameData field, including the terminating NULL character. This value MUST be an even number and less than or equal to 0xFE. If the value is 0x00, nameData will not be written.- unused2 (1 byte): A value that is undefined and MUST be ignored.- unused3 (1 byte): A value that is undefined and MUST be ignored.- nameData (variable): A Unicode null-terminated string that specifies the name of the BLIP.- embeddedBlip (variable): An OfficeArtBlip record, as defined in section 2.2.23, specifying the BLIP file data that is embedded in this record. If this value is not 0, foDelay MUST be ignored.-#endif-- case 0xF008:- {- printf("OfficeArtFDG\n");- dumpRec("OfficeArtFDG - spidCur needs to be set", &head, 0, NULL);- struct {- uint32_t csp;- uint32_t spidCur;- } fooper1;- memcpy(&fooper1, buf+off, 8);- off += 8;- printf("%.*s", level*3, spaces);- printf(" csp=%d spidCur=%d\n", fooper1.csp, fooper1.spidCur);- -#if 0- csp (4 bytes): An unsigned integer that specifies the number of shapes in this drawing.- spidCur (4 bytes): An MSOSPID structure, as defined in section 2.1.2, that specifies the shape- identifier of the last shape in this drawing.-#endif- - } break;-- case 0xF009:- {- printf("OfficeArtFSPGR\n");- dumpRec("OfficeArtFSPGR", &head, head.len, buf+off);- struct {- int32_t xLeft;- int32_t yTop;- int32_t xRight;- int32_t yBottom;- } foo;- memcpy(&foo, buf+off, 16);- off += 16;- printf("%.*s", level*3, spaces);- printf(" l=%d t=%d r=%d b=%d\n", foo.xLeft, foo.yTop, foo.xRight, foo.yBottom);- } break;-- case 0xF00A: // OfficeArtFSP- {- printf("OfficeArtFSP\n");- dumpRec("OfficeArtFSP", &head, 0, NULL);- struct {- uint32_t spid;- uint32_t flags;- } foo;- memcpy(&foo, buf+off, 8);- off += 8;- printf("%.*s", level*3, spaces);- printf(" SPID=%d flags=0x%x\n", foo.spid, foo.flags);- } break;-- case 0xF00B:- {- printf("OfficeArtFOPT\n");- dumpRec("OfficeArtFOPT", &head, head.len, buf+off);- struct {- //uint16_t blip : 1;- //uint16_t complex : 1;- uint16_t opid; // : 14- uint32_t op;- } foo;- - // OfficeArtFOPTE + complex- for(int i=0; i<head.instance; ++i) {- memcpy(&foo, buf+off, 6);- off += 6;- printf("%.*s", level*3, spaces);- printf(" opid=0x%4.4X(%.5d) op=%8.8X\n", foo.opid, foo.opid, foo.op); // blip=%d complex=%d , foo.blip, foo.complex- //printf("drawDataOPID(data, 0x%4.4X, 0x%8.8X);\n", foo.opid, foo.op);- }-#if 0- opid=80 op=000018AC(6316) Text ID- opid=bf op=0000000A(10) fFitTextToShape- opid=158 op=00000000(0) // Type of connection sites- opid=181 op=00000800(2048) // fillColor- opid=183 op=00000800(2048) // fillBackColor- opid=1bf op=00000010(16) // hit test- opid=23f op=00000003(3) // fshadowObscured-#endif- int complex = head.len - head.instance * 6;- if(complex) {- printf("%.*s", level*3, spaces);- printf(" complex:");- - for(int i=0; i<complex; ++i) {- printf(" %2.2x", *(BYTE *)(buf+off+i));- }- printf("\n");- }- off += complex;- } break;-- case 0xF00D:- printf("msofbtClientTextbox\n");- dumpRec("msofbtClientTextbox", &head, head.len, buf+off);- break;-- case 0xF010:- printf("msofbtClientAnchor: ");- dumpRec("msofbtClientAnchor", &head, head.len, buf+off);- // https://code.google.com/p/excellibrary/source/browse/trunk/src/ExcelLibrary/Office/Excel/EscherRecords/MsofbtClientAnchor.cs?spec=svn18&r=18- struct {- uint16_t Flag;- uint16_t Col1;- uint16_t DX1;- uint16_t Row1;- uint16_t DY1;- uint16_t Col2;- uint16_t DX2;- uint16_t Row2;- uint16_t DY2;- } foo;- memcpy(&foo, buf+off, 18);- printf(" Flag=0x%2.2x Col1=0x%2.2x DX1=0x%2.2x Row1=0x%2.2x DY1=0x%2.2x Col2=0x%2.2x DX2=0x%2.2x Row2=0x%2.2x DY2=0x%2.2x \n",- foo.Flag, foo.Col1, foo.DX1, foo.Row1, foo.DY1, foo.Col2, foo.DX2, foo.Row2, foo.DY2);- off += head.len;- break;- case 0xF011:- printf("msofbtClientData\n");- dumpRec("msofbtClientData", &head, head.len, buf+off);- off += head.len;- break;-- case 0xF01E:- { printf("OfficeArtBlipPNG\n");- dumpRec("OfficeArtBlipPNG", &head, head.len, buf+off);- struct {- uint8_t rgbUid1[16];- uint16_t tag;- } foo;- memcpy(&foo, buf+off, sizeof(foo));- - //off += sizeof(foo);- printf("%.*s", level*3, spaces);- printf(" rgbUid1: ");- for(int i=0; i<16; ++i) {- printf(" %2.2x", foo.rgbUid1[i]);- }- printf("\n");- off += head.len;- } break;-- case 0xF11E:- printf("OfficeArtSplitMenuColorContainer: Array of colors\n");- dumpRec("OfficeArtSplitMenuColorContainer", &head, head.len, buf+off);- off += head.len;- break;-- case 0xF122:- { printf("OfficeArtTertiaryFOPT\n");- struct {- //uint16_t blip : 1;- //uint16_t complex : 1;- uint16_t opid; // : 14- uint16_t op1;- uint16_t op2;- } foo;- int count = head.len/6;- printf("OfficeArtFOPT count=%d\n", count);- dumpRec("OfficeArtTertiaryFOPT", &head, head.len, buf+off);-- // OfficeArtFOPTE + complex- for(int i=0; i<head.instance; ++i) {- memcpy(&foo, buf+off, 6);- off += 6;- printf("%.*s", level*3, spaces);- printf(" opid=0x%4.4X(%.5d) op1=%4.4X op1=%4.4X\n", foo.opid, foo.opid, foo.op1, foo.op2); // blip=%d complex=%d , foo.blip, foo.complex- }- //off += head.len;- } break;-- default:- printf("WTF ?!?!?!\n");- //assert(!"Not Possible");- off += head.len;- break;- }-- *off_p = off;- return head;-}--static void dumpData(char *data);-static void dumpFunc(char *func);--static void dumpRec(char *comment, struct drawHeader *h, int len, uint8_t *buf)-{- int width = 0;- static int num;- char *tmp;- -return;-- if(len) {- ++num;- //asprintf(&tmp, "// %s real len = %d\n", comment, h->len);- asprintf(&tmp, "static unsigned char draw%03.3d[%d] = { ", num+sheetOffset, len);- width = strlen(tmp);- dumpData(tmp);- - for(int i=0; i<len; ++i) {- asprintf(&tmp, "0x%02.2X, ", buf[i]);- width += strlen(tmp);- dumpData(tmp);- - if(width >= 79) {- dumpData(strdup("\n "));- width = 4;- }- }- dumpData(strdup("\n };\n"));- }- - char name[32];- if(len) {- sprintf(name, "draw%03.3d", num+sheetOffset);- } else {- strcpy(name, "NULL");- }-- asprintf(&tmp, "dumpDrawData(data, 0x%X, 0x%X, 0x%X, %u, %d, %s /* len=%d */ ) ; // %s\n", h->rec, h->instance, h->type, h->len, len, name, len, comment);- dumpFunc(tmp);-}---static void dumpData(char *data)-{- if(!formData) {- formData = calloc(1,1);- }- - char *oldStr = formData;- asprintf(&formData, "%s%s", oldStr, data);- free(oldStr);- free(data);-}-static void dumpFunc(char *func)-{- if(!formFunc) {- formFunc = calloc(1,1);- }- - char *oldStr = formFunc;- asprintf(&formFunc, "%s%s", oldStr, func);- free(oldStr);-}--#if 0-static int finder(uint8_t *buf, uint32_t len, uint16_t pattern)-{- int ret = 0;- uint8_t b1 = pattern & 0xFF;- uint8_t b2 = pattern >> 8;- - for(int i=0; i<(len-1); ++i) {- if(buf[i] == b1 && buf[i+1] == b2) {- printf("GOT FINDER HIT OFFSET %d\n", i);- ret = 1;- }- }- return ret;-}--// MD4 open source: http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4 or-// http://www.opensource.apple.com/source/freeradius/freeradius-11/freeradius/src/lib/md4.c-// Size of TWIPS: http://support.microsoft.com/kb/76388-#endif--#pragma pack(pop)--#endif-----+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller+ *+ * 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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.+ *+ */++#include "config.h"++#include <stdio.h>+#include <stdlib.h>+#include <stddef.h>+#include <errno.h>++#include <memory.h>+#include <math.h>+#include <sys/types.h>+#include <string.h>+#include <wchar.h>++#include "../include/libxls/endian.h"+#include "../include/xls.h"++#ifndef min+#define min(a,b) ((a) < (b) ? (a) : (b))+#endif++//#define DEBUG_DRAWINGS+int xls_debug = 0;++static double NumFromRk(DWORD drk);+static xls_formula_handler formula_handler;++static xls_error_t xls_addSST(xlsWorkBook* pWB, SST* sst, DWORD size);+static xls_error_t xls_appendSST(xlsWorkBook* pWB, BYTE* buf, DWORD size);+static xls_error_t xls_addFormat(xlsWorkBook* pWB, FORMAT* format, DWORD size);+static char* xls_addSheet(xlsWorkBook* pWB, BOUNDSHEET* bs, DWORD size);+static xls_error_t xls_addRow(xlsWorkSheet* pWS,ROW* row);+static xls_error_t xls_makeTable(xlsWorkSheet* pWS);+static struct st_cell_data *xls_addCell(xlsWorkSheet* pWS, BOF* bof, BYTE* buf);+static char *xls_addFont(xlsWorkBook* pWB, FONT* font, DWORD size);+static xls_error_t xls_addXF8(xlsWorkBook* pWB, XF8* xf);+static xls_error_t xls_addXF5(xlsWorkBook* pWB, XF5* xf);+static xls_error_t xls_addColinfo(xlsWorkSheet* pWS, COLINFO* colinfo);+static xls_error_t xls_mergedCells(xlsWorkSheet* pWS, BOF* bof, BYTE* buf);+static xls_error_t xls_preparseWorkSheet(xlsWorkSheet* pWS);+static xls_error_t xls_formatColumn(xlsWorkSheet* pWS);+static void xls_dumpSummary(char *buf, int isSummary, xlsSummaryInfo *pSI);++#if defined(_AIX) || defined(__sun)+#pragma pack(1)+#else+#pragma pack(push, 1)+#endif++typedef struct {+ uint32_t format[4];+ uint32_t offset;+} sectionList;++typedef struct {+ uint16_t sig;+ uint16_t _empty;+ uint32_t os;+ uint32_t format[4];+ uint32_t count;+ sectionList secList[1];+} header;++typedef struct {+ uint32_t propertyID;+ uint32_t sectionOffset;+} propertyList;++typedef struct {+ uint32_t length;+ uint32_t numProperties;+ propertyList properties[1];+} sectionHeader;++typedef struct {+ uint32_t propertyID;+ uint32_t data[1];+} property;++#pragma pack(pop)++int xls(int debug)+{+ xls_debug = debug;+ return 1;+}++static xls_error_t xls_addSST(xlsWorkBook* pWB,SST* sst,DWORD size)+{+ verbose("xls_addSST");++ pWB->sst.continued=0;+ pWB->sst.lastln=0;+ pWB->sst.lastid=0;+ pWB->sst.lastrt=0;+ pWB->sst.lastsz=0;++ if (sst->num > (1<<24))+ return LIBXLS_ERROR_MALLOC;++ if (pWB->sst.string)+ return LIBXLS_ERROR_PARSE;++ if ((pWB->sst.string = calloc(pWB->sst.count = sst->num,+ sizeof(struct str_sst_string))) == NULL)+ return LIBXLS_ERROR_MALLOC;++ return xls_appendSST(pWB, sst->strings, size - offsetof(SST, strings));+}++static xls_error_t xls_appendSST(xlsWorkBook* pWB, BYTE* buf, DWORD size)+{+ DWORD ln; // String character count+ DWORD ofs; // Current offset in SST buffer+ DWORD rt; // Count of rich text formatting runs+ DWORD sz; // Size of asian phonetic settings block+ BYTE flag; // String flags+ char* ret = NULL;++ if (xls_debug) {+ printf("xls_appendSST %u\n", size);+ }++ sz = rt = ln = 0; // kch+ ofs=0;++ while(ofs<size)+ {+ int ln_toread;++ // Restore state when we're in a continue record+ // or read string length+ if (pWB->sst.continued) {+ ln=pWB->sst.lastln;+ rt=pWB->sst.lastrt;+ sz=pWB->sst.lastsz;+ } else {+ if (ofs + 2 > size) {+ return LIBXLS_ERROR_PARSE;+ }+ ln = buf[ofs+0] + (buf[ofs+1] << 8);+ rt = 0;+ sz = 0;++ ofs+=2;+ }++ if (xls_debug) {+ printf("ln=%u\n", ln);+ }++ // Read flags+ if ( !pWB->sst.continued || (pWB->sst.continued && ln != 0) ) {+ if (ofs + sizeof(BYTE) > size) {+ return LIBXLS_ERROR_PARSE;+ }+ flag=*(BYTE *)(buf+ofs);+ ofs++;++ // Count of rich text formatting runs+ if (flag & 0x8) {+ if (ofs + sizeof(WORD) > size) {+ return LIBXLS_ERROR_PARSE;+ }+ rt = buf[ofs+0] + (buf[ofs+1] << 8);+ ofs+=2;+ }++ // Size of asian phonetic settings block+ if (flag & 0x4) {+ if (ofs + sizeof(DWORD) > size) {+ return LIBXLS_ERROR_PARSE;+ }+ sz = buf[ofs+0] + (buf[ofs+1] << 8) + (buf[ofs+2] << 16) + ((DWORD)buf[ofs+3] << 24);+ ofs+=4;++ if (xls_debug) {+ printf("sz=%u\n", sz);+ }+ }+ } else {+ flag = 0;+ }++ // Read characters (compressed or not)+ ln_toread = 0;+ if (ln > 0) {+ if (flag & 0x1) {+ size_t new_len = 0;+ ln_toread = min((size-ofs)/2, ln);+ ret=unicode_decode((char *)buf+ofs,ln_toread*2,&new_len,pWB->charset);++ if (ret == NULL)+ {+ ret = strdup("*failed to decode utf16*");+ new_len = strlen(ret);+ }++ ret = realloc(ret,new_len+1);+ ret[new_len]=0;++ ln -= ln_toread;+ ofs+=ln_toread*2;++ if (xls_debug) {+ printf("String16SST: %s(%lu)\n", ret, (unsigned long)new_len);+ }+ } else {+ ln_toread = min((size-ofs), ln);++ ret = utf8_decode((char *)buf+ofs, ln_toread, pWB->charset);++ ln -= ln_toread;+ ofs += ln_toread;++ if (xls_debug) {+ printf("String8SST: %s(%u) \n",ret,ln);+ }+ }+ } else {+ ret = strdup("");+ }++ if (ln_toread > 0 || !pWB->sst.continued) {+ // Concat string if it's a continue, or add string in table+ if (!pWB->sst.continued) {+ if (pWB->sst.lastid >= pWB->sst.count) {+ free(ret);+ return LIBXLS_ERROR_PARSE;+ }+ pWB->sst.lastid++;+ pWB->sst.string[pWB->sst.lastid-1].str=ret;+ } else {+ char *tmp = pWB->sst.string[pWB->sst.lastid-1].str;+ if (tmp == NULL) {+ free(ret);+ return LIBXLS_ERROR_PARSE;+ }+ tmp = realloc(tmp, strlen(tmp)+strlen(ret)+1);+ if (tmp == NULL) {+ free(ret);+ return LIBXLS_ERROR_MALLOC;+ }+ pWB->sst.string[pWB->sst.lastid-1].str=tmp;+ memcpy(tmp+strlen(tmp), ret, strlen(ret)+1);+ free(ret);+ }++ if (xls_debug) {+ printf("String %4u: %s<end>\n", pWB->sst.lastid-1, pWB->sst.string[pWB->sst.lastid-1].str);+ }+ } else {+ free(ret);+ }++ // Jump list of rich text formatting runs+ if (ofs < size && rt > 0) {+ int rt_toread = min((size-ofs)/4, rt);+ rt -= rt_toread;+ ofs += rt_toread*4;+ }++ // Jump asian phonetic settings block+ if (ofs < size && sz > 0) {+ int sz_toread = min((size-ofs), sz);+ sz -= sz_toread;+ ofs += sz_toread;+ }++ pWB->sst.continued=0;+ }++ // Save current character count and count of rich text formatting runs and size of asian phonetic settings block+ if (ln > 0 || rt > 0 || sz > 0) {+ pWB->sst.continued = 1;+ pWB->sst.lastln = ln;+ pWB->sst.lastrt = rt;+ pWB->sst.lastsz = sz;++ if (xls_debug) {+ printf("continued: ln=%u, rt=%u, sz=%u\n", ln, rt, sz);+ }+ }++ return LIBXLS_OK;+}++static double NumFromRk(DWORD drk)+{+ double ret;++ // What kind of value is this ?+ if (drk & 0x02) {+ // Integer value+ int tmp = (int)drk >> 2; // cast to keep it negative in < 0+ ret = (double)tmp;+ } else {+ // Floating point value;+ unsigned64_t tmp = drk & 0xfffffffc;+ tmp <<= 32;+ memcpy(&ret, &tmp, sizeof(unsigned64_t));+ }+ // Is value multiplied by 100 ?+ if (drk & 0x01) {+ ret /= 100.0;+ }+ return ret;+}++static char * xls_addSheet(xlsWorkBook* pWB, BOUNDSHEET *bs, DWORD size)+{+ char * name;+ DWORD filepos;+ BYTE visible, type;++ filepos = bs->filepos;+ visible = bs->visible;+ type = bs->type;++ // printf("charset=%s uni=%d\n", pWB->charset, unicode);+ // printf("bs name %.*s\n", bs->name[0], bs->name+1);+ name = get_string(bs->name, size - offsetof(BOUNDSHEET, name), 0, pWB->is5ver, pWB->charset);+ // printf("name=%s\n", name);++ if(xls_debug) {+ printf ("xls_addSheet[0x%x]\n", type);+ switch (type & 0x0f)+ {+ case 0x00:+ /* worksheet or dialog sheet */+ printf ("85: Worksheet or dialog sheet\n");+ break;+ case 0x01:+ /* Microsoft Excel 4.0 macro sheet */+ printf ("85: Microsoft Excel 4.0 macro sheet\n");+ break;+ case 0x02:+ /* Chart */+ printf ("85: Chart sheet\n");+ break;+ case 0x06:+ /* Visual Basic module */+ printf ("85: Visual Basic sheet\n");+ break;+ default:+ printf ("???\n");+ break;+ }+ printf("visible: %x\n", visible);+ printf(" Pos: %Xh\n",filepos);+ printf(" type: %.4Xh\n",type);+ printf(" name: %s\n", name);+ }++ pWB->sheets.sheet = realloc(pWB->sheets.sheet,(pWB->sheets.count+1)*sizeof (struct st_sheet_data));+ if (pWB->sheets.sheet == NULL)+ return NULL;++ pWB->sheets.sheet[pWB->sheets.count].name=name;+ pWB->sheets.sheet[pWB->sheets.count].filepos=filepos;+ pWB->sheets.sheet[pWB->sheets.count].visibility=visible;+ pWB->sheets.sheet[pWB->sheets.count].type=type;+ pWB->sheets.count++;++ return name;+}+++static xls_error_t xls_addRow(xlsWorkSheet* pWS,ROW* row)+{+ struct st_row_data* tmp;++ //verbose ("xls_addRow");++ if (row->index > pWS->rows.lastrow)+ return LIBXLS_ERROR_PARSE;++ tmp=&pWS->rows.row[row->index];+ tmp->height=row->height;+ tmp->fcell=row->fcell;+ tmp->lcell=row->lcell;+ tmp->flags=row->flags;+ tmp->xf=row->xf&0xfff;+ tmp->xfflags=(row->xf >> 8)&0xf0;+ if(xls_debug) xls_showROW(tmp);++ return LIBXLS_OK;+}++static xls_error_t xls_makeTable(xlsWorkSheet* pWS)+{+ DWORD i,t;+ struct st_row_data* tmp;+ verbose ("xls_makeTable");++ if ((pWS->rows.row = calloc((pWS->rows.lastrow+1),sizeof(struct st_row_data))) == NULL)+ return LIBXLS_ERROR_MALLOC;++ // printf("ALLOC: rows=%d cols=%d\n", pWS->rows.lastrow, pWS->rows.lastcol);+ for (t=0;t<=pWS->rows.lastrow;t++)+ {+ tmp=&pWS->rows.row[t];+ tmp->index=t;+ tmp->fcell=0;+ tmp->lcell=pWS->rows.lastcol;++ tmp->cells.count = pWS->rows.lastcol+1;+ if ((tmp->cells.cell = calloc(tmp->cells.count, sizeof(struct st_cell_data))) == NULL)+ return LIBXLS_ERROR_MALLOC;++ for (i=0;i<=pWS->rows.lastcol;i++)+ {+ tmp->cells.cell[i].col = i;+ tmp->cells.cell[i].row = t;+ tmp->cells.cell[i].width = pWS->defcolwidth;+ tmp->cells.cell[i].id = XLS_RECORD_BLANK;+ }+ }+ return LIBXLS_OK;+}++int xls_isCellTooSmall(xlsWorkBook* pWB, BOF* bof, BYTE* buf) {+ if (bof->size < sizeof(COL))+ return 1;++ if (bof->id == XLS_RECORD_FORMULA || bof->id == XLS_RECORD_FORMULA_ALT)+ return (bof->size < sizeof(FORMULA));++ if (bof->id == XLS_RECORD_MULRK)+ return (bof->size < offsetof(MULRK, rk));++ if (bof->id == XLS_RECORD_MULBLANK)+ return (bof->size < offsetof(MULBLANK, xf));++ if (bof->id == XLS_RECORD_LABELSST)+ return (bof->size < offsetof(LABEL, value) + (pWB->is5ver ? 2 : 4));++ if (bof->id == XLS_RECORD_LABEL) {+ if (bof->size < offsetof(LABEL, value) + 2)+ return 1;++ size_t label_len = ((LABEL*)buf)->value[0] + (((LABEL*)buf)->value[1] << 8);+ if (pWB->is5ver) {+ return (bof->size < offsetof(LABEL, value) + 2 + label_len);+ }++ if (bof->size < offsetof(LABEL, value) + 3)+ return 1;++ if ((((LABEL*)buf)->value[2] & 0x01) == 0) {+ return (bof->size < offsetof(LABEL, value) + 3 + label_len);+ }+ return (bof->size < offsetof(LABEL, value) + 3 + 2 * label_len);+ }++ if (bof->id == XLS_RECORD_RK)+ return (bof->size < sizeof(RK));++ if (bof->id == XLS_RECORD_NUMBER)+ return (bof->size < sizeof(BR_NUMBER));++ if (bof->id == XLS_RECORD_BOOLERR)+ return (bof->size < sizeof(BOOLERR));++ return 0;+}++void xls_cell_set_str(struct st_cell_data *cell, char *str) {+ if (cell->str) {+ free(cell->str);+ }+ cell->str = str;+}++static struct st_cell_data *xls_addCell(xlsWorkSheet* pWS,BOF* bof,BYTE* buf)+{+ struct st_cell_data* cell;+ struct st_row_data* row;+ WORD col;+ int i;++ verbose ("xls_addCell");++ if (xls_isCellTooSmall(pWS->workbook, bof, buf))+ return NULL;++ // printf("ROW: %u COL: %u\n", xlsShortVal(((COL*)buf)->row), xlsShortVal(((COL*)buf)->col));+ row=&pWS->rows.row[xlsShortVal(((COL*)buf)->row)];++ col = xlsShortVal(((COL*)buf)->col);+ if (col >= row->cells.count) {+ if (xls_debug) fprintf(stderr, "Error: Column index out of bounds\n");+ return NULL;+ }+ cell = &row->cells.cell[col];++ cell->id=bof->id;+ cell->xf=xlsShortVal(((COL*)buf)->xf);++ switch (bof->id)+ {+ case XLS_RECORD_FORMULA:+ case XLS_RECORD_FORMULA_ALT:+ xlsConvertFormula((FORMULA *)buf);+ cell->id=XLS_RECORD_FORMULA;+ if (((FORMULA*)buf)->res!=0xffff) {+ // if a double, then set double and clear l+ cell->l=0;+ memcpy(&cell->d, &((FORMULA*)buf)->resid, sizeof(double)); // Required for ARM+ cell->id = XLS_RECORD_NUMBER; // hack+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook,cell, NULL));+ cell->id = bof->id;+ } else {+ double d = ((FORMULA*)buf)->resdata[1];+ cell->l = 0xFFFF;+ switch(((FORMULA*)buf)->resid) {+ case 0: // String+ break; // cell is half complete, get the STRING next record+ case 1: // Boolean+ memcpy(&cell->d, &d, sizeof(double)); // Required for ARM+ xls_cell_set_str(cell, strdup("bool"));+ break;+ case 2: // error+ memcpy(&cell->d, &d, sizeof(double)); // Required for ARM+ xls_cell_set_str(cell, strdup("error"));+ break;+ case 3: // empty string+ xls_cell_set_str(cell, strdup(""));+ break;+ }+ }+ if(formula_handler) formula_handler(bof->id, bof->size, buf);+ break;+ case XLS_RECORD_MULRK:+ for (i = 0; i < (bof->size - 6)/6; i++) // 6 == 2 row + 2 col + 2 trailing index+ {+ WORD index = col + i;+ if(index >= row->cells.count) {+ if (xls_debug) fprintf(stderr, "Error: MULTI-RK index out of bounds\n");+ return NULL;+ }+ cell=&row->cells.cell[index];+ cell->id=XLS_RECORD_RK;+ cell->xf=xlsShortVal(((MULRK*)buf)->rk[i].xf);+ cell->d=NumFromRk(xlsIntVal(((MULRK*)buf)->rk[i].value));+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook,cell, NULL));+ }+ break;+ case XLS_RECORD_MULBLANK:+ for (i = 0; i < (bof->size - 6)/2; i++) // 6 == 2 row + 2 col + 2 trailing index+ {+ WORD index = col + i;+ if(index >= row->cells.count) {+ if (xls_debug) fprintf(stderr, "Error: MULTI-BLANK index out of bounds\n");+ return NULL;+ }+ cell=&row->cells.cell[index];+ cell->id=XLS_RECORD_BLANK;+ cell->xf=xlsShortVal(((MULBLANK*)buf)->xf[i]);+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook,cell, NULL));+ }+ break;+ case XLS_RECORD_LABELSST:+ case XLS_RECORD_LABEL:+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook, cell, ((LABEL*)buf)->value));+ if (cell->str) {+ sscanf((char *)cell->str, "%d", &cell->l);+ sscanf((char *)cell->str, "%lf", &cell->d);+ }+ break;+ case XLS_RECORD_RK:+ cell->d=NumFromRk(xlsIntVal(((RK*)buf)->value));+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook,cell, NULL));+ break;+ case XLS_RECORD_BLANK:+ break;+ case XLS_RECORD_NUMBER:+ xlsConvertDouble((BYTE *)&((BR_NUMBER*)buf)->value);+ memcpy(&cell->d, &((BR_NUMBER*)buf)->value, sizeof(double)); // Required for ARM+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook,cell, NULL));+ break;+ case XLS_RECORD_BOOLERR:+ cell->d = ((BOOLERR *)buf)->value;+ if (((BOOLERR *)buf)->iserror) {+ xls_cell_set_str(cell, strdup("error"));+ } else {+ xls_cell_set_str(cell, strdup("bool"));+ }+ break;+ default:+ xls_cell_set_str(cell, xls_getfcell(pWS->workbook,cell, NULL));+ break;+ }+ if (xls_debug) xls_showCell(cell);++ return cell;+}++static char *xls_addFont(xlsWorkBook* pWB, FONT* font, DWORD size)+{+ struct st_font_data* tmp;++ verbose("xls_addFont");++ pWB->fonts.font = realloc(pWB->fonts.font,(pWB->fonts.count+1)*sizeof(struct st_font_data));+ if (pWB->fonts.font == NULL)+ return NULL;++ tmp=&pWB->fonts.font[pWB->fonts.count];++ tmp->name = get_string(font->name, size - offsetof(FONT, name), 0, pWB->is5ver, pWB->charset);++ tmp->height=font->height;+ tmp->flag=font->flag;+ tmp->color=font->color;+ tmp->bold=font->bold;+ tmp->escapement=font->escapement;+ tmp->underline=font->underline;+ tmp->family=font->family;+ tmp->charset=font->charset;++ // xls_showFont(tmp);+ pWB->fonts.count++;++ return tmp->name;+}++static xls_error_t xls_addFormat(xlsWorkBook* pWB, FORMAT* format, DWORD size)+{+ struct st_format_data* tmp;++ verbose("xls_addFormat");+ pWB->formats.format = realloc(pWB->formats.format, (pWB->formats.count+1)*sizeof(struct st_format_data));+ if (pWB->formats.format == NULL)+ return LIBXLS_ERROR_MALLOC;++ tmp = &pWB->formats.format[pWB->formats.count];+ tmp->index = format->index;+ tmp->value = get_string(format->value, size - offsetof(FORMAT, value), (BYTE)!pWB->is5ver, (BYTE)pWB->is5ver, pWB->charset);+ if(xls_debug) xls_showFormat(tmp);+ pWB->formats.count++;++ return LIBXLS_OK;+}++static xls_error_t xls_addXF8(xlsWorkBook* pWB,XF8* xf)+{+ struct st_xf_data* tmp;++ verbose("xls_addXF");+ pWB->xfs.xf= realloc(pWB->xfs.xf, (pWB->xfs.count+1)*sizeof(struct st_xf_data));+ if (pWB->xfs.xf == NULL)+ return LIBXLS_ERROR_MALLOC;++ tmp=&pWB->xfs.xf[pWB->xfs.count];++ tmp->font=xf->font;+ tmp->format=xf->format;+ tmp->type=xf->type;+ tmp->align=xf->align;+ tmp->rotation=xf->rotation;+ tmp->ident=xf->ident;+ tmp->usedattr=xf->usedattr;+ tmp->linestyle=xf->linestyle;+ tmp->linecolor=xf->linecolor;+ tmp->groundcolor=xf->groundcolor;++ // xls_showXF(tmp);+ pWB->xfs.count++;++ return LIBXLS_OK;+}++static xls_error_t xls_addXF5(xlsWorkBook* pWB,XF5* xf)+{+ struct st_xf_data* tmp;++ verbose("xls_addXF");+ pWB->xfs.xf = realloc(pWB->xfs.xf, (pWB->xfs.count+1)*sizeof(struct st_xf_data));+ if (pWB->xfs.xf == NULL)+ return LIBXLS_ERROR_MALLOC;++ tmp=&pWB->xfs.xf[pWB->xfs.count];++ tmp->font=xf->font;+ tmp->format=xf->format;+ tmp->type=xf->type;+ tmp->align=(BYTE)xf->align;+/*+ tmp->rotation=xf->rotation;+ tmp->ident=xf->ident;+ tmp->usedattr=xf->usedattr;+ tmp->linestyle=xf->linestyle;+ tmp->linecolor=xf->linecolor;+ tmp->groundcolor=xf->groundcolor;+*/++ // xls_showXF(tmp);+ pWB->xfs.count++;+ return LIBXLS_OK;+}++static xls_error_t xls_addColinfo(xlsWorkSheet* pWS,COLINFO* colinfo)+{+ struct st_colinfo_data* tmp;++ verbose("xls_addColinfo");+ pWS->colinfo.col = realloc(pWS->colinfo.col,(pWS->colinfo.count+1)*sizeof(struct st_colinfo_data));+ if (pWS->colinfo.col == NULL)+ return LIBXLS_ERROR_MALLOC;++ tmp=&pWS->colinfo.col[pWS->colinfo.count];+ tmp->first=colinfo->first;+ tmp->last=colinfo->last;+ tmp->width=colinfo->width;+ tmp->xf=colinfo->xf;+ tmp->flags=colinfo->flags;++ if(xls_debug) xls_showColinfo(tmp);+ pWS->colinfo.count++;++ return LIBXLS_OK;+}++static xls_error_t xls_mergedCells(xlsWorkSheet* pWS,BOF* bof,BYTE* buf)+{+ if (bof->size < sizeof(WORD))+ return LIBXLS_ERROR_PARSE;++ int count = buf[0] + (buf[1] << 8);+ DWORD limit = sizeof(WORD)+count*sizeof(struct MERGEDCELLS);+ if(limit > (DWORD)bof->size) {+ verbose("Merged Cells Count out of range");+ return LIBXLS_ERROR_PARSE;+ }+ int i,c,r;+ struct MERGEDCELLS *span;+ verbose("Merged Cells");+ for (i=0;i<count;i++)+ {+ span=(struct MERGEDCELLS*)(buf+(2+i*sizeof(struct MERGEDCELLS)));+ xlsConvertMergedcells(span);+ // printf("Merged Cells: [%i,%i] [%i,%i] \n",span->colf,span->rowf,span->coll,span->rowl);+ // Sanity check:+ if(!( span->rowf <= span->rowl &&+ span->rowl <= pWS->rows.lastrow &&+ span->colf <= span->coll &&+ span->coll <= pWS->rows.lastcol+ )) {+ return LIBXLS_ERROR_PARSE;+ }++ for (r=span->rowf;r<=span->rowl;r++)+ for (c=span->colf;c<=span->coll;c++)+ pWS->rows.row[r].cells.cell[c].isHidden=1;+ pWS->rows.row[span->rowf].cells.cell[span->colf].colspan=(span->coll-span->colf+1);+ pWS->rows.row[span->rowf].cells.cell[span->colf].rowspan=(span->rowl-span->rowf+1);+ pWS->rows.row[span->rowf].cells.cell[span->colf].isHidden=0;+ }+ return LIBXLS_OK;+}++int xls_isRecordTooSmall(xlsWorkBook *pWB, BOF *bof1) {+ switch (bof1->id) {+ case XLS_RECORD_BOF: // BIFF5-8+ return (bof1->size < 2 * sizeof(WORD));+ case XLS_RECORD_CODEPAGE:+ return (bof1->size < sizeof(WORD));+ case XLS_RECORD_WINDOW1:+ return (bof1->size < sizeof(WIND1));+ case XLS_RECORD_SST:+ return (bof1->size < offsetof(SST, strings));+ case XLS_RECORD_BOUNDSHEET:+ return (bof1->size < offsetof(BOUNDSHEET, name));+ case XLS_RECORD_XF:+ if(pWB->is5ver) {+ return (bof1->size < sizeof(XF5));+ }+ return (bof1->size < sizeof(XF8));+ case XLS_RECORD_FONT:+ case XLS_RECORD_FONT_ALT:+ return (bof1->size < offsetof(FONT, name));+ case XLS_RECORD_FORMAT:+ return (bof1->size < offsetof(FORMAT, value));+ case XLS_RECORD_1904:+ return (bof1->size < sizeof(BYTE));+ default:+ break;+ }+ return 0;+}++xls_error_t xls_parseWorkBook(xlsWorkBook* pWB)+{+ BOF bof1 = { .id = 0, .size = 0 };+ BOF bof2 = { .id = 0, .size = 0 };+ BYTE* buf = NULL;+ BYTE once = 0;+ xls_error_t retval = LIBXLS_OK;++ verbose ("xls_parseWorkBook");+ do {+ if(xls_debug > 10) {+ printf("READ WORKBOOK filePos=%ld\n", (long)pWB->filepos);+ printf(" OLE: start=%d pos=%u size=%u fatPos=%u\n",+ pWB->olestr->start, (unsigned int)pWB->olestr->pos,+ (unsigned int)pWB->olestr->size, (unsigned int)pWB->olestr->fatpos); + }++ if (ole2_read(&bof1, 1, 4, pWB->olestr) != 4) {+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ xlsConvertBof(&bof1);+ if(xls_debug) xls_showBOF(&bof1);++ if (bof1.size) {+ if ((buf = realloc(buf, bof1.size)) == NULL) {+ if (xls_debug) fprintf(stderr, "Error: failed to allocate buffer of size %d\n", (int)bof1.size);+ retval = LIBXLS_ERROR_MALLOC;+ goto cleanup;+ }+ if (ole2_read(buf, 1, bof1.size, pWB->olestr) != bof1.size) {+ if (xls_debug) fprintf(stderr, "Error: failed to read OLE block\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ }++ if (xls_isRecordTooSmall(pWB, &bof1)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }++ switch (bof1.id) {+ case XLS_RECORD_EOF:+ //verbose("EOF");+ break;+ case XLS_RECORD_BOF: // BIFF5-8+ pWB->is5ver = (buf[0] + (buf[1] << 8) != 0x600);+ pWB->type = buf[2] + (buf[3] << 8);++ if(xls_debug) {+ printf("version: %s\n", pWB->is5ver ? "BIFF5" : "BIFF8" );+ printf(" type: %.2X\n", pWB->type);+ }+ break;++ case XLS_RECORD_CODEPAGE:+ pWB->codepage = buf[0] + (buf[1] << 8);+ if(xls_debug) printf("codepage=%x\n", pWB->codepage);+ break;++ case XLS_RECORD_CONTINUE:+ if(once) {+ if (bof2.id==XLS_RECORD_SST) {+ if ((retval = xls_appendSST(pWB,buf,bof1.size)) != LIBXLS_OK)+ goto cleanup;+ }+ bof1=bof2;+ }+ break;++ case XLS_RECORD_WINDOW1:+ {+ WIND1 *w = (WIND1*)buf;+ xlsConvertWindow(w);+ pWB->activeSheetIdx = w->itabCur;+ if(xls_debug) {+ printf("WINDOW1: ");+ printf("xWn : %d\n", w->xWn/20);+ printf("yWn : %d\n", w->yWn/20);+ printf("dxWn : %d\n", w->dxWn/20);+ printf("dyWn : %d\n", w->dyWn/20);+ printf("grbit : %d\n", w->grbit);+ printf("itabCur: %d\n", w->itabCur);+ printf("itabFi : %d\n", w->itabFirst);+ printf("ctabSel: %d\n", w->ctabSel);+ printf("wTabRat: %d\n", w->wTabRatio);+ }+ }+ break;++ case XLS_RECORD_SST:+ //printf("ADD SST\n");+ xlsConvertSst((SST *)buf);+ if ((retval = xls_addSST(pWB,(SST*)buf,bof1.size)) != LIBXLS_OK) {+ goto cleanup;+ }+ break;++ case XLS_RECORD_EXTSST:+ break;++ case XLS_RECORD_BOUNDSHEET:+ {+ //printf("ADD SHEET\n");+ BOUNDSHEET *bs = (BOUNDSHEET *)buf;+ xlsConvertBoundsheet(bs);+ //char *s;+ // different for BIFF5 and BIFF8+ /*s = */ xls_addSheet(pWB, bs, bof1.size);+ }+ break;++ case XLS_RECORD_XF:+ if(pWB->is5ver) {+ XF5 *xf;+ xf = (XF5 *)buf;+ xlsConvertXf5(xf);++ if ((retval = xls_addXF5(pWB,xf)) != LIBXLS_OK) {+ goto cleanup;+ }+ if(xls_debug) {+ printf(" font: %d\n", xf->font);+ printf(" format: %d\n", xf->format);+ printf(" type: %.4x\n", xf->type);+ printf(" align: %.4x\n", xf->align);+ printf("rotatio: %.4x\n", xf->color);+ printf(" ident: %.4x\n", xf->fill);+ printf("usedatt: %.4x\n", xf->border);+ printf("linesty: %.4x\n", xf->linestyle);+ }+ } else {+ XF8 *xf;+ xf = (XF8 *)buf;+ xlsConvertXf8(xf);++ if ((retval = xls_addXF8(pWB,xf)) != LIBXLS_OK) {+ goto cleanup;+ }++ if(xls_debug) {+ xls_showXF(xf);+ }+ }+ break;++ case XLS_RECORD_FONT:+ case XLS_RECORD_FONT_ALT:+ {+ char *s;+ FONT *f = (FONT*)buf;+ xlsConvertFont(f);+ s = xls_addFont(pWB,f, bof1.size);+ if(xls_debug) {+ printf(" height: %d\n", f->height);+ printf(" flag: 0x%x\n", f->flag);+ printf(" color: 0x%x\n", f->color);+ printf(" weight: %d\n", f->bold);+ printf("escapem: 0x%x\n", f->escapement);+ printf("underln: 0x%x\n", f->underline);+ printf(" family: 0x%x\n", f->family);+ printf("charset: 0x%x\n", f->charset);+ if(s) printf(" name: %s\n", s);+ }+ }+ break;++ case XLS_RECORD_FORMAT:+ xlsConvertFormat((FORMAT *)buf);+ if ((retval = xls_addFormat(pWB, (FORMAT*)buf, bof1.size)) != LIBXLS_OK) {+ goto cleanup;+ }+ break;++ case XLS_RECORD_STYLE:+ if(xls_debug) {+ struct { unsigned short idx; unsigned char ident; unsigned char lvl; } *styl;+ styl = (void *)buf;++ printf(" idx: 0x%x\n", styl->idx & 0x07FF);+ if(styl->idx & 0x8000) {+ printf(" ident: 0x%x\n", styl->ident);+ printf(" level: 0x%x\n", styl->lvl);+ } else {+ char *s = get_string((char *)&buf[2], bof1.size - 2, 1, pWB->is5ver, pWB->charset);+ printf(" name=%s\n", s);+ free(s);+ }+ }+ break;++ case XLS_RECORD_PALETTE:+ if(xls_debug > 10) {+ unsigned char *p = buf + 2;+ int idx, len;++ len = buf[0] + (buf[1] << 8);+ for(idx=0; idx<len; ++idx) {+ printf(" Index=0x%2.2x %2.2x%2.2x%2.2x\n", idx+8, p[0], p[1], p[2] );+ p += 4;+ }+ }+ break;++ case XLS_RECORD_1904:+ pWB->is1904 = *(BYTE *)buf; // the field is a short, but with little endian the first byte is 0 or 1+ if(xls_debug) {+ printf(" mode: 0x%x\n", pWB->is1904);+ }+ break;+ + case XLS_RECORD_DEFINEDNAME:+ if(xls_debug) {+ int i;+ printf(" DEFINEDNAME: ");+ for(i=0; i<bof1.size; ++i) printf("%2.2x ", buf[i]);+ printf("\n");+ }+ break;+ + default:+ if(xls_debug)+ {+ //xls_showBOF(&bof1);+ printf(" Not Processed in parseWoorkBook(): BOF=0x%4.4X size=%d\n", bof1.id, bof1.size);+ }+ break;+ }+ bof2=bof1;+ once=1;+ }+ while ((!pWB->olestr->eof)&&(bof1.id!=XLS_RECORD_EOF));++cleanup:+ if (buf)+ free(buf);++ return retval;+}+++static xls_error_t xls_preparseWorkSheet(xlsWorkSheet* pWS)+{+ BOF tmp;+ BYTE* buf = NULL;+ xls_error_t retval = LIBXLS_OK;++ verbose ("xls_preparseWorkSheet");++ if (ole2_seek(pWS->workbook->olestr,pWS->filepos) == -1) {+ retval = LIBXLS_ERROR_SEEK;+ goto cleanup;+ }+ do+ {+ size_t read;+ if((read = ole2_read(&tmp, 1, 4, pWS->workbook->olestr)) != 4) {+ if (xls_debug) fprintf(stderr, "Error: failed to read OLE size\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ xlsConvertBof(&tmp);+ if (tmp.size) {+ if ((buf = realloc(buf, tmp.size)) == NULL) {+ if (xls_debug) fprintf(stderr, "Error: failed to allocate buffer of size %d\n", (int)tmp.size);+ retval = LIBXLS_ERROR_MALLOC;+ goto cleanup;+ }+ if((read = ole2_read(buf, 1, tmp.size, pWS->workbook->olestr)) != tmp.size) {+ if (xls_debug) fprintf(stderr, "Error: failed to read OLE block\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ }++ switch (tmp.id)+ {+ case XLS_RECORD_DEFCOLWIDTH:+ if (tmp.size < sizeof(WORD)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ pWS->defcolwidth = (buf[0] << 8) + (buf[1] << 16);+ break;+ case XLS_RECORD_COLINFO:+ if (tmp.size < sizeof(COLINFO)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ xlsConvertColinfo((COLINFO*)buf);+ if ((retval = xls_addColinfo(pWS,(COLINFO*)buf)) != LIBXLS_OK)+ goto cleanup;+ break;+ case XLS_RECORD_ROW:+ if (tmp.size < sizeof(ROW)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ xlsConvertRow((ROW*)buf);+ if (pWS->rows.lastcol<((ROW*)buf)->lcell)+ pWS->rows.lastcol=((ROW*)buf)->lcell;+ if (pWS->rows.lastrow<((ROW*)buf)->index)+ pWS->rows.lastrow=((ROW*)buf)->index;+ break;+ /* If the ROW record is incorrect or missing, infer the information from+ * cell data. */+ case XLS_RECORD_MULRK:+ if (xls_isCellTooSmall(pWS->workbook, &tmp, buf)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ if (pWS->rows.lastcol<xlsShortVal(((MULRK*)buf)->col) + (tmp.size - 6)/6 - 1)+ pWS->rows.lastcol=xlsShortVal(((MULRK*)buf)->col) + (tmp.size - 6)/6 - 1;+ if (pWS->rows.lastrow<xlsShortVal(((MULRK*)buf)->row))+ pWS->rows.lastrow=xlsShortVal(((MULRK*)buf)->row);+ break;+ case XLS_RECORD_MULBLANK:+ if (xls_isCellTooSmall(pWS->workbook, &tmp, buf)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ if (pWS->rows.lastcol<xlsShortVal(((MULBLANK*)buf)->col) + (tmp.size - 6)/2 - 1)+ pWS->rows.lastcol=xlsShortVal(((MULBLANK*)buf)->col) + (tmp.size - 6)/2 - 1;+ if (pWS->rows.lastrow<xlsShortVal(((MULBLANK*)buf)->row))+ pWS->rows.lastrow=xlsShortVal(((MULBLANK*)buf)->row);+ break;+ case XLS_RECORD_NUMBER:+ case XLS_RECORD_RK:+ case XLS_RECORD_LABELSST:+ case XLS_RECORD_BLANK:+ case XLS_RECORD_LABEL:+ case XLS_RECORD_FORMULA:+ case XLS_RECORD_FORMULA_ALT:+ case XLS_RECORD_BOOLERR:+ if (xls_isCellTooSmall(pWS->workbook, &tmp, buf)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ if (pWS->rows.lastcol<xlsShortVal(((COL*)buf)->col))+ pWS->rows.lastcol=xlsShortVal(((COL*)buf)->col);+ if (pWS->rows.lastrow<xlsShortVal(((COL*)buf)->row))+ pWS->rows.lastrow=xlsShortVal(((COL*)buf)->row);+ break;+ }+ if (pWS->rows.lastcol > 256) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ }+ while ((!pWS->workbook->olestr->eof)&&(tmp.id!=XLS_RECORD_EOF));++cleanup:+ if (buf)+ free(buf);+ return retval;+}++static xls_error_t xls_formatColumn(xlsWorkSheet* pWS)+{+ DWORD i,t,ii;+ DWORD fcol,lcol;+ WORD width;+ BYTE isHidden;++ for (i=0;i<pWS->colinfo.count;i++)+ {+ width = pWS->colinfo.col[i].width;+ isHidden = (pWS->colinfo.col[i].flags&1);+ if (pWS->colinfo.col[i].first<=pWS->rows.lastcol)+ fcol=pWS->colinfo.col[i].first;+ else+ fcol=pWS->rows.lastcol;++ if (pWS->colinfo.col[i].last<=pWS->rows.lastcol)+ lcol=pWS->colinfo.col[i].last;+ else+ lcol=pWS->rows.lastcol;++ for (ii=0;ii<=pWS->rows.lastrow;ii++) {+ for (t=fcol;t<=lcol;t++) {+ pWS->rows.row[ii].cells.cell[t].isHidden |= isHidden;+ pWS->rows.row[ii].cells.cell[t].width = width;+ }+ }+ }+ return LIBXLS_OK;+}++xls_error_t xls_parseWorkSheet(xlsWorkSheet* pWS)+{+ BOF tmp;+ BYTE* buf = NULL;+ long offset = pWS->filepos;+ size_t read;+ xls_error_t retval = 0;++ struct st_cell_data *cell = NULL;+ xlsWorkBook *pWB = pWS->workbook;++ verbose ("xls_parseWorkSheet");++ if ((retval = xls_preparseWorkSheet(pWS)) != LIBXLS_OK) {+ goto cleanup;+ }+ // printf("size=%d fatpos=%d)\n", pWS->workbook->olestr->size, pWS->workbook->olestr->fatpos);++ if ((retval = xls_makeTable(pWS)) != LIBXLS_OK) {+ goto cleanup;+ }++ if ((retval = xls_formatColumn(pWS)) != LIBXLS_OK) {+ goto cleanup;+ }++ if (ole2_seek(pWS->workbook->olestr,pWS->filepos) == -1) {+ retval = LIBXLS_ERROR_SEEK;+ goto cleanup;+ }+ do+ {+ long lastPos = offset;++ if(xls_debug > 10) {+ printf("LASTPOS=%ld pos=%d filePos=%d filePos=%d\n", lastPos, (int)pWB->olestr->pos, pWS->filepos, pWB->filepos);+ }+ if((read = ole2_read(&tmp, 1, 4, pWS->workbook->olestr)) != 4) {+ if (xls_debug) fprintf(stderr, "Error: failed to read OLE size\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ xlsConvertBof((BOF *)&tmp);+ if (tmp.size) {+ if ((buf = realloc(buf, tmp.size)) == NULL) {+ if (xls_debug) fprintf(stderr, "Error: failed to allocate buffer of size %d\n", (int)tmp.size);+ retval = LIBXLS_ERROR_MALLOC;+ goto cleanup;+ }+ if((read = ole2_read(buf, 1, tmp.size, pWS->workbook->olestr)) != tmp.size) {+ if (xls_debug) fprintf(stderr, "Error: failed to read OLE block\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ }+ offset += 4 + tmp.size;++ if(xls_debug)+ xls_showBOF(&tmp);++ switch (tmp.id)+ {+ case XLS_RECORD_EOF:+ break;+ case XLS_RECORD_MERGEDCELLS:+ if ((retval = xls_mergedCells(pWS,&tmp,buf)) != LIBXLS_OK) {+ goto cleanup;+ }+ break;+ case XLS_RECORD_ROW:+ if (tmp.size < sizeof(ROW)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ if(xls_debug > 10) printf("ROW: %x at pos=%ld\n", tmp.id, lastPos);+ xlsConvertRow((ROW *)buf);+ if ((retval = xls_addRow(pWS,(ROW*)buf)) != LIBXLS_OK) {+ goto cleanup;+ }+ break;+ case XLS_RECORD_DEFCOLWIDTH:+ if (tmp.size < sizeof(WORD)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ if(xls_debug > 10) printf("DEFAULT COL WIDTH: %d\n", ((WORD *)buf)[0]);+ break;+ case XLS_RECORD_DEFAULTROWHEIGHT:+ if (tmp.size < 2 * sizeof(WORD)) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ if(xls_debug > 10) printf("DEFAULT ROW Height: 0x%x %d\n", ((WORD *)buf)[0], ((WORD *)buf)[1]);+ break;+ case XLS_RECORD_DBCELL:+ if(xls_debug > 10) {+ DWORD *foo = (DWORD *)buf;+ WORD *goo;+ int i;+ printf("DBCELL: size %d\n", tmp.size);+ printf("DBCELL OFFSET=%4.4u -> ROW %ld\n", foo[0], lastPos-foo[0]);+ ++foo;+ goo = (WORD *)foo;+ for(i=0; i<5; ++i) printf("goo[%d]=%4.4x %u\n", i, goo[i], goo[i]);+ }+ break;+ case XLS_RECORD_INDEX:+ if(xls_debug > 10) {+ DWORD *foo = (DWORD *)buf;+ int i;+ printf("INDEX: size %d\n", tmp.size);+ for(i=0; i<5; ++i) printf("FOO[%d]=%4.4x %u\n", i, foo[i], foo[i]);+ }+#if 0+ 0 4 4 4 8 4+ 12 4 16 4∙nm+ Not used Index to first used row (rf, 0-based) Index to first row of unused tail of sheet (rl, last used row + 1, 0-based)+ Absolute stream position of the DEFCOLWIDTH record (➜5.32) of the current sheet. If this record does not exist, the offset points to the record at the position where the DEFCOLWIDTH record would occur.+ Array of nm absolute stream positions to the DBCELL record (➜5.29) of each Row Block+#endif+ break;+ case XLS_RECORD_MULRK:+ case XLS_RECORD_MULBLANK:+ case XLS_RECORD_NUMBER:+ case XLS_RECORD_BOOLERR:+ case XLS_RECORD_RK:+ case XLS_RECORD_LABELSST:+ case XLS_RECORD_BLANK:+ case XLS_RECORD_LABEL:+ case XLS_RECORD_FORMULA:+ case XLS_RECORD_FORMULA_ALT:+ if ((cell = xls_addCell(pWS, &tmp, buf)) == NULL) {+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }+ break;+ case XLS_RECORD_ARRAY:+ if(formula_handler) formula_handler(tmp.id, tmp.size, buf);+ break;++ case XLS_RECORD_STRING:+ if(cell && (cell->id == XLS_RECORD_FORMULA || cell->id == XLS_RECORD_FORMULA_ALT)) {+ xls_cell_set_str(cell, get_string((char *)buf, tmp.size,+ (BYTE)!pWB->is5ver, pWB->is5ver, pWB->charset));+ if (xls_debug) xls_showCell(cell);+ }+ break;++ default:+ if(xls_debug)+ {+ //xls_showBOF(&tmp);+ if (tmp.size >= sizeof(COL)) {+ printf(" [%d:%d]: 0x%X at pos=%lu size=%u\n", xlsShortVal(((COL*)buf)->row), xlsShortVal(((COL*)buf)->col),+ tmp.id, lastPos, tmp.size);+ } else {+ printf(" 0x%X at pos=%lu size=%u\n", tmp.id, lastPos, tmp.size);+ }+ }+ break;+ }+ }+ while ((!pWS->workbook->olestr->eof)&&(tmp.id!=XLS_RECORD_EOF));++cleanup:+ if (buf)+ free(buf);++ return retval;+}++xlsWorkSheet * xls_getWorkSheet(xlsWorkBook* pWB,int num)+{+ xlsWorkSheet * pWS = NULL;+ verbose ("xls_getWorkSheet");+ if (num >= 0 && num < (int)pWB->sheets.count) {+ pWS = calloc(1, sizeof(xlsWorkSheet));+ pWS->filepos=pWB->sheets.sheet[num].filepos;+ pWS->workbook=pWB;+ pWS->rows.lastcol=0;+ pWS->rows.lastrow=0;+ pWS->colinfo.count=0;+ }+ return pWS;+}++static xlsWorkBook *xls_open_ole(OLE2 *ole, const char *charset, xls_error_t *outError) {+ xlsWorkBook* pWB;+ xls_error_t retval = LIBXLS_OK;++ pWB = calloc(1, sizeof(xlsWorkBook));+ verbose ("xls_open_ole");++ if ((pWB->olestr=ole2_fopen(ole, "\005SummaryInformation")))+ {+ pWB->summary = calloc(1,4096);+ if (ole2_read(pWB->summary, 4096, 1, pWB->olestr) == -1) {+ if (xls_debug) fprintf(stderr, "SummaryInformation not found\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ ole2_fclose(pWB->olestr);+ }++ if ((pWB->olestr=ole2_fopen(ole, "\005DocumentSummaryInformation")))+ {+ pWB->docSummary = calloc(1, 4096);+ if (ole2_read(pWB->docSummary, 4096, 1, pWB->olestr) == -1) {+ if (xls_debug) fprintf(stderr, "DocumentSummaryInformation not found\n");+ retval = LIBXLS_ERROR_READ;+ goto cleanup;+ }+ ole2_fclose(pWB->olestr);+ }++#if 0+ if(xls_debug) {+ printf("summary=%d docsummary=%d\n", pWB->summary ? 1 : 0, pWB->docSummary ? 1 : 0);+ xlsSummaryInfo *si = xls_summaryInfo(pWB);+ printf("title=%s\n", si->title);+ printf("subject=%s\n", si->subject);+ printf("author=%s\n", si->author);+ printf("keywords=%s\n", si->keywords);+ printf("comment=%s\n", si->comment);+ printf("lastAuthor=%s\n", si->lastAuthor);+ printf("appName=%s\n", si->appName);+ printf("category=%s\n", si->category);+ printf("manager=%s\n", si->manager);+ printf("company=%s\n", si->company);+ }+#endif++ // open Workbook+ if (!(pWB->olestr=ole2_fopen(ole,"Workbook")) && !(pWB->olestr=ole2_fopen(ole,"Book")))+ {+ if(xls_debug) fprintf(stderr, "Workbook not found\n");+ retval = LIBXLS_ERROR_PARSE;+ goto cleanup;+ }++ pWB->sheets.count=0;+ pWB->xfs.count=0;+ pWB->fonts.count=0;+ if (charset) {+ pWB->charset = malloc(strlen(charset) * sizeof(char)+1);+ strcpy(pWB->charset, charset);+ } else {+ pWB->charset = strdup("UTF-8");+ }++ retval = xls_parseWorkBook(pWB);++cleanup:+ if (retval != LIBXLS_OK) {+ if (!pWB->olestr)+ ole2_close(ole);+ xls_close_WB(pWB);+ pWB = NULL;+ }+ if (outError)+ *outError = retval;++ return pWB;+}++xlsWorkBook* xls_open(const char *file, const char* charset)+{+ return xls_open_file(file, charset, NULL);+}++xlsWorkBook* xls_open_file(const char *file, const char* charset, xls_error_t *outError) {+ OLE2* ole = NULL;++ if (!(ole=ole2_open_file(file)))+ {+ if (xls_debug) fprintf(stderr, "File \"%s\" not found\n",file);+ if (outError) *outError = LIBXLS_ERROR_OPEN;+ return NULL;+ }++ return xls_open_ole(ole, charset, outError);+}++xlsWorkBook *xls_open_buffer(const unsigned char *buffer, size_t len,+ const char *charset, xls_error_t *outError) {+ OLE2* ole = NULL;++ if (!(ole=ole2_open_buffer(buffer, len)))+ {+ if (outError) *outError = LIBXLS_ERROR_OPEN;+ return NULL;+ }++ return xls_open_ole(ole, charset, outError);+}++xlsRow *xls_row(xlsWorkSheet* pWS, WORD cellRow)+{+ if(cellRow > pWS->rows.lastrow)+ return NULL;++ if (pWS->rows.row == NULL)+ return NULL;++ return &pWS->rows.row[cellRow];+}++xlsCell *xls_cell(xlsWorkSheet* pWS, WORD cellRow, WORD cellCol)+{+ struct st_row_data *row;++ if ((row = xls_row(pWS, cellRow)) == NULL)+ return NULL;++ if(cellCol >= row->cells.count)+ return NULL;++ return &row->cells.cell[cellCol];+}++void xls_close_WB(xlsWorkBook* pWB)+{+ OLE2* ole;++ verbose ("xls_close");++ if(!pWB) return;++ // OLE first+ if (pWB->olestr) {+ ole=pWB->olestr->ole;+ ole2_fclose(pWB->olestr);+ ole2_close(ole);+ }++ // WorkBook+ free(pWB->charset);++ // Sheets+ {+ DWORD i;+ for(i=0; i<pWB->sheets.count; ++i) {+ free(pWB->sheets.sheet[i].name);+ }+ free(pWB->sheets.sheet);+ }++ // SST+ {+ DWORD i;+ for(i=0; i<pWB->sst.count; ++i) {+ free(pWB->sst.string[i].str);+ }+ free(pWB->sst.string);+ }++ // xfs+ {+ free(pWB->xfs.xf);+ }++ // fonts+ {+ DWORD i;+ for(i=0; i<pWB->fonts.count; ++i) {+ free(pWB->fonts.font[i].name);+ }+ free(pWB->fonts.font);+ }++ // formats+ {+ DWORD i;+ for(i=0; i<pWB->formats.count; ++i) {+ free(pWB->formats.format[i].value);+ }+ free(pWB->formats.format);+ }++ // buffers+ if(pWB->summary) free(pWB->summary);+ if(pWB->docSummary) free(pWB->docSummary);++ // TODO - free other dynamically allocated objects like string table??+ free(pWB);+}++void xls_close_WS(xlsWorkSheet* pWS)+{+ if(!pWS) return;++ if (pWS->rows.row) {+ DWORD i, j;+ for(j=0; j<=pWS->rows.lastrow; ++j) {+ struct st_row_data *row = &pWS->rows.row[j];+ for(i=0; i<row->cells.count; ++i) {+ free(row->cells.cell[i].str);+ }+ free(row->cells.cell);+ }+ free(pWS->rows.row);+ }++ // COLINFO+ {+ free(pWS->colinfo.col);+ }+ free(pWS);+}++const char* xls_getVersion(void)+{+ return PACKAGE_VERSION;+}++const char* xls_getError(xls_error_t code) {+ if (code == LIBXLS_OK)+ return "No error";+ if (code == LIBXLS_ERROR_READ)+ return "Unable to read from file";+ if (code == LIBXLS_ERROR_OPEN)+ return "Unable to open file";+ if (code == LIBXLS_ERROR_SEEK)+ return "Unable to seek within file";+ if (code == LIBXLS_ERROR_MALLOC)+ return "Unable to allocate memory";+ if (code == LIBXLS_ERROR_PARSE)+ return "Unable to parse file";++ return "Unknown error";+}++//+// http://poi.apache.org/hpsf/internals.html+// or google "DocumentSummaryInformation and UserDefined Property Sets" and look for MSDN hits+//++xlsSummaryInfo *xls_summaryInfo(xlsWorkBook* pWB)+{+ xlsSummaryInfo *pSI;++ pSI = (xlsSummaryInfo *)calloc(1, sizeof(xlsSummaryInfo));+ xls_dumpSummary(pWB->summary, 1, pSI);+ xls_dumpSummary(pWB->docSummary, 0, pSI);++ return pSI;+}++void xls_close_summaryInfo(xlsSummaryInfo *pSI)+{+ if(!pSI) return;++ if(pSI->title) free(pSI->title);+ if(pSI->subject) free(pSI->subject);+ if(pSI->author) free(pSI->author);+ if(pSI->keywords) free(pSI->keywords);+ if(pSI->comment) free(pSI->comment);+ if(pSI->lastAuthor) free(pSI->lastAuthor);+ if(pSI->appName) free(pSI->appName);+ if(pSI->category) free(pSI->category);+ if(pSI->manager) free(pSI->manager);+ if(pSI->company) free(pSI->company);++ free(pSI);+}++static void xls_dumpSummary(char *buf,int isSummary,xlsSummaryInfo *pSI) {+ header *head;+ sectionList *secList;+ propertyList *plist;+ sectionHeader *secHead;+ property *prop;+ uint32_t i, j;++ if(!buf) return; // perhaps the document was missing??++ head = (header *)buf;+ //printf("header: \n");+ //printf(" sig=%x\n", head->sig);+ //printf(" os=%x\n", head->os >> 16);+ //printf(" class=%8.8x%8.8x%8.8x%8.8x\n", head->format[0], head->format[1], head->format[2], head->format[3]);+ //printf(" count=%x\n", head->count);++ for(i=0; i<head->count; ++i) {+ secList = &head->secList[i];+ //printf("Section %d:\n", i);+ //printf(" class=%8.8x%8.8x%8.8x%8.8x\n", secList->format[0], secList->format[1], secList->format[2], secList->format[3]);+ //printf(" offset=%d (now at %ld\n", secList->offset, (char *)secList - (char *)buf + sizeof(sectionList));+++ secHead = (sectionHeader *)((char *)head + secList->offset);+ //printf(" len=%d\n", secHead->length);+ //printf(" properties=%d\n", secHead->numProperties);+ for(j=0; j<secHead->numProperties; ++j) {+ BYTE **s;++ plist = &secHead->properties[j];+ //printf(" ---------\n");+ //printf(" propID=%d offset=%d\n", plist->propertyID, plist->sectionOffset);+ prop = (property *)((char *)secHead + plist->sectionOffset);+ //printf(" propType=%d\n", prop->propertyID);++ switch(prop->propertyID) {+ case 2:+ //printf(" xlsShortVal=%x\n", *(uint16_t *)prop->data);+ break;+ case 3:+ //printf(" wordVal=%x\n", *(uint32_t *)prop->data);+ break;+ case 30:+ //printf(" longVal=%llx\n", *(uint64_t *)prop->data);+ //printf(" s[%u]=%s\n", *(uint32_t *)prop->data, (char *)prop->data + 4);+ if(isSummary) {+ switch(plist->propertyID) {+ case 2: s = &pSI->title; break;+ case 3: s = &pSI->subject; break;+ case 4: s = &pSI->author; break;+ case 5: s = &pSI->keywords; break;+ case 6: s = &pSI->comment; break;+ case 8: s = &pSI->lastAuthor; break;+ case 18: s = &pSI->appName; break;+ default: s = NULL; break;+ }+ } else {+ switch(plist->propertyID) {+ case 2: s = &pSI->category; break;+ case 14: s = &pSI->manager; break;+ case 15: s = &pSI->company; break;+ default: s = NULL; break;+ }+ }+ if(s) *s = (BYTE *)strdup((char *)prop->data + 4);+ break;+ case 64:+ //printf(" longVal=%llx\n", *(uint64_t *)prop->data);+ break;+ case 65:+#if 0+ {+ uint32_t k;+ for(k=0; k<*(uint32_t *)prop->data; ++k) {+ unsigned char *t = (unsigned char *)prop->data + 4 + k;+ printf(" %2.2x(%c)", *t, *t);+ }+ printf("\n");+ }+#endif+ break;+ default:+ //printf(" UNKNOWN!\n");+ break;+ }+ }+ }+}++void xls_set_formula_hander(xls_formula_handler handler)+{+ formula_handler = handler;+}
lib/libxls/src/xlstool.c view
@@ -1,32 +1,35 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *- * This file is part of libxls -- A multiplatform, C/C++ library- * for parsing Excel(TM) files.+ * Copyright 2004 Komarov Valery+ * Copyright 2006 Christophe Leitienne+ * Copyright 2008-2017 David Hoerl+ * Copyright 2013 Bob Colbert+ * Copyright 2013-2018 Evan Miller *- * Redistribution and use in source and binary forms, with or without modification, are- * permitted provided that the following conditions are met:+ * This file is part of libxls -- A multiplatform, C/C++ library for parsing+ * Excel(TM) files. *- * 1. Redistributions of source code must retain the above copyright notice, this list of- * conditions and the following disclaimer.+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions are met: *- * 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.+ * 1. Redistributions of source code must retain the above copyright notice,+ * this list of conditions and the following disclaimer. *- * 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.+ * 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. *- * Copyright 2004 Komarov Valery- * Copyright 2006 Christophe Leitienne- * Copyright 2013 Bob Colbert- * Copyright 2008-2013 David Hoerl+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''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 THE COPYRIGHT HOLDERS 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. * */ @@ -39,7 +42,14 @@ #ifdef HAVE_ICONV #include <iconv.h>++#if defined(_AIX) || defined(__sun)+static const char *from_enc = "UTF-16le"; #else+static const char *from_enc = "UTF-16LE";+#endif++#else #include <locale.h> #endif @@ -49,15 +59,30 @@ #include <string.h> //#include "xls.h"-#include "libxls/xlstypes.h"-#include "libxls/xlsstruct.h"-#include "libxls/xlstool.h"-#include "libxls/brdb.h"-#include "libxls/endian.h"+#include "../include/libxls/xlstypes.h"+#include "../include/libxls/xlsstruct.h"+#include "../include/libxls/xlstool.h"+#include "../include/libxls/brdb.h"+#include "../include/libxls/endian.h" extern int xls_debug; -static void xls_showBOUNDSHEET(void* bsheet);+/* Not a complete list */+enum xls_format_e {+ XLS_FORMAT_GENERAL, // ""+ XLS_FORMAT_NUMBER1, // "0"+ XLS_FORMAT_NUMBER2, // "0.00",+ XLS_FORMAT_NUMBER3, // "#,##0",+ XLS_FORMAT_NUMBER4, // "#,##0.00",+ XLS_FORMAT_CURRENCY1, // "\"$\"#,##0_);(\"$\"#,##0)",+ XLS_FORMAT_CURRENCY2, // "\"$\"#,##0_);[Red](\"$\"#,##0)",+ XLS_FORMAT_CURRENCY3, // "\"$\"#,##0.00_);(\"$\"#,##0.00)",+ XLS_FORMAT_CURRENCY4, // "\"$\"#,##0.00_);[Red](\"$\"#,##0.00)",+ XLS_FORMAT_PERCENT1, // "0%",+ XLS_FORMAT_PERCENT2, // "0.00%",+ XLS_FORMAT_SCIENTIFIC1, // "0.00E+00",+ XLS_FORMAT_SCIENTIFIC2 = 34 // "##0.0E+0"+}; static const DWORD colors[] = {@@ -119,84 +144,7 @@ 0x333333 }; -#if HAVE_ASPRINTF != 1 -#include <stdarg.h>--#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) {@@ -204,10 +152,10 @@ printf("libxls : %s\n",str); } -BYTE *utf8_decode(BYTE *str, DWORD len, char *encoding)+char *utf8_decode(const char *str, DWORD len, char *encoding) { int utf8_chars = 0;- BYTE *ret;+ char *ret = NULL; DWORD i; for(i=0; i<len; ++i) {@@ -217,14 +165,14 @@ } if(utf8_chars == 0 || strcmp(encoding, "UTF-8")) {- ret = (BYTE *)malloc(len+1);+ ret = malloc(len+1); memcpy(ret, str, len); ret[len] = 0; } else { DWORD i;- BYTE *out;+ char *out; // UTF-8 encoding inline- ret = (BYTE *)malloc(len+utf8_chars+1);+ ret = malloc(len+utf8_chars+1); out = ret; for(i=0; i<len; ++i) { BYTE c = str[i];@@ -241,17 +189,9 @@ 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;+static char* unicode_decode_iconv(const char *s, size_t len, size_t *newlen, const char* to_enc) {+ char* outbuf = 0; if(s && len && from_enc && to_enc) {@@ -259,8 +199,8 @@ 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;+ const char* src_ptr = s;+ char* out_ptr = 0; if(ic == (iconv_t)-1) {@@ -284,14 +224,14 @@ } } size_t st; - outbuf = (BYTE*)malloc(outlen + 1);+ outbuf = malloc(outlen + 1); if(outbuf) {- out_ptr = (BYTE*)outbuf;+ out_ptr = outbuf; while(inlenleft) {- st = iconv(ic, (char **)&src_ptr, &inlenleft, (char **)&out_ptr,(size_t *) &outlenleft);+ st = iconv(ic, (ICONV_CONST char **)&src_ptr, &inlenleft, (char **)&out_ptr,(size_t *) &outlenleft); if(st == (size_t)(-1)) { if(errno == E2BIG)@@ -299,7 +239,7 @@ size_t diff = out_ptr - outbuf; outlen += inlenleft; outlenleft += inlenleft;- outbuf = (BYTE*)realloc(outbuf, outlen + 1);+ outbuf = realloc(outbuf, outlen + 1); if(!outbuf) { break;@@ -327,95 +267,113 @@ } } 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;+static char *unicode_decode_wcstombs(const char *s, size_t len, size_t *newlen) {+ // Do wcstombs conversion+ char *converted = NULL;+ int count, count2;+ size_t i;+ wchar_t *w;+ if (setlocale(LC_CTYPE, "") == NULL) {+ printf("setlocale failed: %d\n", errno);+ return NULL;+ } - w = (wchar_t*)malloc((len+1)*sizeof(wchar_t));+ w = malloc((len/2+1)*sizeof(wchar_t)); - for(i=0; i<len; i++)+ for(i=0; i<len/2; i++) {- w[i]=xlsShortVal(x[i]);+ w[i] = (BYTE)s[2*i] + ((BYTE)s[2*i+1] << 8); }- w[len] = '\0';+ w[len/2] = '\0'; count = wcstombs(NULL, w, 0); - if (count <= 0) {- if (newlen) *newlen = 0;- return NULL;- }+ if (count <= 0) {+ if (newlen) *newlen = 0;+ free(w);+ return NULL;+ } - converted = calloc(count+1, sizeof(char));- count2 = wcstombs(converted, w, count);+ converted = calloc(count+1, sizeof(char));+ count2 = wcstombs(converted, w, count); free(w);- if (count2 <= 0) {- printf("wcstombs failed (%d)\n", len);- if (newlen) *newlen = 0;- return converted;- } else {- if (newlen) *newlen = count2;- return converted;- }+ if (count2 <= 0) {+ printf("wcstombs failed (%lu)\n", (unsigned long)len/2);+ if (newlen) *newlen = 0;+ return converted;+ }+ if (newlen) *newlen = count2;+ return converted;+} #endif++// Convert unicode string to to_enc encoding+char* unicode_decode(const char *s, size_t len, size_t *newlen, const char* to_enc)+{+#ifdef HAVE_ICONV+ return unicode_decode_iconv(s, len, newlen, to_enc);+#else+ return unicode_decode_wcstombs(s, len, newlen);+#endif } // Read and decode string-BYTE* get_string(BYTE *s, BYTE is2, BYTE is5ver, char *charset)+char *get_string(const char *s, size_t len, BYTE is2, BYTE is5ver, char *charset) { WORD ln;- DWORD ofs;- BYTE flag;- BYTE* str;- BYTE* ret;+ DWORD ofs = 0;+ BYTE flag = 0;+ const char *str = s;+ char *ret = NULL; - flag = 0;- str=s;-- ofs=0;- if (is2) { // length is two bytes- ln=xlsShortVal(*(WORD_UA *)str);+ if (ofs + 2 > len) {+ return NULL;+ }+ ln= ((BYTE*)str)[0] + (((BYTE*)str)[1] << 8); ofs+=2; } else { // single byte length+ if (ofs + 1 > len) {+ return NULL;+ } ln=*(BYTE*)str; ofs++; } if(!is5ver) { // unicode strings have a format byte before the string+ if (ofs + 1 > len) {+ return NULL;+ } flag=*(BYTE*)(str+ofs); ofs++; }- if (flag&0x8)- {+ if (flag&0x8) { // WORD rt; // rt=*(WORD*)(str+ofs); // unused ofs+=2; }- if (flag&0x4)- {+ if (flag&0x4) { // DWORD sz; // sz=*(DWORD*)(str+ofs); // unused ofs+=4; }- if(flag & 0x1)- {- size_t new_len = 0;- ret = unicode_decode(str+ofs,ln*2, &new_len,charset);+ if(flag & 0x1) {+ if (ofs + 2*ln > len) {+ return NULL;+ }+ ret = unicode_decode(str+ofs, ln*2, NULL, charset); } else {- ret = utf8_decode((str+ofs), ln, charset);+ if (ofs + ln > len) {+ return NULL;+ }+ ret = utf8_decode(str+ofs, ln, charset); } #if 0 // debugging@@ -622,78 +580,91 @@ printf("GroundColor: 0x%x\n",xf->groundcolor); } -BYTE *xls_getfcell(xlsWorkBook* pWB,struct st_cell_data* cell,WORD *label)+char *xls_getfcell(xlsWorkBook* pWB, struct st_cell_data* cell, BYTE *label) {- struct st_xf_data *xf;- WORD len;+ struct st_xf_data *xf = NULL;+ WORD len = 0;+ DWORD offset = 0; char *ret = NULL;+ size_t retlen = 100; - xf=&pWB->xfs.xf[cell->xf];+ if (cell->xf < pWB->xfs.count)+ 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);+ offset = label[0] + (label[1] << 8);+ if(!pWB->is5ver) {+ offset += ((DWORD)label[2] << 16);+ offset += ((DWORD)label[3] << 24);+ }+ if(offset < pWB->sst.count && pWB->sst.string[offset].str) {+ ret = strdup(pWB->sst.string[offset].str);+ } break; case XLS_RECORD_BLANK: case XLS_RECORD_MULBLANK:- asprintf(&ret, "");+ ret = strdup(""); break; case XLS_RECORD_LABEL:- len = xlsShortVal(*label);- label++;+ len = label[0] + (label[1] << 8);+ label += 2; if(pWB->is5ver) {- asprintf(&ret,"%.*s", len, (char *)label);+ ret = malloc(len+1);+ memcpy(ret, label, len);+ ret[len] = 0; //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);- }+ if ((*(label++) & 0x01) == 0) {+ ret = utf8_decode((char *)label, len, pWB->charset);+ } else {+ ret = unicode_decode((char *)label, len*2, NULL, pWB->charset);+ }+ } break; case XLS_RECORD_RK: case XLS_RECORD_NUMBER:- asprintf(&ret,"%lf", cell->d);+ ret = malloc(retlen);+ snprintf(ret, retlen, "%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);+ if (xf) {+ ret = malloc(retlen);+ switch (xf->format)+ {+ case XLS_FORMAT_GENERAL:+ case XLS_FORMAT_NUMBER1:+ case XLS_FORMAT_NUMBER3:+ snprintf(ret, retlen, "%.0lf", cell->d);+ break;+ case XLS_FORMAT_NUMBER2:+ case XLS_FORMAT_NUMBER4:+ snprintf(ret, retlen, "%.2f", cell->d);+ break;+ case XLS_FORMAT_PERCENT1:+ snprintf(ret, retlen, "%.0lf%%", 100 * cell->d);+ break;+ case XLS_FORMAT_PERCENT2:+ snprintf(ret, retlen, "%.2lf%%", 100 * cell->d);+ break;+ case XLS_FORMAT_SCIENTIFIC1:+ snprintf(ret, retlen, "%.2e", cell->d);+ break;+ case XLS_FORMAT_SCIENTIFIC2:+ snprintf(ret, retlen, "%.1e", cell->d);+ break;+ default:+ snprintf(ret, retlen, "%.2f", cell->d);+ break;+ } break; }- break; } - return (BYTE *)ret;+ return ret; } char* xls_getCSS(xlsWorkBook* pWB)
stack.yaml view
@@ -1,3 +1,3 @@-resolver: lts-10.4+resolver: lts-13.25 packages: - '.'
xls.cabal view
@@ -1,12 +1,12 @@ name: xls-version: 0.1.1+version: 0.1.2 synopsis: Parse Microsoft Excel xls files (BIFF/Excel 97-2004) description: Parse Microsoft Excel spreadsheet files in @.xls@ file format (extension '.xls') more specifically known as 'BIFF/Excel 97-2004'. . The library is based on the C library- 'https://sourceforge.net/projects/libxls'.+ 'https://github.com/libxls/libxls'. homepage: http://github.com/harendra-kumar/xls license: BSD3@@ -26,6 +26,7 @@ README.md stack.yaml lib/libxls/config/*.h+ lib/libxls/include/*.h lib/libxls/include/libxls/*.h lib/libxls/include/libxls/*.c.h