http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h new file mode 100755 index 0000000..90d442a --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2010, Stig Brautaset. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <Foundation/Foundation.h> + +@class SBJsonStreamWriter; + +@interface SBJsonStreamWriterState : NSObject ++ (id)sharedInstance; +- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer; +- (void)appendSeparator:(SBJsonStreamWriter*)writer; +- (BOOL)expectingKey:(SBJsonStreamWriter*)writer; +- (void)transitionState:(SBJsonStreamWriter*)writer; +- (void)appendWhitespace:(SBJsonStreamWriter*)writer; +@end + +@interface SBJsonStreamWriterStateObjectStart : SBJsonStreamWriterState +@end + +@interface SBJsonStreamWriterStateObjectKey : SBJsonStreamWriterStateObjectStart +@end + +@interface SBJsonStreamWriterStateObjectValue : SBJsonStreamWriterState +@end + +@interface SBJsonStreamWriterStateArrayStart : SBJsonStreamWriterState +@end + +@interface SBJsonStreamWriterStateArrayValue : SBJsonStreamWriterState +@end + +@interface SBJsonStreamWriterStateStart : SBJsonStreamWriterState +@end + +@interface SBJsonStreamWriterStateComplete : SBJsonStreamWriterState +@end + +@interface SBJsonStreamWriterStateError : SBJsonStreamWriterState +@end +
http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m new file mode 100755 index 0000000..9f04cac --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m @@ -0,0 +1,139 @@ +/* + Copyright (c) 2010, Stig Brautaset. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonStreamWriterState.h" +#import "SBJsonStreamWriter.h" + +#define SINGLETON \ ++ (id)sharedInstance { \ + static id state; \ + if (!state) state = [[self alloc] init]; \ + return state; \ +} + + +@implementation SBJsonStreamWriterState ++ (id)sharedInstance { return nil; } +- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer { return NO; } +- (void)appendSeparator:(SBJsonStreamWriter*)writer {} +- (BOOL)expectingKey:(SBJsonStreamWriter*)writer { return NO; } +- (void)transitionState:(SBJsonStreamWriter *)writer {} +- (void)appendWhitespace:(SBJsonStreamWriter*)writer { + [writer appendBytes:"\n" length:1]; + for (NSUInteger i = 0; i < writer.stateStack.count; i++) + [writer appendBytes:" " length:2]; +} +@end + +@implementation SBJsonStreamWriterStateObjectStart + +SINGLETON + +- (void)transitionState:(SBJsonStreamWriter *)writer { + writer.state = [SBJsonStreamWriterStateObjectValue sharedInstance]; +} +- (BOOL)expectingKey:(SBJsonStreamWriter *)writer { + writer.error = @"JSON object key must be string"; + return YES; +} +@end + +@implementation SBJsonStreamWriterStateObjectKey + +SINGLETON + +- (void)appendSeparator:(SBJsonStreamWriter *)writer { + [writer appendBytes:"," length:1]; +} +@end + +@implementation SBJsonStreamWriterStateObjectValue + +SINGLETON + +- (void)appendSeparator:(SBJsonStreamWriter *)writer { + [writer appendBytes:":" length:1]; +} +- (void)transitionState:(SBJsonStreamWriter *)writer { + writer.state = [SBJsonStreamWriterStateObjectKey sharedInstance]; +} +- (void)appendWhitespace:(SBJsonStreamWriter *)writer { + [writer appendBytes:" " length:1]; +} +@end + +@implementation SBJsonStreamWriterStateArrayStart + +SINGLETON + +- (void)transitionState:(SBJsonStreamWriter *)writer { + writer.state = [SBJsonStreamWriterStateArrayValue sharedInstance]; +} +@end + +@implementation SBJsonStreamWriterStateArrayValue + +SINGLETON + +- (void)appendSeparator:(SBJsonStreamWriter *)writer { + [writer appendBytes:"," length:1]; +} +@end + +@implementation SBJsonStreamWriterStateStart + +SINGLETON + + +- (void)transitionState:(SBJsonStreamWriter *)writer { + writer.state = [SBJsonStreamWriterStateComplete sharedInstance]; +} +- (void)appendSeparator:(SBJsonStreamWriter *)writer { +} +@end + +@implementation SBJsonStreamWriterStateComplete + +SINGLETON + +- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer { + writer.error = @"Stream is closed"; + return YES; +} +@end + +@implementation SBJsonStreamWriterStateError + +SINGLETON + +@end + http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h new file mode 100755 index 0000000..e484a94 --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h @@ -0,0 +1,67 @@ +/* + Copyright (c) 2010, Stig Brautaset. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <Foundation/Foundation.h> + +typedef enum { + sbjson_token_error = -1, + sbjson_token_eof, + + sbjson_token_array_start, + sbjson_token_array_end, + + sbjson_token_object_start, + sbjson_token_object_end, + + sbjson_token_separator, + sbjson_token_keyval_separator, + + sbjson_token_number, + sbjson_token_string, + sbjson_token_true, + sbjson_token_false, + sbjson_token_null, + +} sbjson_token_t; + +@class SBJsonUTF8Stream; + +@interface SBJsonTokeniser : NSObject + +@property (strong) SBJsonUTF8Stream *stream; +@property (copy) NSString *error; + +- (void)appendData:(NSData*)data_; + +- (sbjson_token_t)getToken:(NSObject**)token; + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m new file mode 100755 index 0000000..75d3268 --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m @@ -0,0 +1,453 @@ +/* + Copyright (c) 2010-2011, Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonTokeniser.h" +#import "SBJsonUTF8Stream.h" + +#define SBStringIsIllegalSurrogateHighCharacter(character) (((character) >= 0xD800UL) && ((character) <= 0xDFFFUL)) +#define SBStringIsSurrogateLowCharacter(character) ((character >= 0xDC00UL) && (character <= 0xDFFFUL)) +#define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL)) + +@implementation SBJsonTokeniser + +@synthesize error = _error; +@synthesize stream = _stream; + +- (id)init { + self = [super init]; + if (self) { + _stream = [[SBJsonUTF8Stream alloc] init]; + + } + + return self; +} + + +- (void)appendData:(NSData *)data_ { + [_stream appendData:data_]; +} + + +- (sbjson_token_t)match:(const char *)pattern length:(NSUInteger)len retval:(sbjson_token_t)token { + if (![_stream haveRemainingCharacters:len]) + return sbjson_token_eof; + + if ([_stream skipCharacters:pattern length:len]) + return token; + + self.error = [NSString stringWithFormat:@"Expected '%s' after initial '%.1s'", pattern, pattern]; + return sbjson_token_error; +} + +- (BOOL)decodeEscape:(unichar)ch into:(unichar*)decoded { + switch (ch) { + case '\\': + case '/': + case '"': + *decoded = ch; + break; + + case 'b': + *decoded = '\b'; + break; + + case 'n': + *decoded = '\n'; + break; + + case 'r': + *decoded = '\r'; + break; + + case 't': + *decoded = '\t'; + break; + + case 'f': + *decoded = '\f'; + break; + + default: + self.error = @"Illegal escape character"; + return NO; + break; + } + return YES; +} + +- (BOOL)decodeHexQuad:(unichar*)quad { + unichar c, tmp = 0; + + for (int i = 0; i < 4; i++) { + (void)[_stream getNextUnichar:&c]; + tmp *= 16; + switch (c) { + case '0' ... '9': + tmp += c - '0'; + break; + + case 'a' ... 'f': + tmp += 10 + c - 'a'; + break; + + case 'A' ... 'F': + tmp += 10 + c - 'A'; + break; + + default: + return NO; + } + } + *quad = tmp; + return YES; +} + +- (sbjson_token_t)getStringToken:(NSObject**)token { + NSMutableString *acc = nil; + + for (;;) { + [_stream skip]; + + unichar ch; + { + NSMutableString *string = nil; + + if (![_stream getStringFragment:&string]) + return sbjson_token_eof; + + if (!string) { + self.error = @"Broken Unicode encoding"; + return sbjson_token_error; + } + + if (![_stream getUnichar:&ch]) + return sbjson_token_eof; + + if (acc) { + [acc appendString:string]; + + } else if (ch == '"') { + *token = [string copy]; + [_stream skip]; + return sbjson_token_string; + + } else { + acc = [string mutableCopy]; + } + } + + + switch (ch) { + case 0 ... 0x1F: + self.error = [NSString stringWithFormat:@"Unescaped control character [0x%0.2X]", (int)ch]; + return sbjson_token_error; + break; + + case '"': + *token = acc; + [_stream skip]; + return sbjson_token_string; + break; + + case '\\': + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + + if (ch == 'u') { + if (![_stream haveRemainingCharacters:5]) + return sbjson_token_eof; + + unichar hi; + if (![self decodeHexQuad:&hi]) { + self.error = @"Invalid hex quad"; + return sbjson_token_error; + } + + if (SBStringIsSurrogateHighCharacter(hi)) { + unichar lo; + + if (![_stream haveRemainingCharacters:6]) + return sbjson_token_eof; + + (void)[_stream getNextUnichar:&ch]; + (void)[_stream getNextUnichar:&lo]; + if (ch != '\\' || lo != 'u' || ![self decodeHexQuad:&lo]) { + self.error = @"Missing low character in surrogate pair"; + return sbjson_token_error; + } + + if (!SBStringIsSurrogateLowCharacter(lo)) { + self.error = @"Invalid low character in surrogate pair"; + return sbjson_token_error; + } + + [acc appendFormat:@"%C%C", hi, lo]; + } else if (SBStringIsIllegalSurrogateHighCharacter(hi)) { + self.error = @"Invalid high character in surrogate pair"; + return sbjson_token_error; + } else { + [acc appendFormat:@"%C", hi]; + } + + + } else { + unichar decoded; + if (![self decodeEscape:ch into:&decoded]) + return sbjson_token_error; + [acc appendFormat:@"%C", decoded]; + } + + break; + + default: { + self.error = [NSString stringWithFormat:@"Invalid UTF-8: '%x'", (int)ch]; + return sbjson_token_error; + break; + } + } + } + return sbjson_token_eof; +} + +- (sbjson_token_t)getNumberToken:(NSObject**)token { + + NSUInteger numberStart = _stream.index; + NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet]; + + unichar ch; + if (![_stream getUnichar:&ch]) + return sbjson_token_eof; + + BOOL isNegative = NO; + if (ch == '-') { + isNegative = YES; + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + } + + unsigned long long mantissa = 0; + int mantissa_length = 0; + + if (ch == '0') { + mantissa_length++; + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + + if ([digits characterIsMember:ch]) { + self.error = @"Leading zero is illegal in number"; + return sbjson_token_error; + } + } + + while ([digits characterIsMember:ch]) { + mantissa *= 10; + mantissa += (ch - '0'); + mantissa_length++; + + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + } + + short exponent = 0; + BOOL isFloat = NO; + + if (ch == '.') { + isFloat = YES; + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + + while ([digits characterIsMember:ch]) { + mantissa *= 10; + mantissa += (ch - '0'); + mantissa_length++; + exponent--; + + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + } + + if (!exponent) { + self.error = @"No digits after decimal point"; + return sbjson_token_error; + } + } + + BOOL hasExponent = NO; + if (ch == 'e' || ch == 'E') { + hasExponent = YES; + + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + + BOOL expIsNegative = NO; + if (ch == '-') { + expIsNegative = YES; + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + + } else if (ch == '+') { + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + } + + short explicit_exponent = 0; + short explicit_exponent_length = 0; + while ([digits characterIsMember:ch]) { + explicit_exponent *= 10; + explicit_exponent += (ch - '0'); + explicit_exponent_length++; + + if (![_stream getNextUnichar:&ch]) + return sbjson_token_eof; + } + + if (explicit_exponent_length == 0) { + self.error = @"No digits in exponent"; + return sbjson_token_error; + } + + if (expIsNegative) + exponent -= explicit_exponent; + else + exponent += explicit_exponent; + } + + if (!mantissa_length && isNegative) { + self.error = @"No digits after initial minus"; + return sbjson_token_error; + + } else if (mantissa_length >= 19) { + + NSString *number = [_stream stringWithRange:NSMakeRange(numberStart, _stream.index - numberStart)]; + *token = [NSDecimalNumber decimalNumberWithString:number]; + + } else if (!isFloat && !hasExponent) { + if (!isNegative) + *token = [NSNumber numberWithUnsignedLongLong:mantissa]; + else + *token = [NSNumber numberWithLongLong:-mantissa]; + } else { + *token = [NSDecimalNumber decimalNumberWithMantissa:mantissa + exponent:exponent + isNegative:isNegative]; + } + + return sbjson_token_number; +} + +- (sbjson_token_t)getToken:(NSObject **)token { + + [_stream skipWhitespace]; + + unichar ch; + if (![_stream getUnichar:&ch]) + return sbjson_token_eof; + + NSUInteger oldIndexLocation = _stream.index; + sbjson_token_t tok; + + switch (ch) { + case '[': + tok = sbjson_token_array_start; + [_stream skip]; + break; + + case ']': + tok = sbjson_token_array_end; + [_stream skip]; + break; + + case '{': + tok = sbjson_token_object_start; + [_stream skip]; + break; + + case ':': + tok = sbjson_token_keyval_separator; + [_stream skip]; + break; + + case '}': + tok = sbjson_token_object_end; + [_stream skip]; + break; + + case ',': + tok = sbjson_token_separator; + [_stream skip]; + break; + + case 'n': + tok = [self match:"null" length:4 retval:sbjson_token_null]; + break; + + case 't': + tok = [self match:"true" length:4 retval:sbjson_token_true]; + break; + + case 'f': + tok = [self match:"false" length:5 retval:sbjson_token_false]; + break; + + case '"': + tok = [self getStringToken:token]; + break; + + case '0' ... '9': + case '-': + tok = [self getNumberToken:token]; + break; + + case '+': + self.error = @"Leading + is illegal in number"; + tok = sbjson_token_error; + break; + + default: + self.error = [NSString stringWithFormat:@"Illegal start of token [%c]", ch]; + tok = sbjson_token_error; + break; + } + + if (tok == sbjson_token_eof) { + // We ran out of bytes in the middle of a token. + // We don't know how to restart in mid-flight, so + // rewind to the start of the token for next attempt. + // Hopefully we'll have more data then. + _stream.index = oldIndexLocation; + } + + return tok; +} + + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h new file mode 100755 index 0000000..a26f032 --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2011, Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <Foundation/Foundation.h> + + +@interface SBJsonUTF8Stream : NSObject { +@private + const char *_bytes; + NSMutableData *_data; + NSUInteger _length; +} + +@property (assign) NSUInteger index; + +- (void)appendData:(NSData*)data_; + +- (BOOL)haveRemainingCharacters:(NSUInteger)chars; + +- (void)skip; +- (void)skipWhitespace; +- (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len; + +- (BOOL)getUnichar:(unichar*)ch; +- (BOOL)getNextUnichar:(unichar*)ch; +- (BOOL)getStringFragment:(NSString**)string; + +- (NSString*)stringWithRange:(NSRange)range; + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m new file mode 100755 index 0000000..f57015d --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m @@ -0,0 +1,141 @@ +/* + Copyright (c) 2011, Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name of the the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonUTF8Stream.h" + + +@implementation SBJsonUTF8Stream + +@synthesize index = _index; + +- (id)init { + self = [super init]; + if (self) { + _data = [[NSMutableData alloc] initWithCapacity:4096u]; + } + return self; +} + + +- (void)appendData:(NSData *)data_ { + + if (_index) { + // Discard data we've already parsed + [_data replaceBytesInRange:NSMakeRange(0, _index) withBytes:"" length:0]; + + // Reset index to point to current position + _index = 0; + } + + [_data appendData:data_]; + + // This is an optimisation. + _bytes = (const char*)[_data bytes]; + _length = [_data length]; +} + + +- (BOOL)getUnichar:(unichar*)ch { + if (_index < _length) { + *ch = (unichar)_bytes[_index]; + return YES; + } + return NO; +} + +- (BOOL)getNextUnichar:(unichar*)ch { + if (++_index < _length) { + *ch = (unichar)_bytes[_index]; + return YES; + } + return NO; +} + +- (BOOL)getStringFragment:(NSString **)string { + NSUInteger start = _index; + while (_index < _length) { + switch (_bytes[_index]) { + case '"': + case '\\': + case 0 ... 0x1f: + *string = [[NSString alloc] initWithBytes:(_bytes + start) + length:(_index - start) + encoding:NSUTF8StringEncoding]; + return YES; + break; + default: + _index++; + break; + } + } + return NO; +} + +- (void)skip { + _index++; +} + +- (void)skipWhitespace { + while (_index < _length) { + switch (_bytes[_index]) { + case ' ': + case '\t': + case '\r': + case '\n': + _index++; + break; + default: + return; + break; + } + } +} + +- (BOOL)haveRemainingCharacters:(NSUInteger)chars { + return [_data length] - _index >= chars; +} + +- (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len { + const void *bytes = ((const char*)[_data bytes]) + _index; + if (!memcmp(bytes, chars, len)) { + _index += len; + return YES; + } + return NO; +} + +- (NSString*)stringWithRange:(NSRange)range { + return [[NSString alloc] initWithBytes:_bytes + range.location length:range.length encoding:NSUTF8StringEncoding]; + +} + + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h new file mode 100755 index 0000000..640816c --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h @@ -0,0 +1,117 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <Foundation/Foundation.h> + +/** + @brief The JSON writer class. + + This uses SBJsonStreamWriter internally. + + @see @ref json2objc + */ + +@interface SBJsonWriter : NSObject + +/** + @brief The maximum recursing depth. + + Defaults to 32. If the input is nested deeper than this the input will be deemed to be + malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can + turn off this security feature by setting the maxDepth value to 0. + */ +@property NSUInteger maxDepth; + +/** + @brief Return an error trace, or nil if there was no errors. + + Note that this method returns the trace of the last method that failed. + You need to check the return value of the call you're making to figure out + if the call actually failed, before you know call this method. + */ +@property (readonly, copy) NSString *error; + +/** + @brief Whether we are generating human-readable (multiline) JSON. + + Set whether or not to generate human-readable JSON. The default is NO, which produces + JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable + JSON with linebreaks after each array value and dictionary key/value pair, indented two + spaces per nesting level. + */ +@property BOOL humanReadable; + +/** + @brief Whether or not to sort the dictionary keys in the output. + + If this is set to YES, the dictionary keys in the JSON output will be in sorted order. + (This is useful if you need to compare two structures, for example.) The default is NO. + */ +@property BOOL sortKeys; + +/** + @brief An optional comparator to be used if sortKeys is YES. + + If this is nil, sorting will be done via @selector(compare:). + */ +@property (copy) NSComparator sortKeysComparator; + +/** + @brief Return JSON representation for the given object. + + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as JSON text. + */ +- (NSString*)stringWithObject:(id)value; + +/** + @brief Return JSON representation for the given object. + + Returns an NSData object containing JSON represented as UTF8 text, or nil on error. + + @param value any instance that can be represented as JSON text. + */ +- (NSData*)dataWithObject:(id)value; + +/** + @brief Return JSON representation (or fragment) for the given object. + + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + @param error pointer to object to be populated with NSError on failure + + */- (NSString*)stringWithObject:(id)value + error:(NSError**)error; + + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m new file mode 100755 index 0000000..d200f9c --- /dev/null +++ b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m @@ -0,0 +1,112 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonWriter.h" +#import "SBJsonStreamWriter.h" +#import "SBJsonStreamWriterAccumulator.h" + + +@interface SBJsonWriter () +@property (copy) NSString *error; +@end + +@implementation SBJsonWriter + +@synthesize sortKeys; +@synthesize humanReadable; + +@synthesize error; +@synthesize maxDepth; + +@synthesize sortKeysComparator; + +- (id)init { + self = [super init]; + if (self) { + self.maxDepth = 32u; + } + return self; +} + + +- (NSString*)stringWithObject:(id)value { + NSData *data = [self dataWithObject:value]; + if (data) + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + return nil; +} + +- (NSString*)stringWithObject:(id)value error:(NSError**)error_ { + NSString *tmp = [self stringWithObject:value]; + if (tmp) + return tmp; + + if (error_) { + NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:error, NSLocalizedDescriptionKey, nil]; + *error_ = [NSError errorWithDomain:@"org.brautaset.SBJsonWriter.ErrorDomain" code:0 userInfo:ui]; + } + + return nil; +} + +- (NSData*)dataWithObject:(id)object { + self.error = nil; + + SBJsonStreamWriterAccumulator *accumulator = [[SBJsonStreamWriterAccumulator alloc] init]; + + SBJsonStreamWriter *streamWriter = [[SBJsonStreamWriter alloc] init]; + streamWriter.sortKeys = self.sortKeys; + streamWriter.maxDepth = self.maxDepth; + streamWriter.sortKeysComparator = self.sortKeysComparator; + streamWriter.humanReadable = self.humanReadable; + streamWriter.delegate = accumulator; + + BOOL ok = NO; + if ([object isKindOfClass:[NSDictionary class]]) + ok = [streamWriter writeObject:object]; + + else if ([object isKindOfClass:[NSArray class]]) + ok = [streamWriter writeArray:object]; + + else if ([object respondsToSelector:@selector(proxyForJson)]) + return [self dataWithObject:[object proxyForJson]]; + else { + self.error = @"Not valid type for JSON"; + return nil; + } + + if (ok) + return accumulator.data; + + self.error = streamWriter.error; + return nil; +} + + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SSKeychain.h ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SSKeychain.h b/sdks/other/ios/UGAPI/SSKeychain.h new file mode 100644 index 0000000..23093b6 --- /dev/null +++ b/sdks/other/ios/UGAPI/SSKeychain.h @@ -0,0 +1,357 @@ +// +// SSKeychain.h +// SSToolkit +// +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2009-2011 Sam Soffes. All rights reserved. +// + +#import <Foundation/Foundation.h> +#import <Security/Security.h> + +/** Error codes that can be returned in NSError objects. */ +typedef enum { + /** No error. */ + SSKeychainErrorNone = noErr, + + /** Some of the arguments were invalid. */ + SSKeychainErrorBadArguments = -1001, + + /** There was no password. */ + SSKeychainErrorNoPassword = -1002, + + /** One or more parameters passed internally were not valid. */ + SSKeychainErrorInvalidParameter = errSecParam, + + /** Failed to allocate memory. */ + SSKeychainErrorFailedToAllocated = errSecAllocate, + + /** No trust results are available. */ + SSKeychainErrorNotAvailable = errSecNotAvailable, + + /** Authorization/Authentication failed. */ + SSKeychainErrorAuthorizationFailed = errSecAuthFailed, + + /** The item already exists. */ + SSKeychainErrorDuplicatedItem = errSecDuplicateItem, + + /** The item cannot be found.*/ + SSKeychainErrorNotFound = errSecItemNotFound, + + /** Interaction with the Security Server is not allowed. */ + SSKeychainErrorInteractionNotAllowed = errSecInteractionNotAllowed, + + /** Unable to decode the provided data. */ + SSKeychainErrorFailedToDecode = errSecDecode +} SSKeychainErrorCode; + +extern NSString *const kSSKeychainErrorDomain; + +/** Account name. */ +extern NSString *const kSSKeychainAccountKey; + +/** + Time the item was created. + + The value will be a string. + */ +extern NSString *const kSSKeychainCreatedAtKey; + +/** Item class. */ +extern NSString *const kSSKeychainClassKey; + +/** Item description. */ +extern NSString *const kSSKeychainDescriptionKey; + +/** Item label. */ +extern NSString *const kSSKeychainLabelKey; + +/** Time the item was last modified. + + The value will be a string. + */ +extern NSString *const kSSKeychainLastModifiedKey; + +/** Where the item was created. */ +extern NSString *const kSSKeychainWhereKey; + +/** + Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system + Keychain on Mac OS X and iOS. + + This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors. + SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it). + */ +@interface SSKeychain : NSObject + +///----------------------- +/// @name Getting Accounts +///----------------------- + +/** + Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any + accounts. The order of the objects in the array isn't defined. + + @see allAccounts: + */ ++ (NSArray *)allAccounts; + +/** + Returns an array containing the Keychain's accounts, or `nil` if the Keychain doesn't have any + accounts. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @param error If accessing the accounts fails, upon return contains an error that describes the problem. + + @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any + accounts. The order of the objects in the array isn't defined. + + @see allAccounts + */ ++ (NSArray *)allAccounts:(NSError **)error; + +/** + Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any + accounts for the given service. + + See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the + dictionaries returned by this method. + + @param serviceName The service for which to return the corresponding accounts. + + @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain + doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. + + @see accountsForService:error: + */ ++ (NSArray *)accountsForService:(NSString *)serviceName; + +/** + Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any + accounts for the given service. + + @param serviceName The service for which to return the corresponding accounts. + + @param error If accessing the accounts fails, upon return contains an error that describes the problem. + + @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain + doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined. + + @see accountsForService: + */ ++ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError **)error; + + +///------------------------ +/// @name Getting Passwords +///------------------------ + +/** + Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a + password for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + + @see passwordForService:account:error: + */ ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account; + +/** + Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a + password for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @param error If accessing the password fails, upon return contains an error that describes the problem. + + @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + + @see passwordForService:account: + */ ++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + +/** + Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data + for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @param error If accessing the password fails, upon return contains an error that describes the problem. + + @return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't + have data for the given parameters. + + @see passwordDataForService:account:error: + */ ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; + +/** + Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data + for the given parameters. + + @param serviceName The service for which to return the corresponding password. + + @param account The account for which to return the corresponding password. + + @param error If accessing the password fails, upon return contains an error that describes the problem. + + @return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't + have a password for the given parameters. + + @see passwordDataForService:account: + */ ++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + + +///------------------------- +/// @name Deleting Passwords +///------------------------- + +/** + Deletes a password from the Keychain. + + @param serviceName The service for which to delete the corresponding password. + + @param account The account for which to delete the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + + @see deletePasswordForService:account:error: + */ ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account; + +/** + Deletes a password from the Keychain. + + @param serviceName The service for which to delete the corresponding password. + + @param account The account for which to delete the corresponding password. + + @param error If deleting the password fails, upon return contains an error that describes the problem. + + @return Returns `YES` on success, or `NO` on failure. + + @see deletePasswordForService:account: + */ ++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + + +///------------------------ +/// @name Setting Passwords +///------------------------ + +/** + Sets a password in the Keychain. + + @param password The password to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @return Returns `YES` on success, or `NO` on failure. + + @see setPassword:forService:account:error: + */ ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account; + +/** + Sets a password in the Keychain. + + @param password The password to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @param error If setting the password fails, upon return contains an error that describes the problem. + + @return Returns `YES` on success, or `NO` on failure. + + @see setPassword:forService:account: + */ ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + +/** + Sets arbirary data in the Keychain. + + @param password The data to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @param error If setting the password fails, upon return contains an error that describes the problem. + + @return Returns `YES` on success, or `NO` on failure. + + @see setPasswordData:forService:account:error: + */ ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; + +/** + Sets arbirary data in the Keychain. + + @param password The data to store in the Keychain. + + @param serviceName The service for which to set the corresponding password. + + @param account The account for which to set the corresponding password. + + @param error If setting the password fails, upon return contains an error that describes the problem. + + @return Returns `YES` on success, or `NO` on failure. + + @see setPasswordData:forService:account: + */ ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error; + + +///-------------------- +/// @name Configuration +///-------------------- + +#if __IPHONE_4_0 && TARGET_OS_IPHONE +/** + Returns the accessibility type for all future passwords saved to the Keychain. + + @return Returns the accessibility type. + + The return value will be `NULL` or one of the "Keychain Item Accessibility Constants" used for determining when a + keychain item should be readable. + + @see accessibilityType + */ ++ (CFTypeRef)accessibilityType; + +/** + Sets the accessibility type for all future passwords saved to the Keychain. + + @param accessibilityType One of the "Keychain Item Accessibility Constants" used for determining when a keychain item + should be readable. + + If the value is `NULL` (the default), the Keychain default will be used. + + @see accessibilityType + */ ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType; +#endif + +@end \ No newline at end of file http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SSKeychain.m ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/SSKeychain.m b/sdks/other/ios/UGAPI/SSKeychain.m new file mode 100644 index 0000000..1267b5e --- /dev/null +++ b/sdks/other/ios/UGAPI/SSKeychain.m @@ -0,0 +1,262 @@ +// +// SSKeychain.m +// SSToolkit +// +// Created by Sam Soffes on 5/19/10. +// Copyright (c) 2009-2011 Sam Soffes. All rights reserved. +// + +#import "SSKeychain.h" + +NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain"; + +NSString *const kSSKeychainAccountKey = @"acct"; +NSString *const kSSKeychainCreatedAtKey = @"cdat"; +NSString *const kSSKeychainClassKey = @"labl"; +NSString *const kSSKeychainDescriptionKey = @"desc"; +NSString *const kSSKeychainLabelKey = @"labl"; +NSString *const kSSKeychainLastModifiedKey = @"mdat"; +NSString *const kSSKeychainWhereKey = @"svce"; + +#if __IPHONE_4_0 && TARGET_OS_IPHONE +CFTypeRef SSKeychainAccessibilityType = NULL; +#endif + +@interface SSKeychain () ++ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account; +@end + +@implementation SSKeychain + +#pragma mark - Getting Accounts + ++ (NSArray *)allAccounts { + return [self accountsForService:nil error:nil]; +} + + ++ (NSArray *)allAccounts:(NSError **)error { + return [self accountsForService:nil error:error]; +} + + ++ (NSArray *)accountsForService:(NSString *)service { + return [self accountsForService:service error:nil]; +} + + ++ (NSArray *)accountsForService:(NSString *)service error:(NSError **)error { + OSStatus status = SSKeychainErrorBadArguments; + NSMutableDictionary *query = [self _queryForService:service account:nil]; +#if __has_feature(objc_arc) + [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes]; + [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; +#else + [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; + [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit]; +#endif + + CFTypeRef result = NULL; +#if __has_feature(objc_arc) + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); +#else + status = SecItemCopyMatching((CFDictionaryRef)query, &result); +#endif + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; + return nil; + } + +#if __has_feature(objc_arc) + return (__bridge_transfer NSArray *)result; +#else + return [(NSArray *)result autorelease]; +#endif +} + + +#pragma mark - Getting Passwords + ++ (NSString *)passwordForService:(NSString *)service account:(NSString *)account { + return [self passwordForService:service account:account error:nil]; +} + + ++ (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + NSData *data = [self passwordDataForService:service account:account error:error]; + if (data.length > 0) { + NSString *string = [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding]; +#if !__has_feature(objc_arc) + [string autorelease]; +#endif + return string; + } + + return nil; +} + + ++ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account { + return [self passwordDataForService:service account:account error:nil]; +} + + ++ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + OSStatus status = SSKeychainErrorBadArguments; + if (!service || !account) { + if (error) { + *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; + } + return nil; + } + + CFTypeRef result = NULL; + NSMutableDictionary *query = [self _queryForService:service account:account]; +#if __has_feature(objc_arc) + [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); +#else + [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; + [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; + status = SecItemCopyMatching((CFDictionaryRef)query, &result); +#endif + + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; + return nil; + } + +#if __has_feature(objc_arc) + return (__bridge_transfer NSData *)result; +#else + return [(NSData *)result autorelease]; +#endif +} + + +#pragma mark - Deleting Passwords + ++ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account { + return [self deletePasswordForService:service account:account error:nil]; +} + + ++ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error { + OSStatus status = SSKeychainErrorBadArguments; + if (service && account) { + NSMutableDictionary *query = [self _queryForService:service account:account]; +#if __has_feature(objc_arc) + status = SecItemDelete((__bridge CFDictionaryRef)query); +#else + status = SecItemDelete((CFDictionaryRef)query); +#endif + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; + } + return (status == noErr); + +} + + +#pragma mark - Setting Passwords + ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account { + return [self setPassword:password forService:service account:account error:nil]; +} + + ++ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error { + NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding]; + return [self setPasswordData:data forService:service account:account error:error]; +} + + ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account { + return [self setPasswordData:password forService:service account:account error:nil]; +} + + ++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error { + OSStatus status = SSKeychainErrorBadArguments; + if (password && service && account) { + [self deletePasswordForService:service account:account]; + NSMutableDictionary *query = [self _queryForService:service account:account]; +#if __has_feature(objc_arc) + [query setObject:password forKey:(__bridge id)kSecValueData]; +#else + [query setObject:password forKey:(id)kSecValueData]; +#endif + +#if __IPHONE_4_0 && TARGET_OS_IPHONE + if (SSKeychainAccessibilityType) { +#if __has_feature(objc_arc) + [query setObject:(id)[self accessibilityType] forKey:(__bridge id)kSecAttrAccessible]; +#else + [query setObject:(id)[self accessibilityType] forKey:(id)kSecAttrAccessible]; +#endif + } +#endif + +#if __has_feature(objc_arc) + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); +#else + status = SecItemAdd((CFDictionaryRef)query, NULL); +#endif + } + if (status != noErr && error != NULL) { + *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil]; + } + return (status == noErr); +} + + +#pragma mark - Configuration + +#if __IPHONE_4_0 && TARGET_OS_IPHONE ++ (CFTypeRef)accessibilityType { + return SSKeychainAccessibilityType; +} + + ++ (void)setAccessibilityType:(CFTypeRef)accessibilityType { + CFRetain(accessibilityType); + if (SSKeychainAccessibilityType) { + CFRelease(SSKeychainAccessibilityType); + } + SSKeychainAccessibilityType = accessibilityType; +} +#endif + + +#pragma mark - Private + ++ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3]; +#if __has_feature(objc_arc) + [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; +#else + [dictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; +#endif + + if (service) { +#if __has_feature(objc_arc) + [dictionary setObject:service forKey:(__bridge id)kSecAttrService]; +#else + [dictionary setObject:service forKey:(id)kSecAttrService]; +#endif + } + + if (account) { +#if __has_feature(objc_arc) + [dictionary setObject:account forKey:(__bridge id)kSecAttrAccount]; +#else + [dictionary setObject:account forKey:(id)kSecAttrAccount]; +#endif + } + + return dictionary; +} + +@end \ No newline at end of file http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/UGActivity.h ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/UGActivity.h b/sdks/other/ios/UGAPI/UGActivity.h new file mode 100755 index 0000000..1139518 --- /dev/null +++ b/sdks/other/ios/UGAPI/UGActivity.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import <Foundation/Foundation.h> + +@interface UGActivity : NSObject + +// In order for an activity to be valid, you must call setBasics and one of the setActor functions. +// In all cases, the return value will be YES if the function succeeded and NO if there +// was a problem with the set. A response of NO will usually mean you sent nil for a required field. + +// these are the basics of the activity. +// verb: the action being taken +// category: The type of activity it is +// content: The content of this activity. The format is defined by the category +// title: The title of this category. +-(BOOL) setBasics: (NSString *)verb category:(NSString *)category content:(NSString *)content title:(NSString *)title; + +// actorUserName: The username of the entity doing this activity +// actorDisplayName: The visible name of the entity doing this activity +// actorUUID: The UUID of the entity doing this activity +-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorUUID:(NSString *)actorUUID; + +// actorUserName: The username of the entity doing this activity +// actorDisplayName: The visible name of the entity doing this activity +// actorUUID: The UUID of the entity doing this activity +-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorEmail:(NSString *)actorEmail; + +// Associating an object with the Activity is optional. You don't have to supply an object at all. + +// objectType: the type of the object associated with this activity +// displayName: The visible name of the object associated with this activity +// entityType: the entity type of this object within UserGrid. The actual type that it is stored under +// entityUUID: The uuid of the object associated with this activity +-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName entityType:(NSString *)entityType entityUUID:(NSString *)entityUUID; + +// similar to the function above, but it takes an arbitrary object content (which can be new and unique) instead of an already-defined object +-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName objectContent:(NSString *)objectContent; + +// similar to the other two functions, but simply has the type and displayName. In this case, the +// "content" value supplied in setBasics will be used as the object content. +-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName; + +// returns YES if this is properly set up. NO if it has not been properly set up +-(BOOL)isValid; + +// turn this object in to an NSDictionary. Used internally by UGClient +-(NSDictionary *)toNSDictionary; + +@end http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/UGActivity.m ---------------------------------------------------------------------- diff --git a/sdks/other/ios/UGAPI/UGActivity.m b/sdks/other/ios/UGAPI/UGActivity.m new file mode 100755 index 0000000..3eaea00 --- /dev/null +++ b/sdks/other/ios/UGAPI/UGActivity.m @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "UGActivity.h" + +// the way they have set up the object info +enum +{ + kUGActivityNoObject = 0, + kUGActivityObjectEntity = 1, + kUGActivityObjectContent = 2, + kUGActivityObjectNameOnly = 3 +}; + +@implementation UGActivity +{ + // basic stats + NSString *m_verb; + NSString *m_category; + NSString *m_content; + NSString *m_title; + + // stats related to the actor + NSString *m_actorUserName; + NSString *m_actorDisplayName; + NSString *m_actorUUID; + NSString *m_actorEmail; + + // stats related to the object + NSString *m_objectType; + NSString *m_objectDisplayName; + + // for the object, either these must be set... + NSString *m_entityType; + NSString *m_entityUUID; + + // ...or this must be set + NSString *m_objectContent; + + // or it will use the content field as the content for the object + + // tracking how the object is currently set up + int m_objectDataType; +} + +-(id)init +{ + self = [super init]; + if ( self ) + { + m_objectDataType = kUGActivityNoObject; + } + return self; +} + +-(BOOL) setBasics: (NSString *)verb category:(NSString *)category content:(NSString *)content title:(NSString *)title +{ + // input validation + if ( !verb || !category || !content || !title ) return NO; + + m_verb = verb; + m_category = category; + m_content = content; + m_title = title; + + return YES; +} + +-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorUUID:(NSString *)actorUUID +{ + // input validation + if ( !actorUserName || !actorDisplayName || !actorUUID ) return NO; + + m_actorUserName = actorUserName; + m_actorDisplayName = actorDisplayName; + m_actorUUID = actorUUID; + m_actorEmail = nil; + + return YES; +} + +-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorEmail:(NSString *)actorEmail +{ + // input validation + if ( !actorUserName || !actorDisplayName || !actorEmail ) return NO; + + m_actorUserName = actorUserName; + m_actorDisplayName = actorDisplayName; + m_actorEmail = actorEmail; + m_actorUUID = nil; + + return YES; +} + +-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName entityType:(NSString *)entityType entityUUID:(NSString *)entityUUID +{ + // input validation + if ( !objectType || !displayName || !entityType || !entityUUID ) return NO; + + m_objectType = objectType; + m_objectDisplayName = displayName; + m_entityType = entityType; + m_entityUUID = entityUUID; + m_objectDataType = kUGActivityObjectEntity; + + // clear out the unused value + m_objectContent = nil; + + return YES; +} + +-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName objectContent:(NSString *)objectContent +{ + // input validation + if ( !objectType || !displayName || !objectContent ) return NO; + + m_objectType = objectType; + m_objectDisplayName = displayName; + m_objectContent = objectContent; + m_objectDataType = kUGActivityObjectContent; + + // clear out the unused values + m_entityType = nil; + m_entityUUID = nil; + + return YES; +} + +-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName +{ + // input validation + if ( !objectType || !displayName ) return NO; + + m_objectType = objectType; + m_objectDisplayName = displayName; + m_objectDataType = kUGActivityObjectNameOnly; + + // we'll use m_content when the time comes. But we don't want to + // assume they've set it yet. They can call the setup functions in any order. + m_objectContent = nil; + m_entityType = nil; + m_entityUUID = nil; + + return YES; +} + +-(BOOL)isValid +{ + // if any of the required values are nil, it's not valid + if ( !m_verb || !m_category || !m_content || !m_title || !m_actorUserName || !m_actorDisplayName ) + { + return NO; + } + + // either the uuid or the email of the user must be valid + if ( !m_actorUUID && !m_actorEmail ) + { + return NO; + } + + // the object data requirements are based on the object setup + switch ( m_objectDataType ) + { + case kUGActivityObjectEntity: + { + if ( !m_objectType || !m_objectDisplayName || !m_entityType || !m_entityUUID ) return NO; + } + break; + + case kUGActivityObjectContent: + { + if ( !m_objectType || !m_objectDisplayName || !m_objectContent ) return NO; + } + break; + + case kUGActivityObjectNameOnly: + { + if ( !m_objectType || !m_objectDisplayName ) return NO; + } + break; + + // kUGActivityNoObject has no requirements. + } + + // if we're here, we're valid. + return YES; +} + +-(NSDictionary *)toNSDictionary +{ + NSMutableDictionary *ret = [NSMutableDictionary new]; + + // add all the fields in + [ret setObject:@"activity" forKey:@"type"]; + [ret setObject:m_verb forKey:@"verb"]; + [ret setObject:m_category forKey:@"category"]; + [ret setObject:m_content forKey:@"content"]; + [ret setObject:m_title forKey:@"title"]; + + // make the actor's subdictionary + NSMutableDictionary *actor = [NSMutableDictionary new]; + [actor setObject:@"person" forKey:@"type"]; + [actor setObject:@"user" forKey:@"entityType"]; + [actor setObject:m_actorDisplayName forKey:@"displayName"]; + + if ( m_actorUUID ) + { + [actor setObject:m_actorUUID forKey:@"uuid"]; + } + if ( m_actorEmail ) + { + [actor setObject:m_actorEmail forKey:@"email"]; + } + + // add the actor to the main dict + [ret setObject:actor forKey:@"actor"]; + + if ( m_objectDataType != kUGActivityNoObject ) + { + // there is an associated object. Prep a dict for it + NSMutableDictionary *object = [NSMutableDictionary new]; + + // these fields are involved in all cases + [object setObject:m_objectType forKey:@"type"]; + [object setObject:m_objectDisplayName forKey:@"displayName"]; + + if ( m_objectDataType == kUGActivityObjectContent ) + { + [object setObject:m_objectContent forKey:@"content"]; + } + else if ( m_objectDataType == kUGActivityObjectNameOnly ) + { + [object setObject:m_content forKey:@"content"]; + } + else if ( m_objectDataType == kUGActivityObjectEntity ) + { + [object setObject:m_entityType forKey:@"entityType"]; + [object setObject:m_entityUUID forKey:@"entityUUID"]; + } + + // add to the dict + [ret setObject:object forKey:@"object"]; + } + + // done with the assembly + return ret; +} + +@end
