FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
Utils.m
1/*
2 Utility functions
3
4 Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
5
6 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
7 If a copy of the MPL was not distributed with this file, You can obtain one at
8 http://mozilla.org/MPL/2.0/.
9 */
10
11#import "Utils.h"
12#import "OrderedDictionary.h"
13#import "TSXAdditions.h"
14
15#import <freerdp/input.h>
16#import <freerdp/version.h>
17#import <freerdp/config.h>
18
19#include <sys/types.h>
20#include <sys/sysctl.h>
21#include <sys/socket.h>
22#include <ifaddrs.h>
23#include <net/if_dl.h>
24
25BOOL ScanHostNameAndPort(NSString *address, NSString **host, unsigned short *port)
26{
27 *host = @"";
28 *port = 0;
29
30 if (![address length])
31 return NO;
32
33 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"rdp://%@", address]];
34
35 if (!url || ![[url host] length])
36 return NO;
37
38 *host = [url host];
39 *port = [[url port] unsignedShortValue];
40 return YES;
41}
42
43#pragma mark -
44#pragma mark Working with Screen Resolutions
45
46NSString *LocalizedFitScreen()
47{
48 return NSLocalizedString(@"Automatic", @"Screen resolution selector: Automatic resolution "
49 @"(Full Screen on iPad, reasonable size on iPhone)");
50}
51
52NSString *LocalizedCustom()
53{
54 return NSLocalizedString(@"Custom", @"Screen resolution selector: Custom");
55}
56
57BOOL ScanScreenResolution(NSString *description, int *width, int *height, TSXScreenOptions *type)
58{
59 *height = 0;
60 *width = 0;
61 *type = TSXScreenOptionFixed;
62
63 if ([description isEqualToString:LocalizedFitScreen()])
64 {
65 *type = TSXScreenOptionFitScreen;
66 return YES;
67 }
68 else if ([description isEqualToString:LocalizedCustom()])
69 {
70 *type = TSXScreenOptionCustom;
71 return YES;
72 }
73
74 NSArray *resolution_components = [description
75 componentsSeparatedByCharactersInSet:[NSCharacterSet
76 characterSetWithCharactersInString:@"x*×"]];
77
78 if ([resolution_components count] != 2)
79 return NO;
80
81 *width = [[resolution_components objectAtIndex:0] intValue];
82 *height = [[resolution_components objectAtIndex:1] intValue];
83 return YES;
84}
85
86NSString *ScreenResolutionDescription(TSXScreenOptions type, int width, int height)
87{
88 if (type == TSXScreenOptionFitScreen)
89 return LocalizedFitScreen();
90 else if (type == TSXScreenOptionCustom)
91 return LocalizedCustom();
92
93 return [NSString stringWithFormat:@"%dx%d", width, height];
94}
95
96NSDictionary *SelectionForColorSetting()
97{
98 OrderedDictionary *dict = [OrderedDictionary dictionaryWithCapacity:3];
99 [dict setValue:[NSNumber numberWithInt:8]
100 forKey:NSLocalizedString(@"Palette Color (8 Bit)", @"8 bit color selection")];
101 [dict setValue:[NSNumber numberWithInt:15]
102 forKey:NSLocalizedString(@"High Color (15 Bit)", @"15 bit color selection")];
103 [dict setValue:[NSNumber numberWithInt:16]
104 forKey:NSLocalizedString(@"High Color (16 Bit)", @"16 bit color selection")];
105 [dict setValue:[NSNumber numberWithInt:24]
106 forKey:NSLocalizedString(@"True Color (24 Bit)", @"24 bit color selection")];
107 [dict setValue:[NSNumber numberWithInt:32]
108 forKey:NSLocalizedString(@"Highest Quality (32 Bit)", @"32 bit color selection")];
109 return dict;
110}
111
112NSArray *ResolutionModes()
113{
114 NSArray *array =
115 [NSArray arrayWithObjects:ScreenResolutionDescription(TSXScreenOptionFitScreen, 0, 0),
116 ScreenResolutionDescription(TSXScreenOptionFixed, 640, 480),
117 ScreenResolutionDescription(TSXScreenOptionFixed, 800, 600),
118 ScreenResolutionDescription(TSXScreenOptionFixed, 1024, 768),
119 ScreenResolutionDescription(TSXScreenOptionFixed, 1280, 1024),
120 ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 900),
121 ScreenResolutionDescription(TSXScreenOptionFixed, 1440, 1050),
122 ScreenResolutionDescription(TSXScreenOptionFixed, 1600, 1200),
123 ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1080),
124 ScreenResolutionDescription(TSXScreenOptionFixed, 1920, 1200),
125 ScreenResolutionDescription(TSXScreenOptionCustom, 0, 0), nil];
126 return array;
127}
128
129#pragma mark Working with Security Protocols
130
131NSString *LocalizedAutomaticSecurity()
132{
133 return NSLocalizedString(@"Automatic", @"Automatic protocol security selection");
134}
135
136NSString *ProtocolSecurityDescription(TSXProtocolSecurityOptions type)
137{
138 if (type == TSXProtocolSecurityNLA)
139 return @"NLA";
140 else if (type == TSXProtocolSecurityTLS)
141 return @"TLS";
142 else if (type == TSXProtocolSecurityRDP)
143 return @"RDP";
144
145 return LocalizedAutomaticSecurity();
146}
147
148BOOL ScanProtocolSecurity(NSString *description, TSXProtocolSecurityOptions *type)
149{
150 *type = TSXProtocolSecurityRDP;
151
152 if ([description isEqualToString:@"NLA"])
153 {
154 *type = TSXProtocolSecurityNLA;
155 return YES;
156 }
157 else if ([description isEqualToString:@"TLS"])
158 {
159 *type = TSXProtocolSecurityTLS;
160 return YES;
161 }
162 else if ([description isEqualToString:@"RDP"])
163 {
164 *type = TSXProtocolSecurityRDP;
165 return YES;
166 }
167 else if ([description isEqualToString:LocalizedAutomaticSecurity()])
168 {
169 *type = TSXProtocolSecurityAutomatic;
170 return YES;
171 }
172
173 return NO;
174}
175
176NSDictionary *SelectionForSecuritySetting()
177{
178 OrderedDictionary *dict = [OrderedDictionary dictionaryWithCapacity:4];
179 [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityAutomatic]
180 forKey:ProtocolSecurityDescription(TSXProtocolSecurityAutomatic)];
181 [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityRDP]
182 forKey:ProtocolSecurityDescription(TSXProtocolSecurityRDP)];
183 [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityTLS]
184 forKey:ProtocolSecurityDescription(TSXProtocolSecurityTLS)];
185 [dict setValue:[NSNumber numberWithInt:TSXProtocolSecurityNLA]
186 forKey:ProtocolSecurityDescription(TSXProtocolSecurityNLA)];
187 return dict;
188}
189
190#pragma mark -
191#pragma mark Bookmarks
192
193#import "Bookmark.h"
194
195NSMutableArray *FilterBookmarks(NSArray *bookmarks, NSArray *filter_words)
196{
197 NSMutableArray *matching_items = [NSMutableArray array];
198 NSArray *searched_keys = [NSArray
199 arrayWithObjects:@"label", @"params.hostname", @"params.username", @"params.domain", nil];
200
201 for (ComputerBookmark *cur_bookmark in bookmarks)
202 {
203 double match_score = 0.0;
204
205 for (int i = 0; i < [searched_keys count]; i++)
206 {
207 NSString *val = [cur_bookmark valueForKeyPath:[searched_keys objectAtIndex:i]];
208
209 if (![val isKindOfClass:[NSString class]] || ![val length])
210 continue;
211
212 for (NSString *word in filter_words)
213 if ([val rangeOfString:word
214 options:(NSCaseInsensitiveSearch | NSWidthInsensitiveSearch)]
215 .location != NSNotFound)
216 match_score += (1.0 / [filter_words count]) * pow(2, [searched_keys count] - i);
217 }
218
219 if (match_score > 0.001)
220 [matching_items
221 addObject:[NSDictionary
222 dictionaryWithObjectsAndKeys:cur_bookmark, @"bookmark",
223 [NSNumber numberWithFloat:match_score],
224 @"score", nil]];
225 }
226
227 [matching_items
228 sortUsingComparator:^NSComparisonResult(NSDictionary *obj1, NSDictionary *obj2) {
229 return [[obj2 objectForKey:@"score"] compare:[obj1 objectForKey:@"score"]];
230 }];
231 return matching_items;
232}
233
234NSMutableArray *FilterHistory(NSArray *history, NSString *filterStr)
235{
236 NSMutableArray *result = [NSMutableArray array];
237
238 for (NSString *item in history)
239 {
240 if ([item rangeOfString:filterStr].location != NSNotFound)
241 [result addObject:item];
242 }
243
244 return result;
245}
246
247#pragma mark Version Info
248NSString *TSXAppFullVersion()
249{
250 return [NSString stringWithUTF8String:FREERDP_GIT_REVISION];
251}
252
253#pragma mark iPad/iPhone detection
254
255BOOL IsPad()
256{
257#ifdef UI_USER_INTERFACE_IDIOM
258 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
259#else
260 return NO;
261#endif
262}
263
264BOOL IsPhone()
265{
266#ifdef UI_USER_INTERFACE_IDIOM
267 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone);
268#else
269 return NO;
270#endif
271}
272
273// set mouse buttons swapped flag
274static BOOL g_swap_mouse_buttons = NO;
275void SetSwapMouseButtonsFlag(BOOL swapped)
276{
277 g_swap_mouse_buttons = swapped;
278}
279
280// set invert scrolling flag
281static BOOL g_invert_scrolling = NO;
282void SetInvertScrollingFlag(BOOL invert)
283{
284 g_invert_scrolling = invert;
285}
286
287// return event value for left mouse button
288int GetLeftMouseButtonClickEvent(BOOL down)
289{
290 if (g_swap_mouse_buttons)
291 return (PTR_FLAGS_BUTTON2 | (down ? PTR_FLAGS_DOWN : 0));
292 else
293 return (PTR_FLAGS_BUTTON1 | (down ? PTR_FLAGS_DOWN : 0));
294}
295
296// return event value for right mouse button
297int GetRightMouseButtonClickEvent(BOOL down)
298{
299 if (g_swap_mouse_buttons)
300 return (PTR_FLAGS_BUTTON1 | (down ? PTR_FLAGS_DOWN : 0));
301 else
302 return (PTR_FLAGS_BUTTON2 | (down ? PTR_FLAGS_DOWN : 0));
303}
304
305// get mouse move event
306int GetMouseMoveEvent()
307{
308 return (PTR_FLAGS_MOVE);
309}
310
311// return mouse wheel event
312int GetMouseWheelEvent(BOOL down)
313{
314 if (g_invert_scrolling)
315 down = !down;
316
317 if (down)
318 return (PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | (0x0088));
319 else
320 return (PTR_FLAGS_WHEEL | (0x0078));
321}
322
323// scrolling gesture detection delta
324CGFloat GetScrollGestureDelta()
325{
326 return 10.0f;
327}
328
329// this hack activates the iphone's WWAN interface in case it is offline
330void WakeUpWWAN()
331{
332 NSURL *url = [[[NSURL alloc] initWithString:@"http://www.nonexistingdummyurl.com"] autorelease];
333 // NSData * data =
334 [NSData dataWithContentsOfURL:url]; // we don't need data but assigning one causes a "data not
335 // used" compiler warning
336}
337
338#pragma mark System Info functions
339
340NSString *TSXGetPrimaryMACAddress(NSString *sep)
341{
342 NSString *macaddress = @"";
343 struct ifaddrs *addrs;
344
345 if (getifaddrs(&addrs) < 0)
346 {
347 NSLog(@"getPrimaryMACAddress: getifaddrs failed.");
348 return macaddress;
349 }
350
351 for (struct ifaddrs *cursor = addrs; cursor != NULL; cursor = cursor->ifa_next)
352 {
353 if (strcmp(cursor->ifa_name, "en0"))
354 continue;
355
356 if ((cursor->ifa_addr->sa_family == AF_LINK) &&
357 (((struct sockaddr_dl *)cursor->ifa_addr)->sdl_type == 0x6 /*IFT_ETHER*/))
358 {
359 struct sockaddr_dl *dlAddr = (struct sockaddr_dl *)cursor->ifa_addr;
360
361 if (dlAddr->sdl_alen != 6)
362 continue;
363
364 unsigned char *base = (unsigned char *)&dlAddr->sdl_data[dlAddr->sdl_nlen];
365 macaddress = [NSString hexStringFromData:base
366 ofSize:6
367 withSeparator:sep
368 afterNthChar:1];
369 break;
370 }
371 }
372
373 freeifaddrs(addrs);
374 return macaddress;
375}
376
377BOOL TSXDeviceHasJailBreak()
378{
379 if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app/"])
380 return YES;
381
382 if ([[NSFileManager defaultManager] fileExistsAtPath:@"/etc/apt/"])
383 return YES;
384
385 return NO;
386}
387
388NSString *TSXGetPlatform()
389{
390 size_t size;
391 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
392 char *machine = malloc(size);
393 sysctlbyname("hw.machine", machine, &size, NULL, 0);
394 NSString *platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];
395 free(machine);
396 return platform;
397}