int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QgsApplication qgsapp( argc, argv, getenv( "DISPLAY" ) ); //Default prefix path may be altered by environment variable char* prefixPath = getenv( "QGIS_PREFIX_PATH" ); if ( prefixPath ) { QgsApplication::setPrefixPath( prefixPath, TRUE ); } #if !defined(Q_OS_WIN) else { // init QGIS's paths - true means that all path will be inited from prefix QgsApplication::setPrefixPath( CMAKE_INSTALL_PREFIX, TRUE ); } #endif QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars ); // Instantiate the plugin directory so that providers are loaded QgsProviderRegistry::instance( QgsApplication::pluginPath() ); QgsDebugMsg( "Prefix PATH: " + QgsApplication::prefixPath() ); QgsDebugMsg( "Plugin PATH: " + QgsApplication::pluginPath() ); QgsDebugMsg( "PkgData PATH: " + QgsApplication::pkgDataPath() ); QgsDebugMsg( "User DB PATH: " + QgsApplication::qgisUserDbFilePath() ); QgsDebugMsg( qgsapp.applicationDirPath() + "/qgis_wms_server.log" ); //create config cache and search for config files in the current directory. //These configurations are used if no mapfile parameter is present in the request QString defaultConfigFilePath; QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory if ( projectFileInfo.exists() ) { defaultConfigFilePath = projectFileInfo.absoluteFilePath(); } else { QFileInfo adminSLDFileInfo = defaultAdminSLD(); if ( adminSLDFileInfo.exists() ) { defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath(); } } //create cache for capabilities XML QgsCapabilitiesCache capabilitiesCache; //creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop QgsMapRenderer* theMapRenderer = new QgsMapRenderer(); theMapRenderer->setLabelingEngine( new QgsPalLabeling() ); while ( fcgi_accept() >= 0 ) { printRequestInfos(); //print request infos if in debug mode //use QgsGetRequestHandler in case of HTTP GET and QgsSOAPRequestHandler in case of HTTP POST QgsRequestHandler* theRequestHandler = 0; char* requestMethod = getenv( "REQUEST_METHOD" ); if ( requestMethod != NULL ) { if ( strcmp( requestMethod, "POST" ) == 0 ) { //QgsDebugMsg( "Creating QgsSOAPRequestHandler" ); //theRequestHandler = new QgsSOAPRequestHandler(); theRequestHandler = new QgsPostRequestHandler(); } else { QgsDebugMsg( "Creating QgsGetRequestHandler" ); theRequestHandler = new QgsGetRequestHandler(); } } else { QgsDebugMsg( "Creating QgsGetRequestHandler" ); theRequestHandler = new QgsGetRequestHandler(); } QMap<QString, QString> parameterMap; try { parameterMap = theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsDebugMsg( "An exception was thrown during input parsing" ); theRequestHandler->sendServiceException( e ); continue; } QMap<QString, QString>::const_iterator paramIt; //set admin config file to wms server object QString configFilePath( defaultConfigFilePath ); paramIt = parameterMap.find( "MAP" ); if ( paramIt == parameterMap.constEnd() ) { QgsDebugMsg( QString( "Using default configuration file path: %1" ).arg( defaultConfigFilePath ) ); } else { configFilePath = paramIt.value(); } QgsConfigParser* adminConfigParser = QgsConfigCache::instance()->searchConfiguration( configFilePath ); if ( !adminConfigParser ) { QgsDebugMsg( "parse error on config file " + configFilePath ); theRequestHandler->sendServiceException( QgsMapServiceException( "", "Configuration file problem : perhaps you left off the .qgs extension?" ) ); continue; } //sld parser might need information about request parameters adminConfigParser->setParameterMap( parameterMap ); //request to WMS? QString serviceString; paramIt = parameterMap.find( "SERVICE" ); if ( paramIt == parameterMap.constEnd() ) { #ifndef QGISDEBUG serviceString = parameterMap.value( "SERVICE", "WMS" ); #else QgsDebugMsg( "unable to find 'SERVICE' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) ); delete theRequestHandler; continue; #endif } else { serviceString = paramIt.value(); } QgsWMSServer* theServer = 0; if ( serviceString == "WFS" ) { delete theServer; QgsWFSServer* theServer = 0; try { theServer = new QgsWFSServer( parameterMap ); } catch ( QgsMapServiceException e ) //admin.sld may be invalid { theRequestHandler->sendServiceException( e ); continue; } theServer->setAdminConfigParser( adminConfigParser ); //request type QString request = parameterMap.value( "REQUEST" ); if ( request.isEmpty() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); delete theRequestHandler; delete theServer; continue; } if ( request.toLower() == QString( "GetCapabilities" ).toLower() ) { QDomDocument capabilitiesDocument; try { capabilitiesDocument = theServer->getCapabilities(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending GetCapabilities response" ); theRequestHandler->sendGetCapabilitiesResponse( capabilitiesDocument ); delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "DescribeFeatureType" ).toLower() ) { QDomDocument describeDocument; try { describeDocument = theServer->describeFeatureType(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending GetCapabilities response" ); theRequestHandler->sendGetCapabilitiesResponse( describeDocument ); delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "GetFeature" ).toLower() ) { //output format for GetFeature QString outputFormat = parameterMap.value( "OUTPUTFORMAT" ); try { if ( theServer->getFeature( *theRequestHandler, outputFormat ) != 0 ) { delete theRequestHandler; delete theServer; continue; } else { delete theRequestHandler; delete theServer; continue; } } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } } else if ( request.toLower() == QString( "Transaction" ).toLower() ) { QDomDocument transactionDocument; try { transactionDocument = theServer->transaction( parameterMap.value( "REQUEST_BODY" ) ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending Transaction response" ); theRequestHandler->sendGetCapabilitiesResponse( transactionDocument ); delete theRequestHandler; delete theServer; continue; } return 0; } try { theServer = new QgsWMSServer( parameterMap, theMapRenderer ); } catch ( QgsMapServiceException e ) //admin.sld may be invalid { theRequestHandler->sendServiceException( e ); continue; } theServer->setAdminConfigParser( adminConfigParser ); //request type QString request = parameterMap.value( "REQUEST" ); if ( request.isEmpty() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); delete theRequestHandler; delete theServer; continue; } QString version = parameterMap.value( "VERSION", "1.3.0" ); bool getProjectSettings = ( request.toLower() == QString( "GetProjectSettings" ).toLower() ); if ( getProjectSettings ) { version = "1.3.0"; //getProjectSettings extends WMS 1.3.0 capabilities } if ( request.toLower() == QString( "GetCapabilities" ).toLower() || getProjectSettings ) { const QDomDocument* capabilitiesDocument = capabilitiesCache.searchCapabilitiesDocument( configFilePath, getProjectSettings ? "projectSettings" : version ); if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one { QgsDebugMsg( "Capabilities document not found in cache" ); QDomDocument doc; try { doc = theServer->getCapabilities( version, getProjectSettings ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } capabilitiesCache.insertCapabilitiesDocument( configFilePath, getProjectSettings ? "projectSettings" : version, &doc ); capabilitiesDocument = capabilitiesCache.searchCapabilitiesDocument( configFilePath, getProjectSettings ? "projectSettings" : version ); } else { QgsDebugMsg( "Found capabilities document in cache" ); } if ( capabilitiesDocument ) { theRequestHandler->sendGetCapabilitiesResponse( *capabilitiesDocument ); } delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "GetMap" ).toLower() ) { QImage* result = 0; try { result = theServer->getMap(); } catch ( QgsMapServiceException& ex ) { QgsDebugMsg( "Caught exception during GetMap request" ); theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } if ( result ) { QgsDebugMsg( "Sending GetMap response" ); theRequestHandler->sendGetMapResponse( serviceString, result ); QgsDebugMsg( "Response sent" ); } else { //do some error handling QgsDebugMsg( "result image is 0" ); } delete result; delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "GetFeatureInfo" ).toLower() ) { QDomDocument featureInfoDoc; try { if ( theServer->getFeatureInfo( featureInfoDoc, version ) != 0 ) { delete theRequestHandler; delete theServer; continue; } } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QString infoFormat = parameterMap.value( "INFO_FORMAT" ); theRequestHandler->sendGetFeatureInfoResponse( featureInfoDoc, infoFormat ); delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "GetStyles" ).toLower() || request.toLower() == QString( "GetStyle" ).toLower() ) // GetStyle for compatibility with earlier QGIS versions { try { QDomDocument doc = theServer->getStyle(); theRequestHandler->sendGetStyleResponse( doc ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "GetLegendGraphic" ).toLower() || request.toLower() == QString( "GetLegendGraphics" ).toLower() ) // GetLegendGraphics for compatibility with earlier QGIS versions { QImage* result = 0; try { result = theServer->getLegendGraphics(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } if ( result ) { QgsDebugMsg( "Sending GetLegendGraphic response" ); //sending is the same for GetMap and GetLegendGraphic theRequestHandler->sendGetMapResponse( serviceString, result ); } else { //do some error handling QgsDebugMsg( "result image is 0" ); } delete result; delete theRequestHandler; delete theServer; continue; } else if ( request.toLower() == QString( "GetPrint" ).toLower() ) { QByteArray* printOutput = 0; try { printOutput = theServer->getPrint( theRequestHandler->format() ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } if ( printOutput ) { theRequestHandler->sendGetPrintResponse( printOutput ); } delete printOutput; delete theRequestHandler; delete theServer; continue; } else//unknown request { QgsMapServiceException e( "OperationNotSupported", "Operation " + request + " not supported" ); theRequestHandler->sendServiceException( e ); delete theRequestHandler; delete theServer; } } delete theMapRenderer; QgsDebugMsg( "************* all done ***************" ); return 0; }
int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QgsApplication qgsapp( argc, argv, getenv( "DISPLAY" ) ); //Default prefix path may be altered by environment variable QgsApplication::init(); #if defined(MAPSERVER_SKIP_ECW) QgsDebugMsg( "Skipping GDAL ECW drivers in server." ); QgsApplication::skipGdalDriver( "ECW" ); QgsApplication::skipGdalDriver( "JP2ECW" ); #endif QSettings settings; QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance(); QNetworkDiskCache *cache = new QNetworkDiskCache( 0 ); QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString(); qint64 cacheSize = settings.value( "cache/size", 50 * 1024 * 1024 ).toULongLong(); QgsDebugMsg( QString( "setCacheDirectory: %1" ).arg( cacheDirectory ) ); QgsDebugMsg( QString( "setMaximumCacheSize: %1" ).arg( cacheSize ) ); cache->setCacheDirectory( cacheDirectory ); cache->setMaximumCacheSize( cacheSize ); QgsDebugMsg( QString( "cacheDirectory: %1" ).arg( cache->cacheDirectory() ) ); QgsDebugMsg( QString( "maximumCacheSize: %1" ).arg( cache->maximumCacheSize() ) ); nam->setCache( cache ); QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars ); // Instantiate the plugin directory so that providers are loaded QgsProviderRegistry::instance( QgsApplication::pluginPath() ); QgsDebugMsg( "Prefix PATH: " + QgsApplication::prefixPath() ); QgsDebugMsg( "Plugin PATH: " + QgsApplication::pluginPath() ); QgsDebugMsg( "PkgData PATH: " + QgsApplication::pkgDataPath() ); QgsDebugMsg( "User DB PATH: " + QgsApplication::qgisUserDbFilePath() ); QgsDebugMsg( qgsapp.applicationDirPath() + "/qgis_wms_server.log" ); QgsApplication::createDB(); //init qgis.db (e.g. necessary for user crs) //create config cache and search for config files in the current directory. //These configurations are used if no mapfile parameter is present in the request QString defaultConfigFilePath; QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory if ( projectFileInfo.exists() ) { defaultConfigFilePath = projectFileInfo.absoluteFilePath(); QgsDebugMsg( "Using default project file: " + defaultConfigFilePath ); } else { QFileInfo adminSLDFileInfo = defaultAdminSLD(); if ( adminSLDFileInfo.exists() ) { defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath(); } } //create cache for capabilities XML QgsCapabilitiesCache capabilitiesCache; //creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop QgsMapRenderer* theMapRenderer = new QgsMapRenderer(); theMapRenderer->setLabelingEngine( new QgsPalLabeling() ); #ifdef QGSMSDEBUG QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" ); #endif while ( fcgi_accept() >= 0 ) { printRequestInfos(); //print request infos if in debug mode //use QgsGetRequestHandler in case of HTTP GET and QgsSOAPRequestHandler in case of HTTP POST QgsRequestHandler* theRequestHandler = 0; char* requestMethod = getenv( "REQUEST_METHOD" ); if ( requestMethod != NULL ) { if ( strcmp( requestMethod, "POST" ) == 0 ) { //QgsDebugMsg( "Creating QgsSOAPRequestHandler" ); //theRequestHandler = new QgsSOAPRequestHandler(); theRequestHandler = new QgsPostRequestHandler(); } else { QgsDebugMsg( "Creating QgsGetRequestHandler" ); theRequestHandler = new QgsGetRequestHandler(); } } else { QgsDebugMsg( "Creating QgsGetRequestHandler" ); theRequestHandler = new QgsGetRequestHandler(); } QMap<QString, QString> parameterMap; try { parameterMap = theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsDebugMsg( "An exception was thrown during input parsing" ); theRequestHandler->sendServiceException( e ); continue; } QMap<QString, QString>::const_iterator paramIt; //set admin config file to wms server object QString configFilePath( defaultConfigFilePath ); QString projectFile = getenv( "QGIS_PROJECT_FILE" ); if ( !projectFile.isEmpty() ) { configFilePath = projectFile; } else { paramIt = parameterMap.find( "MAP" ); if ( paramIt == parameterMap.constEnd() ) { QgsDebugMsg( QString( "Using default configuration file path: %1" ).arg( defaultConfigFilePath ) ); } else { configFilePath = paramIt.value(); } } QgsConfigParser* adminConfigParser = QgsConfigCache::instance()->searchConfiguration( configFilePath ); if ( !adminConfigParser ) { QgsDebugMsg( "parse error on config file " + configFilePath ); theRequestHandler->sendServiceException( QgsMapServiceException( "", "Configuration file problem : perhaps you left off the .qgs extension?" ) ); continue; } //sld parser might need information about request parameters adminConfigParser->setParameterMap( parameterMap ); //request to WMS? QString serviceString; paramIt = parameterMap.find( "SERVICE" ); if ( paramIt == parameterMap.constEnd() ) { #ifndef QGISDEBUG serviceString = parameterMap.value( "SERVICE", "WMS" ); #else QgsDebugMsg( "unable to find 'SERVICE' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) ); delete theRequestHandler; continue; #endif } else { serviceString = paramIt.value(); } QgsWMSServer* theServer = 0; if ( serviceString == "WCS" ) { delete theServer; QgsWCSServer* theServer = 0; try { theServer = new QgsWCSServer( parameterMap ); } catch ( const QgsMapServiceException &e ) //admin.sld may be invalid { theRequestHandler->sendServiceException( e ); continue; } theServer->setAdminConfigParser( adminConfigParser ); //request type QString request = parameterMap.value( "REQUEST" ); if ( request.isEmpty() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); delete theRequestHandler; delete theServer; continue; } if ( request.compare( "GetCapabilities", Qt::CaseInsensitive ) == 0 ) { QDomDocument capabilitiesDocument; try { capabilitiesDocument = theServer->getCapabilities(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending GetCapabilities response" ); theRequestHandler->sendGetCapabilitiesResponse( capabilitiesDocument ); delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "DescribeCoverage", Qt::CaseInsensitive ) == 0 ) { QDomDocument describeDocument; try { describeDocument = theServer->describeCoverage(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending GetCapabilities response" ); theRequestHandler->sendGetCapabilitiesResponse( describeDocument ); delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetCoverage", Qt::CaseInsensitive ) == 0 ) { QByteArray* coverageOutput; try { coverageOutput = theServer->getCoverage(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } if ( coverageOutput ) { theRequestHandler->sendGetCoverageResponse( coverageOutput ); } delete theRequestHandler; delete theServer; continue; } } else if ( serviceString == "WFS" ) { delete theServer; QgsWFSServer* theServer = 0; try { theServer = new QgsWFSServer( parameterMap ); } catch ( const QgsMapServiceException &e ) //admin.sld may be invalid { theRequestHandler->sendServiceException( e ); continue; } theServer->setAdminConfigParser( adminConfigParser ); //request type QString request = parameterMap.value( "REQUEST" ); if ( request.isEmpty() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); delete theRequestHandler; delete theServer; continue; } if ( request.compare( "GetCapabilities", Qt::CaseInsensitive ) == 0 ) { QDomDocument capabilitiesDocument; try { capabilitiesDocument = theServer->getCapabilities(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending GetCapabilities response" ); theRequestHandler->sendGetCapabilitiesResponse( capabilitiesDocument ); delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "DescribeFeatureType", Qt::CaseInsensitive ) == 0 ) { QDomDocument describeDocument; try { describeDocument = theServer->describeFeatureType(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending GetCapabilities response" ); theRequestHandler->sendGetCapabilitiesResponse( describeDocument ); delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetFeature", Qt::CaseInsensitive ) == 0 ) { //output format for GetFeature QString outputFormat = parameterMap.value( "OUTPUTFORMAT" ); try { theServer->getFeature( *theRequestHandler, outputFormat ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "Transaction", Qt::CaseInsensitive ) == 0 ) { QDomDocument transactionDocument; try { transactionDocument = theServer->transaction( parameterMap.value( "REQUEST_BODY" ) ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QgsDebugMsg( "sending Transaction response" ); theRequestHandler->sendGetCapabilitiesResponse( transactionDocument ); delete theRequestHandler; delete theServer; continue; } return 0; } try { theServer = new QgsWMSServer( parameterMap, theMapRenderer ); } catch ( const QgsMapServiceException &e ) //admin.sld may be invalid { theRequestHandler->sendServiceException( e ); continue; } adminConfigParser->loadLabelSettings( theMapRenderer->labelingEngine() ); theServer->setAdminConfigParser( adminConfigParser ); //request type QString request = parameterMap.value( "REQUEST" ); if ( request.isEmpty() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); delete theRequestHandler; delete theServer; continue; } QString version = parameterMap.value( "VERSION", "1.3.0" ); bool getProjectSettings = ( request.compare( "GetProjectSettings", Qt::CaseInsensitive ) == 0 ); if ( getProjectSettings ) { version = "1.3.0"; //getProjectSettings extends WMS 1.3.0 capabilities } if ( request.compare( "GetCapabilities", Qt::CaseInsensitive ) == 0 || getProjectSettings ) { const QDomDocument* capabilitiesDocument = capabilitiesCache.searchCapabilitiesDocument( configFilePath, getProjectSettings ? "projectSettings" : version ); if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one { QgsDebugMsg( "Capabilities document not found in cache" ); QDomDocument doc; try { doc = theServer->getCapabilities( version, getProjectSettings ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } capabilitiesCache.insertCapabilitiesDocument( configFilePath, getProjectSettings ? "projectSettings" : version, &doc ); capabilitiesDocument = capabilitiesCache.searchCapabilitiesDocument( configFilePath, getProjectSettings ? "projectSettings" : version ); } else { QgsDebugMsg( "Found capabilities document in cache" ); } if ( capabilitiesDocument ) { theRequestHandler->sendGetCapabilitiesResponse( *capabilitiesDocument ); } delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetMap", Qt::CaseInsensitive ) == 0 ) { QImage* result = 0; try { result = theServer->getMap(); } catch ( QgsMapServiceException& ex ) { QgsDebugMsg( "Caught exception during GetMap request" ); theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } if ( result ) { QgsDebugMsg( "Sending GetMap response" ); theRequestHandler->sendGetMapResponse( serviceString, result ); QgsDebugMsg( "Response sent" ); } else { //do some error handling QgsDebugMsg( "result image is 0" ); } delete result; delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetFeatureInfo", Qt::CaseInsensitive ) == 0 ) { QDomDocument featureInfoDoc; try { if ( theServer->getFeatureInfo( featureInfoDoc, version ) != 0 ) { delete theRequestHandler; delete theServer; continue; } } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } QString infoFormat = parameterMap.value( "INFO_FORMAT" ); theRequestHandler->sendGetFeatureInfoResponse( featureInfoDoc, infoFormat ); delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetContext", Qt::CaseInsensitive ) == 0 ) { try { QDomDocument doc = theServer->getContext(); theRequestHandler->sendGetStyleResponse( doc ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetStyle", Qt::CaseInsensitive ) == 0 ) // GetStyle for compatibility with earlier QGIS versions { try { QDomDocument doc = theServer->getStyle(); theRequestHandler->sendGetStyleResponse( doc ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetStyles", Qt::CaseInsensitive ) == 0 ) { // GetStyles is only defined for WMS1.1.1/SLD1.0 if ( version != "1.1.1" ) { theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "GetStyles method is only available in WMS version 1.1.1" ) ); } else { try { QDomDocument doc = theServer->getStyles(); theRequestHandler->sendGetStyleResponse( doc ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } } delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetLegendGraphic", Qt::CaseInsensitive ) == 0 || request.compare( "GetLegendGraphics", Qt::CaseInsensitive ) == 0 ) // GetLegendGraphics for compatibility with earlier QGIS versions { QImage* result = 0; try { result = theServer->getLegendGraphics(); } catch ( QgsMapServiceException& ex ) { QgsDebugMsg( "Caught exception during GetLegendGraphic request" ); theRequestHandler->sendServiceException( ex ); } if ( result ) { QgsDebugMsg( "Sending GetLegendGraphic response" ); //sending is the same for GetMap and GetLegendGraphic theRequestHandler->sendGetMapResponse( serviceString, result ); QgsDebugMsg( "Response sent" ); } else { //do some error handling QgsDebugMsg( "result image is 0" ); } delete result; delete theRequestHandler; delete theServer; continue; } else if ( request.compare( "GetPrint", Qt::CaseInsensitive ) == 0 ) { QByteArray* printOutput = 0; try { printOutput = theServer->getPrint( theRequestHandler->format() ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } if ( printOutput ) { theRequestHandler->sendGetPrintResponse( printOutput ); } delete printOutput; delete theRequestHandler; delete theServer; continue; } else//unknown request { QgsMapServiceException e( "OperationNotSupported", "Operation " + request + " not supported" ); theRequestHandler->sendServiceException( e ); delete theRequestHandler; delete theServer; } } delete theMapRenderer; QgsDebugMsg( "************* all done ***************" ); return 0; }
int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QgsApplication qgsapp( argc, argv, false ); //Default prefix path may be altered by environment variable char* prefixPath = getenv( "QGIS_PREFIX_PATH" ); if ( prefixPath ) { QgsApplication::setPrefixPath( prefixPath, TRUE ); } #if !defined(Q_OS_WIN) else { // init QGIS's paths - true means that all path will be inited from prefix QgsApplication::setPrefixPath( CMAKE_INSTALL_PREFIX, TRUE ); } #endif // Instantiate the plugin directory so that providers are loaded QgsProviderRegistry::instance( QgsApplication::pluginPath() ); QgsDebugMsg( "Prefix PATH: " + QgsApplication::prefixPath() ); QgsDebugMsg( "Plugin PATH: " + QgsApplication::pluginPath() ); QgsDebugMsg( "PkgData PATH: " + QgsApplication::pkgDataPath() ); QgsDebugMsg( "User DB PATH: " + QgsApplication::qgisUserDbFilePath() ); QgsDebugMsg( qgsapp.applicationDirPath() + "/qgis_wms_server.log" ); //create config cache and search for config files in the current directory. //These configurations are used if no mapfile parameter is present in the request QString defaultConfigFilePath; QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory if ( projectFileInfo.exists() ) { defaultConfigFilePath = projectFileInfo.absoluteFilePath(); } else { QFileInfo adminSLDFileInfo = defaultAdminSLD(); if ( adminSLDFileInfo.exists() ) { defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath(); } } //create cache for capabilities XML QgsCapabilitiesCache capabilitiesCache; //creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop QgsMapRenderer* theMapRenderer = new QgsMapRenderer(); while ( fcgi_accept() >= 0 ) { printRequestInfos(); //print request infos if in debug mode //use QgsGetRequestHandler in case of HTTP GET and QgsSOAPRequestHandler in case of HTTP POST QgsRequestHandler* theRequestHandler = 0; char* requestMethod = getenv( "REQUEST_METHOD" ); if ( requestMethod != NULL ) { if ( strcmp( requestMethod, "POST" ) == 0 ) { //QgsDebugMsg( "Creating QgsSOAPRequestHandler" ); //theRequestHandler = new QgsSOAPRequestHandler(); theRequestHandler = new QgsPostRequestHandler(); } else { QgsDebugMsg( "Creating QgsGetRequestHandler" ); theRequestHandler = new QgsGetRequestHandler(); } } else { QgsDebugMsg( "Creating QgsGetRequestHandler" ); theRequestHandler = new QgsGetRequestHandler(); } std::map<QString, QString> parameterMap; try { parameterMap = theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsDebugMsg( "An exception was thrown during input parsing" ); theRequestHandler->sendServiceException( e ); continue; } //set admin config file to wms server object QString configFilePath = defaultConfigFilePath; std::map<QString, QString>::const_iterator mapFileIt = parameterMap.find( "MAP" ); if ( mapFileIt != parameterMap.end() ) { configFilePath = mapFileIt->second; QgsDebugMsg( QString( "Configuration file path set to: %1" ).arg( defaultConfigFilePath ) ); } else { QgsDebugMsg( QString( "Using default configuration file path: %1" ).arg( defaultConfigFilePath ) ); } QgsConfigParser* adminConfigParser = QgsConfigCache::instance()->searchConfiguration( configFilePath ); if ( !adminConfigParser ) { QgsDebugMsg( "parse error on config file " + configFilePath ); theRequestHandler->sendServiceException( QgsMapServiceException( "", "Configuration file problem : perhaps you left off the .qgs extension?" ) ); continue; } //sld parser might need information about request parameters adminConfigParser->setParameterMap( parameterMap ); //request to WMS? QString serviceString( "WMS" ); std::map<QString, QString>::const_iterator serviceIt = parameterMap.find( "SERVICE" ); if ( serviceIt != parameterMap.end() ) { serviceString = serviceIt->second; } /*else { QgsDebugMsg( "unable to find 'SERVICE' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) ); delete theRequestHandler; continue; }*/ QgsWMSServer* theServer = 0; try { theServer = new QgsWMSServer( parameterMap, theMapRenderer ); } catch ( QgsMapServiceException e ) //admin.sld may be invalid { theRequestHandler->sendServiceException( e ); continue; } theServer->setAdminConfigParser( adminConfigParser ); //request type std::map<QString, QString>::const_iterator requestIt = parameterMap.find( "REQUEST" ); if ( requestIt == parameterMap.end() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); delete theRequestHandler; delete theServer; continue; } if ( requestIt->second == "GetCapabilities" ) { const QDomDocument* capabilitiesDocument = capabilitiesCache.searchCapabilitiesDocument( configFilePath ); if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one { QgsDebugMsg( "Capabilities document not found in cache" ); QDomDocument doc; try { doc = theServer->getCapabilities(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } capabilitiesCache.insertCapabilitiesDocument( configFilePath, &doc ); capabilitiesDocument = capabilitiesCache.searchCapabilitiesDocument( configFilePath ); } else { QgsDebugMsg( "Found capabilities document in cache" ); } if ( capabilitiesDocument ) { theRequestHandler->sendGetCapabilitiesResponse( *capabilitiesDocument ); } delete theRequestHandler; delete theServer; continue; } else if ( requestIt->second == "GetMap" ) { QImage* result = 0; try { result = theServer->getMap(); } catch ( QgsMapServiceException& ex ) { QgsDebugMsg( "Catched exception during GetMap request" ); theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } if ( result ) { QgsDebugMsg( "Sending GetMap response" ); theRequestHandler->sendGetMapResponse( serviceString, result ); } else { //do some error handling QgsDebugMsg( "result image is 0" ); } delete result; delete theRequestHandler; delete theServer; continue; } else if ( requestIt->second == "GetFeatureInfo" ) { QDomDocument featureInfoDoc; try { if ( theServer->getFeatureInfo( featureInfoDoc ) != 0 ) { delete theRequestHandler; delete theServer; continue; } } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); delete theRequestHandler; delete theServer; continue; } //info format for GetFeatureInfo QString infoFormat; std::map<QString, QString>::const_iterator p_it = parameterMap.find( "INFO_FORMAT" ); if ( p_it != parameterMap.end() ) { infoFormat = p_it->second; } theRequestHandler->sendGetFeatureInfoResponse( featureInfoDoc, infoFormat ); delete theRequestHandler; delete theServer; continue; } else if ( requestIt->second == "GetStyle" ) { try { QDomDocument doc = theServer->getStyle(); theRequestHandler->sendGetStyleResponse( doc ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } delete theRequestHandler; delete theServer; continue; } else if ( requestIt->second == "GetLegendGraphics" ) { QImage* result = 0; try { result = theServer->getLegendGraphics(); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } if ( result ) { QgsDebugMsg( "Sending GetLegendGraphics response" ); //sending is the same for GetMap and GetLegendGraphics theRequestHandler->sendGetMapResponse( serviceString, result ); } else { //do some error handling QgsDebugMsg( "result image is 0" ); } delete result; delete theRequestHandler; delete theServer; continue; } else if ( requestIt->second == "GetPrint" ) { QByteArray* printOutput = 0; try { printOutput = theServer->getPrint( theRequestHandler->format() ); } catch ( QgsMapServiceException& ex ) { theRequestHandler->sendServiceException( ex ); } if ( printOutput ) { theRequestHandler->sendGetPrintResponse( printOutput ); } delete printOutput; delete theRequestHandler; delete theServer; continue; } else//unknown request { QgsMapServiceException e( "OperationNotSupported", "Operation " + requestIt->second + " not supported" ); theRequestHandler->sendServiceException( e ); delete theRequestHandler; delete theServer; } } delete theMapRenderer; return 0; }
int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QgsApplication qgsapp( argc, argv, getenv( "DISPLAY" ) ); //Default prefix path may be altered by environment variable QgsApplication::init(); #if !defined(Q_OS_WIN) // init QGIS's paths - true means that all path will be inited from prefix QgsApplication::setPrefixPath( CMAKE_INSTALL_PREFIX, TRUE ); #endif #if defined(MAPSERVER_SKIP_ECW) QgsDebugMsg( "Skipping GDAL ECW drivers in server." ); QgsApplication::skipGdalDriver( "ECW" ); QgsApplication::skipGdalDriver( "JP2ECW" ); #endif setupNetworkAccessManager(); QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars ); // Instantiate the plugin directory so that providers are loaded QgsProviderRegistry::instance( QgsApplication::pluginPath() ); QgsDebugMsg( "Prefix PATH: " + QgsApplication::prefixPath() ); QgsDebugMsg( "Plugin PATH: " + QgsApplication::pluginPath() ); QgsDebugMsg( "PkgData PATH: " + QgsApplication::pkgDataPath() ); QgsDebugMsg( "User DB PATH: " + QgsApplication::qgisUserDbFilePath() ); QgsDebugMsg( qgsapp.applicationDirPath() + "/qgis_wms_server.log" ); QgsApplication::createDB(); //init qgis.db (e.g. necessary for user crs) QString defaultConfigFilePath; QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory if ( projectFileInfo.exists() ) { defaultConfigFilePath = projectFileInfo.absoluteFilePath(); QgsDebugMsg( "Using default project file: " + defaultConfigFilePath ); } else { QFileInfo adminSLDFileInfo = defaultAdminSLD(); if ( adminSLDFileInfo.exists() ) { defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath(); } } //create cache for capabilities XML QgsCapabilitiesCache capabilitiesCache; //creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop QgsMapRenderer* theMapRenderer = new QgsMapRenderer(); theMapRenderer->setLabelingEngine( new QgsPalLabeling() ); printRequestInfos(); #ifdef QGSMSDEBUG QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" ); #endif while ( fcgi_accept() >= 0 ) { printRequestInfos(); //print request infos if in debug mode //Request handler QgsRequestHandler* theRequestHandler = createRequestHandler(); QMap<QString, QString> parameterMap; try { parameterMap = theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsDebugMsg( "An exception was thrown during input parsing" ); theRequestHandler->sendServiceException( e ); continue; } QMap<QString, QString>::const_iterator paramIt; //Config file path QString configFilePath = configPath( defaultConfigFilePath, parameterMap ); //Service parameter QString serviceString; paramIt = parameterMap.find( "SERVICE" ); if ( paramIt == parameterMap.constEnd() ) { theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) ); delete theRequestHandler; continue; } else { serviceString = paramIt.value(); } if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath ); if ( !p ) { //error handling } QgsWCSServer wcsServer( configFilePath, parameterMap, p, theRequestHandler ); wcsServer.executeRequest(); } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath ); if ( !p ) { //error handling } QgsWFSServer wfsServer( configFilePath, parameterMap, p, theRequestHandler ); wfsServer.executeRequest(); } else //WMS else { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath, parameterMap ); if ( !p ) { //error handling } //adminConfigParser->loadLabelSettings( theMapRenderer->labelingEngine() ); QgsWMSServer wmsServer( configFilePath, parameterMap, p, theRequestHandler, theMapRenderer, &capabilitiesCache ); wmsServer.executeRequest(); } } delete theMapRenderer; return 0; }