1/* Implementation for NSURLCredentialStorage for GNUstep
2   Copyright (C) 2006 Software Foundation, Inc.
3
4   Written by:  Richard Frith-Macdonald <rfm@gnu.org>
5   Date: 2006
6
7   This file is part of the GNUstep Base Library.
8
9   This library is free software; you can redistribute it and/or
10   modify it under the terms of the GNU Lesser General Public
11   License as published by the Free Software Foundation; either
12   version 2 of the License, or (at your option) any later version.
13
14   This library is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public
20   License along with this library; if not, write to the Free
21   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22   Boston, MA 02110 USA.
23   */
24
25#import "common.h"
26
27#define	EXPOSE_NSURLCredentialStorage_IVARS	1
28#import "GSURLPrivate.h"
29
30NSString *const NSURLCredentialStorageChangedNotification
31  = @"NSURLCredentialStorageChangedNotification";
32
33// Internal data storage
34typedef struct {
35  NSMutableDictionary	*credentials;
36  NSMutableDictionary	*defaults;
37} Internal;
38
39#define	this	((Internal*)(self->_NSURLCredentialStorageInternal))
40
41@implementation	NSURLCredentialStorage
42
43static NSURLCredentialStorage	*storage = nil;
44
45+ (id) allocWithZone: (NSZone*)z
46{
47  return RETAIN([self sharedCredentialStorage]);
48}
49
50+ (NSURLCredentialStorage *) sharedCredentialStorage
51{
52  if (storage == nil)
53    {
54      [gnustep_global_lock lock];
55      if (storage == nil)
56        {
57	  NSURLCredentialStorage	*o;
58
59	  o = (NSURLCredentialStorage*)
60	    NSAllocateObject(self, 0, NSDefaultMallocZone());
61	  o->_NSURLCredentialStorageInternal = (Internal*)
62	    NSZoneCalloc(NSDefaultMallocZone(), 1, sizeof(Internal));
63	  ((Internal*)(o->_NSURLCredentialStorageInternal))->credentials
64	    = [NSMutableDictionary new];
65	  ((Internal*)(o->_NSURLCredentialStorageInternal))->defaults
66	    = [NSMutableDictionary new];
67	  storage = o;
68	}
69      [gnustep_global_lock unlock];
70    }
71  return storage;
72}
73
74- (NSDictionary *) allCredentials
75{
76  NSMutableDictionary	*all;
77  NSEnumerator		*enumerator;
78  NSURLProtectionSpace	*space;
79
80  all = [NSMutableDictionary dictionaryWithCapacity: [this->credentials count]];
81  enumerator = [this->credentials keyEnumerator];
82  while ((space = [enumerator nextObject]) != nil)
83    {
84      NSDictionary	*info = [[this->credentials objectForKey: space] copy];
85
86      [all setObject: info forKey: space];
87      RELEASE(info);
88    }
89  return all;
90}
91
92- (NSDictionary *) credentialsForProtectionSpace: (NSURLProtectionSpace *)space
93{
94  return AUTORELEASE([[this->credentials objectForKey: space] copy]);
95}
96
97- (void) dealloc
98{
99  [NSException raise: NSInternalInconsistencyException
100  	      format: @"Attempt to deallocate credential storage"];
101  GSNOSUPERDEALLOC;
102}
103
104- (NSURLCredential *) defaultCredentialForProtectionSpace:
105  (NSURLProtectionSpace *)space
106{
107  return [this->defaults objectForKey: space];
108}
109
110// Should never be called.
111- (id) init
112{
113  DESTROY(self);
114  return nil;
115}
116
117- (void) removeCredential: (NSURLCredential *)credential
118       forProtectionSpace: (NSURLProtectionSpace *)space
119{
120  if (credential == nil || ![credential isKindOfClass: [NSURLCredential class]])
121    {
122      [NSException raise: NSInvalidArgumentException
123      		  format: @"[%@-%@] nil or bad  class for credential",
124		  NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
125    }
126  if (space == nil || ![space isKindOfClass: [NSURLProtectionSpace class]])
127    {
128      [NSException raise: NSInvalidArgumentException
129      		  format: @"[%@-%@] nil or bad  class for space",
130		  NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
131    }
132  [[this->credentials objectForKey: space]
133    removeObjectForKey: [credential user]];
134}
135
136/**
137 * Sets credential in the storage for the protection space specified.<br />
138 * This replaces any old value with the same username.
139 */
140- (void) setCredential: (NSURLCredential *)credential
141    forProtectionSpace: (NSURLProtectionSpace *)space
142{
143  NSMutableDictionary	*info;
144
145  if (credential == nil || ![credential isKindOfClass: [NSURLCredential class]])
146    {
147      [NSException raise: NSInvalidArgumentException
148      		  format: @"[%@-%@] nil or bad  class for credential",
149		  NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
150    }
151  if (space == nil || ![space isKindOfClass: [NSURLProtectionSpace class]])
152    {
153      [NSException raise: NSInvalidArgumentException
154      		  format: @"[%@-%@] nil or bad  class for space",
155		  NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
156    }
157  info = [this->credentials objectForKey: space];
158  if (info == nil)
159    {
160      info = [NSMutableDictionary new];
161      [this->credentials setObject: info forKey: space];
162      RELEASE(info);
163    }
164  [info setObject: credential forKey: [credential user]];
165}
166
167/**
168 * Sets the default credential for the protection space.  Also calls
169 * -setCredential:forProtectionSpace: if the credential has not already
170 * been set in space.
171 */
172- (void) setDefaultCredential: (NSURLCredential *)credential
173	   forProtectionSpace: (NSURLProtectionSpace *)space
174{
175  if (credential == nil || ![credential isKindOfClass: [NSURLCredential class]])
176    {
177      [NSException raise: NSInvalidArgumentException
178      		  format: @"[%@-%@] nil or bad  class for credential",
179		  NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
180    }
181  if (space == nil || ![space isKindOfClass: [NSURLProtectionSpace class]])
182    {
183      [NSException raise: NSInvalidArgumentException
184      		  format: @"[%@-%@] nil or bad  class for space",
185		  NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
186    }
187  [this->defaults setObject: credential forKey: space];
188  if ([[this->credentials objectForKey: space] objectForKey: [credential user]]
189    != credential)
190    {
191      [self setCredential: credential forProtectionSpace: space];
192    }
193}
194
195@end
196
197