void QgsHttpRequestHandler::setGetMapResponse( const QString& service, QImage* img, int imageQuality = -1 ) { Q_UNUSED( service ); QgsMessageLog::logMessage( "setting getmap response..." ); if ( img ) { bool png16Bit = ( mFormatString.compare( "image/png; mode=16bit", Qt::CaseInsensitive ) == 0 ); bool png8Bit = ( mFormatString.compare( "image/png; mode=8bit", Qt::CaseInsensitive ) == 0 ); bool png1Bit = ( mFormatString.compare( "image/png; mode=1bit", Qt::CaseInsensitive ) == 0 ); bool isBase64 = mFormatString.endsWith( ";base64", Qt::CaseInsensitive ); if ( mFormat != "PNG" && mFormat != "JPG" && !png16Bit && !png8Bit && !png1Bit ) { QgsMessageLog::logMessage( "service exception - incorrect image format requested..." ); setServiceException( QgsMapServiceException( "InvalidFormat", "Output format '" + mFormatString + "' is not supported in the GetMap request" ) ); return; } //store the image in a QByteArray and set it directly QByteArray ba; QBuffer buffer( &ba ); buffer.open( QIODevice::WriteOnly ); // Do not use imageQuality for PNG images // For now, QImage expects quality to be a range 0-9 for PNG if ( mFormat == "PNG" ) { imageQuality = -1; } if ( png8Bit ) { QVector<QRgb> colorTable; medianCut( colorTable, 256, *img ); QImage palettedImg = img->convertToFormat( QImage::Format_Indexed8, colorTable, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); palettedImg.save( &buffer, "PNG", imageQuality ); } else if ( png16Bit ) { QImage palettedImg = img->convertToFormat( QImage::Format_ARGB4444_Premultiplied ); palettedImg.save( &buffer, "PNG", imageQuality ); } else if ( png1Bit ) { QImage palettedImg = img->convertToFormat( QImage::Format_Mono, Qt::MonoOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); palettedImg.save( &buffer, "PNG", imageQuality ); } else { img->save( &buffer, mFormat.toUtf8().data(), imageQuality ); } if ( isBase64 ) { ba = ba.toBase64(); } setHttpResponse( &ba, formatToMimeType( mFormat ) ); } }
QDomDocument QgsSLDConfigParser::getStyle( const QString& styleName, const QString& layerName ) const { QDomElement userLayerElement = findUserLayerElement( layerName ); if ( userLayerElement.isNull() ) { throw QgsMapServiceException( QStringLiteral( "LayerNotDefined" ), QStringLiteral( "Operation request is for a Layer not offered by the server." ) ); } QDomElement userStyleElement = findUserStyleElement( userLayerElement, styleName ); if ( userStyleElement.isNull() ) { throw QgsMapServiceException( QStringLiteral( "StyleNotDefined" ), QStringLiteral( "Operation request references a Style not offered by the server." ) ); } QDomDocument styleDoc; styleDoc.appendChild( styleDoc.importNode( userStyleElement, true ) ); return styleDoc; }
QgsFeatureRenderer* QgsSLDConfigParser::rendererFromUserStyle( const QDomElement& userStyleElement, QgsVectorLayer* vec ) const { if ( !vec || userStyleElement.isNull() ) { return nullptr; } QgsDebugMsg( "Entering" ); QString errorMessage; QgsFeatureRenderer* renderer = QgsFeatureRenderer::loadSld( userStyleElement.parentNode(), vec->geometryType(), errorMessage ); if ( !renderer ) { throw QgsMapServiceException( QStringLiteral( "SLD error" ), errorMessage ); } return renderer; }
void QgsGetRequestHandler::sendGetMapResponse( const QString& service, QImage* img ) const { if ( img ) { if ( mFormat != "PNG" && mFormat != "JPG" ) { sendServiceException( QgsMapServiceException( "InvalidFormat", "Output format '" + mFormat + "' is not supported in the GetMap request" ) ); return; } //store the image in a QByteArray and send it directly QByteArray ba; QBuffer buffer( &ba ); buffer.open( QIODevice::WriteOnly ); img->save( &buffer, mFormat.toLocal8Bit().data(), -1 ); sendHttpResponse( &ba, formatToMimeType( mFormat ) ); } }
QDomDocument QgsSLDConfigParser::getStyles( QStringList& layerList ) const { QDomDocument styleDoc; for ( int i = 0; i < layerList.size(); i++ ) { QString layerName; layerName = layerList.at( i ); QDomElement userLayerElement = findUserLayerElement( layerName ); if ( userLayerElement.isNull() ) { throw QgsMapServiceException( QStringLiteral( "LayerNotDefined" ), QStringLiteral( "Operation request is for a Layer not offered by the server." ) ); } QDomNodeList userStyleList = userLayerElement.elementsByTagName( QStringLiteral( "UserStyle" ) ); for ( int j = 0; j < userStyleList.size(); j++ ) { QDomElement userStyleElement = userStyleList.item( i ).toElement(); styleDoc.appendChild( styleDoc.importNode( userStyleElement, true ) ); } } return styleDoc; }
void QgsSOAPRequestHandler::parseInput() { QString inputString = readPostBody(); //QgsDebugMsg("input string is: " + inputString) //inputString to QDomDocument QDomDocument inputXML; QString errorMsg; if ( !inputXML.setContent( inputString, true, &errorMsg ) ) { QgsDebugMsg( "soap request parse error" ); QgsDebugMsg( "error message: " + errorMsg ); QgsDebugMsg( "the xml string was:" ); QgsDebugMsg( inputString ); throw QgsMapServiceException( "InvalidXML", "XML error: " + errorMsg ); } // if xml reading was successfull, save the inputXML in a file QFile soapFile; QTextStream soapStream; //go through soap envelope->soap body, search for either GetCapabilities or GetMap QDomNodeList envelopeNodeList = inputXML.elementsByTagNameNS( "http://schemas.xmlsoap.org/soap/envelope/", "Envelope" ); if ( envelopeNodeList.size() < 1 ) { QgsDebugMsg( "Envelope element not found" ); throw QgsMapServiceException( "SOAPError", "Element <Envelope> not found" ); } QDomNodeList bodyNodeList = envelopeNodeList.item( 0 ).toElement().elementsByTagNameNS( "http://schemas.xmlsoap.org/soap/envelope/", "Body" ); if ( bodyNodeList.size() < 1 ) { QgsDebugMsg( "body node not found" ); throw QgsMapServiceException( "SOAPError", "Element <Body> not found" ); } QDomElement bodyElement = bodyNodeList.item( 0 ).toElement(); QDomElement firstChildElement = bodyElement.firstChild().toElement(); QString serviceString = firstChildElement.attribute( "service" ); if ( serviceString == "MS" ) { QgsDebugMsg( "service = MS " ); mParameterMap.insert( "SERVICE", "MS" ); mService = "MS"; } else if ( serviceString == "WMS" ) { mParameterMap.insert( "SERVICE", "WMS" ); mService = "WMS"; } else if ( serviceString == "MDS" ) { mParameterMap.insert( "SERVICE", "MDS" ); mService = "MDS"; } else if ( serviceString == "MAS" ) { mParameterMap.insert( "SERVICE", "MAS" ); mService = "MAS"; } else { mParameterMap.insert( "SERVICE", "DISCOVERY" ); mService = "DISCOVERY"; } //GetCapabilities request //if(firstChildElement.localName().compare("getCapabilities", Qt::CaseInsensitive) == 0) if ( firstChildElement.localName() == "GetCapabilities" || firstChildElement.localName() == "getCapabilities" ) { mParameterMap.insert( "REQUEST", "GetCapabilities" ); } //GetMap request //else if(firstChildElement.tagName().compare("getMap",Qt::CaseInsensitive) == 0) else if ( firstChildElement.localName() == "GetMap" || firstChildElement.localName() == "getMap" ) { mParameterMap.insert( "REQUEST", "GetMap" ); parseGetMapElement( mParameterMap, firstChildElement ); } //GetDiagram request //else if(firstChildElement.tagName().compare("getDiagram", Qt::CaseInsensitive) == 0) else if ( firstChildElement.localName() == "GetDiagram" ) { mParameterMap.insert( "REQUEST", "GetDiagram" ); parseGetMapElement( mParameterMap, firstChildElement ); //reuse the method for GetMap } //GetFeatureInfo request else if ( firstChildElement.localName() == "GetFeatureInfo" ) { mParameterMap.insert( "REQUEST", "GetFeatureInfo" ); parseGetFeatureInfoElement( mParameterMap, firstChildElement ); } //set mFormat QString formatString = mParameterMap.value( "FORMAT" ); if ( !formatString.isEmpty() ) { //remove the image/ in front of the format if ( formatString == "image/jpeg" || formatString == "JPG" || formatString == "jpg" ) { formatString = "JPG"; } else if ( formatString == "image/png" || formatString == "PNG" || formatString == "png" ) { formatString = "PNG"; } else if ( formatString == "image/gif" || formatString == "GIF" || formatString == "gif" ) { formatString = "GIF"; } else { throw QgsMapServiceException( "InvalidFormat", "Invalid format " + formatString + ", only jpg and png are supported" ); } mFormat = formatString; } }
void QgsWCSServer::executeRequest() { //request type QString request = mParameters.value( "REQUEST" ); if ( request.isEmpty() ) { //do some error handling QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); mRequestHandler->setServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); return; } if ( request.compare( "GetCapabilities", Qt::CaseInsensitive ) == 0 ) { QDomDocument capabilitiesDocument; try { capabilitiesDocument = getCapabilities(); } catch ( QgsMapServiceException& ex ) { mRequestHandler->setServiceException( ex ); return; } QgsDebugMsg( "seting GetCapabilities response" ); mRequestHandler->setGetCapabilitiesResponse( capabilitiesDocument ); return; } else if ( request.compare( "DescribeCoverage", Qt::CaseInsensitive ) == 0 ) { QDomDocument describeDocument; try { describeDocument = describeCoverage(); } catch ( QgsMapServiceException& ex ) { mRequestHandler->setServiceException( ex ); return; } QgsDebugMsg( "seting GetCapabilities response" ); mRequestHandler->setGetCapabilitiesResponse( describeDocument ); return; } else if ( request.compare( "GetCoverage", Qt::CaseInsensitive ) == 0 ) { QByteArray* coverageOutput; try { coverageOutput = getCoverage(); } catch ( QgsMapServiceException& ex ) { mRequestHandler->setServiceException( ex ); return; } if ( coverageOutput ) { mRequestHandler->setGetCoverageResponse( coverageOutput ); } return; } }
QByteArray* QgsWCSServer::getCoverage() { QStringList wcsLayersId = mConfigParser->wcsLayers(); QList<QgsMapLayer*> layerList; QStringList mErrors = QStringList(); //defining coverage name QString coveName = ""; //read COVERAGE QMap<QString, QString>::const_iterator cove_name_it = mParameters.find( "COVERAGE" ); if ( cove_name_it != mParameters.end() ) { coveName = cove_name_it.value(); } if ( coveName == "" ) { QMap<QString, QString>::const_iterator cove_name_it = mParameters.find( "IDENTIFIER" ); if ( cove_name_it != mParameters.end() ) { coveName = cove_name_it.value(); } } if ( coveName == "" ) { mErrors << QString( "COVERAGE is mandatory" ); } layerList = mConfigParser->mapLayerFromCoverage( coveName ); if ( layerList.size() < 1 ) { mErrors << QString( "The layer for the COVERAGE '%1' is not found" ).arg( coveName ); } bool conversionSuccess; // BBOX bool bboxOk = false; double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0; // WIDTh and HEIGHT int width = 0, height = 0; // CRS QString crs = ""; // read BBOX QMap<QString, QString>::const_iterator bbIt = mParameters.find( "BBOX" ); if ( bbIt == mParameters.end() ) { minx = 0; miny = 0; maxx = 0; maxy = 0; } else { bboxOk = true; QString bbString = bbIt.value(); minx = bbString.section( ",", 0, 0 ).toDouble( &conversionSuccess ); if ( !conversionSuccess ) {bboxOk = false;} miny = bbString.section( ",", 1, 1 ).toDouble( &conversionSuccess ); if ( !conversionSuccess ) {bboxOk = false;} maxx = bbString.section( ",", 2, 2 ).toDouble( &conversionSuccess ); if ( !conversionSuccess ) {bboxOk = false;} maxy = bbString.section( ",", 3, 3 ).toDouble( &conversionSuccess ); if ( !conversionSuccess ) {bboxOk = false;} } if ( !bboxOk ) { mErrors << QString( "The BBOX is mandatory and has to be xx.xxx,yy.yyy,xx.xxx,yy.yyy" ); } // read WIDTH width = mParameters.value( "WIDTH", "0" ).toInt( &conversionSuccess ); if ( !conversionSuccess ) width = 0; // read HEIGHT height = mParameters.value( "HEIGHT", "0" ).toInt( &conversionSuccess ); if ( !conversionSuccess ) { height = 0; } if ( width < 0 || height < 0 ) { mErrors << QString( "The WIDTH and HEIGHT are mandatory and have to be integer" ); } crs = mParameters.value( "CRS", "" ); if ( crs == "" ) { mErrors << QString( "The CRS is mandatory" ); } if ( mErrors.count() != 0 ) { throw QgsMapServiceException( "RequestNotWellFormed", mErrors.join( ". " ) ); } QgsCoordinateReferenceSystem requestCRS = QgsCRSCache::instance()->crsByAuthId( crs ); if ( !requestCRS.isValid() ) { mErrors << QString( "Could not create request CRS" ); throw QgsMapServiceException( "RequestNotWellFormed", mErrors.join( ". " ) ); } QgsRectangle rect( minx, miny, maxx, maxy ); QgsMapLayer* layer = layerList.at( 0 ); QgsRasterLayer* rLayer = dynamic_cast<QgsRasterLayer*>( layer ); if ( rLayer && wcsLayersId.contains( rLayer->id() ) ) { // RESPONSE_CRS QgsCoordinateReferenceSystem responseCRS = rLayer->crs(); crs = mParameters.value( "RESPONSE_CRS", "" ); if ( crs != "" ) { responseCRS = QgsCRSCache::instance()->crsByAuthId( crs ); if ( !responseCRS.isValid() ) { responseCRS = rLayer->crs(); } } // transform rect if ( requestCRS != rLayer->crs() ) { QgsCoordinateTransform t( requestCRS, rLayer->crs() ); rect = t.transformBoundingBox( rect ); } QTemporaryFile tempFile; tempFile.open(); QgsRasterFileWriter fileWriter( tempFile.fileName() ); // clone pipe/provider QgsRasterPipe* pipe = new QgsRasterPipe(); if ( !pipe->set( rLayer->dataProvider()->clone() ) ) { mErrors << QString( "Cannot set pipe provider" ); throw QgsMapServiceException( "RequestNotWellFormed", mErrors.join( ". " ) ); } // add projector if necessary if ( responseCRS != rLayer->crs() ) { QgsRasterProjector * projector = new QgsRasterProjector; projector->setCRS( rLayer->crs(), responseCRS ); if ( !pipe->insert( 2, projector ) ) { mErrors << QString( "Cannot set pipe projector" ); throw QgsMapServiceException( "RequestNotWellFormed", mErrors.join( ". " ) ); } } QgsRasterFileWriter::WriterError err = fileWriter.writeRaster( pipe, width, height, rect, responseCRS ); if ( err != QgsRasterFileWriter::NoError ) { mErrors << QString( "Cannot write raster error code: %1" ).arg( err ); throw QgsMapServiceException( "RequestNotWellFormed", mErrors.join( ". " ) ); } delete pipe; QByteArray* ba = 0; ba = new QByteArray(); *ba = tempFile.readAll(); return ba; } return 0; }
QgsComposition* QgsProjectParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* >& labelList ) const { //Create composition from xml QDomElement composerElem = composerByName( composerTemplate ); if ( composerElem.isNull() ) { throw QgsMapServiceException( "Error", "Composer template not found" ); } QDomElement compositionElem = composerElem.firstChildElement( "Composition" ); if ( compositionElem.isNull() ) { return 0; } QgsComposition* composition = new QgsComposition( mapRenderer ); //set resolution, paper size from composer element attributes if ( !composition->readXML( compositionElem, *mXMLDoc ) ) { delete composition; return 0; } //go through all the item elements and add them to the composition (and to the lists) QDomNodeList itemNodes = composerElem.childNodes(); for ( int i = 0; i < itemNodes.size(); ++i ) { QDomElement currentElem = itemNodes.at( i ).toElement(); QString elemName = currentElem.tagName(); if ( elemName == "ComposerMap" ) { QgsComposerMap* map = new QgsComposerMap( composition ); map->readXML( currentElem, *mXMLDoc ); composition->addItem( map ); mapList.push_back( map ); } else if ( elemName == "ComposerLabel" ) { QgsComposerLabel* label = new QgsComposerLabel( composition ); label->readXML( currentElem, *mXMLDoc ); composition->addItem( label ); labelList.push_back( label ); } else if ( elemName == "ComposerLegend" ) { //legend needs to be loaded indirectly to have generic content //and to avoid usage of x-server with pixmap icons //read full legend from xml QgsComposerLegend* legend = new QgsComposerLegend( composition ); legend->readXML( currentElem, *mXMLDoc ); //dynamic legend (would be interesting in case of layers dynamically defined in SLD) //legend->_readXML( currentElem.firstChildElement( "ComposerItem" ), *mXMLDoc ); //legend->updateLegend(); composition->addItem( legend ); } else if ( elemName == "ComposerShape" ) { QgsComposerShape* shape = new QgsComposerShape( composition ); shape->readXML( currentElem, *mXMLDoc ); composition->addItem( shape ); } else if ( elemName == "ComposerArrow" ) { QgsComposerArrow* arrow = new QgsComposerArrow( composition ); arrow->readXML( currentElem, *mXMLDoc ); composition->addItem( arrow ); } else if ( elemName == "ComposerAttributeTable" ) { QgsComposerAttributeTable* table = new QgsComposerAttributeTable( composition ); table->readXML( currentElem, *mXMLDoc ); composition->addItem( table ); } } //scalebars and pictures need to be loaded after the maps to receive the correct size / rotation for ( int i = 0; i < itemNodes.size(); ++i ) { QDomElement currentElem = itemNodes.at( i ).toElement(); QString elemName = currentElem.tagName(); if ( elemName == "ComposerPicture" ) { QgsComposerPicture* picture = new QgsComposerPicture( composition ); picture->readXML( currentElem, *mXMLDoc ); //qgis mapserver needs an absolute file path picture->setPictureFile( convertToAbsolutePath( picture->pictureFile() ) ); composition->addItem( picture ); } else if ( elemName == "ComposerScaleBar" ) { QgsComposerScaleBar* bar = new QgsComposerScaleBar( composition ); bar->readXML( currentElem, *mXMLDoc ); composition->addItem( bar ); } } return composition; }
void QgsHttpRequestHandler::setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) { QByteArray ba; QgsMessageLog::logMessage( "Info format is:" + infoFormat ); if ( infoFormat == "text/xml" || infoFormat.startsWith( "application/vnd.ogc.gml" ) ) { ba = infoDoc.toByteArray(); } else if ( infoFormat == "text/plain" || infoFormat == "text/html" ) { //create string QString featureInfoString; if ( infoFormat == "text/plain" ) { featureInfoString.append( "GetFeatureInfo results\n" ); featureInfoString.append( "\n" ); } else if ( infoFormat == "text/html" ) { featureInfoString.append( "<HEAD>\n" ); featureInfoString.append( "<TITLE> GetFeatureInfo results </TITLE>\n" ); featureInfoString.append( "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n" ); featureInfoString.append( "</HEAD>\n" ); featureInfoString.append( "<BODY>\n" ); } QDomNodeList layerList = infoDoc.elementsByTagName( "Layer" ); //layer loop for ( int i = 0; i < layerList.size(); ++i ) { QDomElement layerElem = layerList.at( i ).toElement(); if ( infoFormat == "text/plain" ) { featureInfoString.append( "Layer '" + layerElem.attribute( "name" ) + "'\n" ); } else if ( infoFormat == "text/html" ) { featureInfoString.append( "<TABLE border=1 width=100%>\n" ); featureInfoString.append( "<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( "name" ) + "</TD></TR>\n" ); featureInfoString.append( "</BR>" ); } //feature loop (for vector layers) QDomNodeList featureNodeList = layerElem.elementsByTagName( "Feature" ); QDomElement currentFeatureElement; if ( featureNodeList.size() < 1 ) //raster layer? { QDomNodeList attributeNodeList = layerElem.elementsByTagName( "Attribute" ); for ( int j = 0; j < attributeNodeList.size(); ++j ) { QDomElement attributeElement = attributeNodeList.at( j ).toElement(); if ( infoFormat == "text/plain" ) { featureInfoString.append( attributeElement.attribute( "name" ) + " = '" + attributeElement.attribute( "value" ) + "'\n" ); } else if ( infoFormat == "text/html" ) { featureInfoString.append( "<TR><TH>" + attributeElement.attribute( "name" ) + "</TH><TD>" + attributeElement.attribute( "value" ) + "</TD></TR>\n" ); } } } else //vector layer { for ( int j = 0; j < featureNodeList.size(); ++j ) { QDomElement featureElement = featureNodeList.at( j ).toElement(); if ( infoFormat == "text/plain" ) { featureInfoString.append( "Feature " + featureElement.attribute( "id" ) + "\n" ); } else if ( infoFormat == "text/html" ) { featureInfoString.append( "<TABLE border=1 width=100%>\n" ); featureInfoString.append( "<TR><TH>Feature</TH><TD>" + featureElement.attribute( "id" ) + "</TD></TR>\n" ); } //attribute loop QDomNodeList attributeNodeList = featureElement.elementsByTagName( "Attribute" ); for ( int k = 0; k < attributeNodeList.size(); ++k ) { QDomElement attributeElement = attributeNodeList.at( k ).toElement(); if ( infoFormat == "text/plain" ) { featureInfoString.append( attributeElement.attribute( "name" ) + " = '" + attributeElement.attribute( "value" ) + "'\n" ); } else if ( infoFormat == "text/html" ) { featureInfoString.append( "<TR><TH>" + attributeElement.attribute( "name" ) + "</TH><TD>" + attributeElement.attribute( "value" ) + "</TD></TR>\n" ); } } if ( infoFormat == "text/html" ) { featureInfoString.append( "</TABLE>\n</BR>\n" ); } } } if ( infoFormat == "text/plain" ) { featureInfoString.append( "\n" ); } else if ( infoFormat == "text/html" ) { featureInfoString.append( "</TABLE>\n<BR></BR>\n" ); } } if ( infoFormat == "text/html" ) { featureInfoString.append( "</BODY>\n" ); } ba = featureInfoString.toUtf8(); } else //unsupported format, set exception { setServiceException( QgsMapServiceException( "InvalidFormat", "Feature info format '" + mFormat + "' is not supported. Possibilities are 'text/plain', 'text/html' or 'text/xml'." ) ); return; } setHttpResponse( &ba, infoFormat ); }
/** * @brief Handles the request * @param queryString * @return response headers and body */ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryString ) { // Run init if handleRequest was called without previously initialising // the server if ( ! mInitialised ) { init(); } /* * This is mainly for python bindings, passing QUERY_STRING * to handleRequest without using os.environment */ if ( ! queryString.isEmpty() ) putenv( "QUERY_STRING", queryString ); int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 QgsMapLayerRegistry::instance()->removeAllMapLayers(); mQgsApplication->processEvents(); if ( logLevel < 1 ) { time.start(); printRequestInfos(); } //Request handler QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler( mCaptureOutput ) ); try { // TODO: split parse input into plain parse and processing from specific services theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL ); theRequestHandler->setServiceException( e ); } #ifdef HAVE_SERVER_PYTHON_PLUGINS // Set the request handler into the interface for plugins to manipulate it mServerInterface->setRequestHandler( theRequestHandler.data() ); // Iterate filters and call their requestReady() method QgsServerFiltersMap::const_iterator filtersIterator; QgsServerFiltersMap filters = mServerInterface->filters(); for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator ) { filtersIterator.value()->requestReady(); } //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook theRequestHandler->setPluginFilters( mServerInterface->filters() ); #endif // Copy the parameters map QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); #ifdef HAVE_SERVER_PYTHON_PLUGINS const QgsAccessControl* accessControl = nullptr; accessControl = mServerInterface->accessControls(); #endif printRequestParameters( parameterMap, logLevel ); QMap<QString, QString>::const_iterator paramIt; //Config file path QString configFilePath = configPath( mConfigFilePath, parameterMap ); #ifdef HAVE_SERVER_PYTHON_PLUGINS mServerInterface->setConfigFilePath( configFilePath ); #endif //Service parameter QString serviceString = theRequestHandler->parameter( "SERVICE" ); if ( serviceString.isEmpty() ) { // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo QString requestString = theRequestHandler->parameter( "REQUEST" ); if ( requestString == "GetMap" || requestString == "GetFeatureInfo" ) { serviceString = "WMS"; } } //possibility for client to suggest a download filename QString outputFileName = theRequestHandler->parameter( "FILE_NAME" ); if ( !outputFileName.isEmpty() ) { theRequestHandler->setDefaultHeaders(); theRequestHandler->setHeader( "Content-Disposition", "attachment; filename=\"" + outputFileName + "\"" ); } // Enter core services main switch if ( !theRequestHandler->exceptionRaised() ) { if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", QString( "Error reading the project file: %1" ).arg( configFilePath ) ) ); } else { QgsWCSServer wcsServer( configFilePath , parameterMap , p , theRequestHandler.data() #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); wcsServer.executeRequest(); } } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", QString( "Error reading the project file: %1" ).arg( configFilePath ) ) ); } else { QgsWFSServer wfsServer( configFilePath , parameterMap , p , theRequestHandler.data() #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); wfsServer.executeRequest(); } } else if ( serviceString == "WMS" ) { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) ); } else { QgsWMSServer wmsServer( configFilePath , parameterMap , p , theRequestHandler.data() , mMapRenderer , mCapabilitiesCache #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); wmsServer.executeRequest(); } } else { theRequestHandler->setServiceException( QgsMapServiceException( "Service configuration error", "Service unknown or unsupported" ) ); } // end switch } // end if not exception raised #ifdef HAVE_SERVER_PYTHON_PLUGINS // Iterate filters and call their responseComplete() method filters = mServerInterface->filters(); for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator ) { filtersIterator.value()->responseComplete(); } // We are done using theRequestHandler in plugins, make sure we don't access // to a deleted request handler from Python bindings mServerInterface->clearRequestHandler(); #endif theRequestHandler->sendResponse(); if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); } // Returns the header and response bytestreams (to be used in Python bindings) return theRequestHandler->getResponse(); }
int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QString optionsPath = getenv( "QGIS_OPTIONS_PATH" ); if ( !optionsPath.isEmpty() ) { QgsDebugMsg( "Options PATH: " + optionsPath ); QSettings::setDefaultFormat( QSettings::IniFormat ); QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, optionsPath ); } QgsApplication qgsapp( argc, argv, getenv( "DISPLAY" ) ); QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME ); QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN ); QCoreApplication::setApplicationName( QgsApplication::QGIS_APPLICATION_NAME ); //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(SERVER_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( "SVG PATHS: " + QgsApplication::svgPaths().join( ":" ) ); 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 QScopedPointer< QgsMapRenderer > theMapRenderer( new QgsMapRenderer ); theMapRenderer->setLabelingEngine( new QgsPalLabeling() ); #ifdef QGSMSDEBUG QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" ); #endif int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 #ifdef HAVE_SERVER_PYTHON_PLUGINS // Create the interface QgsServerInterfaceImpl serverIface( &capabilitiesCache ); // Init plugins if ( ! QgsServerPlugins::initPlugins( &serverIface ) ) { QgsMessageLog::logMessage( "No server python plugins are available", "Server", QgsMessageLog::INFO ); } else { QgsMessageLog::logMessage( "Server python plugins loaded", "Server", QgsMessageLog::INFO ); } // Store plugin filters for faster access QMultiMap<int, QgsServerFilter*> pluginFilters = serverIface.filters(); #endif QgsEditorWidgetRegistry::initEditors(); while ( fcgi_accept() >= 0 ) { QgsMapLayerRegistry::instance()->removeAllMapLayers(); qgsapp.processEvents(); if ( logLevel < 1 ) { time.start(); printRequestInfos(); } //Request handler QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler() ); try { // TODO: split parse input into plain parse and processing from specific services theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL ); theRequestHandler->setServiceException( e ); } #ifdef HAVE_SERVER_PYTHON_PLUGINS // Set the request handler into the interface for plugins to manipulate it serverIface.setRequestHandler( theRequestHandler.data() ); // Iterate filters and call their requestReady() method QgsServerFiltersMap::const_iterator filtersIterator; for ( filtersIterator = pluginFilters.constBegin(); filtersIterator != pluginFilters.constEnd(); ++filtersIterator ) { filtersIterator.value()->requestReady(); } //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook //TODO: implement this in the requestHandler ctor (far easier if we will get rid of // HAVE_SERVER_PYTHON_PLUGINS theRequestHandler->setPluginFilters( pluginFilters ); #endif // Copy the parameters map QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); printRequestParameters( parameterMap, logLevel ); QMap<QString, QString>::const_iterator paramIt; //Config file path QString configFilePath = configPath( defaultConfigFilePath, parameterMap ); //Service parameter QString serviceString = theRequestHandler->parameter( "SERVICE" ); if ( serviceString.isEmpty() ) { // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo QString requestString = theRequestHandler->parameter( "REQUEST" ); if ( requestString == "GetMap" || requestString == "GetFeatureInfo" ) { serviceString = "WMS"; } } // Enter core services main switch if ( !theRequestHandler->exceptionRaised() ) { if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWCSServer wcsServer( configFilePath, parameterMap, p, theRequestHandler.data() ); wcsServer.executeRequest(); } } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWFSServer wfsServer( configFilePath, parameterMap, p, theRequestHandler.data() ); wfsServer.executeRequest(); } } else if ( serviceString == "WMS" ) { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath, parameterMap ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) ); } else { QgsWMSServer wmsServer( configFilePath, parameterMap, p, theRequestHandler.data(), theMapRenderer.data(), &capabilitiesCache ); wmsServer.executeRequest(); } } else { theRequestHandler->setServiceException( QgsMapServiceException( "Service configuration error", "Service unknown or unsupported" ) ); } // end switch } // end if not exception raised #ifdef HAVE_SERVER_PYTHON_PLUGINS // Iterate filters and call their responseComplete() method for ( filtersIterator = pluginFilters.constBegin(); filtersIterator != pluginFilters.constEnd(); ++filtersIterator ) { filtersIterator.value()->responseComplete(); } #endif theRequestHandler->sendResponse(); if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); } } 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(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; }
QgsVectorLayer* QgsSLDConfigParser::contourLayerFromRaster( const QDomElement& userStyleElem, QgsRasterLayer* rasterLayer ) const { QgsDebugMsg( "Entering." ); if ( !rasterLayer ) { return nullptr; } //get <ContourSymbolizer> element QDomNodeList contourNodeList = userStyleElem.elementsByTagName( QStringLiteral( "ContourSymbolizer" ) ); if ( contourNodeList.size() < 1 ) { return nullptr; } QDomElement contourSymbolizerElem = contourNodeList.item( 0 ).toElement(); if ( contourSymbolizerElem.isNull() ) { return nullptr; } double equidistance, minValue, maxValue, offset; QString propertyName; equidistance = contourSymbolizerElem.attribute( QStringLiteral( "equidistance" ) ).toDouble(); minValue = contourSymbolizerElem.attribute( QStringLiteral( "minValue" ) ).toDouble(); maxValue = contourSymbolizerElem.attribute( QStringLiteral( "maxValue" ) ).toDouble(); offset = contourSymbolizerElem.attribute( QStringLiteral( "offset" ) ).toDouble(); propertyName = contourSymbolizerElem.attribute( QStringLiteral( "propertyName" ) ); if ( equidistance <= 0.0 ) { return nullptr; } QTemporaryFile* tmpFile1 = new QTemporaryFile(); tmpFile1->open(); mFilesToRemove.push_back( tmpFile1 ); QString tmpBaseName = tmpFile1->fileName(); QString tmpFileName = tmpBaseName + ".shp"; //hack: use gdal_contour first to write into a temporary file /* todo: use GDALContourGenerate( hBand, dfInterval, dfOffset, nFixedLevelCount, adfFixedLevels, bNoDataSet, dfNoData, hLayer, 0, nElevField, GDALTermProgress, nullptr );*/ //do the stuff that is also done in the main method of gdal_contour... /* -------------------------------------------------------------------- */ /* Open source raster file. */ /* -------------------------------------------------------------------- */ GDALRasterBandH hBand; GDALDatasetH hSrcDS; int numberOfLevels = 0; double currentLevel = 0.0; if ( maxValue > minValue ) { //find first level currentLevel = ( int )(( minValue - offset ) / equidistance + 0.5 ) * equidistance + offset; while ( currentLevel <= maxValue ) { ++numberOfLevels; currentLevel += equidistance; } } double *adfFixedLevels = new double[numberOfLevels]; int nFixedLevelCount = numberOfLevels; currentLevel = ( int )(( minValue - offset ) / equidistance + 0.5 ) * equidistance + offset; for ( int i = 0; i < numberOfLevels; ++i ) { adfFixedLevels[i] = currentLevel; currentLevel += equidistance; } int nBandIn = 1; double dfInterval = equidistance, dfNoData = 0.0, dfOffset = offset; int /* b3D = FALSE, */ bNoDataSet = FALSE, bIgnoreNoData = FALSE; hSrcDS = GDALOpen( rasterLayer->source().toUtf8().constData(), GA_ReadOnly ); if ( !hSrcDS ) { delete [] adfFixedLevels; throw QgsMapServiceException( QStringLiteral( "LayerNotDefined" ), QStringLiteral( "Operation request is for a file not available on the server." ) ); } hBand = GDALGetRasterBand( hSrcDS, nBandIn ); if ( !hBand ) { CPLError( CE_Failure, CPLE_AppDefined, "Band %d does not exist on dataset.", nBandIn ); } if ( !bNoDataSet && !bIgnoreNoData ) dfNoData = GDALGetRasterNoDataValue( hBand, &bNoDataSet ); /* -------------------------------------------------------------------- */ /* Try to get a coordinate system from the raster. */ /* -------------------------------------------------------------------- */ OGRSpatialReferenceH hSRS = nullptr; const char *pszWKT = GDALGetProjectionRef( hBand ); if ( pszWKT && strlen( pszWKT ) != 0 ) hSRS = OSRNewSpatialReference( pszWKT ); /* -------------------------------------------------------------------- */ /* Create the outputfile. */ /* -------------------------------------------------------------------- */ OGRDataSourceH hDS; OGRSFDriverH hDriver = OGRGetDriverByName( "ESRI Shapefile" ); OGRFieldDefnH hFld; OGRLayerH hLayer; int nElevField = -1; if ( !hDriver ) { //fprintf( FCGI_stderr, "Unable to find format driver named 'ESRI Shapefile'.\n" ); delete [] adfFixedLevels; throw QgsMapServiceException( QStringLiteral( "LayerNotDefined" ), QStringLiteral( "Operation request is for a file not available on the server." ) ); } hDS = OGR_Dr_CreateDataSource( hDriver, tmpFileName.toUtf8().constData(), nullptr ); if ( !hDS ) { delete [] adfFixedLevels; throw QgsMapServiceException( QStringLiteral( "LayerNotDefined" ), QStringLiteral( "Operation request cannot create data source." ) ); } hLayer = OGR_DS_CreateLayer( hDS, "contour", hSRS, /* b3D ? wkbLineString25D : */ wkbLineString, nullptr ); if ( !hLayer ) { delete [] adfFixedLevels; throw QgsMapServiceException( QStringLiteral( "LayerNotDefined" ), QStringLiteral( "Operation request could not create contour file." ) ); } hFld = OGR_Fld_Create( "ID", OFTInteger ); OGR_Fld_SetWidth( hFld, 8 ); OGR_L_CreateField( hLayer, hFld, FALSE ); OGR_Fld_Destroy( hFld ); if ( !propertyName.isEmpty() ) { hFld = OGR_Fld_Create( propertyName.toUtf8().constData(), OFTReal ); OGR_Fld_SetWidth( hFld, 12 ); OGR_Fld_SetPrecision( hFld, 3 ); OGR_L_CreateField( hLayer, hFld, FALSE ); OGR_Fld_Destroy( hFld ); nElevField = 1; } /* -------------------------------------------------------------------- */ /* Invoke. */ /* -------------------------------------------------------------------- */ GDALContourGenerate( hBand, dfInterval, dfOffset, nFixedLevelCount, adfFixedLevels, bNoDataSet, dfNoData, hLayer, 0, nElevField, GDALTermProgress, nullptr ); delete [] adfFixedLevels; OGR_DS_Destroy( hDS ); GDALClose( hSrcDS ); //todo: store those three files elsewhere... //mark shp, dbf and shx to delete after the request mFilePathsToRemove.push_back( tmpBaseName + ".shp" ); mFilePathsToRemove.push_back( tmpBaseName + ".dbf" ); mFilePathsToRemove.push_back( tmpBaseName + ".shx" ); QgsVectorLayer* contourLayer = new QgsVectorLayer( tmpFileName, QStringLiteral( "layer" ), QStringLiteral( "ogr" ) ); //create renderer QgsFeatureRenderer* theRenderer = rendererFromUserStyle( userStyleElem, contourLayer ); contourLayer->setRenderer( theRenderer ); //add labeling if requested labelSettingsFromUserStyle( userStyleElem, contourLayer ); QgsDebugMsg( "Returning the contour layer" ); return contourLayer; }
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; }
/** * @brief Handles the request * @param queryString * @param returnBody * @param returnHeaders * @return response body and headers if mCaptureOutput is set and the * flags are set, empty QByteArray if not */ QByteArray QgsServer::handleRequest( const QString queryString , bool returnHeaders, bool returnBody ) { // Run init if handleRequest was called without previously initialising // the server if ( ! mInitialised ) { init( ); } /* * This is mainly for python bindings, passing QUERY_STRING * to handleRequest without using os.environment */ if ( ! queryString.isEmpty() ) { #ifdef _MSC_VER _putenv_s( "QUERY_STRING", queryString.toUtf8().data() ); #else setenv( "QUERY_STRING", queryString.toUtf8().data(), 1 ); #endif } int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 QgsMapLayerRegistry::instance()->removeAllMapLayers(); mQgsApplication->processEvents(); if ( logLevel < 1 ) { time.start(); printRequestInfos(); } //Request handler QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler( mCaptureOutput ) ); try { // TODO: split parse input into plain parse and processing from specific services theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL ); theRequestHandler->setServiceException( e ); } #ifdef HAVE_SERVER_PYTHON_PLUGINS // Set the request handler into the interface for plugins to manipulate it mServerInterface->setRequestHandler( theRequestHandler.data() ); // Iterate filters and call their requestReady() method QgsServerFiltersMap::const_iterator filtersIterator; for ( filtersIterator = mServerInterface->filters().constBegin(); filtersIterator != mServerInterface->filters().constEnd(); ++filtersIterator ) { filtersIterator.value()->requestReady(); } //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook theRequestHandler->setPluginFilters( mServerInterface->filters() ); #endif // Copy the parameters map QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); printRequestParameters( parameterMap, logLevel ); QMap<QString, QString>::const_iterator paramIt; //Config file path mConfigFilePath = configPath( mConfigFilePath, parameterMap ); #ifdef HAVE_SERVER_PYTHON_PLUGINS mServerInterface->setConfigFilePath( mConfigFilePath ); #endif //Service parameter QString serviceString = theRequestHandler->parameter( "SERVICE" ); if ( serviceString.isEmpty() ) { // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo QString requestString = theRequestHandler->parameter( "REQUEST" ); if ( requestString == "GetMap" || requestString == "GetFeatureInfo" ) { serviceString = "WMS"; } } // Enter core services main switch if ( !theRequestHandler->exceptionRaised() ) { if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( mConfigFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWCSServer wcsServer( mConfigFilePath, parameterMap, p, theRequestHandler.data() ); wcsServer.executeRequest(); } } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( mConfigFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWFSServer wfsServer( mConfigFilePath, parameterMap, p, theRequestHandler.data() ); wfsServer.executeRequest(); } } else if ( serviceString == "WMS" ) { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( mConfigFilePath, parameterMap ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) ); } else { QgsWMSServer wmsServer( mConfigFilePath, parameterMap, p, theRequestHandler.data(), mMapRenderer, mCapabilitiesCache ); wmsServer.executeRequest(); } } else { theRequestHandler->setServiceException( QgsMapServiceException( "Service configuration error", "Service unknown or unsupported" ) ); } // end switch } // end if not exception raised #ifdef HAVE_SERVER_PYTHON_PLUGINS // Iterate filters and call their responseComplete() method for ( filtersIterator = mServerInterface->filters().constBegin(); filtersIterator != mServerInterface->filters().constEnd(); ++filtersIterator ) { filtersIterator.value()->responseComplete(); } #endif theRequestHandler->sendResponse(); if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); } // TODO: if HAVE_SERVER_PYTHON // Returns the response bytestream return theRequestHandler->getResponse( returnHeaders , returnBody ); }
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; }