~ubuntu-branches/ubuntu/trusty/postgis/trusty-security

« back to all changes in this revision

Viewing changes to lwgeom/lwgeom_pg.c

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2009-12-11 13:10:34 UTC
  • mfrom: (1.1.9 upstream) (5.2.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20091211131034-wmsz69wxvt95pe5r
Tags: 1.4.0-2
* Upload to unstable.
* Better parameterized debian/rules against postgis $(VERSION).
* Added dblatex and libcunit1-dev among build-deps.
* Added postgis_comments.sql to contrib/ SQL templates.
* Dropping 8.3 support, no more supported for squeeze.
  (closes: #559587)
* Do not stop on error in postrm if the target dir does not exist.
  (closes: #560409)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <stdio.h>
2
 
#include <stdlib.h>
3
 
#include <stdarg.h>
4
 
#include <postgres.h>
5
 
#include <fmgr.h>
6
 
#include <executor/spi.h>
7
 
#include "liblwgeom.h"
8
 
#include "lwgeom_pg.h"
9
 
#include "wktparse.h"
10
 
 
11
 
 
12
 
/* #undef PGIS_DEBUG */
13
 
 
14
 
#define PARANOIA_LEVEL 1
15
 
 
16
 
/*
17
 
 * This is required for builds against pgsql 8.2
18
 
 */
19
 
/*#include "pgmagic.h"*/
20
 
#ifdef PG_MODULE_MAGIC
21
 
PG_MODULE_MAGIC;
22
 
#endif
23
 
 
24
 
void *
25
 
pg_alloc(size_t size)
26
 
{
27
 
        void * result;
28
 
#ifdef PGIS_DEBUG_ALLOCS
29
 
        lwnotice("  pg_alloc(%d) called", size);
30
 
#endif
31
 
        result = palloc(size);
32
 
#ifdef PGIS_DEBUG_ALLOCS
33
 
        lwnotice("  pg_alloc(%d) returning %p", size, result);
34
 
#endif
35
 
        if ( ! result )
36
 
        {
37
 
                elog(ERROR, "Out of virtual memory");
38
 
                return NULL;
39
 
        }
40
 
        return result;
41
 
}
42
 
 
43
 
void *
44
 
pg_realloc(void *mem, size_t size)
45
 
{
46
 
        void * result;
47
 
#ifdef PGIS_DEBUG_ALLOCS
48
 
        lwnotice("  pg_realloc(%p, %d) called", mem, size);
49
 
#endif
50
 
        result = repalloc(mem, size);
51
 
#ifdef PGIS_DEBUG_ALLOCS
52
 
        lwnotice("  pg_realloc(%p, %d) returning %p", mem, size, result);
53
 
#endif
54
 
        return result;
55
 
}
56
 
 
57
 
void
58
 
pg_free(void *ptr)
59
 
{
60
 
        pfree(ptr);
61
 
}
62
 
 
63
 
void
64
 
pg_error(const char *fmt, ...)
65
 
{
66
 
#define ERRMSG_MAXLEN 256
67
 
 
68
 
        char errmsg[ERRMSG_MAXLEN+1];
69
 
        va_list ap;
70
 
 
71
 
        va_start (ap, fmt);
72
 
        vsnprintf (errmsg, ERRMSG_MAXLEN, fmt, ap);
73
 
        va_end (ap);
74
 
 
75
 
        errmsg[ERRMSG_MAXLEN]='\0';
76
 
        elog(ERROR, "%s", errmsg);
77
 
}
78
 
 
79
 
void
80
 
pg_notice(const char *fmt, ...)
81
 
{
82
 
        char *msg;
83
 
        va_list ap;
84
 
 
85
 
        va_start (ap, fmt);
86
 
 
87
 
        /*
88
 
         * This is a GNU extension.
89
 
         * Dunno how to handle errors here.
90
 
         */
91
 
        if (!vasprintf (&msg, fmt, ap))
92
 
        {
93
 
                va_end (ap);
94
 
                return;
95
 
        }
96
 
        elog(NOTICE, "%s", msg);
97
 
        va_end(ap);
98
 
        free(msg);
99
 
}
100
 
 
101
 
void
102
 
init_pg_func(void)
103
 
{
104
 
        lwalloc_var = pg_alloc;
105
 
        lwrealloc_var = pg_realloc;
106
 
        lwfree_var = pg_free;
107
 
        lwerror = pg_error;
108
 
        lwnotice = pg_notice;
109
 
}
110
 
 
111
 
PG_LWGEOM *
112
 
pglwgeom_serialize(LWGEOM *in)
113
 
{
114
 
        size_t size;
115
 
        PG_LWGEOM *result;
116
 
 
117
 
#if AUTOCACHE_BBOX
118
 
        if ( ! in->bbox && is_worth_caching_lwgeom_bbox(in) )
119
 
        {
120
 
                lwgeom_addBBOX(in);
121
 
        }
122
 
#endif
123
 
 
124
 
        size = lwgeom_serialize_size(in) + VARHDRSZ;
125
 
 
126
 
#ifdef PGIS_DEBUG
127
 
        lwnotice("lwgeom_serialize_size returned %d", size-VARHDRSZ);
128
 
#endif
129
 
 
130
 
        result = palloc(size);
131
 
    SET_VARSIZE(result, size);
132
 
        lwgeom_serialize_buf(in, SERIALIZED_FORM(result), &size);
133
 
 
134
 
#ifdef PGIS_DEBUG
135
 
        lwnotice("pglwgeom_serialize: serialized size: %d, computed size: %d", size, VARSIZE(result)-VARHDRSZ);
136
 
#endif
137
 
 
138
 
#if PARANOIA_LEVEL > 0
139
 
        if ( size != VARSIZE(result)-VARHDRSZ )
140
 
        {
141
 
                lwerror("pglwgeom_serialize: serialized size:%d, computed size:%d", size, VARSIZE(result)-VARHDRSZ);
142
 
                return NULL;
143
 
        }
144
 
#endif
145
 
 
146
 
        return result;
147
 
}
148
 
 
149
 
LWGEOM *
150
 
pglwgeom_deserialize(PG_LWGEOM *in)
151
 
{
152
 
        return lwgeom_deserialize(SERIALIZED_FORM(in));
153
 
}
154
 
 
155
 
Oid
156
 
getGeometryOID(void)
157
 
{
158
 
        static Oid OID = InvalidOid;
159
 
        int SPIcode;
160
 
        bool isnull;
161
 
        char *query = "select OID from pg_type where typname = 'geometry'";     
162
 
 
163
 
        if ( OID != InvalidOid ) return OID;
164
 
        
165
 
        SPIcode = SPI_connect();
166
 
        if (SPIcode  != SPI_OK_CONNECT) {
167
 
                lwerror("getGeometryOID(): couldn't connection to SPI");
168
 
        }
169
 
 
170
 
        SPIcode = SPI_exec(query, 0); 
171
 
        if (SPIcode != SPI_OK_SELECT ) {
172
 
                lwerror("getGeometryOID(): error querying geometry oid");
173
 
        }
174
 
        if (SPI_processed != 1) {
175
 
                lwerror("getGeometryOID(): error querying geometry oid");
176
 
        }
177
 
 
178
 
        OID = (Oid)SPI_getbinval(SPI_tuptable->vals[0],
179
 
                SPI_tuptable->tupdesc, 1, &isnull);
180
 
 
181
 
        if (isnull) 
182
 
                lwerror("getGeometryOID(): couldn't find geometry oid");
183
 
 
184
 
        return OID;
185
 
}
186
 
 
187
 
PG_LWGEOM *
188
 
PG_LWGEOM_construct(uchar *ser, int SRID, int wantbbox)
189
 
{
190
 
        int size;
191
 
        uchar *iptr, *optr, *eptr;
192
 
        int wantsrid = 0;
193
 
        BOX2DFLOAT4 box;
194
 
        PG_LWGEOM *result;
195
 
 
196
 
        /* COMPUTE_BBOX FOR_COMPLEX_GEOMS */
197
 
        if ( is_worth_caching_serialized_bbox(ser) ) 
198
 
        {
199
 
                /* if ( ! wantbbox ) elog(NOTICE, "PG_LWGEOM_construct forced wantbbox=1 due to rule FOR_COMPLEX_GEOMS"); */
200
 
                wantbbox=1;
201
 
        }
202
 
 
203
 
        size = lwgeom_size(ser);
204
 
        eptr = ser+size; /* end of subgeom */
205
 
 
206
 
        iptr = ser+1; /* skip type */
207
 
        if ( lwgeom_hasSRID(ser[0]) )
208
 
        {
209
 
                iptr += 4; /* skip SRID */
210
 
                size -= 4;
211
 
        }
212
 
        if ( lwgeom_hasBBOX(ser[0]) )
213
 
        {
214
 
                iptr += sizeof(BOX2DFLOAT4); /* skip BBOX */
215
 
                size -= sizeof(BOX2DFLOAT4);
216
 
        }
217
 
 
218
 
        if ( SRID != -1 )
219
 
        {
220
 
                wantsrid = 1;
221
 
                size += 4;
222
 
        }
223
 
        if ( wantbbox )
224
 
        {
225
 
                size += sizeof(BOX2DFLOAT4);
226
 
                getbox2d_p(ser, &box);
227
 
        }
228
 
 
229
 
        size+=4; /* size header */
230
 
 
231
 
        result = lwalloc(size);
232
 
    SET_VARSIZE(result, size);
233
 
 
234
 
        result->type = lwgeom_makeType_full(
235
 
                TYPE_HASZ(ser[0]), TYPE_HASM(ser[0]),
236
 
                wantsrid, lwgeom_getType(ser[0]), wantbbox);
237
 
        optr = result->data;
238
 
        if ( wantbbox )
239
 
        {
240
 
                memcpy(optr, &box, sizeof(BOX2DFLOAT4));
241
 
                optr += sizeof(BOX2DFLOAT4);
242
 
        }
243
 
        if ( wantsrid )
244
 
        {
245
 
                memcpy(optr, &SRID, 4);
246
 
                optr += 4;
247
 
        }
248
 
        memcpy(optr, iptr, eptr-iptr);
249
 
 
250
 
        return result;
251
 
}
252
 
 
253
 
/*
254
 
 * Make a PG_LWGEOM object from a WKB binary representation.
255
 
 */
256
 
PG_LWGEOM *
257
 
pglwgeom_from_ewkb(uchar *ewkb, size_t ewkblen)
258
 
{
259
 
        PG_LWGEOM *ret;
260
 
    SERIALIZED_LWGEOM *serialized_lwgeom;
261
 
        char *hexewkb;
262
 
        size_t hexewkblen = ewkblen*2;
263
 
        int i;
264
 
 
265
 
        hexewkb = lwalloc(hexewkblen+1);
266
 
        for (i=0; i<ewkblen; i++)
267
 
        {
268
 
                deparse_hex(ewkb[i], &hexewkb[i*2]);
269
 
        }
270
 
        hexewkb[hexewkblen] = '\0';
271
 
 
272
 
    serialized_lwgeom = parse_lwgeom_wkt(hexewkb);
273
 
    
274
 
    ret = (PG_LWGEOM *)palloc(serialized_lwgeom->size + VARHDRSZ);
275
 
    SET_VARSIZE(ret, serialized_lwgeom->size + VARHDRSZ);
276
 
        memcpy(VARDATA(ret), serialized_lwgeom->lwgeom, serialized_lwgeom->size);
277
 
 
278
 
        lwfree(hexewkb);
279
 
 
280
 
        return ret;
281
 
}
282
 
 
283
 
/*
284
 
 * Return the EWKB (binary) representation for a PG_LWGEOM.
285
 
 */
286
 
char *
287
 
pglwgeom_to_ewkb(PG_LWGEOM *geom, char byteorder, size_t *outsize)
288
 
{
289
 
        uchar *srl = &(geom->type);
290
 
        return unparse_WKB(srl, lwalloc, lwfree,
291
 
                byteorder, outsize, 0);
292
 
}
293
 
 
294
 
/*
295
 
 * Set the SRID of a PG_LWGEOM
296
 
 * Returns a newly allocated PG_LWGEOM object.
297
 
 * Allocation will be done using the lwalloc.
298
 
 */
299
 
PG_LWGEOM *
300
 
pglwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID)
301
 
{
302
 
        uchar type = lwgeom->type;
303
 
        int bbox_offset=0; /* 0=no bbox, otherwise sizeof(BOX2DFLOAT4) */
304
 
        int len,len_new,len_left;
305
 
        PG_LWGEOM *result;
306
 
        uchar *loc_new, *loc_old;
307
 
 
308
 
        if (lwgeom_hasBBOX(type))
309
 
                bbox_offset = sizeof(BOX2DFLOAT4);
310
 
 
311
 
        len = lwgeom->size;
312
 
 
313
 
        if (lwgeom_hasSRID(type))
314
 
        {
315
 
                if ( newSRID != -1 ) {
316
 
                        /* we create a new one and copy the SRID in */
317
 
                        result = lwalloc(len);
318
 
                        memcpy(result, lwgeom, len);
319
 
                        memcpy(result->data+bbox_offset, &newSRID,4);
320
 
                } else {
321
 
                        /* we create a new one dropping the SRID */
322
 
                        result = lwalloc(len-4);
323
 
                        result->size = len-4;
324
 
                        result->type = lwgeom_makeType_full(
325
 
                                TYPE_HASZ(type), TYPE_HASM(type),
326
 
                                0, lwgeom_getType(type),
327
 
                                lwgeom_hasBBOX(type));
328
 
                        loc_new = result->data;
329
 
                        loc_old = lwgeom->data;
330
 
                        len_left = len-4-1;
331
 
 
332
 
                        /* handle bbox (if there) */
333
 
                        if (lwgeom_hasBBOX(type))
334
 
                        {
335
 
                                memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4));
336
 
                                loc_new += sizeof(BOX2DFLOAT4);
337
 
                                loc_old += sizeof(BOX2DFLOAT4);
338
 
                                len_left -= sizeof(BOX2DFLOAT4);
339
 
                        }
340
 
 
341
 
                        /* skip SRID, copy the remaining */
342
 
                        loc_old += 4;
343
 
                        len_left -= 4;
344
 
                        memcpy(loc_new, loc_old, len_left);
345
 
 
346
 
                }
347
 
 
348
 
        }
349
 
        else 
350
 
        {
351
 
                /* just copy input, already w/out a SRID */
352
 
                if ( newSRID == -1 ) {
353
 
                        result = lwalloc(len);
354
 
                        memcpy(result, lwgeom, len);
355
 
                }
356
 
                /* need to add one */
357
 
                else {
358
 
                        len_new = len + 4; /* +4 for SRID */
359
 
                        result = lwalloc(len_new);
360
 
                        memcpy(result, &len_new, 4); /* size copy in */
361
 
                        result->type = lwgeom_makeType_full(
362
 
                                TYPE_HASZ(type), TYPE_HASM(type),
363
 
                                1, lwgeom_getType(type),lwgeom_hasBBOX(type));
364
 
 
365
 
                        loc_new = result->data;
366
 
                        loc_old = lwgeom->data;
367
 
 
368
 
                        len_left = len -4-1; /* old length - size - type */
369
 
 
370
 
                        /* handle bbox (if there) */
371
 
 
372
 
                        if (lwgeom_hasBBOX(type))
373
 
                        {
374
 
                                memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4)) ; /* copy in bbox */
375
 
                                loc_new += sizeof(BOX2DFLOAT4);
376
 
                                loc_old += sizeof(BOX2DFLOAT4);
377
 
                                len_left -= sizeof(BOX2DFLOAT4);
378
 
                        }
379
 
 
380
 
                        /* put in SRID */
381
 
 
382
 
                        memcpy(loc_new, &newSRID,4);
383
 
                        loc_new +=4;
384
 
                        memcpy(loc_new, loc_old, len_left);
385
 
                }
386
 
        }
387
 
        return result;
388
 
}
389
 
 
390
 
/*
391
 
 * get the SRID from the LWGEOM
392
 
 * none present => -1
393
 
 */
394
 
int
395
 
pglwgeom_getSRID(PG_LWGEOM *lwgeom)
396
 
{
397
 
        uchar type = lwgeom->type;
398
 
        uchar *loc = lwgeom->data;
399
 
 
400
 
        if ( ! lwgeom_hasSRID(type)) return -1;
401
 
 
402
 
        if (lwgeom_hasBBOX(type))
403
 
        {
404
 
                loc += sizeof(BOX2DFLOAT4);
405
 
        }
406
 
 
407
 
        return lw_get_int32(loc);
408
 
}
409
 
 
410
 
 
411