[Thuban-commits] r2887 - in branches/WIP-pyshapelib-Unicode/thuban/libraries: pyshapelib shapelib

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu Sep 17 20:57:49 CEST 2009


Author: bramz
Date: 2009-09-17 20:57:48 +0200 (Thu, 17 Sep 2009)
New Revision: 2887

Modified:
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py
   branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/dbfopen.c
   branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/safileio.c
   branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shapefil.h
   branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shpopen.c
   branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shptree.c
Log:
- forward porting shapelib to 1.3.0-a2 with snprintf patch
- add delete_field if DBFDeleteField is available in shapefil.h


Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/ChangeLog	2009-09-17 18:57:48 UTC (rev 2887)
@@ -1,3 +1,8 @@
+2009-09-17  Bram de Greve <bram.degreve at bramz.net>
+
+	* dbflibmodule.c: add delete_field, if necessary API function is available 
+	in shapefil.h
+
 2009-08-15  Bram de Greve <bram.degreve at bramz.net>
 
 	* setup.py: add compiler flags to suppress a spurious warning

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/dbflibmodule.c	2009-09-17 18:57:48 UTC (rev 2887)
@@ -210,6 +210,33 @@
 
 
 
+static int check_field_index(DBFFileObject* self, int field)
+{
+	if (field < 0 || field >= DBFGetFieldCount(self->handle))
+	{
+		PyErr_Format(PyExc_IndexError,
+				"field index %d out of bounds (field count: %d)",
+				field, DBFGetFieldCount(self->handle));
+		return -1;
+	}
+	return field;
+}
+
+
+static int check_record_index(DBFFileObject* self, int record)
+{
+	if (record < 0 || record >= DBFGetRecordCount(self->handle))
+	{
+		PyErr_Format(PyExc_IndexError,
+				"record index %d out of bounds (record count: %d)",
+				record, DBFGetRecordCount(self->handle));
+		return -1;
+	}
+	return record;
+}
+
+
+
 static PyObject* dbffile_field_info(DBFFileObject* self, PyObject* args)
 {
 	char field_name[12];
@@ -217,6 +244,7 @@
 	PyObject* name_object = NULL;
 	
 	if (!PyArg_ParseTuple(args, "i:field_info", &field)) return NULL;
+	if (check_field_index(self, field) < 0) return NULL;
 	
 	field_name[0] = '\0';
 	field_type = DBFGetFieldInfo(self->handle, field, field_name, &width, &decimals);
@@ -259,6 +287,29 @@
 
 
 
+/* The method relies on the DBFDeleteField method which is not
+* available in shapelib <= 1.3.0.  setup.py defines
+* HAVE_DELETE_FIELD's value depending on whether the function is
+* available in the shapelib version the code is compiled with.
+*/
+#if HAVE_DELETE_FIELD
+static PyObject* dbffile_delete_field(DBFFileObject* self, PyObject* args)
+{
+	int field;
+	if (!PyArg_ParseTuple(args, "i:field_info", &field)) return NULL;
+	if (check_field_index(self, field) < 0) return NULL;
+	
+	if (!DBFDeleteField(self->handle, field))
+	{
+		PyErr_SetString(PyExc_RuntimeError, "failed to delete field.");
+	}
+
+	Py_RETURN_NONE;
+}
+#endif
+
+
+
 /* Read one attribute from the dbf handle and return it as a new python object
 *
 * If an error occurs, set the appropriate Python exception and return
@@ -343,23 +394,9 @@
 	int record, field;
 
 	if (!PyArg_ParseTuple(args, "ii:read_attribute", &record, &field)) return NULL;
-	
-	if (record < 0 || record >= DBFGetRecordCount(self->handle))
-	{
-		PyErr_Format(PyExc_IndexError,
-				"record index %d out of bounds (record count: %d)",
-				record, DBFGetRecordCount(self->handle));
-		return NULL;
-	}
+	if (check_record_index(self, record) < 0) return NULL;
+	if (check_field_index(self, field) < 0) return NULL;
 
-	if (field < 0 || field >= DBFGetFieldCount(self->handle))
-	{
-		PyErr_Format(PyExc_IndexError,
-				"field index %d out of bounds (field count: %d)",
-				field, DBFGetFieldCount(self->handle));
-		return NULL;
-	}
-
 	return do_read_attribute(self, record, field, NULL);
 }
 
@@ -379,15 +416,8 @@
 	PyObject *value = NULL;
 
 	if (!PyArg_ParseTuple(args, "i:read_record", &record)) return NULL;
+	if (check_record_index(self, record) < 0) return NULL;
 
-	if (record < 0 || record >= DBFGetRecordCount(self->handle))
-	{
-		PyErr_Format(PyExc_IndexError,
-			"record index %d out of bounds (record count: %d)",
-			record, DBFGetRecordCount(self->handle));
-		return NULL;
-	}
-
 	dict = PyDict_New();
 	if (!dict) return NULL;
 	
@@ -474,15 +504,8 @@
 	int type;
 
 	if (!PyArg_ParseTuple(args, "iiO:write_attribute", &record, &field, &value)) return NULL;
+	if (check_field_index(self, field) < 0) return NULL;
 	
-	if (field < 0 || field >= DBFGetFieldCount(self->handle))
-	{
-		PyErr_Format(PyExc_ValueError,
-				"field index %d out of bounds (field count: %d)",
-				field, DBFGetFieldCount(self->handle));
-		return NULL;
-	}
-
 	type = DBFGetFieldInfo(self->handle, field, NULL, NULL, NULL);
 	if (!do_write_attribute(self, record, field, type, value)) return NULL;
 	Py_RETURN_NONE;
@@ -627,6 +650,11 @@
 		"- name: the name of the field as a string\n"
 		"- width: the width of the field as a number of characters\n"
 		"- decimals: the number of decimal digits" },
+#if HAVE_DELETE_FIELD
+	{"delete_field", (PyCFunction)dbffile_delete_field, METH_NOARGS, 
+		"delete_field(field_index) -> None"
+		"removes an entire column"},
+#endif
 	{"read_attribute", (PyCFunction)dbffile_read_attribute, METH_VARARGS, 
 		"read_attribute(record_index, field_index) -> value\n\n"
 		"returns the value of one field of a record"},

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/setup.py	2009-09-17 18:57:48 UTC (rev 2887)
@@ -74,6 +74,7 @@
 	return [
 		("HAVE_UPDATE_HEADER", have("DBFUpdateHeader")),
 		("HAVE_CODE_PAGE", have("DBFGetCodePage")),
+		("HAVE_DELETE_FIELD", have("DBFDeleteField")),
 		("DISABLE_CVSID", "1")]
 
 macros = determine_macros()

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/dbfopen.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/dbfopen.c	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/dbfopen.c	2009-09-17 18:57:48 UTC (rev 2887)
@@ -34,6 +34,12 @@
  ******************************************************************************
  *
  * $Log: dbfopen.c,v $
+ * Revision 1.83  2008-11-12 14:28:15  fwarmerdam
+ * DBFCreateField() now works on files with records
+ *
+ * Revision 1.82  2008/11/11 17:47:09  fwarmerdam
+ * added DBFDeleteField() function
+ *
  * Revision 1.81  2008/01/03 17:48:13  bram
  * in DBFCreate, use default code page LDID/87 (= 0x57, ANSI)
  * instead of LDID/3.  This seems to be the same as what ESRI
@@ -739,8 +745,7 @@
 /************************************************************************/
 /*                            DBFAddField()                             */
 /*                                                                      */
-/*      Add a field to a newly created .dbf file before any records     */
-/*      are written.                                                    */
+/*      Add a field to a newly created .dbf or to an existing one       */
 /************************************************************************/
 
 int SHPAPI_CALL
@@ -775,22 +780,23 @@
 {
     char	*pszFInfo;
     int		i;
+    int         nOldRecordLength, nOldHeaderLength;
+    char        *pszRecord;
+    char        chFieldFill;
+    SAOffset    nRecordOffset;
 
 /* -------------------------------------------------------------------- */
 /*      Do some checking to ensure we can add records to this file.     */
 /* -------------------------------------------------------------------- */
-    if( psDBF->nRecords > 0 )
-        return( -1 );
-
-    if( !psDBF->bNoHeader )
-        return( -1 );
-
     if( nWidth < 1 )
         return -1;
 
     if( nWidth > 255 )
         nWidth = 255;
 
+    nOldRecordLength = psDBF->nRecordLength;
+    nOldHeaderLength = psDBF->nHeaderLength;
+
 /* -------------------------------------------------------------------- */
 /*      SfRealloc all the arrays larger to hold the additional field      */
 /*      information.                                                    */
@@ -855,6 +861,59 @@
     psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
                                                  psDBF->nRecordLength);
 
+    /* we're done if dealing with new .dbf */
+    if( psDBF->bNoHeader )
+        return( psDBF->nFields - 1 );
+
+/* -------------------------------------------------------------------- */
+/*      For existing .dbf file, shift records                           */
+/* -------------------------------------------------------------------- */
+
+    /* alloc record */
+    pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+
+    switch (chType)
+    {
+      case 'N':
+      case 'F':
+        chFieldFill = '*';
+        break;
+      case 'D':
+        chFieldFill = '0';
+        break;
+      case 'L':
+       chFieldFill = '?';
+       break;
+      default:
+       chFieldFill = ' ';
+       break;
+    }
+
+    for (i = psDBF->nRecords-1; i >= 0; --i)
+    {
+        nRecordOffset = nOldRecordLength * (SAOffset) i + nOldHeaderLength;
+
+        /* load record */
+        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+        psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+        /* set new field's value to NULL */
+        memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
+
+        nRecordOffset = psDBF->nRecordLength * (SAOffset) i + psDBF->nHeaderLength;
+
+        /* move record to the new place*/
+        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+        psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+    }
+
+    /* free record */
+    free(pszRecord);
+
+    /* force update of header with new header, record length and new field */
+    psDBF->bNoHeader = TRUE;
+    DBFUpdateHeader( psDBF );
+
     return( psDBF->nFields-1 );
 }
 
@@ -1702,3 +1761,111 @@
         return NULL;
     return psDBF->pszCodePage;
 }
+
+/************************************************************************/
+/*                          DBFDeleteField()                            */
+/*                                                                      */
+/*      Remove a field from a .dbf file                                 */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFDeleteField(DBFHandle psDBF, int iField)
+{
+    int nOldRecordLength, nOldHeaderLength;
+    int nDeletedFieldOffset, nDeletedFieldSize;
+    SAOffset nRecordOffset;
+    char* pszRecord;
+    int i, iRecord;
+
+    if (iField < 0 || iField >= psDBF->nFields)
+        return FALSE;
+
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return FALSE;
+
+    /* get information about field to be deleted */
+    nOldRecordLength = psDBF->nRecordLength;
+    nOldHeaderLength = psDBF->nHeaderLength;
+    nDeletedFieldOffset = psDBF->panFieldOffset[iField];
+    nDeletedFieldSize = psDBF->panFieldSize[iField];
+
+    /* update fields info */
+    for (i = iField + 1; i < psDBF->nFields; i++)
+    {
+        psDBF->panFieldOffset[i-1] = psDBF->panFieldOffset[i] - nDeletedFieldSize;
+        psDBF->panFieldSize[i-1] = psDBF->panFieldSize[i];
+        psDBF->panFieldDecimals[i-1] = psDBF->panFieldDecimals[i];
+        psDBF->pachFieldType[i-1] = psDBF->pachFieldType[i];
+    }
+
+    /* resize fields arrays */
+    psDBF->nFields--;
+
+    psDBF->panFieldOffset = (int *) 
+        SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+
+    psDBF->panFieldSize = (int *) 
+        SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+
+    psDBF->panFieldDecimals = (int *) 
+        SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+
+    psDBF->pachFieldType = (char *) 
+        SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+
+    /* update header information */
+    psDBF->nHeaderLength -= 32;
+    psDBF->nRecordLength -= nDeletedFieldSize;
+
+    /* overwrite field information in header */
+    memcpy(psDBF->pszHeader + iField*32,
+           psDBF->pszHeader + (iField+1)*32,
+           sizeof(char) * (psDBF->nFields - iField)*32);
+
+    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+
+    /* update size of current record appropriately */
+    psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+                                                 psDBF->nRecordLength);
+
+    /* we're done if we're dealing with not yet created .dbf */
+    if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+        return TRUE;
+
+    /* force update of header with new header and record length */
+    psDBF->bNoHeader = TRUE;
+    DBFUpdateHeader( psDBF );
+
+    /* alloc record */
+    pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
+
+    /* shift records to their new positions */
+    for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+    {
+        nRecordOffset = 
+            nOldRecordLength * (SAOffset) iRecord + nOldHeaderLength;
+
+        /* load record */
+        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+        psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+        nRecordOffset = 
+            psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+        /* move record in two steps */
+        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+        psDBF->sHooks.FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->fp );
+        psDBF->sHooks.FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
+                              nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
+                              1, psDBF->fp );
+
+    }
+
+    /* TODO: truncate file */
+
+    /* free record */
+    free(pszRecord);
+
+    return TRUE;
+}

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/safileio.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/safileio.c	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/safileio.c	2009-09-17 18:57:48 UTC (rev 2887)
@@ -1,281 +1,286 @@
-/******************************************************************************
- * $Id: safileio.c,v 1.3 2007/12/18 18:28:11 bram Exp $
- *
- * Project:  Shapelib
- * Purpose:  Default implementation of file io based on stdio.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2007, Frank Warmerdam
- *
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: safileio.c,v $
- * Revision 1.3  2007/12/18 18:28:11  bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.2  2007/12/15 20:25:30  bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is 
- * either the number from the LDID header field ("LDID/<number>") or as the 
- * content of an accompanying .CPG file.  When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.1  2007/12/06 06:56:41  fwarmerdam
- * new
- *
- */
-
-#include "shapefil.h"
-
-#include <math.h>
-#include <limits.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-SHP_CVSID("$Id: safileio.c,v 1.3 2007/12/18 18:28:11 bram Exp $");
-
-#ifdef SHPAPI_UTF8_HOOKS
-#   ifdef SHPAPI_WINDOWS
-#       define WIN32_LEAN_AND_MEAN
-#       define NOMINMAX
-#       include <windows.h>
-#       pragma comment(lib, "kernel32.lib")
-#   endif
-#endif
-
-/************************************************************************/
-/*                              SADFOpen()                              */
-/************************************************************************/
-
-SAFile SADFOpen( const char *pszFilename, const char *pszAccess )
-
-{
-    return (SAFile) fopen( pszFilename, pszAccess );
-}
-
-/************************************************************************/
-/*                              SADFRead()                              */
-/************************************************************************/
-
-SAOffset SADFRead( void *p, SAOffset size, SAOffset nmemb, SAFile file )
-
-{
-    return (SAOffset) fread( p, (size_t) size, (size_t) nmemb, 
-                             (FILE *) file );
-}
-
-/************************************************************************/
-/*                             SADFWrite()                              */
-/************************************************************************/
-
-SAOffset SADFWrite( void *p, SAOffset size, SAOffset nmemb, SAFile file )
-
-{
-    return (SAOffset) fwrite( p, (size_t) size, (size_t) nmemb, 
-                              (FILE *) file );
-}
-
-/************************************************************************/
-/*                              SADFSeek()                              */
-/************************************************************************/
-
-SAOffset SADFSeek( SAFile file, SAOffset offset, int whence )
-
-{
-    return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
-}
-
-/************************************************************************/
-/*                              SADFTell()                              */
-/************************************************************************/
-
-SAOffset SADFTell( SAFile file )
-
-{
-    return (SAOffset) ftell( (FILE *) file );
-}
-
-/************************************************************************/
-/*                             SADFFlush()                              */
-/************************************************************************/
-
-int SADFFlush( SAFile file )
-
-{
-    return fflush( (FILE *) file );
-}
-
-/************************************************************************/
-/*                             SADFClose()                              */
-/************************************************************************/
-
-int SADFClose( SAFile file )
-
-{
-    return fclose( (FILE *) file );
-}
-
-/************************************************************************/
-/*                             SADFClose()                              */
-/************************************************************************/
-
-int SADRemove( const char *filename )
-
-{
-    return remove( filename );
-}
-
-/************************************************************************/
-/*                              SADError()                              */
-/************************************************************************/
-
-void SADError( const char *message )
-
-{
-    fprintf( stderr, "%s\n", message );
-}
-
-/************************************************************************/
-/*                        SASetupDefaultHooks()                         */
-/************************************************************************/
-
-void SASetupDefaultHooks( SAHooks *psHooks )
-
-{
-    psHooks->FOpen   = SADFOpen;
-    psHooks->FRead   = SADFRead;
-    psHooks->FWrite  = SADFWrite;
-    psHooks->FSeek   = SADFSeek;
-    psHooks->FTell   = SADFTell;
-    psHooks->FFlush  = SADFFlush;
-    psHooks->FClose  = SADFClose;
-    psHooks->Remove  = SADRemove;
-
-    psHooks->Error   = SADError;
-    psHooks->Atof    = atof;
-}
-
-
-
-
-#ifdef SHPAPI_WINDOWS
-
-/************************************************************************/
-/*                          Utf8ToWideChar                              */
-/************************************************************************/
-
-const wchar_t* Utf8ToWideChar( const char *pszFilename )
-{
-    int nMulti, nWide;
-    wchar_t *pwszFileName;
-    
-    nMulti = strlen(pszFilename) + 1;
-    nWide = MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, 0, 0);
-    if( nWide == 0 )
-    {
-        return NULL;
-    }
-    pwszFileName = (wchar_t*) malloc(nWide * sizeof(wchar_t));
-    if ( pwszFileName == NULL )
-    {
-        return NULL;
-    }
-    if( MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, pwszFileName, nWide ) == 0 )
-    {
-        free( pwszFileName );
-        return NULL;
-    }
-    return pwszFileName;
-}
-
-/************************************************************************/
-/*                           SAUtf8WFOpen                               */
-/************************************************************************/
-
-SAFile SAUtf8WFOpen( const char *pszFilename, const char *pszAccess )
-{
-    SAFile file = NULL;
-    const wchar_t *pwszFileName, *pwszAccess;
-    pwszFileName = Utf8ToWideChar( pszFilename );
-    pwszAccess = Utf8ToWideChar( pszAccess );
-    if( pwszFileName != NULL && pwszFileName != NULL)
-    {
-        file = (SAFile) _wfopen( pwszFileName, pwszAccess );
-    }
-    free ((wchar_t*) pwszFileName);
-    free ((wchar_t*) pwszAccess);
-    return file;
-}
-
-/************************************************************************/
-/*                             SAUtf8WRemove()                          */
-/************************************************************************/
-
-int SAUtf8WRemove( const char *pszFilename )
-{
-    const wchar_t *pwszFileName = Utf8ToWideChar( pszFilename );
-    int rc = -1; 
-    if( pwszFileName != NULL )
-    {
-        rc = _wremove( pwszFileName );
-    }
-    free ((wchar_t*) pwszFileName);
-    return rc;
-}
-
-#endif
-
-#ifdef SHPAPI_UTF8_HOOKS
-
-/************************************************************************/
-/*                          SASetupUtf8Hooks()                          */
-/************************************************************************/
-
-void SASetupUtf8Hooks( SAHooks *psHooks )
-{
-#ifdef SHPAPI_WINDOWS    
-    psHooks->FOpen   = SAUtf8WFOpen;
-    psHooks->Remove  = SAUtf8WRemove;
-#else
-    psHooks->FOpen   = SADFOpen;
-    psHooks->Remove  = SADRemove;
-#endif
-    psHooks->FRead   = SADFRead;
-    psHooks->FWrite  = SADFWrite;
-    psHooks->FSeek   = SADFSeek;
-    psHooks->FTell   = SADFTell;
-    psHooks->FFlush  = SADFFlush;
-    psHooks->FClose  = SADFClose;
-
-    psHooks->Error   = SADError;
-    psHooks->Atof    = atof;
-}
-
-#endif
+/******************************************************************************
+ * $Id: safileio.c,v 1.4 2008-01-16 20:05:14 bram Exp $
+ *
+ * Project:  Shapelib
+ * Purpose:  Default implementation of file io based on stdio.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: safileio.c,v $
+ * Revision 1.4  2008-01-16 20:05:14  bram
+ * Add file hooks that accept UTF-8 encoded filenames on some platforms.  Use SASetupUtf8Hooks
+ *  tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability.  Currently, this
+ *  is only available on the Windows platform that decodes the UTF-8 filenames to wide
+ *  character strings and feeds them to _wfopen and _wremove.
+ *
+ * Revision 1.3  2007/12/18 18:28:11  bram
+ * - create hook for client specific atof (bugzilla ticket 1615)
+ * - check for NULL handle before closing cpCPG file, and close after reading.
+ *
+ * Revision 1.2  2007/12/15 20:25:30  bram
+ * dbfopen.c now reads the Code Page information from the DBF file, and exports
+ * this information as a string through the DBFGetCodePage function.  This is 
+ * either the number from the LDID header field ("LDID/<number>") or as the 
+ * content of an accompanying .CPG file.  When creating a DBF file, the code can
+ * be set using DBFCreateEx.
+ *
+ * Revision 1.1  2007/12/06 06:56:41  fwarmerdam
+ * new
+ *
+ */
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+SHP_CVSID("$Id: safileio.c,v 1.4 2008-01-16 20:05:14 bram Exp $");
+
+#ifdef SHPAPI_UTF8_HOOKS
+#   ifdef SHPAPI_WINDOWS
+#       define WIN32_LEAN_AND_MEAN
+#       define NOMINMAX
+#       include <windows.h>
+#       pragma comment(lib, "kernel32.lib")
+#   endif
+#endif
+
+/************************************************************************/
+/*                              SADFOpen()                              */
+/************************************************************************/
+
+SAFile SADFOpen( const char *pszFilename, const char *pszAccess )
+
+{
+    return (SAFile) fopen( pszFilename, pszAccess );
+}
+
+/************************************************************************/
+/*                              SADFRead()                              */
+/************************************************************************/
+
+SAOffset SADFRead( void *p, SAOffset size, SAOffset nmemb, SAFile file )
+
+{
+    return (SAOffset) fread( p, (size_t) size, (size_t) nmemb, 
+                             (FILE *) file );
+}
+
+/************************************************************************/
+/*                             SADFWrite()                              */
+/************************************************************************/
+
+SAOffset SADFWrite( void *p, SAOffset size, SAOffset nmemb, SAFile file )
+
+{
+    return (SAOffset) fwrite( p, (size_t) size, (size_t) nmemb, 
+                              (FILE *) file );
+}
+
+/************************************************************************/
+/*                              SADFSeek()                              */
+/************************************************************************/
+
+SAOffset SADFSeek( SAFile file, SAOffset offset, int whence )
+
+{
+    return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
+}
+
+/************************************************************************/
+/*                              SADFTell()                              */
+/************************************************************************/
+
+SAOffset SADFTell( SAFile file )
+
+{
+    return (SAOffset) ftell( (FILE *) file );
+}
+
+/************************************************************************/
+/*                             SADFFlush()                              */
+/************************************************************************/
+
+int SADFFlush( SAFile file )
+
+{
+    return fflush( (FILE *) file );
+}
+
+/************************************************************************/
+/*                             SADFClose()                              */
+/************************************************************************/
+
+int SADFClose( SAFile file )
+
+{
+    return fclose( (FILE *) file );
+}
+
+/************************************************************************/
+/*                             SADFClose()                              */
+/************************************************************************/
+
+int SADRemove( const char *filename )
+
+{
+    return remove( filename );
+}
+
+/************************************************************************/
+/*                              SADError()                              */
+/************************************************************************/
+
+void SADError( const char *message )
+
+{
+    fprintf( stderr, "%s\n", message );
+}
+
+/************************************************************************/
+/*                        SASetupDefaultHooks()                         */
+/************************************************************************/
+
+void SASetupDefaultHooks( SAHooks *psHooks )
+
+{
+    psHooks->FOpen   = SADFOpen;
+    psHooks->FRead   = SADFRead;
+    psHooks->FWrite  = SADFWrite;
+    psHooks->FSeek   = SADFSeek;
+    psHooks->FTell   = SADFTell;
+    psHooks->FFlush  = SADFFlush;
+    psHooks->FClose  = SADFClose;
+    psHooks->Remove  = SADRemove;
+
+    psHooks->Error   = SADError;
+    psHooks->Atof    = atof;
+}
+
+
+
+
+#ifdef SHPAPI_WINDOWS
+
+/************************************************************************/
+/*                          Utf8ToWideChar                              */
+/************************************************************************/
+
+const wchar_t* Utf8ToWideChar( const char *pszFilename )
+{
+    int nMulti, nWide;
+    wchar_t *pwszFileName;
+    
+    nMulti = strlen(pszFilename) + 1;
+    nWide = MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, 0, 0);
+    if( nWide == 0 )
+    {
+        return NULL;
+    }
+    pwszFileName = (wchar_t*) malloc(nWide * sizeof(wchar_t));
+    if ( pwszFileName == NULL )
+    {
+        return NULL;
+    }
+    if( MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, pwszFileName, nWide ) == 0 )
+    {
+        free( pwszFileName );
+        return NULL;
+    }
+    return pwszFileName;
+}
+
+/************************************************************************/
+/*                           SAUtf8WFOpen                               */
+/************************************************************************/
+
+SAFile SAUtf8WFOpen( const char *pszFilename, const char *pszAccess )
+{
+    SAFile file = NULL;
+    const wchar_t *pwszFileName, *pwszAccess;
+    pwszFileName = Utf8ToWideChar( pszFilename );
+    pwszAccess = Utf8ToWideChar( pszAccess );
+    if( pwszFileName != NULL && pwszFileName != NULL)
+    {
+        file = (SAFile) _wfopen( pwszFileName, pwszAccess );
+    }
+    free ((wchar_t*) pwszFileName);
+    free ((wchar_t*) pwszAccess);
+    return file;
+}
+
+/************************************************************************/
+/*                             SAUtf8WRemove()                          */
+/************************************************************************/
+
+int SAUtf8WRemove( const char *pszFilename )
+{
+    const wchar_t *pwszFileName = Utf8ToWideChar( pszFilename );
+    int rc = -1; 
+    if( pwszFileName != NULL )
+    {
+        rc = _wremove( pwszFileName );
+    }
+    free ((wchar_t*) pwszFileName);
+    return rc;
+}
+
+#endif
+
+#ifdef SHPAPI_UTF8_HOOKS
+
+/************************************************************************/
+/*                          SASetupUtf8Hooks()                          */
+/************************************************************************/
+
+void SASetupUtf8Hooks( SAHooks *psHooks )
+{
+#ifdef SHPAPI_WINDOWS    
+    psHooks->FOpen   = SAUtf8WFOpen;
+    psHooks->Remove  = SAUtf8WRemove;
+#else
+#   error "no implementations of UTF-8 hooks available for this platform"
+#endif
+    psHooks->FRead   = SADFRead;
+    psHooks->FWrite  = SADFWrite;
+    psHooks->FSeek   = SADFSeek;
+    psHooks->FTell   = SADFTell;
+    psHooks->FFlush  = SADFFlush;
+    psHooks->FClose  = SADFClose;
+
+    psHooks->Error   = SADError;
+    psHooks->Atof    = atof;
+}
+
+#endif

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shapefil.h
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shapefil.h	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shapefil.h	2009-09-17 18:57:48 UTC (rev 2887)
@@ -37,6 +37,12 @@
  ******************************************************************************
  *
  * $Log: shapefil.h,v $
+ * Revision 1.46  2008-11-12 14:28:15  fwarmerdam
+ * DBFCreateField() now works on files with records
+ *
+ * Revision 1.45  2008/11/11 17:47:10  fwarmerdam
+ * added DBFDeleteField() function
+ *
  * Revision 1.44  2008/01/16 20:05:19  bram
  * Add file hooks that accept UTF-8 encoded filenames on some platforms.  Use SASetupUtf8Hooks
  *  tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability.  Currently, this
@@ -124,6 +130,7 @@
 
 #ifdef USE_CPL
 #include "cpl_error.h"
+#include "cpl_vsi.h"
 #endif
 
 #ifdef __cplusplus
@@ -534,6 +541,9 @@
       DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
                              char chType, int nWidth, int nDecimals );
 
+int	SHPAPI_CALL
+      DBFDeleteField( DBFHandle hDBF, int iField );
+
 DBFFieldType SHPAPI_CALL
       DBFGetFieldInfo( DBFHandle psDBF, int iField, 
                        char * pszFieldName, int * pnWidth, int * pnDecimals );

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shpopen.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shpopen.c	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shpopen.c	2009-09-17 18:57:48 UTC (rev 2887)
@@ -34,6 +34,9 @@
  ******************************************************************************
  *
  * $Log: shpopen.c,v $
+ * Revision 1.59  2008-03-14 05:25:31  fwarmerdam
+ * Correct crash on buggy geometries (gdal #2218)
+ *
  * Revision 1.58  2008/01/08 23:28:26  bram
  * on line 2095, use a float instead of a double to avoid a compiler warning
  *
@@ -249,6 +252,12 @@
 #  define MAX(a,b)      ((a>b) ? a : b)
 #endif
 
+#if defined(WIN32) || defined(_WIN32)
+#  ifndef snprintf
+#     define snprintf _snprintf
+#  endif
+#endif
+
 static int 	bBigEndian;
 
 
@@ -1497,7 +1506,9 @@
 SHPReadObject( SHPHandle psSHP, int hEntity )
 
 {
+    int                  nEntitySize, nRequiredSize;
     SHPObject		*psShape;
+    char                 pszErrorMsg[128];
 
 /* -------------------------------------------------------------------- */
 /*      Validate the record/entity number.                              */
@@ -1508,27 +1519,39 @@
 /* -------------------------------------------------------------------- */
 /*      Ensure our record buffer is large enough.                       */
 /* -------------------------------------------------------------------- */
-    if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
+    nEntitySize = psSHP->panRecSize[hEntity]+8;
+    if( nEntitySize > psSHP->nBufSize )
     {
-	psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
-	psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
+	psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
         if (psSHP->pabyRec == NULL)
         {
             char szError[200];
 
+            /* Reallocate previous successfull size for following features */
+            psSHP->pabyRec = malloc(psSHP->nBufSize);
+
             sprintf( szError, 
                      "Not enough memory to allocate requested memory (nBufSize=%d). "
                      "Probably broken SHP file", psSHP->nBufSize );
             psSHP->sHooks.Error( szError );
             return NULL;
         }
+
+        /* Only set new buffer size after successfull alloc */
+	psSHP->nBufSize = nEntitySize;
     }
 
+    /* In case we were not able to reallocate the buffer on a previous step */
+    if (psSHP->pabyRec == NULL)
+    {
+        return NULL;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Read the record.                                                */
 /* -------------------------------------------------------------------- */
     if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 
-        || psSHP->sHooks.FRead( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, 
+        || psSHP->sHooks.FRead( psSHP->pabyRec, nEntitySize, 1, 
                   psSHP->fpSHP ) != 1 )
     {
         /*
@@ -1547,7 +1570,16 @@
     psShape->nShapeId = hEntity;
     psShape->bMeasureIsUsed = FALSE;
 
+    if ( 8 + 4 > nEntitySize )
+    {
+        snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+                    hEntity, nEntitySize); 
+        psSHP->sHooks.Error( pszErrorMsg );
+        SHPDestroyObject(psShape);
+        return NULL;
+    }
     memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+
     if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
 
 /* ==================================================================== */
@@ -1563,6 +1595,14 @@
 	int32		nPoints, nParts;
 	int    		i, nOffset;
 
+        if ( 40 + 8 + 4 > nEntitySize )
+        {
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+                     hEntity, nEntitySize); 
+            psSHP->sHooks.Error( pszErrorMsg );
+            SHPDestroyObject(psShape);
+            return NULL;
+        }
 /* -------------------------------------------------------------------- */
 /*	Get the X/Y bounds.						*/
 /* -------------------------------------------------------------------- */
@@ -1586,15 +1626,38 @@
 	if( bBigEndian ) SwapWord( 4, &nPoints );
 	if( bBigEndian ) SwapWord( 4, &nParts );
 
-        if (nPoints < 0 || nParts < 0)
+        if (nPoints < 0 || nParts < 0 ||
+            nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
         {
-#ifdef USE_CPL
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "nPoints=%d, nParts=%d : bad value(s). Probably broken SHP file", nPoints, nParts );
-#endif
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
+                        hEntity, nPoints, nParts);
+            psSHP->sHooks.Error( pszErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
+        
+        /* With the previous checks on nPoints and nParts, */
+        /* we should not overflow here and after */
+        /* since 50 M * (16 + 8 + 8) = 1 600 MB */
+        nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
+        if ( psShape->nSHPType == SHPT_POLYGONZ
+            || psShape->nSHPType == SHPT_ARCZ
+            || psShape->nSHPType == SHPT_MULTIPATCH )
+        {
+            nRequiredSize += 16 + 8 * nPoints;
+        }
+        if( psShape->nSHPType == SHPT_MULTIPATCH )
+        {
+            nRequiredSize += 4 * nParts;
+        }
+        if (nRequiredSize > nEntitySize)
+        {
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
+                        hEntity, nPoints, nParts, nEntitySize);
+            psSHP->sHooks.Error( pszErrorMsg );
+            SHPDestroyObject(psShape);
+            return NULL;
+        }
 
 	psShape->nVertices = nPoints;
         psShape->padfX = (double *) calloc(nPoints,sizeof(double));
@@ -1613,11 +1676,10 @@
             psShape->panPartStart == NULL ||
             psShape->panPartType == NULL)
         {
-#ifdef USE_CPL
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d). "
-                     "Probably broken SHP file", nPoints, nParts );
-#endif
+            snprintf(pszErrorMsg, 128,
+                     "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
+                     "Probably broken SHP file", hEntity, nPoints, nParts );
+            psSHP->sHooks.Error( pszErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
@@ -1632,6 +1694,25 @@
 	for( i = 0; i < nParts; i++ )
 	{
 	    if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+
+            /* We check that the offset is inside the vertex array */
+            if (psShape->panPartStart[i] < 0 ||
+                psShape->panPartStart[i] >= psShape->nVertices)
+            {
+                snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
+                         hEntity, i, psShape->panPartStart[i], psShape->nVertices); 
+                psSHP->sHooks.Error( pszErrorMsg );
+                SHPDestroyObject(psShape);
+                return NULL;
+            }
+            if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
+            {
+                snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
+                         hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]); 
+                psSHP->sHooks.Error( pszErrorMsg );
+                SHPDestroyObject(psShape);
+                return NULL;
+            }
 	}
 
 	nOffset = 44 + 8 + 4*nParts;
@@ -1698,7 +1779,7 @@
 /*      big enough, but really it will only occur for the Z shapes      */
 /*      (options), and the M shapes.                                    */
 /* -------------------------------------------------------------------- */
-        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+        if( nEntitySize >= nOffset + 16 + 8*nPoints )
         {
             memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
             memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -1726,18 +1807,40 @@
 	int32		nPoints;
 	int    		i, nOffset;
 
+        if ( 44 + 4 > nEntitySize )
+        {
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+                     hEntity, nEntitySize); 
+            psSHP->sHooks.Error( pszErrorMsg );
+            SHPDestroyObject(psShape);
+            return NULL;
+        }
 	memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+
 	if( bBigEndian ) SwapWord( 4, &nPoints );
 
-        if (nPoints < 0)
+        if (nPoints < 0 || nPoints > 50 * 1000 * 1000)
         {
-#ifdef USE_CPL
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "nPoints=%d : bad value. Probably broken SHP file", nPoints );
-#endif
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d",
+                     hEntity, nPoints); 
+            psSHP->sHooks.Error( pszErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
+
+        nRequiredSize = 48 + nPoints * 16;
+        if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+        {
+            nRequiredSize += 16 + nPoints * 8;
+        }
+        if (nRequiredSize > nEntitySize)
+        {
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
+                     hEntity, nPoints, nEntitySize); 
+            psSHP->sHooks.Error( pszErrorMsg );
+            SHPDestroyObject(psShape);
+            return NULL;
+        }
         
 	psShape->nVertices = nPoints;
         psShape->padfX = (double *) calloc(nPoints,sizeof(double));
@@ -1750,11 +1853,10 @@
             psShape->padfZ == NULL ||
             psShape->padfM == NULL)
         {
-#ifdef USE_CPL
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Not enough memory to allocate requested memory (nPoints=%d). "
-                     "Probably broken SHP file", nPoints );
-#endif
+            snprintf(pszErrorMsg, 128,
+                     "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. "
+                     "Probably broken SHP file", hEntity, nPoints );
+            psSHP->sHooks.Error( pszErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
         }
@@ -1810,7 +1912,7 @@
 /*      big enough, but really it will only occur for the Z shapes      */
 /*      (options), and the M shapes.                                    */
 /* -------------------------------------------------------------------- */
-        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+        if( nEntitySize >= nOffset + 16 + 8*nPoints )
         {
             memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
             memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -1843,6 +1945,14 @@
         psShape->padfZ = (double *) calloc(1,sizeof(double));
         psShape->padfM = (double *) calloc(1,sizeof(double));
 
+        if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
+        {
+            snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+                     hEntity, nEntitySize); 
+            psSHP->sHooks.Error( pszErrorMsg );
+            SHPDestroyObject(psShape);
+            return NULL;
+        }
 	memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
 	memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
 
@@ -1869,7 +1979,7 @@
 /*      big enough, but really it will only occur for the Z shapes      */
 /*      (options), and the M shapes.                                    */
 /* -------------------------------------------------------------------- */
-        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
+        if( nEntitySize >= nOffset + 8 )
         {
             memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
         

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shptree.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shptree.c	2009-08-18 20:04:10 UTC (rev 2886)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/shapelib/shptree.c	2009-09-17 18:57:48 UTC (rev 2887)
@@ -34,6 +34,9 @@
  ******************************************************************************
  *
  * $Log: shptree.c,v $
+ * Revision 1.12  2008-11-12 15:39:50  fwarmerdam
+ * improve safety in face of buggy .shp file.
+ *
  * Revision 1.11  2007/10/27 03:31:14  fwarmerdam
  * limit default depth of tree to 12 levels (gdal ticket #1594)
  *
@@ -259,8 +262,11 @@
             SHPObject	*psShape;
             
             psShape = SHPReadObject( hSHP, iShape );
-            SHPTreeAddShapeId( psTree, psShape );
-            SHPDestroyObject( psShape );
+            if( psShape != NULL )
+            {
+                SHPTreeAddShapeId( psTree, psShape );
+                SHPDestroyObject( psShape );
+            }
         }
     }        
 



More information about the Thuban-commits mailing list