5 // Created by Matt Meissner on 10/30/09.
6 // Modified by Michael Lamb on 2/27/13
7 // Copyright 2013 Michael Lamb/Harris Kauffman. All rights reserved.
10 #import <AISharedAdium.h>
12 #import <Adium/AIStatus.h>
13 #import <Adium/AIStatusControllerProtocol.h>
14 #import <ESDebugAILog.h>
16 #import "ESPurpleSIPEAccount.h"
17 #import "ESSIPEService.h"
19 #include "sipe-core.h"
20 #include "sipe-backend.h"
21 #include "purple-private.h"
23 @class AICoreComponentLoader;
25 @implementation ESPurpleSIPEAccount
31 sipe_to_adium_status =
32 [[NSDictionary alloc] initWithObjectsAndKeys:
33 STATUS_NAME_AVAILABLE, @"available", //SIPE_ACTIVITY_AVAILABLE
34 STATUS_NAME_AVAILABLE, @"online", //SIPE_ACTIVITY_ONLINE
35 STATUS_NAME_AWAY, @"idle", //SIPE_ACTIVITY_INACTIVE
36 STATUS_NAME_BUSY, @"busy", //SIPE_ACTIVITY_BUSY
37 STATUS_NAME_BUSY, @"busyidle", //SIPE_ACTIVITY_BUSYIDLE
38 STATUS_NAME_DND, @"do-not-disturb", //SIPE_ACTIVITY_DND
39 STATUS_NAME_BRB, @"be-right-back", //SIPE_ACTIVITY_BRB
40 STATUS_NAME_AWAY, @"away", //SIPE_ACTIVITY_AWAY
41 STATUS_NAME_LUNCH, @"out-to-lunch", //SIPE_ACTIVITY_LUNCH
42 STATUS_NAME_INVISIBLE, @"invisible", //SIPE_ACTIVITY_INVISIBLE
43 STATUS_NAME_OFFLINE, @"offline", //SIPE_ACTIVITY_OFFLINE
44 STATUS_NAME_PHONE, @"on-the-phone", //SIPE_ACTIVITY_ON_PHONE
45 STATUS_NAME_NOT_AT_DESK, @"in-a-conference", //SIPE_ACTIVITY_IN_CONF
46 STATUS_NAME_NOT_AT_DESK, @"in-a-meeting", //SIPE_ACTIVITY_IN_MEETING
47 STATUS_NAME_NOT_IN_OFFICE, @"out-of-office", //SIPE_ACTIVITY_OOF
48 STATUS_NAME_AWAY_FRIENDS_ONLY, @"urgent-interruptions-only", //SIPE_ACTIVITY_URGENT_ONLY
52 adium_to_sipe_status =
53 [[NSDictionary alloc] initWithObjectsAndKeys:
54 @"available", STATUS_NAME_AVAILABLE, //SIPE_ACTIVITY_AVAILABLE
55 @"busy", STATUS_NAME_BUSY, //SIPE_ACTIVITY_BUSY
56 @"do-not-disturb", STATUS_NAME_DND, //SIPE_ACTIVITY_DND
57 @"be-right-back", STATUS_NAME_BRB, //SIPE_ACTIVITY_BRB
58 @"away", STATUS_NAME_AWAY, //SIPE_ACTIVITY_AWAY
59 @"out-to-lunch", STATUS_NAME_LUNCH, //SIPE_ACTIVITY_LUNCH
60 @"invisible", STATUS_NAME_INVISIBLE, //SIPE_ACTIVITY_INVISIBLE
61 @"offline", STATUS_NAME_OFFLINE, //SIPE_ACTIVITY_OFFLINE
62 @"on-the-phone", STATUS_NAME_PHONE, //SIPE_ACTIVITY_ON_PHONE
63 @"in-a-meeting", STATUS_NAME_NOT_AT_DESK, //SIPE_ACTIVITY_IN_MEETING
64 @"out-of-office", STATUS_NAME_NOT_IN_OFFICE, //SIPE_ACTIVITY_OOF
65 @"urgent-interruptions-only", STATUS_NAME_AWAY_FRIENDS_ONLY, //SIPE_ACTIVITY_URGENT_ONLY
72 [adium_to_sipe_status release];
73 [sipe_to_adium_status release];
77 - (const char*)protocolPlugin
82 - (const char *)purpleAccountName
84 NSString *completeUserName = [NSString stringWithUTF8String:[super purpleAccountName]];
85 NSString *windowsLogin =[self preferenceForKey:KEY_SIPE_WINDOWS_LOGIN group:GROUP_ACCOUNT_STATUS];
87 if ( ![windowsLogin isEqualToString:@""] ) {
88 completeUserName = [NSString stringWithFormat:@"%@,%@", completeUserName, windowsLogin];
91 return [completeUserName UTF8String];
94 #pragma mark Account Configuration
95 - (void)configurePurpleAccount
97 // Account preferences
98 AILog(@"(ESPurpleSIPEAccount) Configuring account: %s\n", self.purpleAccountName);
100 NSArray *myArray = [NSArray arrayWithObjects:@"auto", @"tls", @"tcp", nil];
102 NSDictionary *keys_to_account =
103 [NSDictionary dictionaryWithObjectsAndKeys:
104 @"server", KEY_SIPE_CONNECT_HOST,
105 @"password", KEY_SIPE_PASSWORD,
106 @"transport", KEY_SIPE_CONNECTION_TYPE,
107 @"email", KEY_SIPE_EMAIL,
108 @"email_login", KEY_SIPE_EMAIL_LOGIN,
109 @"email_url", KEY_SIPE_EMAIL_URL,
110 @"email_password", KEY_SIPE_EMAIL_PASSWORD,
111 @"groupchat_user", KEY_SIPE_GROUP_CHAT_PROXY,
112 @"useragent", KEY_SIPE_USER_AGENT,
113 @"sso", KEY_SIPE_SINGLE_SIGN_ON,
114 @"dont-publish", KEY_SIPE_DONT_PUBLISH,
115 @"authentication", KEY_SIPE_AUTH_SCHEME,
116 @"ssl_cdsa_beast_tls_workaround", KEY_SIPE_BEAST_DISABLE,
120 for (NSString* key in keys_to_account) {
121 NSString *prpl_key = [keys_to_account objectForKey:key];
122 id value = [self preferenceForKey:key group:GROUP_ACCOUNT_STATUS];
124 if ([value isKindOfClass:[NSString class]]) {
125 if ([key isEqualToString:KEY_SIPE_CONNECT_HOST]) {
126 if ([value isEqualToString:@""]) {
127 // An empty sipe_connect_host means we're autodetecting the server
128 // So we set this to our own hostname, so that the reachability test has a *network* address (i.e. non-loopback) to check connectivity against.
129 // SIPE Bug #262: this does not work, because the name is not a valid DNS name
130 // [self setPreference:[[NSHost currentHost] localizedName] forKey:KEY_CONNECT_HOST group:GROUP_ACCOUNT_STATUS];
131 // Replacing localizedName with name/names does also no work, because the value changes depending on network connectivity
132 // [self setPreference:[[NSHost currentHost] name] forKey:KEY_CONNECT_HOST group:GROUP_ACCOUNT_STATUS];
133 // hard-code to "localhost" instead, which should always be valid
134 [self setPreference:@"localhost" forKey:KEY_CONNECT_HOST group:GROUP_ACCOUNT_STATUS];
136 // If the user entered server:port only give the server portion to adium
137 // otherwise the DNS lookup will fail the reachability test
138 NSArray *server = [value componentsSeparatedByString:@":"];
139 [self setPreference:[server objectAtIndex:0] forKey:KEY_CONNECT_HOST group:GROUP_ACCOUNT_STATUS];
143 purple_account_set_string(account, [prpl_key UTF8String], [value UTF8String]);
144 } else if ([value isKindOfClass:[NSNumber class]]) {
145 if ([key isEqualToString:KEY_SIPE_CONNECTION_TYPE]) {
146 NSString *tmp = [myArray objectAtIndex:(NSUInteger)value];
147 purple_account_set_string(account, [prpl_key UTF8String], [tmp UTF8String]);
149 purple_account_set_bool(account, [prpl_key UTF8String], [value boolValue]);
152 AILog(@"(ESPurpleSIPEAccount) Unknown class %@ for key %@", [value class], key);
156 // Adium doesn't honor our "optional" password on account creation and will prompt if the password field is left blank, so we must force it to think there is one, but only if there isn't already a password saved
157 if ( [[self preferenceForKey:KEY_SIPE_SINGLE_SIGN_ON group:GROUP_ACCOUNT_STATUS] boolValue] &&
158 [[self preferenceForKey:KEY_SIPE_PASSWORD group:GROUP_ACCOUNT_STATUS] isEqualToString:@""] )
160 [self setPasswordTemporarily:@"placeholder"];
164 #pragma mark File transfer
166 - (BOOL)canSendFolders
171 - (void)beginSendOfFileTransfer:(ESFileTransfer *)fileTransfer
173 [super _beginSendOfFileTransfer:fileTransfer];
176 - (void)acceptFileTransferRequest:(ESFileTransfer *)fileTransfer
178 [super acceptFileTransferRequest:fileTransfer];
181 - (void)rejectFileReceiveRequest:(ESFileTransfer *)fileTransfer
183 [super rejectFileReceiveRequest:fileTransfer];
186 - (void)cancelFileTransfer:(ESFileTransfer *)fileTransfer
188 [super cancelFileTransfer:fileTransfer];
191 #pragma mark Status Messages
193 * @brief Status name to use for a Purple buddy
195 - (NSString *)statusNameForPurpleBuddy:(PurpleBuddy *)buddy
197 NSString *statusName = [super statusNameForPurpleBuddy:buddy];
198 PurplePresence *presence = purple_buddy_get_presence(buddy);
199 PurpleStatus *status = purple_presence_get_active_status(presence);
200 NSString *purpleStatusID = [NSString stringWithUTF8String:purple_status_get_id(status)];
202 if (!purpleStatusID) return nil;
204 if (sipe_to_adium_status[purpleStatusID])
205 statusName = sipe_to_adium_status[purpleStatusID];
207 AILog(@"(ESPurpleSIPEAccount) Unknown purpleStatusID in statusNameForPurpleBuddy: %@", purpleStatusID);
208 statusName = STATUS_NAME_OFFLINE;
215 * @brief Maps purple status IDs to Adium statuses
217 - (const char *)purpleStatusIDForStatus:(AIStatus *)statusState arguments:(NSMutableDictionary *)arguments
219 const gchar *statusID;
220 NSString *statusName = statusState.statusName;
221 NSString *statusMessageString = [statusState statusMessageString];
223 if (!statusMessageString) statusMessageString = @"";
225 if ( adium_to_sipe_status[statusName] )
226 statusID = [adium_to_sipe_status[statusName] UTF8String];
228 AILog(@"(ESPurpleSIPEAccount): Unknown statusName in purpleStatusIDForStatus: %@", statusName);
229 statusID = [super purpleStatusIDForStatus:statusState arguments:arguments];