Bug Summary

File:Plugins/Purple Service/ESPurpleJabberAccountViewController.m
Location:line 209, column 4
Description:Memory Leak
Code is compiled without garbage collection.

Annotated Source Code

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 */
16
17#import "ESPurpleJabberAccountViewController.h"
18#import <Adium/AIAccount.h>
19#import <Adium/AIContactControllerProtocol.h>
20#import <Adium/AIService.h>
21#include <SystemConfiguration/SystemConfiguration.h>
22
23#define SERVERFEEDRSSURL @"https://www.xmpp.net/servers/feed/rss"
24
25@implementation ESPurpleJabberAccountViewController
26
27- (NSString *)nibName{
28 return @"ESPurpleJabberAccountView";
29}
30
31- (void)awakeFromNib
32{
33 [super awakeFromNib];
34
35 [checkBox_checkMail setEnabled:NO( BOOL ) 0];
36
37 [[adium notificationCenter] addObserver:self
38 selector:@selector(contactListChanged:)
39 name:Contact_ListChanged@ "Contact_ListChanged"
40 object:nil0];
41}
42
43//Configure our controls
44- (void)configureForAccount:(AIAccount *)inAccount
45{
46 [super configureForAccount:inAccount];
47
48 //Connection security
49 [checkBox_forceOldSSL setState:[[account preferenceForKey:KEY_JABBER_FORCE_OLD_SSL@ "Jabber:Force Old SSL" group:GROUP_ACCOUNT_STATUS@ "Account Status"] boolValue]];
50 [checkBox_requireTLS setState:[[account preferenceForKey:KEY_JABBER_REQUIRE_TLS@ "Jabber:Require TLS" group:GROUP_ACCOUNT_STATUS@ "Account Status"] boolValue]];
51 [checkBox_checkCertificates setState:[account preferenceForKey:KEY_JABBER_VERIFY_CERTS@ "Jabber:Verify Certificates" group:GROUP_ACCOUNT_STATUS@ "Account Status"]?[[account preferenceForKey:KEY_JABBER_VERIFY_CERTS@ "Jabber:Verify Certificates" group:GROUP_ACCOUNT_STATUS@ "Account Status"] boolValue]:YES( BOOL ) 1];
52 [checkBox_allowPlaintext setState:[[account preferenceForKey:KEY_JABBER_ALLOW_PLAINTEXT@ "Jabber:Allow Plaintext Authentication" group:GROUP_ACCOUNT_STATUS@ "Account Status"] boolValue]];
53
54 //Resource
55 if([account preferenceForKey:KEY_JABBER_RESOURCE@ "Jabber:Resource" group:GROUP_ACCOUNT_STATUS@ "Account Status"])
56 [textField_resource setStringValue:[account preferenceForKey:KEY_JABBER_RESOURCE@ "Jabber:Resource" group:GROUP_ACCOUNT_STATUS@ "Account Status"]];
57 else
58 [textField_resource setStringValue:[(NSString*)SCDynamicStoreCopyLocalHostName(NULL( ( void * ) 0 )) autorelease]];
59
60 //Connect server
61 NSString *connectServer = [account preferenceForKey:KEY_JABBER_CONNECT_SERVER@ "Jabber:Connect Server" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
62 [textField_connectServer setStringValue:(connectServer ? connectServer : @"")];
63
64 //Priority
65 NSNumber *priority = [account preferenceForKey:KEY_JABBER_PRIORITY_AVAILABLE@ "Jabber:Priority when Available" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
66 [textField_priorityAvailable setStringValue:(priority ? [priority stringValue] : @"")];
67 priority = [account preferenceForKey:KEY_JABBER_PRIORITY_AWAY@ "Jabber:Priority when Away" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
68 [textField_priorityAway setStringValue:(priority ? [priority stringValue] : @"")];
69
70 //Subscription behavior
71 int subbeh = [[account preferenceForKey:KEY_JABBER_SUBSCRIPTION_BEHAVIOR@ "Jabber:Subscription Behavior" group:GROUP_ACCOUNT_STATUS@ "Account Status"] intValue];
72 [popup_subscriptionBehavior selectItemWithTag:subbeh];
73 NSString *defaultGroup = [account preferenceForKey:KEY_JABBER_SUBSCRIPTION_GROUP@ "Jabber:Default Subscription Group" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
74 [comboBox_subscriptionGroup setStringValue:(defaultGroup ? defaultGroup : @"")];
75
76 //Hide the register button if the account can't register new accounts
77 [button_register setHidden:![[account service] canRegisterNewAccounts]];
78
79 //Set hidden flag of the default group combobox
80 [self subscriptionModeDidChange:nil0];
81}
82
83//Save controls
84- (void)saveConfiguration
85{
86 [super saveConfiguration];
87
88 //Connection security
89 [account setPreference:[NSNumber numberWithBool:[checkBox_forceOldSSL state]]
90 forKey:KEY_JABBER_FORCE_OLD_SSL@ "Jabber:Force Old SSL" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
91 [account setPreference:[NSNumber numberWithBool:[checkBox_requireTLS state]]
92 forKey:KEY_JABBER_REQUIRE_TLS@ "Jabber:Require TLS" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
93 [account setPreference:[NSNumber numberWithBool:[checkBox_checkCertificates state]]
94 forKey:KEY_JABBER_VERIFY_CERTS@ "Jabber:Verify Certificates" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
95 [account setPreference:[NSNumber numberWithBool:[checkBox_allowPlaintext state]]
96 forKey:KEY_JABBER_ALLOW_PLAINTEXT@ "Jabber:Allow Plaintext Authentication" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
97
98 //Resource
99 [account setPreference:([[textField_resource stringValue] length] ? [textField_resource stringValue] : nil0)
100 forKey:KEY_JABBER_RESOURCE@ "Jabber:Resource" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
101
102 //Connect server
103 [account setPreference:([[textField_connectServer stringValue] length] ? [textField_connectServer stringValue] : nil0)
104 forKey:KEY_JABBER_CONNECT_SERVER@ "Jabber:Connect Server" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
105
106 //Priority
107 [account setPreference:([textField_priorityAvailable intValue] ? [NSNumber numberWithInt:[textField_priorityAvailable intValue]] : nil0)
108 forKey:KEY_JABBER_PRIORITY_AVAILABLE@ "Jabber:Priority when Available"
109 group:GROUP_ACCOUNT_STATUS@ "Account Status"];
110 [account setPreference:([textField_priorityAway intValue] ? [NSNumber numberWithInt:[textField_priorityAway intValue]] : nil0)
111 forKey:KEY_JABBER_PRIORITY_AWAY@ "Jabber:Priority when Away"
112 group:GROUP_ACCOUNT_STATUS@ "Account Status"];
113
114 //Subscription Behavior
115 [account setPreference:([[popup_subscriptionBehavior selectedItem] tag] ? [NSNumber numberWithInt:[[popup_subscriptionBehavior selectedItem] tag]] : nil0)
116 forKey:KEY_JABBER_SUBSCRIPTION_BEHAVIOR@ "Jabber:Subscription Behavior"
117 group:GROUP_ACCOUNT_STATUS@ "Account Status"];
118 [account setPreference:([[comboBox_subscriptionGroup stringValue] length] ? [comboBox_subscriptionGroup stringValue] : nil0)
119 forKey:KEY_JABBER_SUBSCRIPTION_GROUP@ "Jabber:Default Subscription Group" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
120}
121
122- (IBActionvoid)subscriptionModeDidChange:(id)sender {
123 // only show these two when "accept and add to contact list" is selected
124 int tag = [[popup_subscriptionBehavior selectedItem] tag];
125 [textField_subscriptionModeLabel setHidden:tag != 2];
126 [comboBox_subscriptionGroup setHidden:tag != 2];
127}
128
129- (void)dealloc {
130 [[adium notificationCenter] removeObserver:self];
131 [window_registerServer release];
132 [servers release];
133
134 [super dealloc];
135}
136
137#pragma mark group combobox datasource
138
139- (void)contactListChanged:(NSNotification*)n {
140 [comboBox_subscriptionGroup reloadData];
141}
142
143- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox {
144 AIListGroup *list = [[adium contactController] contactList];
145 return [list containedObjectsCount];
146}
147
148- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index {
149 AIListGroup *list = [[adium contactController] contactList];
150 return [[list objectAtIndex:index] formattedUID];
151}
152
153- (unsigned int)comboBox:(NSComboBox *)aComboBox indexOfItemWithStringValue:(NSString *)string {
154 AIListGroup *list = [[adium contactController] contactList];
155 NSArray *groups = [list containedObjects];
156 unsigned i;
157 for(i=0;i < [groups count];++i) {
158 AIListGroup *group = [groups objectAtIndex:i];
159 if([[group formattedUID] isEqualToString:string])
160 return i;
161 }
162 return NSNotFound;
163}
164
165- (NSString *)comboBox:(NSComboBox *)aComboBox completedString:(NSString *)string {
166 AIListGroup *list = [[adium contactController] contactList];
167 NSArray *groups = [list containedObjects];
168 unsigned i;
169 for(i=0;i < [groups count];++i) {
170 AIListGroup *group = [groups objectAtIndex:i];
171 if([[group formattedUID] hasPrefix:string])
172 return [group formattedUID];
173 }
174 return string;
175}
176
177#pragma mark account creation
178
179static int compareByDistance(id one, id two, void*context) {
180 NSNumber *dist1obj = [one objectForKey:@"distance"];
181 NSNumber *dist2obj = [two objectForKey:@"distance"];
182
183 if((id)dist2obj == [NSNull null]) {
184 if((id)dist1obj == [NSNull null])
185 return NSOrderedSame;
186 return NSOrderedAscending;
187 }
188 if((id)dist1obj == [NSNull null])
189 return NSOrderedDescending;
190
191 float dist1 = [dist1obj floatValue];
192 float dist2 = [dist2obj floatValue];
193
194 if(fabs(dist1 - dist2) < 0.000001)
195 return NSOrderedSame;
196
197 if(dist1 > dist2)
198 return NSOrderedDescending;
199 return NSOrderedAscending;
200}
201
202- (IBActionvoid)registerNewAccount:(id)sender {
[1] Taking true branch.
203 if(!servers) {
204 NSError *err = NULL( ( void * ) 0 );
[2] Method returns an object with a +1 retain count (owning reference).
205 NSXMLDocument *serverfeed = [[NSXMLDocument alloc] initWithContentsOfURL:[NSURL URLWithString:SERVERFEEDRSSURL@ "https://www.xmpp.net/servers/feed/rss"]
206 options:0
207 error:&err];
[3] Taking true branch.
208 if(err) {
[4] Object allocated on line 205 and stored into 'serverfeed' is no longer referenced after this point and has a retain count of +1 (object leaked).
209 [[NSAlert alertWithError:err] runModal];
210 } else {
211 NSXMLElement *root = [serverfeed rootElement];
212 NSArray *channels = [root elementsForName:@"channel"];
213
214 if(!root || !channels || ![[root name] isEqualToString:@"rss"] || [channels count] != 1) {
215 [serverfeed release];
216
217 [[NSAlert alertWithMessageText:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Parse Error." ) value : @ "" table : ( 0 ) ]
(@"Parse Error.",nil)
218 defaultButton:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "OK" ) value : @ "" table : ( 0 ) ]
(@"OK",nil)
219 alternateButton:nil0
220 otherButton:nil0
221 informativeTextWithFormat:[NSString stringWithFormat:
222 AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Unable to parse the server list at %@. Please try again later."
) value : @ "" table : ( 0 ) ]
(@"Unable to parse the server list at %@. Please try again later.",nil), SERVERFEEDRSSURL@ "https://www.xmpp.net/servers/feed/rss"]] runModal];
223 } else {
224 float longitude, latitude;
225
226 MachineLocation loc;
227 ReadLocation(&loc);
228
229 latitude = FractToFloat( ( float ) ( loc . latitude ) / ( ( Fract ) 0x40000000L ) )(loc.latitude)*(M_PI3.14159265358979323846264338327950288/2.0f);
230 longitude = FractToFloat( ( float ) ( loc . longitude ) / ( ( Fract ) 0x40000000L ) )(loc.longitude)*(M_PI3.14159265358979323846264338327950288/2.0f);
231
232 servers = [[NSMutableArray alloc] init];
233 NSEnumerator *enumer = [[[channels lastObject] elementsForName:@"item"] objectEnumerator];
234 NSXMLElement *item;
235
236 while((item = [enumer nextObject])) {
237 NSXMLElement *title = [[item elementsForName:@"title"] lastObject];
238 if(!title)
239 continue;
240 NSXMLElement *description = [[item elementsForName:@"description"] lastObject];
241 NSXMLElement *latitudeNode = [[item elementsForLocalName:@"latitude" URI:@"http://geourl.org/rss/module/"] lastObject];
242 NSXMLElement *longitudeNode = [[item elementsForLocalName:@"longitude" URI:@"http://geourl.org/rss/module/"] lastObject];
243
244 id distance = [NSNull null];
245 if (latitudeNode && longitudeNode) {
246 /* Calculate the distance between the computer and the xmpp server in km
247 * Note that this assumes that the earth is a perfect sphere
248 * If it turns out to be flat or doughnut-shaped, this will not work!
249 */
250
251 float latitude2 = [[latitudeNode stringValue] floatValue] * (M_PI3.14159265358979323846264338327950288/180.0f);
252 float longitude2 = [[longitudeNode stringValue] floatValue] * (M_PI3.14159265358979323846264338327950288/180.0f);
253
254 float d_lat = sinf((latitude2 - latitude)/2.0);
255 float d_long = sinf((longitude2 - longitude)/2.0);
256 float a = d_lat*d_lat + cosf(latitude)*cosf(latitude2)*d_long*d_long;
257 float c = 2*atan2f(sqrtf(a),sqrtf(1.0-a));
258 float d = 6372.797*c; // mean earth radius
259
260 distance = [NSNumber numberWithFloat:d];
261 }
262
263 [(NSMutableArray*)servers addObject:[NSDictionary dictionaryWithObjectsAndKeys:
264 [title stringValue], @"servername",
265 (description ? (id)[description stringValue] : (id)[NSNull null]), @"description",
266 distance, @"distance",
267 nil0]];
268 }
269
270 [serverfeed release];
271
272 [(NSMutableArray*)servers sortUsingFunction:compareByDistance context:nil0];
273
274 [tableview_servers reloadData];
275 }
276 }
277 }
278
279 [NSApp beginSheet:window_registerServer
280 modalForWindow:[sender window]
281 modalDelegate:self
282 didEndSelector:@selector(registrationSheetDidEnd:returnCode:contextInfo:)
283 contextInfo:NULL( ( void * ) 0 )];
284}
285
286- (void)registrationSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
287{
288
289}
290
291- (int)numberOfRowsInTableView:(NSTableView *)tableView {
292 return [servers count];
293}
294
295- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row {
296 id objectValue = [[servers objectAtIndex:row] objectForKey:[tableColumn identifier]];
297 return ((objectValue && ![objectValue isKindOfClass:[NSNull class]]) ? objectValue : @"");
298}
299
300- (void)tableViewSelectionDidChange:(NSNotification *)notification {
301 NSString *servername = [self tableView:[notification object] objectValueForTableColumn:[[notification object] tableColumnWithIdentifier:@"servername"] row:[[notification object] selectedRow]];
302 [textField_registerServerName setStringValue:servername];
303 [textField_registerServerPort setStringValue:@""];
304}
305
306- (IBActionvoid)registerCancel:(id)sender {
307 [window_registerServer orderOut:nil0];
308 [NSApp endSheet:window_registerServer];
309}
310
311- (IBActionvoid)registerRequestAccount:(id)sender {
312 [[sender window] makeFirstResponder:nil0]; // apply all changes
313 if([[textField_registerServerName stringValue] length] == 0) {
314 NSBeep();
315 return;
316 }
317// [account setUID:[NSString stringWithFormat:@"unknown@%@", [textField_registerServerName stringValue]]];
318 [account setPreference:[textField_registerServerName stringValue]
319 forKey:KEY_JABBER_CONNECT_SERVER@ "Jabber:Connect Server" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
320 [account setPreference:[NSNumber numberWithInt:[textField_registerServerPort intValue]]
321 forKey:KEY_CONNECT_PORT@ "Connect Port" group:GROUP_ACCOUNT_STATUS@ "Account Status"];
322
323 NSString *newUID;
324 if ([[textField_accountUID stringValue] length]) {
325 NSRange atLocation = [[textField_accountUID stringValue] rangeOfString:@"@" options:NSLiteralSearch];
326 if (atLocation.location == NSNotFound)
327 newUID = [NSString stringWithFormat:@"%@@%@",[textField_accountUID stringValue], [textField_registerServerName stringValue]];
328 else
329 newUID = [NSString stringWithFormat:@"%@@%@",[[textField_accountUID stringValue] substringToIndex:atLocation.location], [textField_registerServerName stringValue]];
330 } else {
331 newUID = [NSString stringWithFormat:@"nobody@%@",[textField_registerServerName stringValue]];
332 }
333
334 [account filterAndSetUID:newUID];
335
336 [window_registerServer orderOut:nil0];
337 [NSApp endSheet:window_registerServer];
338
339 [account performRegisterWithPassword:[textField_password stringValue]];
340 [self didBeginRegistration];
341}
342
343@end