Smailez – Chat software (C++/Qt)

The websites Smail.fr & Jasez.ca use both the same source code but on two different servers. These websites, community-oriented, have for main fonction a Chat written in Java.

In my free time, to learn network development with Qt framework, I developed a chat software connecting to both smail.fr & jasez.ca servers (aught that you have correct credential for both servers) to unify both systems in a unique user interface.

This development, detailed hereafter, turned more complex and ambitious than expected.

Servers connection

To limit usage of clients like I made, the connection to Smail or Jasez is well protected.

The first step is to authenticate himself on the web server by using its username and password to generate a cookie containing the SESSID we will need later.

User who wants to use the chat needs to do the following steps:

  • Authenticate himself on smail.fr or jasez.ca
  • Configure options for connections
    • Choose pseudo/alias
    • Age
    • Gender
    • City
  • Choose the channel

Once these options are configured, the user click on the connection button, it opens a popup linking to the chat (Java applet) as well as a key (called TID) used when the client is connecting to the chat server.

The TID is a unique key generated for each client connection to the chat server. I don’t know the algorithm generating the TID, nevertheless, when the TID is generated, it is saved into the database. When the client connect to the chat, the Java applet open a connection to the chat server which return a welcome message and wait for the TID. Once the TID is send, the server check if it is correct and set an invalid flag for all futures connections using the same TID.

It is useless to try to understand the algorithm generating the TID, save a SQL injection issue, we can’t force its entry into the database.

Project complexities

  • Get the SESSID from smail.fr and jasez.ca
  • Get the TID from smail.fr and jasez.ca
  • Get the responses from both smail.fr and jasez.ca serversRecevoir les réponses des serveurs smail.fr et jasez.ca
  • Getting to know where the response is coming from (smail.fr or jasez.ca)/li>
  • Learn and respect the communication protocol

Source code

Get the cookie containing the SESSID
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//Get the cookie containing the SESSID
void SmailezLogin::recuperationCookie(const QHttpResponseHeader& header)
{
// Ce test est tiré de la norme RFC 1945
if ( header.reasonPhrase().toUpper() == "FOUND" && (header.statusCode() >= 300 && header.statusCode() <= 399) )
{
// Récupération du cookie
qDebug() << header.toString();
QString cookie = header.value("Set-Cookie");
emit reply(cookie, header.value("Location"));
iFlagRecuperation ++;
//iFlagConnexion indicate the number of time the connection has to be established.
//iFlagRecuperation indicate the number of time we went into this fonction.
//If iFlagConnexion and iFlagRecuperation are equal, means we have all the required data.
if(iFlagConnexion == iFlagRecuperation)
{
QStringList strSmailValues, strJasezValues;
strSmailValues << "Smail";
strSmailValues << ui->txtSmailezAge->text();
strSmailValues << ui->txtSmailezUsername->text();
strSmailValues << ui->cmbSmailezSexe->itemData(ui->cmbSmailezSexe->currentIndex()).toString();
strSmailValues << ui->txtSmailezVille->text();
strJasezValues << "Jasez";
strJasezValues << ui->txtJasezAge->text();
strJasezValues << ui->txtJasezUsername->text();
strJasezValues << ui->cmbJasezSexe->itemData(ui->cmbJasezSexe->currentIndex()).toString();
strJasezValues << ui->txtJasezVille->text();
emit finished(strSmailValues, strJasezValues);
this->close();
}
}
else
{
QMessageBox *msg = new QMessageBox(QMessageBox::Warning, "Erreur d'identifiant", "Vos identifiants sont incorrects.", QMessageBox::Ok);
msg->exec();
}
}

Get the TID
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//Get the TID
void SmailezQNetwork::fRetreiveTID(QString _SessID)
{
QString _url = "http://www."+ this->_provider +"/chat";
QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkCookieJar *managersetCookieJar = new QNetworkCookieJar(manager);
manager->setCookieJar(managersetCookieJar);
QNetworkRequest request;
request.setUrl(QUrl(_url));
request.setRawHeader("Host", "www."+ this->_provider.toUtf8());
request.setRawHeader("User-Agent", "User-Agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:6.0.1) Gecko/20100101 Firefox/6.0.1");
request.setRawHeader("Accept", "Accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.setRawHeader("Accept-Language", "Accept-Language=fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3");
request.setRawHeader("Accept-Charset", "Accept-Charset=ISO-8859-1,utf-8;q=0.7,*;q=0.7");
request.setRawHeader("DNT", "1");
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setRawHeader("Connection", "keep-alive");
request.setRawHeader("Referer", "http://www."+ this->_provider.toUtf8() +"/chat");
request.setRawHeader("Pragma", "no-cache");
request.setRawHeader("Cache-Control", "no-cache");
QList<QNetworkCookie>cookie;
cookie.append(QNetworkCookie("PHPSESSID", _SessID.toUtf8()));
manager->cookieJar()->setCookiesFromUrl(cookie, QUrl(_url));
QByteArray _postData;
_postData.append("action=join&");
_postData.append("room="+ _userInfos[0] +"&");
_postData.append("avatar=459053&");
_postData.append("alias="+ _userInfos[2] +"&");
_postData.append("age="+ _userInfos[1] +"&");
_postData.append("gender="+ _userInfos[3] +"&");
_postData.append("city="+ _userInfos[4] +"&");
_postData.append("color=1");
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(result(QNetworkReply *)));
manager->post(request, _postData );
qDebug() << "Try to get the TID for " << this->_provider << " (pseudo: " << this->_userInfos[2] << ")";
}

Source reading and extract the TID
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Source reading and extract the TID
void SmailezQNetwork::result(QNetworkReply *reply)
{
QString source = reply->readAll();
qDebug() << source;
int begin = source.indexOf("<param name=\"TID\"")+25; //29
int end = source.indexOf("<param name=\"salon\"", begin)-15;
QString tid = source.mid(begin, end-begin);
if(this->strTID == "")
this->strTID = "1";
this->fConnection();
if(!tid.isEmpty() && end > 0)
{
this->strTID = tid;
this->fConnection();
}
qDebug() << "TID: " << this->strTID;
}

Screenshots

   

Files
Smailez v0.1a (executable)
Smailez Source v0.1a (source, Qt 4.7.3/Mingw)

This entry was posted in Free Projects and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>