packages feed

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 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 -[![Hackage](https://img.shields.io/hackage/v/xls.svg?style=flat)](https://hackage.haskell.org/package/xls)-[![Build Status](https://travis-ci.org/harendra-kumar/xls.svg?branch=master)](https://travis-ci.org/harendra-kumar/xls)-[![Build status](https://ci.appveyor.com/api/projects/status/nwknaf0gw1p9vqnv?svg=true)](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(&note, 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