Ejemplo n.º 1
0
shared_ptr<ZLExecutionData> OPDSLink::createNetworkData(const std::string &url, NetworkOperationData &result) const {
	if (url.empty()) {
		return 0;
	}
	std::string modifiedUrl(url);
	rewriteUrl(modifiedUrl);
	return ZLNetworkManager::Instance().createXMLParserRequest(
		modifiedUrl,
		new OPDSXMLParser(new NetworkOPDSFeedReader(*this, url, result))
	);
}
Ejemplo n.º 2
0
bool QgsWfsRequest::sendPOST( const QUrl &url, const QString &contentTypeHeader, const QByteArray &data )
{
  abort(); // cancel previous
  mIsAborted = false;
  mTimedout = false;
  mGotNonEmptyResponse = false;

  mErrorMessage.clear();
  mErrorCode = QgsWfsRequest::NoError;
  mForceRefresh = true;
  mResponse.clear();

  if ( url.toEncoded().contains( "fake_qgis_http_endpoint" ) )
  {
    // Hack for testing purposes
    QUrl modifiedUrl( url );
    modifiedUrl.addQueryItem( QStringLiteral( "POSTDATA" ), QString::fromUtf8( data ) );
    return sendGET( modifiedUrl, true, true, false );
  }

  QNetworkRequest request( url );
  QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWfsRequest" ) );
  if ( !mUri.auth().setAuthorization( request ) )
  {
    mErrorCode = QgsWfsRequest::NetworkError;
    mErrorMessage = errorMessageFailedAuth();
    QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
    return false;
  }
  request.setHeader( QNetworkRequest::ContentTypeHeader, contentTypeHeader );

  mReply = QgsNetworkAccessManager::instance()->post( request, data );
  mReply->setReadBufferSize( READ_BUFFER_SIZE_HINT );
  if ( !mUri.auth().setAuthorizationReply( mReply ) )
  {
    mErrorCode = QgsWfsRequest::NetworkError;
    mErrorMessage = errorMessageFailedAuth();
    QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
    return false;
  }
  connect( mReply, &QNetworkReply::finished, this, &QgsWfsRequest::replyFinished );
  connect( mReply, &QNetworkReply::downloadProgress, this, &QgsWfsRequest::replyProgress );

  QEventLoop loop;
  connect( this, &QgsWfsRequest::downloadFinished, &loop, &QEventLoop::quit );
  loop.exec( QEventLoop::ExcludeUserInputEvents );

  return mErrorMessage.isEmpty();
}
Ejemplo n.º 3
0
bool QgsWFSRequest::sendPOST( const QUrl& url, const QString& contentTypeHeader, const QByteArray& data )
{
    abort(); // cancel previous
    mIsAborted = false;
    mTimedout = false;
    mGotNonEmptyResponse = false;

    mErrorMessage.clear();
    mErrorCode = QgsWFSRequest::NoError;
    mForceRefresh = true;
    mResponse.clear();

    if ( url.toEncoded().contains( "fake_qgis_http_endpoint" ) )
    {
        // Hack for testing purposes
        QUrl modifiedUrl( url );
        modifiedUrl.addQueryItem( "POSTDATA", QString::fromUtf8( data ) );
        return sendGET( modifiedUrl, true, true, false );
    }

    QNetworkRequest request( url );
    if ( !mUri.auth().setAuthorization( request ) )
    {
        mErrorCode = QgsWFSRequest::NetworkError;
        mErrorMessage = errorMessageFailedAuth();
        QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
        return false;
    }
    request.setHeader( QNetworkRequest::ContentTypeHeader, contentTypeHeader );

    mReply = QgsNetworkAccessManager::instance()->post( request, data );
    connect( mReply, SIGNAL( finished() ), this, SLOT( replyFinished() ) );
    connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( replyProgress( qint64, qint64 ) ) );

    QEventLoop loop;
    connect( this, SIGNAL( downloadFinished() ), &loop, SLOT( quit() ) );
    loop.exec( QEventLoop::ExcludeUserInputEvents );

    return mErrorMessage.isEmpty();
}
Ejemplo n.º 4
0
bool QgsWFSRequest::sendGET( const QUrl& url, bool synchronous, bool forceRefresh, bool cache )
{
    abort(); // cancel previous
    mIsAborted = false;
    mTimedout = false;
    mGotNonEmptyResponse = false;

    mErrorMessage.clear();
    mErrorCode = QgsWFSRequest::NoError;
    mForceRefresh = forceRefresh;
    mResponse.clear();

    QUrl modifiedUrl( url );
    if ( modifiedUrl.toString().contains( "fake_qgis_http_endpoint" ) )
    {
        // Just for testing with local files instead of http:// ressources
        QString modifiedUrlString = modifiedUrl.toString();
        // Qt5 does URL encoding from some reason (of the FILTER parameter for example)
        modifiedUrlString = QUrl::fromPercentEncoding( modifiedUrlString.toUtf8() );
        QgsDebugMsg( QString( "Get %1" ).arg( modifiedUrlString ) );
        modifiedUrlString = modifiedUrlString.mid( QString( "http://" ).size() );
        QString args = modifiedUrlString.mid( modifiedUrlString.indexOf( '?' ) );
        if ( modifiedUrlString.size() > 256 )
        {
            args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex();
        }
        else
        {
            args.replace( "?", "_" );
            args.replace( "&", "_" );
            args.replace( "<", "_" );
            args.replace( ">", "_" );
            args.replace( "'", "_" );
            args.replace( "\"", "_" );
            args.replace( " ", "_" );
            args.replace( ":", "_" );
            args.replace( "/", "_" );
            args.replace( "\n", "_" );
        }
#ifdef Q_OS_WIN
        // Passing "urls" like "http://c:/path" to QUrl 'eats' the : after c,
        // so we must restore it
        if ( modifiedUrlString[1] == '/' )
        {
            modifiedUrlString = modifiedUrlString[0] + ":/" + modifiedUrlString.mid( 2 );
        }
#endif
        modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf( '?' ) ) + args;
        QgsDebugMsg( QString( "Get %1 (after laundering)" ).arg( modifiedUrlString ) );
        modifiedUrl = QUrl::fromLocalFile( modifiedUrlString );
    }

    QNetworkRequest request( modifiedUrl );
    if ( !mUri.auth().setAuthorization( request ) )
    {
        mErrorCode = QgsWFSRequest::NetworkError;
        mErrorMessage = errorMessageFailedAuth();
        QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
        return false;
    }

    if ( cache )
    {
        request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, forceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
        request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
    }

    mReply = QgsNetworkAccessManager::instance()->get( request );
    connect( mReply, SIGNAL( finished() ), this, SLOT( replyFinished() ) );
    connect( mReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( replyProgress( qint64, qint64 ) ) );

    if ( !synchronous )
        return true;

    QEventLoop loop;
    connect( this, SIGNAL( downloadFinished() ), &loop, SLOT( quit() ) );
    loop.exec( QEventLoop::ExcludeUserInputEvents );

    return mErrorMessage.isEmpty();
}
Ejemplo n.º 5
0
bool QgsWfsRequest::sendGET( const QUrl &url, bool synchronous, bool forceRefresh, bool cache )
{
  abort(); // cancel previous
  mIsAborted = false;
  mTimedout = false;
  mGotNonEmptyResponse = false;

  mErrorMessage.clear();
  mErrorCode = QgsWfsRequest::NoError;
  mForceRefresh = forceRefresh;
  mResponse.clear();

  QUrl modifiedUrl( url );

  // Specific code for testing
  if ( modifiedUrl.toString().contains( QLatin1String( "fake_qgis_http_endpoint" ) ) )
  {
    // Just for testing with local files instead of http:// resources
    QString modifiedUrlString = modifiedUrl.toString();
    // Qt5 does URL encoding from some reason (of the FILTER parameter for example)
    modifiedUrlString = QUrl::fromPercentEncoding( modifiedUrlString.toUtf8() );
    QgsDebugMsgLevel( QStringLiteral( "Get %1" ).arg( modifiedUrlString ), 4 );
    modifiedUrlString = modifiedUrlString.mid( QStringLiteral( "http://" ).size() );
    QString args = modifiedUrlString.mid( modifiedUrlString.indexOf( '?' ) );
    if ( modifiedUrlString.size() > 256 )
    {
      args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex();
    }
    else
    {
      args.replace( QLatin1String( "?" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( "&" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( "<" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( ">" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( "'" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( "\"" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( " " ), QLatin1String( "_" ) );
      args.replace( QLatin1String( ":" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( "/" ), QLatin1String( "_" ) );
      args.replace( QLatin1String( "\n" ), QLatin1String( "_" ) );
    }
#ifdef Q_OS_WIN
    // Passing "urls" like "http://c:/path" to QUrl 'eats' the : after c,
    // so we must restore it
    if ( modifiedUrlString[1] == '/' )
    {
      modifiedUrlString = modifiedUrlString[0] + ":/" + modifiedUrlString.mid( 2 );
    }
#endif
    modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf( '?' ) ) + args;
    QgsDebugMsgLevel( QStringLiteral( "Get %1 (after laundering)" ).arg( modifiedUrlString ), 4 );
    modifiedUrl = QUrl::fromLocalFile( modifiedUrlString );
  }

  QgsDebugMsgLevel( QStringLiteral( "Calling: %1" ).arg( modifiedUrl.toDisplayString( ) ), 4 );

  QNetworkRequest request( modifiedUrl );
  if ( !mUri.auth().setAuthorization( request ) )
  {
    mErrorCode = QgsWfsRequest::NetworkError;
    mErrorMessage = errorMessageFailedAuth();
    QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
    return false;
  }

  if ( cache )
  {
    request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, forceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
    request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
  }

  QWaitCondition waitCondition;
  QMutex waitConditionMutex;
  bool threadFinished = false;
  bool success = false;

  std::function<void()> downloaderFunction = [ this, request, synchronous, &waitConditionMutex, &waitCondition, &threadFinished, &success ]()
  {
    if ( QThread::currentThread() != QgsApplication::instance()->thread() )
      QgsNetworkAccessManager::instance( Qt::DirectConnection );

    success = true;
    mReply = QgsNetworkAccessManager::instance()->get( request );

    mReply->setReadBufferSize( READ_BUFFER_SIZE_HINT );
    if ( !mUri.auth().setAuthorizationReply( mReply ) )
    {
      mErrorCode = QgsWfsRequest::NetworkError;
      mErrorMessage = errorMessageFailedAuth();
      QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) );
      waitCondition.wakeAll();
      success = false;
    }
    else
    {
      // We are able to use direct connection here, because we
      // * either run on the thread mReply lives in, so DirectConnection is standard and safe anyway
      // * or the owner thread of mReply is currently not doing anything because it's blocked in future.waitForFinished() (if it is the main thread)
      connect( mReply, &QNetworkReply::finished, this, &QgsWfsRequest::replyFinished, Qt::DirectConnection );
      connect( mReply, &QNetworkReply::downloadProgress, this, &QgsWfsRequest::replyProgress, Qt::DirectConnection );

      if ( synchronous )
      {
        auto resumeMainThread = [&waitConditionMutex, &waitCondition]()
        {
          waitConditionMutex.lock();
          waitCondition.wakeAll();
          waitConditionMutex.unlock();

          waitConditionMutex.lock();
          waitCondition.wait( &waitConditionMutex );
          waitConditionMutex.unlock();
        };

        connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::authenticationRequired, this, resumeMainThread, Qt::DirectConnection );
        connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::proxyAuthenticationRequired, this, resumeMainThread, Qt::DirectConnection );

#ifndef QT_NO_SSL
        connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::sslErrors, this, resumeMainThread, Qt::DirectConnection );
#endif
        QEventLoop loop;
        connect( this, &QgsWfsRequest::downloadFinished, &loop, &QEventLoop::quit, Qt::DirectConnection );
        loop.exec();
      }
    }
    waitConditionMutex.lock();
    threadFinished = true;
    waitCondition.wakeAll();
    waitConditionMutex.unlock();
  };

  if ( synchronous && QThread::currentThread() == QApplication::instance()->thread() )
  {
    std::unique_ptr<DownloaderThread> downloaderThread = qgis::make_unique<DownloaderThread>( downloaderFunction );
    downloaderThread->start();

    while ( true )
    {
      waitConditionMutex.lock();
      if ( threadFinished )
      {
        waitConditionMutex.unlock();
        break;
      }
      waitCondition.wait( &waitConditionMutex );

      // If the downloader thread wakes us (the main thread) up and is not yet finished
      // he needs the authentication to run.
      // The processEvents() call gives the auth manager the chance to show a dialog and
      // once done with that, we can wake the downloaderThread again and continue the download.
      if ( !threadFinished )
      {
        waitConditionMutex.unlock();

        QgsApplication::instance()->processEvents();
        waitConditionMutex.lock();
        waitCondition.wakeAll();
        waitConditionMutex.unlock();
      }
      else
      {
        waitConditionMutex.unlock();
      }
    }
    // wait for thread to gracefully exit
    downloaderThread->wait();
  }
  else
  {
    downloaderFunction();
  }
  return success && mErrorMessage.isEmpty();
}