Import release 2.0alpha2
This commit is contained in:
@@ -0,0 +1,414 @@
|
||||
/***************************************************************************
|
||||
kmessshared.cpp - description
|
||||
-------------------
|
||||
begin : Thu May 8 2008
|
||||
copyright : (C) 2008 by Valerio Pilo
|
||||
email : valerio@kmess.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "kmessshared.h"
|
||||
|
||||
#include "../kmess.h"
|
||||
#include "../kmessapplication.h"
|
||||
#include "../kmessdebug.h"
|
||||
#include "../currentaccount.h"
|
||||
#include "../network/soap/passportloginservice.h"
|
||||
#include "kmessconfig.h"
|
||||
|
||||
#include <KRun>
|
||||
#include <KUrl>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QFile>
|
||||
|
||||
#ifdef KMESSDEBUG_SHAREDMETHODS
|
||||
#define KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Create a HMACSha1 hash
|
||||
QByteArray KMessShared::createHMACSha1 ( const QByteArray &keyForHash , const QByteArray &secret )
|
||||
{
|
||||
// The algorithm is definited into RFC 2104
|
||||
int blocksize = 64;
|
||||
QByteArray key( keyForHash );
|
||||
QByteArray data( secret );
|
||||
QByteArray opad( blocksize, 0x5c );
|
||||
QByteArray ipad( blocksize, 0x36 );
|
||||
|
||||
// If key size is too larg, compute the hash
|
||||
if( key.size() > blocksize )
|
||||
{
|
||||
key = QCryptographicHash::hash( key, QCryptographicHash::Sha1 );
|
||||
}
|
||||
|
||||
// If too small, pad with 0x00
|
||||
if( key.size() < blocksize )
|
||||
{
|
||||
key += QByteArray( blocksize - key.size() , 0x00 );
|
||||
|
||||
}
|
||||
|
||||
// Compute the XOR operations
|
||||
for(int i=0; i < key.size() - 1; i++ )
|
||||
{
|
||||
ipad[i] = (char) ( ipad[i] ^ key[i] );
|
||||
opad[i] = (char) ( opad[i] ^ key[i] );
|
||||
}
|
||||
|
||||
// Append the data to ipad
|
||||
ipad += data;
|
||||
|
||||
// Compute result: hash sha1 of ipad
|
||||
QByteArray result;
|
||||
result = QCryptographicHash::hash( ipad, QCryptographicHash::Sha1 );
|
||||
|
||||
// Append the data to opad
|
||||
opad += result;
|
||||
|
||||
// Return array contains the result of HMACSha1
|
||||
return QCryptographicHash::hash( opad, QCryptographicHash::Sha1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create the html file to request the given service
|
||||
QString KMessShared::createRequestFile( const QString &folder )
|
||||
{
|
||||
CurrentAccount *currentAccount = CurrentAccount::instance();
|
||||
|
||||
// Use the method into passport to compute the token
|
||||
QString token = PassportLoginService::createHotmailToken( currentAccount->getPassportToken(),
|
||||
currentAccount->getProofToken(), folder );
|
||||
|
||||
// Use one file for hml page with post method
|
||||
QString filename = KMessConfig::instance()->getAccountDirectory( currentAccount-> getHandle() )
|
||||
+ "/hotmail.htm";
|
||||
|
||||
QFile file( filename );
|
||||
if ( ! file.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
QTextStream outBuffer( &file );
|
||||
|
||||
QString pageHtml = "<html><head></head><body onload=\"document.pform.submit(); \"><form name=\"pform\""
|
||||
"action=\"https://login.live.com/ppsecure/sha1auth.srf?lc=" + currentAccount->getLanguageCode() +
|
||||
"\" method=\"POST\"><input type=\"hidden\" name=\"token\" value=\"";
|
||||
|
||||
pageHtml += token + "\"><noscript>Enable yout javascript, please!<br /> <br /> <input type=\"submit\""
|
||||
"value=\"Click here to get redirected\"/></noscript></form></body></html>";
|
||||
|
||||
// Write and close the file
|
||||
outBuffer << pageHtml;
|
||||
file.close();
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Return a derived key with HMACSha1 algorithm
|
||||
QByteArray KMessShared::deriveKey ( const QByteArray &keyToDerive, const QByteArray &magic )
|
||||
{
|
||||
// create the four hashes needed for the implementation.
|
||||
QByteArray hash1, hash2, hash3, hash4, temp;
|
||||
QByteArray key(keyToDerive);
|
||||
|
||||
// append the magic string.
|
||||
temp.append ( magic );
|
||||
|
||||
// create the HMAC Sha1 hash and assign it.
|
||||
hash1 = createHMACSha1 ( key, temp );
|
||||
temp.clear();
|
||||
|
||||
// append the first hash with the magic string.
|
||||
temp.append ( hash1 + magic );
|
||||
|
||||
// create the HMAC Sha1 hash and assign it.
|
||||
hash2 = createHMACSha1 ( key, temp );
|
||||
temp.clear();
|
||||
|
||||
// append the first hash.
|
||||
temp.append ( hash1 );
|
||||
|
||||
// create the HMAC Sha1 hash and assign it.
|
||||
hash3 = createHMACSha1 ( key, temp );
|
||||
temp.clear();
|
||||
|
||||
// assign the third hash with the magic string.
|
||||
temp.append ( hash3 + magic );
|
||||
// create the HMAC Sha1 hash and assign it.
|
||||
hash4 = createHMACSha1 ( key, temp );
|
||||
temp.clear();
|
||||
|
||||
// return the second hash with the first four bytes of the fourth hash.
|
||||
return hash2 + hash4.left ( 4 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate a random GUID.
|
||||
*
|
||||
* This is used in MSNP2P for the Call ID and Branch ID.
|
||||
*
|
||||
* @return A randomly generated GUID value.
|
||||
*/
|
||||
QString KMessShared::generateGUID()
|
||||
{
|
||||
// This code is based on Kopete, but much shorter.
|
||||
QString guid = "{"
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ "-"
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ "-"
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ "-"
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ "-"
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ QString::number((rand() & 0xAAFF) + 0x1111, 16)
|
||||
+ "}";
|
||||
return guid.toUpper();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate an random number to use as ID.
|
||||
*
|
||||
* For use in MSNP2P, the value will not be below 4
|
||||
*
|
||||
* @return A random value between 4 and 4294967295.
|
||||
*/
|
||||
unsigned long KMessShared::generateID()
|
||||
{
|
||||
return (rand() & 0x00FFFFFC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Return the hash of a file name using the SHA1 algorithm
|
||||
QByteArray KMessShared::generateFileHash( const QString &fileName )
|
||||
{
|
||||
// Read the file's contents into a byte array
|
||||
QFile file( fileName );
|
||||
if( ! file.open( QIODevice::ReadOnly ) )
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray fileData( file.readAll() );
|
||||
|
||||
file.close();
|
||||
|
||||
// Retrieve and return the file's hash
|
||||
return QCryptographicHash::hash( fileData, QCryptographicHash::Sha1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open the given URL respecting the user's preference
|
||||
*
|
||||
* The program which will open the URL is the one selected in the Global Settings
|
||||
*
|
||||
* @param url The URL to open
|
||||
*/
|
||||
void KMessShared::openBrowser( const KUrl &url )
|
||||
{
|
||||
// Open the options
|
||||
KConfigGroup group = KMessConfig::instance()->getGlobalConfig( "General" );
|
||||
|
||||
QString browser;
|
||||
QString fallbackBrowser( group.readEntry( "customBrowser", "konqueror" ) );
|
||||
|
||||
// Obtain the widget of the main KMess window, to correctly link it to the opened browser
|
||||
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
|
||||
QWidget *mainWindow = kmessApp->getContactListWindow()->window();
|
||||
|
||||
// Read which browser has to be opened
|
||||
QString browserChoice( group.readEntry( "useBrowser", "KDE" ) );
|
||||
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Opening URL" << url << "- The setting is" << browserChoice;
|
||||
#endif
|
||||
|
||||
// If the preference had an invalid choice, use the KDE default browser.
|
||||
if( browserChoice != "custom"
|
||||
&& browserChoice != "listed"
|
||||
&& browserChoice != "KDE" )
|
||||
{
|
||||
kWarning() << "Invalid browser choice:" << browserChoice << ", using KDE default.";
|
||||
|
||||
browserChoice = "KDE";
|
||||
}
|
||||
|
||||
// Launch the appropriate browser
|
||||
if( browserChoice == "custom" )
|
||||
{
|
||||
browser = group.readEntry( "customBrowser", fallbackBrowser );
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Custom browser selected:" << browser;
|
||||
#endif
|
||||
}
|
||||
else if( browserChoice == "listed" )
|
||||
{
|
||||
browser = group.readEntry( "listedBrowser", fallbackBrowser );
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Listed browser selected:" << browser;
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the option isn't valid use the KDE default
|
||||
if( browser.isEmpty() )
|
||||
{
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Invalid browser option, using KDE default.";
|
||||
#endif
|
||||
browserChoice = "KDE";
|
||||
}
|
||||
|
||||
if( browserChoice == "KDE" )
|
||||
{
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "KDE default browser selected.";
|
||||
#endif
|
||||
new KRun( url, mainWindow );
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace the %u in the command line with the actual URL, and launch the browser.
|
||||
browser.replace( "%u", "\"" + url.url() + "\"", Qt::CaseInsensitive );
|
||||
KRun::run( browser, KUrl::List(), mainWindow );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open the given URL mail respecting the user's preference
|
||||
*
|
||||
* The program which will open the URL is the one selected in the Global Settings
|
||||
*
|
||||
* @param folder The folder to open.
|
||||
* @param isHotmailAvailable Whether Hotmail can be used to access the e-mail for this account.
|
||||
*/
|
||||
void KMessShared::openEmailClient( const QString folder, bool isHotmailAvailable )
|
||||
{
|
||||
// Open the options
|
||||
KConfigGroup group = KMessConfig::instance()->getGlobalConfig( "General" );
|
||||
|
||||
// When using Live! Mail accounts, the webmail can be used
|
||||
if( isHotmailAvailable && group.readEntry( "useLiveMail", true ) )
|
||||
{
|
||||
// Create the request file
|
||||
QString filename( createRequestFile( folder ) );
|
||||
if( ! filename.isEmpty() )
|
||||
{
|
||||
// Open the webmail in the browser
|
||||
openBrowser( KUrl( "file://" + filename ) );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QString mailClient;
|
||||
QString fallbackMailClient( group.readEntry( "customMailClient", "kmail" ) );
|
||||
|
||||
// Obtain the widget of the main KMess window, to correctly link it to the opened app
|
||||
KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
|
||||
QWidget *mainWindow = kmessApp->getContactListWindow()->window();
|
||||
|
||||
// Read which mail client has to be opened
|
||||
QString mailClientChoice( group.readEntry( "useMailClient", "KDE" ) );
|
||||
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Opening mail at" << folder << "- The setting is" << mailClientChoice;
|
||||
#endif
|
||||
|
||||
// If the preference had an invalid choice, use the KDE default mail client.
|
||||
if( mailClientChoice != "custom"
|
||||
&& mailClientChoice != "listed"
|
||||
&& mailClientChoice != "KDE" )
|
||||
{
|
||||
kWarning() << "Invalid mail client choice:" << mailClientChoice << ", using KDE default.";
|
||||
|
||||
mailClientChoice = "KDE";
|
||||
}
|
||||
|
||||
// Launch the appropriate mail client
|
||||
if( mailClientChoice == "custom" )
|
||||
{
|
||||
mailClient = group.readEntry( "customMailClient", fallbackMailClient );
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Custom mail client selected:" << mailClient;
|
||||
#endif
|
||||
}
|
||||
else if( mailClientChoice == "listed" )
|
||||
{
|
||||
mailClient = group.readEntry( "listedMailClient", fallbackMailClient );
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Listed mail client selected:" << mailClient;
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the option isn't valid use the KDE default
|
||||
if( mailClient.isEmpty() )
|
||||
{
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "Invalid mail client option, using KDE default.";
|
||||
#endif
|
||||
mailClientChoice = "KDE";
|
||||
}
|
||||
|
||||
// Retrieve the mail address to open
|
||||
QString handleToSend;
|
||||
if( folder.contains( "?mailto=1&to=" ) )
|
||||
{
|
||||
handleToSend = folder.split( "?mailto=1&to=" )[1];
|
||||
}
|
||||
|
||||
if( mailClientChoice == "KDE" )
|
||||
{
|
||||
#ifdef KMESSDEBUG_SHARED_OPENEXTERNAL
|
||||
kDebug() << "KDE default mail client selected.";
|
||||
#endif
|
||||
new KRun( "mailto:" + handleToSend, mainWindow );
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace the %u in the command line with the contact address, and launch the application.
|
||||
mailClient.replace( "%u", "\"" + handleToSend + "\"", Qt::CaseInsensitive );
|
||||
KRun::run( mailClient, KUrl::List(), mainWindow );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Open the give Profile
|
||||
void KMessShared::openProfile( const QString &handle )
|
||||
{
|
||||
QString folder = "http://members.msn.com/default.msnw?mem=" + handle + "&pgmarket";
|
||||
QString filename = createRequestFile( folder );
|
||||
if( filename.isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the profile in the browser
|
||||
openBrowser( KUrl( "file://" + filename ) );
|
||||
}
|
||||
Reference in New Issue
Block a user