int msWFSException11(mapObj *map, const char *locator,
                     const char *exceptionCode, const char *version)
{
  int size = 0;
  char *errorString     = NULL;
  char *errorMessage    = NULL;
  char *schemasLocation = NULL;
  const char *encoding;

  xmlDocPtr  psDoc      = NULL;
  xmlNodePtr psRootNode = NULL;
  xmlNsPtr   psNsOws    = NULL;
  xmlChar *buffer       = NULL;

  if (version == NULL)
    version = "1.1.0";

  psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");

  encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");

  errorString = msGetErrorString("\n");
  errorMessage = msEncodeHTMLEntities(errorString);
  schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));

  psDoc = xmlNewDoc(BAD_CAST "1.0");

  psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_0_0, schemasLocation, version, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage);

  xmlDocSetRootElement(psDoc, psRootNode);

  xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");

  if (encoding)
    msIO_setHeader("Content-Type","text/xml; charset=%s", encoding);
  else
    msIO_setHeader("Content-Type","text/xml");
  msIO_sendHeaders();

  xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);

  msIO_printf("%s", buffer);

  /*free buffer and the document */
  free(errorString);
  free(errorMessage);
  free(schemasLocation);
  xmlFree(buffer);
  xmlFreeDoc(psDoc);
  xmlFreeNs(psNsOws);

  /* clear error since we have already reported it */
  msResetErrorList();

  return MS_FAILURE;
}
Beispiel #2
0
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;
}
Beispiel #3
0
int loadParams(cgiRequestObj *request,
               char* (*getenv2)(const char*, void* thread_context),
               char *raw_post_data,
               ms_uint32 raw_post_data_length,
               void* thread_context)
{
  register int x,m=0;
  char *s, *queryString = NULL, *httpCookie = NULL;
  int debuglevel;
  int maxParams = MS_DEFAULT_CGI_PARAMS;

  if (getenv2==NULL)
    getenv2 = &msGetEnv;

  if(getenv2("REQUEST_METHOD", thread_context)==NULL) {
    msIO_printf("This script can only be used to decode form results and \n");
    msIO_printf("should be initiated as a CGI process via a httpd server.\n");
    return -1;
  }

  debuglevel = (int)msGetGlobalDebugLevel();

  if(strcmp(getenv2("REQUEST_METHOD", thread_context),"POST") == 0) { /* we've got a post from a form */
    char *post_data;
    int data_len;
    request->type = MS_POST_REQUEST;

    s = getenv2("CONTENT_TYPE", thread_context);
    if (s != NULL)
      request->contenttype = msStrdup(s);
    /* we've to set default Content-Type which is
     * application/octet-stream according to
     * W3 RFC 2626 section 7.2.1 */
    else request->contenttype = msStrdup("application/octet-stream");

    if (raw_post_data) {
      post_data = msStrdup(raw_post_data);
      data_len = raw_post_data_length;
    } else {
      if(MS_SUCCESS != readPostBody( request, &post_data ))
        return -1;
      data_len = strlen(post_data);
    }

    /* if the content_type is application/x-www-form-urlencoded,
       we have to parse it like the QUERY_STRING variable */
    if(strncmp(request->contenttype, "application/x-www-form-urlencoded", strlen("application/x-www-form-urlencoded")) == 0) {
      while( data_len > 0 && isspace(post_data[data_len-1]) )
        post_data[--data_len] = '\0';

      while( post_data[0] ) {
        if(m >= maxParams) {
          maxParams *= 2;
          request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams);
          request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams);
        }
        request->ParamValues[m] = makeword(post_data,'&');
        plustospace(request->ParamValues[m]);
        unescape_url(request->ParamValues[m]);
        request->ParamNames[m] = makeword(request->ParamValues[m],'=');
        m++;
      }
      free( post_data );
    } else
      request->postrequest = post_data;

    /* check the QUERY_STRING even in the post request since it can contain
       information. Eg a wfs request with  */
    s = getenv2("QUERY_STRING", thread_context);
    if(s) {
      if (debuglevel >= MS_DEBUGLEVEL_DEBUG)
        msDebug("loadParams() QUERY_STRING: %s\n", s);

      queryString = msStrdup(s);
      for(x=0; queryString[0] != '\0'; x++) {
        if(m >= maxParams) {
          maxParams *= 2;
          request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams);
          request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams);
        }
        request->ParamValues[m] = makeword(queryString,'&');
        plustospace(request->ParamValues[m]);
        unescape_url(request->ParamValues[m]);
        request->ParamNames[m] = makeword(request->ParamValues[m],'=');
        m++;
      }
    }
  } else {
    if(strcmp(getenv2("REQUEST_METHOD", thread_context),"GET") == 0) { /* we've got a get request */
      request->type = MS_GET_REQUEST;

      s = getenv2("QUERY_STRING", thread_context);
      if(s == NULL) {
        msIO_setHeader("Content-Type","text/html");
        msIO_sendHeaders();
        msIO_printf("No query information to decode. QUERY_STRING not set.\n");
        return -1;
      }

      if (debuglevel >= MS_DEBUGLEVEL_DEBUG)
        msDebug("loadParams() QUERY_STRING: %s\n", s);

      if(strlen(s)==0) {
        msIO_setHeader("Content-Type","text/html");
        msIO_sendHeaders();
        msIO_printf("No query information to decode. QUERY_STRING is set, but empty.\n");
        return -1;
      }

      /* don't modify the string returned by getenv2 */
      queryString = msStrdup(s);
      for(x=0; queryString[0] != '\0'; x++) {
        if(m >= maxParams) {
          maxParams *= 2;
          request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams);
          request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams);
        }
        request->ParamValues[m] = makeword(queryString,'&');
        plustospace(request->ParamValues[m]);
        unescape_url(request->ParamValues[m]);
        request->ParamNames[m] = makeword(request->ParamValues[m],'=');
        m++;
      }
    } else {
      msIO_setHeader("Content-Type","text/html");
      msIO_sendHeaders();
      msIO_printf("This script should be referenced with a METHOD of GET or METHOD of POST.\n");
      return -1;
    }
  }

  /* check for any available cookies */
  s = getenv2("HTTP_COOKIE", thread_context);
  if(s != NULL) {
    httpCookie = msStrdup(s);
    request->httpcookiedata = msStrdup(s);
    for(x=0; httpCookie[0] != '\0'; x++) {
      if(m >= maxParams) {
        maxParams *= 2;
        request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams);
        request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams);
      }
      request->ParamValues[m] = makeword(httpCookie,';');
      plustospace(request->ParamValues[m]);
      unescape_url(request->ParamValues[m]);
      request->ParamNames[m] = makeword_skip(request->ParamValues[m],'=',' ');
      m++;
    }
  }

  if (queryString)
    free(queryString);
  if (httpCookie)
    free(httpCookie);

  return(m);
}
Beispiel #4
0
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
                           cgiRequestObj *req, owsRequestObj *ows_request)
{
  xmlDocPtr psDoc = NULL;       /* document pointer */
  xmlNodePtr psRootNode, psMainNode, psNode, psFtNode;
  const char *updatesequence=NULL;
  xmlNsPtr psNsOws, psNsXLink, psNsOgc;
  char *schemalocation = NULL;
  char *xsi_schemaLocation = NULL;
  const char *user_namespace_prefix = NULL;
  const char *user_namespace_uri = NULL;
  gmlNamespaceListObj *namespaceList=NULL; /* for external application schema support */

  char *script_url=NULL, *formats_list;
  const char *value = NULL;

  xmlChar *buffer = NULL;
  int size = 0, i;
  msIOContext *context = NULL;

  int ows_version = OWS_1_0_0;
  int ret;

  /* -------------------------------------------------------------------- */
  /*      Handle updatesequence                                           */
  /* -------------------------------------------------------------------- */
  ret = msWFSHandleUpdateSequence(map, params, "msWFSGetCapabilities11()");
  if( ret != MS_SUCCESS )
      return ret;

  /* -------------------------------------------------------------------- */
  /*      Create document.                                                */
  /* -------------------------------------------------------------------- */
  psDoc = xmlNewDoc(BAD_CAST "1.0");

  psRootNode = xmlNewNode(NULL, BAD_CAST "WFS_Capabilities");

  xmlDocSetRootElement(psDoc, psRootNode);

  /* -------------------------------------------------------------------- */
  /*      Name spaces                                                     */
  /* -------------------------------------------------------------------- */
  /*default name space*/
  xmlNewProp(psRootNode, BAD_CAST "xmlns", BAD_CAST "http://www.opengis.net/wfs");

  xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"));
  xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wfs", BAD_CAST "wfs"));

  psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
  psNsXLink = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX);
  xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX);
  xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX );

  value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_uri");
  if(value) user_namespace_uri = value;

  value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix");
  if(value) user_namespace_prefix = value;
  if(user_namespace_prefix != NULL && msIsXMLTagValid(user_namespace_prefix) == MS_FALSE)
    msIO_printf("<!-- WARNING: The value '%s' is not valid XML namespace. -->\n", user_namespace_prefix);
  else
    xmlNewNs(psRootNode, BAD_CAST user_namespace_uri, BAD_CAST user_namespace_prefix);

  /* any additional namespaces */
  namespaceList = msGMLGetNamespaces(&(map->web), "G");
  for(i=0; i<namespaceList->numnamespaces; i++) {
    if(namespaceList->namespaces[i].uri) {
      xmlNewNs(psRootNode, BAD_CAST namespaceList->namespaces[i].uri, BAD_CAST namespaceList->namespaces[i].prefix);
    }
  }
  msGMLFreeNamespaces(namespaceList);
  

  xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->pszVersion );

  updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence");

  if (updatesequence)
    xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence);

  /*schema*/
  schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) );
  xsi_schemaLocation = msStrdup("http://www.opengis.net/wfs");
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " ");
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation);
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/wfs/1.1.0/wfs.xsd");
  xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation);

  /* -------------------------------------------------------------------- */
  /*      Service metadata.                                               */
  /* -------------------------------------------------------------------- */

  xmlAddChild(psRootNode,
                          msOWSCommonServiceIdentification(psNsOws, map, "OGC WFS", params->pszVersion, "FO", NULL));

  /*service provider*/
  xmlAddChild(psRootNode, msOWSCommonServiceProvider(
                            psNsOws, psNsXLink, map, "FO", NULL));

  /*operation metadata */
  if ((script_url=msOWSGetOnlineResource(map, "FO", "onlineresource", req)) == NULL) {
    msSetError(MS_WFSERR, "Server URL not found", "msWFSGetCapabilities11()");
    return msWFSException11(map, "mapserv", MS_OWS_ERROR_NO_APPLICABLE_CODE, params->pszVersion);
  }

  /* -------------------------------------------------------------------- */
  /*      Operations metadata.                                            */
  /* -------------------------------------------------------------------- */
  psMainNode= xmlAddChild(psRootNode,msOWSCommonOperationsMetadata(psNsOws));

  /* -------------------------------------------------------------------- */
  /*      GetCapabilities                                                 */
  /* -------------------------------------------------------------------- */
  psNode = xmlAddChild(psMainNode,
                       msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetCapabilities",
                           OWS_METHOD_GETPOST, script_url));

  xmlAddChild(psMainNode, psNode);
  xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
                ows_version, psNsOws, "Parameter", "service", "WFS"));
  /*accept version*/
  xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
              "Parameter", "AcceptVersions",
              "1.0.0,1.1.0"));
  /*format*/
  xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
              "Parameter", "AcceptFormats",
              "text/xml"));


  /* -------------------------------------------------------------------- */
  /*      DescribeFeatureType                                             */
  /* -------------------------------------------------------------------- */
  if (msOWSRequestIsEnabled(map, NULL, "F", "DescribeFeatureType", MS_TRUE)) {
    psNode = xmlAddChild(psMainNode,
                         msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeFeatureType",
                             OWS_METHOD_GETPOST, script_url));
    xmlAddChild(psMainNode, psNode);

    /*output format*/
    xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
                "Parameter", "outputFormat",
                "XMLSCHEMA,text/xml; subtype=gml/2.1.2,text/xml; subtype=gml/3.1.1"));
  }

  /* -------------------------------------------------------------------- */
  /*      GetFeature                                                      */
  /* -------------------------------------------------------------------- */
  if (msOWSRequestIsEnabled(map, NULL, "F", "GetFeature", MS_TRUE)) {

    psNode = xmlAddChild(psMainNode,
                         msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetFeature",
                             OWS_METHOD_GETPOST, script_url));
    xmlAddChild(psMainNode, psNode);

    xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
                "Parameter", "resultType",
                "results,hits"));

    formats_list = msWFSGetOutputFormatList( map, NULL, OWS_1_1_0 );
    xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
                "Parameter", "outputFormat",
                formats_list));
    msFree( formats_list );

    value = msOWSLookupMetadata(&(map->web.metadata), "FO", "maxfeatures");

    if (value) {
      xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
                  "Constraint", "DefaultMaxFeatures",
                  (char *)value));
    }
  }

  /* -------------------------------------------------------------------- */
  /*      FeatureTypeList                                                 */
  /* -------------------------------------------------------------------- */

  psFtNode = xmlNewNode(NULL, BAD_CAST "FeatureTypeList");
  xmlAddChild(psRootNode, psFtNode);
  psNode = xmlNewChild(psFtNode, NULL, BAD_CAST "Operations", NULL);
  xmlNewChild(psNode, NULL, BAD_CAST "Operation", BAD_CAST "Query");

  for(i=0; i<map->numlayers; i++) {
    layerObj *lp;
    lp = GET_LAYER(map, i);

    if (!msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers))
      continue;

    /* List only vector layers in which DUMP=TRUE */
    if (msWFSIsLayerSupported(lp))
      xmlAddChild(psFtNode, msWFSDumpLayer11(map, lp, psNsOws, OWS_1_1_0, NULL));
  }





  /* -------------------------------------------------------------------- */
  /*      Filter capabilities.                                            */
  /* -------------------------------------------------------------------- */

  psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX);
  xmlAddChild(psRootNode, FLTGetCapabilities(psNsOgc, psNsOgc, MS_FALSE));
  /* -------------------------------------------------------------------- */
  /*      Write out the document.                                         */
  /* -------------------------------------------------------------------- */

  if( msIO_needBinaryStdout() == MS_FAILURE )
    return MS_FAILURE;

  msIO_setHeader("Content-Type","text/xml; charset=UTF-8");
  msIO_sendHeaders();

  context = msIO_getHandler(stdout);

  xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, ("UTF-8"), 1);
  msIO_contextWrite(context, buffer, size);
  xmlFree(buffer);

  /*free buffer and the document */
  /*xmlFree(buffer);*/
  xmlFreeDoc(psDoc);
  xmlFreeNs(psNsOgc);

  free(script_url);
  free(xsi_schemaLocation);
  free(schemalocation);

  xmlCleanupParser();

  return(MS_SUCCESS);
}
Beispiel #5
0
void msWriteErrorImage(mapObj *map, char *filename, int blank) {
    imageObj *img;
    rendererVTableObj *renderer;
    int font_index = 0;
    int width=400, height=300;
    int nMargin =5;
    int nTextLength = 0;
    int nUsableWidth = 0;
    int nMaxCharsPerLine = 0;
    int nLines = 0;
    int i = 0;
    int nStart = 0;
    int nEnd = 0;
    int nLength = 0;
    char **papszLines = NULL;
    int nXPos = 0;
    int nYPos = 0;
    int nWidthTxt = 0;
    outputFormatObj *format = NULL;
    char *errormsg = msGetErrorString("; ");
    fontMetrics *font = NULL;
    char *imagepath = NULL, *imageurl = NULL;
    labelStyleObj ls;
    colorObj labelcolor, labeloutlinecolor, imagecolor, *imagecolorptr=NULL;
    ls.color = &labelcolor;
    ls.outlinecolor = &labeloutlinecolor;

    if (map) {
        if( map->width > 0 && map->height > 0 )
        {
            width = map->width;
            height = map->height;
        }
        format = map->outputformat;
        imagepath = map->web.imagepath;
        imageurl = map->web.imageurl;
    }

    /* Default to GIF if no suitable GD output format set */
    if (format == NULL || !MS_RENDERER_PLUGIN(format) || !format->vtable->supports_bitmap_fonts)
        format = msCreateDefaultOutputFormat( NULL, "GD/PC256", "gif" );

    if(!format->transparent) {
        if(map && MS_VALID_COLOR(map->imagecolor)) {
            imagecolorptr = &map->imagecolor;
        } else {
            MS_INIT_COLOR(imagecolor,255,255,255,255);
            imagecolorptr = &imagecolor;
        }
    }

    img = msImageCreate(width,height,format,imagepath,imageurl,MS_DEFAULT_RESOLUTION,MS_DEFAULT_RESOLUTION,imagecolorptr);
    renderer = MS_IMAGE_RENDERER(img);

    for(i=0; i<5; i++) {
        /* use the first font we find */
        if((font = renderer->bitmapFontMetrics[font_index]) != NULL) {
            ls.size = i;
            MS_INIT_COLOR(*ls.color,0,0,0,255);
            MS_INIT_COLOR(*ls.outlinecolor,255,255,255,255);
            break;
        }
    }
    /* if no font found we can't do much. this shouldn't happen */
    if(font) {

        nTextLength = strlen(errormsg);
        nWidthTxt  =  nTextLength * font->charWidth;
        nUsableWidth = width - (nMargin*2);

        /* Check to see if it all fits on one line. If not, split the text on several lines. */
        if(!blank) {
            if (nWidthTxt > nUsableWidth) {
                nMaxCharsPerLine =  nUsableWidth/font->charWidth;
                nLines = (int) ceil ((double)nTextLength / (double)nMaxCharsPerLine);
                if (nLines > 0) {
                    papszLines = (char **)malloc(nLines*sizeof(char *));
                    for (i=0; i<nLines; i++) {
                        papszLines[i] = (char *)malloc((nMaxCharsPerLine+1)*sizeof(char));
                        papszLines[i][0] = '\0';
                    }
                }
                for (i=0; i<nLines; i++) {
                    nStart = i*nMaxCharsPerLine;
                    nEnd = nStart + nMaxCharsPerLine;
                    if (nStart < nTextLength) {
                        if (nEnd > nTextLength)
                            nEnd = nTextLength;
                        nLength = nEnd-nStart;

                        strncpy(papszLines[i], errormsg+nStart, nLength);
                        papszLines[i][nLength] = '\0';
                    }
                }
            } else {
                nLines = 1;
                papszLines = (char **)malloc(nLines*sizeof(char *));
                papszLines[0] = msStrdup(errormsg);
            }
            for (i=0; i<nLines; i++) {
                nYPos = (font->charHeight) * ((i*2) +1);
                nXPos = font->charWidth;;
                renderer->renderBitmapGlyphs(img, nXPos, nYPos, &ls, papszLines[i]);
            }
            if (papszLines) {
                for (i=0; i<nLines; i++) {
                    free(papszLines[i]);
                }
                free(papszLines);
            }
        }
    }

    /* actually write the image */
    if(!filename) {
        msIO_setHeader("Content-type","%s", MS_IMAGE_MIME_TYPE(format));
        msIO_sendHeaders();
    }
    msSaveImage(NULL,img,filename);
    msFreeImage(img);

    if (format->refcount == 0)
        msFreeOutputFormat(format);
    msFree(errormsg);
}