Add -[AIService pathForDefaultServiceIconOfType:], and use it for replacing %serviceIconImg% in headers. Fixes #12697.
2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
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.
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.
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.
17 #import <Adium/AIAccount.h>
18 #import <Adium/AIService.h>
19 #import <Adium/AIAccountControllerProtocol.h>
20 #import <Adium/AIAccountViewController.h>
21 #import "AICreateCommand.h"
25 * @brief An IM Service
27 * This abstract class represents a service that Adium supports. Subclass this for every service.
29 @implementation AIService
31 + (void)registerService
33 [[[self alloc] init] autorelease];
41 if ((self = [super init])) {
42 //Register this service with Adium
43 [adium.accountController registerService:self];
45 [self registerStatuses];
52 //Account Creation -----------------------------------------------------------------------------------------------------
53 #pragma mark Account Creation
55 * @brief Create a new account for this service
57 * Creates a new account of this service. Accounts are identified by a unique number. We can't use service or
58 * UID, since both those values may change.
59 * @param inUID A unique identifier for the account being created.
60 * @param inInternalObjectID A unique internalObjectID for the account being created.
61 * @return An AIAccount object for this service.
63 - (id)accountWithUID:(NSString *)inUID internalObjectID:(NSString *)inInternalObjectID
65 return [[[[self accountClass] alloc] initWithUID:[self normalizeUID:inUID removeIgnoredCharacters:YES]
66 internalObjectID:inInternalObjectID
67 service:self] autorelease];
71 * @brief Account class associated with this service
73 * Subclass to return the account class associated with this service ([AISomethingAccount class]).
74 * @return The account class associated with this service.
82 * @brief Account view controller for this service
84 * Subclass to return an account view controller which provides the necessary controls for configuring an account
86 * @return An AIAccountViewController or subclass for this service.
88 - (AIAccountViewController *)accountViewController
90 return [AIAccountViewController accountViewController];
94 * @brief Join chat view controller for this service
96 * Subclass to return a join chat view controller which provides the necessary controls for joining a chat on this
98 * @return An DCJoinChatViewController or subclass for this service.
100 - (DCJoinChatViewController *)joinChatView
106 //Service Description --------------------------------------------------------------------------------------------------
107 #pragma mark Service Description
109 * @brief Unique ID for this class
111 * Subclass to return a unique string ID which identifies this class. No two classes should have the same uniqueID.
112 * This value is used to determine which protocol code to use for the user's accounts.
113 * Examples: "libgaim-aim", "aim-toc2", "imservices-aim-.mac"
114 * @return NSString unique ID
116 - (NSString *)serviceCodeUniqueID{
121 * @brief Service ID for this service
123 * Subclass to return a string which identifies this service. If multiple service classes are supporting the same
124 * service they should have the same serviceID. Not for user-display.
125 * Examples: "AIM", "MSN", "Jabber", "ICQ", "Mac"
126 * @return NSString service ID
128 - (NSString *)serviceID{
133 * @brief Service class for this service
135 * Some separate services can communicate with eachother. These services, while they have separate serviceID's,
136 * are all part of a common service class. For instance, AIM, ICQ, and .Mac are all part of the "AIM" service class.
137 * For many services, the serviceClass will be identical to the serviceID. Not for user-display.
138 * Service classes may change, do not use them for any permenant storage (logs, preferences, etc).
139 * Examples: "AIM-compatible", "Jabber", "MSN"
140 * @return NSString service class
142 - (NSString *)serviceClass{
147 * @brief Human readable short description
149 * Human readable, short description of this service
150 * This value is used in tooltips and the message window.
151 * Examples: "Jabber", "MSN", "AIM", ".Mac"
152 * @return NSString short description
154 - (NSString *)shortDescription{
159 * @brief Human readable long description
161 * Human readable, long description of this service
162 * If there are multiple classes available for the same service, this description should briefly show the difference
163 * between the implementations. This value is used in the account preferences service menu.
164 * Examples: "Jabber", "MSN", "AOL Instant Messenger", ".Mac"
165 * @return NSString long description
167 - (NSString *)longDescription{
172 * @brief Label for user name (general)
174 * String to use for describing the UID/username of this service. This value varies by service, but should be something
175 * along the lines of "User name", "Account name", "Screen name", "Member name", etc.
177 * This will be used for the account preferences to indicate the field for the account's user name. By default, contactUserNameLabel
178 * will return this value, as well.
180 * @return NSString label for username
182 - (NSString *)userNameLabel
184 return AILocalizedStringFromTableInBundle(@"User Name", nil, [NSBundle bundleForClass:[AIService class]], nil);
188 * @brief Label for user name
190 * String to use for describing the UID/username of contacts for this service. This value varies by service, but should be something
191 * along the lines of "User name", "Account name", "Screen name", "Member name", etc.
193 * By default, this returns -[self userNameLabel]; only override this method if contacts are named differently than own-account usernames.
195 * @return NSString label for username
197 - (NSString *)contactUserNameLabel
199 return [self userNameLabel];
203 * @brief Placeholder string for the UID field
205 - (NSString *)UIDPlaceholder
211 * @brief Service importance
213 * Importance grouping of this service. Used to make service listings and menus more organized by placing more important
214 * services at the top of lists or displaying them with more visibility.
215 * @return AIServiceImportance importance of this service
217 - (AIServiceImportance)serviceImportance
219 return AIServiceUnsupported;
223 * @brief Default icon
225 * Service Icon packs should always include images for all the built-in Adium services. This method allows external
226 * service plugins to specify an image which will be used when the service icon pack does not specify one. It will
227 * also be useful if new services are added to Adium itself after a significant number of Service Icon packs exist
228 * which do not yet have an image for this service. If the active Service Icon pack provides an image for this service,
229 * this method will not be called.
231 * The service should _not_ cache this icon internally; multiple calls should return unique NSImage objects.
233 * @param iconType The AIServiceIconType of the icon to return. This specifies the desired size of the icon.
234 * @return NSImage to use for this service by default
236 - (NSImage *)defaultServiceIconOfType:(AIServiceIconType)iconType
242 * @brief Path for default icon
244 * For use in message views, this is the path to a default icon as described above.
246 * @param iconType The AIServiceIconType of the icon to return.
247 * @return The path to the image, otherwise nil.
249 - (NSString *)pathForDefaultServiceIconOfType:(AIServiceIconType)iconType
254 //Service Properties ---------------------------------------------------------------------------------------------------
255 #pragma mark Service Properties
257 * @brief Allowed characters
259 * Characters allowed in user names on this service. The user will not be allowed to type any characters not in this
260 * set as a contact or account name.
261 * @return NSCharacterSet of allowed characters
263 - (NSCharacterSet *)allowedCharacters
269 * @brief Allowed characters for our account name
271 * Offers further distinction of allowed characters, for situations where certain characters are allowed
272 * for our account name only, or characters which are allowed in user names are forbidden in our own account name.
273 * If this distinction is not made, do not subclass this methods and instead subclass allowedCharacters.
274 * @return NSCharacterSet of allowed characters
276 - (NSCharacterSet *)allowedCharactersForAccountName
278 return ([self allowedCharacters]);
282 * @brief Allowed characters for UIDs
284 * Offers further distinction of allowed characters, for situations where certain characters are allowed
285 * for our account name only, or characters which are allowed in user names are forbidden in our own account name.
286 * If this distinction is not made, do not subclass this methods and instead subclass allowedCharacters.
287 * @return NSCharacterSet of allowed characters
289 - (NSCharacterSet *)allowedCharactersForUIDs
291 return [self allowedCharacters];
295 * @brief Ignored characters
297 * Ignored characters for user names on this service. Ignored characters are stripped from account and contact names
298 * before they are used, but the user is free to type them and they may be used by the service code. For instance,
299 * spaces are allowed in AIM usernames, but "ad am" is treated as equal to "adam" because space is an ignored character.
300 * @return NSCharacterSet of ignored characters
302 - (NSCharacterSet *)ignoredCharacters
304 return [NSCharacterSet characterSetWithCharactersInString:@""];
308 * @brief Allowed name length
310 * Max allowed length of user names of this service. Account and contact names longer than this will not be allowed.
311 * @return Max name length
313 - (NSUInteger)allowedLength
315 return NSUIntegerMax;
319 * @brief Allowed account name length
321 * Offers further distinction of allowed name length, for situations where our account name has a different
322 * length restriction than the names of our contacts. If this distinction is not made, do not subclass these methods
323 * and instead subclass allowedLength.
324 * @return Max name length
326 - (int)allowedLengthForAccountName
328 return [self allowedLength];
332 * @brief Allowed UID length
334 * Offers further distinction of allowed name length, for situations where our account name has a different
335 * length restriction than the names of our contacts. If this distinction is not made, do not subclass these methods
336 * and instead subclass allowedLength.
337 * @return Max name length
339 - (int)allowedLengthForUIDs
341 return [self allowedLength];
345 * @brief Case sensitivity of names
347 * Determines if usernames such as "Adam" and "adam" are unique.
348 * @return Case sensitivity
350 - (BOOL)caseSensitive
356 * @brief Can create group chats?
358 * Does this service support group chats (Also known as multi-user chats, chat rooms, conferences, etc)? Services
359 * which do not support group chats are automatically excluded from the group chat interface elements.
360 * @return Can create group chats
362 - (BOOL)canCreateGroupChats
368 * @brief Can register accounts?
370 * Does this service support registering new accounts from within Adium? This is here for Jabber.
371 * @return Can register accounts
373 - (BOOL)canRegisterNewAccounts
379 * @brief Supports proxy settings?
381 * Does this service support connecting via a proxy?
382 * @return Supports proxy settings
384 - (BOOL)supportsProxySettings
389 * @brief Supports password
391 * Subclasses should return NO if this service does not use passwords at all for connectivity.
392 * If NO, all fields related to passwords will be hidden for this service and the user will never be prompted to
395 - (BOOL)supportsPassword
401 * @brief Requires Password
403 * Subclasses should return NO if this service does not require a password. Returning NO from this method will use the password if
404 * entered but allow a conection to be initiated with no password without prompting for one.
405 * If YES, Adium will insist upon a password being entered before a connection can begin.
407 * By default, the service requires a password if it is supported. See -[AIService supportsPassword].
409 - (BOOL)requiresPassword
411 return [self supportsPassword];
415 * @brief Register statuses
417 * Called automatically. Services should register any supported status with the statusController.
419 - (void)registerStatuses{};
422 * @brief Default user name
424 * The default user name for a service is set for all new accounts. As it's not
425 * possible to guess the user name for most service types (AIM, MSN, etc.), the
426 * base class returns @"".
428 * @return The default user name for this service, or @"" for no default
430 - (NSString *)defaultUserName
436 * @brief Is this a social networking service like Twitter or Facebook?
438 * If YES, accounts on this service treat status very differently than non-social-networking accounts.
439 * For example, global status messages dont apply to social networking services, and their status is handled uniquely.
441 - (BOOL)isSocialNetworkingService
447 * @brief Is this service hidden?
449 * If YES, it will not appear in service dropdowns.
450 * This is useful for allowing a legacy service to stick around seamlessly.
457 //Utilities ------------------------------------------------------------------------------------------------------------
458 #pragma mark Utilities
460 * @brief Normalize a UID
462 * Normalizes a UID. All invalid characters and ignored characters are removed.
463 * UID's are ONLY filtered when creating contacts, and when renaming contacts.
464 * - When changing ownership of a contact, a filter is not necessary, since all the accounts should have the same service
465 * types and requirements.
466 * - When account code retrieves contacts from the contact list, filtering is NOT done. It is up to the account to
467 * ensure it passes UIDs in the proper format for its service type.
468 * - Filter UIDs only when the user has entered or mucked with them in some way... UID's TO and FROM account code
469 * SHOULD ALWAYS BE VALID.
470 * @return NSString filtered UID
472 - (NSString *)normalizeUID:(NSString *)inUID removeIgnoredCharacters:(BOOL)removeIgnored
474 NSString *workingString = ([self caseSensitive] ? inUID : [inUID lowercaseString]);
475 NSCharacterSet *allowedCharacters = [self allowedCharactersForUIDs];
476 NSCharacterSet *ignoredCharacters = [self ignoredCharacters];
478 //Prepare a little buffer for our filtered UID
479 unsigned destLength = 0;
480 unsigned workingStringLength = [workingString length];
481 unichar *dest = malloc(workingStringLength * sizeof(unichar));
485 for (pos = 0; pos < workingStringLength; pos++) {
486 unichar c = [workingString characterAtIndex:pos];
488 if ([allowedCharacters characterIsMember:c] && (!removeIgnored || ![ignoredCharacters characterIsMember:c])) {
489 dest[destLength] = (removeIgnored ? c : [inUID characterAtIndex:pos]);
494 //Turn it back into a string and return
495 NSString *filteredString = [NSString stringWithCharacters:dest length:destLength];
498 return filteredString;
502 * @brief Normalize a chat name
504 * The default implementation only lowercases the name.
506 - (NSString *)normalizeChatName:(NSString *)inChatName
508 return [inChatName lowercaseString];
512 * @brief Compare this service to another, ranking by long description
514 - (NSComparisonResult)compareLongDescription:(AIService *)inService
516 return [[self longDescription] compare:[inService longDescription]];
519 - (NSString *)description
521 return [NSString stringWithFormat:@"<%@: serviceCodeUniqueID = %@; serviceID = %@; serviceClass = %@; longDescription = %@>",
522 NSStringFromClass([self class]), self.serviceCodeUniqueID, self.serviceID, self.serviceClass, self.longDescription];
526 #pragma mark AppleScript
529 * @brief Returns a list of all accounts that use this service.
531 - (NSArray *)accounts
533 NSMutableArray *accountsForThisService = [[[NSMutableArray alloc] init] autorelease];
534 for (AIAccount *account in adium.accountController.accounts) {
535 if (account.service == self)
536 [accountsForThisService addObject:account];
538 return accountsForThisService;
542 * @brief This class is specified using the 'services' key of AIApplication
544 - (NSScriptObjectSpecifier *)objectSpecifier
546 NSScriptClassDescription *containerClassDesc = (NSScriptClassDescription *)[NSScriptClassDescription classDescriptionForClass:[NSApp class]];
547 return [[[NSNameSpecifier alloc]
548 initWithContainerClassDescription:containerClassDesc
549 containerSpecifier:nil key:@"services"
550 name:self.serviceID] autorelease];
555 return [[AIServiceIcons serviceIconForService:self type:AIServiceIconLarge direction:AIIconNormal] TIFFRepresentation];