pt_BR strings updates
[adiumx.git] / Source / AdiumPasswords.m
blobe5b0c5dd657d89781edabff5cd65e679abdb3154
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  * 
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import <Adium/AIAccountControllerProtocol.h>
18 #import <Adium/AILoginControllerProtocol.h>
19 #import "AdiumPasswords.h"
20 #import "ESAccountPasswordPromptController.h"
21 #import "ESProxyPasswordPromptController.h"
22 #import <AIUtilities/AIKeychain.h>
23 #import <AIUtilities/AIObjectAdditions.h>
24 #import <Adium/AIAccount.h>
25 #import <Adium/AIService.h>
27 @interface AdiumPasswords (PRIVATE)
28 - (NSString *)_accountNameForAccount:(AIAccount *)inAccount;
29 - (NSString *)_passKeyForAccount:(AIAccount *)inAccount;
30 - (NSString *)_accountNameForProxyServer:(NSString *)proxyServer userName:(NSString *)userName;
31 - (NSString *)_passKeyForProxyServer:(NSString *)proxyServer;
32 @end
34 @implementation AdiumPasswords
36 //Accounts -------------------------------------------------------------------------------------------------------------
37 #pragma mark Accounts
39 /*!
40  * @brief Set the password of an account
41  *
42  * @param inPassword password to store
43  * @param inAccount account the password belongs to
44  */
45 - (void)setPassword:(NSString *)inPassword forAccount:(AIAccount *)inAccount
47         NSError *error = nil;
48         [[AIKeychain defaultKeychain_error:&error] setInternetPassword:inPassword
49                                                                                                                  forServer:[self _passKeyForAccount:inAccount]
50                                                                                                                    account:[self _accountNameForAccount:inAccount]
51                                                                                                                   protocol:FOUR_CHAR_CODE('AdIM')
52                                                                                                                          error:&error];
53         if (error) {
54                 OSStatus err = [error code];
55                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
56                  *we don't ignore it if we're trying to set the password, though (because that would be strange).
57                  *we don't get here at all for noErr (error will be nil).
58                  */
59                 if (inPassword || (err != errSecItemNotFound)) {
60                         NSDictionary *userInfo = [error userInfo];
61                         NSLog(@"could not %@ password for account %@: %@ returned %i (%@)", inPassword ? @"set" : @"remove", [self _accountNameForAccount:inAccount], [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME], err, [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
62                 }
63         }
66 /*!
67  * @brief Forget the password of an account
68  *
69  * @param inAccount account whose password should be forgotten
70  */
71 - (void)forgetPasswordForAccount:(AIAccount *)inAccount
73         NSError         *error    = nil;
74         AIKeychain      *keychain = [AIKeychain defaultKeychain_error:&error];
75         [keychain deleteInternetPasswordForServer:[self _passKeyForAccount:inAccount]
76                 account:[self _accountNameForAccount:inAccount]
77                 protocol:FOUR_CHAR_CODE('AdIM')
78                 error:&error];
79         if (error) {
80                 OSStatus err = [error code];
81                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
82                  *we don't get here at all for noErr (error will be nil).
83                  */
84                 if (err != errSecItemNotFound) {
85                         NSDictionary *userInfo = [error userInfo];
86                         NSLog(@"could not delete password for account %@: %@ returned %i (%@)", [self _accountNameForAccount:inAccount], [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME], err, [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
87                 }
88         }
91 /*!
92  * @brief Retrieve the password of an account
93  * 
94  * @param inAccount account whose password is desired
95  * @return account password, or nil if the password is not available
96  */
97 - (NSString *)passwordForAccount:(AIAccount *)inAccount
99         NSError         *error    = nil;
100         AIKeychain      *keychain = [AIKeychain defaultKeychain_error:&error];
101         NSString        *password = [keychain internetPasswordForServer:[self _passKeyForAccount:inAccount]
102                                                                                                                 account:[self _accountNameForAccount:inAccount]
103                                                                                                            protocol:FOUR_CHAR_CODE('AdIM')
104                                                                                                                   error:&error];
105         if (error) {
106                 OSStatus err = [error code];
107                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
108                  *we don't get here at all for noErr (error will be nil).
109                  */
110                 if (err != errSecItemNotFound) {
111                         NSDictionary *userInfo = [error userInfo];
112                         NSLog(@"could not retrieve password for account %@: %@ returned %i (%@)", [self _accountNameForAccount:inAccount], [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME], err, [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
113                 }
114         }
115         return password;
119  * @brief Retrieve the password of an account, prompting the user if necessary
121  * @param inAccount account whose password is desired
122  * @param inTarget target to notify when password is available
123  * @param inSelector selector to notify when password is available
124  * @param inContext context passed to target
125  */
126 - (void)passwordForAccount:(AIAccount *)inAccount notifyingTarget:(id)inTarget selector:(SEL)inSelector context:(id)inContext
128         NSError         *error    = nil;
129         AIKeychain      *keychain = [AIKeychain defaultKeychain_error:&error];
130         NSString        *password = [keychain internetPasswordForServer:[self _passKeyForAccount:inAccount]
131                                                                                                                 account:[self _accountNameForAccount:inAccount]
132                                                                                                            protocol:FOUR_CHAR_CODE('AdIM')
133                                                                                                                   error:&error];
134         if (error) {
135                 OSStatus err = [error code];
136                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
137                  *we don't get here at all for noErr (error will be nil).
138                  */
139                 if (err != errSecItemNotFound) {
140                         NSDictionary *userInfo = [error userInfo];
141                         NSLog(@"could not retrieve password for account %@: %@ returned %i (%@)", [self _accountNameForAccount:inAccount], [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME], err, [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
142                 }
143         }
144         
145         if (password && [password length] != 0) {
146                 //Invoke the target right away
147                 [inTarget performSelector:inSelector withObject:password withObject:inContext afterDelay:0.0001];
148         } else {
149                 //Prompt the user for their password
150                 [ESAccountPasswordPromptController showPasswordPromptForAccount:inAccount
151                                                                                                                 notifyingTarget:inTarget
152                                                                                                                            selector:inSelector
153                                                                                                                                 context:inContext];
154         }
157 //Proxy Servers --------------------------------------------------------------------------------------------------------
158 #pragma mark Proxy Servers
161  * @brief Set the password for a proxy server
163  * @param inPassword password to store
164  * @param server proxy server name
165  * @param userName proxy server user name
167  * XXX - This is inconsistent.  Above we have a separate forget method, here we forget when nil is passed...
168  */
169 - (void)setPassword:(NSString *)inPassword forProxyServer:(NSString *)server userName:(NSString *)userName
171         NSError *error = nil;
172         [[AIKeychain defaultKeychain_error:&error] setInternetPassword:inPassword
173                                                                                                                  forServer:[self _passKeyForProxyServer:server]
174                                                                                                                    account:[self _accountNameForProxyServer:server 
175                                                                                                                                                                                    userName:userName]
176                                                                                                                   protocol:FOUR_CHAR_CODE('AdIM')
177                                                                                                                          error:&error];
178         if (error) {
179                 OSStatus err = [error code];
180                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
181                  *we don't ignore it if we're trying to set the password, though (because that would be strange).
182                  *we don't get here at all for noErr (error will be nil).
183                  */
184                 if (inPassword || (err != errSecItemNotFound)) {
185                         NSDictionary *userInfo = [error userInfo];
186                         NSLog(@"could not %@ password for proxy server %@: %@ returned %i (%@)",
187                               inPassword ? @"set" : @"remove",
188                               [self _accountNameForProxyServer:server
189                                                           userName:userName],
190                                   [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME],
191                                   err,
192                                   [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
193                 }
194         }
198  * @brief Retrieve the password for a proxy server
199  * 
200  * @param server proxy server name
201  * @param userName proxy server user name
202  * @return proxy server password, or nil if the password is not available
203  */
204 - (NSString *)passwordForProxyServer:(NSString *)server userName:(NSString *)userName
206         NSError         *error    = nil;
207         AIKeychain      *keychain = [AIKeychain defaultKeychain_error:&error];
208         NSString        *password = [keychain internetPasswordForServer:[self _passKeyForProxyServer:server]
209                                                                                                                 account:[self _accountNameForProxyServer:server 
210                                                                                                                                                                                 userName:userName]
211                                                                                                            protocol:FOUR_CHAR_CODE('AdIM')
212                                                                                                                   error:&error];
213         if (error) {
214                 OSStatus err = [error code];
215                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
216                  *we don't get here at all for noErr (error will be nil).
217                  */
218                 if (err != errSecItemNotFound) {
219                         NSDictionary *userInfo = [error userInfo];
220                         NSLog(@"could not retrieve password for proxy server %@: %@ returned %i (%@)",
221                                   [self _accountNameForProxyServer:server
222                                                           userName:userName],
223                                   [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME],
224                                   err,
225                                   [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
226                 }
227         }
228         return password;
232  * @brief Retrieve the password for a proxy server, prompting the user if necessary
234  * @param server proxy server name
235  * @param userName proxy server user name
236  * @param inTarget target to notify when password is available
237  * @param inSelector selector to notify when password is available
238  * @param inContext context passed to target
239  */
240 - (void)passwordForProxyServer:(NSString *)server userName:(NSString *)userName notifyingTarget:(id)inTarget selector:(SEL)inSelector context:(id)inContext
242         NSError         *error    = nil;
243         AIKeychain      *keychain = [AIKeychain defaultKeychain_error:&error];
244         NSString        *password = [keychain internetPasswordForServer:[self _passKeyForProxyServer:server]
245                                                                                                                 account:[self _accountNameForProxyServer:server 
246                                                                                                                                                                                 userName:userName]
247                                                                                                            protocol:FOUR_CHAR_CODE('AdIM')
248                                                                                                                   error:&error];
249         if (error) {
250                 OSStatus err = [error code];
251                 /*errSecItemNotFound: no entry in the keychain. a harmless error.
252                  *we don't get here at all for noErr (error will be nil).
253                  */
254                 if (err != errSecItemNotFound) {
255                         NSDictionary *userInfo = [error userInfo];
256                         NSLog(@"could not retrieve password for proxy server %@: %@ returned %i (%@)",
257                                   [self _accountNameForProxyServer:server
258                                                           userName:userName],
259                                   [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_SECURITYFUNCTIONNAME],
260                                   err,
261                                   [userInfo objectForKey:AIKEYCHAIN_ERROR_USERINFO_ERRORDESCRIPTION]);
262                 }
263         }
264         
265         if (password && [password length] != 0) {
266                 //Invoke the target right away
267                 [inTarget performSelector:inSelector withObject:password withObject:inContext afterDelay:0.0001];    
268         } else {
269                 //Prompt the user for their password
270                 [ESProxyPasswordPromptController showPasswordPromptForProxyServer:server
271                                                                                                                                  userName:userName
272                                                                                                                   notifyingTarget:inTarget
273                                                                                                                                  selector:inSelector
274                                                                                                                                   context:inContext];
275         }
279 //Password Keys --------------------------------------------------------------------------------------------------------
280 #pragma mark Password Keys
283  * @brief Keychain identifier for an account
284  */
285 - (NSString *)_accountNameForAccount:(AIAccount *)inAccount{
286         return [NSString stringWithFormat:@"%@.%@",[[inAccount service] serviceID],[inAccount internalObjectID]];
288 - (NSString *)_passKeyForAccount:(AIAccount *)inAccount{
289         if ([[[adium loginController] userArray] count] > 1) {
290                 return [NSString stringWithFormat:@"Adium.%@.%@",[[adium loginController] currentUser],[self _accountNameForAccount:inAccount]];
291         } else {
292                 return [NSString stringWithFormat:@"Adium.%@",[self _accountNameForAccount:inAccount]];
293         }
297  * @brief Keychain identifier for a proxy server
298  */
299 - (NSString *)_accountNameForProxyServer:(NSString *)proxyServer userName:(NSString *)userName{
300         return [NSString stringWithFormat:@"%@.%@",proxyServer,userName];
302 - (NSString *)_passKeyForProxyServer:(NSString *)proxyServer{
303         if ([[[adium loginController] userArray] count] > 1) {
304                 return [NSString stringWithFormat:@"Adium.%@.%@",[[adium loginController] currentUser],proxyServer];
305         } else {
306                 return [NSString stringWithFormat:@"Adium.%@",proxyServer];     
307         }
310 @end