forked from KOed/welly
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathWLConnection.m
286 lines (250 loc) · 7.31 KB
/
WLConnection.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
//
// WLConnection.h
// Welly
//
// YLConnection.mm
// MacBlueTelnet
//
// Created by Lan Yung-Luen on 12/7/07.
// Copyright 2007 yllan.org. All rights reserved.
//
#import "WLConnection.h"
#import "WLTerminal.h"
#import "WLTerminalFeeder.h"
#import "WLEncoder.h"
#import "WLGlobalConfig.h"
#import "WLMessageDelegate.h"
#import "WLSite.h"
#import "WLPTY.h"
@interface WLConnection ()
- (void)login;
@end
@implementation WLConnection
@synthesize site = _site;
@synthesize terminal = _terminal;
@synthesize terminalFeeder = _feeder;
@synthesize protocol = _protocol;
@synthesize isConnected = _connected;
@synthesize icon = _icon;
@synthesize isProcessing = _isProcessing;
@synthesize objectCount = _objectCount;
@synthesize lastTouchDate = _lastTouchDate;
@synthesize messageCount = _messageCount;
@synthesize messageDelegate = _messageDelegate;
@synthesize tabViewItemController = _tabViewItemController;
- (id)initWithSite:(WLSite *)site {
if (self == [self init]) {
// Create a feeder to parse content from the connection
_feeder = [[WLTerminalFeeder alloc] initWithConnection:self];
[self setSite:site];
if (![site isDummy]) {
// WLPTY as the default protocol (a proxy)
WLPTY *protocol = [[WLPTY new] autorelease];
[self setProtocol:protocol];
[protocol setDelegate:self];
[protocol setProxyType:[site proxyType]];
[protocol setProxyAddress:[site proxyAddress]];
[protocol connect:[site address]];
}
// Setup the message delegate
_messageDelegate = [[WLMessageDelegate alloc] init];
[_messageDelegate setConnection: self];
}
return self;
}
- (void)dealloc {
[_lastTouchDate release];
[_icon release];
[_terminal release];
[_feeder release];
[_protocol release];
[_messageDelegate release];
[_site release];
[super dealloc];
}
#pragma mark -
#pragma mark Accessor
- (void)setTerminal:(WLTerminal *)value {
if (_terminal != value) {
[_terminal release];
_terminal = [value retain];
[_terminal setConnection:self];
[_feeder setTerminal:_terminal];
}
}
- (void)setConnected:(BOOL)value {
_connected = value;
if (_connected)
[self setIcon:[NSImage imageNamed:@"online.pdf"]];
else {
[self resetMessageCount];
[self setIcon:[NSImage imageNamed:@"offline.pdf"]];
}
}
- (void)setLastTouchDate {
[_lastTouchDate release];
_lastTouchDate = [[NSDate date] retain];
}
#pragma mark -
#pragma mark WLProtocol delegate methods
- (void)protocolWillConnect:(id)protocol {
[self setIsProcessing:YES];
[self setConnected:NO];
[self setIcon:[NSImage imageNamed:@"waiting.pdf"]];
}
- (void)protocolDidConnect:(id)protocol {
[self setIsProcessing:NO];
[self setConnected:YES];
[NSThread detachNewThreadSelector:@selector(login) toTarget:self withObject:nil];
//[self login];
}
- (void)protocolDidRecv:(id)protocol
data:(NSData*)data {
[_feeder feedData:data connection:self];
}
- (void)protocolWillSend:(id)protocol
data:(NSData*)data {
[self setLastTouchDate];
}
- (void)protocolDidClose:(id)protocol {
[self setIsProcessing:NO];
[self setConnected:NO];
[_feeder clearAll];
[_terminal clearAll];
}
#pragma mark -
#pragma mark Network
- (void)close {
[_protocol close];
}
- (void)reconnect {
[_protocol close];
[_protocol connect:[_site address]];
[self resetMessageCount];
}
- (void)sendMessage:(NSData *)msg {
[_protocol send:msg];
}
- (void)sendBytes:(const void *)buf
length:(NSInteger)length {
NSData *data = [[NSData alloc] initWithBytes:buf length:length];
[self sendMessage:data];
[data release];
}
- (void)sendText:(NSString *)s {
[self sendText:s withDelay:0];
}
- (void)sendText:(NSString *)text
withDelay:(int)microsecond {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
// replace all '\n' with '\r'
NSString *s = [text stringByReplacingOccurrencesOfString:@"\n" withString:@"\r"];
// translate into proper encoding of the site
NSMutableData *data = [NSMutableData data];
WLEncoding encoding = [_site encoding];
for (int i = 0; i < [s length]; i++) {
unichar ch = [s characterAtIndex:i];
char buf[2];
if (ch < 0x007F) {
buf[0] = ch;
[data appendBytes:buf length:1];
} else {
unichar code = [WLEncoder fromUnicode:ch encoding:encoding];
if (code != 0) {
buf[0] = code >> 8;
buf[1] = code & 0xFF;
} else {
if (ch == 8943 && encoding == WLGBKEncoding) {
// hard code for the ellipsis
buf[0] = '\xa1';
buf[1] = '\xad';
} else if (ch != 0) {
buf[0] = ' ';
buf[1] = ' ';
}
}
[data appendBytes:buf length:2];
}
}
// Now send the message
if (microsecond == 0) {
// send immediately
[self sendMessage:data];
} else {
// send with delay
const char *buf = (const char *)[data bytes];
for (int i = 0; i < [data length]; i++) {
[self sendBytes:buf+i length:1];
usleep(microsecond);
}
}
[pool release];
}
- (void)login {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSString *addr = [_site address];
const char *account = [addr UTF8String];
// telnet; send username
if (![addr hasPrefix:@"ssh"]) {
char *pe = strchr(account, '@');
if (pe) {
char *ps = pe;
for (; ps >= account; --ps)
if (*ps == ' ' || *ps == '/')
break;
if (ps != pe) {
while ([_feeder cursorY] <= 3)
sleep(1);
[self sendBytes:ps+1 length:pe-ps-1];
[self sendBytes:"\r" length:1];
}
}
} else if ([_feeder grid][[_feeder cursorY]][[_feeder cursorX] - 2].byte == '?') {
[self sendBytes:"yes\r" length:4];
sleep(1);
}
// send password
const char *service = "Welly";
UInt32 len = 0;
void *pass = 0;
SecKeychainFindGenericPassword(nil,
strlen(service), service,
strlen(account), account,
&len, &pass,
nil);
if (len) {
[self sendBytes:pass length:len];
[self sendBytes:"\r" length:1];
SecKeychainItemFreeContent(nil, pass);
}
[pool release];
}
#pragma mark -
#pragma mark Message
- (void)increaseMessageCount:(NSInteger)value {
// increase the '_messageCount' by 'value'
if (value <= 0)
return;
WLGlobalConfig *config = [WLGlobalConfig sharedInstance];
// we should let the icon on the deck bounce
[NSApp requestUserAttention: ([config shouldRepeatBounce] ? NSCriticalRequest : NSInformationalRequest)];
[config setMessageCount:[config messageCount] + value];
_messageCount += value;
[self setObjectCount:_messageCount];
}
// reset '_messageCount' to zero
- (void)resetMessageCount {
if (_messageCount <= 0)
return;
WLGlobalConfig *config = [WLGlobalConfig sharedInstance];
[config setMessageCount:[config messageCount] - _messageCount];
_messageCount = 0;
[self setObjectCount:_messageCount];
}
- (void)didReceiveNewMessage:(NSString *)message
fromCaller:(NSString *)caller {
// If there is a new message, we should notify the auto-reply delegate.
[_messageDelegate connectionDidReceiveNewMessage:message
fromCaller:caller];
}
@end