treeObj *msCreateTree(shapefileObj *shapefile, int maxdepth) { int i; treeObj *tree; rectObj bounds; if(!shapefile) return NULL; /* -------------------------------------------------------------------- */ /* Allocate the tree object */ /* -------------------------------------------------------------------- */ tree = (treeObj *) msSmallMalloc(sizeof(treeObj)); tree->numshapes = shapefile->numshapes; tree->maxdepth = maxdepth; /* -------------------------------------------------------------------- */ /* If no max depth was defined, try to select a reasonable one */ /* that implies approximately 8 shapes per node. */ /* -------------------------------------------------------------------- */ if( tree->maxdepth == 0 ) { int numnodes = 1; while(numnodes*4 < shapefile->numshapes) { tree->maxdepth += 1; numnodes = numnodes * 2; } } /* -------------------------------------------------------------------- */ /* Allocate the root node. */ /* -------------------------------------------------------------------- */ tree->root = treeNodeCreate(shapefile->bounds); for(i=0; i<shapefile->numshapes; i++) { if(msSHPReadBounds(shapefile->hSHP, i, &bounds) == MS_SUCCESS) treeAddShapeId(tree, i, bounds); } return tree; }
int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, char *pszExpression) { int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.filter = (expressionObj *) msSmallMalloc(sizeof(expressionObj)); initExpression( map->query.filter); map->query.filter->string = msStrdup(pszExpression); map->query.filter->type = 2000; map->query.layer = iLayerIndex; /*TODO: if there is a bbox in the node, get it and set the map extent*/ map->query.rect = map->extent; retval = msQueryByFilter(map); return retval; }
static void writeTreeNode(SHPTreeHandle disktree, treeNodeObj *node) { int i,j; ms_int32 offset; char *pabyRec = NULL; offset = getSubNodeOffset(node); pabyRec = msSmallMalloc(sizeof(rectObj) + (3 * sizeof(ms_int32)) + (node->numshapes * sizeof(ms_int32)) ); memcpy( pabyRec, &offset, 4); if( disktree->needswap ) SwapWord( 4, pabyRec ); memcpy( pabyRec+4, &node->rect, sizeof(rectObj)); for (i=0; i < 4; i++) if( disktree->needswap ) SwapWord( 8, pabyRec+4+(8*i) ); memcpy( pabyRec+36, &node->numshapes, 4); if( disktree->needswap ) SwapWord( 4, pabyRec+36 ); j = node->numshapes*sizeof(ms_int32); memcpy( pabyRec+40, node->ids, j); for (i=0; i<node->numshapes; i++) if( disktree->needswap ) SwapWord( 4, pabyRec+40+(4*i)); memcpy( pabyRec+j+40, &node->numsubnodes, 4); if( disktree->needswap ) SwapWord( 4, pabyRec+40+j ); fwrite( pabyRec, 44+j, 1, disktree->fp); free (pabyRec); for(i=0; i<node->numsubnodes; i++ ) { if(node->subnode[i]) writeTreeNode(disktree, node->subnode[i]); } return; }
void msSetLimitedPatternsToUse(const char *patternstring) { int *limitedpatternindice = NULL; int numpatterns=0, i=0, j=0, ntmp=0; char **patterns = NULL; msTimeSetup(); limitedpatternindice = (int *)msSmallMalloc(sizeof(int)*MS_NUMTIMEFORMATS); /* free previous setting */ msUnsetLimitedPatternToUse(); if (patternstring) { patterns = msStringSplit(patternstring, ',', &ntmp); if (patterns && ntmp >= 1) { for (i=0; i<ntmp; i++) { for (j=0; j<MS_NUMTIMEFORMATS; j++) { if (strcasecmp( ms_timeFormats[j].userformat, patterns[i]) ==0) { limitedpatternindice[numpatterns] = j; numpatterns++; break; } } } } msFreeCharArray(patterns, ntmp); } if (numpatterns > 0) { for (i=0; i<numpatterns; i++) ms_limited_pattern[i] = limitedpatternindice[i]; ms_num_limited_pattern = numpatterns; } free (limitedpatternindice); }
void KmlRenderer::addLineStyleToList(strokeStyleObj *style) { /*actually this is not necessary. kml only uses the last LineStyle so we should not bother keeping them all*/ int i =0; for (i=0; i<numLineStyle; i++) { if (style->width == LineStyle[i].width && LineStyle[i].color->alpha == style->color->alpha && LineStyle[i].color->red == style->color->red && LineStyle[i].color->green == style->color->green && LineStyle[i].color->blue == style->color->blue) break; } if (i == numLineStyle) { numLineStyle++; if (LineStyle == NULL) LineStyle = (strokeStyleObj *)msSmallMalloc(sizeof(strokeStyleObj)); else LineStyle = (strokeStyleObj *)msSmallRealloc(LineStyle, sizeof(strokeStyleObj)*numLineStyle); memcpy(&LineStyle[numLineStyle-1], style, sizeof(strokeStyleObj)); } }
int msParseTime(const char *string, struct tm *tm) { int i, indice = 0; int num_patterns = 0; /* if limited patterns are set, use then. Else use all the */ /* patterns defined */ if (ms_limited_pattern && ms_num_limited_pattern > 0) num_patterns = ms_num_limited_pattern; else num_patterns = MS_NUMTIMEFORMATS; for(i=0; i<num_patterns; i++) { if (ms_num_limited_pattern > 0) indice = ms_limited_pattern[i]; else indice = i; if(!ms_timeFormats[indice].regex) { /* compile the expression */ ms_timeFormats[indice].regex = (ms_regex_t *) msSmallMalloc(sizeof(ms_regex_t)); if(ms_regcomp(ms_timeFormats[indice].regex, ms_timeFormats[indice].pattern, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msParseTime()", ms_timeFormats[indice].pattern); return(MS_FALSE); } } /* test the expression against the string */ if(ms_regexec(ms_timeFormats[indice].regex, string, 0, NULL, 0) == 0) { /* match */ msStrptime(string, ms_timeFormats[indice].format, tm); return(MS_TRUE); } } msSetError(MS_REGEXERR, "Unrecognized date or time format (%s).", "msParseTime()", string); return(MS_FALSE); }
xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws, int nWFSVersion, const char* validate_language) { rectObj ext; xmlNodePtr psRootNode, psNode; const char *value = NULL; char *valueToFree; char **tokens; int n=0,i=0; psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType"); /* add namespace to layer name */ value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix"); /* FIXME? Should probably be applied to WFS 1.1 as well, but the addition */ /* of the prefix can be disruptive for clients */ if( value == NULL && nWFSVersion >= OWS_2_0_0 ) value = MS_DEFAULT_NAMESPACE_PREFIX; if(value) { n = strlen(value)+strlen(lp->name)+1+1; valueToFree = (char *) msSmallMalloc(sizeof(char*)*n); snprintf(valueToFree, n, "%s%s%s", (value ? value : ""), (value ? ":" : ""), lp->name); psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST valueToFree); msFree(valueToFree); } else { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name); } if (lp->name && strlen(lp->name) > 0 && (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0]))) { char szTmp[512]; snprintf(szTmp, sizeof(szTmp), "WARNING: The layer name '%s' might contain spaces or " "invalid characters or may start with a number. This could lead to potential problems", lp->name); xmlAddSibling(psNode, xmlNewComment(BAD_CAST szTmp)); } value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "title", validate_language); if (!value) value =(const char*)lp->name; psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value); value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "abstract", validate_language); if (value) psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value); value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "keywordlist", validate_language); if(value) msLibXml2GenerateList( xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL), NULL, "Keyword", value, ',' ); /*support DefaultSRS and OtherSRS*/ valueToFree = msOWSGetProjURN(&(map->projection),&(map->web.metadata),"FO",MS_FALSE); if (!valueToFree) valueToFree = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE); if (valueToFree) { tokens = msStringSplit(valueToFree, ' ', &n); if (tokens && n > 0) { if( nWFSVersion == OWS_1_1_0 ) psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]); else psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultCRS", BAD_CAST tokens[0]); for (i=1; i<n; i++) { if( nWFSVersion == OWS_1_1_0 ) psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]); else psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherCRS", BAD_CAST tokens[i]); } msFreeCharArray(tokens, n); } } else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context.")); free(valueToFree); valueToFree = NULL; /*TODO: adevertize only gml3?*/ psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats"); xmlAddChild(psRootNode, psNode); { char *formats_list = msWFSGetOutputFormatList( map, lp, nWFSVersion ); int iformat, n; char **tokens; n = 0; tokens = msStringSplit(formats_list, ',', &n); for( iformat = 0; iformat < n; iformat++ ) xmlNewChild(psNode, NULL, BAD_CAST "Format", BAD_CAST tokens[iformat] ); msFree( formats_list ); msFreeCharArray( tokens, n ); } /*bbox*/ if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) { /*convert to latlong*/ if (lp->projection.numargs > 0) msOWSProjectToWGS84(&lp->projection, &ext); else msOWSProjectToWGS84(&map->projection, &ext); xmlAddChild(psRootNode, msOWSCommonWGS84BoundingBox( psNsOws, 2, ext.minx, ext.miny, ext.maxx, ext.maxy)); } else { xmlNewChild(psRootNode, psNsOws, BAD_CAST "WGS84BoundingBox", NULL); xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional WGS84BoundingBox could not be established for this layer. Consider setting the EXTENT in the LAYER object, or wfs_extent metadata. Also check that your data exists in the DATA statement")); } value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href"); if (value) { if( nWFSVersion >= OWS_2_0_0 ) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", NULL); xmlNewProp(psNode, BAD_CAST "xlink:href", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_about"); if( value != NULL ) xmlNewProp(psNode, BAD_CAST "about", BAD_CAST value); } else { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format"); if (!value) value = msStrdup("text/html"); /* default */ xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_type"); if (!value) value = msStrdup("FGDC"); /* default */ xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value); } } return psRootNode; }
static xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws) { rectObj ext; xmlNodePtr psRootNode, psNode; const char *value = NULL; const char *encoding = NULL; char *encoded=NULL; char *valueToFree; char **tokens; int n=0,i=0; encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding"); if (!encoding) encoding = "ISO-8859-1"; psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType"); /* add namespace to layer name */ value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix"); if(value) { n = strlen(value)+strlen(lp->name)+1+1; valueToFree = (char *) msSmallMalloc(sizeof(char*)*n); snprintf(valueToFree, n, "%s%s%s", (value ? value : ""), (value ? ":" : ""), lp->name); /*if there is an encoding using it on some of the items*/ psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", valueToFree, encoding); msFree(valueToFree); } else { psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", lp->name, encoding); } if (lp->name && strlen(lp->name) > 0 && (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0]))) xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: The layer name '%s' might contain spaces or " "invalid characters or may start with a number. This could lead to potential problems")); value = msOWSLookupMetadata(&(lp->metadata), "FO", "title"); if (!value) value =(const char*)lp->name; psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Title", value, encoding); value = msOWSLookupMetadata(&(lp->metadata), "FO", "abstract"); if (value) psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Abstract", value, encoding); value = msOWSLookupMetadata(&(lp->metadata), "FO", "keywordlist"); if (value) { encoded = msGetEncodedString(value, encoding); msLibXml2GenerateList( xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL), NULL, "Keyword", encoded, ',' ); msFree(encoded); } /*support DefaultSRS and OtherSRS*/ valueToFree = msOWSGetProjURN(&(map->projection),&(map->web.metadata),"FO",MS_FALSE); if (!valueToFree) valueToFree = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE); if (valueToFree) { tokens = msStringSplit(valueToFree, ' ', &n); if (tokens && n > 0) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]); for (i=1; i<n; i++) psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]); msFreeCharArray(tokens, n); } } else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context.")); free(valueToFree); valueToFree = NULL; /*TODO: adevertize only gml3?*/ psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats"); xmlAddChild(psRootNode, psNode); { char *formats_list = msWFSGetOutputFormatList( map, lp, "1.1.0" ); int iformat, n; char **tokens; n = 0; tokens = msStringSplit(formats_list, ',', &n); for( iformat = 0; iformat < n; iformat++ ) xmlNewChild(psNode, NULL, BAD_CAST "Format", BAD_CAST tokens[iformat] ); msFree( formats_list ); msFreeCharArray( tokens, n ); } /*bbox*/ if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) { /*convert to latlong*/ if (lp->projection.numargs > 0) msOWSProjectToWGS84(&lp->projection, &ext); else msOWSProjectToWGS84(&map->projection, &ext); xmlAddChild(psRootNode, msOWSCommonWGS84BoundingBox( psNsOws, 2, ext.minx, ext.miny, ext.maxx, ext.maxy)); } else { xmlNewChild(psRootNode, psNsOws, BAD_CAST "WGS84BoundingBox", NULL); xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional WGS84BoundingBox could not be established for this layer. Consider setting the EXTENT in the LAYER object, or wfs_extent metadata. Also check that your data exists in the DATA statement")); } value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href"); if (value) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format"); if (!value) value = msStrdup("text/html"); /* default */ xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value); value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_type"); if (!value) value = msStrdup("FGDC"); /* default */ xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value); } return psRootNode; }
DBFHandle msDBFOpen( const char * pszFilename, const char * pszAccess ) { DBFHandle psDBF; uchar *pabyBuf; int nFields, nRecords, nHeadLen, nRecLen, iField; char *pszDBFFilename; /* -------------------------------------------------------------------- */ /* We only allow the access strings "rb" and "r+". */ /* -------------------------------------------------------------------- */ if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0 && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"r+b") != 0 ) return( NULL ); /* -------------------------------------------------------------------- */ /* Ensure the extension is converted to dbf or DBF if it is */ /* currently .shp or .shx. */ /* -------------------------------------------------------------------- */ pszDBFFilename = (char *) msSmallMalloc(strlen(pszFilename)+1); strcpy( pszDBFFilename, pszFilename ); if( strcmp(pszFilename+strlen(pszFilename)-4,".shp") || strcmp(pszFilename+strlen(pszFilename)-4,".shx") ) { strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".dbf"); } else if( strcmp(pszFilename+strlen(pszFilename)-4,".SHP") || strcmp(pszFilename+strlen(pszFilename)-4,".SHX") ) { strcpy( pszDBFFilename+strlen(pszDBFFilename)-4, ".DBF"); } /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) ); MS_CHECK_ALLOC(psDBF, sizeof(DBFInfo), NULL); psDBF->fp = fopen( pszDBFFilename, pszAccess ); if( psDBF->fp == NULL ) return( NULL ); psDBF->bNoHeader = MS_FALSE; psDBF->nCurrentRecord = -1; psDBF->bCurrentRecordModified = MS_FALSE; psDBF->pszStringField = NULL; psDBF->nStringFieldLen = 0; free( pszDBFFilename ); /* -------------------------------------------------------------------- */ /* Read Table Header info */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) msSmallMalloc(500); fread( pabyBuf, 32, 1, psDBF->fp ); psDBF->nRecords = nRecords = pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256; psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256; psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256; psDBF->nFields = nFields = (nHeadLen - 32) / 32; psDBF->pszCurrentRecord = (char *) msSmallMalloc(nRecLen); /* -------------------------------------------------------------------- */ /* Read in Field Definitions */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) SfRealloc(pabyBuf,nHeadLen); psDBF->pszHeader = (char *) pabyBuf; fseek( psDBF->fp, 32, 0 ); fread( pabyBuf, nHeadLen, 1, psDBF->fp ); psDBF->panFieldOffset = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->panFieldSize = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->panFieldDecimals = (int *) msSmallMalloc(sizeof(int) * nFields); psDBF->pachFieldType = (char *) msSmallMalloc(sizeof(char) * nFields); for( iField = 0; iField < nFields; iField++ ) { uchar *pabyFInfo; pabyFInfo = pabyBuf+iField*32; if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' ) { psDBF->panFieldSize[iField] = pabyFInfo[16]; psDBF->panFieldDecimals[iField] = pabyFInfo[17]; } else { psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256; psDBF->panFieldDecimals[iField] = 0; } psDBF->pachFieldType[iField] = (char) pabyFInfo[11]; if( iField == 0 ) psDBF->panFieldOffset[iField] = 1; else psDBF->panFieldOffset[iField] = psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1]; } return( psDBF ); }
char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp) { char *pszExpression = NULL; shapeObj *psQueryShape = NULL; double dfDistance = -1; int nUnit = -1, nLayerUnit = -1; char *pszWktText = NULL; char szBuffer[256]; char *pszTmp=NULL; projectionObj sProjTmp; rectObj sQueryRect; shapeObj *psTmpShape=NULL; int bBBoxQuery = 0; int bAlreadyReprojected = 0; if (psNode == NULL || lp == NULL) return NULL; if (psNode->eType != FILTER_NODE_TYPE_SPATIAL) return NULL; /* get the shape */ if (FLTIsBBoxFilter(psNode)) { char szPolygon[512]; FLTGetBBOX(psNode, &sQueryRect); snprintf(szPolygon, sizeof(szPolygon), "POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))", sQueryRect.minx, sQueryRect.miny, sQueryRect.minx, sQueryRect.maxy, sQueryRect.maxx, sQueryRect.maxy, sQueryRect.maxx, sQueryRect.miny, sQueryRect.minx, sQueryRect.miny); psTmpShape = msShapeFromWKT(szPolygon); /* ** This is a horrible hack to deal with world-extent requests and ** reprojection. msProjectRect() detects if reprojection from longlat to ** projected SRS, and in that case it transforms the bbox to -1e-15,-1e-15,1e15,1e15 ** to ensure that all features are returned. ** ** Make wfs_200_cite_filter_bbox_world.xml and wfs_200_cite_postgis_bbox_world.xml pass */ if (fabs(sQueryRect.minx - -180.0) < 1e-5 && fabs(sQueryRect.miny - -90.0) < 1e-5 && fabs(sQueryRect.maxx - 180.0) < 1e-5 && fabs(sQueryRect.maxy - 90.0) < 1e-5) { if (lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS) { /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) { msProjectRect(&sProjTmp, &lp->projection, &sQueryRect); } } else if (lp->map->projection.numargs > 0) msProjectRect(&lp->map->projection, &lp->projection, &sQueryRect); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } if (sQueryRect.minx <= -1e14) { msFreeShape(psTmpShape); msFree(psTmpShape); psTmpShape = (shapeObj*) msSmallMalloc(sizeof(shapeObj)); msInitShape(psTmpShape); msRectToPolygon(sQueryRect, psTmpShape); bAlreadyReprojected = 1; } } bBBoxQuery = 1; } else { /* other geos type operations */ /* project shape to layer projection. If the proj is not part of the filter query, assume that the cooredinates are in the map projection */ psQueryShape = FLTGetShape(psNode, &dfDistance, &nUnit); if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0 ) && dfDistance > 0) { nLayerUnit = lp->units; if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->projection); if(nLayerUnit == -1) nLayerUnit = lp->map->units; if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->map->projection); if (nUnit >= 0 && nUnit != nLayerUnit) dfDistance *= msInchesPerUnit(nUnit,0)/msInchesPerUnit(nLayerUnit,0); /* target is layer units */ } psTmpShape = psQueryShape; } if (psTmpShape) { /* ** target is layer projection */ if (!bAlreadyReprojected && lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS) { /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) { msProjectShape(&sProjTmp, &lp->projection, psTmpShape); } } else if (lp->map->projection.numargs > 0) msProjectShape(&lp->map->projection, &lp->projection, psTmpShape); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } /* function name */ if (bBBoxQuery) { sprintf(szBuffer, "%s", "intersects"); } else { if (strncasecmp(psNode->pszValue, "intersect", 9) == 0) sprintf(szBuffer, "%s", "intersects"); else { pszTmp = msStrdup(psNode->pszValue); msStringToLower(pszTmp); sprintf(szBuffer, "%s", pszTmp); msFree(pszTmp); } } pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, "("); /* geometry binding */ sprintf(szBuffer, "%s", "[shape]"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, ","); /* filter geometry */ pszWktText = msGEOSShapeToWKT(psTmpShape); sprintf(szBuffer, "%s", "fromText('"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszWktText); sprintf(szBuffer, "%s", "')"); pszExpression = msStringConcatenate(pszExpression, szBuffer); msGEOSFreeWKT(pszWktText); /* (optional) beyond/dwithin distance, always 0.0 since we apply the distance as a buffer earlier */ if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0)) { // pszExpression = msStringConcatenate(pszExpression, ",0.0"); sprintf(szBuffer, ",%g", dfDistance); pszExpression = msStringConcatenate(pszExpression, szBuffer); } /* terminate the function */ pszExpression = msStringConcatenate(pszExpression, ") = TRUE"); } /* ** Cleanup */ if (bBBoxQuery) { msFreeShape(psTmpShape); msFree(psTmpShape); } return pszExpression; }
int msPreloadSVGSymbol(symbolObj *symbol) { #ifdef USE_SVG_CAIRO int status; unsigned int svg_width, svg_height; struct svg_symbol_cache *cache; if(!symbol->renderer_cache) { cache = msSmallCalloc(1,sizeof(struct svg_symbol_cache)); } else { cache = symbol->renderer_cache; } if(cache->svgc) return MS_SUCCESS; if (!symbol->svg_text) { FILE *stream; long int file_len; if ((stream = fopen(symbol->full_pixmap_path, "rb")) == NULL) { msSetError(MS_IOERR, "Could not open svg file %s", "msPreloadSVGSymbol()",symbol->full_pixmap_path); return (MS_FAILURE); } fseek(stream, 0, SEEK_END); file_len = ftell(stream); rewind(stream); symbol->svg_text = (char*) msSmallMalloc(sizeof (char) * file_len); if (1 != fread(symbol->svg_text, file_len, 1, stream)) { msSetError(MS_IOERR, "failed to read %d bytes from svg file %s", "loadSymbol()", file_len, symbol->full_pixmap_path); free(symbol->svg_text); return MS_FAILURE; } symbol->svg_text[file_len - 1] = '\0'; fclose(stream); } status = svg_cairo_create(&cache->svgc); if (status) { msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()"); return MS_FAILURE; } status = svg_cairo_parse_buffer(cache->svgc, symbol->svg_text, strlen(symbol->svg_text)); if (status) { msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()"); return MS_FAILURE; } svg_cairo_get_size (cache->svgc, &svg_width, &svg_height); if (svg_width == 0 || svg_height == 0) { msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()"); return MS_FAILURE; } symbol->sizex = svg_width; symbol->sizey = svg_height; symbol->renderer_cache = cache; return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but is not built with libsvgcairo", "msPreloadSVGSymbol()"); return MS_FAILURE; #endif }
int utfgridCleanData(imageObj *img) { UTFGridRenderer *r = UTFGRID_RENDERER(img); unsigned char* usedChar; int i,bufferLength,itemFound,dataCounter; shapeData* updatedData; band_type utfvalue; bufferLength = (img->height/r->utfresolution) * (img->width/r->utfresolution); usedChar =(unsigned char*) msSmallMalloc(r->data->counter*sizeof(unsigned char)); for(i=0;i<r->data->counter;i++){ usedChar[i]=0; } itemFound=0; for(i=0;i<bufferLength;i++) { if(decodeRendered(r->buffer[i]) != 0 && usedChar[decodeRendered(r->buffer[i])-1]==0) { itemFound++; usedChar[decodeRendered(r->buffer[i])-1] = 1; } } updatedData = (shapeData*) msSmallMalloc(itemFound * sizeof(shapeData)); dataCounter = 0; for(i=0; i< r->data->counter; i++){ if(usedChar[decodeRendered(r->data->table[i].utfvalue)-1]==1){ updatedData[dataCounter] = r->data->table[i]; updatedData[dataCounter].serialid=dataCounter+1; utfvalue=encodeForRendering(dataCounter+1); utfgridUpdateChar(img,updatedData[dataCounter].utfvalue,utfvalue); updatedData[dataCounter].utfvalue = utfvalue; dataCounter++; } else { if(r->data->table[i].datavalues) msFree(r->data->table[i].datavalues); if(r->data->table[i].itemvalue) msFree(r->data->table[i].itemvalue); } } msFree(usedChar); msFree(r->data->table); r->data->table = updatedData; r->data->counter = dataCounter; r->data->size = dataCounter; return MS_SUCCESS; }
/** * replace wrap characters with \n , respecting maximal line length. * * returns a pointer to the newly allocated text. memory is controlled * inside this function, so the caller MUST use the pointer returned by * the function: * text = msWrapText(label,text); * * TODO/FIXME: function will produce erroneous/crashing? results * if the wrap character is encoded with multiple bytes * * see http://mapserver.org/development/rfc/ms-rfc-40.html * for a summary of how wrap/maxlength interact on the result * of the text transformation */ char *msWrapText(labelObj *label, char *text) { char wrap; int maxlength; if(!text) /*not an error if no text*/ return text; wrap = label->wrap; maxlength = label->maxlength; if(maxlength == 0) { if(wrap!='\0') { /* if maxlength = 0 *and* a wrap character was specified, * replace all wrap characters by \n * this is the traditional meaning of the wrap character */ msReplaceChar(text, wrap, '\n'); } /* if neither maxlength, nor wrap were specified, * don't transform this text */ return text; } else if(maxlength>0) { if(wrap!='\0') { /* split input text at the wrap character, only if * the current line length is over maxlength */ /* TODO: check if the wrap character is a valid byte * inside a multibyte utf8 glyph. if so, the msCountChars * will return an erroneous value */ int numwrapchars = msCountChars(text,wrap); if(numwrapchars > 0) { if(label->encoding) { /* we have to use utf decoding functions here, so as not to * split a text line on a multibyte character */ int num_cur_glyph_on_line = 0; /*count for the number of glyphs on the current line*/ char *textptr = text; char glyph[11]; /*storage for unicode fetching function*/ int glyphlen = 0; /*size of current glyph in bytes*/ while((glyphlen = msGetNextGlyph((const char**)&textptr,glyph))>0) { num_cur_glyph_on_line++; if(*glyph == wrap && num_cur_glyph_on_line>=(maxlength)) { /*FIXME (if wrap becomes something other than char):*/ *(textptr-1)='\n'; /*replace wrap char with a \n*/ num_cur_glyph_on_line=0; /*reset count*/ } } } else { int cur_char_on_line = 0; char *textptr = text; while(*textptr != 0) { cur_char_on_line++; if(*textptr == wrap && cur_char_on_line>=maxlength) { *textptr='\n'; /*replace wrap char with a \n*/ cur_char_on_line=0; /*reset count*/ } textptr++; } } return text; } else { /*there are no characters available for wrapping*/ return text; } } else { /* if no wrap character was specified, but a maxlength was, * don't draw this label if it is longer than the specified maxlength*/ if(msGetNumGlyphs(text)>maxlength) { free(text); return NULL; } else { return text; } } } else { /* negative maxlength: we split lines unconditionally, i.e. without loooking for a wrap character*/ int numglyphs,numlines; maxlength = -maxlength; /* use a positive value*/ numglyphs = msGetNumGlyphs(text); numlines = (numglyphs-1) / maxlength + 1; /*count total number of lines needed after splitting*/ if(numlines>1) { char *newtext = msSmallMalloc(strlen(text)+numlines+1); char *newtextptr = newtext; char *textptr = text; int glyphlen = 0, num_cur_glyph = 0; while((glyphlen = msGetNextGlyph((const char**)&textptr,newtextptr))>0) { num_cur_glyph++; newtextptr += glyphlen; if(num_cur_glyph%maxlength == 0 && num_cur_glyph != numglyphs) { /*we're at a split location, insert a newline*/ *newtextptr = '\n'; newtextptr++; } } free(text); return newtext; } else { /*no splitting needed, return the original*/ return text; } } }
shapeObj* msSmoothShapeSIA(shapeObj *shape, int ss, int si, char *preprocessing) { int i, j; pointObj *p; double *coeff; shapeObj *newShape; newShape = (shapeObj *) msSmallMalloc(sizeof (shapeObj)); msInitShape(newShape); if (ss < 3) ss = 3; if (si < 1) si = 1; /* Apply preprocessing */ if (preprocessing) { if (strcasecmp(preprocessing, "all") == 0) processShapePathDistance(shape, MS_TRUE); else if (strcasecmp(preprocessing, "angle") == 0) processShapePathDistance(shape, MS_FALSE); } p = (pointObj *) msSmallMalloc(ss*sizeof(pointObj)); coeff = (double *) msSmallMalloc(ss*sizeof (double)); for (i=0;i<si;++i) { shapeObj initialShape; if (si > 1 && i>0) { msInitShape(&initialShape); msCopyShape(shape, &initialShape); /* Clean our shape object */ for (j=0; j < newShape->numlines; ++j) free(newShape->line[j].point); newShape->numlines = 0; if (newShape->line) { free(newShape->line); newShape->line = NULL; } shape = &initialShape; } for (j=0;j<shape->numlines;++j) { int k, ws, res; lineObj newLine = {0,NULL}; lineWindow lw; /* determine if we can use the ss for this line */ ws = ss; if (ws >= shape->line[j].numpoints) { ws = shape->line[j].numpoints-1; } if (ws%2==0) ws-=1; initLineWindow(&lw, &shape->line[j], ws); msAddLine(newShape, &newLine); coeff[lw.index] = 1; for (k=0;k<lw.index;++k) { coeff[lw.index+(k+1)] = coeff[lw.index-k]/2; coeff[lw.index-(k+1)] = coeff[lw.index+k]/2; } while ((res = nextLineWindow(&lw)) != MS_DONE) { double sum_x=0, sum_y=0, sum = 0; pointObj point; int k = 0; if (res == MS_FALSE) { /* invalid window */ msAddPointToLine(&newShape->line[j], lw.points[lw.index]); continue; } /* Apply Coefficient */ p[lw.index] = *lw.points[lw.index]; for (k=0; k<lw.index; ++k) { p[lw.index-(k+1)] = *lw.points[lw.index-(k+1)]; p[lw.index-(k+1)].x *= coeff[lw.index-(k+1)]; p[lw.index-(k+1)].y *= coeff[lw.index-(k+1)]; p[lw.index+(k+1)] = *lw.points[lw.index+(k+1)]; p[lw.index+(k+1)].x *= coeff[lw.index+(k+1)]; p[lw.index+(k+1)].y *= coeff[lw.index+(k+1)]; } for (k=0; k<lw.size; ++k) { sum += coeff[k]; sum_x += p[k].x; sum_y += p[k].y; } point.x = sum_x/sum; point.y = sum_y/sum; msAddPointToLine(&newShape->line[j], &point); } freeLineWindow(&lw); } if (i>0) { msFreeShape(shape); shape = newShape; } } free(p); free(coeff); return newShape; }
SHPTreeHandle msSHPDiskTreeOpen(const char * pszTree, int debug) { char *pszFullname, *pszBasename; SHPTreeHandle psTree; char pabyBuf[16]; int i; char bBigEndian; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Initialize the info structure. */ /* -------------------------------------------------------------------- */ psTree = (SHPTreeHandle) msSmallMalloc(sizeof(SHPTreeInfo)); /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszTree)+5); strcpy( pszBasename, pszTree ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, MS_INDEX_EXTENSION); psTree->fp = fopen(pszFullname, "rb" ); if( psTree->fp == NULL ) { sprintf( pszFullname, "%s.QIX", pszBasename); psTree->fp = fopen(pszFullname, "rb" ); } msFree(pszBasename); /* don't need these any more */ msFree(pszFullname); if( psTree->fp == NULL ) { msFree(psTree); return( NULL ); } fread( pabyBuf, 8, 1, psTree->fp ); memcpy( &psTree->signature, pabyBuf, 3 ); if( strncmp(psTree->signature,"SQT",3) ) { /* ---------------------------------------------------------------------- */ /* must check if the 2 first bytes equal 0 of max depth that cannot */ /* be more than 65535. If yes, we must swap all value. The problem */ /* here is if there's no Depth (bytea 5,6,7,8 in the file) all bytes */ /* will be set to 0. So,we will test with the number of shapes (bytes */ /* 1,2,3,4) that cannot be more than 65535 too. */ /* ---------------------------------------------------------------------- */ if (debug) { msDebug("WARNING in msSHPDiskTreeOpen(): %s is in old index format " "which has been deprecated. It is strongly recommended to " "regenerate it in new format.\n", pszTree); } if((pabyBuf[4] == 0 && pabyBuf[5] == 0 && pabyBuf[6] == 0 && pabyBuf[7] == 0)) { psTree->LSB_order = !(pabyBuf[0] == 0 && pabyBuf[1] == 0); } else { psTree->LSB_order = !(pabyBuf[4] == 0 && pabyBuf[5] == 0); } psTree->needswap = ((psTree->LSB_order) != (!bBigEndian)); /* ---------------------------------------------------------------------- */ /* poor hack to see if this quadtree was created by a computer with a */ /* different Endian */ /* ---------------------------------------------------------------------- */ psTree->version = 0; } else { psTree->needswap = (( pabyBuf[3] == MS_NEW_MSB_ORDER ) ^ ( bBigEndian )); psTree->LSB_order = ( pabyBuf[3] == MS_NEW_LSB_ORDER ); memcpy( &psTree->version, pabyBuf+4, 1 ); memcpy( &psTree->flags, pabyBuf+5, 3 ); fread( pabyBuf, 8, 1, psTree->fp ); } if( psTree->needswap ) SwapWord( 4, pabyBuf ); memcpy( &psTree->nShapes, pabyBuf, 4 ); if( psTree->needswap ) SwapWord( 4, pabyBuf+4 ); memcpy( &psTree->nDepth, pabyBuf+4, 4 ); return( psTree ); }
/********************************************************************** * msHTTPExecuteRequests() * * Fetch a map slide via HTTP request and save to specified temp file. * * If bCheckLocalCache==MS_TRUE then if the pszOutputfile already exists * then is is not downloaded again, and status 242 is returned. * * Return value: * MS_SUCCESS if all requests completed succesfully. * MS_FAILURE if a fatal error happened * MS_DONE if some requests failed with 40x status for instance (not fatal) **********************************************************************/ int msHTTPExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, int bCheckLocalCache) { int i, nStatus = MS_SUCCESS, nTimeout, still_running=0, num_msgs=0; CURLM *multi_handle; CURLMsg *curl_msg; char debug = MS_FALSE; const char *pszCurlCABundle = NULL; if (numRequests == 0) return MS_SUCCESS; /* Nothing to do */ if (!gbCurlInitialized) msHTTPInit(); /* Establish the timeout (seconds) for how long we are going to wait * for a response. * We use the longest timeout value in the array of requests */ nTimeout = pasReqInfo[0].nTimeout; for (i=0; i<numRequests; i++) { if (pasReqInfo[i].nTimeout > nTimeout) nTimeout = pasReqInfo[i].nTimeout; if (pasReqInfo[i].debug) debug = MS_TRUE; /* For the download loop */ } if (nTimeout <= 0) nTimeout = 30; /* Check if we've got a CURL_CA_BUNDLE env. var. * If set then the value is the full path to the ca-bundle.crt file * e.g. CURL_CA_BUNDLE=/usr/local/share/curl/curl-ca-bundle.crt */ pszCurlCABundle = getenv("CURL_CA_BUNDLE"); if (debug) { msDebug("HTTP: Starting to prepare HTTP requests.\n"); if (pszCurlCABundle) msDebug("Using CURL_CA_BUNDLE=%s\n", pszCurlCABundle); } /* Alloc a curl-multi handle, and add a curl-easy handle to it for each * file to download. */ multi_handle = curl_multi_init(); if (multi_handle == NULL) { msSetError(MS_HTTPERR, "curl_multi_init() failed.", "msHTTPExecuteRequests()"); return(MS_FAILURE); } for (i=0; i<numRequests; i++) { CURL *http_handle; FILE *fp; if (pasReqInfo[i].pszGetUrl == NULL ) { msSetError(MS_HTTPERR, "URL or output file parameter missing.", "msHTTPExecuteRequests()"); return(MS_FAILURE); } if (pasReqInfo[i].debug) { msDebug("HTTP request: id=%d, %s\n", pasReqInfo[i].nLayerId, pasReqInfo[i].pszGetUrl); } /* Reset some members */ pasReqInfo[i].nStatus = 0; if (pasReqInfo[i].pszContentType) free(pasReqInfo[i].pszContentType); pasReqInfo[i].pszContentType = NULL; /* Check local cache if requested */ if (bCheckLocalCache && pasReqInfo[i].pszOutputFile != NULL ) { fp = fopen(pasReqInfo[i].pszOutputFile, "r"); if (fp) { /* File already there, don't download again. */ if (pasReqInfo[i].debug) msDebug("HTTP request: id=%d, found in cache, skipping.\n", pasReqInfo[i].nLayerId); fclose(fp); pasReqInfo[i].nStatus = 242; pasReqInfo[i].pszContentType = msStrdup("unknown/cached"); continue; } } /* Alloc curl handle */ http_handle = curl_easy_init(); if (http_handle == NULL) { msSetError(MS_HTTPERR, "curl_easy_init() failed.", "msHTTPExecuteRequests()"); return(MS_FAILURE); } pasReqInfo[i].curl_handle = http_handle; /* set URL, note that curl keeps only a ref to our string buffer */ curl_easy_setopt(http_handle, CURLOPT_URL, pasReqInfo[i].pszGetUrl ); /* Set User-Agent (auto-generate if not set by caller */ if (pasReqInfo[i].pszUserAgent == NULL) { curl_version_info_data *psCurlVInfo; psCurlVInfo = curl_version_info(CURLVERSION_NOW); pasReqInfo[i].pszUserAgent = (char*)msSmallMalloc(100*sizeof(char)); if (pasReqInfo[i].pszUserAgent) { sprintf(pasReqInfo[i].pszUserAgent, "MapServer/%s libcurl/%d.%d.%d", MS_VERSION, psCurlVInfo->version_num/0x10000 & 0xff, psCurlVInfo->version_num/0x100 & 0xff, psCurlVInfo->version_num & 0xff ); } } if (pasReqInfo[i].pszUserAgent) { curl_easy_setopt(http_handle, CURLOPT_USERAGENT, pasReqInfo[i].pszUserAgent ); } /* Enable following redirections. Requires libcurl 7.10.1 at least */ curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1 ); curl_easy_setopt(http_handle, CURLOPT_MAXREDIRS, 10 ); /* Set timeout.*/ curl_easy_setopt(http_handle, CURLOPT_TIMEOUT, nTimeout ); /* Pass CURL_CA_BUNDLE if set */ if (pszCurlCABundle) curl_easy_setopt(http_handle, CURLOPT_CAINFO, pszCurlCABundle ); /* Set proxying settings */ if (pasReqInfo[i].pszProxyAddress != NULL && strlen(pasReqInfo[i].pszProxyAddress) > 0) { long nProxyType = CURLPROXY_HTTP; curl_easy_setopt(http_handle, CURLOPT_PROXY, pasReqInfo[i].pszProxyAddress); if (pasReqInfo[i].nProxyPort > 0 && pasReqInfo[i].nProxyPort < 65535) { curl_easy_setopt(http_handle, CURLOPT_PROXYPORT, pasReqInfo[i].nProxyPort); } switch (pasReqInfo[i].eProxyType) { case MS_HTTP: nProxyType = CURLPROXY_HTTP; break; case MS_SOCKS5: nProxyType = CURLPROXY_SOCKS5; break; } curl_easy_setopt(http_handle, CURLOPT_PROXYTYPE, nProxyType); /* If there is proxy authentication information, set it */ if (pasReqInfo[i].pszProxyUsername != NULL && pasReqInfo[i].pszProxyPassword != NULL && strlen(pasReqInfo[i].pszProxyUsername) > 0 && strlen(pasReqInfo[i].pszProxyPassword) > 0) { char szUsernamePasswd[128]; #ifdef USE_CURLOPT_PROXYAUTH long nProxyAuthType = CURLAUTH_BASIC; /* CURLOPT_PROXYAUTH available only in Curl 7.10.7 and up */ nProxyAuthType = msGetCURLAuthType(pasReqInfo[i].eProxyAuthType); curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, nProxyAuthType); #else /* We log an error but don't abort processing */ msSetError(MS_HTTPERR, "CURLOPT_PROXYAUTH not supported. Requires Curl 7.10.7 and up. *_proxy_auth_type setting ignored.", "msHTTPExecuteRequests()"); #endif /* CURLOPT_PROXYAUTH */ snprintf(szUsernamePasswd, 127, "%s:%s", pasReqInfo[i].pszProxyUsername, pasReqInfo[i].pszProxyPassword); curl_easy_setopt(http_handle, CURLOPT_PROXYUSERPWD, szUsernamePasswd); } } /* Set HTTP Authentication settings */ if (pasReqInfo[i].pszHttpUsername != NULL && pasReqInfo[i].pszHttpPassword != NULL && strlen(pasReqInfo[i].pszHttpUsername) > 0 && strlen(pasReqInfo[i].pszHttpPassword) > 0) { char szUsernamePasswd[128]; long nHttpAuthType = CURLAUTH_BASIC; snprintf(szUsernamePasswd, 127, "%s:%s", pasReqInfo[i].pszHttpUsername, pasReqInfo[i].pszHttpPassword); curl_easy_setopt(http_handle, CURLOPT_USERPWD, szUsernamePasswd); nHttpAuthType = msGetCURLAuthType(pasReqInfo[i].eHttpAuthType); curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, nHttpAuthType); } /* NOSIGNAL should be set to true for timeout to work in multithread * environments on Unix, requires libcurl 7.10 or more recent. * (this force avoiding the use of sgnal handlers) */ #ifdef CURLOPT_NOSIGNAL curl_easy_setopt(http_handle, CURLOPT_NOSIGNAL, 1 ); #endif /* If we are writing file to disk, open the file now. */ if( pasReqInfo[i].pszOutputFile != NULL ) { if ( (fp = fopen(pasReqInfo[i].pszOutputFile, "wb")) == NULL) { msSetError(MS_HTTPERR, "Can't open output file %s.", "msHTTPExecuteRequests()", pasReqInfo[i].pszOutputFile); return(MS_FAILURE); } pasReqInfo[i].fp = fp; } curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, &(pasReqInfo[i])); curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, msHTTPWriteFct); /* Provide a buffer where libcurl can write human readable error msgs */ if (pasReqInfo[i].pszErrBuf == NULL) pasReqInfo[i].pszErrBuf = (char *)msSmallMalloc((CURL_ERROR_SIZE+1)* sizeof(char)); pasReqInfo[i].pszErrBuf[0] = '\0'; curl_easy_setopt(http_handle, CURLOPT_ERRORBUFFER, pasReqInfo[i].pszErrBuf); if(pasReqInfo[i].pszPostRequest != NULL ) { char szBuf[100]; struct curl_slist *headers=NULL; snprintf(szBuf, 100, "Content-Type: %s", pasReqInfo[i].pszPostContentType); headers = curl_slist_append(headers, szBuf); curl_easy_setopt(http_handle, CURLOPT_POST, 1 ); curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, pasReqInfo[i].pszPostRequest); curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers); /* curl_slist_free_all(headers); */ /* free the header list */ } /* Added by RFC-42 HTTP Cookie Forwarding */ if(pasReqInfo[i].pszHTTPCookieData != NULL) { /* Check if there's no end of line in the Cookie string */ /* This could break the HTTP Header */ int nPos; for(nPos=0; nPos<strlen(pasReqInfo[i].pszHTTPCookieData); nPos++) { if(pasReqInfo[i].pszHTTPCookieData[nPos] == '\n') { msSetError(MS_HTTPERR, "Can't use cookie containing a newline character.", "msHTTPExecuteRequests()"); return(MS_FAILURE); } } /* Set the Curl option to send Cookie */ curl_easy_setopt(http_handle, CURLOPT_COOKIE, pasReqInfo[i].pszHTTPCookieData); } /* Add to multi handle */ curl_multi_add_handle(multi_handle, http_handle); } if (debug) { msDebug("HTTP: Before download loop\n"); } /* DOWNLOAD LOOP ... inspired from multi-double.c example */ /* we start some action by calling perform right away */ while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &still_running)); while(still_running) { struct timeval timeout; int rc; /* select() return code */ fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); /* set a suitable timeout to play around with */ timeout.tv_sec = 0; timeout.tv_usec = 100000; /* get file descriptors from the transfers */ curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); switch(rc) { case -1: /* select error */ /* ==================================================================== */ /* On Windows the select function (just above) returns -1 when */ /* it is called the second time and all the calls after */ /* that. This causes an infinite loop. */ /* I do not really know why. */ /* To sovle the problem the break frop case -1 has been removed. */ /* ==================================================================== */ #ifndef _WIN32 break; #endif case 0: default: /* timeout or readable/writable sockets */ curl_multi_perform(multi_handle, &still_running); break; } } if (debug) msDebug("HTTP: After download loop\n"); /* Scan message stack from CURL and report fatal errors*/ while((curl_msg = curl_multi_info_read( multi_handle, &num_msgs)) != NULL) { httpRequestObj *psReq = NULL; if (curl_msg->msg == CURLMSG_DONE && curl_msg->data.result != CURLE_OK) { /* Something went wrong with this transfer... report error */ for (i=0; i<numRequests; i++) { if (pasReqInfo[i].curl_handle == curl_msg->easy_handle) { psReq = &(pasReqInfo[i]); break; } } if (psReq != NULL) { /* Record error code in nStatus as a negative value */ psReq->nStatus = -curl_msg->data.result; } } } if (debug) { /* Print a msDebug header for timings reported in the loop below */ msDebug("msHTTPExecuteRequests() timing summary per layer (connect_time + time_to_first_packet + download_time = total_time in seconds)\n"); } /* Check status of all requests, close files, report errors and cleanup * handles */ for (i=0; i<numRequests; i++) { httpRequestObj *psReq; CURL *http_handle; long lVal=0; psReq = &(pasReqInfo[i]); if (psReq->nStatus == 242) continue; /* Nothing to do here, this file was in cache already */ if (psReq->fp) fclose(psReq->fp); psReq->fp = NULL; http_handle = (CURL*)(psReq->curl_handle); if (psReq->nStatus == 0 && curl_easy_getinfo(http_handle, CURLINFO_HTTP_CODE, &lVal) == CURLE_OK) { char *pszContentType = NULL; psReq->nStatus = lVal; /* Fetch content type of response */ if (curl_easy_getinfo(http_handle, CURLINFO_CONTENT_TYPE, &pszContentType) == CURLE_OK && pszContentType != NULL) { psReq->pszContentType = msStrdup(pszContentType); } } if (!MS_HTTP_SUCCESS(psReq->nStatus)) { /* Set status to MS_DONE to indicate that transfers were */ /* completed but may not be succesfull */ nStatus = MS_DONE; if (psReq->nStatus == -(CURLE_OPERATION_TIMEOUTED)) { /* Timeout isn't a fatal error */ if (psReq->debug) msDebug("HTTP: TIMEOUT of %d seconds exceeded for %s\n", nTimeout, psReq->pszGetUrl ); msSetError(MS_HTTPERR, "HTTP: TIMEOUT of %d seconds exceeded for %s\n", "msHTTPExecuteRequests()", nTimeout, psReq->pszGetUrl); /* Rewrite error message, the curl timeout message isn't * of much use to our users. */ sprintf(psReq->pszErrBuf, "TIMEOUT of %d seconds exceeded.", nTimeout); } else if (psReq->nStatus > 0) { /* Got an HTTP Error, e.g. 404, etc. */ if (psReq->debug) msDebug("HTTP: HTTP GET request failed with status %d (%s)" " for %s\n", psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); msSetError(MS_HTTPERR, "HTTP GET request failed with status %d (%s) " "for %s", "msHTTPExecuteRequests()", psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); } else { /* Got a curl error */ if (psReq->debug) msDebug("HTTP: request failed with curl error " "code %d (%s) for %s", -psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); msSetError(MS_HTTPERR, "HTTP: request failed with curl error " "code %d (%s) for %s", "msHTTPExecuteRequests()", -psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); } } /* Report download times foreach handle, in debug mode */ if (psReq->debug) { double dConnectTime=0.0, dTotalTime=0.0, dStartTfrTime=0.0; curl_easy_getinfo(http_handle, CURLINFO_CONNECT_TIME, &dConnectTime); curl_easy_getinfo(http_handle, CURLINFO_STARTTRANSFER_TIME, &dStartTfrTime); curl_easy_getinfo(http_handle, CURLINFO_TOTAL_TIME, &dTotalTime); /* STARTTRANSFER_TIME includes CONNECT_TIME, but TOTAL_TIME * doesn't, so we need to add it. */ dTotalTime += dConnectTime; msDebug("Layer %d: %.3f + %.3f + %.3f = %.3fs\n", psReq->nLayerId, dConnectTime, dStartTfrTime-dConnectTime, dTotalTime-dStartTfrTime, dTotalTime); } /* Cleanup this handle */ curl_easy_setopt(http_handle, CURLOPT_URL, "" ); curl_multi_remove_handle(multi_handle, http_handle); curl_easy_cleanup(http_handle); psReq->curl_handle = NULL; } /* Cleanup multi handle, each handle had to be cleaned up individually */ curl_multi_cleanup(multi_handle); return nStatus; }
/* * generic function for drawing a legend icon. (added for bug #2348) * renderer specific drawing functions shouldn't be called directly, but through * this function */ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, int width, int height, imageObj *image, int dstX, int dstY) { int i, type, hasmarkersymbol; double offset; shapeObj box, zigzag; pointObj marker; char szPath[MS_MAXPATHLEN]; styleObj outline_style; imageObj *image_draw = image; int originalopacity = lp->opacity; rendererVTableObj *renderer; outputFormatObj *transFormat = NULL, *altFormat=NULL; const char *alternativeFormatString = NULL; if(!MS_RENDERER_PLUGIN(image->format)) { msSetError(MS_MISCERR,"unsupported image format","msDrawLegendIcon()"); return MS_FAILURE; } alternativeFormatString = msLayerGetProcessingKey(lp, "RENDERER"); if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFormatString!=NULL && (altFormat= msSelectOutputFormat(map, alternativeFormatString))) { msInitializeRendererVTable(altFormat); image_draw = msImageCreate(image->width, image->height, altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor); renderer = MS_IMAGE_RENDERER(image_draw); } else { renderer = MS_IMAGE_RENDERER(image_draw); if (lp->opacity > 0 && lp->opacity < 100) { if (!renderer->supports_transparent_layers) { image_draw = msImageCreate(image->width, image->height, image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!image_draw) { msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.", "msDrawLegendIcon()"); return (MS_FAILURE); } /* set opacity to full, as the renderer should be rendering a fully opaque image */ lp->opacity=100; } } } if(renderer->supports_clipping && MS_VALID_COLOR(map->legend.outlinecolor)) { /* keep GD specific code here for now as it supports clipping */ rectObj clip; clip.maxx = dstX + width - 1; clip.maxy = dstY + height -1; clip.minx = dstX; clip.miny = dstY; renderer->setClip(image_draw,clip); } /* initialize the box used for polygons and for outlines */ box.line = (lineObj *)msSmallMalloc(sizeof(lineObj)); box.numlines = 1; box.line[0].point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5); box.line[0].numpoints = 5; box.line[0].point[0].x = dstX + 0.5; box.line[0].point[0].y = dstY + 0.5; box.line[0].point[1].x = dstX + width - 0.5; box.line[0].point[1].y = dstY + 0.5; box.line[0].point[2].x = dstX + width - 0.5; box.line[0].point[2].y = dstY + height - 0.5; box.line[0].point[3].x = dstX + 0.5; box.line[0].point[3].y = dstY + height - 0.5; box.line[0].point[4].x = box.line[0].point[0].x; box.line[0].point[4].y = box.line[0].point[0].y; box.line[0].numpoints = 5; /* if the class has a keyimage, treat it as a point layer * (the keyimage will be treated there) */ if(theclass->keyimage != NULL) { type = MS_LAYER_POINT; } else { /* some polygon layers may be better drawn using zigzag if there is no fill */ type = lp->type; if(type == MS_LAYER_POLYGON) { type = MS_LAYER_LINE; for(i=0; i<theclass->numstyles; i++) { if(MS_VALID_COLOR(theclass->styles[i]->color)) { /* there is a fill */ type = MS_LAYER_POLYGON; break; } } } } /* ** now draw the appropriate color/symbol/size combination */ switch(type) { case MS_LAYER_ANNOTATION: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); hasmarkersymbol = 0; for(i=0; i<theclass->numstyles; i++) { if (theclass->styles[i]->symbol < map->symbolset.numsymbols && theclass->styles[i]->symbol > 0) { hasmarkersymbol = 1; break; } } if (hasmarkersymbol) { for(i=0; i<theclass->numstyles; i++) msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor); } else if (theclass->labels && theclass->numlabels > 0) { labelObj *label = theclass->labels[0]; /* use the first label definition */ double lsize = label->size; double langle = label->angle; int lpos = label->position; int loffsetx = label->offsetx; int loffsety = label->offsety; label->offsetx = 0; label->offsety = 0; label->angle = 0; label->position = MS_CC; if (label->type == MS_TRUETYPE) label->size = height; msDrawLabel(map, image_draw, marker, (char*)"Az", label,1.0); label->size = lsize; label->position = lpos; label->angle = langle; label->offsetx = loffsetx; label->offsety = loffsety; } break; case MS_LAYER_POINT: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); if(theclass->keyimage != NULL) { int symbolNum; styleObj imgStyle; symbolObj *symbol=NULL; symbolNum = msAddImageSymbol(&(map->symbolset), msBuildPath(szPath, map->mappath, theclass->keyimage)); if(symbolNum == -1) { msSetError(MS_GDERR, "Failed to open legend key image", "msCreateLegendIcon()"); return(MS_FAILURE); } symbol = map->symbolset.symbol[symbolNum]; initStyle(&imgStyle); /*set size so that symbol will be scaled properly #3296*/ if (width/symbol->sizex < height/symbol->sizey) imgStyle.size = symbol->sizey*(width/symbol->sizex); else imgStyle.size = symbol->sizey*(height/symbol->sizey); if (imgStyle.size > imgStyle.maxsize) imgStyle.maxsize = imgStyle.size; imgStyle.symbol = symbolNum; msDrawMarkerSymbol(&map->symbolset,image_draw,&marker,&imgStyle,lp->scalefactor); /* TO DO: we may want to handle this differently depending on the relative size of the keyimage */ } else { for(i=0; i<theclass->numstyles; i++) msDrawMarkerSymbol(&map->symbolset, image_draw, &marker, theclass->styles[i], lp->scalefactor); } break; case MS_LAYER_LINE: offset = 1; /* To set the offset, we only check the size/width parameter of the first style */ if (theclass->numstyles > 0) { if (theclass->styles[0]->symbol > 0 && theclass->styles[0]->symbol < map->symbolset.numsymbols && map->symbolset.symbol[theclass->styles[0]->symbol]->type != MS_SYMBOL_SIMPLE) offset = theclass->styles[0]->size/2; else offset = theclass->styles[0]->width/2; } zigzag.line = (lineObj *)msSmallMalloc(sizeof(lineObj)); zigzag.numlines = 1; zigzag.line[0].point = (pointObj *)msSmallMalloc(sizeof(pointObj)*4); zigzag.line[0].numpoints = 4; zigzag.line[0].point[0].x = dstX + offset; zigzag.line[0].point[0].y = dstY + height - offset; zigzag.line[0].point[1].x = dstX + MS_NINT(width / 3.0) - 1; zigzag.line[0].point[1].y = dstY + offset; zigzag.line[0].point[2].x = dstX + MS_NINT(2.0 * width / 3.0) - 1; zigzag.line[0].point[2].y = dstY + height - offset; zigzag.line[0].point[3].x = dstX + width - offset; zigzag.line[0].point[3].y = dstY + offset; for(i=0; i<theclass->numstyles; i++) msDrawLineSymbol(&map->symbolset, image_draw, &zigzag, theclass->styles[i], lp->scalefactor); free(zigzag.line[0].point); free(zigzag.line); break; case MS_LAYER_CIRCLE: case MS_LAYER_RASTER: case MS_LAYER_CHART: case MS_LAYER_POLYGON: for(i=0; i<theclass->numstyles; i++) msDrawShadeSymbol(&map->symbolset, image_draw, &box, theclass->styles[i], lp->scalefactor); break; default: return MS_FAILURE; break; } /* end symbol drawing */ /* handle an outline if necessary */ if(MS_VALID_COLOR(map->legend.outlinecolor)) { initStyle(&outline_style); outline_style.color = map->legend.outlinecolor; msDrawLineSymbol(&map->symbolset, image_draw, &box, &outline_style, 1.0); /* reset clipping rectangle */ if(renderer->supports_clipping) renderer->resetClip(image_draw); } if (altFormat) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rendererVTableObj *altrenderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); altrenderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height); /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; i<map->symbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == altrenderer) { altrenderer->freeSymbol(s); s->renderer = NULL; } } } msFreeImage(image_draw); } else if(image != image_draw) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); lp->opacity = originalopacity; renderer->getRasterBufferHandle(image_draw,&rb); renderer->mergeRasterBuffer(image,&rb,lp->opacity*0.01,0,0,0,0,rb.width,rb.height); msFreeImage(image_draw); /* deref and possibly free temporary transparent output format. */ msApplyOutputFormat( &transFormat, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } free(box.line[0].point); free(box.line); return MS_SUCCESS; }
/********************************************************************** * msBuildWFSLayerPostRequest() * * Build a WFS GetFeature xml document for a Post Request. * * Returns a reference to a newly allocated string that should be freed * by the caller. **********************************************************************/ static char *msBuildWFSLayerPostRequest(mapObj *map, layerObj *lp, rectObj *bbox, wfsParamsObj *psParams) { char *pszPostReq = NULL; char *pszFilter = NULL; char *pszGeometryName = "Geometry"; size_t bufferSize = 0; if (psParams->pszVersion == NULL || (strncmp(psParams->pszVersion, "0.0.14", 6) != 0 && strncmp(psParams->pszVersion, "1.0.0", 5)) != 0) { msSetError(MS_WFSCONNERR, "MapServer supports only WFS 1.0.0 or 0.0.14 (please verify the version metadata wfs_version).", "msBuildWFSLayerPostRequest()"); return NULL; } if (psParams->pszTypeName == NULL) { msSetError(MS_WFSCONNERR, "Metadata wfs_typename must be set in the layer", "msBuildWFSLayerPostRequest()"); return NULL; } if (psParams->pszGeometryName) { pszGeometryName = psParams->pszGeometryName; } if (psParams->pszFilter) pszFilter = psParams->pszFilter; else { bufferSize = 500; pszFilter = (char *)msSmallMalloc(bufferSize); snprintf(pszFilter, bufferSize, "<ogc:Filter>\n" "<ogc:BBOX>\n" "<ogc:PropertyName>%s</ogc:PropertyName>\n" "<gml:Box>\n" "<gml:coordinates>%f,%f %f,%f</gml:coordinates>\n" "</gml:Box>\n" "</ogc:BBOX>\n" "</ogc:Filter>", pszGeometryName, bbox->minx, bbox->miny, bbox->maxx, bbox->maxy); } bufferSize = strlen(pszFilter)+500; pszPostReq = (char *)msSmallMalloc(bufferSize); if (psParams->nMaxFeatures > 0) snprintf(pszPostReq, bufferSize, "<?xml version=\"1.0\" ?>\n" "<wfs:GetFeature\n" "service=\"WFS\"\n" "version=\"1.0.0\"\n" "maxFeatures=\"%d\"\n" "outputFormat=\"GML2\"\n" "xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:ogc=\"http://www.opengis.net/ogc\" xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:gml=\"http://www.opengis.net/gml\">\n" "<wfs:Query typeName=\"%s\">\n" "%s" "</wfs:Query>\n" "</wfs:GetFeature>\n", psParams->nMaxFeatures, psParams->pszTypeName, pszFilter); else snprintf(pszPostReq, bufferSize, "<?xml version=\"1.0\" ?>\n" "<wfs:GetFeature\n" "service=\"WFS\"\n" "version=\"1.0.0\"\n" "outputFormat=\"GML2\"\n" "xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:ogc=\"http://www.opengis.net/ogc\" xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:gml=\"http://www.opengis.net/gml\">\n" "<wfs:Query typeName=\"%s\">\n" "%s" "</wfs:Query>\n" "</wfs:GetFeature>\n", psParams->pszTypeName, pszFilter); if (psParams->pszFilter == NULL) free(pszFilter); return pszPostReq; }
int msContourLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i; rectObj newRect; contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerWhichShapes().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerWhichShapes()"); return MS_FAILURE; } newRect = rect; #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if (msProjectionsDiffer( &(layer->map->projection), &(layer->projection))) { if (msProjectRect(&layer->projection, &layer->map->projection, &newRect) != MS_SUCCESS ) { msDebug("msContourLayerWhichShapes(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } } #endif /* regenerate the raster io */ if (clinfo->hOGRDS) msConnPoolRelease(&clinfo->ogrLayer, clinfo->hOGRDS); msLayerClose(&clinfo->ogrLayer); /* Open the raster source */ if (msContourLayerReadRaster(layer, newRect) != MS_SUCCESS) return MS_FAILURE; /* Generate Contour Dataset */ if (msContourLayerGenerateContour(layer) != MS_SUCCESS) return MS_FAILURE; if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } if (!clinfo->hOGRDS) /* no overlap */ return MS_DONE; /* Open our virtual ogr layer */ if (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS) return MS_FAILURE; clinfo->ogrLayer.numitems = layer->numitems; clinfo->ogrLayer.items = (char **) msSmallMalloc(sizeof(char *)*layer->numitems); for (i=0; i<layer->numitems;++i) { clinfo->ogrLayer.items[i] = msStrdup(layer->items[i]); } return msLayerWhichShapes(&clinfo->ogrLayer, rect, isQuery); }
/* * Print the renderer datas as a JSON. */ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { int row, col, i, imgheight, imgwidth; band_type pixelid; char* pszEscaped; utfgridCleanData(img); UTFGridRenderer *renderer = UTFGRID_RENDERER(img); if(renderer->layerwatch>1) return MS_FAILURE; imgheight = img->height/renderer->utfresolution; imgwidth = img->width/renderer->utfresolution; fprintf(fp,"{\"grid\":["); /* Print the buffer, also */ for(row=0; row<imgheight; row++) { wchar_t *string = (wchar_t*) msSmallMalloc ((imgwidth + 1) * sizeof(wchar_t)); wchar_t *stringptr; stringptr = string; /* Needs comma between each lines but JSON must not start with a comma. */ if(row!=0) fprintf(fp,","); fprintf(fp,"\""); for(col=0; col<img->width/renderer->utfresolution; col++) { /* Get the datas from buffer. */ pixelid = renderer->buffer[(row*imgwidth)+col]; *stringptr = pixelid; stringptr++; } /* Convertion to UTF-8 encoding */ *stringptr = '\0'; char * utf8; utf8 = msConvertWideStringToUTF8 (string, "UCS-4LE"); fprintf(fp,"%s", utf8); msFree(utf8); msFree(string); fprintf(fp,"\""); } fprintf(fp,"],\"keys\":[\"\""); /* Prints the key specified */ for(i=0;i<renderer->data->counter;i++) { fprintf(fp,","); if(renderer->useutfitem) { pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue); fprintf(fp,"\"%s\"", pszEscaped); msFree(pszEscaped); } /* If no UTFITEM specified use the serial ID as the key */ else fprintf(fp,"\"%i\"", renderer->data->table[i].serialid); } fprintf(fp,"],\"data\":{"); /* Print the datas */ if(renderer->useutfdata) { for(i=0;i<renderer->data->counter;i++) { if(i!=0) fprintf(fp,","); if(renderer->useutfitem) { pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue); fprintf(fp,"\"%s\":", pszEscaped); msFree(pszEscaped); } /* If no UTFITEM specified use the serial ID as the key */ else fprintf(fp,"\"%i\":", renderer->data->table[i].serialid); fprintf(fp,"%s", renderer->data->table[i].datavalues); } } fprintf(fp,"}}"); return MS_SUCCESS; }
int readPostBody( cgiRequestObj *request, char **data ) { size_t data_max, data_len; int chunk_size; msIO_needBinaryStdin(); /* -------------------------------------------------------------------- */ /* If the length is provided, read in one gulp. */ /* -------------------------------------------------------------------- */ if( getenv("CONTENT_LENGTH") != NULL ) { data_max = (size_t) atoi(getenv("CONTENT_LENGTH")); /* Test for suspicious CONTENT_LENGTH (negative value or SIZE_MAX) */ if( data_max >= SIZE_MAX ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("Suspicious Content-Length.\n"); return MS_FAILURE; } *data = (char *) malloc(data_max+1); if( *data == NULL ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("malloc() failed, Content-Length: %u unreasonably large?\n", data_max ); return MS_FAILURE; } if( (int) msIO_fread(*data, 1, data_max, stdin) < data_max ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("POST body is short\n"); return MS_FAILURE; } (*data)[data_max] = '\0'; return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Otherwise read in chunks to the end. */ /* -------------------------------------------------------------------- */ #define DATA_ALLOC_SIZE 10000 data_max = DATA_ALLOC_SIZE; data_len = 0; *data = (char *) msSmallMalloc(data_max+1); while( (chunk_size = msIO_fread( *data + data_len, 1, data_max-data_len, stdin )) > 0 ) { data_len += chunk_size; if( data_len == data_max ) { /* Realloc buffer, making sure we check for possible size_t overflow */ if ( data_max > SIZE_MAX - (DATA_ALLOC_SIZE+1) ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("Possible size_t overflow, cannot reallocate input buffer, POST body too large?\n" ); return MS_FAILURE; } data_max = data_max + DATA_ALLOC_SIZE; *data = (char *) msSmallRealloc(*data, data_max+1); } } (*data)[data_len] = '\0'; return MS_SUCCESS; }
xmlNodePtr KmlRenderer::createDescriptionNode(shapeObj *shape) { /* <description> <![CDATA[ special characters here ]]> <description> */ /*description nodes for vector layers: - if kml_description is set, use it - if not, dump the attributes */ if (pszLayerDescMetadata) { char *pszTmp=NULL; char *pszTmpDesc = NULL; size_t bufferSize = 0; pszTmpDesc = msStrdup(pszLayerDescMetadata); for (int i=0; i<currentLayer->numitems; i++) { bufferSize = strlen(currentLayer->items[i]) + 3; pszTmp = (char *)msSmallMalloc(bufferSize); snprintf(pszTmp, bufferSize, "%%%s%%",currentLayer->items[i]); if (strcasestr(pszTmpDesc, pszTmp)) pszTmpDesc = msCaseReplaceSubstring(pszTmpDesc, pszTmp, shape->values[i]); msFree(pszTmp); } xmlNodePtr descriptionNode = xmlNewNode(NULL, BAD_CAST "description"); xmlNodeAddContent(descriptionNode, BAD_CAST pszTmpDesc); msFree(pszTmpDesc); return descriptionNode; } else if ((papszLayerIncludeItems && nIncludeItems > 0) || (papszLayerExcludeItems && nExcludeItems > 0)) { /* -------------------------------------------------------------------- */ /* preffered way is to use the ExtendedData tag (#3728) */ /* http://code.google.com/apis/kml/documentation/extendeddata.html */ /* -------------------------------------------------------------------- */ xmlNodePtr extendedDataNode = xmlNewNode(NULL, BAD_CAST "ExtendedData"); xmlNodePtr dataNode = NULL; const char*pszAlias=NULL; int bIncludeAll = MS_FALSE; if(papszLayerIncludeItems && nIncludeItems == 1 && strcasecmp(papszLayerIncludeItems[0], "all") == 0) bIncludeAll = MS_TRUE; for (int i=0; i<currentLayer->numitems; i++) { int j=0,k=0; /*TODO optimize to calculate this only once per layer*/ for (j=0; j<nIncludeItems; j++) { if (strcasecmp(currentLayer->items[i], papszLayerIncludeItems[j]) == 0) break; } if (j<nIncludeItems || bIncludeAll) { if (papszLayerExcludeItems && nExcludeItems > 0) { for (k=0; k<nExcludeItems; k++) { if (strcasecmp(currentLayer->items[i], papszLayerExcludeItems[k]) == 0) break; } } if (nExcludeItems == 0 || k == nExcludeItems) { dataNode = xmlNewNode(NULL, BAD_CAST "Data"); xmlNewProp(dataNode, BAD_CAST "name", BAD_CAST currentLayer->items[i]); pszAlias = getAliasName(currentLayer, currentLayer->items[i], "GO"); if (pszAlias) xmlNewChild(dataNode, NULL, BAD_CAST "displayName", BAD_CAST pszAlias); else xmlNewChild(dataNode, NULL, BAD_CAST "displayName", BAD_CAST currentLayer->items[i]); if (shape->values[i] && strlen(shape->values[i])) xmlNewChild(dataNode, NULL, BAD_CAST "value", BAD_CAST shape->values[i]); else xmlNewChild(dataNode, NULL, BAD_CAST "value", NULL); xmlAddChild(extendedDataNode, dataNode); } } } return extendedDataNode; } return NULL; }
/** * Compute a palette for the given RGBA rasterBuffer using a median cut quantization. * - rb: the rasterBuffer to quantize * - reqcolors: the desired number of colors the palette should contain. will be set * with the actual number of entries in the computed palette * - forced_palette: entries that should appear in the computed palette * - num_forced_palette_entries: number of entries contained in "force_palette". if 0, * "force_palette" can be NULL * - palette_scaling_maxval: the quantization process may have to reduce the image depth * by iteratively dividing the pixels by 2. In case palette_scaling_maxval is set to * something different than 255, the returned palette colors have to be scaled back up to * 255, and rb's pixels will have been scaled down to maxsize (see bug #3848) */ int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette, rgbaPixel *forced_palette, int num_forced_palette_entries, unsigned int *palette_scaling_maxval) { rgbaPixel **apixels=NULL; /* pointer to the start rows of truecolor pixels */ register rgbaPixel *pP; register int col; unsigned char newmaxval; acolorhist_vector achv, acolormap=NULL; int row; int colors; int newcolors = 0; int x; /* int channels; */ assert(rb->type == MS_BUFFER_BYTE_RGBA); *palette_scaling_maxval = 255; apixels=(rgbaPixel**)msSmallMalloc(rb->height*sizeof(rgbaPixel*)); for(row=0; row<rb->height; row++) { apixels[row]=(rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step])); } /* ** Step 2: attempt to make a histogram of the colors, unclustered. ** If at first we don't succeed, lower maxval to increase color ** coherence and try again. This will eventually terminate, with ** maxval at worst 15, since 32^3 is approximately MAXCOLORS. [GRR POSSIBLE BUG: what about 32^4 ?] */ for ( ; ; ) { achv = pam_computeacolorhist( apixels, rb->width, rb->height, MAXCOLORS, &colors ); if ( achv != (acolorhist_vector) 0 ) break; newmaxval = *palette_scaling_maxval / 2; for ( row = 0; row < rb->height; ++row ) for ( col = 0, pP = apixels[row]; col < rb->width; ++col, ++pP ) PAM_DEPTH( *pP, *pP, *palette_scaling_maxval, newmaxval ); *palette_scaling_maxval = newmaxval; } newcolors = MS_MIN(colors, *reqcolors); acolormap = mediancut(achv, colors, rb->width*rb->height, *palette_scaling_maxval, newcolors); pam_freeacolorhist(achv); *reqcolors = newcolors; for (x = 0; x < newcolors; ++x) { palette[x].r = acolormap[x].acolor.r; palette[x].g = acolormap[x].acolor.g; palette[x].b = acolormap[x].acolor.b; palette[x].a = acolormap[x].acolor.a; } free(acolormap); free(apixels); return MS_SUCCESS; }
/** * Is there any XMP metadata in the map file for us to worry about? */ int msXmpWrite( mapObj *map, const char *filename ) { #ifdef USE_EXEMPI /* Should hold our keys */ hashTableObj hash_metadata = map->web.metadata; /* Temporary place for custom name spaces */ hashTableObj hash_ns; /* We use regex to strip out the namespace and XMP key value from the metadata key */ regex_t xmp_regex; const char *xmp_ns_str = "^xmp_(.+)_namespace$"; const char *xmp_tag_str = "^xmp_(.+)_(.+)$"; const char *key = NULL; static int regflags = REG_ICASE | REG_EXTENDED; /* XMP object and file pointers */ XmpPtr xmp; XmpFilePtr f; /* Force the hash table to empty */ hash_ns.numitems = 0; /* Prepare XMP library */ xmp_init(); f = xmp_files_open_new(filename, XMP_OPEN_FORUPDATE); if ( ! f ) { msSetError( MS_MISCERR, "Unable to open temporary file '%s' to write XMP info", "msXmpWrite()", filename ); return MS_FAILURE; } /* Create a new XMP structure if the file doesn't already have one */ xmp = xmp_files_get_new_xmp(f); if ( xmp == NULL ) xmp = xmp_new_empty(); /* Check we can write to the file */ if ( ! xmp_files_can_put_xmp(f, xmp) ) { msSetError( MS_MISCERR, "Unable to write XMP information to '%s'", "msXmpWrite()", filename ); return MS_FAILURE; } /* Compile our "xmp_*_namespace" regex */ if ( regcomp(&xmp_regex, xmp_ns_str, regflags) ) { msSetError( MS_MISCERR, "Unable compile regex '%s'", "msXmpWrite()", xmp_ns_str ); return MS_FAILURE; } /* Check all the keys for "xmp_*_namespace" pattern */ initHashTable(&hash_ns); key = msFirstKeyFromHashTable(&hash_metadata); /* No first key? No license info. We shouldn't get here. */ if ( ! key ) return MS_SUCCESS; do { /* Our regex has one match slot */ regmatch_t matches[2]; /* Found a custom namespace entry! Store it for later. */ if ( 0 == regexec(&xmp_regex, key, 2, matches, 0) ) { size_t ns_size = 0; char *ns_name = NULL; const char *ns_uri; /* Copy in the namespace name */ ns_size = matches[1].rm_eo - matches[1].rm_so; ns_name = msSmallMalloc(ns_size + 1); memcpy(ns_name, key + matches[1].rm_so, ns_size); ns_name[ns_size] = 0; /* null terminate */ /* Copy in the namespace uri */ ns_uri = msLookupHashTable(&hash_metadata, key); msInsertHashTable(&hash_ns, ns_name, ns_uri); xmp_register_namespace(ns_uri, ns_name, NULL); msFree(ns_name); } } while( (key = msNextKeyFromHashTable(&hash_metadata, key)) ); /* Clean up regex */ regfree(&xmp_regex); /* Compile our "xmp_*_*" regex */ if ( regcomp(&xmp_regex, xmp_tag_str, regflags) ) { msFreeHashItems(&hash_ns); msSetError( MS_MISCERR, "Unable compile regex '%s'", "msXmpWrite()", xmp_tag_str ); return MS_FAILURE; } /* Check all the keys for "xmp_*_*" pattern */ key = msFirstKeyFromHashTable(&hash_metadata); do { /* Our regex has two match slots */ regmatch_t matches[3]; /* Found a namespace entry! Write it into XMP. */ if ( 0 == regexec(&xmp_regex, key, 3, matches, 0) ) { /* Get the namespace and tag name */ size_t ns_name_size = matches[1].rm_eo - matches[1].rm_so; size_t ns_tag_size = matches[2].rm_eo - matches[2].rm_so; char *ns_name = msSmallMalloc(ns_name_size + 1); char *ns_tag = msSmallMalloc(ns_tag_size + 1); const char *ns_uri = NULL; memcpy(ns_name, key + matches[1].rm_so, ns_name_size); memcpy(ns_tag, key + matches[2].rm_so, ns_tag_size); ns_name[ns_name_size] = 0; /* null terminate */ ns_tag[ns_tag_size] = 0; /* null terminate */ if ( strcmp(ns_tag,"namespace") == 0 ) { msFree(ns_name); msFree(ns_tag); continue; } /* If this is a default name space?... */ if ( (ns_uri = msXmpUri(ns_name)) ) { xmp_register_namespace(ns_uri, ns_name, NULL); xmp_set_property(xmp, ns_uri, ns_tag, msLookupHashTable(&hash_metadata, key), 0); } /* Or maybe it's a custom one?... */ else if ( (ns_uri = msLookupHashTable(&hash_ns, ns_name)) ) { xmp_set_property(xmp, ns_uri, ns_tag, msLookupHashTable(&hash_metadata, key), 0); } /* Or perhaps we're screwed. */ else { msSetError( MS_MISCERR, "Unable to identify XMP namespace '%s' in metadata key '%s'", "msXmpWrite()", ns_name, key ); msFreeHashItems(&hash_ns); msFree(ns_name); msFree(ns_tag); return MS_FAILURE; } msFree(ns_name); msFree(ns_tag); } } while( (key = msNextKeyFromHashTable(&hash_metadata, key)) ); /* Clean up regex */ regfree(&xmp_regex); /* Write out the XMP */ if ( !xmp_files_put_xmp(f, xmp) ) { msFreeHashItems(&hash_ns); msSetError( MS_MISCERR, "Unable to execute '%s' on pointer %p", "msXmpWrite()", "xmp_files_put_xmp", f ); return MS_FAILURE; } /* Write out the file and flush */ if ( !xmp_files_close(f, XMP_CLOSE_SAFEUPDATE) ) { msFreeHashItems(&hash_ns); msSetError( MS_MISCERR, "Unable to execute '%s' on pointer %p", "msXmpWrite()", "xmp_files_close", f ); return MS_FAILURE; } msFreeHashItems(&hash_ns); xmp_free(xmp); xmp_terminate(); return MS_SUCCESS; #else return MS_FAILURE; #endif }
char *msAlignText(mapObj *map, labelObj *label, char *text) { double spacewidth=0.0; /*size of a single space, in fractional pixels*/ int numlines; char **textlines,*newtext,*newtextptr; int *textlinelengths,*numspacesforpadding; int numspacestoadd,maxlinelength,i; rectObj label_rect; if(!msCountChars(text,'\n')) return text; /*only one line*/ /*split text into individual lines * TODO: check if splitting on \n is utf8 safe*/ textlines = msStringSplit(text,'\n',&numlines); /* * label->space_size_10 contains a cache for the horizontal size of a single * 'space' character, at size 10 for the current label * FIXME: in case of attribute binding for the FONT of the label, this cache will * be wrong for labels where the attributed font is different than the first * computed font. This shouldn't happen too often, and hopefully the size of a * space character shouldn't vary too much between different fonts*/ if(label->space_size_10 == 0.0) { /*if the cache hasn't been initialized yet, or with pixmap fonts*/ /* compute the size of 16 adjacent spaces. we can't do this for just one space, * as the labelSize computing functions return integer bounding boxes. we assume * that the integer rounding for such a number of spaces will be negligeable * compared to the actual size of thoses spaces */ if(msGetLabelSize(map,label,". .",10.0,&label_rect,NULL) != MS_SUCCESS) { /*error computing label size, we can't continue*/ /*free the previously allocated split text*/ while(numlines--) free(textlines[numlines]); free(textlines); return text; } /* this is the size of a single space character. for truetype fonts, * it's the size of a 10pt space. For pixmap fonts, it's the size * for the current label */ spacewidth = (label_rect.maxx-label_rect.minx)/16.0; if(label->type == MS_TRUETYPE) { label->space_size_10=spacewidth; /*cache the computed size*/ /*size of a space for current label size*/ spacewidth = spacewidth * (double)label->size/10.0; } } else { spacewidth = label->space_size_10 * (double)label->size/10.0; } spacewidth = MS_MAX(1,spacewidth); /*length in pixels of each line*/ textlinelengths = (int*)msSmallMalloc(numlines*sizeof(int)); /*number of spaces that need to be added to each line*/ numspacesforpadding = (int*)msSmallMalloc(numlines*sizeof(int)); /*total number of spaces that need to be added*/ numspacestoadd=0; /*length in pixels of the longest line*/ maxlinelength=0; for(i=0; i<numlines; i++) { if(MS_SUCCESS != msGetLabelSize(map,label,textlines[i],label->size, &label_rect,NULL)) { msFreeCharArray(textlines,numlines); msFree(textlinelengths); msFree(numspacesforpadding); return text; } textlinelengths[i] = label_rect.maxx-label_rect.minx; if(maxlinelength<textlinelengths[i]) maxlinelength=textlinelengths[i]; } for(i=0; i<numlines; i++) { /* number of spaces to add so the current line is * as long as the longest line */ double nfracspaces = (maxlinelength - textlinelengths[i])/spacewidth; if(label->align == MS_ALIGN_CENTER) { numspacesforpadding[i]=MS_NINT(nfracspaces/2.0); } else { if(label->align == MS_ALIGN_RIGHT) { numspacesforpadding[i]=MS_NINT(nfracspaces); } } numspacestoadd+=numspacesforpadding[i]; } /*allocate new text with room for the additional spaces needed*/ newtext = (char*)msSmallMalloc(strlen(text)+1+numspacestoadd); newtextptr=newtext; for(i=0; i<numlines; i++) { int j; /*padd beginning of line with needed spaces*/ for(j=0; j<numspacesforpadding[i]; j++) { *(newtextptr++)=' '; } /*copy original line*/ strcpy(newtextptr,textlines[i]); /*place pointer at the char right after the current line*/ newtextptr+=strlen(textlines[i])+1; if(i!=numlines-1) { /*put the \n back in (was taken away by msStringSplit)*/ *(newtextptr-1)='\n'; } } /*free the original text*/ free(text); for(i=0; i<numlines; i++) { free(textlines[i]); } free(textlines); free(textlinelengths); free(numspacesforpadding); /*return the aligned text. note that the terminating \0 was added by the last * call to strcpy */ return newtext; }
int msAddLabelGroup(mapObj *map, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize) { int i, priority, numactivelabels=0; labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; layerPtr = (GET_LAYER(map, layerindex)); /* set up a few pointers for clarity */ classPtr = GET_LAYER(map, layerindex)->class[classindex]; if(classPtr->numlabels == 0) return MS_SUCCESS; /* not an error just nothing to do */ for(i=0; i<classPtr->numlabels; i++) { if(classPtr->labels[i]->status == MS_ON) { numactivelabels++; } } if(numactivelabels == 0) return MS_SUCCESS; /* if the number of labels is 1 then call msAddLabel() accordingly */ if(numactivelabels == 1) { for(i=0; i<classPtr->numlabels; i++) { if(classPtr->labels[i]->status == MS_ON) return msAddLabel(map, classPtr->labels[i], layerindex, classindex, shape, point, NULL, featuresize); } } if (layerPtr->type == MS_LAYER_ANNOTATION && (classPtr->numlabels > 1 || classPtr->leader.maxdistance)) { msSetError(MS_MISCERR, "Multiple Labels and/or LEADERs are not supported with annotation layers", "msAddLabelGroup()"); return MS_FAILURE; } /* check that the label intersects the layer mask */ if(layerPtr->mask) { int maskLayerIdx = msGetLayerIndex(map,layerPtr->mask); layerObj *maskLayer = GET_LAYER(map,maskLayerIdx); unsigned char *alphapixptr; if(maskLayer->maskimage && MS_IMAGE_RENDERER(maskLayer->maskimage)->supports_pixel_buffer) { rasterBufferObj rb; int x,y; memset(&rb,0,sizeof(rasterBufferObj)); MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,&rb); x = MS_NINT(point->x); y = MS_NINT(point->y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { #ifdef USE_GD if(rb.type == MS_BUFFER_BYTE_RGBA) { alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } } else { if(!gdImageGetPixel(rb.data.gd_img,x,y)) return MS_SUCCESS; } #else assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } #endif } } else { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msAddLabelGroup()", layerPtr->name); return (MS_FAILURE); } } /* Validate label priority value and get ref on label cache for it */ priority = classPtr->labels[0]->priority; /* take priority from the first label */ if (priority < 1) priority = 1; else if (priority > MS_MAX_LABEL_PRIORITY) priority = MS_MAX_LABEL_PRIORITY; cacheslot = &(map->labelcache.slots[priority-1]); if(cacheslot->numlabels == cacheslot->cachesize) { /* just add it to the end */ cacheslot->labels = (labelCacheMemberObj *) realloc(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->cachesize += MS_LABELCACHEINCREMENT; } cachePtr = &(cacheslot->labels[cacheslot->numlabels]); cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */ cachePtr->classindex = classindex; if(shape) { cachePtr->shapetype = shape->type; } else { cachePtr->shapetype = MS_SHAPE_POINT; } cachePtr->point = *point; /* the actual label point */ cachePtr->labelpath = NULL; cachePtr->leaderline = NULL; cachePtr->leaderbbox = NULL; // cachePtr->text = msStrdup(string); /* the actual text */ /* TODO: perhaps we can get rid of this next section and just store a marker size? Why do we cache the styles for a point layer? */ /* copy the styles (only if there is an accompanying marker) * We cannot simply keep refs because the rendering code might alters some members of the style objects */ cachePtr->styles = NULL; cachePtr->numstyles = 0; if(layerPtr->type == MS_LAYER_ANNOTATION && classPtr->numstyles > 0) { cachePtr->numstyles = classPtr->numstyles; cachePtr->styles = (styleObj *) msSmallMalloc(sizeof(styleObj)*classPtr->numstyles); if (classPtr->numstyles > 0) { for(i=0; i<classPtr->numstyles; i++) { initStyle(&(cachePtr->styles[i])); msCopyStyle(&(cachePtr->styles[i]), classPtr->styles[i]); } } } /* ** copy the labels (we are guaranteed to have more than one): ** we cannot simply keep refs because the rendering code alters some members of the style objects */ cachePtr->numlabels = 0; cachePtr->labels = (labelObj *) msSmallMalloc(sizeof(labelObj)*numactivelabels); for(i=0; i<classPtr->numlabels; i++) { if(classPtr->labels[i]->status == MS_OFF) continue; initLabel(&(cachePtr->labels[cachePtr->numlabels])); msCopyLabel(&(cachePtr->labels[cachePtr->numlabels]), classPtr->labels[i]); cachePtr->numlabels++; } assert(cachePtr->numlabels == numactivelabels); cachePtr->markerid = -1; cachePtr->featuresize = featuresize; //cachePtr->poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); //msInitShape(cachePtr->poly); cachePtr->poly = NULL; cachePtr->status = MS_FALSE; if(layerPtr->type == MS_LAYER_POINT && classPtr->numstyles > 0) { /* cache the marker placement, it's already on the map */ /* TO DO: at the moment only checks the bottom style, perhaps should check all of them */ /* #2347: after RFC-24 classPtr->styles could be NULL so we check it */ rectObj rect; double w, h; if(msGetMarkerSize(&map->symbolset, classPtr->styles[0], &w, &h, layerPtr->scalefactor) != MS_SUCCESS) return(MS_FAILURE); if(cacheslot->nummarkers == cacheslot->markercachesize) { /* just add it to the end */ cacheslot->markers = (markerCacheMemberObj *) realloc(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->markercachesize+=MS_LABELCACHEINCREMENT; } i = cacheslot->nummarkers; cacheslot->markers[i].poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(cacheslot->markers[i].poly); rect.minx = (point->x - .5 * w); rect.miny = (point->y - .5 * h); rect.maxx = rect.minx + (w-1); rect.maxy = rect.miny + (h-1); msRectToPolygon(rect, cacheslot->markers[i].poly); cacheslot->markers[i].id = cacheslot->numlabels; cachePtr->markerid = i; cacheslot->nummarkers++; } cacheslot->numlabels++; /* Maintain main labelCacheObj.numlabels only for backwards compatibility */ map->labelcache.numlabels++; return(MS_SUCCESS); }
int msWriteTree(treeObj *tree, char *filename, int B_order) { char signature[3] = "SQT"; char version = 1; char reserved[3] = {0,0,0}; SHPTreeHandle disktree; int i; char mtBigEndian; char pabyBuf[32]; char *pszBasename, *pszFullname; disktree = (SHPTreeHandle) malloc(sizeof(SHPTreeInfo)); MS_CHECK_ALLOC(disktree, sizeof(SHPTreeInfo), MS_FALSE); /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(filename)+5); strcpy( pszBasename, filename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, MS_INDEX_EXTENSION); disktree->fp = fopen(pszFullname, "wb"); msFree(pszBasename); /* not needed */ msFree(pszFullname); if(!disktree->fp) { msFree(disktree); msSetError(MS_IOERR, NULL, "msWriteTree()"); return(MS_FALSE); } /* for efficiency, trim the tree */ msTreeTrim(tree); /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) mtBigEndian = MS_FALSE; else mtBigEndian = MS_TRUE; if( !(mtBigEndian ^ ( B_order == MS_LSB_ORDER || B_order == MS_NEW_LSB_ORDER )) ) disktree->needswap = 1; else disktree->needswap = 0; if( B_order == MS_NATIVE_ORDER ) disktree->needswap = 0; /* write the header */ if ( B_order > 0 ) { memcpy( pabyBuf, &signature, 3 ); memcpy (&disktree->signature, &signature, 3); pabyBuf[3] = B_order; memcpy( pabyBuf+4, &version, 1); memcpy( pabyBuf+5, &reserved, 3); memcpy( &disktree->version, &version, 1); memcpy( &disktree->flags, &reserved, 3); fwrite( pabyBuf, 8, 1, disktree->fp ); } memcpy( pabyBuf, &tree->numshapes, 4 ); if( disktree->needswap ) SwapWord( 4, pabyBuf ); memcpy( pabyBuf+4, &tree->maxdepth, 4 ); if( disktree->needswap ) SwapWord( 4, pabyBuf+4 ); i = fwrite( pabyBuf, 8, 1, disktree->fp ); if( !i ) { fprintf (stderr, "unable to write to index file ... exiting \n"); msSHPDiskTreeClose( disktree ); return (MS_FALSE); } writeTreeNode(disktree, tree->root); msSHPDiskTreeClose( disktree ); return(MS_TRUE); }
int msAddLabel(mapObj *map, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, labelPathObj *labelpath, double featuresize) { int i; labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; if(!label) return(MS_FAILURE); // RFC 77 TODO: set a proper message if(label->status == MS_OFF) return(MS_SUCCESS); /* not an error */ if(!label->annotext) { /* check if we have a labelpnt style */ for(i=0; i<label->numstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) break; } if(i==label->numstyles) { /* label has no text or marker symbols */ return MS_SUCCESS; } } layerPtr = (GET_LAYER(map, layerindex)); /* set up a few pointers for clarity */ classPtr = GET_LAYER(map, layerindex)->class[classindex]; if(classPtr->leader.maxdistance) { if (layerPtr->type == MS_LAYER_ANNOTATION) { msSetError(MS_MISCERR, "LEADERs are not supported on annotation layers", "msAddLabel()"); return MS_FAILURE; } if(labelpath) { msSetError(MS_MISCERR, "LEADERs are not supported on ANGLE FOLLOW labels", "msAddLabel()"); return MS_FAILURE; } } /* check that the label intersects the layer mask */ if (layerPtr->mask) { int maskLayerIdx = msGetLayerIndex(map, layerPtr->mask); layerObj *maskLayer = GET_LAYER(map, maskLayerIdx); unsigned char *alphapixptr; if (maskLayer->maskimage && MS_IMAGE_RENDERER(maskLayer->maskimage)->supports_pixel_buffer) { rasterBufferObj rb; memset(&rb, 0, sizeof (rasterBufferObj)); MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage, &rb); if (point) { int x = MS_NINT(point->x); int y = MS_NINT(point->y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { #ifdef USE_GD if(rb.type == MS_BUFFER_BYTE_RGBA) { alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } } else { if(!gdImageGetPixel(rb.data.gd_img,x,y)) { return MS_SUCCESS; } } #else assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } #endif } } else if (labelpath) { int i = 0; for (i = 0; i < labelpath->path.numpoints; i++) { int x = MS_NINT(labelpath->path.point[i].x); int y = MS_NINT(labelpath->path.point[i].y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { #ifdef USE_GD if (rb.type == MS_BUFFER_BYTE_RGBA) { alphapixptr = rb.data.rgba.a + rb.data.rgba.row_step * y + rb.data.rgba.pixel_step*x; if (!*alphapixptr) { /* label point does not intersect mask */ msFreeLabelPathObj(labelpath); return MS_SUCCESS; } } else { if (!gdImageGetPixel(rb.data.gd_img, x, y)) { msFreeLabelPathObj(labelpath); return MS_SUCCESS; } } #else assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a + rb.data.rgba.row_step * y + rb.data.rgba.pixel_step*x; if (!*alphapixptr) { /* label point does not intersect mask */ msFreeLabelPathObj(labelpath); return MS_SUCCESS; } #endif } } } } else { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msAddLabel()", layerPtr->name); return (MS_FAILURE); } } /* Validate label priority value and get ref on label cache for it */ if (label->priority < 1) label->priority = 1; else if (label->priority > MS_MAX_LABEL_PRIORITY) label->priority = MS_MAX_LABEL_PRIORITY; cacheslot = &(map->labelcache.slots[label->priority-1]); if(cacheslot->numlabels == cacheslot->cachesize) { /* just add it to the end */ cacheslot->labels = (labelCacheMemberObj *) realloc(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->cachesize += MS_LABELCACHEINCREMENT; } cachePtr = &(cacheslot->labels[cacheslot->numlabels]); cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */ cachePtr->classindex = classindex; if(shape) { cachePtr->shapetype = shape->type; } else { cachePtr->shapetype = MS_SHAPE_POINT; } cachePtr->leaderline = NULL; cachePtr->leaderbbox = NULL; /* Store the label point or the label path (Bug #1620) */ if ( point ) { cachePtr->point = *point; /* the actual label point */ cachePtr->labelpath = NULL; } else { assert(labelpath); cachePtr->labelpath = labelpath; /* Use the middle point of the labelpath for mindistance calculations */ cachePtr->point = labelpath->path.point[labelpath->path.numpoints / 2]; } /* TODO: perhaps we can get rid of this next section and just store a marker size? Why do we cache the styles for a point layer? */ /* copy the styles (only if there is an accompanying marker) * We cannot simply keeep refs because the rendering code alters some members of the style objects */ cachePtr->styles = NULL; cachePtr->numstyles = 0; if(layerPtr->type == MS_LAYER_ANNOTATION && classPtr->numstyles > 0) { cachePtr->numstyles = classPtr->numstyles; cachePtr->styles = (styleObj *) msSmallMalloc(sizeof(styleObj)*classPtr->numstyles); if (classPtr->numstyles > 0) { for(i=0; i<classPtr->numstyles; i++) { initStyle(&(cachePtr->styles[i])); msCopyStyle(&(cachePtr->styles[i]), classPtr->styles[i]); } } } /* copy the label */ cachePtr->numlabels = 1; cachePtr->labels = (labelObj *) msSmallMalloc(sizeof(labelObj)); initLabel(cachePtr->labels); msCopyLabel(cachePtr->labels, label); cachePtr->markerid = -1; cachePtr->featuresize = featuresize; //cachePtr->poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); //msInitShape(cachePtr->poly); cachePtr->poly = NULL; cachePtr->status = MS_FALSE; if(layerPtr->type == MS_LAYER_POINT && classPtr->numstyles > 0) { /* cache the marker placement, it's already on the map */ rectObj rect; double w, h; if(cacheslot->nummarkers == cacheslot->markercachesize) { /* just add it to the end */ cacheslot->markers = (markerCacheMemberObj *) realloc(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->markercachesize+=MS_LABELCACHEINCREMENT; } i = cacheslot->nummarkers; cacheslot->markers[i].poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(cacheslot->markers[i].poly); /* TO DO: at the moment only checks the bottom style, perhaps should check all of them */ /* #2347: after RFC-24 classPtr->styles could be NULL so we check it */ if(classPtr->styles != NULL) { if(msGetMarkerSize(&map->symbolset, classPtr->styles[0], &w, &h, layerPtr->scalefactor) != MS_SUCCESS) return(MS_FAILURE); rect.minx = point->x - .5 * w; rect.miny = point->y - .5 * h; rect.maxx = rect.minx + (w-1); rect.maxy = rect.miny + (h-1); msRectToPolygon(rect, cacheslot->markers[i].poly); cacheslot->markers[i].id = cacheslot->numlabels; cachePtr->markerid = i; cacheslot->nummarkers++; } } cacheslot->numlabels++; /* Maintain main labelCacheObj.numlabels only for backwards compatibility */ map->labelcache.numlabels++; return(MS_SUCCESS); }
int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; imageObj *image_tmp; outputFormatObj *outputformat = NULL; mapObj *map_tmp; double map_cellsize; unsigned int spacing; int width, height, u_src_off, v_src_off, i, x, y; char **alteredProcessing = NULL, *saved_layer_mask; char **savedProcessing = NULL; if (layer->debug) msDebug("Entering msUVRASTERLayerWhichShapes().\n"); if( uvlinfo == NULL ) return MS_FAILURE; /* QUERY NOT SUPPORTED YET */ if (isQuery == MS_TRUE) { msSetError( MS_MISCERR, "Query is not supported for UV layer.", "msUVRASTERLayerWhichShapes()" ); return MS_FAILURE; } if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { msSetError( MS_MISCERR, "BANDS processing option is required for UV layer. You have to specified 2 bands.", "msUVRASTERLayerWhichShapes()" ); return MS_FAILURE; } /* ** Allocate mapObj structure */ map_tmp = (mapObj *)msSmallCalloc(sizeof(mapObj),1); if(initMap(map_tmp) == -1) { /* initialize this map */ msFree(map_tmp); return(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* Determine desired spacing. Default to 32 if not otherwise set */ /* -------------------------------------------------------------------- */ spacing = 32; if( CSLFetchNameValue( layer->processing, "UV_SPACING" ) != NULL ) { spacing = atoi(CSLFetchNameValue( layer->processing, "UV_SPACING" )); } width = (int)ceil(layer->map->width/spacing); height = (int)ceil(layer->map->height/spacing); map_cellsize = MS_MAX(MS_CELLSIZE(rect.minx, rect.maxx,layer->map->width), MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height)); map_tmp->cellsize = map_cellsize*spacing; if (layer->debug) msDebug("msUVRASTERLayerWhichShapes(): width: %d, height: %d, cellsize: %g\n", width, height, map_tmp->cellsize); /* Initialize our dummy map */ MS_INIT_COLOR(map_tmp->imagecolor, 255,255,255,255); map_tmp->resolution = layer->map->resolution; map_tmp->defresolution = layer->map->defresolution; outputformat = (outputFormatObj *) msSmallCalloc(1,sizeof(outputFormatObj)); outputformat->bands = uvlinfo->band_count = 2; outputformat->name = NULL; outputformat->driver = NULL; outputformat->refcount = 0; outputformat->vtable = NULL; outputformat->device = NULL; outputformat->renderer = MS_RENDER_WITH_RAWDATA; outputformat->imagemode = MS_IMAGEMODE_FLOAT32; msAppendOutputFormat(map_tmp, outputformat); msCopyHashTable(&map_tmp->configoptions, &layer->map->configoptions); map_tmp->mappath = msStrdup(layer->map->mappath); map_tmp->shapepath = msStrdup(layer->map->shapepath); map_tmp->extent.minx = rect.minx-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.miny = rect.miny-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.maxx = map_tmp->extent.minx+((width-1)*map_tmp->cellsize); map_tmp->extent.maxy = map_tmp->extent.miny+((height-1)*map_tmp->cellsize); map_tmp->gt.rotation_angle = 0.0; msCopyProjection(&map_tmp->projection, &layer->projection); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): extent: %g %g %g %g\n", map_tmp->extent.minx, map_tmp->extent.miny, map_tmp->extent.maxx, map_tmp->extent.maxy); /* important to use that function, to compute map geotransform, used by the resampling*/ msMapSetSize(map_tmp, width, height); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): geotransform: %g %g %g %g %g %g\n", map_tmp->gt.geotransform[0], map_tmp->gt.geotransform[1], map_tmp->gt.geotransform[2], map_tmp->gt.geotransform[3], map_tmp->gt.geotransform[4], map_tmp->gt.geotransform[5]); uvlinfo->extent = map_tmp->extent; image_tmp = msImageCreate(width, height, map_tmp->outputformatlist[0], NULL, NULL, map_tmp->resolution, map_tmp->defresolution, &(map_tmp->imagecolor)); /* Default set to AVERAGE resampling */ if( CSLFetchNameValue( layer->processing, "RESAMPLE" ) == NULL ) { alteredProcessing = CSLDuplicate( layer->processing ); alteredProcessing = CSLSetNameValue( alteredProcessing, "RESAMPLE", "AVERAGE"); savedProcessing = layer->processing; layer->processing = alteredProcessing; } /* disable masking at this level: we don't want to apply the mask at the raster level, * it will be applied with the correct cellsize and image size in the vector rendering * phase. */ saved_layer_mask = layer->mask; layer->mask = NULL; if (msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL ) == MS_FAILURE) { msSetError(MS_MISCERR, "Unable to draw raster data.", "msUVRASTERLayerWhichShapes()"); layer->mask = saved_layer_mask; return MS_FAILURE; } /* restore layer mask */ layer->mask = saved_layer_mask; /* restore the saved processing */ if (alteredProcessing != NULL) { layer->processing = savedProcessing; CSLDestroy(alteredProcessing); } /* free old query arrays */ if (uvlinfo->u) { for (i=0; i<uvlinfo->width; ++i) { free(uvlinfo->u[i]); } free(uvlinfo->u); } if (uvlinfo->v) { for (i=0; i<uvlinfo->height; ++i) { free(uvlinfo->v[i]); } free(uvlinfo->v); } /* Update our uv layer structure */ uvlinfo->width = width; uvlinfo->height = height; uvlinfo->query_results = width*height; uvlinfo->u = (float **)msSmallMalloc(sizeof(float *)*width); uvlinfo->v = (float **)msSmallMalloc(sizeof(float *)*width); for (x = 0; x < width; ++x) { uvlinfo->u[x] = (float *)msSmallMalloc(height * sizeof(float)); uvlinfo->v[x] = (float *)msSmallMalloc(height * sizeof(float)); for (y = 0; y < height; ++y) { u_src_off = v_src_off = x + y * width; v_src_off += width*height; uvlinfo->u[x][y] = image_tmp->img.raw_float[u_src_off]; uvlinfo->v[x][y] = image_tmp->img.raw_float[v_src_off]; /* null vector? update the number of results */ if (uvlinfo->u[x][y] == 0 && uvlinfo->v[x][y] == 0) --uvlinfo->query_results; } } msFreeImage(image_tmp); /* we do not need the imageObj anymore */ msFreeMap(map_tmp); uvlinfo->next_shape = 0; return MS_SUCCESS; }
char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; int nTokens = 0, i=0, bString=0; char **tokens = NULL; const char *pszAttribute=NULL; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode->pszValue) { pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if (pszAttribute) { tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); if (tokens && nTokens > 0) { for (i=0; i<nTokens; i++) { char *pszTmp = NULL; int bufferSize = 0; if (i == 0) { if(FLTIsNumeric(tokens[0]) == MS_FALSE) bString = 1; } if (bString) { bufferSize = 11+strlen(tokens[i])+strlen(pszAttribute)+1; pszTmp = (char *)msSmallMalloc(bufferSize); snprintf(pszTmp, bufferSize, "(\"[%s]\" ==\"%s\")" , pszAttribute, tokens[i]); } else { bufferSize = 8+strlen(tokens[i])+strlen(pszAttribute)+1; pszTmp = (char *)msSmallMalloc(bufferSize); snprintf(pszTmp, bufferSize, "([%s] == %s)" , pszAttribute, tokens[i]); } if (pszExpression != NULL) pszExpression = msStringConcatenate(pszExpression, " OR "); else pszExpression = msStringConcatenate(pszExpression, "("); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); } msFreeCharArray(tokens, nTokens); } } /*opening and closing brackets are needed for mapserver expressions*/ if (pszExpression) pszExpression = msStringConcatenate(pszExpression, ")"); } #endif return pszExpression; }