FreeRDP
TSXAdditions.m
1 /*
2  Additions to Cocoa touch classes
3 
4  Copyright 2013 Thincast Technologies GmbH, Authors: Dorian Johnson, Martin Fleisz
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 "TSXAdditions.h"
12 #include <openssl/bio.h>
13 #include <openssl/evp.h>
14 #include <openssl/err.h>
15 
16 @implementation NSObject (TSXAdditions)
17 
18 - (void)setValuesForKeyPathsWithDictionary:(NSDictionary *)keyedValues
19 {
20  for (id keyPath in keyedValues)
21  [self setValue:[keyedValues objectForKey:keyPath] forKeyPath:keyPath];
22 }
23 
24 - mutableDeepCopy
25 {
26  if ([self respondsToSelector:@selector(mutableCopyWithZone:)])
27  return [self mutableCopy];
28  else if ([self respondsToSelector:@selector(copyWithZone:)])
29  return [self copy];
30  else
31  return [self retain];
32 }
33 
34 @end
35 
36 #pragma mark -
37 
38 @implementation NSString (TSXAdditions)
39 
40 #pragma mark Creation routines
41 + (NSString *)stringWithUUID
42 {
43  CFUUIDRef uuidObj = CFUUIDCreate(nil);
44  NSString *uuidString = (NSString *)CFUUIDCreateString(nil, uuidObj);
45  CFRelease(uuidObj);
46  return [uuidString autorelease];
47 }
48 
49 /* Code from
50  * http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMNSData%2BHex.m?r=344
51  */
52 - (NSData *)dataFromHexString
53 {
54  NSData *hexData = [self dataUsingEncoding:NSASCIIStringEncoding];
55  const char *hexBuf = [hexData bytes];
56  NSUInteger hexLen = [hexData length];
57 
58  // This indicates an error converting to ASCII.
59  if (!hexData)
60  return nil;
61 
62  if ((hexLen % 2) != 0)
63  {
64  return nil;
65  }
66 
67  NSMutableData *binaryData = [NSMutableData dataWithLength:(hexLen / 2)];
68  unsigned char *binaryPtr = [binaryData mutableBytes];
69  unsigned char value = 0;
70  for (NSUInteger i = 0; i < hexLen; i++)
71  {
72  char c = hexBuf[i];
73 
74  if (!isxdigit(c))
75  {
76  return nil;
77  }
78 
79  if (isdigit(c))
80  {
81  value += c - '0';
82  }
83  else if (islower(c))
84  {
85  value += 10 + c - 'a';
86  }
87  else
88  {
89  value += 10 + c - 'A';
90  }
91 
92  if (i & 1)
93  {
94  *binaryPtr++ = value;
95  value = 0;
96  }
97  else
98  {
99  value <<= 4;
100  }
101  }
102 
103  return [NSData dataWithData:binaryData];
104 }
105 
106 + (NSString *)hexStringFromData:(const unsigned char *)data
107  ofSize:(unsigned int)size
108  withSeparator:(NSString *)sep
109  afterNthChar:(int)sepnth
110 {
111  NSMutableString *result;
112  NSString *immutableResult;
113 
114  result = [[NSMutableString alloc] init];
115  for (int i = 0; i < size; i++)
116  {
117  if (i && sep && sepnth && i % sepnth == 0)
118  [result appendString:sep];
119  [result appendFormat:@"%02X", data[i]];
120  }
121 
122  immutableResult = [NSString stringWithString:result];
123  [result release];
124  return immutableResult;
125 }
126 
127 @end
128 
129 #pragma mark Mutable deep copy for dicionary, array and set
130 
131 @implementation NSDictionary (TSXAdditions)
132 
133 - mutableDeepCopy
134 {
135  NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] init];
136  NSEnumerator *enumerator = [self keyEnumerator];
137  id key;
138  while ((key = [enumerator nextObject]))
139  {
140  id obj = [[self objectForKey:key] mutableDeepCopy];
141  [newDictionary setObject:obj forKey:key];
142  [obj release];
143  }
144  return newDictionary;
145 }
146 
147 @end
148 
149 @implementation NSArray (TSXAdditions)
150 
151 - mutableDeepCopy
152 {
153  NSMutableArray *newArray = [[NSMutableArray alloc] init];
154  NSEnumerator *enumerator = [self objectEnumerator];
155  id obj;
156  while ((obj = [enumerator nextObject]))
157  {
158  obj = [obj mutableDeepCopy];
159  [newArray addObject:obj];
160  [obj release];
161  }
162  return newArray;
163 }
164 
165 @end
166 
167 @implementation NSSet (TSXAdditions)
168 
169 - mutableDeepCopy
170 {
171  NSMutableSet *newSet = [[NSMutableSet alloc] init];
172  NSEnumerator *enumerator = [self objectEnumerator];
173  id obj;
174  while ((obj = [enumerator nextObject]))
175  {
176  obj = [obj mutableDeepCopy];
177  [newSet addObject:obj];
178  [obj release];
179  }
180  return newSet;
181 }
182 
183 @end
184 
185 #pragma mark -
186 
187 /* Code from
188  * http://stackoverflow.com/questions/1305225/best-way-to-serialize-a-nsdata-into-an-hexadeximal-string
189  */
190 @implementation NSData (TSXAdditions)
191 
192 #pragma mark - String Conversion
193 - (NSString *)hexadecimalString
194 {
195  /* Returns hexadecimal string of NSData. Empty string if data is empty. */
196 
197  const unsigned char *dataBuffer = (const unsigned char *)[self bytes];
198 
199  if (!dataBuffer)
200  return [NSString string];
201 
202  NSUInteger dataLength = [self length];
203  NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
204 
205  for (int i = 0; i < dataLength; ++i)
206  [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
207 
208  return [NSString stringWithString:hexString];
209 }
210 
211 /* Code from http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html */
212 - (NSString *)base64EncodedString
213 {
214  // Construct an OpenSSL context
215  BIO *context = BIO_new(BIO_s_mem());
216 
217  // Tell the context to encode base64
218  BIO *command = BIO_new(BIO_f_base64());
219  context = BIO_push(command, context);
220  BIO_set_flags(context, BIO_FLAGS_BASE64_NO_NL);
221 
222  // Encode all the data
223  ERR_clear_error();
224  BIO_write(context, [self bytes], [self length]);
225  (void)BIO_flush(context);
226 
227  // Get the data out of the context
228  char *outputBuffer;
229  long outputLength = BIO_get_mem_data(context, &outputBuffer);
230  NSString *encodedString = [[NSString alloc] initWithBytes:outputBuffer
231  length:outputLength
232  encoding:NSASCIIStringEncoding];
233 
234  BIO_free_all(context);
235 
236  return encodedString;
237 }
238 
239 @end