Skip to content

Commit

Permalink
Merge pull request #154 from pipacs/update-readme
Browse files Browse the repository at this point in the history
Update README.
  • Loading branch information
pipacs committed Dec 29, 2021
2 parents 186b5bb + 078eea0 commit 8492f54
Showing 1 changed file with 116 additions and 94 deletions.
210 changes: 116 additions & 94 deletions README.md
Expand Up @@ -4,13 +4,13 @@ This library encapsulates the OAuth 1.0 and 2.0 client authentication flows, and

The primary target is Qt Quick applications on embedded devices.

Supported Qt versions: 5 and 6.

Notes to contributors:

* Please follow the coding style of the existing source
* Please follow the coding style of the existing source code
* Code contributions are released under Simplified BSD License, as specified in LICENSE. Do not contribute if this license does not suit your code

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/A0A74ID8G)

## Classes

Class | Header | Purpose
Expand Down Expand Up @@ -55,55 +55,61 @@ This example assumes a hypothetical Twitter client that will post tweets. Twitte

Include the required header files, and have some member variables that will be used for authentication and sending requests:

#include "o1twitter.h"
#include "o1requestor.h"
O1Twitter *o1;
```c++
#include "o1twitter.h"
#include "o1requestor.h"
O1Twitter *o1;
```

### Initialization

Instantiate one of the authenticator classes, like O1Twitter, set your application ID and application secret, and install the signal handlers:

o1 = new O1Twitter(this);
o1->setClientId(MY_CLIENT_ID);
o1->setClientSecret(MY_CLIENT_SECRET);
connect(o1, SIGNAL(linkedChanged()), this, SLOT(onLinkedChanged()));
connect(o1, SIGNAL(linkingFailed()), this, SLOT(onLinkingFailed()));
connect(o1, SIGNAL(linkingSucceeded()), this, SLOT(onLinkingSucceeded()));
connect(o1, SIGNAL(openBrowser(QUrl)), this, SLOT(onOpenBrowser(QUrl)));
connect(o1, SIGNAL(closeBrowser()), this, SLOT(onCloseBrowser()));
```c++
o1 = new O1Twitter(this);
o1->setClientId(MY_CLIENT_ID);
o1->setClientSecret(MY_CLIENT_SECRET);
connect(o1, SIGNAL(linkedChanged()), this, SLOT(onLinkedChanged()));
connect(o1, SIGNAL(linkingFailed()), this, SLOT(onLinkingFailed()));
connect(o1, SIGNAL(linkingSucceeded()), this, SLOT(onLinkingSucceeded()));
connect(o1, SIGNAL(openBrowser(QUrl)), this, SLOT(onOpenBrowser(QUrl)));
connect(o1, SIGNAL(closeBrowser()), this, SLOT(onCloseBrowser()));
```
**Note:** For browserless Twitter authentication, you can use the OXTwitter specialized class which can do Twitter XAuth. You will need to additionally provide your Twitter login credentials (username & password) before calling *link()*.
**Note:** For browserless Twitter authentication, you can use the OXTwitter specialized class that can do Twitter XAuth. You will need to additionally provide your Twitter login credentials (username & password) before calling *link()*.
### Handling Signals
O2 is an asynchronous library. It will send signals at various stages of authentication and request processing.
To handle these signals, implement the following slots in your code:
void onLinkedChanged() {
// Linking (login) state has changed.
// Use o1->linked() to get the actual state
}

void onLinkingFailed() {
// Login has failed
}

void onLinkingSucceeded() {
// Login has succeeded
}

void onOpenBrowser(const QUrl *url) {
// Open a web browser or a web view with the given URL.
// The user will interact with this browser window to
// enter login name, password, and authorize your application
// to access the Twitter account
}

void onCloseBrowser() {
// Close the browser window opened in openBrowser()
}

```c++
void onLinkedChanged() {
// Linking (login) state has changed.
// Use o1->linked() to get the actual state
}
void onLinkingFailed() {
// Login has failed
}
void onLinkingSucceeded() {
// Login has succeeded
}
void onOpenBrowser(const QUrl *url) {
// Open a web browser or a web view with the given URL.
// The user will interact with this browser window to
// enter login name, password, and authorize your application
// to access the Twitter account
}
void onCloseBrowser() {
// Close the browser window opened in openBrowser()
}
```

**Note:** From _onOpenBrowser_, prefer opening a web view, instead of a full-blown external browser.

**Note:** If you _must_ use an external browser on Android, change this line in the Qt-generated manifest.xml:
Expand All @@ -115,15 +121,19 @@ To handle these signals, implement the following slots in your code:

To log in (e.g. to link your application to the OAuth service), call the link() method:

o1->link();
```c++
o1->link();
```

This initiates the authentication sequence. Your signal handlers above will be called at various stages. Lastly, if linking succeeds, onLinkingSucceeded() will be called.

### Logging Out

To log out, call the unlink() method:

o1->unlink();
```c++
o1->unlink();
```

Logging out always succeeds, and requires no user interaction.

Expand All @@ -133,96 +143,108 @@ Once linked, you can start sending authenticated requests to the service. We sta

First we need a Qt network manager and an O1 requestor object:

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
O1Requestor *requestor = new O1Requestor(manager, o1, this);
```c++
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
O1Requestor *requestor = new O1Requestor(manager, o1, this);
```

Next, create parameters for posting the update:

QByteArray paramName("status");
QByteArray tweetText("My first tweet!");
```c++
QByteArray paramName("status");
QByteArray tweetText("My first tweet!");

QList<O1RequestParameter> requestParams = QList<O1RequestParameter>();
requestParams << O1RequestParameter(paramName, tweetText);
QList<O1RequestParameter> requestParams = QList<O1RequestParameter>();
requestParams << O1RequestParameter(paramName, tweetText);

QByteArray postData = O1::createQueryParams(requestParams);
QByteArray postData = O1::createQueryParams(requestParams);

// Using Twitter's REST API ver 1.1
QUrl url = QUrl("https://api.twitter.com/1.1/statuses/update.json");
// Using Twitter's REST API ver 1.1
QUrl url = QUrl("https://api.twitter.com/1.1/statuses/update.json");

QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM);
```
Finally we authenticate and send the request using the O1 requestor object:
QNetworkReply *reply = requestor->post(request, reqestParams, postData);
```c++
QNetworkReply *reply = requestor->post(request, reqestParams, postData);
```

Continuing with the example, we will now send a tweet containing an image as well as a message.

We create an HTTP request containing the image and the message, in the format specified by Twitter:

QString imagePath("/tmp/image.jpg");
QString message("My tweet with an image!");

QFileInfo fileInfo(imagePath);
QFile file(imagePath);
file.open(QIODevice::ReadOnly);

QString boundary("7d44e178b0439");
QByteArray data(QString("--" + boundary + "\r\n").toAscii());
data += "Content-Disposition: form-data; name=\"media[]\"; filename=\"" + fileInfo.fileName() + "\"\r\n";
data += "Content-Transfer-Encoding: binary\r\n";
data += "Content-Type: application/octet-stream\r\n\r\n";
data += file.readAll();
file.close();
data += QString("\r\n--") + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"status\"\r\n";
data += "Content-Transfer-Encoding: binary\r\n";
data += "Content-Type: text/plain; charset=utf-8\r\n\r\n";
data += message.toUtf8();
data += QString("\r\n--") + boundary + "--\r\n";

QNetworkRequest request;
// Using Twitter's REST API ver 1.1
request.setUrl(QUrl("https://api.twitter.com/1.1/statuses/update_with_media.json"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary);
request.setHeader(QNetworkRequest::ContentLengthHeader, data.length());

QNetworkReply *reply = requestor->post(request, QList<O1RequestParameter>(), data);
```c++
QString imagePath("/tmp/image.jpg");
QString message("My tweet with an image!");

QFileInfo fileInfo(imagePath);
QFile file(imagePath);
file.open(QIODevice::ReadOnly);

QString boundary("7d44e178b0439");
QByteArray data(QString("--" + boundary + "\r\n").toAscii());
data += "Content-Disposition: form-data; name=\"media[]\"; filename=\"" + fileInfo.fileName() + "\"\r\n";
data += "Content-Transfer-Encoding: binary\r\n";
data += "Content-Type: application/octet-stream\r\n\r\n";
data += file.readAll();
file.close();
data += QString("\r\n--") + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"status\"\r\n";
data += "Content-Transfer-Encoding: binary\r\n";
data += "Content-Type: text/plain; charset=utf-8\r\n\r\n";
data += message.toUtf8();
data += QString("\r\n--") + boundary + "--\r\n";

QNetworkRequest request;
// Using Twitter's REST API ver 1.1
request.setUrl(QUrl("https://api.twitter.com/1.1/statuses/update_with_media.json"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + boundary);
request.setHeader(QNetworkRequest::ContentLengthHeader, data.length());

QNetworkReply *reply = requestor->post(request, QList<O1RequestParameter>(), data);
```
That's it. Tweets using the O2 library!
### Storing OAuth Tokens
O2 provides simple storage classes for writing OAuth tokens in a peristent location. Currently, a QSettings based backing store **O2SettingsStore** is provided in O2. O2SettingsStore keeps all token values in an encrypted form. You have to specify the encryption key to use while constructing the object:
O2 provides simple storage classes for writing OAuth tokens in a peristent location. Currently, a QSettings based backing store **O0SettingsStore** is provided in O2. O2SettingsStore keeps all token values in an encrypted form. You have to specify the encryption key to use while constructing the object:
O0SettingsStore *settings = new O0SettingsStore("myencryptionkey");
// Set the store before starting OAuth, i.e before calling link()
o1->setStore(settings);
...
```c++
O0SettingsStore *settings = new O0SettingsStore("myencryptionkey");
// Set the store before starting OAuth, i.e before calling link()
o1->setStore(settings);
// ...
```

Once set, the O0BaseAuth takes ownership of the O0SettingsStore object.

You can also create it with your customized QSettings object. O2SettingsStore will then use that QSettings object for storing the tokens:

O0SettingsStore *settings = new O0SettingsStore(mySettingsObject, "myencryptionkey");
```c++
O0SettingsStore *settings = new O0SettingsStore(mySettingsObject, "myencryptionkey");
```

Once set, O2SettingsStore takes ownership of the QSettings object.

**Note:** If you do not specify a storage object to use, O2 will create one by default (which QSettings based), and use it. In such a case, a default encryption key is used for encrypting the data. *This is not a secure solution: prefer storing the tokens in a Keychain or Wallet based facility instead*.

**Note:** If using O2SettingsStore, make sure organization name, domain and application name are set:

```
```c++
QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");
```
### Extra OAuth Tokens
Some OAuth service providers provide additional information in the access token response. Eg: Twitter returns 2 additional tokens in it's access token response - *screen_name* and *user_id*.
Some OAuth services provide additional information in the access token response. For example Twitter returns two additional tokens: *screen_name* and *user_id*.
O2 provides all such tokens via the property - *extraTokens*. You can query this property after a successful OAuth exchange, i.e after the *linkingSucceeded()* signal has been emitted.
O2 exposes such tokens via the property *extraTokens*. You can query this property after a successful OAuth exchange, i.e after the *linkingSucceeded()* signal has been emitted.
## More Examples
Expand All @@ -236,11 +258,11 @@ twitterdemo | Command line client for authenticating with Twitter and posting st
## Change Log
### 1.0.2
* Last Qt5-only release
### 0.1.0
* Persist the extra tokens, too
* Add Qt Quick Twitter client example




0 comments on commit 8492f54

Please sign in to comment.