1/* 2 * Copyright (C) 2010 Stephan A��mus <superstippi@gmx.de> 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "CredentialsStorage.h" 29 30#include <new> 31#include <stdio.h> 32 33#include <Autolock.h> 34#include <Entry.h> 35#include <File.h> 36#include <FindDirectory.h> 37#include <Message.h> 38#include <Path.h> 39 40#include "BrowserApp.h" 41 42 43Credentials::Credentials() 44 : 45 fUsername(), 46 fPassword() 47{ 48} 49 50 51Credentials::Credentials(const BString& username, const BString& password) 52 : 53 fUsername(username), 54 fPassword(password) 55{ 56} 57 58 59Credentials::Credentials(const Credentials& other) 60{ 61 *this = other; 62} 63 64 65Credentials::Credentials(const BMessage* archive) 66{ 67 if (archive == NULL) 68 return; 69 archive->FindString("username", &fUsername); 70 archive->FindString("password", &fPassword); 71} 72 73 74Credentials::~Credentials() 75{ 76} 77 78 79status_t 80Credentials::Archive(BMessage* archive) const 81{ 82 if (archive == NULL) 83 return B_BAD_VALUE; 84 status_t status = archive->AddString("username", fUsername); 85 if (status == B_OK) 86 status = archive->AddString("password", fPassword); 87 return status; 88} 89 90 91Credentials& 92Credentials::operator=(const Credentials& other) 93{ 94 if (this == &other) 95 return *this; 96 97 fUsername = other.fUsername; 98 fPassword = other.fPassword; 99 100 return *this; 101} 102 103 104bool 105Credentials::operator==(const Credentials& other) const 106{ 107 if (this == &other) 108 return true; 109 110 return fUsername == other.fUsername && fPassword == other.fPassword; 111} 112 113 114bool 115Credentials::operator!=(const Credentials& other) const 116{ 117 return !(*this == other); 118} 119 120 121const BString& 122Credentials::Username() const 123{ 124 return fUsername; 125} 126 127 128const BString& 129Credentials::Password() const 130{ 131 return fPassword; 132} 133 134 135// #pragma mark - CredentialsStorage 136 137 138CredentialsStorage 139CredentialsStorage::sPersistentInstance(true); 140 141 142CredentialsStorage 143CredentialsStorage::sSessionInstance(false); 144 145 146CredentialsStorage::CredentialsStorage(bool persistent) 147 : 148 BLocker(persistent ? "persistent credential storage" 149 : "credential storage"), 150 fCredentialMap(), 151 fSettingsLoaded(false), 152 fPersistent(persistent) 153{ 154} 155 156 157CredentialsStorage::~CredentialsStorage() 158{ 159 _SaveSettings(); 160} 161 162 163/*static*/ CredentialsStorage* 164CredentialsStorage::SessionInstance() 165{ 166 return &sSessionInstance; 167} 168 169 170/*static*/ CredentialsStorage* 171CredentialsStorage::PersistentInstance() 172{ 173 if (sPersistentInstance.Lock()) { 174 sPersistentInstance._LoadSettings(); 175 sPersistentInstance.Unlock(); 176 } 177 return &sPersistentInstance; 178} 179 180 181bool 182CredentialsStorage::Contains(const HashKeyString& key) 183{ 184 BAutolock _(this); 185 186 return fCredentialMap.ContainsKey(key); 187} 188 189 190status_t 191CredentialsStorage::PutCredentials(const HashKeyString& key, 192 const Credentials& credentials) 193{ 194 BAutolock _(this); 195 196 return fCredentialMap.Put(key, credentials); 197} 198 199 200Credentials 201CredentialsStorage::GetCredentials(const HashKeyString& key) 202{ 203 BAutolock _(this); 204 205 return fCredentialMap.Get(key); 206} 207 208 209// #pragma mark - private 210 211 212void 213CredentialsStorage::_LoadSettings() 214{ 215 if (!fPersistent || fSettingsLoaded) 216 return; 217 218 fSettingsLoaded = true; 219 220 BFile settingsFile; 221 if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { 222 BMessage settingsArchive; 223 settingsArchive.Unflatten(&settingsFile); 224 BMessage credentialsArchive; 225 for (int32 i = 0; settingsArchive.FindMessage("credentials", i, 226 &credentialsArchive) == B_OK; i++) { 227 BString key; 228 if (credentialsArchive.FindString("key", &key) == B_OK) { 229 Credentials credentials(&credentialsArchive); 230 fCredentialMap.Put(key, credentials); 231 } 232 } 233 } 234} 235 236 237void 238CredentialsStorage::_SaveSettings() const 239{ 240 BFile settingsFile; 241 if (_OpenSettingsFile(settingsFile, 242 B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { 243 BMessage settingsArchive; 244 BMessage credentialsArchive; 245 CredentialMap::Iterator iterator = fCredentialMap.GetIterator(); 246 while (iterator.HasNext()) { 247 const CredentialMap::Entry& entry = iterator.Next(); 248 if (entry.value.Archive(&credentialsArchive) != B_OK 249 || credentialsArchive.AddString("key", 250 entry.key.value) != B_OK) { 251 break; 252 } 253 if (settingsArchive.AddMessage("credentials", 254 &credentialsArchive) != B_OK) { 255 break; 256 } 257 credentialsArchive.MakeEmpty(); 258 } 259 settingsArchive.Flatten(&settingsFile); 260 } 261} 262 263 264bool 265CredentialsStorage::_OpenSettingsFile(BFile& file, uint32 mode) const 266{ 267 BPath path; 268 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK 269 || path.Append(kApplicationName) != B_OK 270 || path.Append("CredentialsStorage") != B_OK) { 271 return false; 272 } 273 return file.SetTo(path.Path(), mode) == B_OK; 274} 275 276