How to authenticate with GitHub using Qt and Access Token - qt

I try to implement GitHub authentication from my Qt application using Access Token. I can connect to GitHub using Postman without any problem by providing URL (in my case this is https://api.github.com/notifications) and access token I've generated on the GitHub (Settings/Developer settings/Personal access tokens) https://github.com/settings/tokens. Now I want to do the same using Qt but can't find examples how to do that. There is example for Reddit( https://doc.qt.io/qt-5/qtnetworkauth-redditclient-example.html) in the Qt documentation but it uses some redirect algorithm, not access token:
auto replyHandler = new QOAuthHttpServerReplyHandler(1337, this);
oauth2.setReplyHandler(replyHandler);
oauth2.setAuthorizationUrl(QUrl("https://www.reddit.com/api/v1/authorize"));
oauth2.setAccessTokenUrl(QUrl("https://www.reddit.com/api/v1/access_token"));
I have no clue how to do the same using provided Access Token.

If you are going to use the personal token then it is not necessary to implement the OAuth/OAuth2 logic since the first part of the transaction is to obtain the token but the OP already has it. If you have the token then it is only necessary to request the rest API:
#include <QByteArray>
#include <QCoreApplication>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const QString username = "<username>";
const QString token = "<token>";
const QByteArray basic_authorization = QByteArray("Basic ") + (username + ":" + token).toUtf8().toBase64();
QNetworkRequest request;
request.setRawHeader(QByteArrayLiteral("Authorization"), basic_authorization);
QUrl url("https://api.github.com/notifications");
request.setUrl(url);
QNetworkAccessManager manager;
QNetworkReply *reply = manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, [reply](){
QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
qDebug() << doc;
QTimer::singleShot(1000, &QCoreApplication::quit);
});
return a.exec();
}

Related

Get SO_RCVBUF socket option value from Qt

I want to get the value of the SO_RCVBUF socket option used by Qt to be sure that it uses by default the system value (that I changed).
But the following piece of code returns an "Invalid" QVariant:
QUdpSocket socket;
qDebug() << socket.socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
Does it mean that the socketOption() Qt method only get the value if it has been set with setSocketOption()?
Or did I make a mistake?
In order to obtain the socket information, then the native socket must have been created, that is, obtain a socketDescriptor() other than -1, but in your case it is not connected causing that value not to be read, returning a invalid QVariant.
The solution is to connect the socket and analyze that the socket is valid to obtain the desired information:
#include <QCoreApplication>
#include <QTimer>
#include <QUdpSocket>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QUdpSocket socket;
QObject::connect(&socket, &QAbstractSocket::stateChanged, [&socket](){
if(socket.socketDescriptor() != -1){
qDebug() << socket.socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
// kill application
QTimer::singleShot(1000, &QCoreApplication::quit);
}
});
socket.bind(QHostAddress::LocalHost, 1234);
return a.exec();
}
Output:
QVariant(int, 212992)

Registring QList<CustomType>

I got a runtime crash when registering a QList (CustomType is a Q_GADGET generate by the repc (Qt remote object compiler)).
Actually I am trying to expose a list of custom type using Qt Remote Object.
file.rep :
POD Service(QString name, QUrl enpoint)
POD Services(QList<Service> svcs)
class ROObject
{
PROP(bool state = false);
PROP(Services services);
}
main.cpp:
#include <QCoreApplication>
#include <QTimer>
#include <QRemoteObjectHost>
#include "rotest.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<QList<Service>>();
ROTest t;
QList<Service> l;
l.push_back(Service("houssem", QUrl("local:houssem")));
l.push_back(Service("houss", QUrl("local:houss")));
Services ss(l);
t.setServices(ss);
QRemoteObjectHost host;
host.setHostUrl(QUrl("local:s"));
host.enableRemoting(&t);
qDebug() << "Services : " << t.services().svcs().count();
return a.exec();
}
error:
Thank you for your help.
Qt doesn't know how to serialize your custom types.
In addition to registering it as a meta type, you need to implement and register stream operators for it:
void qRegisterMetaTypeStreamOperators(const char *typeName)
Registers the stream operators for the type T called typeName.
Afterward, the type can be streamed using QMetaType::load() and
QMetaType::save(). These functions are used when streaming a QVariant.
qRegisterMetaTypeStreamOperators<MyClass>("MyClass");
// The stream operators should have the following signatures:
QDataStream &operator<<(QDataStream &out, const MyClass &myObj);
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
Also, what you actually need to register as a meta type is Service and not QList<Service>. Once service is registered and its streaming operators are implemented you should be all set, Qt knows how to handle the QList part.

QNetworkAccessManager is not sending data part of POST request

When sending POST data to server, from Qt application looks everything good but data part of HTTP part were not sent. In Wireshark in POST packet is visible correct "Content-Length" value but size of whole HTTP segment is only about 226 bytes (is independent on POST data size).
I can't find reason why data part is not send. Any idea?
The application is running in console. A complete source is below.
project.pro:
QT += widgets
QT -= gui
QT += network
CONFIG += c++11
TARGET = POSTrequest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
main.cpp:
#include <QObject>
#include <QApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QNetworkRequest request(QUrl("http://www.server.com/index.php"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkAccessManager manager;
QNetworkReply *reply = manager.post(request, "a=aaaaaa");
QObject::connect(reply, SIGNAL(finished()), &a, SLOT(quit()));
return a.exec();
}
This works for me on both OS X and Windows:
#post-request-36549732.pro
QT = core network
CONFIG += console c++11
CONFIG -= app_bundle
TARGET = post-request-36549732
TEMPLATE = app
SOURCES += main.cpp
// main.cpp
#include <QtNetwork>
int main(int argc, char ** argv)
{
QCoreApplication a{argc, argv};
QNetworkAccessManager manager;
QByteArray post{"a="};
post.append(QByteArray{512, 'b'});
QNetworkRequest req(QUrl("http://server/test.php"));
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
// Must be a queued connection, or else the multi-threaded manager might
// win the race and signal quit before `a.exec()` starts running. In such
// case, the `quit()` is a NOP. We don't want that.
QObject::connect(&manager, &QNetworkAccessManager::finished, &a, [](QNetworkReply * reply){
qDebug() << reply->errorString();
qApp->quit();
}, Qt::QueuedConnection);
manager.post(req, post);
return a.exec();
}
You might be interpreting your Wireshark data incorrectly. Make sure you're looking at the Reassembled TCP aspect of the HTTP request. Here's how it looks for me; server is 192.168.2.1:

How to tell QWebPage not to load specific type of resources?

How to tell QWebPage not to load specific type of resources like js, css or png?
The solution is to extend QNetworkAccessManager class and override it's virtual method QNetworkAccessManager::createRequest In our implementation we check the path of the requested url and if it's the one we don't want to download we create and hand over an empty request instead of the real one.
Below is a complete, working example.
#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) {
if (req.url().path().endsWith("css")) {
qDebug() << "skipping " << req.url();
return QNetworkAccessManager::createRequest(QNetworkAccessManager::GetOperation,
QNetworkRequest(QUrl()));
} else {
return QNetworkAccessManager::createRequest(op, req, outgoingData);
}
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWebPage page;
NAM nam;
page.setNetworkAccessManager(&nam);
page.mainFrame()->load(QUrl("http://google.com"));
app.exec();
}
#include "main.moc"
I am actually struggling with the same problem, Piotr solution is assuming urls with file extensions, unfortunately this is not always the case.
it is possible toe get mime-type but only after we get the response' and this is offcore to late.
we tried to get the element context requesting the resources, say if it is an <img> element or <link> to get CSS, but req.originatingObject()
only gives us a QWebFrame.
i know for example that this was possible in mozilla code.
BTW, turning off javascript and auto load images will prevent loading of images and scripts.
If your goal is to prevent the Webpage from changing, you can take a look at
virtual bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type);
in QWebPage. You can inspect the request and return false if you want to prevent the request from being sent.

HowTo Crypt/Encrypt some string (e.g. Password) on Qt simple

Here what I have got:
Qt SDK version 4.6.2
Windows XP
Question: how can I simply crypt and encrypt simple QString value? I need this to be able to save some crypted string into the INI file, and after reopening application encrypt string to normal password string value.
PS: I'm looking simple and nice solution.
Thanks for help!
There is SimpleCrypt here: https://wiki.qt.io/Simple_encryption_with_SimpleCrypt and as the name suggests the author says that the class does not provide strong encryption but its pretty good in my view.
You can download a working example here: http://www.qtcentre.org/threads/45346-Encrypting-an-existing-sqlite-database-in-sqlcipher?p=206406#post206406
#include <QtGui>
#include "simplecrypt.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString FreeTrialStartDate ;
//Set The Encryption And Decryption Key
SimpleCrypt processSimpleCrypt(89473829);
QString FreeTrialStartsOn("22/11/2011");
//Encrypt
FreeTrialStartDate = processSimpleCrypt.encryptToString(FreeTrialStartsOn);
qDebug() << "Encrypted 22/11/2011 to" << FreeTrialStartDate;
//Decrypt
QString decrypt = processSimpleCrypt.decryptToString(FreeTrialStartDate);
qDebug() << "Decrypted 22/11/2011 to" << decrypt;
return a.exec();
}
If you just want to use it for as password, use a QCryptographicHash. Hash the password, save it to the file. Then when you want to compare, hash the input and compare it to the saved password. Of course this is not very secure, and you can get into things like salting for increased security.
If you just want to be able to encrypt and decrypt a string that is stored in a file, use a cipher. Take a look at Botan or Crypto++.
This of course all depends on the levels of security you want.
Adds the data to the cryptographic hash:
QByteArray string = "Nokia";
QCryptographicHash hasher(QCryptographicHash::Sha1);
hasher.addData(string);
Returns the final hash value.
QByteArray string1=hasher.result();
And Main.cpp example
#include <QtGui/QApplication>
#include <QWidget>
#include <QHBoxLayout>
#include <QCryptographicHash>
#include <QString>
#include <QByteArray>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *win=new QWidget();
QHBoxLayout *lay=new QHBoxLayout();
QLabel *lbl=new QLabel();
QLabel *lbl1=new QLabel("Encrypted Text:");
lbl1->setBuddy(lbl);
QByteArray string="Nokia";
QCryptographicHash *hash=new QCryptographicHash(QCryptographicHash::Md4);
hash->addData(string);
QByteArray string1=hash->result();
lbl->setText(string1); // TODO: use e.g. toHex or toBase64
lay->addWidget(lbl1);
lay->addWidget(lbl);
win->setLayout(lay);
win->setStyleSheet("* { background-color:rgb(199,147,88); padding: 7px ; color:rgb(255,255,255)}");
win->showMaximized();
return a.exec();
}

Resources