webengine/osswebengine/WebCore/platform/symbian/FormLoginStore.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 #include "config.h"
       
    19 #include "StringHash.h"
       
    20 #include "FormLoginStore.h"
       
    21 #include "FileStreamSymbian.h"
       
    22 #include <pbe.h>
       
    23 #include <pbedata.h>
       
    24 _LIT(KLoginDatFile, "c:\\private\\%08x\\login.dat");
       
    25 
       
    26 namespace WebCore {
       
    27 
       
    28 //------------------------------------------------------------------------------
       
    29 // LoginData
       
    30 //------------------------------------------------------------------------------
       
    31 LoginData::LoginData(FormLoginStore* s) : m_store(s)
       
    32 {
       
    33 }
       
    34 
       
    35 LoginData::LoginData(FormLoginStore* s, const String& realm, const String& uname, const String& uvalue, const String& pname, const String& pvalue)
       
    36             : m_realm(realm), m_usernameField(uname), m_usernameValue(uvalue), m_passwdField(pname), m_passwdValue(pvalue), m_store(s)
       
    37 {
       
    38 }
       
    39 
       
    40 LoginData::~LoginData()
       
    41 {
       
    42 }
       
    43 
       
    44 void LoginData::read(StreamInput& is)
       
    45 {
       
    46     String encryptedUser, encryptedPasswd;
       
    47     is>>m_realm>>m_usernameField>>encryptedUser>>m_passwdField>>encryptedPasswd;
       
    48     m_usernameValue = m_store->decrypt(encryptedUser);
       
    49     m_passwdValue = m_store->decrypt(encryptedPasswd);
       
    50 }
       
    51 
       
    52 void LoginData::write(StreamOutput& os) const
       
    53 {
       
    54     os<<m_realm<<m_usernameField<<m_store->encrypt(m_usernameValue)<<m_passwdField<<m_store->encrypt(m_passwdValue);
       
    55 }
       
    56 
       
    57 bool LoginData::partialMatch(const String& realm, const String& uname, const String& uvalue, const String& pname) const
       
    58 {
       
    59     return !(realm != m_realm || uname != m_usernameField || uvalue != m_usernameValue || pname != m_passwdField);
       
    60 }
       
    61 
       
    62 bool LoginData::match(const LoginData& b) const
       
    63 {
       
    64     return partialMatch(b.m_realm, b.m_usernameField, b.m_usernameValue, b.m_passwdField) && (m_passwdValue == b.m_passwdValue);
       
    65 }
       
    66 
       
    67 //------------------------------------------------------------------------------
       
    68 // FormLoginStore
       
    69 //------------------------------------------------------------------------------
       
    70 FormLoginStore::FormLoginStore() : m_needCommit(false), m_pbEncrypt(0), m_pbDecrypt(0)
       
    71 {
       
    72     initialize();
       
    73 }
       
    74 
       
    75 FormLoginStore::~FormLoginStore()
       
    76 {
       
    77     commit();
       
    78     clearCache();
       
    79     delete m_pbEncrypt;
       
    80     delete m_pbDecrypt;
       
    81 }
       
    82 
       
    83 void FormLoginStore::setSaveNotAllowed(const String& url)
       
    84 {
       
    85     m_blackList.add(url);
       
    86 }
       
    87 
       
    88 bool FormLoginStore::saveAllowed(const String& url) const
       
    89 {
       
    90     return !m_blackList.contains(url);
       
    91 }
       
    92 
       
    93 void FormLoginStore::add(const String& realm, const String& uname, const String& uvalue, const String& pname, const String& pvalue)
       
    94 {
       
    95     LoginData* login = new LoginData(this, realm, uname, uvalue, pname, pvalue);
       
    96     HashSet<LoginData*>::iterator it = m_logins.begin(), end = m_logins.end();
       
    97     for (; it!=end; ++it) {
       
    98         if ((*it)->match(*login)) {
       
    99             delete login;
       
   100             return;
       
   101         } else if((*it)->partialMatch(realm, uname, uvalue, pname)) {
       
   102             // new password for the same login
       
   103             m_logins.remove(it);
       
   104             m_logins.add(login);
       
   105             m_needCommit = true;
       
   106             return;
       
   107         }
       
   108     }
       
   109 
       
   110     // new entry
       
   111     m_logins.add(login);
       
   112     m_needCommit = true;
       
   113 }
       
   114 
       
   115 void FormLoginStore::remove(const String& realm, const String& uname, const String& uvalue, const String& pname, const String& pvalue)
       
   116 {
       
   117     LoginData login(this, realm, uname, uvalue, pname, pvalue);
       
   118     HashSet<LoginData*>::iterator it = m_logins.begin(), end = m_logins.end();
       
   119     for (; it!=end; ++it) {
       
   120         if ((*it)->match(login)) {
       
   121             break;
       
   122         }
       
   123     }
       
   124 
       
   125     if (it!=end) {
       
   126         m_logins.remove(it);
       
   127         m_needCommit = true;
       
   128     }
       
   129 }
       
   130 
       
   131 void FormLoginStore::removePartial(const String& realm, const String& uname, const String& uvalue, const String& pname)
       
   132 {
       
   133     HashSet<LoginData*>::iterator it = m_logins.begin(), end = m_logins.end();
       
   134     for(; it!=end; ++it) {
       
   135         if ((*it)->partialMatch(realm, uname, uvalue, pname)) {
       
   136             m_logins.remove(it);
       
   137             m_needCommit = true;
       
   138             return;
       
   139         }
       
   140     }
       
   141 }
       
   142 
       
   143 bool FormLoginStore::contains(const String& realm, const String& uname, const String& uvalue, const String& pname, const String& pvalue)
       
   144 {
       
   145     LoginData login(this, realm, uname, uvalue, pname, pvalue);
       
   146     HashSet<LoginData*>::iterator it = m_logins.begin(), end = m_logins.end();
       
   147     for (; it!=end; ++it) {
       
   148         if ((*it)->match(login)) {
       
   149             return true;
       
   150         }
       
   151     }
       
   152     return false;
       
   153 }
       
   154 
       
   155 void FormLoginStore::removeLoginsForRealm(const String& realm)
       
   156 {
       
   157     HashSet<LoginData*>::iterator it = m_logins.begin(), end = m_logins.end();
       
   158     Vector<LoginData*> loginsToDelete;
       
   159 
       
   160     for (; it!=end; ++it) {
       
   161         if( (*it)->realm() == realm ) {
       
   162             loginsToDelete.append( *it );
       
   163         }
       
   164     }
       
   165 
       
   166     for (int i=0; i<loginsToDelete.size(); ++i) {
       
   167         m_logins.remove(loginsToDelete[i]);
       
   168         m_needCommit = true;
       
   169     }
       
   170 }
       
   171 
       
   172 bool FormLoginStore::search(const String& realm, const String& uname, const String& uvalue, const String& pname, String& pvalue)
       
   173 {
       
   174     HashSet<LoginData*>::const_iterator it = m_logins.begin(), end = m_logins.end();
       
   175     for (; it != end; ++it) {
       
   176         if ((*it)->partialMatch(realm, uname, uvalue, pname)) {
       
   177             pvalue = (*it)->passwdValue();
       
   178             return true;
       
   179         }
       
   180     }
       
   181     return false;
       
   182 }
       
   183 
       
   184 // login file format: (Note: this is not the most compact format, 
       
   185 // however we need to keep it this way in order to be backward compatible.)
       
   186 // 
       
   187 // # of blacklist entries
       
   188 // url #1
       
   189 // url #2
       
   190 // ...
       
   191 // # of logins
       
   192 // encryption data for logins
       
   193 //  #1 realm, usernamefield, usernamevalue, passwdfield, passwdvalue
       
   194 //  #2 realm, usernamefield, usernamevalue, passwdfield, passwdvalue
       
   195 // ...
       
   196 void FormLoginStore::commit()
       
   197 {
       
   198     if (!m_needCommit) return;
       
   199 
       
   200 	RProcess myProcess;	
       
   201 	TBuf <256>fileName;    
       
   202     fileName.Format(KLoginDatFile, myProcess.Identity());
       
   203     String s(fileName.Ptr(), fileName.Length());
       
   204 	FileStreamOutput stream(s);
       
   205  
       
   206     if (stream.isOpened()) {
       
   207         // blacklist
       
   208         stream<<(m_blackList.size());
       
   209         for (HashSet<String>::const_iterator it=m_blackList.begin(), end = m_blackList.end(); it != end; ++it) {
       
   210             stream<<(*it);
       
   211         }
       
   212 
       
   213         // login count
       
   214         stream<<(m_logins.size());
       
   215         
       
   216         // write the encryption data if we have logins
       
   217         if (m_logins.size()>0) {
       
   218             if (!m_pbEncrypt)
       
   219                 m_pbEncrypt = CPBEncryptElement::NewL(_L8(""), ECipher3DES_CBC);
       
   220             m_pbEncrypt->EncryptionData().ExternalizeL(stream.platformStream());
       
   221         }
       
   222         
       
   223         // now logins
       
   224         for (HashSet<LoginData*>::const_iterator it=m_logins.begin(), end = m_logins.end(); it != end; ++it) {
       
   225             stream<<(*(*it));
       
   226         }
       
   227 
       
   228         delete m_pbEncrypt;
       
   229         m_pbEncrypt = 0;
       
   230     }
       
   231 
       
   232     m_needCommit = false;
       
   233 }
       
   234 
       
   235 void FormLoginStore::initialize()
       
   236 {
       
   237  	RProcess myProcess;	
       
   238 	TBuf <256>fileName;    
       
   239     fileName.Format(KLoginDatFile, myProcess.Identity());
       
   240     String s(fileName.Ptr(), fileName.Length());
       
   241 	FileStreamInput stream(s);
       
   242    
       
   243     if (stream.isOpened()) {
       
   244         // black-list
       
   245         int bsize = 0;
       
   246         stream>>bsize;
       
   247         for (int i=0; i<bsize; ++i) {
       
   248             String realm;
       
   249             stream>>realm;
       
   250             m_blackList.add(realm);
       
   251         }
       
   252 
       
   253         // logins
       
   254         int lsize = 0;
       
   255         stream>>lsize;
       
   256 
       
   257         CPBEncryptionData* encryptionData = 0;
       
   258         if (lsize) {
       
   259             // prepare for decryption 
       
   260             encryptionData = CPBEncryptionData::NewL(stream.platformStream());
       
   261             if (!m_pbDecrypt)
       
   262                 m_pbDecrypt = CPBEncryptElement::NewL(*encryptionData, _L(""));
       
   263         }
       
   264 
       
   265         for (int i=0; i<lsize; ++i) {
       
   266             LoginData* d = new LoginData(this);
       
   267             stream>>(*d);
       
   268             m_logins.add(d);
       
   269         }
       
   270 
       
   271         // encryptionData is not needed any more
       
   272         delete encryptionData;
       
   273         delete m_pbDecrypt;
       
   274         m_pbDecrypt = 0;
       
   275     }
       
   276 }
       
   277 
       
   278 void FormLoginStore::clearCache()
       
   279 {
       
   280     m_blackList.clear();
       
   281     HashSet<LoginData*>::const_iterator it = m_logins.begin(), end = m_logins.end();
       
   282     for(; it!=end; ++it)
       
   283         delete (*it);
       
   284     m_logins.clear();
       
   285 }
       
   286 
       
   287 void FormLoginStore::deleteAll()
       
   288 {
       
   289     // clear the file data
       
   290     clearCache();
       
   291     m_needCommit = true;
       
   292     commit();
       
   293 }
       
   294 
       
   295 String FormLoginStore::encrypt(const String& src)
       
   296 {
       
   297     if (!m_pbEncrypt)
       
   298         return src;
       
   299 
       
   300     CPBEncryptor* encryptor = m_pbEncrypt->NewEncryptLC();
       
   301     int len = encryptor->MaxFinalOutputLength(src.length()<<1);
       
   302     UChar* data = new UChar[len>>1];
       
   303     TPtrC8 in((const TUint8*)(src.characters()), src.length()<<1);
       
   304     TPtr8 out((TUint8*)data, 0, len);
       
   305     encryptor->ProcessFinalL(in, out);
       
   306     CleanupStack::Pop();  // encryptor
       
   307     delete encryptor;
       
   308 
       
   309     String result(data, len>>1);
       
   310     delete data;
       
   311 
       
   312     return result;
       
   313 }
       
   314 
       
   315 String FormLoginStore::decrypt(const String& src)
       
   316 {
       
   317     if (!m_pbDecrypt) 
       
   318         return src;
       
   319 
       
   320 	CPBDecryptor* decryptor = m_pbDecrypt->NewDecryptLC();
       
   321     int len = decryptor->MaxFinalOutputLength(src.length()<<1);
       
   322     len += (len&0x01);
       
   323     UChar* data = new UChar[len>>1];
       
   324     memset(data, 0x00, len);
       
   325     TPtrC8 in((const TUint8*)(src.characters()), src.length()<<1);
       
   326     TPtr8 out((TUint8*)data, 0, len);
       
   327     decryptor->ProcessFinalL(in, out);
       
   328     CleanupStack::Pop(); // decryptor
       
   329     delete decryptor;
       
   330 
       
   331     // now figure out the padding position
       
   332     int sz=0;
       
   333     for (int i=0; i<len>>1; ++i) {
       
   334         if (data[i] == 0) break;
       
   335         sz++;
       
   336     }
       
   337         
       
   338     String result(data, sz);
       
   339     delete data;
       
   340 
       
   341     return result;
       
   342 }
       
   343 
       
   344 }