|
David@0
|
1 |
/* |
|
David@0
|
2 |
* Adium is the legal property of its developers, whose names are listed in the copyright file included |
|
David@0
|
3 |
* with this source distribution. |
|
David@0
|
4 |
* |
|
David@0
|
5 |
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU |
|
David@0
|
6 |
* General Public License as published by the Free Software Foundation; either version 2 of the License, |
|
David@0
|
7 |
* or (at your option) any later version. |
|
David@0
|
8 |
* |
|
David@0
|
9 |
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
|
David@0
|
10 |
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|
David@0
|
11 |
* Public License for more details. |
|
David@0
|
12 |
* |
|
David@0
|
13 |
* You should have received a copy of the GNU General Public License along with this program; if not, |
|
David@0
|
14 |
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
David@0
|
15 |
*/ |
|
David@0
|
16 |
|
|
David@0
|
17 |
#import <Adium/AIAbstractAccount.h> |
|
David@0
|
18 |
#import <Adium/AIAccount.h> |
|
David@0
|
19 |
#import <Adium/AIListContact.h> |
|
zacw@2131
|
20 |
#import <Adium/AIListGroup.h> |
|
David@0
|
21 |
#import <Adium/AIContentMessage.h> |
|
David@0
|
22 |
#import <Adium/AIContentNotification.h> |
|
David@0
|
23 |
#import <Adium/AIService.h> |
|
David@0
|
24 |
#import <Adium/AIChat.h> |
|
David@0
|
25 |
#import <Adium/ESFileTransfer.h> |
|
David@557
|
26 |
#import "AIStatusItem.h" |
|
David@557
|
27 |
#import "AIStatus.h" |
|
David@0
|
28 |
#import "AdiumAccounts.h" |
|
David@0
|
29 |
|
|
David@0
|
30 |
#import <Adium/AIContactControllerProtocol.h> |
|
David@0
|
31 |
#import <Adium/AIContentControllerProtocol.h> |
|
David@0
|
32 |
#import <Adium/AIAccountControllerProtocol.h> |
|
David@0
|
33 |
|
|
David@0
|
34 |
#import "DCJoinChatViewController.h" |
|
David@0
|
35 |
#import "AIChatControllerProtocol.h" |
|
David@0
|
36 |
#import "AIMessageWindowController.h" |
|
David@0
|
37 |
#import "AIMessageWindow.h" |
|
David@0
|
38 |
#import "AIInterfaceControllerProtocol.h" |
|
David@0
|
39 |
#import "AIStatusControllerProtocol.h" |
|
David@0
|
40 |
|
|
David@0
|
41 |
#define NEW_ACCOUNT_DISPLAY_TEXT AILocalizedString(@"<New Account>", "Placeholder displayed as the name of a new account") |
|
David@0
|
42 |
|
|
David@0
|
43 |
@interface AIAccountDeletionDialog : NSObject <AIAccountControllerRemoveConfirmationDialog> { |
|
David@0
|
44 |
AIAccount *account; |
|
David@0
|
45 |
NSAlert *alert; |
|
David@1598
|
46 |
id userData; |
|
David@0
|
47 |
} |
|
David@0
|
48 |
|
|
David@0
|
49 |
- (id)initWithAccount:(AIAccount*)ac alert:(NSAlert*)al; |
|
David@0
|
50 |
|
|
David@1598
|
51 |
@property (readwrite, retain, nonatomic) id userData; |
|
David@0
|
52 |
|
|
David@0
|
53 |
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo; |
|
David@0
|
54 |
|
|
David@0
|
55 |
@end |
|
David@0
|
56 |
|
|
David@0
|
57 |
@implementation AIAccountDeletionDialog |
|
David@0
|
58 |
|
|
David@0
|
59 |
- (id)initWithAccount:(AIAccount*)ac alert:(NSAlert*)al { |
|
David@0
|
60 |
if((self = [super init])) { |
|
David@0
|
61 |
account = ac; |
|
David@0
|
62 |
alert = [al retain]; |
|
David@0
|
63 |
} |
|
David@0
|
64 |
return self; |
|
David@0
|
65 |
} |
|
David@0
|
66 |
|
|
David@0
|
67 |
- (void)dealloc { |
|
David@0
|
68 |
[alert release]; |
|
David@1598
|
69 |
[userData release]; |
|
David@0
|
70 |
[super dealloc]; |
|
David@0
|
71 |
} |
|
David@0
|
72 |
|
|
David@1598
|
73 |
@synthesize userData; |
|
David@0
|
74 |
|
|
David@0
|
75 |
- (void)runModal { |
|
David@0
|
76 |
[self alertDidEnd:alert returnCode:[alert runModal] contextInfo:NULL]; |
|
David@0
|
77 |
} |
|
David@0
|
78 |
|
|
David@0
|
79 |
- (void)beginSheetModalForWindow:(NSWindow*)window { |
|
David@0
|
80 |
[alert beginSheetModalForWindow:window modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NULL]; |
|
David@0
|
81 |
} |
|
David@0
|
82 |
|
|
David@0
|
83 |
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo { |
|
David@0
|
84 |
[account alertForAccountDeletion:self didReturn:returnCode]; |
|
David@0
|
85 |
} |
|
David@0
|
86 |
|
|
David@0
|
87 |
@end |
|
David@0
|
88 |
|
|
David@0
|
89 |
//Proxy types for applescript |
|
David@0
|
90 |
typedef enum |
|
David@0
|
91 |
{ |
|
David@0
|
92 |
Adium_Proxy_HTTP_AS = 'HTTP', |
|
David@0
|
93 |
Adium_Proxy_SOCKS4_AS = 'SCK4', |
|
David@0
|
94 |
Adium_Proxy_SOCKS5_AS = 'SCK5', |
|
David@0
|
95 |
Adium_Proxy_Default_HTTP_AS = 'DHTP', |
|
David@0
|
96 |
Adium_Proxy_Default_SOCKS4_AS = 'DSK4', |
|
David@0
|
97 |
Adium_Proxy_Default_SOCKS5_AS = 'DSK5', |
|
David@0
|
98 |
Adium_Proxy_None_AS = 'NONE' |
|
David@0
|
99 |
} AdiumProxyTypeApplescript; |
|
David@0
|
100 |
|
|
David@0
|
101 |
@interface AIAccount(AppleScriptPRIVATE) |
|
David@0
|
102 |
- (AdiumProxyType)proxyTypeFromApplescript:(AdiumProxyTypeApplescript)proxyTypeAS; |
|
David@0
|
103 |
- (AdiumProxyTypeApplescript)applescriptProxyType:(AdiumProxyType)proxyType; |
|
David@0
|
104 |
@end |
|
David@0
|
105 |
|
|
David@0
|
106 |
/*! |
|
David@0
|
107 |
* @class AIAccount |
|
David@0
|
108 |
* @brief An account |
|
David@0
|
109 |
* |
|
David@0
|
110 |
* This abstract class represents an account the user has setup in Adium. Subclass this for every service. |
|
David@0
|
111 |
*/ |
|
David@0
|
112 |
@implementation AIAccount |
|
David@0
|
113 |
|
|
David@0
|
114 |
/*! |
|
David@0
|
115 |
* @brief Init Account |
|
David@0
|
116 |
* |
|
David@0
|
117 |
* Init this account instance |
|
David@0
|
118 |
*/ |
|
David@0
|
119 |
- (void)initAccount |
|
David@0
|
120 |
{ |
|
David@0
|
121 |
} |
|
David@0
|
122 |
|
|
David@0
|
123 |
/*! |
|
David@0
|
124 |
* @brief Connect |
|
David@0
|
125 |
* |
|
David@0
|
126 |
* Connect the account, transitioning it into an online state. |
|
David@0
|
127 |
*/ |
|
David@0
|
128 |
- (void)connect |
|
David@0
|
129 |
{ |
|
David@0
|
130 |
//We are connecting |
|
David@0
|
131 |
[self setValue:[NSNumber numberWithBool:YES] forProperty:@"Connecting" notify:NotifyNow]; |
|
David@0
|
132 |
} |
|
David@0
|
133 |
|
|
David@0
|
134 |
/*! |
|
David@0
|
135 |
* @brief rejoinChat |
|
David@0
|
136 |
* |
|
David@0
|
137 |
* Rejoin the open group chats after disconnect |
|
David@0
|
138 |
*/ |
|
David@0
|
139 |
-(BOOL)rejoinChat:(AIChat*)chat |
|
David@0
|
140 |
{ |
|
David@0
|
141 |
return NO; |
|
David@0
|
142 |
} |
|
David@0
|
143 |
|
|
David@0
|
144 |
/*! |
|
zacw@1301
|
145 |
* @brief Do group chats support topics? |
|
zacw@1301
|
146 |
*/ |
|
zacw@1301
|
147 |
- (BOOL)groupChatsSupportTopic |
|
zacw@1301
|
148 |
{ |
|
zacw@1301
|
149 |
return NO; |
|
zacw@1301
|
150 |
} |
|
zacw@1301
|
151 |
|
|
zacw@1301
|
152 |
/*! |
|
zacw@1301
|
153 |
* @brief Set a chat's topic |
|
zacw@1301
|
154 |
* |
|
zacw@1301
|
155 |
* This only has an effect on group chats. |
|
zacw@1301
|
156 |
*/ |
|
zacw@1301
|
157 |
- (void)setTopic:(NSString *)topic forChat:(AIChat *)chat |
|
zacw@1301
|
158 |
{ |
|
zacw@1301
|
159 |
} |
|
zacw@1301
|
160 |
|
|
zacw@1301
|
161 |
/*! |
|
David@0
|
162 |
* @brief Disconnect |
|
David@0
|
163 |
* |
|
David@0
|
164 |
* Disconnect the account, transitioning it into an offline state. |
|
David@0
|
165 |
*/ |
|
David@0
|
166 |
- (void)disconnect |
|
David@0
|
167 |
{ |
|
David@0
|
168 |
[self cancelAutoReconnect]; |
|
David@0
|
169 |
[self setValue:nil forProperty:@"Connecting" notify:NotifyLater]; |
|
David@0
|
170 |
|
|
David@0
|
171 |
[self notifyOfChangedPropertiesSilently:NO]; |
|
David@0
|
172 |
} |
|
David@0
|
173 |
|
|
David@0
|
174 |
/*! |
|
David@0
|
175 |
* @brief Disconnect as a result of the network connection dropping out |
|
David@0
|
176 |
* |
|
David@0
|
177 |
* The default implementation is identical to [self disconect], but subclasses may want to act differently |
|
David@0
|
178 |
* if the network connection is gone than if the user chose to disconnect. |
|
David@0
|
179 |
* |
|
David@0
|
180 |
* Subclasses should call super's implementation. |
|
David@0
|
181 |
*/ |
|
David@0
|
182 |
- (void)disconnectFromDroppedNetworkConnection |
|
David@0
|
183 |
{ |
|
David@0
|
184 |
[self disconnect]; |
|
David@0
|
185 |
} |
|
David@0
|
186 |
|
|
David@0
|
187 |
/*! |
|
David@0
|
188 |
* @brief Register an account |
|
David@0
|
189 |
* |
|
David@0
|
190 |
* Register an account on this service using the currently entered information. This is for services which support |
|
David@0
|
191 |
* in-client registration such as jabber. |
|
David@0
|
192 |
*/ |
|
David@0
|
193 |
- (void)performRegisterWithPassword:(NSString *)inPassword |
|
David@0
|
194 |
{ |
|
David@0
|
195 |
|
|
David@0
|
196 |
} |
|
David@0
|
197 |
|
|
David@0
|
198 |
/*! |
|
David@0
|
199 |
* @brief The UID will be changed. The account has a chance to perform modifications |
|
David@0
|
200 |
* |
|
David@0
|
201 |
* For example, MSN adds \@hotmail.com to the proposedUID and returns the new value |
|
David@0
|
202 |
* |
|
David@0
|
203 |
* @param proposedUID The proposed, pre-filtered UID (filtered means it has no characters invalid for this servce) |
|
David@0
|
204 |
* @result The UID to use; the default implementation just returns proposedUID. |
|
David@0
|
205 |
*/ |
|
David@0
|
206 |
- (NSString *)accountWillSetUID:(NSString *)proposedUID |
|
David@0
|
207 |
{ |
|
David@0
|
208 |
return proposedUID; |
|
David@0
|
209 |
} |
|
David@0
|
210 |
|
|
David@0
|
211 |
/*! |
|
David@0
|
212 |
* @brief The account's UID changed |
|
David@0
|
213 |
*/ |
|
David@0
|
214 |
- (void)didChangeUID |
|
David@0
|
215 |
{ |
|
David@0
|
216 |
|
|
David@0
|
217 |
} |
|
David@0
|
218 |
|
|
David@0
|
219 |
/*! |
|
David@0
|
220 |
* @brief The account will be deleted |
|
David@0
|
221 |
* |
|
David@0
|
222 |
* The default implementation disconnects the account. Subclasses should call super's implementation. |
|
David@0
|
223 |
* If asynchronous behavior is required, the next three methods should be overridden instead. |
|
David@0
|
224 |
*/ |
|
David@0
|
225 |
- (void)willBeDeleted |
|
David@0
|
226 |
{ |
|
David@0
|
227 |
[self setShouldBeOnline:NO]; |
|
David@0
|
228 |
|
|
David@0
|
229 |
//Remove our contacts immediately. |
|
David@0
|
230 |
[self removeAllContacts]; |
|
David@0
|
231 |
} |
|
David@0
|
232 |
|
|
David@0
|
233 |
/*! |
|
David@0
|
234 |
* @brief Perform the deletion of this account |
|
David@0
|
235 |
* |
|
David@0
|
236 |
* This should be called only after proper confirmation has been made by the user. |
|
David@0
|
237 |
*/ |
|
David@0
|
238 |
- (void)performDelete |
|
David@0
|
239 |
{ |
|
David@95
|
240 |
[adium.accountController deleteAccount:self]; |
|
David@0
|
241 |
} |
|
David@0
|
242 |
|
|
David@0
|
243 |
- (id<AIAccountControllerRemoveConfirmationDialog>)confirmationDialogForAccountDeletion |
|
David@0
|
244 |
{ |
|
David@0
|
245 |
//Will be released in alertForAccountDeletion:didReturn: |
|
David@0
|
246 |
return [[AIAccountDeletionDialog alloc] initWithAccount:self alert:[self alertForAccountDeletion]]; |
|
David@0
|
247 |
} |
|
David@0
|
248 |
|
|
David@0
|
249 |
/*! |
|
David@0
|
250 |
* @brief The alert used for confirming the account deletion |
|
David@0
|
251 |
* |
|
David@0
|
252 |
* Meant for subclassers. By default, returns the dialog that asks the user if the account should really be deleted (and how). |
|
David@0
|
253 |
*/ |
|
David@0
|
254 |
- (NSAlert*)alertForAccountDeletion |
|
David@0
|
255 |
{ |
|
David@0
|
256 |
return [NSAlert alertWithMessageText:AILocalizedString(@"Delete Account",nil) |
|
David@0
|
257 |
defaultButton:AILocalizedString(@"Delete",nil) |
|
David@0
|
258 |
alternateButton:AILocalizedString(@"Cancel",nil) |
|
David@0
|
259 |
otherButton:nil |
|
David@427
|
260 |
informativeTextWithFormat:AILocalizedString(@"Delete the account %@?",nil), ([self.formattedUID length] ? self.formattedUID : NEW_ACCOUNT_DISPLAY_TEXT)]; |
|
David@0
|
261 |
} |
|
David@0
|
262 |
|
|
David@0
|
263 |
/*! |
|
David@0
|
264 |
* @brief The dialog asking for confirmation for deleting the account did return. |
|
David@0
|
265 |
* |
|
David@0
|
266 |
* @param dialog The dialog that has completed |
|
David@0
|
267 |
* @param returnCode One of the regular NSAlert return codes |
|
David@0
|
268 |
* |
|
David@0
|
269 |
* This method should be overridden when alertForAccountDeletion: was overridden, and/or asynchronous behavior is required. |
|
David@0
|
270 |
* This implementation disconnects and deletes the account from the accounts list when returnCode == NSAlertDefaultReturn. |
|
David@0
|
271 |
* |
|
David@0
|
272 |
* If this implementation is not called, dialog should be released by the subclass. |
|
David@0
|
273 |
*/ |
|
David@0
|
274 |
- (void)alertForAccountDeletion:(id<AIAccountControllerRemoveConfirmationDialog>)dialog didReturn:(int)returnCode |
|
David@0
|
275 |
{ |
|
David@0
|
276 |
if(returnCode == NSAlertDefaultReturn) { |
|
David@0
|
277 |
[self performDelete]; |
|
David@0
|
278 |
} |
|
David@0
|
279 |
|
|
David@0
|
280 |
[(AIAccountDeletionDialog*)dialog release]; |
|
David@0
|
281 |
} |
|
David@0
|
282 |
|
|
David@0
|
283 |
/*! |
|
David@0
|
284 |
* @brief A formatted UID which may include additional necessary identifying information. |
|
David@0
|
285 |
* |
|
David@0
|
286 |
* For example, an AIM account (tekjew) and a .Mac account (tekjew@mac.com, entered only as tekjew) may appear identical |
|
David@0
|
287 |
* without service information (tekjew). The explicit formatted UID is therefore tekjew@mac.com |
|
David@0
|
288 |
*/ |
|
David@0
|
289 |
- (NSString *)explicitFormattedUID |
|
David@0
|
290 |
{ |
|
David@427
|
291 |
return self.formattedUID; |
|
David@0
|
292 |
} |
|
David@0
|
293 |
|
|
zacw@1121
|
294 |
/*! |
|
zacw@1121
|
295 |
* @brief Use our host for the servername when storing password |
|
zacw@1121
|
296 |
* |
|
zacw@1121
|
297 |
* This should be YES for services which depend upon server information. For example, a password for an IRC account |
|
zacw@1121
|
298 |
* is uniqued by what server it is on. |
|
zacw@1121
|
299 |
*/ |
|
zacw@1121
|
300 |
- (BOOL)useHostForPasswordServerName |
|
zacw@1121
|
301 |
{ |
|
zacw@1121
|
302 |
return NO; |
|
zacw@1121
|
303 |
} |
|
zacw@1121
|
304 |
|
|
zacw@1131
|
305 |
/*! |
|
zacw@1131
|
306 |
* @brief Use our internal object ID for the username when storing password |
|
zacw@1131
|
307 |
* |
|
zacw@1131
|
308 |
* For accounts whose signup process may not be contingent upon the UID. For example, a Twitter account using OAuth might |
|
zacw@1131
|
309 |
* not know its UID when it wants to save itself. |
|
zacw@1131
|
310 |
*/ |
|
zacw@1131
|
311 |
- (BOOL)useInternalObjectIDForPasswordName |
|
zacw@1131
|
312 |
{ |
|
zacw@1131
|
313 |
return NO; |
|
zacw@1131
|
314 |
} |
|
zacw@1131
|
315 |
|
|
David@0
|
316 |
//Properties ----------------------------------------------------------------------------------------------------------- |
|
David@0
|
317 |
#pragma mark Properties |
|
David@0
|
318 |
/*! |
|
David@0
|
319 |
* @brief Send Autoresponses while away |
|
David@0
|
320 |
* |
|
David@0
|
321 |
* Subclass to alter the behavior of this account with regards to autoresponses. Certain services expect the client to |
|
David@0
|
322 |
* auto-respond with away messages. Adium will provide this behavior automatically if desired. |
|
David@0
|
323 |
*/ |
|
David@0
|
324 |
- (BOOL)supportsAutoReplies |
|
David@0
|
325 |
{ |
|
David@0
|
326 |
return NO; |
|
David@0
|
327 |
} |
|
David@0
|
328 |
|
|
David@0
|
329 |
/*! |
|
David@0
|
330 |
* @brief Disconnect on fast user switch |
|
David@0
|
331 |
* |
|
David@0
|
332 |
* It may be required for a service to disconnect when logged in users change. If this is the case, subclass this |
|
David@0
|
333 |
* method to return YES and Adium will automatically disconnect and reconnect on FUS events. |
|
David@0
|
334 |
*/ |
|
David@0
|
335 |
- (BOOL)disconnectOnFastUserSwitch |
|
David@0
|
336 |
{ |
|
David@0
|
337 |
return NO; |
|
David@0
|
338 |
} |
|
David@0
|
339 |
|
|
David@0
|
340 |
/*! |
|
David@0
|
341 |
* @brief Connectivity based on network reachability |
|
David@0
|
342 |
* |
|
David@0
|
343 |
* By default, accounts are automatically disconnected and reconnected when network reachability changes. Accounts |
|
David@0
|
344 |
* that do not require persistent network connections can choose to disable this by returning NO from this method. |
|
David@0
|
345 |
*/ |
|
David@0
|
346 |
- (BOOL)connectivityBasedOnNetworkReachability |
|
David@0
|
347 |
{ |
|
David@0
|
348 |
return YES; |
|
David@0
|
349 |
} |
|
David@0
|
350 |
|
|
David@0
|
351 |
/*! |
|
David@0
|
352 |
* @brief Suppress typing notifications after send |
|
David@0
|
353 |
* |
|
David@0
|
354 |
* Some protocols require a 'Stopped typing' notification to be sent along with an instant message. Other protocols |
|
David@0
|
355 |
* implicitly assume that typing has stopped with an incoming message and the extraneous typing notification may cause |
|
David@0
|
356 |
* strange behavior. Return YES from this method to suppress the sending of a stopped typing notification along with |
|
David@0
|
357 |
* messages. |
|
David@0
|
358 |
*/ |
|
David@0
|
359 |
- (BOOL)suppressTypingNotificationChangesAfterSend |
|
David@0
|
360 |
{ |
|
David@0
|
361 |
return NO; |
|
David@0
|
362 |
} |
|
David@0
|
363 |
|
|
David@0
|
364 |
/*! |
|
David@0
|
365 |
* @brief Support server-side storing of messages to offline users? |
|
David@0
|
366 |
* |
|
David@0
|
367 |
* Some protocols store messages to offline contacts on the server. Subclasses may return YES if their service supports |
|
David@0
|
368 |
* this. Adium will not store the message as an Event, and will just send it along to the server. This may cause a Gaim |
|
David@0
|
369 |
* error on Jabber if the Jabber server they are using is down. |
|
David@0
|
370 |
*/ |
|
David@0
|
371 |
- (BOOL)canSendOfflineMessageToContact:(AIListContact *)inContact |
|
David@0
|
372 |
{ |
|
David@0
|
373 |
return NO; |
|
David@0
|
374 |
} |
|
David@0
|
375 |
|
|
David@0
|
376 |
/*! |
|
Evan@46
|
377 |
* @brief Support messaging invisible contacts? |
|
Evan@46
|
378 |
* |
|
Evan@46
|
379 |
* This will only be called if the protocol returns NO to -[self canSendOfflineMessageToContact:] |
|
Evan@46
|
380 |
* If invisible contacts exist and can be messaged, return YES. |
|
Evan@46
|
381 |
* If the protocol has no concept of invisible contacts, or invisible contacts can't be messaged, return NO. |
|
Evan@46
|
382 |
*/ |
|
Evan@48
|
383 |
- (BOOL)maySendMessageToInvisibleContact:(AIListContact *)inContact |
|
Evan@46
|
384 |
{ |
|
Evan@46
|
385 |
return YES; |
|
Evan@46
|
386 |
} |
|
Evan@46
|
387 |
|
|
Evan@46
|
388 |
/*! |
|
David@0
|
389 |
* @brief Should offline messages be sent without prompting the user? |
|
David@0
|
390 |
* |
|
David@0
|
391 |
* If -[self canSendOfflineMessageToContact:] returns YES, Adium typically asks the user whether or not to send a message |
|
David@0
|
392 |
* to be stored on the server. If sendOfflineMessagesWithoutPrompting returns YES, this prompt is always suppressed. |
|
David@0
|
393 |
* |
|
Evan@672
|
394 |
* This should only be true if offline messaging is a well-established expectation for the service. We assume that |
|
Evan@672
|
395 |
* this is the case by default. |
|
David@0
|
396 |
*/ |
|
David@0
|
397 |
- (BOOL)sendOfflineMessagesWithoutPrompting |
|
David@0
|
398 |
{ |
|
Evan@672
|
399 |
return YES; |
|
David@0
|
400 |
} |
|
David@0
|
401 |
|
|
David@0
|
402 |
/*! |
|
David@0
|
403 |
* @brief Does the account itself display file transfer messages in chat windows? |
|
David@0
|
404 |
* |
|
David@0
|
405 |
* If YES, Adium won't attempt to display messages in chat windows regarding file transfers. |
|
David@0
|
406 |
* If NO, Adium automatically displays appropriate messages in open chats. |
|
David@0
|
407 |
*/ |
|
David@0
|
408 |
- (BOOL)accountDisplaysFileTransferMessages |
|
David@0
|
409 |
{ |
|
David@0
|
410 |
return NO; |
|
David@0
|
411 |
} |
|
David@0
|
412 |
|
|
David@0
|
413 |
/*! |
|
David@0
|
414 |
* @brief Does the account manage its own cache of serverside contact icons? |
|
David@0
|
415 |
*/ |
|
David@0
|
416 |
- (BOOL)managesOwnContactIconCache |
|
David@0
|
417 |
{ |
|
David@0
|
418 |
return NO; |
|
David@0
|
419 |
} |
|
David@0
|
420 |
|
|
David@0
|
421 |
/*! |
|
David@0
|
422 |
* @brief Called once the display name has been properly filtered |
|
David@0
|
423 |
* |
|
David@0
|
424 |
* Subclasses may override to pass this name on to the server if appropriate. |
|
David@0
|
425 |
* Super's implementation should then be called. |
|
David@0
|
426 |
*/ |
|
David@0
|
427 |
- (void)gotFilteredDisplayName:(NSAttributedString *)attributedDisplayName |
|
David@0
|
428 |
{ |
|
David@0
|
429 |
[self updateLocalDisplayNameTo:attributedDisplayName]; |
|
David@0
|
430 |
} |
|
David@0
|
431 |
|
|
David@0
|
432 |
- (NSImage *)userIcon |
|
David@0
|
433 |
{ |
|
David@0
|
434 |
NSData *iconData = [self userIconData]; |
|
David@0
|
435 |
return (iconData ? [[[NSImage alloc] initWithData:iconData] autorelease] : nil); |
|
David@0
|
436 |
} |
|
David@0
|
437 |
|
|
David@1599
|
438 |
@synthesize isTemporary; |
|
David@1599
|
439 |
|
|
David@0
|
440 |
//Status --------------------------------------------------------------------------------------------------------------- |
|
David@0
|
441 |
#pragma mark Status |
|
David@0
|
442 |
/*! |
|
David@0
|
443 |
* @brief Supported properties |
|
David@0
|
444 |
* |
|
David@0
|
445 |
* Returns an array of properties supported by this account. This account will not be informed of changes to keys |
|
David@0
|
446 |
* it does not support. Available keys are: |
|
David@0
|
447 |
* @"Display Name", @"Online", @"Offline", @"IdleSince", @"IdleManuallySet", @"User Icon" |
|
David@0
|
448 |
* @"TextProfile", @"DefaultUserIconFilename", @"StatusState" |
|
David@0
|
449 |
* @return NSSet of supported keys |
|
David@0
|
450 |
*/ |
|
David@0
|
451 |
- (NSSet *)supportedPropertyKeys |
|
David@0
|
452 |
{ |
|
David@0
|
453 |
static NSSet *supportedPropertyKeys = nil; |
|
David@0
|
454 |
if (!supportedPropertyKeys) { |
|
David@0
|
455 |
supportedPropertyKeys = [[NSSet alloc] initWithObjects: |
|
David@0
|
456 |
@"Online", |
|
David@0
|
457 |
@"FormattedUID", |
|
David@0
|
458 |
KEY_ACCOUNT_DISPLAY_NAME, |
|
David@0
|
459 |
@"Display Name", |
|
David@0
|
460 |
@"StatusState", |
|
David@0
|
461 |
KEY_USE_USER_ICON, KEY_USER_ICON, KEY_DEFAULT_USER_ICON, |
|
David@0
|
462 |
@"Enabled", |
|
David@0
|
463 |
nil]; |
|
David@0
|
464 |
} |
|
David@0
|
465 |
|
|
David@0
|
466 |
return supportedPropertyKeys; |
|
David@0
|
467 |
} |
|
David@0
|
468 |
|
|
David@0
|
469 |
/*! |
|
David@0
|
470 |
* @brief Status for key |
|
David@0
|
471 |
* |
|
David@0
|
472 |
* Returns the status this account should be for a specific key |
|
David@0
|
473 |
* @param key Property |
|
David@0
|
474 |
* @return id Status value |
|
David@0
|
475 |
*/ |
|
David@0
|
476 |
- (id)statusForKey:(NSString *)key |
|
David@0
|
477 |
{ |
|
David@0
|
478 |
return [self preferenceForKey:key group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
479 |
} |
|
David@0
|
480 |
|
|
David@0
|
481 |
/*! |
|
David@0
|
482 |
* @brief Update account status |
|
David@0
|
483 |
* |
|
David@0
|
484 |
* Update account status for the changed key. This is called when account status changes Adium-side and the account |
|
David@0
|
485 |
* code should update status account/server side in response. The new value for the key can be accessed using |
|
David@0
|
486 |
* the statusForKey method. |
|
David@0
|
487 |
* @param key The updated property |
|
David@0
|
488 |
*/ |
|
David@0
|
489 |
- (void)updateStatusForKey:(NSString *)key |
|
David@0
|
490 |
{ |
|
David@0
|
491 |
[self updateCommonStatusForKey:key]; |
|
David@0
|
492 |
} |
|
David@0
|
493 |
|
|
David@0
|
494 |
/*! |
|
David@0
|
495 |
* @brief Update contact status |
|
David@0
|
496 |
* |
|
David@0
|
497 |
* Adium is requesting that the account update a contact's status. This method is primarily called by the get info |
|
David@0
|
498 |
* window. Since this is called sparsely, accounts may choose to look up additional information such as profiles |
|
David@0
|
499 |
* in response to this. Adium guards this method to prevent it from being called too rapidly, so expensive lookups |
|
David@0
|
500 |
* are not a problem if the delayedUpdateStatusInterval is set correctly. |
|
David@0
|
501 |
*/ |
|
David@0
|
502 |
- (void)delayedUpdateContactStatus:(AIListContact *)inContact |
|
David@0
|
503 |
{ |
|
David@0
|
504 |
|
|
David@0
|
505 |
} |
|
David@0
|
506 |
|
|
David@0
|
507 |
/*! |
|
David@0
|
508 |
* @brief Update contact interval |
|
David@0
|
509 |
* |
|
David@0
|
510 |
* Specifies the mininum interval at which delayedUpdateContactStatus will be called. If the account code is performing |
|
David@0
|
511 |
* expensive operations (such as profile or web lookups) in response to updateContactStatus, it can guard against |
|
David@0
|
512 |
* the lookups being performed too frequently by returning an interval here. |
|
David@0
|
513 |
*/ |
|
David@0
|
514 |
- (float)delayedUpdateStatusInterval |
|
David@0
|
515 |
{ |
|
David@0
|
516 |
return 0.5; |
|
David@0
|
517 |
} |
|
David@0
|
518 |
|
|
David@0
|
519 |
/*! |
|
David@0
|
520 |
* @brief Perform the setting of a status state |
|
David@0
|
521 |
* |
|
David@0
|
522 |
* Sets the account to a passed status state. The account should set itself to best possible status given the return |
|
David@0
|
523 |
* values of statusState's accessors. The passed statusMessage has been filtered; it should be used rather than |
|
David@837
|
524 |
* statusState.statusMessage, which returns an unfiltered statusMessage. |
|
David@0
|
525 |
* |
|
David@0
|
526 |
* @param statusState The state to enter |
|
David@0
|
527 |
* @param statusMessage The filtered status message to use. |
|
David@0
|
528 |
*/ |
|
David@0
|
529 |
- (void)setStatusState:(AIStatus *)statusState usingStatusMessage:(NSAttributedString *)statusMessage |
|
David@0
|
530 |
{ |
|
David@0
|
531 |
|
|
David@0
|
532 |
} |
|
David@0
|
533 |
|
|
David@0
|
534 |
/*! |
|
David@0
|
535 |
* @brief Set the social networking status message for this account |
|
David@0
|
536 |
* |
|
David@427
|
537 |
* This will only be called if [self.service isSocialNetworkingService] returns TRUE. |
|
David@0
|
538 |
* |
|
David@0
|
539 |
* @param statusMessage The status message, which has already been filtered. |
|
David@0
|
540 |
*/ |
|
David@0
|
541 |
- (void)setSocialNetworkingStatusMessage:(NSAttributedString *)statusMessage |
|
David@0
|
542 |
{ |
|
David@0
|
543 |
|
|
David@0
|
544 |
} |
|
David@0
|
545 |
/*! |
|
David@0
|
546 |
* @brief Should the autorefreshing attributed string associated with a key be updated at the moment? |
|
David@0
|
547 |
* |
|
David@0
|
548 |
* The default implementation causes all dynamic strings which need updating to be updated if the account is |
|
David@0
|
549 |
* online. Subclasses may choose to implement more complex logic; for example, a nickname seen only in a chat |
|
David@0
|
550 |
* might be updated only if a chat is open. |
|
David@0
|
551 |
*/ |
|
David@0
|
552 |
- (BOOL)shouldUpdateAutorefreshingAttributedStringForKey:(NSString *)inKey |
|
David@0
|
553 |
{ |
|
David@837
|
554 |
return self.online; |
|
David@0
|
555 |
} |
|
David@0
|
556 |
|
|
David@0
|
557 |
//Messaging, Chatting, Strings ----------------------------------------------------------------------------------------- |
|
David@0
|
558 |
#pragma mark Messaging, Chatting, Strings |
|
David@0
|
559 |
/*! |
|
David@0
|
560 |
* @brief Available for sending content |
|
David@0
|
561 |
* |
|
David@0
|
562 |
* Returns YES if the contact is available for receiving content of the specified type. If contact is nil, instead |
|
David@0
|
563 |
* check for the availiability to send any content of the given type. |
|
David@0
|
564 |
* |
|
David@0
|
565 |
* The default implementation indicates the account, if online, can send messages to any online contact. |
|
David@0
|
566 |
* It can also send files to any online contact if the account subclass conforms to the AIAccount_Files protocol. |
|
David@0
|
567 |
* |
|
David@0
|
568 |
* @param inType A string content type |
|
David@0
|
569 |
* @param inContact The destination contact, or nil to check global availability |
|
David@0
|
570 |
*/ |
|
David@0
|
571 |
- (BOOL)availableForSendingContentType:(NSString *)inType toContact:(AIListContact *)inContact |
|
David@0
|
572 |
{ |
|
David@0
|
573 |
if ([inType isEqualToString:CONTENT_MESSAGE_TYPE] || |
|
David@0
|
574 |
[inType isEqualToString:CONTENT_NOTIFICATION_TYPE]) { |
|
David@837
|
575 |
return (self.online && |
|
David@837
|
576 |
(!inContact || inContact.online || inContact.isStranger || [self canSendOfflineMessageToContact:inContact])); |
|
David@0
|
577 |
|
|
David@0
|
578 |
} else if ([inType isEqualToString:CONTENT_FILE_TRANSFER_TYPE]) { |
|
David@837
|
579 |
return (self.online && [self conformsToProtocol:@protocol(AIAccount_Files)] && |
|
David@837
|
580 |
(!inContact || inContact.online || inContact.isStranger)); |
|
David@0
|
581 |
} |
|
David@0
|
582 |
|
|
David@0
|
583 |
return NO; |
|
David@0
|
584 |
} |
|
David@0
|
585 |
|
|
David@0
|
586 |
/*! |
|
David@0
|
587 |
* @brief Open a chat |
|
David@0
|
588 |
* |
|
David@0
|
589 |
* Open the passed chat account-side. Depending on the protocol, account code may need to establish a connection in |
|
David@0
|
590 |
* response to this method or perhaps make no actions at all. This method is used by both one-on-one chats and |
|
David@0
|
591 |
* multi-user chats. |
|
David@0
|
592 |
* @param chat The chat to open |
|
David@0
|
593 |
* @return YES on success |
|
David@0
|
594 |
*/ |
|
David@0
|
595 |
- (BOOL)openChat:(AIChat *)chat |
|
David@0
|
596 |
{ |
|
David@0
|
597 |
return NO; |
|
David@0
|
598 |
} |
|
David@0
|
599 |
|
|
David@0
|
600 |
/*! |
|
David@0
|
601 |
* @brief Close a chat |
|
David@0
|
602 |
* |
|
David@0
|
603 |
* Close the passed chat account-side. Depending on the protocol, account code may need to close a connection in |
|
David@0
|
604 |
* response to this method or perhaps make no actions at all. This method is used by both one-on-one chats and |
|
David@0
|
605 |
* multi-user chats. |
|
David@0
|
606 |
* |
|
David@100
|
607 |
* This method should *only* be called by a core controller. Call [adium.interfaceController closeChat:chat] to perform a close from other code. |
|
David@0
|
608 |
* |
|
David@0
|
609 |
* @param chat The chat to close |
|
David@0
|
610 |
* @return YES on success |
|
David@0
|
611 |
*/ |
|
David@0
|
612 |
- (BOOL)closeChat:(AIChat *)chat |
|
David@0
|
613 |
{ |
|
David@0
|
614 |
return NO; |
|
David@0
|
615 |
} |
|
David@0
|
616 |
|
|
David@0
|
617 |
/*! |
|
David@0
|
618 |
* @brief Invite a contact to an open chat |
|
David@0
|
619 |
* |
|
David@0
|
620 |
* Invite a contact to the passed chat, if supported by the protocol and the specific chat instance. An invite |
|
David@0
|
621 |
* message is provided as a convenience to protocols that require or support one. |
|
David@0
|
622 |
* @param contact AIListObject to invite |
|
David@0
|
623 |
* @param chat AIChat they are being invited to |
|
David@0
|
624 |
* @param inviteMessage NSString invite message for the invited contact |
|
David@0
|
625 |
* @return YES on success |
|
David@0
|
626 |
*/ |
|
David@0
|
627 |
- (BOOL)inviteContact:(AIListObject *)contact toChat:(AIChat *)chat withMessage:(NSString *)inviteMessage |
|
David@0
|
628 |
{ |
|
David@0
|
629 |
NSLog(@"invite contact to chat with message"); |
|
David@0
|
630 |
return NO; |
|
David@0
|
631 |
} |
|
David@0
|
632 |
|
|
David@0
|
633 |
/*! |
|
David@0
|
634 |
* @brief Send a typing object |
|
David@0
|
635 |
* |
|
David@0
|
636 |
* The content object contains all the necessary information for sending, |
|
David@0
|
637 |
* including the destination contact. |
|
David@0
|
638 |
*/ |
|
David@0
|
639 |
- (void)sendTypingObject:(AIContentTyping *)inTypingObject |
|
David@0
|
640 |
{ |
|
David@0
|
641 |
|
|
David@0
|
642 |
} |
|
David@0
|
643 |
|
|
David@0
|
644 |
/*! |
|
David@0
|
645 |
* @brief Send a message |
|
David@0
|
646 |
* |
|
David@0
|
647 |
* The content object contains all the necessary information for sending, |
|
David@0
|
648 |
* including the destination contact. [inMessageObject encodedMessage] contains the NSString which should be sent. |
|
David@0
|
649 |
*/ |
|
David@0
|
650 |
- (BOOL)sendMessageObject:(AIContentMessage *)inMessageObject |
|
David@0
|
651 |
{ |
|
David@0
|
652 |
return NO; |
|
David@0
|
653 |
} |
|
David@0
|
654 |
|
|
David@0
|
655 |
/*! |
|
zacw@1716
|
656 |
* @brief Does the account support sending notifications? |
|
zacw@1716
|
657 |
*/ |
|
zacw@1716
|
658 |
- (BOOL)supportsSendingNotifications |
|
zacw@1716
|
659 |
{ |
|
zacw@1716
|
660 |
return NO; |
|
zacw@1716
|
661 |
} |
|
zacw@1716
|
662 |
|
|
zacw@1716
|
663 |
/*! |
|
zacw@1716
|
664 |
* @brief Send a notification |
|
zacw@1716
|
665 |
*/ |
|
zacw@1716
|
666 |
- (BOOL)sendNotificationObject:(AIContentNotification *)inContentNotification |
|
zacw@1716
|
667 |
{ |
|
zacw@1716
|
668 |
return NO; |
|
zacw@1716
|
669 |
} |
|
zacw@1716
|
670 |
|
|
zacw@1716
|
671 |
/*! |
|
David@0
|
672 |
* @brief Encode attributed string (generic) |
|
David@0
|
673 |
* |
|
David@0
|
674 |
* Encode an NSAttributedString into a NSString for this account. Accounts that support formatted text or require |
|
David@0
|
675 |
* special encoding on strings should do that work here. For example, HTML based accounts should convert the |
|
David@0
|
676 |
* NSAttributedString to HTML appropriate for their protocol (Adium can help with this). |
|
David@0
|
677 |
* @param inAttributedString String to encode |
|
David@0
|
678 |
* @param inListObject List object associated with the string; nil if the string is not associated with a particular list object, which is the case if encoding for a status message or a group chat message. |
|
David@0
|
679 |
* @return NSString result from encoding |
|
David@0
|
680 |
*/ |
|
David@0
|
681 |
- (NSString *)encodedAttributedString:(NSAttributedString *)inAttributedString forListObject:(AIListObject *)inListObject |
|
David@0
|
682 |
{ |
|
David@0
|
683 |
return [inAttributedString string]; |
|
David@0
|
684 |
} |
|
David@0
|
685 |
|
|
David@0
|
686 |
/*! |
|
David@0
|
687 |
* @brief Encode attributed string to send as a message |
|
David@0
|
688 |
*/ |
|
David@0
|
689 |
- (NSString *)encodedAttributedStringForSendingContentMessage:(AIContentMessage *)inContentMessage |
|
David@0
|
690 |
{ |
|
David@813
|
691 |
return [self encodedAttributedString:inContentMessage.message forListObject:[inContentMessage destination]]; |
|
David@0
|
692 |
} |
|
David@0
|
693 |
|
|
Evan@522
|
694 |
/*! |
|
Evan@522
|
695 |
* @brief Should an autoreply be sent to this message? |
|
Evan@522
|
696 |
* |
|
Evan@522
|
697 |
* This will only be called if the generic algorithm determines that an autoreply is appropriate. The account |
|
Evan@522
|
698 |
* gets an opportunity to suppress sending the autoreply, e.g. on the basis of the message's content or source. |
|
Evan@522
|
699 |
*/ |
|
Evan@522
|
700 |
- (BOOL)shouldSendAutoreplyToMessage:(AIContentMessage *)message |
|
Evan@522
|
701 |
{ |
|
Evan@522
|
702 |
return YES; |
|
Evan@522
|
703 |
} |
|
Evan@522
|
704 |
|
|
David@0
|
705 |
//Presence Tracking ---------------------------------------------------------------------------------------------------- |
|
David@0
|
706 |
#pragma mark Presence Tracking |
|
David@0
|
707 |
/*! |
|
David@0
|
708 |
* @brief Contact list editable? |
|
David@0
|
709 |
* |
|
David@0
|
710 |
* @return YES if the contact list is currently editable |
|
David@0
|
711 |
*/ |
|
David@0
|
712 |
- (BOOL)contactListEditable |
|
David@0
|
713 |
{ |
|
David@0
|
714 |
return NO; |
|
David@0
|
715 |
} |
|
David@0
|
716 |
|
|
David@0
|
717 |
/*! |
|
David@0
|
718 |
* @brief Add contacts |
|
David@0
|
719 |
* |
|
David@0
|
720 |
* Add contacts to a group on this account. Create the group if it doesn't already exist. |
|
David@0
|
721 |
* @param objects NSArray of AIListContact objects to add |
|
David@0
|
722 |
* @param group AIListGroup destination for contacts |
|
David@0
|
723 |
*/ |
|
David@199
|
724 |
- (void)addContact:(AIListContact *)contact toGroup:(AIListGroup *)group |
|
David@0
|
725 |
{ |
|
David@0
|
726 |
//XXX - Our behavior for duplicate contacts isn't specified here. Should we handle that adium-side automatically? -ai |
|
David@0
|
727 |
} |
|
David@0
|
728 |
|
|
David@0
|
729 |
/*! |
|
David@0
|
730 |
* @brief Remove contacts |
|
David@0
|
731 |
* |
|
David@0
|
732 |
* Remove contacts from this account. |
|
David@0
|
733 |
* @param objects NSArray of AIListContact objects to remove |
|
zacw@2131
|
734 |
* @param groups NSArray of AIListGroup objects to remove from. |
|
David@0
|
735 |
*/ |
|
zacw@2131
|
736 |
- (void)removeContacts:(NSArray *)objects fromGroups:(NSArray *)groups |
|
David@0
|
737 |
{ |
|
David@0
|
738 |
|
|
David@0
|
739 |
} |
|
David@0
|
740 |
|
|
David@0
|
741 |
/*! |
|
David@0
|
742 |
* @brief Remove a group |
|
David@0
|
743 |
* |
|
David@0
|
744 |
* Remove a group from this account. |
|
David@0
|
745 |
* @param group AIListGroup to remove |
|
David@0
|
746 |
*/ |
|
David@0
|
747 |
- (void)deleteGroup:(AIListGroup *)group |
|
David@0
|
748 |
{ |
|
David@0
|
749 |
//XXX - Adium's current behavior is to delete all the contacts within a group, and then delete the group. This is innefficient on protocols which support deleting groups. -ai |
|
David@0
|
750 |
} |
|
David@0
|
751 |
|
|
David@0
|
752 |
/*! |
|
David@0
|
753 |
* @brief Move contacts |
|
David@0
|
754 |
* |
|
David@0
|
755 |
* Move existing contacts to a specific group on this account. The passed contacts should already exist somewhere on |
|
David@0
|
756 |
* this account. |
|
David@0
|
757 |
* @param objects NSArray of AIListContact objects to remove |
|
zacw@2128
|
758 |
* @param oldGroups NSSet of AIListGroup source for contacts |
|
zacw@2128
|
759 |
* @param group NSSet of AIListGroup destination for contacts |
|
David@0
|
760 |
*/ |
|
zacw@2128
|
761 |
- (void)moveListObjects:(NSArray *)objects fromGroups:(NSSet *)oldGroups toGroups:(NSSet *)groups |
|
David@0
|
762 |
{ |
|
David@709
|
763 |
NSAssert(NO, @"Should not be reached"); |
|
David@0
|
764 |
} |
|
David@0
|
765 |
|
|
David@0
|
766 |
/*! |
|
David@0
|
767 |
* @brief Rename a group |
|
David@0
|
768 |
* |
|
David@0
|
769 |
* Rename a group on this account. |
|
David@0
|
770 |
* @param group AIListGroup to rename |
|
David@0
|
771 |
* @param newName NSString name for the group |
|
David@0
|
772 |
*/ |
|
David@0
|
773 |
- (void)renameGroup:(AIListGroup *)group to:(NSString *)newName |
|
David@0
|
774 |
{ |
|
David@709
|
775 |
NSAssert(NO, @"Should not be reached"); |
|
David@0
|
776 |
} |
|
David@0
|
777 |
|
|
David@0
|
778 |
/*! |
|
David@0
|
779 |
* @brief Menu items for contact |
|
David@0
|
780 |
* |
|
David@0
|
781 |
* Returns an array of menu items for a contact on this account. This is the best place to add protocol-specific |
|
David@0
|
782 |
* actions that aren't otherwise supported by Adium. |
|
David@0
|
783 |
* @param inContact AIListContact for menu items |
|
David@0
|
784 |
* @return NSArray of NSMenuItem instances for the passed contact |
|
David@0
|
785 |
*/ |
|
David@0
|
786 |
- (NSArray *)menuItemsForContact:(AIListContact *)inContact |
|
David@0
|
787 |
{ |
|
David@0
|
788 |
return nil; |
|
David@0
|
789 |
} |
|
David@0
|
790 |
|
|
David@0
|
791 |
/*! |
|
zacw@806
|
792 |
* @brief Menu items for chat |
|
zacw@806
|
793 |
* |
|
zacw@806
|
794 |
* Returns an array of menu items for a chat on this account. This is the best place to add protocol-specific |
|
zacw@806
|
795 |
* actions that aren't otherwise supported by Adium. |
|
zacw@806
|
796 |
* @param inChat AIChat for menu items |
|
zacw@806
|
797 |
* @return NSArray of NSMenuItem instances for the passed contact |
|
zacw@806
|
798 |
*/ |
|
zacw@806
|
799 |
- (NSArray *)menuItemsForChat:(AIChat *)inChat |
|
zacw@806
|
800 |
{ |
|
zacw@806
|
801 |
return nil; |
|
zacw@806
|
802 |
} |
|
zacw@806
|
803 |
|
|
zacw@806
|
804 |
/*! |
|
David@0
|
805 |
* @brief Menu items for the account's actions |
|
David@0
|
806 |
* |
|
David@0
|
807 |
* Returns an array of menu items for account-specific actions. This is the best place to add protocol-specific |
|
David@0
|
808 |
* actions that aren't otherwise supported by Adium. It will only be queried if the account is online. |
|
David@0
|
809 |
* @return NSArray of NSMenuItem instances for this account |
|
David@0
|
810 |
*/ |
|
David@0
|
811 |
- (NSArray *)accountActionMenuItems |
|
David@0
|
812 |
{ |
|
David@0
|
813 |
return nil; |
|
David@0
|
814 |
} |
|
David@0
|
815 |
|
|
David@0
|
816 |
/*! |
|
David@0
|
817 |
* @brief The account menu item was updated |
|
David@0
|
818 |
* |
|
David@0
|
819 |
* This method allows the opportunity to update the account menu item, e.g. to add information to it |
|
David@0
|
820 |
*/ |
|
David@0
|
821 |
- (void)accountMenuDidUpdate:(NSMenuItem*)menuItem |
|
David@0
|
822 |
{ |
|
David@0
|
823 |
|
|
David@0
|
824 |
} |
|
David@0
|
825 |
|
|
David@0
|
826 |
/*! |
|
David@0
|
827 |
* @brief Is a contact on the contact list intentionally listed? |
|
David@0
|
828 |
* |
|
David@0
|
829 |
* By default, it is assumed that any contact on the list is intended be there. |
|
David@0
|
830 |
* This is used by AIListContact to determine if the prescence of itself on the list is indicative of a degree |
|
David@0
|
831 |
* of trust, for preferences such as "automatically accept files from contacts on my contact list". |
|
David@0
|
832 |
*/ |
|
David@0
|
833 |
- (BOOL)isContactIntentionallyListed:(AIListContact *)contact |
|
David@0
|
834 |
{ |
|
David@0
|
835 |
return YES; |
|
David@0
|
836 |
} |
|
David@0
|
837 |
|
|
David@0
|
838 |
/*! |
|
David@0
|
839 |
* @brief Return the data for the serverside icon for a contact |
|
David@0
|
840 |
*/ |
|
David@0
|
841 |
- (NSData *)serversideIconDataForContact:(AIListContact *)contact |
|
David@0
|
842 |
{ |
|
David@0
|
843 |
return nil; |
|
David@0
|
844 |
} |
|
David@0
|
845 |
|
|
David@0
|
846 |
#pragma mark Secure messsaging |
|
David@0
|
847 |
|
|
David@0
|
848 |
/*! |
|
David@0
|
849 |
* @brief Allow secure messaging toggling on a chat? |
|
David@0
|
850 |
* |
|
David@0
|
851 |
* Returns YES if secure (encrypted) messaging's status for this chat should be able to be changed. |
|
David@0
|
852 |
* This allows the account to determine on a per-chat basis whether the chat's initial security setting should be permanently |
|
David@0
|
853 |
* maintained. If it returns NO, the user can not request for the chat to become encrypted or unencrypted. |
|
David@0
|
854 |
* This is currently implemented by Gaim accounts to return YES for one-on-one chats and NO for group chats to indicate |
|
David@0
|
855 |
* the functionality provided by Off-the-Record Messaging (OTR). |
|
David@0
|
856 |
* |
|
David@0
|
857 |
* @param inChat The query chat |
|
David@0
|
858 |
* @result Should the state of secure messaging be allowed to change? |
|
David@0
|
859 |
*/ |
|
David@0
|
860 |
- (BOOL)allowSecureMessagingTogglingForChat:(AIChat *)inChat |
|
David@0
|
861 |
{ |
|
David@0
|
862 |
//Allow secure messaging via OTR for one-on-one chats |
|
David@812
|
863 |
return !inChat.isGroupChat; |
|
David@0
|
864 |
} |
|
David@0
|
865 |
|
|
David@0
|
866 |
/*! |
|
David@0
|
867 |
* @brief Provide a localized description of the encryption this account provides |
|
David@0
|
868 |
* |
|
David@0
|
869 |
* Returns a localized string which describes the encryption this account supports. |
|
David@0
|
870 |
* |
|
David@0
|
871 |
* @result An <tt>NSString</tt> describing the encryption offerred by this account, if any. |
|
David@0
|
872 |
*/ |
|
David@0
|
873 |
- (NSString *)aboutEncryption |
|
David@0
|
874 |
{ |
|
David@0
|
875 |
return [NSString stringWithFormat: |
|
David@0
|
876 |
AILocalizedStringFromTableInBundle(@"Adium provides encryption, authentication, deniability, and perfect forward secrecy over %@ via Off-the-Record Messaging (OTR). If your contact is not using an OTR-compatible messaging system, your contact will be sent a link to the OTR web site when you attempt to connect. For more information on OTR, visit http://www.cypherpunks.ca/otr/.", nil, [NSBundle bundleForClass:[AIAccount class]], nil), |
|
David@427
|
877 |
[self.service shortDescription]]; |
|
David@0
|
878 |
} |
|
David@0
|
879 |
|
|
David@0
|
880 |
/*! |
|
David@0
|
881 |
* @brief Start or stop secure messaging in a chat |
|
David@0
|
882 |
* |
|
David@0
|
883 |
* @param inSecureMessaging The desired state of the chat in terms of encryption |
|
David@0
|
884 |
* @param inChat The chat to change |
|
David@0
|
885 |
*/ |
|
David@0
|
886 |
- (void)requestSecureMessaging:(BOOL)inSecureMessaging |
|
David@0
|
887 |
inChat:(AIChat *)inChat |
|
David@0
|
888 |
{ |
|
David@95
|
889 |
[adium.contentController requestSecureOTRMessaging:inSecureMessaging |
|
David@0
|
890 |
inChat:inChat]; |
|
David@0
|
891 |
} |
|
David@0
|
892 |
|
|
David@0
|
893 |
/*! |
|
David@0
|
894 |
* @brief Allow the user to verify (or unverify) the identity being used for encryption in a chat |
|
David@0
|
895 |
* |
|
David@0
|
896 |
* It is an error to call this on a chat which is not currently encrypted. |
|
David@0
|
897 |
* |
|
David@0
|
898 |
* @param inChat The chat |
|
David@0
|
899 |
*/ |
|
David@0
|
900 |
- (void)promptToVerifyEncryptionIdentityInChat:(AIChat *)inChat |
|
David@0
|
901 |
{ |
|
David@95
|
902 |
[adium.contentController promptToVerifyEncryptionIdentityInChat:inChat]; |
|
David@0
|
903 |
} |
|
David@0
|
904 |
|
|
David@0
|
905 |
#pragma mark Image sending |
|
David@0
|
906 |
/*! |
|
David@0
|
907 |
* @brief Can the account send images inline within a chat? |
|
David@0
|
908 |
*/ |
|
David@0
|
909 |
- (BOOL)canSendImagesForChat:(AIChat *)inChat |
|
David@0
|
910 |
{ |
|
David@0
|
911 |
return NO; |
|
David@0
|
912 |
} |
|
David@0
|
913 |
|
|
David@0
|
914 |
#pragma mark Authorization |
|
David@0
|
915 |
/*! |
|
David@0
|
916 |
* @brief An authorization prompt closed, granting or denying a contact's request for authorization |
|
David@0
|
917 |
* |
|
zacw@1257
|
918 |
* @param inDict A dictionary of authorization information created by the account originally and unmodified |
|
David@0
|
919 |
* @param authorizationResponse An AIAuthorizationResponse indicating if authorization was granted or denied or if there was no response |
|
David@0
|
920 |
*/ |
|
zacw@1257
|
921 |
- (void)authorizationWithDict:(NSDictionary *)infoDict response:(AIAuthorizationResponse)authorizationResponse; |
|
David@0
|
922 |
{} |
|
David@0
|
923 |
|
|
zacw@1442
|
924 |
#pragma mark Group Chats |
|
zacw@963
|
925 |
/*! |
|
zacw@963
|
926 |
* @brief Should the chat autocomplete the UID instead of the Display Name? |
|
zacw@963
|
927 |
*/ |
|
zacw@963
|
928 |
- (BOOL)chatShouldAutocompleteUID:(AIChat *)inChat |
|
zacw@963
|
929 |
{ |
|
zacw@963
|
930 |
return NO; |
|
zacw@963
|
931 |
} |
|
zacw@963
|
932 |
|
|
zacw@1609
|
933 |
-(NSMenu*)actionMenuForChat:(AIChat*)chat |
|
David@0
|
934 |
{ |
|
David@0
|
935 |
return nil; |
|
David@0
|
936 |
} |
|
David@0
|
937 |
|
|
zacw@1442
|
938 |
/*! |
|
zacw@1442
|
939 |
* @brief Does the account manage group chat ignoring? |
|
zacw@1442
|
940 |
* |
|
zacw@1442
|
941 |
* If it doesn't, the AIChat will handle ignoring itself. |
|
zacw@1442
|
942 |
*/ |
|
zacw@1442
|
943 |
- (BOOL)accountManagesGroupChatIgnore |
|
zacw@1442
|
944 |
{ |
|
zacw@1442
|
945 |
return NO; |
|
zacw@1442
|
946 |
} |
|
zacw@1442
|
947 |
|
|
zacw@1442
|
948 |
/*! |
|
zacw@1442
|
949 |
* @brief Return if a contact is ignored |
|
zacw@1442
|
950 |
* |
|
zacw@1442
|
951 |
* @param inContact The AIListContact |
|
zacw@1442
|
952 |
* @param chat The AIChat the inContact is a member of. |
|
zacw@1442
|
953 |
* |
|
zacw@1442
|
954 |
* @return YES if ignored, NO otherwise. |
|
zacw@1442
|
955 |
*/ |
|
zacw@1442
|
956 |
- (BOOL)contact:(AIListContact *)inContact isIgnoredInChat:(AIChat *)chat |
|
zacw@1442
|
957 |
{ |
|
zacw@1442
|
958 |
return NO; |
|
zacw@1442
|
959 |
} |
|
zacw@1442
|
960 |
|
|
zacw@1442
|
961 |
/*! |
|
zacw@1442
|
962 |
* @brief Ignore a contact |
|
zacw@1442
|
963 |
* |
|
zacw@1442
|
964 |
* @param inContact The AIListContact |
|
zacw@1442
|
965 |
* @param inIgnored YES if the contact should be ignored, NO otherwise. |
|
zacw@1442
|
966 |
* @param chat The AIChat the inContact is a member of. |
|
zacw@1442
|
967 |
*/ |
|
zacw@1442
|
968 |
- (void)setContact:(AIListContact *)inContact ignored:(BOOL)inIgnored inChat:(AIChat *)chat |
|
zacw@1442
|
969 |
{ |
|
zacw@1442
|
970 |
|
|
zacw@1442
|
971 |
} |
|
zacw@1442
|
972 |
|
|
Evan@364
|
973 |
#pragma mark Logging |
|
Evan@364
|
974 |
- (BOOL)shouldLogChat:(AIChat *)chat |
|
Evan@364
|
975 |
{ |
|
Evan@364
|
976 |
return ![self isTemporary]; |
|
Evan@364
|
977 |
} |
|
Evan@364
|
978 |
|
|
David@0
|
979 |
#pragma mark AppleScript |
|
David@0
|
980 |
- (NSNumber *)scriptingInternalObjectID |
|
David@0
|
981 |
{ |
|
David@838
|
982 |
return [NSNumber numberWithInt:[self.internalObjectID intValue]]; |
|
David@0
|
983 |
} |
|
David@0
|
984 |
|
|
David@0
|
985 |
/** |
|
David@0
|
986 |
* @brief The standard objectSpecifier for this model object. |
|
David@0
|
987 |
* |
|
David@0
|
988 |
* AIAccount is contained by AIService, using the 'accounts' key. |
|
David@0
|
989 |
* Each instance has a unique integer identifier. |
|
David@0
|
990 |
*/ |
|
David@0
|
991 |
- (NSScriptObjectSpecifier *)objectSpecifier |
|
David@0
|
992 |
{ |
|
David@0
|
993 |
//get my service |
|
David@427
|
994 |
AIService *theService = self.service; |
|
David@0
|
995 |
NSScriptObjectSpecifier *containerRef = [theService objectSpecifier]; |
|
David@0
|
996 |
|
|
David@0
|
997 |
return [[[NSUniqueIDSpecifier alloc] |
|
David@0
|
998 |
initWithContainerClassDescription:[containerRef keyClassDescription] |
|
David@0
|
999 |
containerSpecifier:containerRef key:@"accounts" |
|
David@0
|
1000 |
uniqueID:[self scriptingInternalObjectID]] autorelease]; |
|
David@0
|
1001 |
} |
|
David@0
|
1002 |
|
|
David@0
|
1003 |
/** |
|
David@0
|
1004 |
* @brief Returns the UID of this account. |
|
David@0
|
1005 |
*/ |
|
David@0
|
1006 |
- (NSString *)scriptingUID |
|
David@0
|
1007 |
{ |
|
David@427
|
1008 |
return self.UID; |
|
David@0
|
1009 |
} |
|
David@0
|
1010 |
|
|
David@0
|
1011 |
/** |
|
David@0
|
1012 |
* @brief Ensures that it's impossible to set the UID of an account. |
|
David@0
|
1013 |
* |
|
David@0
|
1014 |
* This makes sense for the services I'm familiar with, like AIM and GTalk. It may not make sense for other protocols. |
|
David@0
|
1015 |
* However, it still doesn't seem necessary to do from code. |
|
David@0
|
1016 |
*/ |
|
David@0
|
1017 |
- (void)setScriptingUID:(NSString *)n |
|
David@0
|
1018 |
{ |
|
David@0
|
1019 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1020 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't dynamically change the UID of this account."]; |
|
David@0
|
1021 |
} |
|
David@0
|
1022 |
|
|
David@0
|
1023 |
/** |
|
David@0
|
1024 |
* @brief Make a contact, according to the passed dictionary of AppleScript properties |
|
David@0
|
1025 |
* |
|
David@0
|
1026 |
* @param properties A dictionary of the following keys: |
|
David@0
|
1027 |
* @"KeyDictionary" is the list of the properties in the "with properties" clause of the AS make command. |
|
David@0
|
1028 |
* @"UID" key of KeyDictionary is the required "name" property of contacts |
|
David@0
|
1029 |
* @"parentGroup" key of keyDictionary is the optional "contact group" property of contacts. |
|
David@0
|
1030 |
* If the parentGroup is not specified, the contact will not be added to the contact list. |
|
David@0
|
1031 |
*/ |
|
David@0
|
1032 |
- (id)makeContactWithProperties:(NSDictionary *)properties |
|
David@0
|
1033 |
{ |
|
David@0
|
1034 |
NSDictionary *keyDictionary = [properties objectForKey:@"KeyDictionary"]; |
|
David@0
|
1035 |
if (!keyDictionary) { |
|
David@0
|
1036 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1037 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create a contact without specifying contact properties."]; |
|
David@0
|
1038 |
return nil; |
|
David@0
|
1039 |
} |
|
David@0
|
1040 |
NSString *contactUID = [keyDictionary objectForKey:@"UID"]; |
|
David@0
|
1041 |
if (!contactUID) { |
|
David@0
|
1042 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1043 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create a contact without specifying the contact name."]; |
|
David@0
|
1044 |
return nil; |
|
David@0
|
1045 |
} |
|
David@427
|
1046 |
AIListContact *newContact = [adium.contactController contactWithService:self.service account:self UID:contactUID]; |
|
David@0
|
1047 |
NSScriptObjectSpecifier *groupSpecifier = [keyDictionary objectForKey:@"parentGroup"]; |
|
David@0
|
1048 |
AIListGroup *group = [groupSpecifier objectsByEvaluatingSpecifier]; |
|
David@0
|
1049 |
//If we have a group, we add this contact to the contact list. |
|
David@0
|
1050 |
if (groupSpecifier && group) { |
|
David@199
|
1051 |
[self addContact:newContact toGroup:group]; |
|
David@0
|
1052 |
} |
|
David@0
|
1053 |
|
|
David@0
|
1054 |
return newContact; |
|
David@0
|
1055 |
} |
|
David@0
|
1056 |
- (void)insertObject:(AIListObject *)contact inContactsAtIndex:(int)index |
|
David@0
|
1057 |
{ |
|
David@0
|
1058 |
//Intentially unimplemented. This should never be called (contacts are created a different way), but is required for KVC-compliance. |
|
David@0
|
1059 |
} |
|
zacw@2131
|
1060 |
- (void)removeObjectFromContactsAtIndex:(NSInteger)index |
|
David@0
|
1061 |
{ |
|
zacw@2131
|
1062 |
AIListObject *object = [self.contacts objectAtIndex:index]; |
|
zacw@2131
|
1063 |
|
|
zacw@2131
|
1064 |
for (AIListGroup *group in object.groups) { |
|
zacw@2131
|
1065 |
[object removeFromGroup:group]; |
|
zacw@2131
|
1066 |
} |
|
David@0
|
1067 |
} |
|
David@0
|
1068 |
|
|
David@0
|
1069 |
/** |
|
David@0
|
1070 |
* @brief Creates a chat according to the given properties. |
|
David@0
|
1071 |
* @param resolvedKeyDictionary The dictionary of arguments to the 'make' command. |
|
David@0
|
1072 |
* |
|
David@0
|
1073 |
* This uses my own custom make<Key>WithProperties KVC method. :) |
|
David@0
|
1074 |
* The idea is that be default Cocoa-AS will try to make an object using the standard alloc/init routines |
|
David@0
|
1075 |
* However, you may not want that to be the case. If an AS model object implements this method, then when its the |
|
David@0
|
1076 |
* target of a 'make' command, it will be called. The method should return a new object, already assigned to a |
|
David@0
|
1077 |
* container, as AICreateCommand will not do that for you. |
|
David@0
|
1078 |
*/ |
|
David@0
|
1079 |
- (id)makeChatWithProperties:(NSDictionary *)resolvedKeyDictionary |
|
David@0
|
1080 |
{ |
|
David@0
|
1081 |
AILogWithSignature(@"%@", resolvedKeyDictionary); |
|
David@0
|
1082 |
NSArray *participants = [resolvedKeyDictionary objectForKey:@"withContacts"]; |
|
David@0
|
1083 |
if (!participants) { |
|
David@0
|
1084 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1085 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create a chat without a contact!"]; |
|
David@0
|
1086 |
return nil; |
|
David@0
|
1087 |
} |
|
David@0
|
1088 |
if (![resolvedKeyDictionary objectForKey:@"newChatWindow"] && ![resolvedKeyDictionary objectForKey:@"Location"]) { |
|
David@0
|
1089 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1090 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create a chat without specifying its containing window."]; |
|
David@0
|
1091 |
return nil; |
|
David@0
|
1092 |
} |
|
David@0
|
1093 |
|
|
David@0
|
1094 |
if ([participants count] == 1) { |
|
David@0
|
1095 |
AIListContact *contact = [[participants objectAtIndex:0] objectsByEvaluatingSpecifier]; |
|
David@0
|
1096 |
if (!contact) { |
|
David@0
|
1097 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1098 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't find that contact!"]; |
|
David@0
|
1099 |
return nil; |
|
David@0
|
1100 |
} |
|
David@0
|
1101 |
AIMessageWindowController *chatWindowController = nil; |
|
David@0
|
1102 |
int index = -1; //at end by default |
|
David@0
|
1103 |
if ([resolvedKeyDictionary objectForKey:@"newChatWindow"]) { |
|
David@0
|
1104 |
//I need to put this in a new chat window |
|
David@100
|
1105 |
chatWindowController = [adium.interfaceController openContainerWithID:nil name:nil]; |
|
David@0
|
1106 |
} else { |
|
David@0
|
1107 |
//I need to figure out to which chat window the location specifier is referring. |
|
David@0
|
1108 |
//NSLog(@"Here is the info about the location specifier: %@",[resolvedKeyDictionary objectForKey:@"Location"]); |
|
David@0
|
1109 |
NSPositionalSpecifier *location = [resolvedKeyDictionary objectForKey:@"Location"]; |
|
David@0
|
1110 |
AIMessageWindow *chatWindow = [location insertionContainer]; |
|
David@0
|
1111 |
index = [location insertionIndex]; |
|
David@0
|
1112 |
chatWindowController = (AIMessageWindowController *)[chatWindow windowController]; |
|
David@0
|
1113 |
} |
|
David@0
|
1114 |
|
|
David@0
|
1115 |
if (!chatWindowController) { |
|
David@0
|
1116 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1117 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create chat in that chat window."]; |
|
David@0
|
1118 |
return nil; |
|
David@0
|
1119 |
} |
|
David@0
|
1120 |
|
|
David@95
|
1121 |
AIChat *newChat = [adium.chatController chatWithContact:contact]; |
|
David@0
|
1122 |
// NSLog(@"Making new chat %@ in chat window %@:%@",newChat,chatWindowController,[chatWindowController containerID]); |
|
David@100
|
1123 |
[adium.interfaceController openChat:newChat inContainerWithID:[chatWindowController containerID] atIndex:index]; |
|
David@0
|
1124 |
return newChat; |
|
David@0
|
1125 |
} else { |
|
David@427
|
1126 |
if (![self.service canCreateGroupChats]) { |
|
David@0
|
1127 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1128 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create a group chat with this service!"]; |
|
David@0
|
1129 |
return nil; |
|
David@0
|
1130 |
} |
|
David@0
|
1131 |
NSString *name = [resolvedKeyDictionary objectForKey:@"name"]; |
|
David@0
|
1132 |
if (!name) { |
|
David@0
|
1133 |
[[NSScriptCommand currentCommand] setScriptErrorNumber:errOSACantAssign]; |
|
David@0
|
1134 |
[[NSScriptCommand currentCommand] setScriptErrorString:@"Can't create a group chat without a name!"]; |
|
David@0
|
1135 |
return nil; |
|
David@0
|
1136 |
} |
|
David@0
|
1137 |
//this can take a while... |
|
David@0
|
1138 |
NSMutableArray *newParticipants = [[[NSMutableArray alloc] init] autorelease]; |
|
David@0
|
1139 |
for (int i=0;i<[participants count];i++) { |
|
David@0
|
1140 |
[newParticipants addObject:[[participants objectAtIndex:i] objectsByEvaluatingSpecifier]]; |
|
David@0
|
1141 |
} |
|
David@0
|
1142 |
|
|
David@95
|
1143 |
//AIChat *newChat = [adium.chatController chatWithName:name identifier:nil onAccount:self chatCreationInfo:nil]; |
|
David@0
|
1144 |
DCJoinChatViewController *chatController = [DCJoinChatViewController joinChatView]; |
|
David@0
|
1145 |
[chatController doJoinChatWithName:name onAccount:self chatCreationInfo:nil invitingContacts:newParticipants withInvitationMessage:@"Hey, wanna join my chat?"]; |
|
David@95
|
1146 |
return [adium.chatController existingChatWithName:name onAccount:self]; |
|
David@0
|
1147 |
} |
|
David@0
|
1148 |
} |
|
David@0
|
1149 |
|
|
David@0
|
1150 |
/** |
|
David@0
|
1151 |
* @brief Returns the current status type of this account. |
|
David@0
|
1152 |
*/ |
|
David@0
|
1153 |
- (AIStatusTypeApplescript)scriptingStatusType |
|
David@0
|
1154 |
{ |
|
David@837
|
1155 |
return [self.statusState statusTypeApplescript]; |
|
David@0
|
1156 |
} |
|
David@0
|
1157 |
|
|
David@0
|
1158 |
/** |
|
David@0
|
1159 |
* @brief Sets the type of the current status. |
|
David@0
|
1160 |
* |
|
David@0
|
1161 |
* If the current status is a temporary status, then we simply set it. |
|
David@0
|
1162 |
* Otherwise, we create a temporary copy of it, and set that. |
|
David@0
|
1163 |
*/ |
|
David@0
|
1164 |
- (void)setScriptingStatusType:(AIStatusTypeApplescript)scriptingType |
|
David@0
|
1165 |
{ |
|
David@0
|
1166 |
AIStatusType type; |
|
David@0
|
1167 |
switch (scriptingType) { |
|
David@0
|
1168 |
case AIAvailableStatusTypeAS: |
|
David@0
|
1169 |
type = AIAvailableStatusType; |
|
David@0
|
1170 |
break; |
|
David@0
|
1171 |
case AIAwayStatusTypeAS: |
|
David@0
|
1172 |
type = AIAwayStatusType; |
|
David@0
|
1173 |
break; |
|
David@0
|
1174 |
case AIInvisibleStatusTypeAS: |
|
David@0
|
1175 |
type = AIInvisibleStatusType; |
|
David@0
|
1176 |
break; |
|
David@0
|
1177 |
case AIOfflineStatusTypeAS: |
|
David@0
|
1178 |
default: |
|
David@0
|
1179 |
type = AIOfflineStatusType; |
|
David@0
|
1180 |
break; |
|
David@0
|
1181 |
} |
|
David@0
|
1182 |
|
|
David@837
|
1183 |
AIStatus *currentStatus = self.statusState; |
|
David@0
|
1184 |
if ([currentStatus mutabilityType] == AILockedStatusState || [currentStatus mutabilityType] == AISecondaryLockedStatusState) { |
|
David@0
|
1185 |
switch (type) { |
|
David@0
|
1186 |
case AIAvailableStatusType: |
|
David@100
|
1187 |
currentStatus = [adium.statusController availableStatus]; |
|
David@0
|
1188 |
break; |
|
David@0
|
1189 |
case AIAwayStatusType: |
|
David@100
|
1190 |
currentStatus = [adium.statusController awayStatus]; |
|
David@0
|
1191 |
break; |
|
David@0
|
1192 |
case AIInvisibleStatusType: |
|
David@100
|
1193 |
currentStatus = [adium.statusController invisibleStatus]; |
|
David@0
|
1194 |
break; |
|
David@0
|
1195 |
case AIOfflineStatusType: |
|
David@100
|
1196 |
currentStatus = [adium.statusController offlineStatus]; |
|
David@0
|
1197 |
break; |
|
David@0
|
1198 |
} |
|
David@0
|
1199 |
} else { |
|
David@0
|
1200 |
if ([currentStatus mutabilityType] != AITemporaryEditableStatusState) { |
|
David@0
|
1201 |
currentStatus = [[currentStatus mutableCopy] autorelease]; |
|
David@0
|
1202 |
[currentStatus setMutabilityType:AITemporaryEditableStatusState]; |
|
David@0
|
1203 |
} |
|
David@0
|
1204 |
[currentStatus setStatusType:type]; |
|
David@100
|
1205 |
[currentStatus setStatusName:[adium.statusController defaultStatusNameForType:type]]; |
|
David@0
|
1206 |
} |
|
David@100
|
1207 |
[adium.statusController setActiveStatusState:currentStatus forAccount:self]; |
|
David@0
|
1208 |
} |
|
David@0
|
1209 |
|
|
David@0
|
1210 |
/** |
|
zacw@2340
|
1211 |
* @brief Returns a mutable status |
|
David@0
|
1212 |
* |
|
David@0
|
1213 |
* If the current status is built in, we create a temporary copy of the current status and set that. |
|
zacw@2340
|
1214 |
* |
|
zacw@2340
|
1215 |
* @return An AIStatus fit for being modified. |
|
David@0
|
1216 |
*/ |
|
hg@2356
|
1217 |
- (AIStatus *)modifiableCurrentStatus |
|
David@0
|
1218 |
{ |
|
David@837
|
1219 |
AIStatus *currentStatus = self.statusState; |
|
zacw@2340
|
1220 |
|
|
David@0
|
1221 |
if ([currentStatus mutabilityType] != AITemporaryEditableStatusState) { |
|
David@745
|
1222 |
currentStatus = [[currentStatus mutableCopy] autorelease]; |
|
David@0
|
1223 |
[currentStatus setMutabilityType:AITemporaryEditableStatusState]; |
|
David@0
|
1224 |
} |
|
zacw@2340
|
1225 |
|
|
David@0
|
1226 |
return currentStatus; |
|
David@0
|
1227 |
} |
|
David@0
|
1228 |
|
|
David@0
|
1229 |
/** |
|
David@0
|
1230 |
* @brief Sets the status message |
|
David@0
|
1231 |
* |
|
David@0
|
1232 |
* @param message, which may be an NSAttributedString or NSString |
|
David@0
|
1233 |
*/ |
|
David@0
|
1234 |
- (void)setScriptingStatusMessageWithAttributedString:(id)message |
|
David@0
|
1235 |
{ |
|
hg@2356
|
1236 |
AIStatus *currentStatus = [self modifiableCurrentStatus]; |
|
zacw@2340
|
1237 |
|
|
David@0
|
1238 |
if ([message isKindOfClass:[NSAttributedString class]]) |
|
David@0
|
1239 |
[currentStatus setStatusMessage:(NSAttributedString *)message]; |
|
David@0
|
1240 |
else |
|
David@0
|
1241 |
[currentStatus setStatusMessageString:message]; |
|
zacw@2340
|
1242 |
|
|
David@100
|
1243 |
[adium.statusController setActiveStatusState:currentStatus forAccount:self]; |
|
David@0
|
1244 |
} |
|
David@0
|
1245 |
|
|
David@0
|
1246 |
- (void)setScriptingStatusMessage:(NSString *)message |
|
David@0
|
1247 |
{ |
|
David@0
|
1248 |
[self setScriptingStatusMessageWithAttributedString:message]; |
|
David@0
|
1249 |
} |
|
David@0
|
1250 |
|
|
David@0
|
1251 |
/** |
|
David@0
|
1252 |
* @brief Sets the status message to a NSAttributedString extracted of a NSScriptCommand |
|
David@0
|
1253 |
*/ |
|
David@0
|
1254 |
- (void)setScriptingStatusMessageFromScriptCommand:(NSScriptCommand *)c |
|
David@0
|
1255 |
{ |
|
David@0
|
1256 |
//messageString could also be an NSTextStorage, due to WithMessage being able to also accept rich text |
|
David@0
|
1257 |
NSString *messageString = [[c evaluatedArguments] objectForKey:@"WithMessage"]; |
|
David@0
|
1258 |
if (messageString) |
|
David@0
|
1259 |
[self setScriptingStatusMessageWithAttributedString:messageString]; |
|
David@0
|
1260 |
} |
|
David@0
|
1261 |
|
|
David@0
|
1262 |
/** |
|
David@0
|
1263 |
* @brief Tells this account to be available, with an optional temporary status message. |
|
David@0
|
1264 |
*/ |
|
David@0
|
1265 |
- (void)scriptingGoAvailable:(NSScriptCommand *)c |
|
David@0
|
1266 |
{ |
|
David@100
|
1267 |
[adium.statusController setActiveStatusState:[adium.statusController availableStatus] forAccount:self]; |
|
David@0
|
1268 |
|
|
David@0
|
1269 |
[self setScriptingStatusMessageFromScriptCommand:c]; |
|
David@0
|
1270 |
} |
|
David@0
|
1271 |
|
|
David@0
|
1272 |
/** |
|
David@0
|
1273 |
* @brief Tells this account to be online, with an optional temporary status message. |
|
David@0
|
1274 |
*/ |
|
David@0
|
1275 |
- (void)scriptingGoOnline:(NSScriptCommand *)c |
|
David@0
|
1276 |
{ |
|
David@837
|
1277 |
if (self.statusType == AIInvisibleStatusType) { |
|
David@0
|
1278 |
[self scriptingGoAvailable:c]; |
|
David@0
|
1279 |
|
|
David@0
|
1280 |
} else { |
|
David@0
|
1281 |
[self setShouldBeOnline:YES]; |
|
David@0
|
1282 |
|
|
David@0
|
1283 |
[self setScriptingStatusMessageFromScriptCommand:c]; |
|
David@0
|
1284 |
} |
|
David@0
|
1285 |
} |
|
David@0
|
1286 |
|
|
David@0
|
1287 |
/** |
|
David@0
|
1288 |
* @brief Tells this account to be offline, with an optional temporary status message. |
|
David@0
|
1289 |
*/ |
|
David@0
|
1290 |
- (void)scriptingGoOffline:(NSScriptCommand *)c |
|
David@0
|
1291 |
{ |
|
David@0
|
1292 |
[self setShouldBeOnline:NO]; |
|
David@0
|
1293 |
|
|
David@0
|
1294 |
[self setScriptingStatusMessageFromScriptCommand:c]; |
|
David@0
|
1295 |
} |
|
David@0
|
1296 |
|
|
David@0
|
1297 |
/** |
|
David@0
|
1298 |
* @brief Tells this account to be away, with an optional temporary status message. |
|
David@0
|
1299 |
*/ |
|
David@0
|
1300 |
- (void)scriptingGoAway:(NSScriptCommand *)c |
|
David@0
|
1301 |
{ |
|
David@100
|
1302 |
[adium.statusController setActiveStatusState:[adium.statusController awayStatus] forAccount:self]; |
|
David@0
|
1303 |
|
|
David@0
|
1304 |
[self setScriptingStatusMessageFromScriptCommand:c]; |
|
David@0
|
1305 |
} |
|
David@0
|
1306 |
|
|
David@0
|
1307 |
/** |
|
David@0
|
1308 |
* @brief Tells this account to be invisible. |
|
David@0
|
1309 |
*/ |
|
David@0
|
1310 |
- (void)scriptingGoInvisible:(NSScriptCommand *)c |
|
David@0
|
1311 |
{ |
|
David@100
|
1312 |
[adium.statusController setActiveStatusState:[adium.statusController invisibleStatus] forAccount:self]; |
|
David@0
|
1313 |
|
|
David@0
|
1314 |
[self setScriptingStatusMessageFromScriptCommand:c]; |
|
David@0
|
1315 |
} |
|
David@0
|
1316 |
|
|
David@0
|
1317 |
/** |
|
David@0
|
1318 |
* @brief True, if a proxy is enabled |
|
David@0
|
1319 |
*/ |
|
David@0
|
1320 |
- (BOOL)proxyEnabled |
|
David@0
|
1321 |
{ |
|
David@0
|
1322 |
return [[self preferenceForKey:KEY_ACCOUNT_PROXY_ENABLED group:GROUP_ACCOUNT_STATUS] boolValue]; |
|
David@0
|
1323 |
} |
|
David@0
|
1324 |
/** |
|
David@0
|
1325 |
* @brief Sets whether or not the proxy is enabled for this account. |
|
David@0
|
1326 |
* This does not change the proxy setting immediately, a disconnect and reconnect is still required. |
|
David@0
|
1327 |
*/ |
|
David@0
|
1328 |
- (void)setProxyEnabled:(BOOL)proxyEnabled |
|
David@0
|
1329 |
{ |
|
David@0
|
1330 |
[self setPreference:[NSNumber numberWithBool:proxyEnabled] forKey:KEY_ACCOUNT_PROXY_ENABLED group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1331 |
} |
|
David@0
|
1332 |
/** |
|
David@0
|
1333 |
* @brief Gets the type of the proxy (one of the defined AdiumProxyTypes) |
|
David@0
|
1334 |
*/ |
|
David@0
|
1335 |
- (AdiumProxyType)proxyType |
|
David@0
|
1336 |
{ |
|
David@0
|
1337 |
return [[self preferenceForKey:KEY_ACCOUNT_PROXY_TYPE group:GROUP_ACCOUNT_STATUS] intValue]; |
|
David@0
|
1338 |
} |
|
David@0
|
1339 |
/** |
|
David@0
|
1340 |
* @brief Sets the proxy type (one of the defined AdiumProxyTypes) |
|
David@0
|
1341 |
*/ |
|
David@0
|
1342 |
- (void)setProxyType:(AdiumProxyType)type |
|
David@0
|
1343 |
{ |
|
David@0
|
1344 |
[self setPreference:[NSNumber numberWithInt:type] forKey:KEY_ACCOUNT_PROXY_TYPE group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1345 |
} |
|
David@0
|
1346 |
/** |
|
David@0
|
1347 |
* @brief Gets the proxy host as a string |
|
David@0
|
1348 |
*/ |
|
David@0
|
1349 |
- (NSString *)proxyHost |
|
David@0
|
1350 |
{ |
|
David@0
|
1351 |
return [self preferenceForKey:KEY_ACCOUNT_PROXY_HOST group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1352 |
} |
|
David@0
|
1353 |
/** |
|
David@0
|
1354 |
* @brief Sets the proxy host |
|
David@0
|
1355 |
*/ |
|
David@0
|
1356 |
- (void)setProxyHost:(NSString *)host |
|
David@0
|
1357 |
{ |
|
David@0
|
1358 |
[self setPreference:host forKey:KEY_ACCOUNT_PROXY_HOST group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1359 |
} |
|
David@0
|
1360 |
/** |
|
David@0
|
1361 |
* @brief Gets the proxy's port |
|
David@0
|
1362 |
*/ |
|
Matt@347
|
1363 |
- (NSNumber *)proxyPort |
|
David@0
|
1364 |
{ |
|
Matt@347
|
1365 |
NSString *proxyPort = [self preferenceForKey:KEY_ACCOUNT_PROXY_PORT group:GROUP_ACCOUNT_STATUS]; |
|
Matt@347
|
1366 |
return [NSNumber numberWithUnsignedShort:[proxyPort integerValue]]; |
|
David@0
|
1367 |
} |
|
David@0
|
1368 |
/** |
|
David@0
|
1369 |
* @brief Set the port to which we should connect when connecting to the proxy |
|
David@0
|
1370 |
*/ |
|
Matt@347
|
1371 |
- (void)setProxyPort:(NSNumber *)port |
|
David@0
|
1372 |
{ |
|
Matt@347
|
1373 |
[self setPreference:[port stringValue] forKey:KEY_ACCOUNT_PROXY_PORT group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1374 |
} |
|
David@0
|
1375 |
/** |
|
David@0
|
1376 |
* @brief Gets the username we use when connecting to the proxy |
|
David@0
|
1377 |
*/ |
|
David@0
|
1378 |
- (NSString *)proxyUsername |
|
David@0
|
1379 |
{ |
|
David@0
|
1380 |
return [self preferenceForKey:KEY_ACCOUNT_PROXY_USERNAME group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1381 |
} |
|
David@0
|
1382 |
/** |
|
David@0
|
1383 |
* @brief Sets the username we should use when connecting to the proxy |
|
David@0
|
1384 |
*/ |
|
David@0
|
1385 |
- (void)setProxyUsername:(NSString *)username |
|
David@0
|
1386 |
{ |
|
David@0
|
1387 |
[self setPreference:username forKey:KEY_ACCOUNT_PROXY_USERNAME group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1388 |
} |
|
David@0
|
1389 |
/** |
|
David@0
|
1390 |
* @brief Gets the password we use when connecting to the proxy |
|
David@0
|
1391 |
*/ |
|
David@0
|
1392 |
- (NSString *)proxyPassword |
|
David@0
|
1393 |
{ |
|
David@0
|
1394 |
return [self preferenceForKey:KEY_ACCOUNT_PROXY_PASSWORD group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1395 |
} |
|
David@0
|
1396 |
/** |
|
David@0
|
1397 |
* @brief Sets the password we should use when connecting to the proxy |
|
David@0
|
1398 |
*/ |
|
David@0
|
1399 |
- (void)setProxyPassword:(NSString *)proxyPassword |
|
David@0
|
1400 |
{ |
|
David@0
|
1401 |
[self setPreference:proxyPassword forKey:KEY_ACCOUNT_PROXY_PASSWORD group:GROUP_ACCOUNT_STATUS]; |
|
David@0
|
1402 |
} |
|
David@0
|
1403 |
|
|
David@0
|
1404 |
/** |
|
David@0
|
1405 |
* @brief Gets the proxy type for applescript (using the nice four-letter codes defined by AdiumProxyTypeApplescript) |
|
David@0
|
1406 |
*/ |
|
David@0
|
1407 |
- (AdiumProxyTypeApplescript)scriptingProxyType |
|
David@0
|
1408 |
{ |
|
David@0
|
1409 |
return [self applescriptProxyType:[self proxyType]]; |
|
David@0
|
1410 |
} |
|
David@0
|
1411 |
/** |
|
David@0
|
1412 |
* @brief Sets the proxy type to one of the defined AdiumProxyTypeApplescripts |
|
David@0
|
1413 |
*/ |
|
David@0
|
1414 |
- (void)setScriptingProxyType:(AdiumProxyTypeApplescript)type |
|
David@0
|
1415 |
{ |
|
David@0
|
1416 |
[self setProxyType:[self proxyTypeFromApplescript:type]]; |
|
David@0
|
1417 |
} |
|
David@0
|
1418 |
|
|
David@0
|
1419 |
@end |
|
David@0
|
1420 |
|
|
David@0
|
1421 |
@implementation AIAccount(AppleScriptPRIVATE) |
|
David@0
|
1422 |
- (AdiumProxyType)proxyTypeFromApplescript:(AdiumProxyTypeApplescript)proxyTypeAS |
|
David@0
|
1423 |
{ |
|
David@0
|
1424 |
switch(proxyTypeAS) |
|
David@0
|
1425 |
{ |
|
David@0
|
1426 |
case Adium_Proxy_HTTP_AS: |
|
David@0
|
1427 |
return Adium_Proxy_HTTP; |
|
David@0
|
1428 |
case Adium_Proxy_SOCKS4_AS: |
|
David@0
|
1429 |
return Adium_Proxy_SOCKS4; |
|
David@0
|
1430 |
case Adium_Proxy_SOCKS5_AS: |
|
David@0
|
1431 |
return Adium_Proxy_SOCKS5; |
|
David@0
|
1432 |
case Adium_Proxy_Default_HTTP_AS: |
|
David@0
|
1433 |
return Adium_Proxy_Default_HTTP; |
|
David@0
|
1434 |
case Adium_Proxy_Default_SOCKS4_AS: |
|
David@0
|
1435 |
return Adium_Proxy_Default_SOCKS4; |
|
David@0
|
1436 |
case Adium_Proxy_Default_SOCKS5_AS: |
|
David@0
|
1437 |
return Adium_Proxy_Default_SOCKS5; |
|
David@0
|
1438 |
default: |
|
David@0
|
1439 |
return Adium_Proxy_None; |
|
David@0
|
1440 |
} |
|
David@0
|
1441 |
} |
|
David@0
|
1442 |
- (AdiumProxyTypeApplescript)applescriptProxyType:(AdiumProxyType)proxyType |
|
David@0
|
1443 |
{ |
|
David@0
|
1444 |
switch(proxyType) |
|
David@0
|
1445 |
{ |
|
David@0
|
1446 |
case Adium_Proxy_HTTP: |
|
David@0
|
1447 |
return Adium_Proxy_HTTP_AS; |
|
David@0
|
1448 |
case Adium_Proxy_SOCKS4: |
|
David@0
|
1449 |
return Adium_Proxy_SOCKS4_AS; |
|
David@0
|
1450 |
case Adium_Proxy_SOCKS5: |
|
David@0
|
1451 |
return Adium_Proxy_SOCKS5_AS; |
|
David@0
|
1452 |
case Adium_Proxy_Default_HTTP: |
|
David@0
|
1453 |
return Adium_Proxy_Default_HTTP_AS; |
|
David@0
|
1454 |
case Adium_Proxy_Default_SOCKS4: |
|
David@0
|
1455 |
return Adium_Proxy_Default_SOCKS4_AS; |
|
David@0
|
1456 |
case Adium_Proxy_Default_SOCKS5: |
|
David@0
|
1457 |
return Adium_Proxy_Default_SOCKS5_AS; |
|
David@0
|
1458 |
default: |
|
David@0
|
1459 |
return Adium_Proxy_None_AS; |
|
David@0
|
1460 |
} |
|
David@0
|
1461 |
} |
|
David@0
|
1462 |
|
|
David@0
|
1463 |
@end |