1/*
2 * Copyright (C) 2010 Stephan A��mus <superstippi@gmx.de>
3 *
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6
7#include "CredentialsStorage.h"
8
9#include <new>
10#include <stdio.h>
11
12#include <Autolock.h>
13#include <Entry.h>
14#include <File.h>
15#include <FindDirectory.h>
16#include <Message.h>
17#include <Path.h>
18
19#include "BrowserApp.h"
20
21
22Credentials::Credentials()
23	:
24	fUsername(),
25	fPassword()
26{
27}
28
29
30Credentials::Credentials(const BString& username, const BString& password)
31	:
32	fUsername(username),
33	fPassword(password)
34{
35}
36
37
38Credentials::Credentials(const Credentials& other)
39{
40	*this = other;
41}
42
43
44Credentials::Credentials(const BMessage* archive)
45{
46	if (archive == NULL)
47		return;
48	archive->FindString("username", &fUsername);
49	archive->FindString("password", &fPassword);
50}
51
52
53Credentials::~Credentials()
54{
55}
56
57
58status_t
59Credentials::Archive(BMessage* archive) const
60{
61	if (archive == NULL)
62		return B_BAD_VALUE;
63	status_t status = archive->AddString("username", fUsername);
64	if (status == B_OK)
65		status = archive->AddString("password", fPassword);
66	return status;
67}
68
69
70Credentials&
71Credentials::operator=(const Credentials& other)
72{
73	if (this == &other)
74		return *this;
75
76	fUsername = other.fUsername;
77	fPassword = other.fPassword;
78
79	return *this;
80}
81
82
83bool
84Credentials::operator==(const Credentials& other) const
85{
86	if (this == &other)
87		return true;
88
89	return fUsername == other.fUsername && fPassword == other.fPassword;
90}
91
92
93bool
94Credentials::operator!=(const Credentials& other) const
95{
96	return !(*this == other);
97}
98
99
100const BString&
101Credentials::Username() const
102{
103	return fUsername;
104}
105
106
107const BString&
108Credentials::Password() const
109{
110	return fPassword;
111}
112
113
114// #pragma mark - CredentialsStorage
115
116
117CredentialsStorage
118CredentialsStorage::sPersistentInstance(true);
119
120
121CredentialsStorage
122CredentialsStorage::sSessionInstance(false);
123
124
125CredentialsStorage::CredentialsStorage(bool persistent)
126	:
127	BLocker(persistent ? "persistent credential storage"
128		: "credential storage"),
129	fCredentialMap(),
130	fSettingsLoaded(false),
131	fPersistent(persistent)
132{
133}
134
135
136CredentialsStorage::~CredentialsStorage()
137{
138	_SaveSettings();
139}
140
141
142/*static*/ CredentialsStorage*
143CredentialsStorage::SessionInstance()
144{
145	return &sSessionInstance;
146}
147
148
149/*static*/ CredentialsStorage*
150CredentialsStorage::PersistentInstance()
151{
152	if (sPersistentInstance.Lock()) {
153		sPersistentInstance._LoadSettings();
154		sPersistentInstance.Unlock();
155	}
156	return &sPersistentInstance;
157}
158
159
160bool
161CredentialsStorage::Contains(const HashKeyString& key)
162{
163	BAutolock _(this);
164
165	return fCredentialMap.ContainsKey(key);
166}
167
168
169status_t
170CredentialsStorage::PutCredentials(const HashKeyString& key,
171	const Credentials& credentials)
172{
173	BAutolock _(this);
174
175	return fCredentialMap.Put(key, credentials);
176}
177
178
179Credentials
180CredentialsStorage::GetCredentials(const HashKeyString& key)
181{
182	BAutolock _(this);
183
184	return fCredentialMap.Get(key);
185}
186
187
188// #pragma mark - private
189
190
191void
192CredentialsStorage::_LoadSettings()
193{
194	if (!fPersistent || fSettingsLoaded)
195		return;
196
197	fSettingsLoaded = true;
198
199	BFile settingsFile;
200	if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) {
201		BMessage settingsArchive;
202		settingsArchive.Unflatten(&settingsFile);
203		BMessage credentialsArchive;
204		for (int32 i = 0; settingsArchive.FindMessage("credentials", i,
205				&credentialsArchive) == B_OK; i++) {
206			BString key;
207			if (credentialsArchive.FindString("key", &key) == B_OK) {
208				Credentials credentials(&credentialsArchive);
209				fCredentialMap.Put(key, credentials);
210			}
211		}
212	}
213}
214
215
216void
217CredentialsStorage::_SaveSettings() const
218{
219	BFile settingsFile;
220	if (_OpenSettingsFile(settingsFile,
221			B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) {
222		BMessage settingsArchive;
223		BMessage credentialsArchive;
224		CredentialMap::Iterator iterator = fCredentialMap.GetIterator();
225		while (iterator.HasNext()) {
226			const CredentialMap::Entry& entry = iterator.Next();
227			if (entry.value.Archive(&credentialsArchive) != B_OK
228				|| credentialsArchive.AddString("key",
229					entry.key.value) != B_OK) {
230				break;
231			}
232			if (settingsArchive.AddMessage("credentials",
233					&credentialsArchive) != B_OK) {
234				break;
235			}
236			credentialsArchive.MakeEmpty();
237		}
238		settingsArchive.Flatten(&settingsFile);
239	}
240}
241
242
243bool
244CredentialsStorage::_OpenSettingsFile(BFile& file, uint32 mode) const
245{
246	BPath path;
247	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
248		|| path.Append(kApplicationName) != B_OK
249		|| path.Append("CredentialsStorage") != B_OK) {
250		return false;
251	}
252	return file.SetTo(path.Path(), mode) == B_OK;
253}
254
255