3

How can I read POST data "sent" from my own QtWebKit application? I am developing a small hybrid QWebKit application, which uses HTML forms for user input, than executes local Perl scripts and displays the final result. Nothing is actually sent to or retrieved from servers and no actual network communication is performed; HTML forms are just a local interface for scripts.

I already tried a solution inspired by answers from
Piotr Dobrogost "How to tell QWebPage not to load specific type of resources?" and
Fèlix Galindo Allué "Get raw packet data from Qt application":

# peb.h:
#include <QApplication>
#include <QUrl>
#include <QtWebKit/QWebPage>
#include <QtWebKit/QWebFrame>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QDebug>

class NAM : public QNetworkAccessManager {

    Q_OBJECT

protected:

    virtual QNetworkReply * createRequest ( Operation op,
                                            const QNetworkRequest &req,
                                            QIODevice *outgoingData = 0 ) {
        qDebug() << "Trying to read POST data...";
        QByteArray outgoingByteArray = outgoingData -> readAll();
        QString postData ( outgoingByteArray );
        qDebug() << "POST data" << postData;
        return QNetworkAccessManager::createRequest ( op, req );
    }
};

#peb.cpp
TopLevel::TopLevel()
    : QWebView ( 0 )
{
    main_page = new Page();
    setPage ( main_page );

    NAM *nam = new NAM();
    main_page -> setNetworkAccessManager ( nam );

My program crashes without even displaying GUI after debug message "Trying to read POST data..." Most probably the problem lies within the line:

QByteArray outgoingByteArray = outgoingData -> readAll(); 

I also found and read the following Stack Overflow questions:
1. "QNetworkReply - connection established, first byte written, etc",
2. "QtWebKit QWebPage::acceptNavigationRequest and POST data",
3. "QNetworkAccessManager read outgoingData and keep it in QIODevice",
as well as an interesting post on qt-project.org forums:
4. "[Solved] QNetWorkRequest"
but none of the answers provided me with a working solution.
If no easier solution is found (without external classes), probably will test the Grantlee::Tee solution, proposed by Piotr Dobrogost in question Nr. 3.

I would like to avoid, if possible, Webkit Bridge solutions like Qt Form Extractor Example, which makes my application dependent on inserting specific JavaScript code in each and every HTML form (not to speak that many forms are submitted using jQuery / AJAX and they expect a normal POST capability from the browser).

Every help, advice, information and especially pieces of working code will be highly appreciated!

ddmitov
  • 31
  • 4
  • 1
    You should *really* check that `outgoingData` is not NULL... – peppe Dec 17 '13 at 18:28
  • ` if ( outgoingData -> size() > 0 ){ QByteArray outgoingByteArray = outgoingData -> readAll(); QString postData ( outgoingByteArray ); qDebug() << "POST data" << postData; }` still does not work. If the lines are commented out, everything else works well. I am compiling using Qt 4.8.2 and Qt Creator 2.5.0 (32-bit). – ddmitov Dec 17 '13 at 22:06
  • 1
    **You're still dereferencing `outgoingData` without first checking if it is NULL!** Add a check like this: `if (outgoingData) { outgoingData->foo(); }`. Also remember that if you read from that device, it won't have any data left inside for the actual request. – peppe Dec 17 '13 at 23:17
  • `if ( outgoingData ){ QByteArray outgoingByteArray = outgoingData -> readAll(); QString postData ( outgoingByteArray ); qDebug() << "POST data:" << postData; }` works perfectly well and does exactly what I want! Thank you peppe! I know that after `readAll()` from `outgoingData`, which is `QIODevice`, there is no user input data left in the request, but requests in my program are not going anywhere - user input is captured within the program and (will be) redirected to locally executed scripts - HTTP is used only to extract user input from HTML forms. Thanks again! – ddmitov Dec 18 '13 at 11:20

1 Answers1

1

I think this code will help to catch posted data and show it in message box -- you will reuse outgoing data too -- as you will see :

class netaccess : public QNetworkAccessManager
{
    Q_OBJECT
public:
netaccess() {}
virtual ~netaccess() {}

QNetworkReply * createRequest(Operation op, const QNetworkRequest &req, QIODevice * outgoingData = 0){

  if(outgoingData){

 QByteArray barr = outgoingData->readAll();

    QBuffer * buff = new QBuffer(&barr);

    if (PostOperation == op){
 QMessageBox::information(NULL,"",QString(barr));

buff->open(QIODevice::ReadOnly);
  QNetworkReply * rep = QNetworkAccessManager::createRequest    (op,req,buff);
 buff->setParent(rep);
return  rep;

    }

}



   QNetworkReply * rep = QNetworkAccessManager::createRequest(op,req,NULL);

    return  rep;
}
Ahmad
  • 11
  • 1