LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/libkml - ogrlibkmldatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 618 397 64.2 %
Date: 2012-04-28 Functions: 40 26 65.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Project:  KML Translator
       4                 :  * Purpose:  Implements OGRLIBKMLDriver
       5                 :  * Author:   Brian Case, rush at winkey dot org
       6                 :  *
       7                 :  ******************************************************************************
       8                 :  * Copyright (c) 2010, Brian Case
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  *****************************************************************************/
      28                 : 
      29                 : //#include "cpl_conv.h"
      30                 : //#include "cpl_string.h"
      31                 : //#include "cpl_error.h"
      32                 : #include <iostream>
      33                 : //#include <sstream>
      34                 : #include <kml/dom.h>
      35                 : #include <kml/base/file.h>
      36                 : 
      37                 : using kmldom::KmlFactory;
      38                 : using kmldom::DocumentPtr;
      39                 : using kmldom::FolderPtr;
      40                 : using kmldom::FeaturePtr;
      41                 : using kmldom::NetworkLinkPtr;
      42                 : using kmldom::StyleSelectorPtr;
      43                 : using kmldom::LinkPtr;
      44                 : using kmldom::SchemaPtr;
      45                 : using kmlbase::File;
      46                 : using kmldom::KmlPtr;
      47                 : 
      48                 : #include "ogr_libkml.h"
      49                 : #include "ogrlibkmlstyle.h"
      50                 : 
      51                 : /***** this was shamelessly swiped from the kml driver *****/
      52                 : 
      53                 : #define OGRLIBKMLSRSWKT "GEOGCS[\"WGS 84\", "\
      54                 :                         "   DATUM[\"WGS_1984\","\
      55                 :                         "     SPHEROID[\"WGS 84\",6378137,298.257223563,"\
      56                 :                         "           AUTHORITY[\"EPSG\",\"7030\"]],"\
      57                 :                         "           AUTHORITY[\"EPSG\",\"6326\"]],"\
      58                 :                         "       PRIMEM[\"Greenwich\",0,"\
      59                 :                         "           AUTHORITY[\"EPSG\",\"8901\"]],"\
      60                 :                         "       UNIT[\"degree\",0.01745329251994328,"\
      61                 :                         "           AUTHORITY[\"EPSG\",\"9122\"]],"\
      62                 :                         "           AUTHORITY[\"EPSG\",\"4326\"]]"
      63                 : 
      64                 : /******************************************************************************
      65                 :  OGRLIBKMLDataSource Constructor
      66                 : 
      67                 :  Args:          none
      68                 :  
      69                 :  Returns:       nothing
      70                 :                 
      71                 : ******************************************************************************/
      72                 : 
      73             498 : OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory )
      74                 : {
      75             498 :     pszName = NULL;
      76             498 :     papoLayers = NULL;
      77             498 :     nLayers = 0;
      78             498 :     nAlloced = 0;
      79                 : 
      80             498 :     bUpdated = FALSE;
      81                 : 
      82             498 :     m_isKml = FALSE;
      83             498 :     m_poKmlDSKml = NULL;
      84             498 :     m_poKmlDSContainer = NULL;
      85                 : 
      86             498 :     m_isKmz = FALSE;
      87             498 :     m_poKmlDocKml = NULL;
      88             498 :     pszStylePath = (char *) "";
      89                 : 
      90             498 :     m_isDir = FALSE;
      91                 :     
      92             498 :     m_poKmlFactory = poKmlFactory;
      93                 : 
      94                 :     //m_poStyleTable = NULL;
      95                 : 
      96             498 : }
      97                 : 
      98                 : /******************************************************************************
      99                 :  method to write a single file ds .kml at ds destroy
     100                 : 
     101                 :  Args:          none
     102                 :  
     103                 :  Returns:       nothing
     104                 :                 
     105                 : ******************************************************************************/
     106                 : 
     107               2 : void OGRLIBKMLDataSource::WriteKml (
     108                 :      )
     109                 : {
     110               2 :     std::string oKmlFilename = pszName;
     111                 : 
     112               6 :     if ( m_poKmlDSContainer
     113               2 :          && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) ) {
     114               2 :         DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
     115                 :         int iLayer;
     116                 : 
     117               6 :         for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
     118               4 :             SchemaPtr poKmlSchema;
     119               4 :             SchemaPtr poKmlSchema2;
     120                 : 
     121               4 :             if ( ( poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  ) ) ) {
     122               4 :                 size_t nKmlSchemas = poKmlDocument->get_schema_array_size (  );
     123                 :                 size_t iKmlSchema;
     124                 : 
     125               6 :                 for ( iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ ) {
     126                 :                     poKmlSchema2 =
     127               2 :                         poKmlDocument->get_schema_array_at ( iKmlSchema );
     128               2 :                     if ( poKmlSchema2 == poKmlSchema )
     129               0 :                         break;
     130                 :                 }
     131                 : 
     132               4 :                 if ( poKmlSchema2 != poKmlSchema )
     133               4 :                     poKmlDocument->add_schema ( poKmlSchema );
     134                 :             }
     135               2 :         }
     136                 :     }
     137                 : 
     138               2 :     std::string oKmlOut;
     139               2 :     if ( m_poKmlDSKml ) {
     140               2 :         oKmlOut = kmldom::SerializePretty ( m_poKmlDSKml );
     141                 :     }
     142               0 :     else if ( m_poKmlDSContainer ) {
     143               0 :         oKmlOut = kmldom::SerializePretty ( m_poKmlDSContainer );
     144                 :     }
     145                 : 
     146               2 :     if (oKmlOut.size() != 0)
     147                 :     {
     148               2 :         VSILFILE* fp = VSIFOpenL( oKmlFilename.c_str(), "wb" );
     149               2 :         if (fp == NULL)
     150                 :         {
     151                 :             CPLError ( CE_Failure, CPLE_FileIO,
     152               0 :                        "ERROR writing %s", oKmlFilename.c_str (  ) );
     153                 :             return;
     154                 :         }
     155                 : 
     156               2 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     157               2 :         VSIFCloseL(fp);
     158                 :     }
     159                 : 
     160               0 :     return;
     161                 : }
     162                 : 
     163                 : /******************************************************************************
     164                 :  method to write a ds .kmz at ds destroy
     165                 : 
     166                 :  Args:          none
     167                 :  
     168                 :  Returns:       nothing
     169                 :                 
     170                 : ******************************************************************************/
     171                 : 
     172               2 : void OGRLIBKMLDataSource::WriteKmz (
     173                 :      )
     174                 : {
     175                 : 
     176               2 :     void* hZIP = CPLCreateZip( pszName, NULL );
     177                 : 
     178               2 :     if ( !hZIP ) {
     179                 :         CPLError ( CE_Failure, CPLE_NoWriteAccess, "ERROR creating %s",
     180               0 :                    pszName );
     181               0 :         return;
     182                 :     }
     183                 : 
     184                 :     /***** write out the doc.kml ****/
     185                 : 
     186                 :     const char *pszUseDocKml =
     187               2 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
     188                 : 
     189               2 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
     190                 : 
     191                 :         /***** if we dont have the doc.kml root *****/
     192                 :         /***** make it and add the container    *****/
     193                 :         
     194               2 :         if ( !m_poKmlDocKmlRoot ) {
     195               2 :             m_poKmlDocKmlRoot = m_poKmlFactory->CreateKml (  );
     196                 : 
     197               2 :             AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
     198                 :         }
     199                 :         
     200               2 :         std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
     201                 : 
     202                 : 
     203               2 :         if ( CPLCreateFileInZip( hZIP, "doc.kml", NULL ) != CE_None ||
     204                 :              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
     205                 :             CPLError ( CE_Failure, CPLE_FileIO,
     206               0 :                        "ERROR adding %s to %s", "doc.kml", pszName );
     207               2 :         CPLCloseFileInZip(hZIP);
     208                 : 
     209                 :     }
     210                 : 
     211                 :     /***** loop though the layers and write them *****/
     212                 : 
     213                 :     int iLayer;
     214                 : 
     215               6 :     for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
     216               4 :         ContainerPtr poKlmContainer = papoLayers[iLayer]->GetKmlLayer (  );
     217                 : 
     218               4 :         if ( poKlmContainer->IsA ( kmldom::Type_Document ) ) {
     219                 : 
     220               4 :             DocumentPtr poKmlDocument = AsDocument ( poKlmContainer );
     221               4 :             SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
     222                 : 
     223               4 :             if ( !poKmlDocument->get_schema_array_size (  ) &&
     224                 :                  poKmlSchema &&
     225                 :                  poKmlSchema->get_simplefield_array_size (  ) ) {
     226               2 :                 poKmlDocument->add_schema ( poKmlSchema );
     227               4 :             }
     228                 :         }
     229                 : 
     230                 :         /***** if we dont have the layers root *****/
     231                 :         /***** make it and add the container    *****/
     232                 : 
     233               4 :         KmlPtr poKmlKml = NULL;
     234                 : 
     235               4 :         if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
     236                 : 
     237               4 :             poKmlKml = m_poKmlFactory->CreateKml (  );
     238                 : 
     239               4 :             poKmlKml->set_feature ( poKlmContainer );
     240                 :         }
     241                 : 
     242               4 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     243                 : 
     244               4 :         if ( CPLCreateFileInZip( hZIP, papoLayers[iLayer]->GetFileName (  ), NULL ) != CE_None ||
     245                 :              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
     246                 :             CPLError ( CE_Failure, CPLE_FileIO,
     247               0 :                        "ERROR adding %s to %s", papoLayers[iLayer]->GetFileName (  ), pszName );
     248               4 :         CPLCloseFileInZip(hZIP);
     249                 : 
     250                 :     }
     251                 : 
     252                 :    /***** write the style table *****/
     253                 : 
     254               2 :     if ( m_poKmlStyleKml ) {
     255                 : 
     256               0 :         KmlPtr poKmlKml = m_poKmlFactory->CreateKml (  );
     257                 : 
     258               0 :         poKmlKml->set_feature ( m_poKmlStyleKml );
     259               0 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     260                 : 
     261               0 :         if ( CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
     262                 :              CPLWriteFileInZip( hZIP, oKmlOut.data(), oKmlOut.size() ) != CE_None )
     263                 :             CPLError ( CE_Failure, CPLE_FileIO,
     264               0 :                        "ERROR adding %s to %s", "style/style.kml", pszName );
     265               0 :         CPLCloseFileInZip(hZIP);
     266                 :     }
     267                 : 
     268               2 :     CPLCloseZip(hZIP);
     269                 : 
     270               2 :     return;
     271                 : }
     272                 : 
     273                 : /******************************************************************************
     274                 :  method to write a dir ds at ds destroy
     275                 : 
     276                 :  Args:          none
     277                 :  
     278                 :  Returns:       nothing
     279                 :                 
     280                 : ******************************************************************************/
     281                 : 
     282               2 : void OGRLIBKMLDataSource::WriteDir (
     283                 :      )
     284                 : {
     285                 : 
     286                 :     /***** write out the doc.kml ****/
     287                 : 
     288                 :     const char *pszUseDocKml =
     289               2 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
     290                 : 
     291               2 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
     292                 : 
     293                 :         /***** if we dont have the doc.kml root *****/
     294                 :         /***** make it and add the container    *****/
     295                 :         
     296               2 :         if ( !m_poKmlDocKmlRoot ) {
     297               2 :             m_poKmlDocKmlRoot = m_poKmlFactory->CreateKml (  );
     298                 : 
     299               2 :             AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
     300                 :         }
     301                 :         
     302               2 :         std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
     303                 : 
     304               2 :         const char *pszOutfile = CPLFormFilename ( pszName, "doc.kml", NULL );
     305                 : 
     306               2 :         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
     307               2 :         if (fp == NULL)
     308                 :         {
     309                 :             CPLError ( CE_Failure, CPLE_FileIO,
     310               0 :                        "ERROR Writing %s to %s", "doc.kml", pszName );
     311                 :             return;
     312                 :         }
     313                 : 
     314               2 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     315               2 :         VSIFCloseL(fp);
     316                 :     }
     317                 : 
     318                 :     /***** loop though the layers and write them *****/
     319                 : 
     320                 :     int iLayer;
     321                 : 
     322               2 :     for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
     323               4 :         ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer (  );
     324                 : 
     325               4 :         if ( poKmlContainer->IsA ( kmldom::Type_Document ) ) {
     326                 : 
     327               4 :             DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
     328               4 :             SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
     329                 : 
     330               4 :             if ( !poKmlDocument->get_schema_array_size (  ) &&
     331                 :                  poKmlSchema &&
     332                 :                  poKmlSchema->get_simplefield_array_size (  ) ) {
     333               2 :                 poKmlDocument->add_schema ( poKmlSchema );
     334               4 :             };
     335                 :         }
     336                 : 
     337                 :         /***** if we dont have the layers root *****/
     338                 :         /***** make it and add the container    *****/
     339                 : 
     340               4 :         KmlPtr poKmlKml = NULL;
     341                 : 
     342               4 :         if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
     343                 : 
     344               4 :             poKmlKml = m_poKmlFactory->CreateKml (  );
     345                 : 
     346               4 :             poKmlKml->set_feature ( poKmlContainer );
     347                 :         }
     348                 : 
     349               4 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     350                 : 
     351                 :         const char *pszOutfile = CPLFormFilename ( pszName,
     352               4 :                                                    papoLayers[iLayer]->
     353                 :                                                    GetFileName (  ),
     354               8 :                                                    NULL );
     355                 : 
     356               4 :         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
     357               4 :         if (fp == NULL)
     358                 :         {
     359                 :             CPLError ( CE_Failure, CPLE_FileIO,
     360                 :                        "ERROR Writing %s to %s",
     361               0 :                        papoLayers[iLayer]->GetFileName (  ), pszName );
     362                 :             return;
     363                 :         }
     364                 : 
     365               4 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     366               4 :         VSIFCloseL(fp);
     367                 :     }
     368                 : 
     369                 :    /***** write the style table *****/
     370                 : 
     371               2 :     if ( m_poKmlStyleKml ) {
     372                 : 
     373               0 :         KmlPtr poKmlKml = m_poKmlFactory->CreateKml (  );
     374                 : 
     375               0 :         poKmlKml->set_feature ( m_poKmlStyleKml );
     376               0 :         std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
     377                 : 
     378                 :         const char *pszOutfile = CPLFormFilename ( pszName,
     379                 :                                                    "style.kml",
     380               0 :                                                    NULL );
     381                 : 
     382               0 :         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
     383               0 :         if (fp == NULL)
     384                 :         {
     385                 :             CPLError ( CE_Failure, CPLE_FileIO,
     386               0 :                        "ERROR Writing %s to %s", "style.kml", pszName );
     387                 :             return;
     388                 :         }
     389                 : 
     390               0 :         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
     391               0 :         VSIFCloseL(fp);
     392                 :     }
     393                 : 
     394               2 :     return;
     395                 : }
     396                 : 
     397                 : /******************************************************************************
     398                 :  method to write the datasource to disk
     399                 : 
     400                 :  Args:      none
     401                 : 
     402                 :  Returns    nothing
     403                 : 
     404                 : ******************************************************************************/
     405                 : 
     406             498 : OGRErr OGRLIBKMLDataSource::SyncToDisk (
     407                 :      )
     408                 : {
     409                 : 
     410             498 :     if ( bUpdated ) {
     411                 : 
     412                 :         /***** kml *****/
     413                 : 
     414               6 :         if ( bUpdate && IsKml (  ) )
     415               2 :             WriteKml (  );
     416                 : 
     417                 :         /***** kmz *****/
     418                 : 
     419               4 :         else if ( bUpdate && IsKmz (  ) ) {
     420               2 :             WriteKmz (  );
     421                 :         }
     422                 : 
     423               2 :         else if ( bUpdate && IsDir (  ) ) {
     424               2 :             WriteDir (  );
     425                 :         }
     426                 : 
     427               6 :         bUpdated = FALSE;
     428                 :     }
     429                 : 
     430             498 :     return OGRERR_NONE;
     431                 : }
     432                 : 
     433                 : /******************************************************************************
     434                 :  OGRLIBKMLDataSource Destructor
     435                 :  
     436                 :  Args:          none
     437                 :  
     438                 :  Returns:       nothing
     439                 :                 
     440                 : ******************************************************************************/
     441                 : 
     442             498 : OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
     443                 : {
     444                 : 
     445                 : 
     446                 :     /***** sync the DS to disk *****/
     447                 : 
     448             498 :     SyncToDisk (  );
     449                 : 
     450             498 :     CPLFree ( pszName );
     451                 : 
     452             498 :     if (! EQUAL(pszStylePath, ""))
     453               4 :         CPLFree ( pszStylePath );
     454                 :     
     455             594 :     for ( int i = 0; i < nLayers; i++ )
     456              96 :         delete papoLayers[i];
     457                 : 
     458             498 :     CPLFree ( papoLayers );
     459                 : 
     460                 :     //delete m_poStyleTable;
     461                 : 
     462             498 : }
     463                 : 
     464                 : 
     465                 : /******************************************************************************
     466                 :  method to parse a schemas out of a document
     467                 : 
     468                 :  Args:          poKmlDocument   pointer to the document to parse
     469                 :  
     470                 :  Returns:       nothing
     471                 :                 
     472                 : ******************************************************************************/
     473                 : 
     474               2 : SchemaPtr OGRLIBKMLDataSource::FindSchema (
     475                 :     const char *pszSchemaUrl )
     476                 : {
     477               2 :     char *pszID = NULL;
     478               2 :     char *pszFile = NULL;
     479               2 :     char *pszName = NULL;
     480                 :     char *pszPound;
     481               2 :     DocumentPtr poKmlDocument = NULL;
     482               2 :     SchemaPtr poKmlSchemaResult = NULL;
     483                 : 
     484               2 :     if ( !pszSchemaUrl || !*pszSchemaUrl )
     485               0 :         return NULL;
     486                 : 
     487               2 :     if ( *pszSchemaUrl == '#' ) {
     488               2 :         pszID = CPLStrdup ( pszSchemaUrl + 1 );
     489                 : 
     490                 :         /***** kml *****/
     491                 : 
     492               2 :         if ( IsKml (  ) && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) )
     493               2 :             poKmlDocument = AsDocument ( m_poKmlDSContainer );
     494                 : 
     495                 :         /***** kmz *****/
     496                 : 
     497               0 :         else if ( ( IsKmz (  ) || IsDir (  ) ) && m_poKmlDocKml
     498               0 :                   && m_poKmlDocKml->IsA ( kmldom::Type_Document ) )
     499               0 :             poKmlDocument = AsDocument ( m_poKmlDocKml );
     500                 : 
     501                 :     }
     502                 : 
     503                 : 
     504               0 :     else if ( ( pszPound = strchr ( (char *)pszSchemaUrl, '#' ) ) ) {
     505               0 :         pszFile = CPLStrdup ( pszSchemaUrl );
     506               0 :         pszID = CPLStrdup ( pszPound + 1 );
     507               0 :         pszPound = strchr ( pszFile, '#' );
     508               0 :         *pszPound = '\0';
     509                 :     }
     510                 : 
     511                 :     else {
     512               0 :         pszName = CPLStrdup ( pszSchemaUrl );
     513                 : 
     514                 :         /***** kml *****/
     515                 : 
     516               0 :         if ( IsKml (  ) && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) )
     517               0 :             poKmlDocument = AsDocument ( m_poKmlDSContainer );
     518                 : 
     519                 :         /***** kmz *****/
     520                 : 
     521               0 :         else if ( ( IsKmz (  ) || IsDir (  ) ) && m_poKmlDocKml
     522               0 :                   && m_poKmlDocKml->IsA ( kmldom::Type_Document ) )
     523               0 :             poKmlDocument = AsDocument ( m_poKmlDocKml );
     524                 : 
     525                 :     }
     526                 :     
     527                 : 
     528               2 :     if ( poKmlDocument) {
     529                 : 
     530               2 :         size_t nKmlSchemas = poKmlDocument->get_schema_array_size (  );
     531                 :         size_t iKmlSchema;
     532                 : 
     533               2 :         for ( iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ ) {
     534                 :             SchemaPtr poKmlSchema =
     535               4 :                 poKmlDocument->get_schema_array_at ( iKmlSchema );
     536               4 :             if ( poKmlSchema->has_id (  ) && pszID) {
     537               4 :                 if ( EQUAL ( pszID, poKmlSchema->get_id (  ).c_str (  ) ) ) {
     538               2 :                     poKmlSchemaResult = poKmlSchema;
     539                 :                     break;
     540                 :                 }
     541                 :             }
     542                 : 
     543               0 :             else if ( poKmlSchema->has_name (  ) && pszName) {
     544               0 :                 if ( EQUAL ( pszName, poKmlSchema->get_name (  ).c_str (  ) ) ) {
     545               0 :                     poKmlSchemaResult = poKmlSchema;
     546                 :                     break;
     547                 :                 }
     548                 :             }
     549                 : 
     550                 :         }
     551                 :     }
     552                 : 
     553               2 :     if ( pszFile )
     554               0 :         CPLFree ( pszFile );
     555               2 :     if ( pszID )
     556               2 :         CPLFree ( pszID );
     557                 : 
     558               2 :     return poKmlSchemaResult;
     559                 : 
     560                 : }
     561                 : 
     562                 : /******************************************************************************
     563                 : Method to allocate memory for the layer array, create the layer,
     564                 :  and add it to the layer array
     565                 : 
     566                 :  Args:          pszLayerName    the name of the layer
     567                 :                 poSpatialRef    the spacial Refrance for the layer
     568                 :                 eGType          the layers geometry type
     569                 :                 poOgrDS         pointer to the datasource the layer is in
     570                 :                 poKmlRoot       pointer to the root kml element of the layer
     571                 :                 pszFileName     the filename of the layer
     572                 :                 bNew            true if its a new layer
     573                 :                 bUpdate         true if the layer is writeable
     574                 :                 nGuess          a guess at the number of additional layers
     575                 :                                 we are going to need
     576                 :  
     577                 :  Returns:       Pointer to the new layer
     578                 : ******************************************************************************/
     579                 : 
     580              96 : OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
     581                 :     const char *pszLayerName,
     582                 :     OGRSpatialReference * poSpatialRef,
     583                 :     OGRwkbGeometryType eGType,
     584                 :     OGRLIBKMLDataSource * poOgrDS,
     585                 :     ElementPtr poKmlRoot,
     586                 :     ContainerPtr poKmlContainer,
     587                 :     const char *pszFileName,
     588                 :     int bNew,
     589                 :     int bUpdate,
     590                 :     int nGuess )
     591                 : {
     592                 : 
     593                 :     /***** check to see if we have enough space to store the layer *****/
     594                 : 
     595              96 :     if ( nLayers == nAlloced ) {
     596              38 :         nAlloced += nGuess;
     597                 :         void *tmp = CPLRealloc ( papoLayers,
     598              38 :                                  sizeof ( OGRLIBKMLLayer * ) * nAlloced );
     599                 : 
     600              38 :         papoLayers = ( OGRLIBKMLLayer ** ) tmp;
     601                 :     }
     602                 : 
     603                 :     /***** create the layer *****/
     604                 : 
     605              96 :     int iLayer = nLayers++;
     606                 : 
     607                 :     OGRLIBKMLLayer *poOgrLayer = new OGRLIBKMLLayer ( pszLayerName,
     608                 :                                                       poSpatialRef,
     609                 :                                                       eGType,
     610                 :                                                       poOgrDS,
     611                 :                                                       poKmlRoot,
     612                 :                                                       poKmlContainer,
     613                 :                                                       pszFileName,
     614                 :                                                       bNew,
     615              96 :                                                       bUpdate );
     616                 : 
     617                 :     /***** add the layer to the array *****/
     618                 : 
     619              96 :     papoLayers[iLayer] = poOgrLayer;
     620                 : 
     621              96 :     return poOgrLayer;
     622                 : }
     623                 : 
     624                 : /******************************************************************************
     625                 :  method to parse multiple layers out of a container
     626                 : 
     627                 :  Args:          poKmlContainer  pointer to the container to parse
     628                 :                 poOgrSRS        SRS to use when creating the layer
     629                 :  
     630                 :  Returns:       number of features in the container that are not another
     631                 :                 container
     632                 :                 
     633                 : ******************************************************************************/
     634                 : 
     635             102 : int OGRLIBKMLDataSource::ParseLayers (
     636                 :     ContainerPtr poKmlContainer,
     637                 :     OGRSpatialReference * poOgrSRS )
     638                 : {
     639             102 :     int nResult = 0;
     640                 : 
     641                 :     /***** if container is null just bail now *****/
     642                 : 
     643             102 :     if ( !poKmlContainer )
     644               0 :         return nResult;
     645                 : 
     646             102 :     size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
     647                 : 
     648                 :     /***** loop over the container to seperate the style, layers, etc *****/
     649                 : 
     650                 :     size_t iKmlFeature;
     651                 : 
     652             458 :     for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
     653                 :         FeaturePtr poKmlFeat =
     654             356 :             poKmlContainer->get_feature_array_at ( iKmlFeature );
     655                 : 
     656                 :         /***** container *****/
     657                 : 
     658             356 :         if ( poKmlFeat->IsA ( kmldom::Type_Container ) ) {
     659                 : 
     660                 :             /***** see if the container has a name *****/
     661                 : 
     662              70 :             std::string oKmlFeatName;
     663              70 :             if ( poKmlFeat->has_name (  ) ) {
     664                 :                 /* Strip leading and trailing spaces */
     665              70 :                 const char* pszName = poKmlFeat->get_name (  ).c_str();
     666             140 :                 while(*pszName == ' ' || *pszName == '\n' || *pszName == '\r' || *pszName == '\t' )
     667               0 :                     pszName ++;
     668              70 :                 oKmlFeatName = pszName;
     669              70 :                 int nSize = (int)oKmlFeatName.size();
     670             140 :                 while (nSize > 0 &&
     671                 :                        (oKmlFeatName[nSize-1] == ' ' || oKmlFeatName[nSize-1] == '\n' ||
     672                 :                         oKmlFeatName[nSize-1] == '\r' || oKmlFeatName[nSize-1] == '\t'))
     673                 :                 {
     674               0 :                     nSize --;
     675               0 :                     oKmlFeatName.resize(nSize);
     676                 :                 }
     677                 :             }
     678                 : 
     679                 :             /***** use the feature index number as the name *****/
     680                 :             /***** not sure i like this c++ ich *****/
     681                 : 
     682                 :             else {
     683               0 :                 std::stringstream oOut;
     684               0 :                 oOut << iKmlFeature;
     685               0 :                 oKmlFeatName = "Layer";
     686               0 :                 oKmlFeatName.append(oOut.str (  ));
     687                 :             }
     688                 : 
     689                 :             /***** create the layer *****/
     690                 : 
     691                 :             AddLayer ( oKmlFeatName.c_str (  ),
     692                 :                        poOgrSRS, wkbUnknown, this,
     693              70 :                        NULL, AsContainer( poKmlFeat ), "", FALSE, bUpdate, nKmlFeatures );
     694                 : 
     695                 :         }
     696                 : 
     697                 :         else
     698             286 :             nResult++;
     699                 :     }
     700                 : 
     701             102 :     return nResult;
     702                 : }
     703                 : 
     704                 : /******************************************************************************
     705                 :  function to get the container from the kmlroot
     706                 :  
     707                 :  Args:          poKmlRoot   the root element
     708                 :  
     709                 :  Returns:       root if its a container, if its a kml the container it
     710                 :                 contains, or NULL
     711                 : 
     712                 : ******************************************************************************/
     713                 : 
     714              30 : static ContainerPtr GetContainerFromRoot (
     715                 :     KmlFactory *m_poKmlFactory, ElementPtr poKmlRoot )
     716                 : {
     717              30 :     ContainerPtr poKmlContainer = NULL;
     718                 : 
     719              30 :     if ( poKmlRoot ) {
     720                 : 
     721                 :         /***** skip over the <kml> we want the container *****/
     722                 : 
     723              30 :         if ( poKmlRoot->IsA ( kmldom::Type_kml ) ) {
     724                 : 
     725              30 :             KmlPtr poKmlKml = AsKml ( poKmlRoot );
     726                 : 
     727              30 :             if ( poKmlKml->has_feature (  ) ) {
     728              30 :                 FeaturePtr poKmlFeat = poKmlKml->get_feature (  );
     729                 : 
     730              30 :                 if ( poKmlFeat->IsA ( kmldom::Type_Container ) )
     731              26 :                     poKmlContainer = AsContainer ( poKmlFeat );
     732               4 :                 else if ( poKmlFeat->IsA ( kmldom::Type_Placemark ) )
     733                 :                 {
     734               4 :                     poKmlContainer = m_poKmlFactory->CreateDocument (  );
     735               4 :                     poKmlContainer->add_feature ( kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
     736              30 :                 }
     737                 : 
     738              30 :             }
     739                 : 
     740                 :         }
     741                 : 
     742               0 :         else if ( poKmlRoot->IsA ( kmldom::Type_Container ) )
     743               0 :             poKmlContainer = AsContainer ( poKmlRoot );
     744                 :     }
     745                 : 
     746               0 :     return poKmlContainer;
     747                 : }
     748                 : 
     749                 : /******************************************************************************
     750                 :  method to parse a kml string into the style table
     751                 : ******************************************************************************/
     752                 : 
     753               0 : int OGRLIBKMLDataSource::ParseIntoStyleTable (
     754                 :     std::string *poKmlStyleKml,
     755                 :     const char *pszMyStylePath)
     756                 : {
     757                 :     
     758                 :     /***** parse the kml into the dom *****/
     759                 : 
     760               0 :     std::string oKmlErrors;
     761               0 :     ElementPtr poKmlRoot = kmldom::Parse ( *poKmlStyleKml, &oKmlErrors );
     762                 : 
     763               0 :     if ( !poKmlRoot ) {
     764                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     765                 :                    "ERROR Parseing style kml %s :%s",
     766               0 :                    pszStylePath, oKmlErrors.c_str (  ) );
     767               0 :         return false;
     768                 :     }
     769                 :     
     770               0 :     ContainerPtr poKmlContainer;
     771                 : 
     772               0 :     if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
     773               0 :         return false;
     774                 :     }
     775                 :     
     776               0 :     ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
     777               0 :     pszStylePath = CPLStrdup(pszMyStylePath);
     778                 :     
     779                 :         
     780               0 :     return true;
     781                 : }
     782                 : 
     783                 : /******************************************************************************
     784                 :  method to open a kml file
     785                 :  
     786                 :  Args:          pszFilename file to open
     787                 :                 bUpdate     update mode
     788                 :  
     789                 :  Returns:       True on success, false on failure
     790                 : 
     791                 : ******************************************************************************/
     792                 : 
     793              18 : int OGRLIBKMLDataSource::OpenKml (
     794                 :     const char *pszFilename,
     795                 :     int bUpdate )
     796                 : {
     797              18 :     std::string oKmlKml;
     798                 :     char szBuffer[1024+1];
     799                 : 
     800              18 :     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     801              18 :     if (fp == NULL)
     802                 :     {
     803                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     804               0 :                    "Cannot open %s", pszFilename );
     805               0 :         return FALSE;
     806                 :     }
     807                 :     int nRead;
     808             276 :     while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
     809                 :     {
     810                 :         try
     811                 :         {
     812             240 :             oKmlKml.append(szBuffer, nRead);
     813                 :         }
     814               0 :         catch(std::bad_alloc& e)
     815                 :         {
     816               0 :             VSIFCloseL(fp);
     817               0 :             return FALSE;
     818                 :         }
     819                 :     }
     820              18 :     VSIFCloseL(fp);
     821                 : 
     822              18 :     CPLLocaleC  oLocaleForcer;
     823                 : 
     824                 :     /***** create a SRS *****/
     825                 : 
     826                 :     OGRSpatialReference *poOgrSRS =
     827              18 :         new OGRSpatialReference ( OGRLIBKMLSRSWKT );
     828                 : 
     829                 :     /***** parse the kml into the DOM *****/
     830                 : 
     831              18 :     std::string oKmlErrors;
     832                 : 
     833              18 :     ElementPtr poKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
     834                 : 
     835              18 :     if ( !poKmlRoot ) {
     836                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     837                 :                    "ERROR Parseing kml %s :%s",
     838               0 :                    pszFilename, oKmlErrors.c_str (  ) );
     839               0 :         delete poOgrSRS;
     840                 : 
     841               0 :         return FALSE;
     842                 :     }
     843                 : 
     844                 :     /***** get the container from root  *****/
     845                 : 
     846              18 :     if ( !( m_poKmlDSContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
     847                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     848                 :                    "ERROR Parseing kml %s :%s %s",
     849                 :                    pszFilename, "This file does not fit the OGR model,",
     850               0 :                    "there is no container element at the root." );
     851               0 :         delete poOgrSRS;
     852                 : 
     853               0 :         return FALSE;
     854                 :     }
     855                 : 
     856              18 :     m_isKml = TRUE;
     857                 : 
     858                 :     /***** get the styles *****/
     859                 : 
     860              18 :     ParseStyles ( AsDocument ( m_poKmlDSContainer ), &m_poStyleTable );
     861                 : 
     862                 :     /***** parse for layers *****/
     863                 : 
     864              18 :     int nPlacemarks = ParseLayers ( m_poKmlDSContainer, poOgrSRS );
     865                 : 
     866                 :     /***** if there is placemarks in the root its a layer *****/
     867                 : 
     868              18 :     if ( nPlacemarks && !nLayers ) {
     869                 :         AddLayer ( CPLGetBasename ( pszFilename ),
     870                 :                    poOgrSRS, wkbUnknown,
     871               4 :                    this, poKmlRoot, m_poKmlDSContainer, pszFilename, FALSE, bUpdate, 1 );
     872                 :     }
     873                 : 
     874              18 :     delete poOgrSRS;
     875                 : 
     876              18 :     return TRUE;
     877                 : }
     878                 : 
     879                 : /******************************************************************************
     880                 :  method to open a kmz file
     881                 :  
     882                 :  Args:          pszFilename file to open
     883                 :                 bUpdate     update mode
     884                 :  
     885                 :  Returns:       True on success, false on failure
     886                 : 
     887                 : ******************************************************************************/
     888                 : 
     889                 : 
     890               2 : int OGRLIBKMLDataSource::OpenKmz (
     891                 :     const char *pszFilename,
     892                 :     int bUpdate )
     893                 : {
     894               2 :     std::string oKmlKmz;
     895                 :     char szBuffer[1024+1];
     896                 : 
     897               2 :     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     898               2 :     if (fp == NULL)
     899                 :     {
     900                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     901               0 :                    "Cannot open %s", pszFilename );
     902               0 :         return FALSE;
     903                 :     }
     904                 :     int nRead;
     905               6 :     while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
     906                 :     {
     907                 :         try
     908                 :         {
     909               2 :             oKmlKmz.append(szBuffer, nRead);
     910                 :         }
     911               0 :         catch(std::bad_alloc& e)
     912                 :         {
     913               0 :             VSIFCloseL(fp);
     914               0 :             return FALSE;
     915                 :         }
     916                 :     }
     917               2 :     VSIFCloseL(fp);
     918                 : 
     919               2 :     KmzFile *poKmlKmzfile = KmzFile::OpenFromString ( oKmlKmz );
     920                 : 
     921               2 :     if ( !poKmlKmzfile ) {
     922                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     923               0 :                    "%s is not a valid kmz file", pszFilename );
     924               0 :         return FALSE;
     925                 :     }
     926                 : 
     927               2 :     CPLLocaleC  oLocaleForcer;
     928                 : 
     929                 :     /***** read the doc.kml *****/
     930                 : 
     931               2 :     std::string oKmlKml;
     932               2 :     std::string oKmlKmlPath;
     933               2 :     if ( !poKmlKmzfile->ReadKmlAndGetPath ( &oKmlKml, &oKmlKmlPath ) ) {
     934                 : 
     935               0 :         return FALSE;
     936                 :     }
     937                 : 
     938                 :     /***** create a SRS *****/
     939                 : 
     940                 :     OGRSpatialReference *poOgrSRS =
     941               2 :         new OGRSpatialReference ( OGRLIBKMLSRSWKT );
     942                 : 
     943                 :     /***** parse the kml into the DOM *****/
     944                 : 
     945               2 :     std::string oKmlErrors;
     946               2 :     ElementPtr poKmlDocKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
     947                 : 
     948               2 :     if ( !poKmlDocKmlRoot ) {
     949                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     950                 :                    "ERROR Parseing kml layer %s from %s :%s",
     951                 :                    oKmlKmlPath.c_str (  ),
     952               0 :                    pszFilename, oKmlErrors.c_str (  ) );
     953               0 :         delete poOgrSRS;
     954                 : 
     955               0 :         return FALSE;
     956                 :     }
     957                 : 
     958                 :     /***** get the child contianer from root *****/
     959                 : 
     960               2 :     ContainerPtr poKmlContainer;
     961                 : 
     962               2 :     if (!(poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlDocKmlRoot ))) {
     963                 :         CPLError ( CE_Failure, CPLE_OpenFailed,
     964                 :                    "ERROR Parseing %s from %s :%s",
     965                 :                    oKmlKmlPath.c_str (  ),
     966               0 :                    pszFilename, "kml contains no Containers" );
     967               0 :         delete poOgrSRS;
     968                 : 
     969               0 :         return FALSE;
     970                 :     }
     971                 : 
     972                 :     /***** loop over the container looking for network links *****/
     973                 : 
     974               2 :     size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
     975                 :     size_t iKmlFeature;
     976               2 :     int nLinks = 0;
     977                 : 
     978               2 :     for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
     979                 :         FeaturePtr poKmlFeat =
     980               4 :             poKmlContainer->get_feature_array_at ( iKmlFeature );
     981                 : 
     982                 :         /***** is it a network link? *****/
     983                 : 
     984               4 :         if ( !poKmlFeat->IsA ( kmldom::Type_NetworkLink ) )
     985               0 :             continue;
     986                 : 
     987               4 :         NetworkLinkPtr poKmlNetworkLink = AsNetworkLink ( poKmlFeat );
     988                 : 
     989                 :         /***** does it have a link? *****/
     990                 : 
     991               4 :         if ( !poKmlNetworkLink->has_link (  ) )
     992               0 :             continue;
     993                 : 
     994               4 :         LinkPtr poKmlLink = poKmlNetworkLink->get_link (  );
     995                 : 
     996                 :         /***** does the link have a href? *****/
     997                 : 
     998               4 :         if ( !poKmlLink->has_href (  ) )
     999               0 :             continue;
    1000                 : 
    1001                 :         kmlengine::Href * poKmlHref =
    1002               4 :             new kmlengine::Href ( poKmlLink->get_href (  ) );
    1003                 : 
    1004                 :         /***** is the link relative? *****/
    1005                 : 
    1006               8 :         if ( poKmlHref->IsRelativePath (  ) ) {
    1007                 : 
    1008               4 :             nLinks++;
    1009                 : 
    1010               4 :             std::string oKml;
    1011               4 :             if ( poKmlKmzfile->
    1012                 :                  ReadFile ( poKmlHref->get_path (  ).c_str (  ), &oKml ) ) {
    1013                 : 
    1014                 :                 /***** parse the kml into the DOM *****/
    1015                 : 
    1016               4 :                 std::string oKmlErrors;
    1017               4 :                 ElementPtr poKmlLyrRoot = kmldom::Parse ( oKml, &oKmlErrors );
    1018                 : 
    1019               4 :                 if ( !poKmlLyrRoot ) {
    1020                 :                     CPLError ( CE_Failure, CPLE_OpenFailed,
    1021                 :                                "ERROR Parseing kml layer %s from %s :%s",
    1022                 :                                poKmlHref->get_path (  ).c_str (  ),
    1023               0 :                                pszFilename, oKmlErrors.c_str (  ) );
    1024               0 :                     delete poKmlHref;
    1025                 : 
    1026               0 :                     continue;
    1027                 :                 }
    1028                 : 
    1029                 :                 /***** get the container from root  *****/
    1030                 : 
    1031                 :                 ContainerPtr poKmlLyrContainer =
    1032               4 :                     GetContainerFromRoot ( m_poKmlFactory, poKmlLyrRoot );
    1033                 : 
    1034               4 :                 if ( !poKmlLyrContainer )
    1035                 :                 {
    1036                 :                     CPLError ( CE_Failure, CPLE_OpenFailed,
    1037                 :                                "ERROR Parseing kml layer %s from %s :%s",
    1038                 :                                poKmlHref->get_path (  ).c_str (  ),
    1039               0 :                                pszFilename, oKmlErrors.c_str (  ) );
    1040               0 :                     delete poKmlHref;
    1041                 : 
    1042               0 :                     continue;
    1043                 :                 }
    1044                 : 
    1045                 :                 /***** create the layer *****/
    1046                 : 
    1047                 :                 AddLayer ( CPLGetBasename
    1048                 :                            ( poKmlHref->get_path (  ).c_str (  ) ), poOgrSRS,
    1049                 :                            wkbUnknown, this, poKmlLyrRoot, poKmlLyrContainer,
    1050                 :                            poKmlHref->get_path (  ).c_str (  ), FALSE, bUpdate,
    1051               4 :                            nKmlFeatures );
    1052                 : 
    1053               0 :             }
    1054                 :         }
    1055                 : 
    1056                 :         /***** cleanup *****/
    1057                 : 
    1058               4 :         delete poKmlHref;
    1059                 :     }
    1060                 : 
    1061                 :     /***** if the doc.kml has links store it so if were in update mode we can write it *****/
    1062                 :     
    1063               2 :     if ( nLinks ) {
    1064               2 :         m_poKmlDocKml = poKmlContainer;
    1065               2 :         m_poKmlDocKmlRoot = poKmlDocKmlRoot;
    1066                 :     }
    1067                 :         
    1068                 :     /***** if the doc.kml has no links treat it as a normal kml file *****/
    1069                 : 
    1070                 :     else {
    1071                 : 
    1072                 :         /* todo there could still be a seperate styles file in the kmz
    1073                 :            if there is this would be a layer style table IF its only a single
    1074                 :            layer
    1075                 :          */
    1076                 : 
    1077                 :         /***** get the styles *****/
    1078                 : 
    1079               0 :         ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
    1080                 : 
    1081                 :         /***** parse for layers *****/
    1082                 : 
    1083               0 :         int nPlacemarks = ParseLayers ( poKmlContainer, poOgrSRS );
    1084                 : 
    1085                 :         /***** if there is placemarks in the root its a layer *****/
    1086                 : 
    1087               0 :         if ( nPlacemarks && !nLayers ) {
    1088                 :             AddLayer ( CPLGetBasename ( pszFilename ),
    1089                 :                        poOgrSRS, wkbUnknown,
    1090               0 :                        this, poKmlDocKmlRoot, poKmlContainer, pszFilename, FALSE, bUpdate, 1 );
    1091                 :         }
    1092                 :     }
    1093                 : 
    1094                 :     /***** read the style table if it has one *****/
    1095                 : 
    1096               2 :     std::string oKmlStyleKml;
    1097               2 :     if ( poKmlKmzfile->ReadFile ( "style/style.kml", &oKmlStyleKml ) )
    1098               0 :         ParseIntoStyleTable ( &oKmlStyleKml, "style/style.kml");
    1099                 : 
    1100                 :     /***** cleanup *****/
    1101                 : 
    1102               2 :     delete poOgrSRS;
    1103                 : 
    1104               2 :     delete poKmlKmzfile;
    1105               2 :     m_isKmz = TRUE;
    1106                 :     
    1107               2 :     return TRUE;
    1108                 : }
    1109                 : 
    1110                 : /******************************************************************************
    1111                 :  method to open a dir
    1112                 :  
    1113                 :  Args:          pszFilename Dir to open
    1114                 :                 bUpdate     update mode
    1115                 :  
    1116                 :  Returns:       True on success, false on failure
    1117                 : 
    1118                 : ******************************************************************************/
    1119                 : 
    1120              14 : int OGRLIBKMLDataSource::OpenDir (
    1121                 :     const char *pszFilename,
    1122                 :     int bUpdate )
    1123                 : {
    1124                 : 
    1125              14 :     char **papszDirList = NULL;
    1126                 : 
    1127              14 :     if ( !( papszDirList = VSIReadDir ( pszFilename ) ) )
    1128               0 :         return FALSE;
    1129                 : 
    1130                 :     /***** create a SRS *****/
    1131                 : 
    1132                 :     OGRSpatialReference *poOgrSRS =
    1133              14 :         new OGRSpatialReference ( OGRLIBKMLSRSWKT );
    1134                 : 
    1135              14 :     int nFiles = CSLCount ( papszDirList );
    1136                 :     int iFile;
    1137                 : 
    1138              14 :     for ( iFile = 0; iFile < nFiles; iFile++ ) {
    1139                 : 
    1140                 :         /***** make sure its a .kml file *****/
    1141                 : 
    1142             944 :         if ( !EQUAL ( CPLGetExtension ( papszDirList[iFile] ), "kml" ) )
    1143             938 :             continue;
    1144                 : 
    1145                 :         /***** read the file *****/
    1146               6 :         std::string oKmlKml;
    1147                 :         char szBuffer[1024+1];
    1148                 : 
    1149                 :         CPLString osFilePath =
    1150               6 :             CPLFormFilename ( pszFilename, papszDirList[iFile], NULL );
    1151                 : 
    1152               6 :         VSILFILE* fp = VSIFOpenL(osFilePath, "rb");
    1153               6 :         if (fp == NULL)
    1154                 :         {
    1155                 :              CPLError ( CE_Failure, CPLE_OpenFailed,
    1156               0 :                        "Cannot open %s", osFilePath.c_str() );
    1157               0 :              continue;
    1158                 :         }
    1159                 : 
    1160                 :         int nRead;
    1161              24 :         while ((nRead = VSIFReadL(szBuffer, 1, 1024, fp)) != 0)
    1162                 :         {
    1163                 :             try
    1164                 :             {
    1165              12 :                 oKmlKml.append(szBuffer, nRead);
    1166                 :             }
    1167               0 :             catch(std::bad_alloc& e)
    1168                 :             {
    1169               0 :                 VSIFCloseL(fp);
    1170               0 :                 CSLDestroy ( papszDirList );
    1171               0 :                 return FALSE;
    1172                 :             }
    1173                 :         }
    1174               6 :         VSIFCloseL(fp);
    1175                 : 
    1176               6 :         CPLLocaleC  oLocaleForcer;
    1177                 : 
    1178                 :         /***** parse the kml into the DOM *****/
    1179                 : 
    1180               6 :         std::string oKmlErrors;
    1181               6 :         ElementPtr poKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
    1182                 : 
    1183               6 :         if ( !poKmlRoot ) {
    1184                 :             CPLError ( CE_Failure, CPLE_OpenFailed,
    1185                 :                        "ERROR Parseing kml layer %s from %s :%s",
    1186               0 :                        osFilePath.c_str(), pszFilename, oKmlErrors.c_str (  ) );
    1187                 : 
    1188               0 :             continue;
    1189                 :         }
    1190                 : 
    1191                 :         /***** get the cintainer from the root *****/
    1192                 : 
    1193               6 :         ContainerPtr poKmlContainer;
    1194                 : 
    1195               6 :         if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
    1196                 :             CPLError ( CE_Failure, CPLE_OpenFailed,
    1197                 :                        "ERROR Parseing kml %s :%s %s",
    1198                 :                        pszFilename,
    1199                 :                        "This file does not fit the OGR model,",
    1200               0 :                        "there is no container element at the root." );
    1201               0 :             continue;
    1202                 :         }
    1203                 : 
    1204                 :         /***** is it a style table? *****/
    1205                 : 
    1206               6 :         if ( EQUAL ( papszDirList[iFile], "style.kml" ) ) {
    1207               0 :             ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
    1208               0 :             pszStylePath = CPLStrdup((char *) "style.kml");
    1209               0 :             continue;
    1210                 :         }
    1211                 : 
    1212                 : 
    1213                 :         /***** create the layer *****/
    1214                 : 
    1215                 :         AddLayer ( CPLGetBasename ( osFilePath.c_str() ),
    1216                 :                    poOgrSRS, wkbUnknown,
    1217               6 :                    this, poKmlRoot, poKmlContainer, osFilePath.c_str(), FALSE, bUpdate, nFiles );
    1218                 : 
    1219                 :     }
    1220                 : 
    1221              14 :     delete poOgrSRS;
    1222                 : 
    1223              14 :     CSLDestroy ( papszDirList );
    1224                 : 
    1225              14 :     if ( nLayers > 0 ) {
    1226               2 :         m_isDir = TRUE;
    1227               2 :         return TRUE;
    1228                 :     }
    1229                 : 
    1230              12 :     return FALSE;
    1231                 : }
    1232                 : 
    1233                 : /******************************************************************************
    1234                 :  Method to open a datasource
    1235                 :  
    1236                 :  Args:          pszFilename Darasource to open
    1237                 :                 bUpdate     update mode
    1238                 :  
    1239                 :  Returns:       True on success, false on failure
    1240                 : 
    1241                 : ******************************************************************************/
    1242                 : 
    1243            1038 : static int CheckIsKMZ(const char *pszFilename)
    1244                 : {
    1245            1038 :     char** papszFiles = VSIReadDir(pszFilename);
    1246            1038 :     char** papszIter = papszFiles;
    1247            1038 :     int bFoundKML = FALSE;
    1248            3066 :     while(papszIter && *papszIter)
    1249                 :     {
    1250             990 :         if (EQUAL(CPLGetExtension(*papszIter), "kml"))
    1251                 :         {
    1252               0 :             bFoundKML = TRUE;
    1253               0 :             break;
    1254                 :         }
    1255                 :         else
    1256                 :         {
    1257             990 :             CPLString osFilename(pszFilename);
    1258             990 :             osFilename += "/";
    1259             990 :             osFilename += *papszIter;
    1260             990 :             if (CheckIsKMZ(osFilename))
    1261                 :             {
    1262               0 :                 bFoundKML = TRUE;
    1263                 :                 break;
    1264               0 :             }
    1265                 :         }
    1266             990 :         papszIter ++;
    1267                 :     }
    1268            1038 :     CSLDestroy(papszFiles);
    1269            1038 :     return bFoundKML;
    1270                 : }
    1271                 : 
    1272             492 : int OGRLIBKMLDataSource::Open (
    1273                 :     const char *pszFilename,
    1274                 :     int bUpdate )
    1275                 : {
    1276                 : 
    1277             492 :     this->bUpdate = bUpdate;
    1278             492 :     pszName = CPLStrdup ( pszFilename );
    1279                 : 
    1280                 :     /***** dir *****/
    1281                 : 
    1282             492 :     VSIStatBufL sStatBuf = { };
    1283             492 :     if ( !VSIStatExL ( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) &&
    1284                 :          VSI_ISDIR ( sStatBuf.st_mode ) )
    1285              14 :         return OpenDir ( pszFilename, bUpdate );
    1286                 : 
    1287                 :    /***** kml *****/
    1288                 : 
    1289             478 :     else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
    1290              18 :         return OpenKml ( pszFilename, bUpdate );
    1291                 : 
    1292                 :     /***** kmz *****/
    1293                 : 
    1294             460 :     else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kmz" ) )
    1295               2 :         return OpenKmz ( pszFilename, bUpdate );
    1296                 : 
    1297                 :     else
    1298                 :     {
    1299                 :         char szBuffer[1024+1];
    1300             458 :         VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
    1301             458 :         if (fp == NULL)
    1302             312 :             return FALSE;
    1303                 : 
    1304             146 :         int nRead = VSIFReadL(szBuffer, 1, 1024, fp);
    1305             146 :         szBuffer[nRead] = 0;
    1306                 : 
    1307             146 :         VSIFCloseL(fp);
    1308                 : 
    1309                 :         /* Does it look like a zip file ? */
    1310             422 :         if (nRead == 1024 &&
    1311             180 :             szBuffer[0] == 0x50 && szBuffer[1] == 0x4B &&
    1312              96 :             szBuffer[2] == 0x03  && szBuffer[3] == 0x04)
    1313                 :         {
    1314              48 :             CPLString osFilename("/vsizip/");
    1315              48 :             osFilename += pszFilename;
    1316              48 :             if (!CheckIsKMZ(osFilename))
    1317              48 :                 return FALSE;
    1318                 : 
    1319               0 :             return OpenKmz ( pszFilename, bUpdate );
    1320                 :         }
    1321                 : 
    1322              98 :         if (strstr(szBuffer, "<kml>") || strstr(szBuffer, "<kml xmlns="))
    1323               0 :             return OpenKml ( pszFilename, bUpdate );
    1324                 :         
    1325              98 :         return FALSE;
    1326                 :     }
    1327                 : }
    1328                 : 
    1329                 : /******************************************************************************
    1330                 :  method to create a single file .kml ds
    1331                 :  
    1332                 :  Args:          pszFilename     the datasource to create
    1333                 :                 papszOptions    datasource creation options
    1334                 :  
    1335                 :  Returns:       True on success, false on failure
    1336                 : 
    1337                 : ******************************************************************************/
    1338                 : 
    1339               2 : int OGRLIBKMLDataSource::CreateKml (
    1340                 :     const char *pszFilename,
    1341                 :     char **papszOptions )
    1342                 : {
    1343                 : 
    1344               2 :     m_poKmlDSKml = m_poKmlFactory->CreateKml (  );
    1345               2 :     DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
    1346                 : 
    1347               2 :     m_poKmlDSKml->set_feature ( poKmlDocument );
    1348               2 :     m_poKmlDSContainer = poKmlDocument;
    1349               2 :     m_isKml = TRUE;
    1350               2 :     bUpdated = TRUE;
    1351                 : 
    1352               2 :     return true;
    1353                 : }
    1354                 : 
    1355                 : /******************************************************************************
    1356                 :  method to create a .kmz ds
    1357                 :  
    1358                 :  Args:          pszFilename     the datasource to create
    1359                 :                 papszOptions    datasource creation options
    1360                 :  
    1361                 :  Returns:       True on success, false on failure
    1362                 : 
    1363                 : ******************************************************************************/
    1364                 : 
    1365               2 : int OGRLIBKMLDataSource::CreateKmz (
    1366                 :     const char *pszFilename,
    1367                 :     char **papszOptions )
    1368                 : {
    1369                 : 
    1370                 : 
    1371                 :     /***** create the doc.kml  *****/
    1372                 : 
    1373               2 :     const char *namefield = CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1374                 : 
    1375               2 :     if ( !strcmp ( namefield, "yes" ) ) {
    1376               2 :         m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
    1377                 :     }
    1378                 : 
    1379               2 :     pszStylePath = CPLStrdup((char *) "style/style.kml");
    1380                 : 
    1381               2 :     m_isKmz = TRUE;
    1382               2 :     bUpdated = TRUE;
    1383                 : 
    1384               2 :     return TRUE;
    1385                 : }
    1386                 : 
    1387                 : /******************************************************************************
    1388                 :  Method to create a dir datasource
    1389                 :  
    1390                 :  Args:          pszFilename     the datasource to create
    1391                 :                 papszOptions    datasource creation options
    1392                 :  
    1393                 :  Returns:       True on success, false on failure
    1394                 : 
    1395                 : ******************************************************************************/
    1396                 : 
    1397               2 : int OGRLIBKMLDataSource::CreateDir (
    1398                 :     const char *pszFilename,
    1399                 :     char **papszOptions )
    1400                 : {
    1401                 : 
    1402               2 :     if ( VSIMkdir ( pszFilename, 0755 ) ) {
    1403                 :         CPLError ( CE_Failure, CPLE_AppDefined,
    1404               0 :                    "ERROR Creating dir: %s for KML datasource", pszFilename );
    1405               0 :         return FALSE;
    1406                 :     }
    1407                 : 
    1408               2 :     m_isDir = TRUE;
    1409               2 :     bUpdated = TRUE;
    1410                 : 
    1411                 : 
    1412               2 :     const char *namefield = CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1413                 : 
    1414               2 :     if ( !strcmp ( namefield, "yes" ) ) {
    1415               2 :         m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
    1416                 :     }
    1417                 : 
    1418               2 :     pszStylePath = CPLStrdup((char *) "style.kml");
    1419                 : 
    1420               2 :     return TRUE;
    1421                 : }
    1422                 : 
    1423                 : 
    1424                 : /******************************************************************************
    1425                 :  method to create a datasource
    1426                 :  
    1427                 :  Args:          pszFilename     the datasource to create
    1428                 :                 papszOptions    datasource creation options
    1429                 :  
    1430                 :  Returns:       True on success, false on failure
    1431                 :  
    1432                 :  env vars:
    1433                 :   LIBKML_USE_DOC.KML         default: yes
    1434                 :  
    1435                 : ******************************************************************************/
    1436                 : 
    1437               6 : int OGRLIBKMLDataSource::Create (
    1438                 :     const char *pszFilename,
    1439                 :     char **papszOptions )
    1440                 : {
    1441                 : 
    1442               6 :     int bResult = FALSE;
    1443                 : 
    1444               6 :     if (strcmp(pszFilename, "/dev/stdout") == 0)
    1445               0 :         pszFilename = "/vsistdout/";
    1446                 : 
    1447               6 :     pszName = CPLStrdup ( pszFilename );
    1448               6 :     bUpdate = TRUE;
    1449                 : 
    1450                 :     /***** kml *****/
    1451                 : 
    1452               6 :     if ( strcmp(pszFilename, "/vsistdout/") == 0 ||
    1453                 :          strncmp(pszFilename, "/vsigzip/", 9) == 0 ||
    1454                 :          EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
    1455               2 :         bResult = CreateKml ( pszFilename, papszOptions );
    1456                 : 
    1457                 :     /***** kmz *****/
    1458                 : 
    1459               4 :     else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kmz" ) )
    1460               2 :         bResult = CreateKmz ( pszFilename, papszOptions );
    1461                 : 
    1462                 :     /***** dir *****/
    1463                 : 
    1464                 :     else
    1465               2 :         bResult = CreateDir ( pszFilename, papszOptions );
    1466                 : 
    1467               6 :     return bResult;
    1468                 : }
    1469                 : 
    1470                 : /******************************************************************************
    1471                 :  method to get a layer by index
    1472                 :  
    1473                 :  Args:          iLayer      the index of the layer to get
    1474                 :  
    1475                 :  Returns:       pointer to the layer, or NULL if the layer does not exist
    1476                 : 
    1477                 : ******************************************************************************/
    1478                 : 
    1479              34 : OGRLayer *OGRLIBKMLDataSource::GetLayer (
    1480                 :     int iLayer )
    1481                 : {
    1482              34 :     if ( iLayer < 0 || iLayer >= nLayers )
    1483               0 :         return NULL;
    1484                 :     else
    1485              34 :         return papoLayers[iLayer];
    1486                 : 
    1487                 : }
    1488                 : 
    1489                 : /******************************************************************************
    1490                 :  method to get a layer by name
    1491                 :  
    1492                 :  Args:          pszname     name of the layer to get
    1493                 :  
    1494                 :  Returns:       pointer to the layer, or NULL if the layer does not exist
    1495                 : 
    1496                 : ******************************************************************************/
    1497                 : 
    1498              80 : OGRLayer *OGRLIBKMLDataSource::GetLayerByName (
    1499                 :     const char *pszname )
    1500                 : {
    1501              80 :     int iLayer = 0;
    1502                 : 
    1503             410 :     for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
    1504             410 :         if ( EQUAL ( pszname, papoLayers[iLayer]->GetName (  ) ) )
    1505              80 :             return papoLayers[iLayer];
    1506                 :     }
    1507                 : 
    1508               0 :     return NULL;
    1509                 : }
    1510                 : 
    1511                 : 
    1512                 : /******************************************************************************
    1513                 :  method to DeleteLayers in a .kml datasource
    1514                 :  
    1515                 :  Args:          iLayer  index of the layer to delete
    1516                 :  
    1517                 :  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
    1518                 : 
    1519                 : ******************************************************************************/
    1520                 : 
    1521               0 : OGRErr OGRLIBKMLDataSource::DeleteLayerKml (
    1522                 :     int iLayer )
    1523                 : {
    1524               0 :     OGRLIBKMLLayer *poOgrLayer = ( OGRLIBKMLLayer * ) papoLayers[iLayer];
    1525                 : 
    1526                 :     /***** loop over the features *****/
    1527                 : 
    1528               0 :     size_t nKmlFeatures = m_poKmlDSContainer->get_feature_array_size (  );
    1529                 :     size_t iKmlFeature;
    1530                 : 
    1531               0 :     for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
    1532                 :         FeaturePtr poKmlFeat =
    1533               0 :             m_poKmlDSContainer->get_feature_array_at ( iKmlFeature );
    1534                 : 
    1535               0 :         if ( poKmlFeat == poOgrLayer->GetKmlLayer (  ) ) {
    1536               0 :             m_poKmlDSContainer->DeleteFeatureAt ( iKmlFeature );
    1537                 :             break;
    1538                 :         }
    1539                 : 
    1540                 :     }
    1541                 : 
    1542                 : 
    1543               0 :     return OGRERR_NONE;
    1544                 : }
    1545                 : 
    1546                 : /******************************************************************************
    1547                 :  method to DeleteLayers in a .kmz datasource
    1548                 :  
    1549                 :  Args:          iLayer  index of the layer to delete
    1550                 :  
    1551                 :  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
    1552                 : 
    1553                 : ******************************************************************************/
    1554                 : 
    1555               0 : OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
    1556                 :     int iLayer )
    1557                 : {
    1558               0 :     OGRLIBKMLLayer *poOgrLayer = ( OGRLIBKMLLayer * ) papoLayers[iLayer];
    1559                 : 
    1560                 :     const char *pszUseDocKml =
    1561               0 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1562                 : 
    1563               0 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
    1564                 : 
    1565                 :         /***** loop over the features *****/
    1566                 : 
    1567               0 :         size_t nKmlFeatures = m_poKmlDocKml->get_feature_array_size (  );
    1568                 :         size_t iKmlFeature;
    1569                 : 
    1570               0 :         for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
    1571                 :             FeaturePtr poKmlFeat =
    1572               0 :                 m_poKmlDocKml->get_feature_array_at ( iKmlFeature );
    1573                 : 
    1574               0 :             if ( poKmlFeat->IsA ( kmldom::Type_NetworkLink ) ) {
    1575               0 :                 NetworkLinkPtr poKmlNetworkLink = AsNetworkLink ( poKmlFeat );
    1576                 : 
    1577                 :                 /***** does it have a link? *****/
    1578                 : 
    1579               0 :                 if ( poKmlNetworkLink->has_link (  ) ) {
    1580               0 :                     LinkPtr poKmlLink = poKmlNetworkLink->get_link (  );
    1581                 : 
    1582                 :                     /***** does the link have a href? *****/
    1583                 : 
    1584               0 :                     if ( poKmlLink->has_href (  ) ) {
    1585                 :                         kmlengine::Href * poKmlHref =
    1586               0 :                             new kmlengine::Href ( poKmlLink->get_href (  ) );
    1587                 : 
    1588                 :                         /***** is the link relative? *****/
    1589                 : 
    1590               0 :                         if ( poKmlHref->IsRelativePath (  ) ) {
    1591                 : 
    1592                 :                             const char *pszLink =
    1593               0 :                                 poKmlHref->get_path (  ).c_str (  );
    1594                 : 
    1595               0 :                             if ( EQUAL
    1596                 :                                  ( pszLink, poOgrLayer->GetFileName (  ) ) ) {
    1597               0 :                                 m_poKmlDocKml->DeleteFeatureAt ( iKmlFeature );
    1598                 :                                 break;
    1599                 :                             }
    1600                 : 
    1601                 : 
    1602                 :                         }
    1603               0 :                     }
    1604               0 :                 }
    1605                 :             }
    1606                 :         }
    1607                 : 
    1608                 :     }
    1609                 : 
    1610               0 :     return OGRERR_NONE;
    1611                 : }
    1612                 : 
    1613                 : /******************************************************************************
    1614                 :  method to delete a layer in a datasource
    1615                 :  
    1616                 :  Args:          iLayer  index of the layer to delete
    1617                 :  
    1618                 :  Returns:       OGRERR_NONE on success, OGRERR_FAILURE on failure
    1619                 : 
    1620                 : ******************************************************************************/
    1621                 : 
    1622               0 : OGRErr OGRLIBKMLDataSource::DeleteLayer (
    1623                 :     int iLayer )
    1624                 : {
    1625                 : 
    1626               0 :     if ( !bUpdate )
    1627               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    1628                 : 
    1629               0 :     if ( iLayer >= nLayers )
    1630               0 :         return OGRERR_FAILURE;
    1631                 : 
    1632               0 :     if ( IsKml (  ) )
    1633               0 :         DeleteLayerKml ( iLayer );
    1634                 : 
    1635               0 :     else if ( IsKmz (  ) )
    1636               0 :         DeleteLayerKmz ( iLayer );
    1637                 : 
    1638               0 :     else if ( IsDir (  ) ) {
    1639               0 :         DeleteLayerKmz ( iLayer );
    1640                 : 
    1641                 :         /***** delete the file the layer corisponds to *****/
    1642                 : 
    1643                 :         const char *pszFilePath =
    1644               0 :             CPLFormFilename ( pszName, papoLayers[iLayer]->GetFileName (  ),
    1645               0 :                               NULL );
    1646               0 :         VSIStatBufL oStatBufL = { };
    1647               0 :         if ( !VSIStatL ( pszFilePath, &oStatBufL ) ) {
    1648               0 :             if ( VSIUnlink ( pszFilePath ) ) {
    1649                 :                 CPLError ( CE_Failure, CPLE_AppDefined,
    1650                 :                            "ERROR Deleteing Layer %s from filesystem as %s",
    1651               0 :                            papoLayers[iLayer]->GetName (  ), pszFilePath );
    1652                 :             }
    1653                 :         }
    1654                 :     }
    1655                 : 
    1656                 : 
    1657               0 :     delete papoLayers[iLayer];
    1658                 :     memmove ( papoLayers + iLayer, papoLayers + iLayer + 1,
    1659               0 :               sizeof ( void * ) * ( nLayers - iLayer - 1 ) );
    1660               0 :     nLayers--;
    1661               0 :     bUpdated = TRUE;
    1662                 : 
    1663               0 :     return OGRERR_NONE;
    1664                 : }
    1665                 : 
    1666                 : /******************************************************************************
    1667                 :  method to create a layer in a single file .kml
    1668                 :  
    1669                 :  Args:          pszLayerName    name of the layer to create
    1670                 :                 poOgrSRS        the SRS of the layer
    1671                 :                 eGType          the layers geometry type
    1672                 :                 papszOptions    layer creation options
    1673                 :  
    1674                 :  Returns:       return a pointer to the new layer or NULL on failure
    1675                 : 
    1676                 : ******************************************************************************/
    1677                 : 
    1678               4 : OGRLayer *OGRLIBKMLDataSource::CreateLayerKml (
    1679                 :     const char *pszLayerName,
    1680                 :     OGRSpatialReference * poOgrSRS,
    1681                 :     OGRwkbGeometryType eGType,
    1682                 :     char **papszOptions )
    1683                 : {
    1684                 : 
    1685               4 :     OGRLIBKMLLayer *poOgrLayer = NULL;
    1686                 : 
    1687               4 :     DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
    1688                 : 
    1689               4 :     m_poKmlDSContainer->add_feature ( poKmlDocument );
    1690                 : 
    1691                 :     /***** create the layer *****/
    1692                 : 
    1693                 :     poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
    1694               4 :                             NULL, poKmlDocument, "", TRUE, bUpdate, 1 );
    1695                 : 
    1696                 :     /***** add the layer name as a <Name> *****/
    1697                 : 
    1698               4 :     poKmlDocument->set_name ( pszLayerName );
    1699                 : 
    1700               4 :     return ( OGRLayer * ) poOgrLayer;
    1701                 : }
    1702                 : 
    1703                 : /******************************************************************************
    1704                 :  method to create a layer in a .kmz or dir
    1705                 :  
    1706                 :  Args:          pszLayerName    name of the layer to create
    1707                 :                 poOgrSRS        the SRS of the layer
    1708                 :                 eGType          the layers geometry type
    1709                 :                 papszOptions    layer creation options
    1710                 :  
    1711                 :  Returns:       return a pointer to the new layer or NULL on failure
    1712                 : 
    1713                 : ******************************************************************************/
    1714                 : 
    1715               8 : OGRLayer *OGRLIBKMLDataSource::CreateLayerKmz (
    1716                 :     const char *pszLayerName,
    1717                 :     OGRSpatialReference * poOgrSRS,
    1718                 :     OGRwkbGeometryType eGType,
    1719                 :     char **papszOptions )
    1720                 : {
    1721                 : 
    1722                 :     /***** add a network link to doc.kml *****/
    1723                 : 
    1724                 :     const char *pszUseDocKml =
    1725               8 :         CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
    1726                 : 
    1727               8 :     if ( EQUAL ( pszUseDocKml, "yes" ) && m_poKmlDocKml ) {
    1728                 : 
    1729               8 :         DocumentPtr poKmlDocument = AsDocument ( m_poKmlDocKml );
    1730                 : 
    1731               8 :         NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink (  );
    1732               8 :         LinkPtr poKmlLink = m_poKmlFactory->CreateLink (  );
    1733                 : 
    1734               8 :         std::string oHref;
    1735               8 :         oHref.append ( pszLayerName );
    1736               8 :         oHref.append ( ".kml" );
    1737               8 :         poKmlLink->set_href ( oHref );
    1738                 : 
    1739               8 :         poKmlNetLink->set_link ( poKmlLink );
    1740               8 :         poKmlDocument->add_feature ( poKmlNetLink );
    1741                 : 
    1742                 :     }
    1743                 : 
    1744                 :     /***** create the layer *****/
    1745                 : 
    1746               8 :     OGRLIBKMLLayer *poOgrLayer = NULL;
    1747                 : 
    1748               8 :     DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
    1749                 : 
    1750                 :     poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
    1751                 :                             NULL, poKmlDocument,
    1752                 :                             CPLFormFilename ( NULL, pszLayerName, ".kml" ),
    1753               8 :                             TRUE, bUpdate, 1 );
    1754                 : 
    1755                 :     /***** add the layer name as a <Name> *****/
    1756                 : 
    1757               8 :     poKmlDocument->set_name ( pszLayerName );
    1758                 : 
    1759               8 :     return ( OGRLayer * ) poOgrLayer;
    1760                 : }
    1761                 : 
    1762                 : /******************************************************************************
    1763                 :  CreateLayer()
    1764                 :  
    1765                 :  Args:          pszLayerName    name of the layer to create
    1766                 :                 poOgrSRS        the SRS of the layer
    1767                 :                 eGType          the layers geometry type
    1768                 :                 papszOptions    layer creation options
    1769                 :  
    1770                 :  Returns:       return a pointer to the new layer or NULL on failure
    1771                 : 
    1772                 : ******************************************************************************/
    1773                 : 
    1774              12 : OGRLayer *OGRLIBKMLDataSource::CreateLayer (
    1775                 :     const char *pszLayerName,
    1776                 :     OGRSpatialReference * poOgrSRS,
    1777                 :     OGRwkbGeometryType eGType,
    1778                 :     char **papszOptions )
    1779                 : {
    1780                 : 
    1781              12 :     if ( !bUpdate )
    1782               0 :         return NULL;
    1783                 : 
    1784              12 :     OGRLayer *poOgrLayer = NULL;
    1785                 : 
    1786                 :     /***** kml DS *****/
    1787                 : 
    1788              12 :     if ( IsKml (  ) ) {
    1789                 :         poOgrLayer = CreateLayerKml ( pszLayerName, poOgrSRS,
    1790               4 :                                       eGType, papszOptions );
    1791                 : 
    1792                 :     }
    1793                 : 
    1794               8 :     else if ( IsKmz (  ) || IsDir (  ) ) {
    1795                 :         poOgrLayer = CreateLayerKmz ( pszLayerName, poOgrSRS,
    1796               8 :                                       eGType, papszOptions );
    1797                 : 
    1798                 :     }
    1799                 : 
    1800                 : 
    1801                 : 
    1802                 : 
    1803                 :     /***** mark the dataset as updated *****/
    1804                 : 
    1805              12 :     if ( poOgrLayer )
    1806              12 :         bUpdated = TRUE;
    1807                 : 
    1808              12 :     return poOgrLayer;
    1809                 : }
    1810                 : 
    1811                 : /******************************************************************************
    1812                 :  method to get a datasources style table
    1813                 :  
    1814                 :  Args:          none
    1815                 :  
    1816                 :  Returns:       pointer to the datasources style table, or NULL if it does
    1817                 :                 not have one
    1818                 : 
    1819                 : ******************************************************************************/
    1820                 : 
    1821               0 : OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable (
    1822                 :      )
    1823                 : {
    1824                 : 
    1825               0 :     return m_poStyleTable;
    1826                 : }
    1827                 : 
    1828                 : /******************************************************************************
    1829                 :   method to write a style table to a single file .kml ds
    1830                 :  
    1831                 :  Args:          poStyleTable    pointer to the style table to add
    1832                 :  
    1833                 :  Returns:       nothing
    1834                 : 
    1835                 : ******************************************************************************/
    1836                 : 
    1837               0 : void OGRLIBKMLDataSource::SetStyleTable2Kml (
    1838                 :     OGRStyleTable * poStyleTable )
    1839                 : {
    1840                 : 
    1841                 :     /***** delete all the styles *****/
    1842                 : 
    1843               0 :     DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
    1844               0 :     size_t nKmlStyles = poKmlDocument->get_styleselector_array_size (  );
    1845                 :     int iKmlStyle;
    1846                 : 
    1847               0 :     for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
    1848               0 :         poKmlDocument->DeleteStyleSelectorAt ( iKmlStyle );
    1849                 :     }
    1850                 : 
    1851                 :     /***** add the new style table to the document *****/
    1852                 : 
    1853                 :     styletable2kml ( poStyleTable, m_poKmlFactory,
    1854               0 :                      AsContainer ( poKmlDocument ) );
    1855                 : 
    1856               0 :     return;
    1857                 : }
    1858                 : 
    1859                 : /******************************************************************************
    1860                 :  method to write a style table to a kmz ds
    1861                 :  
    1862                 :  Args:          poStyleTable    pointer to the style table to add
    1863                 :  
    1864                 :  Returns:       nothing
    1865                 : 
    1866                 : ******************************************************************************/
    1867                 : 
    1868               0 : void OGRLIBKMLDataSource::SetStyleTable2Kmz (
    1869                 :     OGRStyleTable * poStyleTable )
    1870                 : {
    1871                 : 
    1872                 :     /***** replace the style document with a new one *****/
    1873                 : 
    1874               0 :     m_poKmlStyleKml = m_poKmlFactory->CreateDocument (  );
    1875                 : 
    1876               0 :     styletable2kml ( poStyleTable, m_poKmlFactory, m_poKmlStyleKml );
    1877                 : 
    1878                 :     return;
    1879                 : }
    1880                 : 
    1881                 : /******************************************************************************
    1882                 :  method to write a style table to a datasource
    1883                 :  
    1884                 :  Args:          poStyleTable    pointer to the style table to add
    1885                 :  
    1886                 :  Returns:       nothing
    1887                 : 
    1888                 :  note: this method assumes ownership of the style table
    1889                 :  
    1890                 : ******************************************************************************/
    1891                 : 
    1892               0 : void OGRLIBKMLDataSource::SetStyleTableDirectly (
    1893                 :     OGRStyleTable * poStyleTable )
    1894                 : {
    1895                 : 
    1896               0 :     if ( !bUpdate )
    1897               0 :         return;
    1898                 : 
    1899               0 :     if ( m_poStyleTable )
    1900               0 :         delete m_poStyleTable;
    1901                 : 
    1902               0 :     m_poStyleTable = poStyleTable;
    1903                 : 
    1904                 :     /***** a kml datasource? *****/
    1905                 : 
    1906               0 :     if ( IsKml (  ) )
    1907               0 :         SetStyleTable2Kml ( m_poStyleTable );
    1908                 : 
    1909               0 :     else if ( IsKmz (  ) || IsDir (  ) )
    1910               0 :         SetStyleTable2Kmz ( m_poStyleTable );
    1911                 : 
    1912               0 :     bUpdated = TRUE;
    1913                 : 
    1914                 : 
    1915                 : 
    1916                 : 
    1917               0 :     return;
    1918                 : }
    1919                 : 
    1920                 : /******************************************************************************
    1921                 :  method to write a style table to a datasource
    1922                 :  
    1923                 :  Args:          poStyleTable    pointer to the style table to add
    1924                 :  
    1925                 :  Returns:       nothing
    1926                 : 
    1927                 :  note:  this method copys the style table, and the user will still be
    1928                 :         responsible for its destruction
    1929                 : 
    1930                 : ******************************************************************************/
    1931                 : 
    1932               0 : void OGRLIBKMLDataSource::SetStyleTable (
    1933                 :     OGRStyleTable * poStyleTable )
    1934                 : {
    1935                 : 
    1936               0 :     if ( !bUpdate )
    1937               0 :         return;
    1938                 : 
    1939               0 :     if ( poStyleTable )
    1940               0 :         SetStyleTableDirectly ( poStyleTable->Clone (  ) );
    1941                 :     else
    1942               0 :         SetStyleTableDirectly ( NULL );
    1943               0 :     return;
    1944                 : }
    1945                 : 
    1946                 : 
    1947                 : /******************************************************************************
    1948                 :  Test if capability is available.
    1949                 : 
    1950                 :  Args:          pszCap  datasource capability name to test
    1951                 :  
    1952                 :  Returns:       nothing
    1953                 : 
    1954                 :  ODsCCreateLayer: True if this datasource can create new layers.
    1955                 :  ODsCDeleteLayer: True if this datasource can delete existing layers.
    1956                 :  
    1957                 : ******************************************************************************/
    1958                 : 
    1959               0 : int OGRLIBKMLDataSource::TestCapability (
    1960                 :     const char *pszCap )
    1961                 : {
    1962                 : 
    1963               0 :     if ( EQUAL ( pszCap, ODsCCreateLayer ) )
    1964               0 :         return bUpdate;
    1965               0 :     else if ( EQUAL ( pszCap, ODsCDeleteLayer ) )
    1966               0 :         return bUpdate;
    1967                 :     else
    1968               0 :         return FALSE;
    1969                 : 
    1970            4029 : }

Generated by: LCOV version 1.7