Coverage Report

Created: 2025-06-13 06:29

/src/MapServer/src/mappluginlayer.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  MapServer
5
 * Purpose:  Implementation of plug-in layer functionality
6
 * Author:   Jani Averbach, SRC,LLC  <javerbach@extendthereach.com>
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a
12
 * copy of this software and associated documentation files (the "Software"),
13
 * to deal in the Software without restriction, including without limitation
14
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
 * and/or sell copies of the Software, and to permit persons to whom the
16
 * Software is furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies of this Software or works derived from this Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
 * DEALINGS IN THE SOFTWARE.
28
 *****************************************************************************/
29
30
#include "mapserver.h"
31
#include "mapthread.h"
32
33
typedef struct {
34
  char *name;
35
  layerVTableObj vtable;
36
} VTFactoryItemObj;
37
38
typedef struct {
39
  unsigned int size;
40
  unsigned int first_free;
41
  VTFactoryItemObj **vtItems;
42
} VTFactoryObj;
43
44
static VTFactoryObj gVirtualTableFactory = {0, 0, NULL};
45
46
0
static VTFactoryItemObj *createVTFItem(const char *name) {
47
0
  VTFactoryItemObj *pVTFI;
48
49
0
  pVTFI = (VTFactoryItemObj *)malloc(sizeof(VTFactoryItemObj));
50
0
  MS_CHECK_ALLOC(pVTFI, sizeof(VTFactoryItemObj), NULL);
51
52
0
  pVTFI->name = msStrdup(name);
53
0
  memset(&pVTFI->vtable, 0, sizeof(layerVTableObj));
54
55
0
  return pVTFI;
56
0
}
57
58
0
static void destroyVTFItem(VTFactoryItemObj **pVTFI) {
59
0
  free((*pVTFI)->name);
60
0
  (*pVTFI)->name = NULL;
61
0
  memset(&(*pVTFI)->vtable, 0, sizeof(layerVTableObj));
62
0
  free(*pVTFI);
63
0
  *pVTFI = NULL;
64
0
}
65
66
static VTFactoryItemObj *lookupVTFItem(VTFactoryObj *VTFactory,
67
171
                                       const char *key) {
68
171
  unsigned int i;
69
171
  for (i = 0; i < VTFactory->size && VTFactory->vtItems[i]; ++i) {
70
0
    if (0 == strcasecmp(key, VTFactory->vtItems[i]->name)) {
71
0
      return VTFactory->vtItems[i];
72
0
    }
73
0
  }
74
171
  return NULL;
75
171
}
76
77
0
static int insertNewVTFItem(VTFactoryObj *pVTFactory, VTFactoryItemObj *pVTFI) {
78
  /* Ensure there is room for one more item in the array
79
   * (safe to use for initial alloc of the array as well)
80
   */
81
0
  if (pVTFactory->first_free == pVTFactory->size) {
82
0
    VTFactoryItemObj **vtItemPtr;
83
0
    vtItemPtr = (VTFactoryItemObj **)realloc(
84
0
        pVTFactory->vtItems,
85
0
        (pVTFactory->size + MS_LAYER_ALLOCSIZE) * sizeof(VTFactoryItemObj *));
86
0
    MS_CHECK_ALLOC(vtItemPtr,
87
0
                   (pVTFactory->size + MS_LAYER_ALLOCSIZE) *
88
0
                       sizeof(VTFactoryItemObj *),
89
0
                   MS_FAILURE);
90
91
0
    pVTFactory->size += MS_LAYER_ALLOCSIZE;
92
0
    pVTFactory->vtItems = vtItemPtr;
93
94
0
    for (unsigned i = pVTFactory->first_free; i < pVTFactory->size; i++)
95
0
      pVTFactory->vtItems[i] = NULL;
96
0
  }
97
98
  /* Insert item */
99
0
  pVTFactory->vtItems[pVTFactory->first_free] = pVTFI;
100
0
  pVTFactory->first_free++;
101
102
0
  return MS_SUCCESS;
103
0
}
104
105
static VTFactoryItemObj *loadCustomLayerDLL(layerObj *layer,
106
171
                                            const char *library_path) {
107
171
  int (*pfnPluginInitVTable)(layerVTableObj *, layerObj *);
108
109
171
  VTFactoryItemObj *pVTFI;
110
111
171
  pfnPluginInitVTable =
112
171
      msGetSymbol(library_path, "PluginInitializeVirtualTable");
113
171
  if (!pfnPluginInitVTable) {
114
171
    msSetError(MS_MISCERR, "Failed to load dynamic Layer LIB: %s",
115
171
               "loadCustomLayerDLL", library_path);
116
171
    return NULL;
117
171
  }
118
119
0
  pVTFI = createVTFItem(library_path);
120
0
  if (!pVTFI) {
121
0
    return NULL;
122
0
  }
123
124
0
  if (pfnPluginInitVTable(&pVTFI->vtable, layer)) {
125
0
    destroyVTFItem(&pVTFI);
126
0
    msSetError(MS_MISCERR, "Failed to initialize dynamic Layer: %s",
127
0
               "loadCustomLayerDLL", library_path);
128
0
    return NULL;
129
0
  }
130
0
  return pVTFI;
131
0
}
132
133
/*
134
 * copyVirtualTable
135
 *
136
 * copy one virtual table from dest to src. Both of dest and src
137
 * have to be allocated already.
138
 *
139
 * If src contains NULL fields, those are NOT copied over.
140
 *
141
 * Because of that, it is possible for plugin layer to use default
142
 * layer API default functions,  just leave those function pointers to NULL.
143
 */
144
0
static void copyVirtualTable(layerVTableObj *dest, const layerVTableObj *src) {
145
0
  dest->LayerTranslateFilter = src->LayerTranslateFilter
146
0
                                   ? src->LayerTranslateFilter
147
0
                                   : dest->LayerTranslateFilter;
148
0
  dest->LayerSupportsCommonFilters = src->LayerSupportsCommonFilters
149
0
                                         ? src->LayerSupportsCommonFilters
150
0
                                         : dest->LayerSupportsCommonFilters;
151
0
  dest->LayerInitItemInfo =
152
0
      src->LayerInitItemInfo ? src->LayerInitItemInfo : dest->LayerInitItemInfo;
153
0
  dest->LayerFreeItemInfo =
154
0
      src->LayerFreeItemInfo ? src->LayerFreeItemInfo : dest->LayerFreeItemInfo;
155
0
  dest->LayerOpen = src->LayerOpen ? src->LayerOpen : dest->LayerOpen;
156
0
  dest->LayerIsOpen = src->LayerIsOpen ? src->LayerIsOpen : dest->LayerIsOpen;
157
0
  dest->LayerWhichShapes =
158
0
      src->LayerWhichShapes ? src->LayerWhichShapes : dest->LayerWhichShapes;
159
0
  dest->LayerNextShape =
160
0
      src->LayerNextShape ? src->LayerNextShape : dest->LayerNextShape;
161
0
  dest->LayerGetShape =
162
0
      src->LayerGetShape ? src->LayerGetShape : dest->LayerGetShape;
163
  /* dest->LayerResultsGetShape = src->LayerResultsGetShape ?
164
   * src->LayerResultsGetShape : dest->LayerResultsGetShape; */
165
0
  dest->LayerGetShapeCount = src->LayerGetShapeCount ? src->LayerGetShapeCount
166
0
                                                     : dest->LayerGetShapeCount;
167
0
  dest->LayerClose = src->LayerClose ? src->LayerClose : dest->LayerClose;
168
0
  dest->LayerGetItems =
169
0
      src->LayerGetItems ? src->LayerGetItems : dest->LayerGetItems;
170
0
  dest->LayerGetExtent =
171
0
      src->LayerGetExtent ? src->LayerGetExtent : dest->LayerGetExtent;
172
0
  dest->LayerGetAutoStyle =
173
0
      src->LayerGetAutoStyle ? src->LayerGetAutoStyle : dest->LayerGetAutoStyle;
174
0
  dest->LayerCloseConnection = src->LayerCloseConnection
175
0
                                   ? src->LayerCloseConnection
176
0
                                   : dest->LayerCloseConnection;
177
0
  dest->LayerSetTimeFilter = src->LayerSetTimeFilter ? src->LayerSetTimeFilter
178
0
                                                     : dest->LayerSetTimeFilter;
179
0
  dest->LayerApplyFilterToLayer = src->LayerApplyFilterToLayer
180
0
                                      ? src->LayerApplyFilterToLayer
181
0
                                      : dest->LayerApplyFilterToLayer;
182
0
  dest->LayerCreateItems =
183
0
      src->LayerCreateItems ? src->LayerCreateItems : dest->LayerCreateItems;
184
0
  dest->LayerGetNumFeatures = src->LayerGetNumFeatures
185
0
                                  ? src->LayerGetNumFeatures
186
0
                                  : dest->LayerGetNumFeatures;
187
0
  dest->LayerGetAutoProjection = src->LayerGetAutoProjection
188
0
                                     ? src->LayerGetAutoProjection
189
0
                                     : dest->LayerGetAutoProjection;
190
0
  dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam
191
0
                                  ? src->LayerEscapeSQLParam
192
0
                                  : dest->LayerEscapeSQLParam;
193
0
  dest->LayerEscapePropertyName = src->LayerEscapePropertyName
194
0
                                      ? src->LayerEscapePropertyName
195
0
                                      : dest->LayerEscapePropertyName;
196
0
  dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam
197
0
                                  ? src->LayerEscapeSQLParam
198
0
                                  : dest->LayerEscapeSQLParam;
199
0
  dest->LayerEnablePaging =
200
0
      src->LayerEnablePaging ? src->LayerEnablePaging : dest->LayerEnablePaging;
201
0
  dest->LayerGetPaging =
202
0
      src->LayerGetPaging ? src->LayerGetPaging : dest->LayerGetPaging;
203
0
}
204
205
285
int msPluginLayerInitializeVirtualTable(layerObj *layer) {
206
285
  VTFactoryItemObj *pVTFI;
207
208
285
  if (!layer->plugin_library) {
209
114
    return MS_FAILURE;
210
114
  }
211
212
171
  msAcquireLock(TLOCK_LAYER_VTABLE);
213
214
171
  pVTFI = lookupVTFItem(&gVirtualTableFactory, layer->plugin_library);
215
171
  if (!pVTFI) {
216
171
    pVTFI = loadCustomLayerDLL(layer, layer->plugin_library);
217
171
    if (!pVTFI) {
218
171
      msReleaseLock(TLOCK_LAYER_VTABLE);
219
171
      return MS_FAILURE;
220
171
    }
221
0
    if (insertNewVTFItem(&gVirtualTableFactory, pVTFI) != MS_SUCCESS) {
222
0
      destroyVTFItem(&pVTFI);
223
0
      msReleaseLock(TLOCK_LAYER_VTABLE);
224
0
      return MS_FAILURE;
225
0
    }
226
0
  }
227
0
  msReleaseLock(TLOCK_LAYER_VTABLE);
228
229
0
  copyVirtualTable(layer->vtable, &pVTFI->vtable);
230
0
  return MS_SUCCESS;
231
171
}
232
233
/* msPluginFreeVirtualTableFactory()
234
** Called by msCleanup() to free the virtual table factory
235
*/
236
0
void msPluginFreeVirtualTableFactory() {
237
0
  msAcquireLock(TLOCK_LAYER_VTABLE);
238
239
0
  for (unsigned i = 0; i < gVirtualTableFactory.size; i++) {
240
0
    if (gVirtualTableFactory.vtItems[i])
241
0
      destroyVTFItem(&(gVirtualTableFactory.vtItems[i]));
242
0
  }
243
0
  free(gVirtualTableFactory.vtItems);
244
0
  gVirtualTableFactory.vtItems = NULL;
245
0
  gVirtualTableFactory.size = 0;
246
0
  gVirtualTableFactory.first_free = 0;
247
248
0
  msReleaseLock(TLOCK_LAYER_VTABLE);
249
0
}